mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 732985 - Part 2: Use ImageScaler for large images. r=jrmuizel
This commit is contained in:
parent
ca48ea5c42
commit
f1cad61c49
@ -42,6 +42,7 @@
|
||||
#include "PathD2D.h"
|
||||
#include "GradientStopsD2D.h"
|
||||
#include "ScaledFontDWrite.h"
|
||||
#include "ImageScaling.h"
|
||||
#include "Logging.h"
|
||||
#include "Tools.h"
|
||||
#include <algorithm>
|
||||
@ -289,7 +290,7 @@ DrawTargetD2D::DrawSurface(SourceSurface *aSurface,
|
||||
|
||||
int stride = srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat());
|
||||
|
||||
unsigned char *data = &srcSurf->mRawData.front() +
|
||||
unsigned char *data = srcSurf->mRawData +
|
||||
(uint32_t)aSource.y * stride +
|
||||
(uint32_t)aSource.x * BytesPerPixel(srcSurf->GetFormat());
|
||||
|
||||
@ -1982,8 +1983,8 @@ DrawTargetD2D::CreatePartialBitmapForSurface(SourceSurfaceD2D *aSurface, Matrix
|
||||
// or downsample in software.
|
||||
|
||||
Matrix transform = mTransform;
|
||||
transform = aMatrix * transform;
|
||||
if (!transform.Invert()) {
|
||||
Matrix invTransform = transform = aMatrix * transform;
|
||||
if (!invTransform.Invert()) {
|
||||
// Singular transform, nothing to be drawn.
|
||||
return NULL;
|
||||
}
|
||||
@ -1991,7 +1992,7 @@ DrawTargetD2D::CreatePartialBitmapForSurface(SourceSurfaceD2D *aSurface, Matrix
|
||||
Rect rect(0, 0, mSize.width, mSize.height);
|
||||
|
||||
// Calculate the rectangle of the source mapped to our surface.
|
||||
rect = transform.TransformBounds(rect);
|
||||
rect = invTransform.TransformBounds(rect);
|
||||
rect.RoundOut();
|
||||
|
||||
Rect uploadRect(0, 0, aSurface->mSize.width, aSurface->mSize.height);
|
||||
@ -2014,19 +2015,59 @@ DrawTargetD2D::CreatePartialBitmapForSurface(SourceSurfaceD2D *aSurface, Matrix
|
||||
|
||||
// A partial upload will suffice.
|
||||
mRT->CreateBitmap(D2D1::SizeU(uint32_t(uploadRect.width), uint32_t(uploadRect.height)),
|
||||
&aSurface->mRawData.front() + int(uploadRect.x) + int(uploadRect.y) * stride,
|
||||
aSurface->mRawData + int(uploadRect.x) * 4 + int(uploadRect.y) * stride,
|
||||
stride,
|
||||
D2D1::BitmapProperties(D2DPixelFormat(aSurface->mFormat)),
|
||||
byRef(bitmap));
|
||||
|
||||
aMatrix.Translate(-uploadRect.x, -uploadRect.y);
|
||||
aMatrix.Translate(uploadRect.x, uploadRect.y);
|
||||
|
||||
return bitmap;
|
||||
} else {
|
||||
// XXX - FIX ME!!
|
||||
MOZ_ASSERT(false);
|
||||
gfxDebug() << "Source surface used for pattern too large!";
|
||||
return NULL;
|
||||
int Bpp = BytesPerPixel(aSurface->mFormat);
|
||||
|
||||
if (Bpp != 4) {
|
||||
// This shouldn't actually happen in practice!
|
||||
MOZ_ASSERT(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int stride = Bpp * aSurface->mSize.width;
|
||||
|
||||
ImageHalfScaler scaler(aSurface->mRawData, stride, IntSize(aSurface->mSize));
|
||||
|
||||
// Calculate the maximum width/height of the image post transform.
|
||||
Point topRight = transform * Point(aSurface->mSize.width, 0);
|
||||
Point topLeft = transform * Point(0, 0);
|
||||
Point bottomRight = transform * Point(aSurface->mSize.width, aSurface->mSize.height);
|
||||
Point bottomLeft = transform * Point(0, aSurface->mSize.height);
|
||||
|
||||
IntSize scaleSize;
|
||||
|
||||
scaleSize.width = max(Distance(topRight, topLeft), Distance(bottomRight, bottomLeft));
|
||||
scaleSize.height = max(Distance(topRight, bottomRight), Distance(topLeft, bottomLeft));
|
||||
|
||||
if (scaleSize.width > mRT->GetMaximumBitmapSize()) {
|
||||
// Ok, in this case we'd really want a downscale of a part of the bitmap,
|
||||
// perhaps we can do this later but for simplicity let's do something
|
||||
// different here and assume it's good enough, this should be rare!
|
||||
scaleSize.width = 4095;
|
||||
}
|
||||
if (scaleSize.height > mRT->GetMaximumBitmapSize()) {
|
||||
scaleSize.height = 4095;
|
||||
}
|
||||
|
||||
scaler.ScaleForSize(scaleSize);
|
||||
|
||||
IntSize newSize = scaler.GetSize();
|
||||
|
||||
mRT->CreateBitmap(D2D1::SizeU(newSize.width, newSize.height),
|
||||
scaler.GetScaledData(), scaler.GetStride(),
|
||||
D2D1::BitmapProperties(D2DPixelFormat(aSurface->mFormat)),
|
||||
byRef(bitmap));
|
||||
|
||||
aMatrix.Scale(aSurface->mSize.width / newSize.width, aSurface->mSize.height / newSize.height);
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,11 +42,13 @@ namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
SourceSurfaceD2D::SourceSurfaceD2D()
|
||||
: mRawData(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
SourceSurfaceD2D::~SourceSurfaceD2D()
|
||||
{
|
||||
delete [] mRawData;
|
||||
}
|
||||
|
||||
IntSize
|
||||
@ -82,9 +84,11 @@ SourceSurfaceD2D::InitFromData(unsigned char *aData,
|
||||
if ((uint32_t)aSize.width > aRT->GetMaximumBitmapSize() ||
|
||||
(uint32_t)aSize.height > aRT->GetMaximumBitmapSize()) {
|
||||
int newStride = BytesPerPixel(aFormat) * aSize.width;
|
||||
mRawData.resize(aSize.height * newStride);
|
||||
// This should only be called once!
|
||||
MOZ_ASSERT(!mRawData);
|
||||
mRawData = new uint8_t[aSize.height * newStride];
|
||||
for (int y = 0; y < aSize.height; y++) {
|
||||
memcpy(&mRawData.front() + y * newStride, aData + y * aStride, newStride);
|
||||
memcpy(mRawData + y * newStride, aData + y * aStride, newStride);
|
||||
}
|
||||
gfxDebug() << "Bitmap does not fit in texture, saving raw data.";
|
||||
return true;
|
||||
|
@ -71,7 +71,7 @@ private:
|
||||
friend class DrawTargetD2D;
|
||||
|
||||
RefPtr<ID2D1Bitmap> mBitmap;
|
||||
std::vector<unsigned char> mRawData;
|
||||
uint8_t *mRawData;
|
||||
SurfaceFormat mFormat;
|
||||
IntSize mSize;
|
||||
};
|
||||
|
@ -66,6 +66,21 @@ struct ClassStorage
|
||||
T *addr() { return (T *)(void *)bytes; }
|
||||
};
|
||||
|
||||
static inline bool
|
||||
FuzzyEqual(Float aA, Float aB, Float aErr)
|
||||
{
|
||||
if ((aA + aErr > aB) && (aA - aErr < aB)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline Float
|
||||
Distance(Point aA, Point aB)
|
||||
{
|
||||
return hypotf(aB.x - aA.x, aB.y - aA.y);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user