зеркало из 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;
|
||||
|
||||
class SkPDFDeviceFactory : public SkDeviceFactory {
|
||||
public:
|
||||
virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width,
|
||||
int height, bool isOpaque, bool isForLayer);
|
||||
};
|
||||
|
@ -138,6 +139,8 @@ protected:
|
|||
virtual SkDeviceFactory* onNewDeviceFactory();
|
||||
|
||||
private:
|
||||
friend class SkPDFDeviceFactory;
|
||||
|
||||
SkISize fPageSize;
|
||||
SkISize fContentSize;
|
||||
SkMatrix fInitialTransform;
|
||||
|
@ -153,10 +156,12 @@ private:
|
|||
SkTScopedPtr<ContentEntry> fContentEntries;
|
||||
ContentEntry* fCurrentContentEntry;
|
||||
|
||||
// For use by the DeviceFactory.
|
||||
SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack,
|
||||
const SkRegion& existingClipRegion);
|
||||
|
||||
void init();
|
||||
void cleanUp();
|
||||
void setExistingClip(const SkClipStack& clipStack,
|
||||
const SkRegion& clipRegion);
|
||||
|
||||
void setUpContentEntry(const SkClipStack& clipStack,
|
||||
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,
|
||||
bool isForLayer) {
|
||||
SkMatrix initialTransform;
|
||||
initialTransform.reset();
|
||||
if (isForLayer) {
|
||||
initialTransform.setTranslate(0, height);
|
||||
initialTransform.preScale(1, -1);
|
||||
}
|
||||
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,
|
||||
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();
|
||||
|
||||
const SkMatrix* initialTransform) {
|
||||
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;
|
||||
}
|
||||
|
||||
SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
|
||||
const SkMatrix& initialTransform)
|
||||
: SkDevice(NULL, makeContentBitmap(contentSize, initialTransform), false),
|
||||
: SkDevice(NULL, makeContentBitmap(contentSize, &initialTransform), false),
|
||||
fPageSize(pageSize),
|
||||
fContentSize(contentSize),
|
||||
fCurrentContentEntry(NULL) {
|
||||
// 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,
|
||||
// we specify an inverse correction to cancel this out.
|
||||
// origin at the bottom left. This matrix corrects for that. But that only
|
||||
// needs to be done once, we don't do it when layering.
|
||||
fInitialTransform.setTranslate(0, pageSize.fHeight);
|
||||
fInitialTransform.preScale(1, -1);
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -454,10 +478,6 @@ void SkPDFDevice::init() {
|
|||
fResourceDict = NULL;
|
||||
fContentEntries.reset();
|
||||
fCurrentContentEntry = NULL;
|
||||
|
||||
SkIRect existingClip = SkIRect::MakeWH(this->width(), this->height());
|
||||
fExistingClipStack.clipDevRect(existingClip);
|
||||
fExistingClipRegion.setRect(existingClip);
|
||||
}
|
||||
|
||||
SkDeviceFactory* SkPDFDevice::onNewDeviceFactory() {
|
||||
|
@ -471,12 +491,6 @@ void SkPDFDevice::cleanUp() {
|
|||
fShaderResources.unrefAll();
|
||||
}
|
||||
|
||||
void SkPDFDevice::setExistingClip(const SkClipStack& clipStack,
|
||||
const SkRegion& clipRegion) {
|
||||
this->fExistingClipStack = clipStack;
|
||||
this->fExistingClipRegion = clipRegion;
|
||||
}
|
||||
|
||||
void SkPDFDevice::clear(SkColor color) {
|
||||
this->cleanUp();
|
||||
this->init();
|
||||
|
@ -809,7 +823,6 @@ void SkPDFDevice::drawDevice(const SkDraw& d, SkDevice* device, int x, int y,
|
|||
SkMatrix matrix;
|
||||
matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
|
||||
setUpContentEntry(*d.fClipStack, *d.fClip, matrix, paint);
|
||||
pdfDevice->setExistingClip(*d.fClipStack, *d.fClip);
|
||||
|
||||
SkPDFFormXObject* xobject = new SkPDFFormXObject(pdfDevice);
|
||||
fXObjectResources.push(xobject); // Transfer reference.
|
||||
|
|
Загрузка…
Ссылка в новой задаче