mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 19:35:51 +00:00
Bug 986526 - Create helper functions to encode DrawTargets/SourceSurfaces to PNG/JPEG/BMP/ICO/etc. and save them, dump them, or copy them to the clipboard, either as binary or as data: URIs. r=mattwoodrow
This commit is contained in:
parent
d365e40ce3
commit
deb2077580
@ -10,9 +10,19 @@
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxDrawable.h"
|
||||
#include "imgIEncoder.h"
|
||||
#include "mozilla/Base64.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/Vector.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsIClipboardHelper.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsRegion.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "yuv_convert.h"
|
||||
#include "ycbcr_to_rgb565.h"
|
||||
#include "GeckoProfiler.h"
|
||||
@ -1105,83 +1115,258 @@ gfxUtils::GetColorForFrameNumber(uint64_t aFrameNumber)
|
||||
return colors[aFrameNumber % sNumFrameColors];
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
/* static */ nsresult
|
||||
gfxUtils::EncodeSourceSurface(SourceSurface* aSurface,
|
||||
const nsACString& aMimeType,
|
||||
const nsAString& aOutputOptions,
|
||||
BinaryOrData aBinaryOrData,
|
||||
FILE* aFile)
|
||||
{
|
||||
MOZ_ASSERT(aBinaryOrData == eDataURIEncode || aFile,
|
||||
"Copying binary encoding to clipboard not currently supported");
|
||||
|
||||
const IntSize size = aSurface->GetSize();
|
||||
if (size.IsEmpty()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
const Size floatSize(size.width, size.height);
|
||||
|
||||
RefPtr<DataSourceSurface> dataSurface;
|
||||
if (aSurface->GetFormat() != SurfaceFormat::B8G8R8A8) {
|
||||
// FIXME bug 995807 (B8G8R8X8), bug 831898 (R5G6B5)
|
||||
dataSurface =
|
||||
CopySurfaceToDataSourceSurfaceWithFormat(aSurface,
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
} else {
|
||||
dataSurface = aSurface->GetDataSurface();
|
||||
}
|
||||
if (!dataSurface) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
DataSourceSurface::MappedSurface map;
|
||||
if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsAutoCString encoderCID(
|
||||
NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type=") + aMimeType);
|
||||
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance(encoderCID.get());
|
||||
if (!encoder) {
|
||||
#ifdef DEBUG
|
||||
int32_t w = std::min(size.width, 8);
|
||||
int32_t h = std::min(size.height, 8);
|
||||
printf("Could not create encoder. Top-left %dx%d pixels contain:\n", w, h);
|
||||
for (int32_t y = 0; y < h; ++y) {
|
||||
for (int32_t x = 0; x < w; ++x) {
|
||||
printf("%x ", reinterpret_cast<uint32_t*>(map.mData)[y*map.mStride+x]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
dataSurface->Unmap();
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = encoder->InitFromData(map.mData,
|
||||
BufferSizeFromStrideAndHeight(map.mStride, size.height),
|
||||
size.width,
|
||||
size.height,
|
||||
map.mStride,
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB,
|
||||
aOutputOptions);
|
||||
dataSurface->Unmap();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIInputStream> imgStream;
|
||||
CallQueryInterface(encoder.get(), getter_AddRefs(imgStream));
|
||||
if (!imgStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint64_t bufSize64;
|
||||
rv = imgStream->Available(&bufSize64);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ENSURE_TRUE(bufSize64 < UINT32_MAX - 16, NS_ERROR_FAILURE);
|
||||
|
||||
uint32_t bufSize = (uint32_t)bufSize64;
|
||||
|
||||
// ...leave a little extra room so we can call read again and make sure we
|
||||
// got everything. 16 bytes for better padding (maybe)
|
||||
bufSize += 16;
|
||||
uint32_t imgSize = 0;
|
||||
Vector<char> imgData;
|
||||
if (!imgData.initCapacity(bufSize)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
uint32_t numReadThisTime = 0;
|
||||
while ((rv = imgStream->Read(imgData.begin() + imgSize,
|
||||
bufSize - imgSize,
|
||||
&numReadThisTime)) == NS_OK && numReadThisTime > 0)
|
||||
{
|
||||
imgSize += numReadThisTime;
|
||||
if (imgSize == bufSize) {
|
||||
// need a bigger buffer, just double
|
||||
bufSize *= 2;
|
||||
if (!imgData.resizeUninitialized(bufSize)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (aBinaryOrData == eBinaryEncode) {
|
||||
if (aFile) {
|
||||
fwrite(imgData.begin(), 1, imgSize, aFile);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// base 64, result will be null-terminated
|
||||
nsCString encodedImg;
|
||||
rv = Base64Encode(Substring(imgData.begin(), imgSize), encodedImg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCString string("data:");
|
||||
string.Append(aMimeType);
|
||||
string.Append(";base64,");
|
||||
string.Append(encodedImg);
|
||||
|
||||
if (aFile) {
|
||||
#ifdef ANDROID
|
||||
if (aFile == stdout || aFile == stderr) {
|
||||
// ADB logcat cuts off long strings so we will break it down
|
||||
const char* cStr = string.BeginReading();
|
||||
size_t len = strlen(cStr);
|
||||
while (true) {
|
||||
printf_stderr("IMG: %.140s\n", cStr);
|
||||
if (len <= 140)
|
||||
break;
|
||||
len -= 140;
|
||||
cStr += 140;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
fprintf(aFile, "%s", string.BeginReading());
|
||||
} else {
|
||||
nsCOMPtr<nsIClipboardHelper> clipboard(do_GetService("@mozilla.org/widget/clipboardhelper;1", &rv));
|
||||
if (clipboard) {
|
||||
clipboard->CopyString(NS_ConvertASCIItoUTF16(string), nullptr);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::WriteAsPNG(SourceSurface* aSurface, const nsAString& aFile)
|
||||
{
|
||||
WriteAsPNG(aSurface, NS_ConvertUTF16toUTF8(aFile).get());
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::WriteAsPNG(SourceSurface* aSurface, const char* aFile)
|
||||
{
|
||||
FILE* file = fopen(aFile, "wb");
|
||||
|
||||
if (!file) {
|
||||
// Maybe the directory doesn't exist; try creating it, then fopen again.
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIFile> comFile = do_CreateInstance("@mozilla.org/file/local;1");
|
||||
if (comFile) {
|
||||
NS_ConvertUTF8toUTF16 utf16path((nsDependentCString(aFile)));
|
||||
rv = comFile->InitWithPath(utf16path);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIFile> dirPath;
|
||||
comFile->GetParent(getter_AddRefs(dirPath));
|
||||
if (dirPath) {
|
||||
rv = dirPath->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
||||
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
file = fopen(aFile, "wb");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!file) {
|
||||
NS_WARNING("Failed to open file to create PNG!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
|
||||
EmptyString(), eBinaryEncode, file);
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::WriteAsPNG(DrawTarget* aDT, const nsAString& aFile)
|
||||
{
|
||||
WriteAsPNG(aDT, NS_ConvertUTF16toUTF8(aFile).get());
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::WriteAsPNG(DrawTarget* aDT, const char* aFile)
|
||||
{
|
||||
aDT->Flush();
|
||||
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(aDT);
|
||||
if (surf) {
|
||||
surf->WriteAsPNG(aFile);
|
||||
RefPtr<SourceSurface> surface = aDT->Snapshot();
|
||||
if (surface) {
|
||||
WriteAsPNG(surface, aFile);
|
||||
} else {
|
||||
NS_WARNING("Failed to get Thebes surface!");
|
||||
NS_WARNING("Failed to get surface!");
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::DumpAsDataURL(DrawTarget* aDT)
|
||||
gfxUtils::WriteAsPNG(nsIPresShell* aShell, const char* aFile)
|
||||
{
|
||||
aDT->Flush();
|
||||
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(aDT);
|
||||
if (surf) {
|
||||
surf->DumpAsDataURL();
|
||||
int32_t width = 1000, height = 1000;
|
||||
nsRect r(0, 0, aShell->GetPresContext()->DevPixelsToAppUnits(width),
|
||||
aShell->GetPresContext()->DevPixelsToAppUnits(height));
|
||||
|
||||
RefPtr<mozilla::gfx::DrawTarget> dt = gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenContentDrawTarget(IntSize(width, height),
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
NS_ENSURE_TRUE(dt, /*void*/);
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(dt);
|
||||
aShell->RenderDocument(r, 0, NS_RGB(255, 255, 0), context);
|
||||
WriteAsPNG(dt.get(), aFile);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::DumpAsDataURI(SourceSurface* aSurface, FILE* aFile)
|
||||
{
|
||||
EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
|
||||
EmptyString(), eDataURIEncode, aFile);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::DumpAsDataURI(DrawTarget* aDT, FILE* aFile)
|
||||
{
|
||||
RefPtr<SourceSurface> surface = aDT->Snapshot();
|
||||
if (surface) {
|
||||
DumpAsDataURI(surface, aFile);
|
||||
} else {
|
||||
NS_WARNING("Failed to get Thebes surface!");
|
||||
NS_WARNING("Failed to get surface!");
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::CopyAsDataURL(DrawTarget* aDT)
|
||||
gfxUtils::CopyAsDataURI(SourceSurface* aSurface)
|
||||
{
|
||||
aDT->Flush();
|
||||
nsRefPtr<gfxASurface> surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(aDT);
|
||||
if (surf) {
|
||||
surf->CopyAsDataURL();
|
||||
EncodeSourceSurface(aSurface, NS_LITERAL_CSTRING("image/png"),
|
||||
EmptyString(), eDataURIEncode, nullptr);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::CopyAsDataURI(DrawTarget* aDT)
|
||||
{
|
||||
RefPtr<SourceSurface> surface = aDT->Snapshot();
|
||||
if (surface) {
|
||||
CopyAsDataURI(surface);
|
||||
} else {
|
||||
NS_WARNING("Failed to get Thebes surface!");
|
||||
NS_WARNING("Failed to get surface!");
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::WriteAsPNG(gfx::SourceSurface* aSourceSurface, const char* aFile)
|
||||
{
|
||||
RefPtr<gfx::DataSourceSurface> dataSurface = aSourceSurface->GetDataSurface();
|
||||
RefPtr<gfx::DrawTarget> dt
|
||||
= gfxPlatform::GetPlatform()
|
||||
->CreateDrawTargetForData(dataSurface->GetData(),
|
||||
dataSurface->GetSize(),
|
||||
dataSurface->Stride(),
|
||||
aSourceSurface->GetFormat());
|
||||
gfxUtils::WriteAsPNG(dt.get(), aFile);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::DumpAsDataURL(gfx::SourceSurface* aSourceSurface)
|
||||
{
|
||||
RefPtr<gfx::DataSourceSurface> dataSurface = aSourceSurface->GetDataSurface();
|
||||
RefPtr<gfx::DrawTarget> dt
|
||||
= gfxPlatform::GetPlatform()
|
||||
->CreateDrawTargetForData(dataSurface->GetData(),
|
||||
dataSurface->GetSize(),
|
||||
dataSurface->Stride(),
|
||||
aSourceSurface->GetFormat());
|
||||
gfxUtils::DumpAsDataURL(dt.get());
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
gfxUtils::CopyAsDataURL(gfx::SourceSurface* aSourceSurface)
|
||||
{
|
||||
RefPtr<gfx::DataSourceSurface> dataSurface = aSourceSurface->GetDataSurface();
|
||||
RefPtr<gfx::DrawTarget> dt
|
||||
= gfxPlatform::GetPlatform()
|
||||
->CreateDrawTargetForData(dataSurface->GetData(),
|
||||
dataSurface->GetSize(),
|
||||
dataSurface->Stride(),
|
||||
aSourceSurface->GetFormat());
|
||||
|
||||
gfxUtils::CopyAsDataURL(dt.get());
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
static bool sDumpPaintList = getenv("MOZ_DUMP_PAINT_LIST") != 0;
|
||||
|
||||
/* static */ bool
|
||||
|
@ -16,6 +16,8 @@
|
||||
class gfxASurface;
|
||||
class gfxDrawable;
|
||||
class nsIntRegion;
|
||||
class nsIPresShell;
|
||||
|
||||
struct nsIntRect;
|
||||
|
||||
namespace mozilla {
|
||||
@ -27,6 +29,7 @@ struct PlanarYCbCrData;
|
||||
class gfxUtils {
|
||||
public:
|
||||
typedef mozilla::gfx::DataSourceSurface DataSourceSurface;
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
typedef mozilla::gfx::IntPoint IntPoint;
|
||||
typedef mozilla::gfx::Matrix Matrix;
|
||||
typedef mozilla::gfx::SourceSurface SourceSurface;
|
||||
@ -228,45 +231,78 @@ public:
|
||||
static const mozilla::gfx::Color& GetColorForFrameNumber(uint64_t aFrameNumber);
|
||||
static const uint32_t sNumFrameColors;
|
||||
|
||||
|
||||
enum BinaryOrData {
|
||||
eBinaryEncode,
|
||||
eDataURIEncode
|
||||
};
|
||||
|
||||
/**
|
||||
* Encodes the given surface to PNG/JPEG/BMP/etc. using imgIEncoder.
|
||||
*
|
||||
* @param aMimeType The MIME-type of the image type that the surface is to
|
||||
* be encoded to. Used to create an appropriate imgIEncoder instance to
|
||||
* do the encoding.
|
||||
*
|
||||
* @param aOutputOptions Passed directly to imgIEncoder::InitFromData as
|
||||
* the value of the |outputOptions| parameter. Callers are responsible
|
||||
* for making sure that this is a sane value for the passed MIME-type
|
||||
* (i.e. for the type of encoder that will be created).
|
||||
*
|
||||
* @aBinaryOrData Flag used to determine if the surface is simply encoded
|
||||
* to the requested binary image format, or if the binary image is
|
||||
* further converted to base-64 and written out as a 'data:' URI.
|
||||
*
|
||||
* @aFile If specified, the encoded data is written out to aFile, otherwise
|
||||
* it is copied to the clipboard.
|
||||
*
|
||||
* TODO: Copying to the clipboard as a binary file is not currently
|
||||
* supported.
|
||||
*/
|
||||
static nsresult
|
||||
EncodeSourceSurface(SourceSurface* aSurface,
|
||||
const nsACString& aMimeType,
|
||||
const nsAString& aOutputOptions,
|
||||
BinaryOrData aBinaryOrData,
|
||||
FILE* aFile);
|
||||
|
||||
/**
|
||||
* Write as a PNG file to the path aFile.
|
||||
*/
|
||||
static void WriteAsPNG(SourceSurface* aSurface, const nsAString& aFile);
|
||||
static void WriteAsPNG(SourceSurface* aSurface, const char* aFile);
|
||||
static void WriteAsPNG(DrawTarget* aDT, const nsAString& aFile);
|
||||
static void WriteAsPNG(DrawTarget* aDT, const char* aFile);
|
||||
static void WriteAsPNG(nsIPresShell* aShell, const char* aFile);
|
||||
|
||||
/**
|
||||
* Dump as a PNG encoded Data URL to a FILE stream (using stdout by
|
||||
* default).
|
||||
*
|
||||
* Rather than giving aFile a default argument we have separate functions
|
||||
* to make them easier to use from a debugger.
|
||||
*/
|
||||
static void DumpAsDataURI(SourceSurface* aSourceSurface, FILE* aFile);
|
||||
static inline void DumpAsDataURI(SourceSurface* aSourceSurface) {
|
||||
DumpAsDataURI(aSourceSurface, stdout);
|
||||
}
|
||||
static void DumpAsDataURI(DrawTarget* aDT, FILE* aFile);
|
||||
static inline void DumpAsDataURI(DrawTarget* aDT) {
|
||||
DumpAsDataURI(aDT, stdout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy to the clipboard as a PNG encoded Data URL.
|
||||
*/
|
||||
static void CopyAsDataURI(SourceSurface* aSourceSurface);
|
||||
static void CopyAsDataURI(DrawTarget* aDT);
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
/**
|
||||
* Writes a binary PNG file.
|
||||
*/
|
||||
static void WriteAsPNG(mozilla::gfx::DrawTarget* aDT, const char* aFile);
|
||||
|
||||
/**
|
||||
* Write as a PNG encoded Data URL to stdout.
|
||||
*/
|
||||
static void DumpAsDataURL(mozilla::gfx::DrawTarget* aDT);
|
||||
|
||||
/**
|
||||
* Copy a PNG encoded Data URL to the clipboard.
|
||||
*/
|
||||
static void CopyAsDataURL(mozilla::gfx::DrawTarget* aDT);
|
||||
|
||||
static bool DumpPaintList();
|
||||
|
||||
static bool sDumpPainting;
|
||||
static bool sDumpPaintingToFile;
|
||||
static FILE* sDumpPaintFile;
|
||||
|
||||
/**
|
||||
* Writes a binary PNG file.
|
||||
* Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads
|
||||
*/
|
||||
static void WriteAsPNG(mozilla::gfx::SourceSurface* aSourceSurface, const char* aFile);
|
||||
|
||||
/**
|
||||
* Write as a PNG encoded Data URL to stdout.
|
||||
* Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads
|
||||
*/
|
||||
static void DumpAsDataURL(mozilla::gfx::SourceSurface* aSourceSurface);
|
||||
|
||||
/**
|
||||
* Copy a PNG encoded Data URL to the clipboard.
|
||||
* Expensive. Creates a DataSourceSurface, then a DrawTarget, then passes to DrawTarget overloads
|
||||
*/
|
||||
static void CopyAsDataURL(mozilla::gfx::SourceSurface* aSourceSurface);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -114,6 +114,7 @@
|
||||
#include "nsStyleSheetService.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxContext.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "nsSMILAnimationController.h"
|
||||
#include "SVGContentUtils.h"
|
||||
#include "nsSVGEffects.h"
|
||||
@ -9522,68 +9523,6 @@ PresShell::CloneStyleSet(nsStyleSet* aSet)
|
||||
return clone;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_Eli
|
||||
static nsresult
|
||||
DumpToPNG(nsIPresShell* shell, nsAString& name) {
|
||||
int32_t width=1000, height=1000;
|
||||
nsRect r(0, 0, shell->GetPresContext()->DevPixelsToAppUnits(width),
|
||||
shell->GetPresContext()->DevPixelsToAppUnits(height));
|
||||
|
||||
nsRefPtr<gfxImageSurface> imgSurface =
|
||||
new gfxImageSurface(gfxIntSize(width, height),
|
||||
gfxImageFormat::ARGB32);
|
||||
|
||||
nsRefPtr<gfxContext> imgContext = new gfxContext(imgSurface);
|
||||
|
||||
nsRefPtr<gfxASurface> surface =
|
||||
gfxPlatform::GetPlatform()->
|
||||
CreateOffscreenSurface(IntSize(width, height),
|
||||
gfxASurface::ContentFromFormat(gfxImageFormat::ARGB32));
|
||||
NS_ENSURE_TRUE(surface, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(surface);
|
||||
|
||||
shell->RenderDocument(r, 0, NS_RGB(255, 255, 0), context);
|
||||
|
||||
imgContext->DrawSurface(surface, gfxSize(width, height));
|
||||
|
||||
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/png");
|
||||
NS_ENSURE_TRUE(encoder, NS_ERROR_FAILURE);
|
||||
encoder->InitFromData(imgSurface->Data(), imgSurface->Stride() * height,
|
||||
width, height, imgSurface->Stride(),
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB, EmptyString());
|
||||
|
||||
// XXX not sure if this is the right way to write to a file
|
||||
nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1");
|
||||
NS_ENSURE_TRUE(file, NS_ERROR_FAILURE);
|
||||
rv = file->InitWithPath(name);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint64_t length64;
|
||||
rv = encoder->Available(&length64);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (length64 > UINT32_MAX)
|
||||
return NS_ERROR_FILE_TOO_BIG;
|
||||
|
||||
uint32_t length = (uint32_t)length64;
|
||||
|
||||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), file);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIOutputStream> bufferedOutputStream;
|
||||
rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
|
||||
outputStream, length);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t numWritten;
|
||||
rv = bufferedOutputStream->WriteFrom(encoder, length, &numWritten);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
// After an incremental reflow, we verify the correctness by doing a
|
||||
// full reflow into a fresh frame tree.
|
||||
bool
|
||||
@ -9668,7 +9607,7 @@ PresShell::VerifyIncrementalReflow()
|
||||
root2->List(stdout, 0);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_Eli
|
||||
#if 0
|
||||
// Sample code for dumping page to png
|
||||
// XXX Needs to be made more flexible
|
||||
if (!ok) {
|
||||
@ -9677,12 +9616,12 @@ PresShell::VerifyIncrementalReflow()
|
||||
stra.AppendLiteral("C:\\mozilla\\mozilla\\debug\\filea");
|
||||
stra.AppendInt(num);
|
||||
stra.AppendLiteral(".png");
|
||||
DumpToPNG(sh, stra);
|
||||
gfxUtils::WriteAsPNG(sh, stra);
|
||||
nsString strb;
|
||||
strb.AppendLiteral("C:\\mozilla\\mozilla\\debug\\fileb");
|
||||
strb.AppendInt(num);
|
||||
strb.AppendLiteral(".png");
|
||||
DumpToPNG(this, strb);
|
||||
gfxUtils::WriteAsPNG(sh, strb);
|
||||
++num;
|
||||
}
|
||||
#endif
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "WinUtils.h"
|
||||
|
||||
#include "gfxPlatform.h"
|
||||
#include "gfxUtils.h"
|
||||
#include "nsWindow.h"
|
||||
#include "nsWindowDefs.h"
|
||||
#include "KeyboardLayout.h"
|
||||
@ -851,65 +852,48 @@ NS_IMETHODIMP AsyncEncodeAndWriteIcon::Run()
|
||||
{
|
||||
NS_PRECONDITION(!NS_IsMainThread(), "Should not be called on the main thread.");
|
||||
|
||||
nsCOMPtr<nsIInputStream> iconStream;
|
||||
nsRefPtr<imgIEncoder> encoder =
|
||||
do_CreateInstance("@mozilla.org/image/encoder;2?"
|
||||
"type=image/vnd.microsoft.icon");
|
||||
NS_ENSURE_TRUE(encoder, NS_ERROR_FAILURE);
|
||||
nsresult rv = encoder->InitFromData(mBuffer, mBufferLength,
|
||||
mWidth, mHeight,
|
||||
mStride,
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB,
|
||||
EmptyString());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
CallQueryInterface(encoder.get(), getter_AddRefs(iconStream));
|
||||
if (!iconStream) {
|
||||
return NS_ERROR_FAILURE;
|
||||
RefPtr<DrawTarget> dt =
|
||||
gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
|
||||
RefPtr<SourceSurface> surface =
|
||||
dt->CreateSourceSurfaceFromData(mBuffer, IntSize(mWidth, mHeight), mStride,
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
|
||||
FILE* file = fopen(NS_ConvertUTF16toUTF8(mIconPath).get(), "wb");
|
||||
if (!file) {
|
||||
// Maybe the directory doesn't exist; try creating it, then fopen again.
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
nsCOMPtr<nsIFile> comFile = do_CreateInstance("@mozilla.org/file/local;1");
|
||||
if (comFile) {
|
||||
//NS_ConvertUTF8toUTF16 utf16path(mIconPath);
|
||||
rv = comFile->InitWithPath(mIconPath);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsCOMPtr<nsIFile> dirPath;
|
||||
comFile->GetParent(getter_AddRefs(dirPath));
|
||||
if (dirPath) {
|
||||
rv = dirPath->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
||||
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
file = fopen(NS_ConvertUTF16toUTF8(mIconPath).get(), "wb");
|
||||
if (!file) {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!file) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
gfxUtils::EncodeSourceSurface(surface,
|
||||
NS_LITERAL_CSTRING("image/vnd.microsoft.icon"),
|
||||
EmptyString(),
|
||||
gfxUtils::eBinaryEncode,
|
||||
file);
|
||||
fclose(file);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIFile> icoFile
|
||||
= do_CreateInstance("@mozilla.org/file/local;1");
|
||||
NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
|
||||
rv = icoFile->InitWithPath(mIconPath);
|
||||
|
||||
// Try to create the directory if it's not there yet
|
||||
nsCOMPtr<nsIFile> dirPath;
|
||||
icoFile->GetParent(getter_AddRefs(dirPath));
|
||||
rv = (dirPath->Create(nsIFile::DIRECTORY_TYPE, 0777));
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Setup the output stream for the ICO file on disk
|
||||
nsCOMPtr<nsIOutputStream> outputStream;
|
||||
rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), icoFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Obtain the ICO buffer size from the re-encoded ICO stream
|
||||
uint64_t bufSize64;
|
||||
rv = iconStream->Available(&bufSize64);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(bufSize64 <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);
|
||||
|
||||
uint32_t bufSize = (uint32_t)bufSize64;
|
||||
|
||||
// Setup a buffered output stream from the stream object
|
||||
// so that we can simply use WriteFrom with the stream object
|
||||
nsCOMPtr<nsIOutputStream> bufferedOutputStream;
|
||||
rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
|
||||
outputStream, bufSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Write out the icon stream to disk and make sure we wrote everything
|
||||
uint32_t wrote;
|
||||
rv = bufferedOutputStream->WriteFrom(iconStream, bufSize, &wrote);
|
||||
NS_ASSERTION(bufSize == wrote,
|
||||
"Icon wrote size should be equal to requested write size");
|
||||
|
||||
// Cleanup
|
||||
bufferedOutputStream->Close();
|
||||
outputStream->Close();
|
||||
if (mURLShortcut) {
|
||||
SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user