зеркало из https://github.com/mozilla/moz-skia.git
[PDF] Fix setting of existing clip for layers.
The current approach of setting the existing clip just before drawing a layer into a device doesn't work. SkDevice::clear() uses existing clip before that and if we need to put the content in a transparency group (i.e. for SrcIn xfermode), we need a valid existing clip. Instead, change the factory to use a special constructor when creating a layer device. Review URL: http://codereview.appspot.com/4495041 git-svn-id: http://skia.googlecode.com/svn/trunk@1270 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
9fbdf87518
Коммит
a0c7edbb08
|
@ -38,6 +38,7 @@ struct ContentEntry;
|
||||||
struct GraphicStateEntry;
|
struct GraphicStateEntry;
|
||||||
|
|
||||||
class SkPDFDeviceFactory : public SkDeviceFactory {
|
class SkPDFDeviceFactory : public SkDeviceFactory {
|
||||||
|
public:
|
||||||
virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width,
|
virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width,
|
||||||
int height, bool isOpaque, bool isForLayer);
|
int height, bool isOpaque, bool isForLayer);
|
||||||
};
|
};
|
||||||
|
@ -138,6 +139,8 @@ protected:
|
||||||
virtual SkDeviceFactory* onNewDeviceFactory();
|
virtual SkDeviceFactory* onNewDeviceFactory();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
friend class SkPDFDeviceFactory;
|
||||||
|
|
||||||
SkISize fPageSize;
|
SkISize fPageSize;
|
||||||
SkISize fContentSize;
|
SkISize fContentSize;
|
||||||
SkMatrix fInitialTransform;
|
SkMatrix fInitialTransform;
|
||||||
|
@ -153,10 +156,12 @@ private:
|
||||||
SkTScopedPtr<ContentEntry> fContentEntries;
|
SkTScopedPtr<ContentEntry> fContentEntries;
|
||||||
ContentEntry* fCurrentContentEntry;
|
ContentEntry* fCurrentContentEntry;
|
||||||
|
|
||||||
|
// For use by the DeviceFactory.
|
||||||
|
SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack,
|
||||||
|
const SkRegion& existingClipRegion);
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
void cleanUp();
|
void cleanUp();
|
||||||
void setExistingClip(const SkClipStack& clipStack,
|
|
||||||
const SkRegion& clipRegion);
|
|
||||||
|
|
||||||
void setUpContentEntry(const SkClipStack& clipStack,
|
void setUpContentEntry(const SkClipStack& clipStack,
|
||||||
const SkRegion& clipRegion,
|
const SkRegion& clipRegion,
|
||||||
|
|
|
@ -402,47 +402,71 @@ void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) {
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SkDevice* SkPDFDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config,
|
SkDevice* SkPDFDeviceFactory::newDevice(SkCanvas* c, SkBitmap::Config config,
|
||||||
int width, int height, bool isOpaque,
|
int width, int height, bool isOpaque,
|
||||||
bool isForLayer) {
|
bool isForLayer) {
|
||||||
SkMatrix initialTransform;
|
SkMatrix initialTransform;
|
||||||
initialTransform.reset();
|
initialTransform.reset();
|
||||||
if (isForLayer) {
|
|
||||||
initialTransform.setTranslate(0, height);
|
|
||||||
initialTransform.preScale(1, -1);
|
|
||||||
}
|
|
||||||
SkISize size = SkISize::Make(width, height);
|
SkISize size = SkISize::Make(width, height);
|
||||||
return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform));
|
if (isForLayer) {
|
||||||
|
return SkNEW_ARGS(SkPDFDevice, (size, c->getTotalClipStack(),
|
||||||
|
c->getTotalClip()));
|
||||||
|
} else {
|
||||||
|
return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline SkBitmap makeContentBitmap(const SkISize& contentSize,
|
static inline SkBitmap makeContentBitmap(const SkISize& contentSize,
|
||||||
const SkMatrix& initialTransform) {
|
const SkMatrix* initialTransform) {
|
||||||
// Compute the size of the drawing area.
|
|
||||||
SkVector drawingSize;
|
|
||||||
SkMatrix inverse;
|
|
||||||
drawingSize.set(contentSize.fWidth, contentSize.fHeight);
|
|
||||||
initialTransform.invert(&inverse);
|
|
||||||
inverse.mapVectors(&drawingSize, 1);
|
|
||||||
SkISize size = SkSize::Make(drawingSize.fX, drawingSize.fY).toRound();
|
|
||||||
|
|
||||||
SkBitmap bitmap;
|
SkBitmap bitmap;
|
||||||
bitmap.setConfig(SkBitmap::kNo_Config, abs(size.fWidth), abs(size.fHeight));
|
if (initialTransform) {
|
||||||
|
// Compute the size of the drawing area.
|
||||||
|
SkVector drawingSize;
|
||||||
|
SkMatrix inverse;
|
||||||
|
drawingSize.set(contentSize.fWidth, contentSize.fHeight);
|
||||||
|
initialTransform->invert(&inverse);
|
||||||
|
inverse.mapVectors(&drawingSize, 1);
|
||||||
|
SkISize size = SkSize::Make(drawingSize.fX, drawingSize.fY).toRound();
|
||||||
|
bitmap.setConfig(SkBitmap::kNo_Config, abs(size.fWidth),
|
||||||
|
abs(size.fHeight));
|
||||||
|
} else {
|
||||||
|
bitmap.setConfig(SkBitmap::kNo_Config, abs(contentSize.fWidth),
|
||||||
|
abs(contentSize.fHeight));
|
||||||
|
}
|
||||||
|
|
||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
|
SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
|
||||||
const SkMatrix& initialTransform)
|
const SkMatrix& initialTransform)
|
||||||
: SkDevice(NULL, makeContentBitmap(contentSize, initialTransform), false),
|
: SkDevice(NULL, makeContentBitmap(contentSize, &initialTransform), false),
|
||||||
fPageSize(pageSize),
|
fPageSize(pageSize),
|
||||||
fContentSize(contentSize),
|
fContentSize(contentSize),
|
||||||
fCurrentContentEntry(NULL) {
|
fCurrentContentEntry(NULL) {
|
||||||
// Skia generally uses the top left as the origin but PDF natively has the
|
// Skia generally uses the top left as the origin but PDF natively has the
|
||||||
// origin at the bottom left. This matrix corrects for that. When layering,
|
// origin at the bottom left. This matrix corrects for that. But that only
|
||||||
// we specify an inverse correction to cancel this out.
|
// needs to be done once, we don't do it when layering.
|
||||||
fInitialTransform.setTranslate(0, pageSize.fHeight);
|
fInitialTransform.setTranslate(0, pageSize.fHeight);
|
||||||
fInitialTransform.preScale(1, -1);
|
fInitialTransform.preScale(1, -1);
|
||||||
fInitialTransform.preConcat(initialTransform);
|
fInitialTransform.preConcat(initialTransform);
|
||||||
|
|
||||||
|
SkIRect existingClip = SkIRect::MakeWH(this->width(), this->height());
|
||||||
|
fExistingClipStack.clipDevRect(existingClip);
|
||||||
|
fExistingClipRegion.setRect(existingClip);
|
||||||
|
|
||||||
|
this->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
SkPDFDevice::SkPDFDevice(const SkISize& layerSize,
|
||||||
|
const SkClipStack& existingClipStack,
|
||||||
|
const SkRegion& existingClipRegion)
|
||||||
|
: SkDevice(NULL, makeContentBitmap(layerSize, NULL), false),
|
||||||
|
fPageSize(layerSize),
|
||||||
|
fContentSize(layerSize),
|
||||||
|
fExistingClipStack(existingClipStack),
|
||||||
|
fExistingClipRegion(existingClipRegion),
|
||||||
|
fCurrentContentEntry(NULL) {
|
||||||
|
fInitialTransform.reset();
|
||||||
this->init();
|
this->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,10 +478,6 @@ void SkPDFDevice::init() {
|
||||||
fResourceDict = NULL;
|
fResourceDict = NULL;
|
||||||
fContentEntries.reset();
|
fContentEntries.reset();
|
||||||
fCurrentContentEntry = NULL;
|
fCurrentContentEntry = NULL;
|
||||||
|
|
||||||
SkIRect existingClip = SkIRect::MakeWH(this->width(), this->height());
|
|
||||||
fExistingClipStack.clipDevRect(existingClip);
|
|
||||||
fExistingClipRegion.setRect(existingClip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SkDeviceFactory* SkPDFDevice::onNewDeviceFactory() {
|
SkDeviceFactory* SkPDFDevice::onNewDeviceFactory() {
|
||||||
|
@ -471,12 +491,6 @@ void SkPDFDevice::cleanUp() {
|
||||||
fShaderResources.unrefAll();
|
fShaderResources.unrefAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkPDFDevice::setExistingClip(const SkClipStack& clipStack,
|
|
||||||
const SkRegion& clipRegion) {
|
|
||||||
this->fExistingClipStack = clipStack;
|
|
||||||
this->fExistingClipRegion = clipRegion;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkPDFDevice::clear(SkColor color) {
|
void SkPDFDevice::clear(SkColor color) {
|
||||||
this->cleanUp();
|
this->cleanUp();
|
||||||
this->init();
|
this->init();
|
||||||
|
@ -809,7 +823,6 @@ void SkPDFDevice::drawDevice(const SkDraw& d, SkDevice* device, int x, int y,
|
||||||
SkMatrix matrix;
|
SkMatrix matrix;
|
||||||
matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
|
matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
|
||||||
setUpContentEntry(*d.fClipStack, *d.fClip, matrix, paint);
|
setUpContentEntry(*d.fClipStack, *d.fClip, matrix, paint);
|
||||||
pdfDevice->setExistingClip(*d.fClipStack, *d.fClip);
|
|
||||||
|
|
||||||
SkPDFFormXObject* xobject = new SkPDFFormXObject(pdfDevice);
|
SkPDFFormXObject* xobject = new SkPDFFormXObject(pdfDevice);
|
||||||
fXObjectResources.push(xobject); // Transfer reference.
|
fXObjectResources.push(xobject); // Transfer reference.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче