mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-12 12:55:46 +00:00
Bug 979853 - Convert the Windows widget consumers of imgIContainer::GetFrame to act on a Moz2D SourceSurface instead of a Thebes gfxASurface. r=mattwoodrow
This commit is contained in:
parent
a8bf6b7f51
commit
c0fabb967b
@ -3,7 +3,8 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/gfx/2D.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
#include "nsITransferable.h"
|
#include "nsITransferable.h"
|
||||||
#include "nsImageClipboard.h"
|
#include "nsImageClipboard.h"
|
||||||
#include "nsGfxCIID.h"
|
#include "nsGfxCIID.h"
|
||||||
@ -15,6 +16,9 @@
|
|||||||
|
|
||||||
#define BFH_LENGTH 14
|
#define BFH_LENGTH 14
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::gfx;
|
||||||
|
|
||||||
/* Things To Do 11/8/00
|
/* Things To Do 11/8/00
|
||||||
|
|
||||||
Check image metrics, can we support them? Do we need to?
|
Check image metrics, can we support them? Do we need to?
|
||||||
@ -116,13 +120,23 @@ nsImageToClipboard::CreateFromImage ( imgIContainer* inImage, HANDLE* outBitmap
|
|||||||
nsresult rv;
|
nsresult rv;
|
||||||
*outBitmap = nullptr;
|
*outBitmap = nullptr;
|
||||||
|
|
||||||
nsRefPtr<gfxASurface> surface =
|
nsRefPtr<gfxASurface> thebesSurface =
|
||||||
inImage->GetFrame(imgIContainer::FRAME_CURRENT,
|
inImage->GetFrame(imgIContainer::FRAME_CURRENT,
|
||||||
imgIContainer::FLAG_SYNC_DECODE);
|
imgIContainer::FLAG_SYNC_DECODE);
|
||||||
NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(thebesSurface, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
nsRefPtr<gfxImageSurface> frame(surface->GetAsReadableARGB32ImageSurface());
|
nsRefPtr<gfxImageSurface> thebesImageSurface =
|
||||||
NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
|
thebesSurface->GetAsReadableARGB32ImageSurface();
|
||||||
|
NS_ENSURE_TRUE(thebesImageSurface, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
IntSize surfaceSize(thebesImageSurface->GetSize().width,
|
||||||
|
thebesImageSurface->GetSize().height);
|
||||||
|
RefPtr<DataSourceSurface> dataSurface =
|
||||||
|
Factory::CreateWrappingDataSourceSurface(thebesImageSurface->Data(),
|
||||||
|
thebesImageSurface->Stride(),
|
||||||
|
surfaceSize,
|
||||||
|
SurfaceFormat::B8G8R8A8);
|
||||||
|
NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/bmp", &rv);
|
nsCOMPtr<imgIEncoder> encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/bmp", &rv);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
@ -134,12 +148,12 @@ nsImageToClipboard::CreateFromImage ( imgIContainer* inImage, HANDLE* outBitmap
|
|||||||
} else {
|
} else {
|
||||||
options.AppendLiteral("version=3;bpp=");
|
options.AppendLiteral("version=3;bpp=");
|
||||||
}
|
}
|
||||||
switch (frame->Format()) {
|
switch (dataSurface->GetFormat()) {
|
||||||
case gfxImageFormat::ARGB32:
|
case SurfaceFormat::B8G8R8A8:
|
||||||
format = imgIEncoder::INPUT_FORMAT_HOSTARGB;
|
format = imgIEncoder::INPUT_FORMAT_HOSTARGB;
|
||||||
options.AppendInt(32);
|
options.AppendInt(32);
|
||||||
break;
|
break;
|
||||||
case gfxImageFormat::RGB24:
|
case SurfaceFormat::B8G8R8X8:
|
||||||
format = imgIEncoder::INPUT_FORMAT_RGB;
|
format = imgIEncoder::INPUT_FORMAT_RGB;
|
||||||
options.AppendInt(24);
|
options.AppendInt(24);
|
||||||
break;
|
break;
|
||||||
@ -147,9 +161,16 @@ nsImageToClipboard::CreateFromImage ( imgIContainer* inImage, HANDLE* outBitmap
|
|||||||
return NS_ERROR_INVALID_ARG;
|
return NS_ERROR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = encoder->InitFromData(frame->Data(), 0, frame->Width(),
|
DataSourceSurface::MappedSurface map;
|
||||||
frame->Height(), frame->Stride(),
|
bool mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ, &map);
|
||||||
|
NS_ENSURE_TRUE(mappedOK, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
rv = encoder->InitFromData(map.mData, 0,
|
||||||
|
dataSurface->GetSize().width,
|
||||||
|
dataSurface->GetSize().height,
|
||||||
|
map.mStride,
|
||||||
format, options);
|
format, options);
|
||||||
|
dataSurface->Unmap();
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
|
@ -29,6 +29,10 @@ using mozilla::plugins::PluginInstanceParent;
|
|||||||
#include "gfxImageSurface.h"
|
#include "gfxImageSurface.h"
|
||||||
#include "gfxWindowsSurface.h"
|
#include "gfxWindowsSurface.h"
|
||||||
#include "gfxWindowsPlatform.h"
|
#include "gfxWindowsPlatform.h"
|
||||||
|
#include "mozilla/gfx/2D.h"
|
||||||
|
#include "mozilla/gfx/DataSurfaceHelpers.h"
|
||||||
|
#include "mozilla/gfx/Tools.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
#include "nsGfxCIID.h"
|
#include "nsGfxCIID.h"
|
||||||
#include "gfxContext.h"
|
#include "gfxContext.h"
|
||||||
#include "nsRenderingContext.h"
|
#include "nsRenderingContext.h"
|
||||||
@ -56,6 +60,7 @@ extern "C" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::gfx;
|
||||||
using namespace mozilla::layers;
|
using namespace mozilla::layers;
|
||||||
using namespace mozilla::widget;
|
using namespace mozilla::widget;
|
||||||
|
|
||||||
@ -619,60 +624,99 @@ nsresult nsWindowGfx::CreateIcon(imgIContainer *aContainer,
|
|||||||
gfxIntSize aScaledSize,
|
gfxIntSize aScaledSize,
|
||||||
HICON *aIcon) {
|
HICON *aIcon) {
|
||||||
|
|
||||||
|
MOZ_ASSERT((aScaledSize.width > 0 && aScaledSize.height > 0) ||
|
||||||
|
(aScaledSize.width == 0 && aScaledSize.height == 0));
|
||||||
|
|
||||||
// Get the image data
|
// Get the image data
|
||||||
nsRefPtr<gfxASurface> surface =
|
nsRefPtr<gfxASurface> thebesSurface =
|
||||||
aContainer->GetFrame(imgIContainer::FRAME_CURRENT,
|
aContainer->GetFrame(imgIContainer::FRAME_CURRENT,
|
||||||
imgIContainer::FLAG_SYNC_DECODE);
|
imgIContainer::FLAG_SYNC_DECODE);
|
||||||
NS_ENSURE_TRUE(surface, NS_ERROR_NOT_AVAILABLE);
|
NS_ENSURE_TRUE(thebesSurface, NS_ERROR_NOT_AVAILABLE);
|
||||||
|
|
||||||
nsRefPtr<gfxImageSurface> frame(surface->GetAsReadableARGB32ImageSurface());
|
RefPtr<SourceSurface> surface =
|
||||||
NS_ENSURE_TRUE(frame, NS_ERROR_NOT_AVAILABLE);
|
gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
|
||||||
|
thebesSurface);
|
||||||
|
NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
int32_t width = frame->Width();
|
IntSize surfaceSize(surface->GetSize().width, surface->GetSize().height);
|
||||||
int32_t height = frame->Height();
|
if (surfaceSize.IsEmpty()) {
|
||||||
if (!width || !height)
|
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
||||||
uint8_t *data;
|
|
||||||
nsRefPtr<gfxImageSurface> dest;
|
|
||||||
|
|
||||||
if ((aScaledSize.width == 0 && aScaledSize.height == 0) ||
|
|
||||||
(aScaledSize.width == width && aScaledSize.height == height)) {
|
|
||||||
// We're not scaling the image. The data is simply what's in the frame.
|
|
||||||
data = frame->Data();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
NS_ENSURE_ARG(aScaledSize.width > 0);
|
|
||||||
NS_ENSURE_ARG(aScaledSize.height > 0);
|
|
||||||
// Draw a scaled version of the image to a temporary surface
|
|
||||||
dest = new gfxImageSurface(aScaledSize, gfxImageFormat::ARGB32);
|
|
||||||
if (!dest)
|
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
|
||||||
|
|
||||||
gfxContext ctx(dest);
|
|
||||||
|
|
||||||
// Set scaling
|
|
||||||
gfxFloat sw = (double) aScaledSize.width / width;
|
|
||||||
gfxFloat sh = (double) aScaledSize.height / height;
|
|
||||||
ctx.Scale(sw, sh);
|
|
||||||
|
|
||||||
// Paint a scaled image
|
|
||||||
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
|
|
||||||
ctx.SetSource(frame);
|
|
||||||
ctx.Paint();
|
|
||||||
|
|
||||||
data = dest->Data();
|
|
||||||
width = aScaledSize.width;
|
|
||||||
height = aScaledSize.height;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HBITMAP bmp = DataToBitmap(data, width, -height, 32);
|
IntSize iconSize(aScaledSize.width, aScaledSize.height);
|
||||||
uint8_t* a1data = Data32BitTo1Bit(data, width, height);
|
if (iconSize == IntSize(0, 0)) { // use frame's intrinsic size
|
||||||
|
iconSize = surfaceSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<DataSourceSurface> dataSurface;
|
||||||
|
bool mappedOK;
|
||||||
|
DataSourceSurface::MappedSurface map;
|
||||||
|
|
||||||
|
if (iconSize != surfaceSize) {
|
||||||
|
// Scale the surface
|
||||||
|
dataSurface = Factory::CreateDataSourceSurface(iconSize,
|
||||||
|
SurfaceFormat::B8G8R8A8);
|
||||||
|
NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
|
||||||
|
mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ_WRITE, &map);
|
||||||
|
NS_ENSURE_TRUE(mappedOK, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
RefPtr<DrawTarget> dt =
|
||||||
|
Factory::CreateDrawTargetForData(BackendType::CAIRO,
|
||||||
|
map.mData,
|
||||||
|
dataSurface->GetSize(),
|
||||||
|
map.mStride,
|
||||||
|
SurfaceFormat::B8G8R8A8);
|
||||||
|
dt->DrawSurface(surface,
|
||||||
|
Rect(0, 0, iconSize.width, iconSize.height),
|
||||||
|
Rect(0, 0, surfaceSize.width, surfaceSize.height),
|
||||||
|
DrawSurfaceOptions(),
|
||||||
|
DrawOptions(1.0f, CompositionOp::OP_SOURCE));
|
||||||
|
} else if (surface->GetFormat() != SurfaceFormat::B8G8R8A8) {
|
||||||
|
// Convert format to SurfaceFormat::B8G8R8A8
|
||||||
|
dataSurface = Factory::CreateDataSourceSurface(iconSize,
|
||||||
|
SurfaceFormat::B8G8R8A8);
|
||||||
|
NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
RefPtr<DrawTarget> dt =
|
||||||
|
Factory::CreateDrawTargetForData(BackendType::CAIRO,
|
||||||
|
map.mData,
|
||||||
|
dataSurface->GetSize(),
|
||||||
|
map.mStride,
|
||||||
|
SurfaceFormat::B8G8R8A8);
|
||||||
|
dt->CopySurface(surface, IntRect(IntPoint(0, 0), iconSize),
|
||||||
|
IntPoint(0, 0));
|
||||||
|
|
||||||
|
mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ, &map);
|
||||||
|
} else {
|
||||||
|
dataSurface = surface->GetDataSurface();
|
||||||
|
mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ, &map);
|
||||||
|
}
|
||||||
|
NS_ENSURE_TRUE(dataSurface && mappedOK, NS_ERROR_FAILURE);
|
||||||
|
MOZ_ASSERT(dataSurface->GetFormat() == SurfaceFormat::B8G8R8A8);
|
||||||
|
|
||||||
|
uint8_t* data = nullptr;
|
||||||
|
nsAutoArrayPtr<uint8_t> autoDeleteArray;
|
||||||
|
if (map.mStride == BytesPerPixel(dataSurface->GetFormat()) * iconSize.width) {
|
||||||
|
// Mapped data is already packed
|
||||||
|
data = map.mData;
|
||||||
|
} else {
|
||||||
|
// We can't use map.mData since the pixels are not packed (as required by
|
||||||
|
// CreateDIBitmap, which is called under the DataToBitmap call below).
|
||||||
|
data = autoDeleteArray = SurfaceToPackedBGRA(dataSurface);
|
||||||
|
if (!data) {
|
||||||
|
dataSurface->Unmap();
|
||||||
|
return NS_ERROR_FAILURE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HBITMAP bmp = DataToBitmap(data, iconSize.width, -iconSize.height, 32);
|
||||||
|
uint8_t* a1data = Data32BitTo1Bit(data, iconSize.width, iconSize.height);
|
||||||
|
dataSurface->Unmap();
|
||||||
if (!a1data) {
|
if (!a1data) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
HBITMAP mbmp = DataToBitmap(a1data, width, -height, 1);
|
HBITMAP mbmp = DataToBitmap(a1data, iconSize.width, -iconSize.height, 1);
|
||||||
PR_Free(a1data);
|
PR_Free(a1data);
|
||||||
|
|
||||||
ICONINFO info = {0};
|
ICONINFO info = {0};
|
||||||
|
Loading…
Reference in New Issue
Block a user