aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdf')
-rw-r--r--src/pdf/SkPDFDevice.cpp357
-rw-r--r--src/pdf/SkPDFGraphicState.cpp7
2 files changed, 245 insertions, 119 deletions
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index a7d2bd459a..91f8e87487 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -480,7 +480,8 @@ void GraphicStackState::updateClip(const SkClipStack& clipStack,
bool needRegion = false;
const SkClipStack::Element* clipEntry;
for (clipEntry = iter.next(); clipEntry; clipEntry = iter.next()) {
- if (clipEntry->getOp() != SkRegion::kIntersect_Op || clipEntry->isInverseFilled()) {
+ if (clipEntry->getOp() != SkRegion::kIntersect_Op ||
+ clipEntry->isInverseFilled()) {
needRegion = true;
break;
}
@@ -619,7 +620,8 @@ public:
const SkPaint& paint, bool hasText = false)
: fDevice(device),
fContentEntry(NULL),
- fXfermode(SkXfermode::kSrcOver_Mode) {
+ fXfermode(SkXfermode::kSrcOver_Mode),
+ fDstFormXObject(NULL) {
init(draw.fClipStack, *draw.fClip, *draw.fMatrix, paint, hasText);
}
ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack,
@@ -627,27 +629,67 @@ public:
const SkPaint& paint, bool hasText = false)
: fDevice(device),
fContentEntry(NULL),
- fXfermode(SkXfermode::kSrcOver_Mode) {
+ fXfermode(SkXfermode::kSrcOver_Mode),
+ fDstFormXObject(NULL) {
init(clipStack, clipRegion, matrix, paint, hasText);
}
~ScopedContentEntry() {
if (fContentEntry) {
- fDevice->finishContentEntry(fXfermode, fDstFormXObject);
+ SkPath* shape = &fShape;
+ if (shape->isEmpty()) {
+ shape = NULL;
+ }
+ fDevice->finishContentEntry(fXfermode, fDstFormXObject, shape);
}
SkSafeUnref(fDstFormXObject);
}
ContentEntry* entry() { return fContentEntry; }
+
+ /* Returns true when we explicitly need the shape of the drawing. */
+ bool needShape() {
+ switch (fXfermode) {
+ case SkXfermode::kClear_Mode:
+ case SkXfermode::kSrc_Mode:
+ case SkXfermode::kSrcIn_Mode:
+ case SkXfermode::kSrcOut_Mode:
+ case SkXfermode::kDstIn_Mode:
+ case SkXfermode::kDstOut_Mode:
+ case SkXfermode::kSrcATop_Mode:
+ case SkXfermode::kDstATop_Mode:
+ case SkXfermode::kModulate_Mode:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ /* Returns true unless we only need the shape of the drawing. */
+ bool needSource() {
+ if (fXfermode == SkXfermode::kClear_Mode) {
+ return false;
+ }
+ return true;
+ }
+
+ /* If the shape is different than the alpha component of the content, then
+ * setShape should be called with the shape. In particular, images and
+ * devices have rectangular shape.
+ */
+ void setShape(const SkPath& shape) {
+ fShape = shape;
+ }
+
private:
SkPDFDevice* fDevice;
ContentEntry* fContentEntry;
SkXfermode::Mode fXfermode;
SkPDFFormXObject* fDstFormXObject;
+ SkPath fShape;
void init(const SkClipStack* clipStack, const SkRegion& clipRegion,
const SkMatrix& matrix, const SkPaint& paint, bool hasText) {
- fDstFormXObject = NULL;
// Shape has to be flatten before we get here.
if (matrix.hasPerspective()) {
NOT_IMPLEMENTED(!matrix.hasPerspective(), false);
@@ -1054,7 +1096,8 @@ void SkPDFDevice::drawBitmap(const SkDraw& d, const SkBitmap& bitmap,
SkMatrix transform = matrix;
transform.postConcat(*d.fMatrix);
- this->internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, NULL, paint);
+ this->internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, NULL,
+ paint);
}
void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap,
@@ -1065,7 +1108,8 @@ void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap,
SkMatrix matrix;
matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
- this->internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL, paint);
+ this->internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL,
+ paint);
}
void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
@@ -1170,7 +1214,8 @@ void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
// find all the typefaces needed to resolve this run of text
bool usesOriginalTypeface = false;
for (uint16_t x = 0; x < numGlyphs; ++x) {
- // optimization that checks to see if original typeface can resolve the glyph
+ // optimization that checks to see if original typeface can resolve
+ // the glyph
if (glyphIDs[x] < origGlyphCount) {
usesOriginalTypeface = true;
continue;
@@ -1178,9 +1223,11 @@ void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
// find the fallback typeface that supports this glyph
TypefaceFallbackData data;
- data.typeface = SkGetTypefaceForGlyphID(glyphIDs[x], origFace.get(),
- paint.getPaintOptionsAndroid(),
- &data.lowerBounds, &data.upperBounds);
+ data.typeface =
+ SkGetTypefaceForGlyphID(glyphIDs[x], origFace.get(),
+ paint.getPaintOptionsAndroid(),
+ &data.lowerBounds,
+ &data.upperBounds);
// add the typeface and its data if we don't have it
if (data.typeface && !visitedTypefaces.contains(data)) {
visitedTypefaces.push(data);
@@ -1208,7 +1255,8 @@ void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
int tmpGlyphCount = 0;
for (uint16_t y = 0; y < numGlyphs; ++y) {
- if (glyphIDs[y] >= data.lowerBounds && glyphIDs[y] < data.upperBounds) {
+ if (glyphIDs[y] >= data.lowerBounds &&
+ glyphIDs[y] < data.upperBounds) {
tmpGlyphIDs[tmpGlyphCount] = glyphIDs[y] - data.lowerBounds;
memcpy(&(tmpPos[tmpGlyphCount * scalarsPerPos]),
&(pos[y * scalarsPerPos]),
@@ -1286,8 +1334,8 @@ void SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode,
NOT_IMPLEMENTED("drawVerticies", true);
}
-void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, int x, int y,
- const SkPaint& paint) {
+void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device,
+ int x, int y, const SkPaint& paint) {
if ((device->getDeviceCapabilities() & kVector_Capability) == 0) {
// If we somehow get a raster device, do what our parent would do.
INHERITED::drawDevice(d, device, x, y, paint);
@@ -1306,10 +1354,18 @@ void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, int x, int y
if (!content.entry()) {
return;
}
+ if (content.needShape()) {
+ SkPath shape;
+ shape.addRect(SkRect::MakeXYWH(SkIntToScalar(x), SkIntToScalar(y),
+ device->width(), device->height()));
+ content.setShape(shape);
+ }
+ if (!content.needSource()) {
+ return;
+ }
- SkPDFFormXObject* xobject = new SkPDFFormXObject(pdfDevice);
- fXObjectResources.push(xobject); // Transfer reference.
- SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1,
+ SkAutoTUnref<SkPDFFormXObject> xObject(new SkPDFFormXObject(pdfDevice));
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()),
&content.entry()->fContent);
// Merge glyph sets from the drawn device.
@@ -1552,7 +1608,8 @@ bool SkPDFDevice::handleRectAnnotation(const SkRect& r, const SkMatrix& matrix,
handleLinkToURL(urlData, r, matrix);
return p.isNoDrawAnnotation();
}
- SkData* linkToName = annotationInfo->find(SkAnnotationKeys::Link_Named_Dest_Key());
+ SkData* linkToName = annotationInfo->find(
+ SkAnnotationKeys::Link_Named_Dest_Key());
if (linkToName) {
handleLinkToNamedDest(linkToName, r, matrix);
return p.isNoDrawAnnotation();
@@ -1567,7 +1624,8 @@ bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count,
if (!annotationInfo) {
return false;
}
- SkData* nameData = annotationInfo->find(SkAnnotationKeys::Define_Named_Dest_Key());
+ SkData* nameData = annotationInfo->find(
+ SkAnnotationKeys::Define_Named_Dest_Key());
if (nameData) {
for (size_t i = 0; i < count; i++) {
defineNamedDestination(nameData, points[i], matrix);
@@ -1577,7 +1635,8 @@ bool SkPDFDevice::handlePointAnnotation(const SkPoint* points, size_t count,
return false;
}
-SkPDFDict* SkPDFDevice::createLinkAnnotation(const SkRect& r, const SkMatrix& matrix) {
+SkPDFDict* SkPDFDevice::createLinkAnnotation(const SkRect& r,
+ const SkMatrix& matrix) {
SkMatrix transform = matrix;
transform.postConcat(fInitialTransform);
SkRect translatedRect;
@@ -1663,7 +1722,8 @@ void SkPDFDevice::appendDestinations(SkPDFDict* dict, SkPDFObject* page) {
pdfDest->appendScalar(dest->point.x());
pdfDest->appendScalar(dest->point.y());
pdfDest->appendInt(0); // Leave zoom unchanged
- dict->insert(static_cast<const char *>(dest->nameData->data()), pdfDest);
+ dict->insert(static_cast<const char *>(dest->nameData->data()),
+ pdfDest);
}
}
@@ -1677,51 +1737,31 @@ SkPDFFormXObject* SkPDFDevice::createFormXObjectFromDevice() {
return xobject;
}
-void SkPDFDevice::clearClipFromContent(const SkClipStack* clipStack,
- const SkRegion& clipRegion) {
- if (clipRegion.isEmpty() || isContentEmpty()) {
- return;
- }
- SkAutoTUnref<SkPDFFormXObject> curContent(createFormXObjectFromDevice());
-
- // Redraw what we already had, but with the clip as a mask.
- drawFormXObjectWithClip(curContent, clipStack, clipRegion, true);
-}
-
-void SkPDFDevice::drawFormXObjectWithClip(SkPDFFormXObject* xobject,
+void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex,
+ SkPDFFormXObject* mask,
const SkClipStack* clipStack,
const SkRegion& clipRegion,
+ SkXfermode::Mode mode,
bool invertClip) {
if (clipRegion.isEmpty() && !invertClip) {
return;
}
- // Create the mask.
- SkMatrix identity;
- identity.reset();
- SkDraw draw;
- draw.fMatrix = &identity;
- draw.fClip = &clipRegion;
- draw.fClipStack = clipStack;
- SkPaint stockPaint;
- this->drawPaint(draw, stockPaint);
- SkAutoTUnref<SkPDFFormXObject> maskFormXObject(createFormXObjectFromDevice());
SkAutoTUnref<SkPDFGraphicState> sMaskGS(
- SkPDFGraphicState::GetSMaskGraphicState(maskFormXObject, invertClip,
- SkPDFGraphicState::kAlpha_SMaskMode));
+ SkPDFGraphicState::GetSMaskGraphicState(
+ mask, invertClip, SkPDFGraphicState::kAlpha_SMaskMode));
- // Draw the xobject with the clip as a mask.
- ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion,
- identity, stockPaint);
+ SkMatrix identity;
+ identity.reset();
+ SkPaint paint;
+ paint.setXfermodeMode(mode);
+ ScopedContentEntry content(this, clipStack, clipRegion, identity, paint);
if (!content.entry()) {
return;
}
SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
&content.entry()->fContent);
- SkPDFUtils::DrawFormXObject(fXObjectResources.count(),
- &content.entry()->fContent);
- fXObjectResources.push(xobject);
- xobject->ref();
+ SkPDFUtils::DrawFormXObject(xObjectIndex, &content.entry()->fContent);
sMaskGS.reset(SkPDFGraphicState::GetNoSMaskGraphicState());
SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
@@ -1762,28 +1802,32 @@ ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack,
paint.getXfermode()->asMode(&xfermode);
}
- if (xfermode == SkXfermode::kClear_Mode ||
- xfermode == SkXfermode::kSrc_Mode) {
- this->clearClipFromContent(clipStack, clipRegion);
- } else if (xfermode == SkXfermode::kSrcIn_Mode ||
- xfermode == SkXfermode::kDstIn_Mode ||
- xfermode == SkXfermode::kSrcOut_Mode ||
- xfermode == SkXfermode::kDstOut_Mode) {
- // For the following modes, we use both source and destination, but
- // we use one as a smask for the other, so we have to make form xobjects
- // out of both of them: SrcIn, DstIn, SrcOut, DstOut.
- if (isContentEmpty()) {
- return NULL;
- } else {
+ // For the following modes, we want to handle source and destination
+ // separately, so make an object of what's already there.
+ if (xfermode == SkXfermode::kClear_Mode ||
+ xfermode == SkXfermode::kSrc_Mode ||
+ xfermode == SkXfermode::kSrcIn_Mode ||
+ xfermode == SkXfermode::kDstIn_Mode ||
+ xfermode == SkXfermode::kSrcOut_Mode ||
+ xfermode == SkXfermode::kDstOut_Mode ||
+ xfermode == SkXfermode::kSrcATop_Mode ||
+ xfermode == SkXfermode::kDstATop_Mode ||
+ xfermode == SkXfermode::kModulate_Mode) {
+ if (!isContentEmpty()) {
*dst = createFormXObjectFromDevice();
+ SkASSERT(isContentEmpty());
+ } else if (xfermode != SkXfermode::kSrc_Mode &&
+ xfermode != SkXfermode::kSrcOut_Mode) {
+ // Except for Src and SrcOut, if there isn't anything already there,
+ // then we're done.
+ return NULL;
}
}
// TODO(vandebo): Figure out how/if we can handle the following modes:
- // SrcAtop, DestAtop, Xor, Plus.
+ // Xor, Plus.
- // These xfer modes don't draw source at all.
- if (xfermode == SkXfermode::kClear_Mode ||
- xfermode == SkXfermode::kDst_Mode) {
+ // Dst xfer mode doesn't draw source at all.
+ if (xfermode == SkXfermode::kDst_Mode) {
return NULL;
}
@@ -1821,70 +1865,135 @@ ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack,
}
void SkPDFDevice::finishContentEntry(const SkXfermode::Mode xfermode,
- SkPDFFormXObject* dst) {
- if (xfermode != SkXfermode::kSrcIn_Mode &&
- xfermode != SkXfermode::kDstIn_Mode &&
- xfermode != SkXfermode::kSrcOut_Mode &&
- xfermode != SkXfermode::kDstOut_Mode) {
+ SkPDFFormXObject* dst,
+ SkPath* shape) {
+ if (xfermode != SkXfermode::kClear_Mode &&
+ xfermode != SkXfermode::kSrc_Mode &&
+ xfermode != SkXfermode::kSrcIn_Mode &&
+ xfermode != SkXfermode::kDstIn_Mode &&
+ xfermode != SkXfermode::kSrcOut_Mode &&
+ xfermode != SkXfermode::kDstOut_Mode &&
+ xfermode != SkXfermode::kSrcATop_Mode &&
+ xfermode != SkXfermode::kDstATop_Mode &&
+ xfermode != SkXfermode::kModulate_Mode) {
SkASSERT(!dst);
return;
}
+ if (!dst) {
+ SkASSERT(xfermode == SkXfermode::kSrc_Mode ||
+ xfermode == SkXfermode::kSrcOut_Mode);
+ return;
+ }
ContentEntry* contentEntries = getContentEntries()->get();
SkASSERT(dst);
SkASSERT(!contentEntries->fNext.get());
// We have to make a copy of these here because changing the current
- // content into a form xobject will destroy them.
+ // content into a form-xobject will destroy them.
SkClipStack clipStack = contentEntries->fState.fClipStack;
SkRegion clipRegion = contentEntries->fState.fClipRegion;
SkAutoTUnref<SkPDFFormXObject> srcFormXObject;
- if (!isContentEmpty()) {
+ if (isContentEmpty()) {
+ SkASSERT(xfermode == SkXfermode::kClear_Mode);
+ } else {
+ SkASSERT(!fContentEntries->fNext.get());
srcFormXObject.reset(createFormXObjectFromDevice());
}
- drawFormXObjectWithClip(dst, &clipStack, clipRegion, true);
+ SkMatrix identity;
+ identity.reset();
- // We've redrawn dst minus the clip area, if there's no src, we're done.
- if (!srcFormXObject.get()) {
- return;
+ // TODO(vandebo) srcFormXObject may contain alpha, but here we want it
+ // without alpha.
+ if (xfermode == SkXfermode::kSrcATop_Mode) {
+ // TODO(vandebo): In order to properly support SrcATop we have to track
+ // the shape of what's been drawn at all times. It's the intersection of
+ // the non-transparent parts of the device and the outlines (shape) of
+ // all images and devices drawn.
+ drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
+ &clipStack, clipRegion,
+ SkXfermode::kSrcOver_Mode, true);
+ } else {
+ SkAutoTUnref<SkPDFFormXObject> dstMaskStorage;
+ SkPDFFormXObject* dstMask = srcFormXObject.get();
+ if (shape != NULL) {
+ // Draw shape into a form-xobject.
+ SkDraw d;
+ d.fMatrix = &identity;
+ d.fClip = &clipRegion;
+ d.fClipStack = &clipStack;
+ SkPaint filledPaint;
+ filledPaint.setColor(SK_ColorBLACK);
+ filledPaint.setStyle(SkPaint::kFill_Style);
+ this->drawPath(d, *shape, filledPaint, NULL, true);
+
+ dstMaskStorage.reset(createFormXObjectFromDevice());
+ dstMask = dstMaskStorage.get();
+ }
+ drawFormXObjectWithMask(addXObjectResource(dst), dstMask, &clipStack,
+ clipRegion, SkXfermode::kSrcOver_Mode, true);
}
- SkMatrix identity;
- identity.reset();
SkPaint stockPaint;
- ScopedContentEntry inClipContentEntry(this, &fExistingClipStack,
- fExistingClipRegion, identity,
- stockPaint);
- if (!inClipContentEntry.entry()) {
+
+ if (xfermode == SkXfermode::kClear_Mode) {
+ return;
+ } else if (xfermode == SkXfermode::kSrc_Mode ||
+ xfermode == SkXfermode::kDstATop_Mode) {
+ ScopedContentEntry content(this, &clipStack, clipRegion, identity,
+ stockPaint);
+ if (content.entry()) {
+ SkPDFUtils::DrawFormXObject(
+ this->addXObjectResource(srcFormXObject.get()),
+ &content.entry()->fContent);
+ }
+ if (xfermode == SkXfermode::kSrc_Mode) {
+ return;
+ }
+ } else if (xfermode == SkXfermode::kSrcATop_Mode) {
+ ScopedContentEntry content(this, &clipStack, clipRegion, identity,
+ stockPaint);
+ if (content.entry()) {
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
+ &content.entry()->fContent);
+ }
+ }
+
+ SkASSERT(xfermode == SkXfermode::kSrcIn_Mode ||
+ xfermode == SkXfermode::kDstIn_Mode ||
+ xfermode == SkXfermode::kSrcOut_Mode ||
+ xfermode == SkXfermode::kDstOut_Mode ||
+ xfermode == SkXfermode::kSrcATop_Mode ||
+ xfermode == SkXfermode::kDstATop_Mode ||
+ xfermode == SkXfermode::kModulate_Mode);
+
+ ScopedContentEntry inShapeContentEntry(this, &fExistingClipStack,
+ fExistingClipRegion, identity,
+ stockPaint);
+ if (!inShapeContentEntry.entry()) {
return;
}
- SkAutoTUnref<SkPDFGraphicState> sMaskGS;
if (xfermode == SkXfermode::kSrcIn_Mode ||
- xfermode == SkXfermode::kSrcOut_Mode) {
- sMaskGS.reset(SkPDFGraphicState::GetSMaskGraphicState(
- dst,
- xfermode == SkXfermode::kSrcOut_Mode,
- SkPDFGraphicState::kAlpha_SMaskMode));
- fXObjectResources.push(srcFormXObject.get());
- srcFormXObject.get()->ref();
+ xfermode == SkXfermode::kSrcOut_Mode ||
+ xfermode == SkXfermode::kSrcATop_Mode) {
+ drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
+ &clipStack, clipRegion,
+ SkXfermode::kSrcOver_Mode,
+ xfermode == SkXfermode::kSrcOut_Mode);
} else {
- sMaskGS.reset(SkPDFGraphicState::GetSMaskGraphicState(
- srcFormXObject.get(),
- xfermode == SkXfermode::kDstOut_Mode,
- SkPDFGraphicState::kAlpha_SMaskMode));
- // dst already added to fXObjectResources in drawFormXObjectWithClip.
+ SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
+ if (xfermode == SkXfermode::kModulate_Mode) {
+ drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()),
+ dst, &clipStack, clipRegion,
+ SkXfermode::kSrcOver_Mode, false);
+ mode = SkXfermode::kMultiply_Mode;
+ }
+ drawFormXObjectWithMask(addXObjectResource(dst), srcFormXObject.get(),
+ &clipStack, clipRegion, mode,
+ xfermode == SkXfermode::kDstOut_Mode);
}
- SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
- &inClipContentEntry.entry()->fContent);
-
- SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1,
- &inClipContentEntry.entry()->fContent);
-
- sMaskGS.reset(SkPDFGraphicState::GetNoSMaskGraphicState());
- SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
- &inClipContentEntry.entry()->fContent);
}
bool SkPDFDevice::isContentEmpty() {
@@ -1996,6 +2105,18 @@ int SkPDFDevice::addGraphicStateResource(SkPDFGraphicState* gs) {
return result;
}
+int SkPDFDevice::addXObjectResource(SkPDFObject* xObject) {
+ // Assumes that xobject has been canonicalized (so we can directly compare
+ // pointers).
+ int result = fXObjectResources.find(xObject);
+ if (result < 0) {
+ result = fXObjectResources.count();
+ fXObjectResources.push(xObject);
+ xObject->ref();
+ }
+ return result;
+}
+
void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID,
ContentEntry* contentEntry) {
SkTypeface* typeface = paint.getTypeface();
@@ -2015,7 +2136,8 @@ void SkPDFDevice::updateFont(const SkPaint& paint, uint16_t glyphID,
}
int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
- SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface, glyphID));
+ SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface,
+ glyphID));
int resourceIndex = fFontResources.find(newFont.get());
if (resourceIndex < 0) {
resourceIndex = fFontResources.count();
@@ -2119,21 +2241,26 @@ void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
SkIntToScalar(subset.height()));
scaled.postConcat(matrix);
ScopedContentEntry content(this, clipStack, *clipRegion, scaled, paint);
- if (!content.entry()) {
+ if (!content.entry() || (srcRect && !subset.intersect(*srcRect))) {
return;
}
-
- if (srcRect && !subset.intersect(*srcRect)) {
+ if (content.needShape()) {
+ SkPath shape;
+ shape.addRect(SkRect::MakeWH(subset.width(), subset.height()));
+ shape.transform(matrix);
+ content.setShape(shape);
+ }
+ if (!content.needSource()) {
return;
}
- SkPDFImage* image = SkPDFImage::CreateImage(*bitmap, subset, fEncoder);
+ SkAutoTUnref<SkPDFImage> image(
+ SkPDFImage::CreateImage(*bitmap, subset, fEncoder));
if (!image) {
return;
}
- fXObjectResources.push(image); // Transfer reference.
- SkPDFUtils::DrawFormXObject(fXObjectResources.count() - 1,
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()),
&content.entry()->fContent);
}
diff --git a/src/pdf/SkPDFGraphicState.cpp b/src/pdf/SkPDFGraphicState.cpp
index 43d22f308e..9f8edfd206 100644
--- a/src/pdf/SkPDFGraphicState.cpp
+++ b/src/pdf/SkPDFGraphicState.cpp
@@ -14,8 +14,6 @@
static const char* blend_mode_from_xfermode(SkXfermode::Mode mode) {
switch (mode) {
case SkXfermode::kSrcOver_Mode: return "Normal";
- // kModulate is not really like multipy but similar most of the time.
- case SkXfermode::kModulate_Mode:
case SkXfermode::kMultiply_Mode: return "Multiply";
case SkXfermode::kScreen_Mode: return "Screen";
case SkXfermode::kOverlay_Mode: return "Overlay";
@@ -41,11 +39,12 @@ static const char* blend_mode_from_xfermode(SkXfermode::Mode mode) {
case SkXfermode::kDstIn_Mode:
case SkXfermode::kSrcOut_Mode:
case SkXfermode::kDstOut_Mode:
+ case SkXfermode::kSrcATop_Mode:
+ case SkXfermode::kDstATop_Mode:
+ case SkXfermode::kModulate_Mode:
return "Normal";
// TODO(vandebo): Figure out if we can support more of these modes.
- case SkXfermode::kSrcATop_Mode:
- case SkXfermode::kDstATop_Mode:
case SkXfermode::kXor_Mode:
case SkXfermode::kPlus_Mode:
return NULL;