diff options
author | 2017-03-07 09:37:29 -0500 | |
---|---|---|
committer | 2017-03-07 15:43:03 +0000 | |
commit | a1361364e64138adda3dc5f71d50d7503838bb6d (patch) | |
tree | 13dd723a62883d7bf3e8d280a0a454fae02081a2 /src/pdf/SkPDFDevice.cpp | |
parent | 467921e5e6479fe9cebba125657d8e33d89004ae (diff) |
Revert[6] "Remove SkDraw from device-draw methods, and enable device-centric clipping.""""""
Previous failure was failure to detect that the clip wasn't wide-open when
optimizing for retain-vs-discard in copy-on-write. gm:copy_on_write_retain
detected this. Now fixed by adding new method to SkBaseDevice.h
This reverts commit 27d07f0acb85eea4062075dfbe9148ce12d92c66.
BUG=skia:6214
Change-Id: I532d16ec075a4525c2a550b1157bcec695dd8efd
Reviewed-on: https://skia-review.googlesource.com/9341
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src/pdf/SkPDFDevice.cpp')
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 356 |
1 files changed, 161 insertions, 195 deletions
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index d54441e92d..26dd09fcd9 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -48,6 +48,23 @@ // Utility functions +static void draw_points(SkCanvas::PointMode mode, + size_t count, + const SkPoint* points, + const SkPaint& paint, + const SkIRect& bounds, + const SkMatrix& ctm, + SkBaseDevice* device) { + SkRasterClip rc(bounds); + SkDraw draw; + draw.fDst = SkPixmap(SkImageInfo::MakeUnknown(bounds.right(), bounds.bottom()), nullptr, 0); + draw.fMatrix = &ctm; + draw.fRC = &rc; + draw.drawPoints(mode, count, points, paint, device); +} + +static SkIRect size(const SkBaseDevice& dev) { return {0, 0, dev.width(), dev.height()}; } + // If the paint will definitely draw opaquely, replace kSrc with // kSrcOver. http://crbug.com/473572 static void replace_srcmode_on_opaque_paint(SkPaint* paint) { @@ -381,23 +398,26 @@ SkPDFCanon* SkPDFDevice::getCanon() const { return fDocument->canon(); } // drawing method and maintain the state needed between set up and finish. class ScopedContentEntry { public: - ScopedContentEntry(SkPDFDevice* device, const SkDraw& draw, - const SkPaint& paint, bool hasText = false) - : fDevice(device), - fContentEntry(nullptr), - fBlendMode(SkBlendMode::kSrcOver), - fDstFormXObject(nullptr) { - init(draw.fClipStack, *draw.fMatrix, paint, hasText); - } - ScopedContentEntry(SkPDFDevice* device, const SkClipStack* clipStack, + ScopedContentEntry(SkPDFDevice* device, + const SkClipStack& clipStack, const SkMatrix& matrix, - const SkPaint& paint, bool hasText = false) - : fDevice(device), - fContentEntry(nullptr), - fBlendMode(SkBlendMode::kSrcOver), - fDstFormXObject(nullptr) { - init(clipStack, matrix, paint, hasText); + const SkPaint& paint, + bool hasText = false) + : fDevice(device) + , fContentEntry(nullptr) + , fBlendMode(SkBlendMode::kSrcOver) + , fDstFormXObject(nullptr) + { + if (matrix.hasPerspective()) { + NOT_IMPLEMENTED(!matrix.hasPerspective(), false); + return; + } + fBlendMode = paint.getBlendMode(); + fContentEntry = + fDevice->setUpContentEntry(clipStack, matrix, paint, hasText, &fDstFormXObject); } + ScopedContentEntry(SkPDFDevice* dev, const SkPaint& paint, bool hasText = false) + : ScopedContentEntry(dev, dev->cs(), dev->ctm(), paint, hasText) {} ~ScopedContentEntry() { if (fContentEntry) { @@ -451,18 +471,6 @@ private: SkBlendMode fBlendMode; sk_sp<SkPDFObject> fDstFormXObject; SkPath fShape; - - void init(const SkClipStack* clipStack, - const SkMatrix& matrix, const SkPaint& paint, bool hasText) { - // Shape has to be flatten before we get here. - if (matrix.hasPerspective()) { - NOT_IMPLEMENTED(!matrix.hasPerspective(), false); - return; - } - fBlendMode = paint.getBlendMode(); - fContentEntry = fDevice->setUpContentEntry(clipStack, matrix, paint, hasText, - &fDstFormXObject); - } }; //////////////////////////////////////////////////////////////////////////////// @@ -503,25 +511,44 @@ void SkPDFDevice::cleanUp() { fShaderResources.unrefAll(); } -void SkPDFDevice::drawAnnotation(const SkDraw& d, const SkRect& rect, const char key[], - SkData* value) { +void SkPDFDevice::drawAnnotation(const SkRect& rect, const char key[], SkData* value) { if (!value) { return; } if (rect.isEmpty()) { - this->handlePointAnnotation({ rect.x(), rect.y() }, *d.fMatrix, key, value); - } else { - this->handleRectAnnotation(rect, d, key, value); + if (!strcmp(SkAnnotationKeys::Define_Named_Dest_Key(), key)) { + SkPoint transformedPoint; + this->ctm().mapXY(rect.x(), rect.y(), &transformedPoint); + fNamedDestinations.emplace_back(value, transformedPoint); + } + return; + } + // Convert to path to handle non-90-degree rotations. + SkPath path; + path.addRect(rect); + path.transform(this->ctm(), &path); + SkPath clip; + (void)this->cs().asPath(&clip); + Op(clip, path, kIntersect_SkPathOp, &path); + // PDF wants a rectangle only. + SkRect transformedRect = path.getBounds(); + if (transformedRect.isEmpty()) { + return; + } + if (!strcmp(SkAnnotationKeys::URL_Key(), key)) { + fLinkToURLs.emplace_back(transformedRect, value); + } else if (!strcmp(SkAnnotationKeys::Link_Named_Dest_Key(), key)) { + fLinkToDestinations.emplace_back(transformedRect, value); } } -void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) { +void SkPDFDevice::drawPaint(const SkPaint& paint) { SkPaint newPaint = paint; replace_srcmode_on_opaque_paint(&newPaint); newPaint.setStyle(SkPaint::kFill_Style); - ScopedContentEntry content(this, d, newPaint); - internalDrawPaint(newPaint, content.entry()); + ScopedContentEntry content(this, newPaint); + this->internalDrawPaint(newPaint, content.entry()); } void SkPDFDevice::internalDrawPaint(const SkPaint& paint, @@ -542,8 +569,7 @@ void SkPDFDevice::internalDrawPaint(const SkPaint& paint, &contentEntry->fContent); } -void SkPDFDevice::drawPoints(const SkDraw& d, - SkCanvas::PointMode mode, +void SkPDFDevice::drawPoints(SkCanvas::PointMode mode, size_t count, const SkPoint* points, const SkPaint& srcPaint) { @@ -558,10 +584,11 @@ void SkPDFDevice::drawPoints(const SkDraw& d, // We only use this when there's a path effect because of the overhead // of multiple calls to setUpContentEntry it causes. if (passedPaint.getPathEffect()) { - if (d.fClipStack->isEmpty(this->getGlobalBounds())) { + if (this->cs().isEmpty(size(*this))) { return; } - d.drawPoints(mode, count, points, passedPaint, this); + draw_points(mode, count, points, passedPaint, + this->devClipBounds(), this->ctm(), this); return; } @@ -581,7 +608,7 @@ void SkPDFDevice::drawPoints(const SkDraw& d, for (size_t i = 0; i < count; i++) { SkRect r = SkRect::MakeXYWH(points[i].fX, points[i].fY, 0, 0); r.inset(-halfStroke, -halfStroke); - drawRect(d, r, modifiedPaint); + this->drawRect(r, modifiedPaint); } return; } else { @@ -589,7 +616,7 @@ void SkPDFDevice::drawPoints(const SkDraw& d, } } - ScopedContentEntry content(this, d, *paint); + ScopedContentEntry content(this, *paint); if (!content.entry()) { return; } @@ -671,8 +698,7 @@ static sk_sp<SkPDFDict> create_link_named_dest(const SkData* nameData, return annotation; } -void SkPDFDevice::drawRect(const SkDraw& d, - const SkRect& rect, +void SkPDFDevice::drawRect(const SkRect& rect, const SkPaint& srcPaint) { SkPaint paint = srcPaint; replace_srcmode_on_opaque_paint(&paint); @@ -680,16 +706,16 @@ void SkPDFDevice::drawRect(const SkDraw& d, r.sort(); if (paint.getPathEffect()) { - if (d.fClipStack->isEmpty(this->getGlobalBounds())) { + if (this->cs().isEmpty(size(*this))) { return; } SkPath path; path.addRect(r); - drawPath(d, path, paint, nullptr, true); + this->drawPath(path, paint, nullptr, true); return; } - ScopedContentEntry content(this, d, paint); + ScopedContentEntry content(this, paint); if (!content.entry()) { return; } @@ -698,37 +724,44 @@ void SkPDFDevice::drawRect(const SkDraw& d, &content.entry()->fContent); } -void SkPDFDevice::drawRRect(const SkDraw& draw, - const SkRRect& rrect, +void SkPDFDevice::drawRRect(const SkRRect& rrect, const SkPaint& srcPaint) { SkPaint paint = srcPaint; replace_srcmode_on_opaque_paint(&paint); SkPath path; path.addRRect(rrect); - this->drawPath(draw, path, paint, nullptr, true); + this->drawPath(path, paint, nullptr, true); } -void SkPDFDevice::drawOval(const SkDraw& draw, - const SkRect& oval, +void SkPDFDevice::drawOval(const SkRect& oval, const SkPaint& srcPaint) { SkPaint paint = srcPaint; replace_srcmode_on_opaque_paint(&paint); SkPath path; path.addOval(oval); - this->drawPath(draw, path, paint, nullptr, true); + this->drawPath(path, paint, nullptr, true); } -void SkPDFDevice::drawPath(const SkDraw& d, - const SkPath& origPath, +void SkPDFDevice::drawPath(const SkPath& origPath, const SkPaint& srcPaint, const SkMatrix* prePathMatrix, bool pathIsMutable) { + this->internalDrawPath( + this->cs(), this->ctm(), origPath, srcPaint, prePathMatrix, pathIsMutable); +} + +void SkPDFDevice::internalDrawPath(const SkClipStack& clipStack, + const SkMatrix& ctm, + const SkPath& origPath, + const SkPaint& srcPaint, + const SkMatrix* prePathMatrix, + bool pathIsMutable) { SkPaint paint = srcPaint; replace_srcmode_on_opaque_paint(&paint); SkPath modifiedPath; SkPath* pathPtr = const_cast<SkPath*>(&origPath); - SkMatrix matrix = *d.fMatrix; + SkMatrix matrix = ctm; if (prePathMatrix) { if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { if (!pathIsMutable) { @@ -742,7 +775,7 @@ void SkPDFDevice::drawPath(const SkDraw& d, } if (paint.getPathEffect()) { - if (d.fClipStack->isEmpty(this->getGlobalBounds())) { + if (clipStack.isEmpty(size(*this))) { return; } if (!pathIsMutable) { @@ -759,15 +792,15 @@ void SkPDFDevice::drawPath(const SkDraw& d, noEffectPaint.setStyle(SkPaint::kStroke_Style); noEffectPaint.setStrokeWidth(0); } - drawPath(d, *pathPtr, noEffectPaint, nullptr, true); + this->internalDrawPath(clipStack, ctm, *pathPtr, noEffectPaint, nullptr, true); return; } - if (handleInversePath(d, origPath, paint, pathIsMutable, prePathMatrix)) { + if (this->handleInversePath(origPath, paint, pathIsMutable, prePathMatrix)) { return; } - ScopedContentEntry content(this, d.fClipStack, matrix, paint); + ScopedContentEntry content(this, clipStack, matrix, paint); if (!content.entry()) { return; } @@ -786,8 +819,7 @@ void SkPDFDevice::drawPath(const SkDraw& d, } -void SkPDFDevice::drawImageRect(const SkDraw& d, - const SkImage* image, +void SkPDFDevice::drawImageRect(const SkImage* image, const SkRect* src, const SkRect& dst, const SkPaint& srcPaint, @@ -815,17 +847,15 @@ void SkPDFDevice::drawImageRect(const SkDraw& d, if (!imageSubset.isValid()) { return; } - transform.postConcat(*d.fMatrix); - this->internalDrawImage(transform, d.fClipStack, - std::move(imageSubset), paint); + transform.postConcat(this->ctm()); + this->internalDrawImage(transform, this->cs(), std::move(imageSubset), paint); } -void SkPDFDevice::drawBitmapRect(const SkDraw& d, - const SkBitmap& bitmap, +void SkPDFDevice::drawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, - const SkPaint& srcPaint, - SkCanvas::SrcRectConstraint) { + const SkPaint& srcPaint, + SkCanvas::SrcRectConstraint) { if (bitmap.drawsNothing()) { return; } @@ -853,16 +883,14 @@ void SkPDFDevice::drawBitmapRect(const SkDraw& d, if (!imageSubset.isValid()) { return; } - transform.postConcat(*d.fMatrix); - this->internalDrawImage(transform, d.fClipStack, - std::move(imageSubset), paint); + transform.postConcat(this->ctm()); + this->internalDrawImage(transform, this->cs(), std::move(imageSubset), paint); } -void SkPDFDevice::drawBitmap(const SkDraw& d, - const SkBitmap& bitmap, +void SkPDFDevice::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint& srcPaint) { - if (bitmap.drawsNothing() || d.fClipStack->isEmpty(this->getGlobalBounds())) { + if (bitmap.drawsNothing() || this->cs().isEmpty(size(*this))) { return; } SkPaint paint = srcPaint; @@ -874,17 +902,15 @@ void SkPDFDevice::drawBitmap(const SkDraw& d, return; } SkMatrix transform = matrix; - transform.postConcat(*d.fMatrix); - this->internalDrawImage( - transform, d.fClipStack, std::move(imageSubset), paint); + transform.postConcat(this->ctm()); + this->internalDrawImage(transform, this->cs(), std::move(imageSubset), paint); } -void SkPDFDevice::drawSprite(const SkDraw& d, - const SkBitmap& bitmap, +void SkPDFDevice::drawSprite(const SkBitmap& bitmap, int x, int y, const SkPaint& srcPaint) { - if (bitmap.drawsNothing() || d.fClipStack->isEmpty(this->getGlobalBounds())) { + if (bitmap.drawsNothing() || this->cs().isEmpty(size(*this))) { return; } SkPaint paint = srcPaint; @@ -896,12 +922,10 @@ void SkPDFDevice::drawSprite(const SkDraw& d, return; } SkMatrix transform = SkMatrix::MakeTrans(SkIntToScalar(x), SkIntToScalar(y)); - this->internalDrawImage( - transform, d.fClipStack, std::move(imageSubset), paint); + this->internalDrawImage(transform, this->cs(), std::move(imageSubset), paint); } -void SkPDFDevice::drawImage(const SkDraw& draw, - const SkImage* image, +void SkPDFDevice::drawImage(const SkImage* image, SkScalar x, SkScalar y, const SkPaint& srcPaint) { @@ -917,9 +941,8 @@ void SkPDFDevice::drawImage(const SkDraw& draw, return; } SkMatrix transform = SkMatrix::MakeTrans(x, y); - transform.postConcat(*draw.fMatrix); - this->internalDrawImage( - transform, draw.fClipStack, std::move(imageSubset), paint); + transform.postConcat(this->ctm()); + this->internalDrawImage(transform, this->cs(), std::move(imageSubset), paint); } namespace { @@ -1213,7 +1236,7 @@ static void update_font(SkWStream* wStream, int fontIndex, SkScalar textSize) { } void SkPDFDevice::internalDrawText( - const SkDraw& d, const void* sourceText, size_t sourceByteCount, + const void* sourceText, size_t sourceByteCount, const SkScalar pos[], SkTextBlob::GlyphPositioning positioning, SkPoint offset, const SkPaint& srcPaint, const uint32_t* clusters, uint32_t textByteLength, const char* utf8Text) { @@ -1297,7 +1320,7 @@ void SkPDFDevice::internalDrawText( } offset.offset(alignmentFactor * advance, 0); } - ScopedContentEntry content(this, d, paint, true); + ScopedContentEntry content(this, paint, true); if (!content.entry()) { return; } @@ -1396,20 +1419,20 @@ void SkPDFDevice::internalDrawText( } } -void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, +void SkPDFDevice::drawText(const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint& paint) { - this->internalDrawText(d, text, len, nullptr, SkTextBlob::kDefault_Positioning, + this->internalDrawText(text, len, nullptr, SkTextBlob::kDefault_Positioning, SkPoint{x, y}, paint, nullptr, 0, nullptr); } -void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, +void SkPDFDevice::drawPosText(const void* text, size_t len, const SkScalar pos[], int scalarsPerPos, const SkPoint& offset, const SkPaint& paint) { - this->internalDrawText(d, text, len, pos, (SkTextBlob::GlyphPositioning)scalarsPerPos, + this->internalDrawText(text, len, pos, (SkTextBlob::GlyphPositioning)scalarsPerPos, offset, paint, nullptr, 0, nullptr); } -void SkPDFDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkScalar x, SkScalar y, +void SkPDFDevice::drawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint &paint, SkDrawFilter* drawFilter) { for (SkTextBlobRunIterator it(blob); !it.done(); it.next()) { SkPaint runPaint(paint); @@ -1419,25 +1442,24 @@ void SkPDFDevice::drawTextBlob(const SkDraw& draw, const SkTextBlob* blob, SkSca } runPaint.setFlags(this->filterTextFlags(runPaint)); SkPoint offset = it.offset() + SkPoint{x, y}; - this->internalDrawText(draw, it.glyphs(), sizeof(SkGlyphID) * it.glyphCount(), + this->internalDrawText(it.glyphs(), sizeof(SkGlyphID) * it.glyphCount(), it.pos(), it.positioning(), offset, runPaint, it.clusters(), it.textSize(), it.text()); } } -void SkPDFDevice::drawVertices(const SkDraw& d, SkCanvas::VertexMode, +void SkPDFDevice::drawVertices(SkCanvas::VertexMode, int vertexCount, const SkPoint verts[], const SkPoint texs[], const SkColor colors[], SkBlendMode, const uint16_t indices[], int indexCount, const SkPaint& paint) { - if (d.fClipStack->isEmpty(this->getGlobalBounds())) { + if (this->cs().isEmpty(size(*this))) { return; } // TODO: implement drawVertices } -void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, - int x, int y, const SkPaint& paint) { +void SkPDFDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPaint& paint) { SkASSERT(!paint.getImageFilter()); // Check if the source device is really a bitmapdevice (because that's what we returned @@ -1446,7 +1468,7 @@ void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, if (device->peekPixels(&pmap)) { SkBitmap bitmap; bitmap.installPixels(pmap); - this->drawSprite(d, bitmap, x, y, paint); + this->drawSprite(bitmap, x, y, paint); return; } @@ -1472,9 +1494,8 @@ void SkPDFDevice::drawDevice(const SkDraw& d, SkBaseDevice* device, return; } - SkMatrix matrix; - matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); - ScopedContentEntry content(this, d.fClipStack, matrix, paint); + SkMatrix matrix = SkMatrix::MakeTrans(SkIntToScalar(x), SkIntToScalar(y)); + ScopedContentEntry content(this, this->cs(), matrix, paint); if (!content.entry()) { return; } @@ -1530,11 +1551,8 @@ std::unique_ptr<SkStreamAsset> SkPDFDevice::content() const { GraphicStackState gsState(fExistingClipStack, &buffer); for (const auto& entry : fContentEntries) { - SkPoint translation; - translation.iset(this->getOrigin()); - translation.negate(); gsState.updateClip(entry.fState.fClipStack, - translation, SkRect::Make(this->getGlobalBounds())); + {0, 0}, SkRect::Make(size(*this))); gsState.updateMatrix(entry.fState.fMatrix); gsState.updateDrawingState(entry.fState); @@ -1555,14 +1573,14 @@ std::unique_ptr<SkStreamAsset> SkPDFDevice::content() const { * either as a (incorrect) fallback or because the path was not inverse * in the first place. */ -bool SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath, +bool SkPDFDevice::handleInversePath(const SkPath& origPath, const SkPaint& paint, bool pathIsMutable, const SkMatrix* prePathMatrix) { if (!origPath.isInverseFillType()) { return false; } - if (d.fClipStack->isEmpty(this->getGlobalBounds())) { + if (this->cs().isEmpty(size(*this))) { return false; } @@ -1582,7 +1600,7 @@ bool SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath, // To be consistent with the raster output, hairline strokes // are rendered as non-inverted. modifiedPath.toggleInverseFillType(); - drawPath(d, modifiedPath, paint, nullptr, true); + this->drawPath(modifiedPath, paint, nullptr, true); return true; } } @@ -1590,16 +1608,14 @@ bool SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath, // Get bounds of clip in current transform space // (clip bounds are given in device space). SkMatrix transformInverse; - SkMatrix totalMatrix = *d.fMatrix; + SkMatrix totalMatrix = this->ctm(); if (prePathMatrix) { totalMatrix.preConcat(*prePathMatrix); } if (!totalMatrix.invert(&transformInverse)) { return false; } - SkRect bounds = d.fClipStack->bounds(this->getGlobalBounds()); - SkIPoint deviceOrigin = this->getOrigin(); - bounds.offset(-deviceOrigin.x(), -deviceOrigin.y()); + SkRect bounds = this->cs().bounds(size(*this)); transformInverse.mapRect(&bounds); // Extend the bounds by the line width (plus some padding) @@ -1611,48 +1627,10 @@ bool SkPDFDevice::handleInversePath(const SkDraw& d, const SkPath& origPath, return false; } - drawPath(d, modifiedPath, noInversePaint, prePathMatrix, true); + this->drawPath(modifiedPath, noInversePaint, prePathMatrix, true); return true; } -void SkPDFDevice::handlePointAnnotation(const SkPoint& point, - const SkMatrix& matrix, - const char key[], SkData* value) { - SkASSERT(value); - if (!strcmp(SkAnnotationKeys::Define_Named_Dest_Key(), key)) { - SkPoint transformedPoint; - matrix.mapXY(point.x(), point.y(), &transformedPoint); - fNamedDestinations.emplace_back(value, transformedPoint); - } -} - -void SkPDFDevice::handleRectAnnotation(const SkRect& rect, - const SkDraw& d, - const char key[], SkData* value) { - SkASSERT(value); - // Convert to path to handle non-90-degree rotations. - SkPath path; - path.addRect(rect); - path.transform(*d.fMatrix, &path); - SkPath clip; - (void)d.fClipStack->asPath(&clip); - SkIPoint deviceOrigin = this->getOrigin(); - clip.offset(-deviceOrigin.x(), -deviceOrigin.y()); - // Offset here to make clip and path share coordinates. - // We remove the offset in SkPDFDevice::drawDevice(). - Op(clip, path, kIntersect_SkPathOp, &path); - // PDF wants a rectangle only. - SkRect transformedRect = path.getBounds(); - - if (!transformedRect.isEmpty()) { - if (!strcmp(SkAnnotationKeys::URL_Key(), key)) { - fLinkToURLs.emplace_back(transformedRect, value); - } else if (!strcmp(SkAnnotationKeys::Link_Named_Dest_Key(), key)) { - fLinkToDestinations.emplace_back(transformedRect, value); - } - } -} - void SkPDFDevice::appendAnnotations(SkPDFArray* array) const { array->reserve(fLinkToURLs.count() + fLinkToDestinations.count()); for (const RectWithData& rectWithURL : fLinkToURLs) { @@ -1704,10 +1682,10 @@ sk_sp<SkPDFObject> SkPDFDevice::makeFormXObjectFromDevice() { void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, sk_sp<SkPDFObject> mask, - const SkClipStack* clipStack, + const SkClipStack& clipStack, SkBlendMode mode, bool invertClip) { - if (!invertClip && clipStack->isEmpty(this->getGlobalBounds())) { + if (!invertClip && clipStack.isEmpty(size(*this))) { return; } @@ -1715,11 +1693,9 @@ void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, std::move(mask), invertClip, SkPDFGraphicState::kAlpha_SMaskMode, fDocument->canon()); - SkMatrix identity; - identity.reset(); SkPaint paint; paint.setBlendMode(mode); - ScopedContentEntry content(this, clipStack, identity, paint); + ScopedContentEntry content(this, clipStack, SkMatrix::I(), paint); if (!content.entry()) { return; } @@ -1735,13 +1711,12 @@ void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, &content.entry()->fContent); } -SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack, +SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack& clipStack, const SkMatrix& matrix, const SkPaint& paint, bool hasText, sk_sp<SkPDFObject>* dst) { *dst = nullptr; - SkASSERT(clipStack); SkBlendMode blendMode = paint.getBlendMode(); // For the following modes, we want to handle source and destination @@ -1781,7 +1756,7 @@ SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* cli } else { entry = fContentEntries.emplace_front(); } - populateGraphicStateEntryFromPaint(matrix, *clipStack, paint, hasText, &entry->fState); + populateGraphicStateEntryFromPaint(matrix, clipStack, paint, hasText, &entry->fState); return entry; } @@ -1826,8 +1801,6 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, SkClipStack clipStack = fContentEntries.front()->fState.fClipStack; - SkMatrix identity; - identity.reset(); SkPaint stockPaint; sk_sp<SkPDFObject> srcFormXObject; @@ -1839,7 +1812,7 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, // reduces to Dst. if (shape == nullptr || blendMode == SkBlendMode::kDstOut || blendMode == SkBlendMode::kSrcATop) { - ScopedContentEntry content(this, &fExistingClipStack, identity, stockPaint); + ScopedContentEntry content(this, fExistingClipStack, SkMatrix::I(), stockPaint); // TODO: addXObjectResource take sk_sp SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()), &content.entry()->fContent); @@ -1860,28 +1833,23 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, // the non-transparent parts of the device and the outlines (shape) of // all images and devices drawn. drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, - &fExistingClipStack, SkBlendMode::kSrcOver, true); + fExistingClipStack, SkBlendMode::kSrcOver, true); } else { if (shape != nullptr) { // Draw shape into a form-xobject. - SkRasterClip rc; - SkDraw d; - d.fMatrix = &identity; - d.fRC = &rc; - d.fClipStack = &clipStack; SkPaint filledPaint; filledPaint.setColor(SK_ColorBLACK); filledPaint.setStyle(SkPaint::kFill_Style); - this->drawPath(d, *shape, filledPaint, nullptr, true); - drawFormXObjectWithMask(addXObjectResource(dst.get()), - this->makeFormXObjectFromDevice(), - &fExistingClipStack, - SkBlendMode::kSrcOver, true); - + this->internalDrawPath(clipStack, SkMatrix::I(), *shape, filledPaint, nullptr, true); + this->drawFormXObjectWithMask(this->addXObjectResource(dst.get()), + this->makeFormXObjectFromDevice(), + fExistingClipStack, + SkBlendMode::kSrcOver, true); } else { - drawFormXObjectWithMask(addXObjectResource(dst.get()), srcFormXObject, - &fExistingClipStack, - SkBlendMode::kSrcOver, true); + this->drawFormXObjectWithMask(this->addXObjectResource(dst.get()), + srcFormXObject, + fExistingClipStack, + SkBlendMode::kSrcOver, true); } } @@ -1889,7 +1857,7 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, return; } else if (blendMode == SkBlendMode::kSrc || blendMode == SkBlendMode::kDstATop) { - ScopedContentEntry content(this, &fExistingClipStack, identity, stockPaint); + ScopedContentEntry content(this, fExistingClipStack, SkMatrix::I(), stockPaint); if (content.entry()) { SkPDFUtils::DrawFormXObject( this->addXObjectResource(srcFormXObject.get()), @@ -1899,8 +1867,8 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, return; } } else if (blendMode == SkBlendMode::kSrcATop) { - ScopedContentEntry content(this, &fExistingClipStack, - identity, stockPaint); + ScopedContentEntry content(this, fExistingClipStack, + SkMatrix::I(), stockPaint); if (content.entry()) { SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()), &content.entry()->fContent); @@ -1920,7 +1888,7 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, blendMode == SkBlendMode::kSrcATop) { drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), std::move(dst), - &fExistingClipStack, + fExistingClipStack, SkBlendMode::kSrcOver, blendMode == SkBlendMode::kSrcOut); return; @@ -1929,12 +1897,12 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, int resourceID = addXObjectResource(dst.get()); if (blendMode == SkBlendMode::kModulate) { drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), - std::move(dst), &fExistingClipStack, + std::move(dst), fExistingClipStack, SkBlendMode::kSrcOver, false); mode = SkBlendMode::kMultiply; } drawFormXObjectWithMask(resourceID, std::move(srcFormXObject), - &fExistingClipStack, mode, + fExistingClipStack, mode, blendMode == SkBlendMode::kDstOut); return; } @@ -1986,9 +1954,7 @@ void SkPDFDevice::populateGraphicStateEntryFromPaint( // PDF doesn't support kClamp_TileMode, so we simulate it by making // a pattern the size of the current clip. - SkRect clipStackBounds = clipStack.bounds(this->getGlobalBounds()); - SkIPoint deviceOrigin = this->getOrigin(); - clipStackBounds.offset(-deviceOrigin.x(), -deviceOrigin.y()); + SkRect clipStackBounds = clipStack.bounds(size(*this)); // We need to apply the initial transform to bounds in order to get // bounds in a consistent coordinate system. @@ -2095,7 +2061,7 @@ static sk_sp<SkImage> color_filter(const SkImageSubset& imageSubset, //////////////////////////////////////////////////////////////////////////////// void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix, - const SkClipStack* clipStack, + const SkClipStack& clipStack, SkImageSubset imageSubset, const SkPaint& paint) { if (imageSubset.dimensions().isZero()) { @@ -2237,8 +2203,8 @@ void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix, #include "SkSpecialImage.h" #include "SkImageFilter.h" -void SkPDFDevice::drawSpecial(const SkDraw& draw, SkSpecialImage* srcImg, int x, int y, - const SkPaint& paint) { +void SkPDFDevice::drawSpecial(SkSpecialImage* srcImg, int x, int y, + const SkPaint& paint) { SkASSERT(!srcImg->isTextureBacked()); SkBitmap resultBM; @@ -2246,10 +2212,10 @@ void SkPDFDevice::drawSpecial(const SkDraw& draw, SkSpecialImage* srcImg, int x, SkImageFilter* filter = paint.getImageFilter(); if (filter) { SkIPoint offset = SkIPoint::Make(0, 0); - SkMatrix matrix = *draw.fMatrix; + SkMatrix matrix = this->ctm(); matrix.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); const SkIRect clipBounds = - draw.fClipStack->bounds(this->imageInfo().bounds()).roundOut().makeOffset(-x, -y); + this->cs().bounds(this->imageInfo().bounds()).roundOut().makeOffset(-x, -y); sk_sp<SkImageFilterCache> cache(this->getImageFilterCache()); // TODO: Should PDF be operating in a specified color space? For now, run the filter // in the same color space as the source (this is different from all other backends). @@ -2261,12 +2227,12 @@ void SkPDFDevice::drawSpecial(const SkDraw& draw, SkSpecialImage* srcImg, int x, SkPaint tmpUnfiltered(paint); tmpUnfiltered.setImageFilter(nullptr); if (resultImg->getROPixels(&resultBM)) { - this->drawSprite(draw, resultBM, x + offset.x(), y + offset.y(), tmpUnfiltered); + this->drawSprite(resultBM, x + offset.x(), y + offset.y(), tmpUnfiltered); } } } else { if (srcImg->getROPixels(&resultBM)) { - this->drawSprite(draw, resultBM, x, y, paint); + this->drawSprite(resultBM, x, y, paint); } } } |