diff options
Diffstat (limited to 'src/pdf')
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 357 | ||||
-rw-r--r-- | src/pdf/SkPDFGraphicState.cpp | 7 |
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; |