aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Hal Canary <halcanary@google.com>2017-06-27 14:28:37 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-27 19:56:43 +0000
commit51329c944c3021d8eb594fcb79989e6a25545c67 (patch)
tree1b86e3184a6fac928bc3dc4b08fd1e6a8838c405 /src
parent0bb0411f59aff6362cedcd90b6ca272c53e19c4c (diff)
SkPDF: clean up PDFDevice.
Motivation: factor out some code for later re-use; clean up. - mask_to_greyscale_image() - addSMaskGraphicState() - clearMaskOnGraphicState() - stop using bare pointer to indicate ownership. - add ScopedContentEntry::stream() Change-Id: I7abe7ff9eab89e1002692017000cda2ca7642631 Reviewed-on: https://skia-review.googlesource.com/20978 Reviewed-by: Ben Wagner <bungeman@google.com> Commit-Queue: Hal Canary <halcanary@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/pdf/SkPDFDevice.cpp149
-rw-r--r--src/pdf/SkPDFDevice.h26
-rw-r--r--src/pdf/SkPDFDocument.cpp3
-rw-r--r--src/pdf/SkPDFShader.cpp3
4 files changed, 87 insertions, 94 deletions
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index c3ff976132..f559e9081e 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -62,6 +62,33 @@
// Utility functions
+// This function destroys the mask and either frees or takes the pixels.
+sk_sp<SkImage> mask_to_greyscale_image(SkMask* mask) {
+ sk_sp<SkImage> img;
+ SkPixmap pm(SkImageInfo::Make(mask->fBounds.width(), mask->fBounds.height(),
+ kGray_8_SkColorType, kOpaque_SkAlphaType),
+ mask->fImage, mask->fRowBytes);
+ const int imgQuality = SK_PDF_MASK_QUALITY;
+ if (imgQuality <= 100 && imgQuality >= 0) {
+ SkDynamicMemoryWStream buffer;
+ SkJpegEncoder::Options jpegOptions;
+ jpegOptions.fQuality = imgQuality;
+ if (SkJpegEncoder::Encode(&buffer, pm, jpegOptions)) {
+ img = SkImage::MakeFromEncoded(buffer.detachAsData());
+ SkASSERT(img);
+ if (img) {
+ SkMask::FreeImage(mask->fImage);
+ }
+ }
+ }
+ if (!img) {
+ img = SkImage::MakeFromRaster(pm, [](const void* p, void*) { SkMask::FreeImage((void*)p); },
+ nullptr);
+ }
+ *mask = SkMask(); // destructive;
+ return img;
+}
+
static void draw_points(SkCanvas::PointMode mode,
size_t count,
const SkPoint* points,
@@ -433,7 +460,7 @@ SkBaseDevice* SkPDFDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint
return SkBitmapDevice::Create(cinfo.fInfo, SkSurfaceProps(0, kUnknown_SkPixelGeometry));
}
SkISize size = SkISize::Make(cinfo.fInfo.width(), cinfo.fInfo.height());
- return SkPDFDevice::Create(size, fRasterDpi, fDocument);
+ return SkPDFDevice::Make(size, fRasterDpi, fDocument).release();
}
SkPDFCanon* SkPDFDevice::getCanon() const { return fDocument->canon(); }
@@ -476,6 +503,7 @@ public:
}
SkPDFDevice::ContentEntry* entry() { return fContentEntry; }
+ SkDynamicMemoryWStream* stream() { return &fContentEntry->fContent; }
/* Returns true when we explicitly need the shape of the drawing. */
bool needShape() {
@@ -675,34 +703,28 @@ void SkPDFDevice::drawPoints(SkCanvas::PointMode mode,
if (!content.entry()) {
return;
}
-
+ SkDynamicMemoryWStream* contentStream = content.stream();
switch (mode) {
case SkCanvas::kPolygon_PointMode:
- SkPDFUtils::MoveTo(points[0].fX, points[0].fY,
- &content.entry()->fContent);
+ SkPDFUtils::MoveTo(points[0].fX, points[0].fY, contentStream);
for (size_t i = 1; i < count; i++) {
- SkPDFUtils::AppendLine(points[i].fX, points[i].fY,
- &content.entry()->fContent);
+ SkPDFUtils::AppendLine(points[i].fX, points[i].fY, contentStream);
}
- SkPDFUtils::StrokePath(&content.entry()->fContent);
+ SkPDFUtils::StrokePath(contentStream);
break;
case SkCanvas::kLines_PointMode:
for (size_t i = 0; i < count/2; i++) {
- SkPDFUtils::MoveTo(points[i * 2].fX, points[i * 2].fY,
- &content.entry()->fContent);
- SkPDFUtils::AppendLine(points[i * 2 + 1].fX,
- points[i * 2 + 1].fY,
- &content.entry()->fContent);
- SkPDFUtils::StrokePath(&content.entry()->fContent);
+ SkPDFUtils::MoveTo(points[i * 2].fX, points[i * 2].fY, contentStream);
+ SkPDFUtils::AppendLine(points[i * 2 + 1].fX, points[i * 2 + 1].fY, contentStream);
+ SkPDFUtils::StrokePath(contentStream);
}
break;
case SkCanvas::kPoints_PointMode:
SkASSERT(paint->getStrokeCap() == SkPaint::kRound_Cap);
for (size_t i = 0; i < count; i++) {
- SkPDFUtils::MoveTo(points[i].fX, points[i].fY,
- &content.entry()->fContent);
- SkPDFUtils::ClosePath(&content.entry()->fContent);
- SkPDFUtils::StrokePath(&content.entry()->fContent);
+ SkPDFUtils::MoveTo(points[i].fX, points[i].fY, contentStream);
+ SkPDFUtils::ClosePath(contentStream);
+ SkPDFUtils::StrokePath(contentStream);
}
break;
default:
@@ -775,9 +797,8 @@ void SkPDFDevice::drawRect(const SkRect& rect,
if (!content.entry()) {
return;
}
- SkPDFUtils::AppendRectangle(r, &content.entry()->fContent);
- SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
- &content.entry()->fContent);
+ SkPDFUtils::AppendRectangle(r, content.stream());
+ SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, content.stream());
}
void SkPDFDevice::drawRRect(const SkRRect& rrect,
@@ -840,38 +861,15 @@ void SkPDFDevice::internalDrawPathWithFilter(const SkClipStack& clipStack,
if (!paint->getMaskFilter()->filterMask(&dstMask, sourceMask, ctm, &margin)) {
return;
}
- SkPixmap pm(SkImageInfo::Make(dstMask.fBounds.width(), dstMask.fBounds.height(),
- kGray_8_SkColorType, kOpaque_SkAlphaType),
- dstMask.fImage, dstMask.fRowBytes);
- sk_sp<SkImage> mask;
- const int maskQuality = SK_PDF_MASK_QUALITY;
- if (maskQuality <= 100 && maskQuality >= 0) {
- SkDynamicMemoryWStream buffer;
- SkJpegEncoder::Options jpegOptions;
- jpegOptions.fQuality = maskQuality;
- if (SkJpegEncoder::Encode(&buffer, pm, jpegOptions)) {
- mask = SkImage::MakeFromEncoded(buffer.detachAsData());
- SkASSERT(mask);
- if (mask) {
- SkMask::FreeImage(dstMask.fImage);
- }
- }
- }
- if (!mask) {
- mask = SkImage::MakeFromRaster(
- pm, [](const void* p, void*) { SkMask::FreeImage((void*)p); }, nullptr);
- }
+ SkIRect dstMaskBounds = dstMask.fBounds;
+ sk_sp<SkImage> mask = mask_to_greyscale_image(&dstMask);
// PDF doesn't seem to allow masking vector graphics with an Image XObject.
// Must mask with a Form XObject.
- sk_sp<SkPDFDevice> maskDevice(SkPDFDevice::CreateUnflipped(fPageSize, fRasterDpi, fDocument));
+ sk_sp<SkPDFDevice> maskDevice = this->makeCongruentDevice();
{
SkPDFCanvas canvas(maskDevice);
- canvas.drawImage(mask, dstMask.fBounds.x(), dstMask.fBounds.y());
+ canvas.drawImage(mask, dstMaskBounds.x(), dstMaskBounds.y());
}
- sk_sp<SkPDFDict> sMaskGS = SkPDFGraphicState::GetSMaskGraphicState(
- maskDevice->makeFormXObjectFromDevice(), false,
- SkPDFGraphicState::kLuminosity_SMaskMode, fDocument->canon());
- maskDevice = nullptr;
if (!ctm.isIdentity() && paint->getShader()) {
transform_shader(paint.writable(), ctm); // Since we are using identity matrix.
}
@@ -879,18 +877,25 @@ void SkPDFDevice::internalDrawPathWithFilter(const SkClipStack& clipStack,
if (!content.entry()) {
return;
}
- SkPDFUtils::ApplyGraphicState(this->addGraphicStateResource(sMaskGS.get()),
- &content.entry()->fContent);
+ this->addSMaskGraphicState(std::move(maskDevice), content.stream());
+ SkPDFUtils::AppendRectangle(SkRect::Make(dstMaskBounds), content.stream());
+ SkPDFUtils::PaintPath(SkPaint::kFill_Style, path.getFillType(), content.stream());
+ this->clearMaskOnGraphicState(content.stream());
+}
- SkRect dstBounds = SkRect::Make(dstMask.fBounds);
- SkPDFUtils::AppendRectangle(dstBounds, &content.entry()->fContent);
- SkPDFUtils::PaintPath(SkPaint::kFill_Style, path.getFillType(), &content.entry()->fContent);
+void SkPDFDevice::addSMaskGraphicState(sk_sp<SkPDFDevice> maskDevice,
+ SkDynamicMemoryWStream* contentStream) {
+ sk_sp<SkPDFDict> sMaskGS = SkPDFGraphicState::GetSMaskGraphicState(
+ maskDevice->makeFormXObjectFromDevice(), false,
+ SkPDFGraphicState::kLuminosity_SMaskMode, this->getCanon());
+ SkPDFUtils::ApplyGraphicState(this->addGraphicStateResource(sMaskGS.get()), contentStream);
+}
+void SkPDFDevice::clearMaskOnGraphicState(SkDynamicMemoryWStream* contentStream) {
// The no-softmask graphic state is used to "turn off" the mask for later draw calls.
- auto noSMaskGS = SkPDFUtils::GetCachedT(&fDocument->canon()->fNoSmaskGraphicState,
+ auto noSMaskGS = SkPDFUtils::GetCachedT(&this->getCanon()->fNoSmaskGraphicState,
&SkPDFGraphicState::MakeNoSmaskGraphicState);
- SkPDFUtils::ApplyGraphicState(this->addGraphicStateResource(noSMaskGS.get()),
- &content.entry()->fContent);
+ SkPDFUtils::ApplyGraphicState(this->addGraphicStateResource(noSMaskGS.get()), contentStream);
}
void SkPDFDevice::internalDrawPath(const SkClipStack& clipStack,
@@ -967,12 +972,9 @@ void SkPDFDevice::internalDrawPath(const SkClipStack& clipStack,
paint.getStyle() == SkPaint::kFill_Style ||
(paint.getStrokeCap() != SkPaint::kRound_Cap &&
paint.getStrokeCap() != SkPaint::kSquare_Cap);
- SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(),
- consumeDegeratePathSegments,
- &content.entry()->fContent,
+ SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(), consumeDegeratePathSegments, content.stream(),
tolerance);
- SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
- &content.entry()->fContent);
+ SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(), content.stream());
}
@@ -1537,7 +1539,7 @@ void SkPDFDevice::internalDrawText(
if (!content.entry()) {
return;
}
- SkDynamicMemoryWStream* out = &content.entry()->fContent;
+ SkDynamicMemoryWStream* out = content.stream();
const SkTDArray<SkUnichar>& glyphToUnicode = metrics->fGlyphToUnicode;
out->writeText("BT\n");
@@ -1732,8 +1734,7 @@ void SkPDFDevice::drawDevice(SkBaseDevice* device, int x, int y, const SkPaint&
}
sk_sp<SkPDFObject> xObject = pdfDevice->makeFormXObjectFromDevice();
- SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()),
- &content.entry()->fContent);
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(xObject.get()), content.stream());
}
sk_sp<SkSurface> SkPDFDevice::makeSurface(const SkImageInfo& info, const SkSurfaceProps& props) {
@@ -1920,14 +1921,12 @@ void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex,
if (!content.entry()) {
return;
}
- SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
- &content.entry()->fContent);
- SkPDFUtils::DrawFormXObject(xObjectIndex, &content.entry()->fContent);
+ SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), content.stream());
+ SkPDFUtils::DrawFormXObject(xObjectIndex, content.stream());
sMaskGS = SkPDFUtils::GetCachedT(&fDocument->canon()->fNoSmaskGraphicState,
&SkPDFGraphicState::MakeNoSmaskGraphicState);
- SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()),
- &content.entry()->fContent);
+ SkPDFUtils::ApplyGraphicState(addGraphicStateResource(sMaskGS.get()), content.stream());
}
SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack& clipStack,
@@ -2033,8 +2032,7 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode,
blendMode == SkBlendMode::kSrcATop) {
ScopedContentEntry content(this, fExistingClipStack, SkMatrix::I(), stockPaint);
// TODO: addXObjectResource take sk_sp
- SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()),
- &content.entry()->fContent);
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()), content.stream());
return;
} else {
blendMode = SkBlendMode::kClear;
@@ -2078,9 +2076,8 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode,
blendMode == SkBlendMode::kDstATop) {
ScopedContentEntry content(this, fExistingClipStack, SkMatrix::I(), stockPaint);
if (content.entry()) {
- SkPDFUtils::DrawFormXObject(
- this->addXObjectResource(srcFormXObject.get()),
- &content.entry()->fContent);
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(srcFormXObject.get()),
+ content.stream());
}
if (blendMode == SkBlendMode::kSrc) {
return;
@@ -2089,8 +2086,7 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode,
ScopedContentEntry content(this, fExistingClipStack,
SkMatrix::I(), stockPaint);
if (content.entry()) {
- SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()),
- &content.entry()->fContent);
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst.get()), content.stream());
}
}
@@ -2409,8 +2405,7 @@ void SkPDFDevice::internalDrawImage(const SkMatrix& origMatrix,
fDocument->canon()->fPDFBitmapMap.set(key, pdfimage);
}
// TODO(halcanary): addXObjectResource() should take a sk_sp<SkPDFObject>
- SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()),
- &content.entry()->fContent);
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), content.stream());
}
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h
index e409ed9bb2..ad44bcd12d 100644
--- a/src/pdf/SkPDFDevice.h
+++ b/src/pdf/SkPDFDevice.h
@@ -59,17 +59,19 @@ public:
* for early serializing of large immutable objects, such
* as images (via SkPDFDocument::serialize()).
*/
- static SkPDFDevice* Create(SkISize pageSize,
- SkScalar rasterDpi,
- SkPDFDocument* doc) {
- return new SkPDFDevice(pageSize, rasterDpi, doc, true);
+ static sk_sp<SkPDFDevice> Make(SkISize pageSize, SkScalar rasterDpi, SkPDFDocument* doc) {
+ return sk_sp<SkPDFDevice>(new SkPDFDevice(pageSize, rasterDpi, doc, true));
}
/** Create a PDF drawing context without fipping the y-axis. */
- static SkPDFDevice* CreateUnflipped(SkISize pageSize,
- SkScalar rasterDpi,
- SkPDFDocument* doc) {
- return new SkPDFDevice(pageSize, rasterDpi, doc, false);
+ static sk_sp<SkPDFDevice> MakeUnflipped(SkISize pageSize,
+ SkScalar rasterDpi,
+ SkPDFDocument* doc) {
+ return sk_sp<SkPDFDevice>(new SkPDFDevice(pageSize, rasterDpi, doc, false));
+ }
+
+ sk_sp<SkPDFDevice> makeCongruentDevice() {
+ return sk_sp<SkPDFDevice>(new SkPDFDevice(fPageSize, fRasterDpi, fDocument, false));
}
~SkPDFDevice() override;
@@ -283,12 +285,10 @@ private:
const SkPaint& paint, bool pathIsMutable,
const SkMatrix* prePathMatrix = nullptr);
- typedef SkClipStackDevice INHERITED;
+ void addSMaskGraphicState(sk_sp<SkPDFDevice> maskDevice, SkDynamicMemoryWStream*);
+ void clearMaskOnGraphicState(SkDynamicMemoryWStream*);
- // TODO(edisonn): Only SkDocument_PDF and SkPDFImageShader should be able to create
- // an SkPDFDevice
- //friend class SkDocument_PDF;
- //friend class SkPDFImageShader;
+ typedef SkClipStackDevice INHERITED;
};
#endif
diff --git a/src/pdf/SkPDFDocument.cpp b/src/pdf/SkPDFDocument.cpp
index 931ce9917d..774d023db6 100644
--- a/src/pdf/SkPDFDocument.cpp
+++ b/src/pdf/SkPDFDocument.cpp
@@ -215,8 +215,7 @@ SkCanvas* SkPDFDocument::onBeginPage(SkScalar width, SkScalar height,
}
SkISize pageSize = SkISize::Make(
SkScalarRoundToInt(width), SkScalarRoundToInt(height));
- fPageDevice.reset(
- SkPDFDevice::Create(pageSize, fRasterDpi, this));
+ fPageDevice = SkPDFDevice::Make(pageSize, fRasterDpi, this);
fCanvas.reset(new SkPDFCanvas(fPageDevice));
if (SkRect::MakeWH(width, height) != trimBox) {
fCanvas->clipRect(trimBox);
diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp
index 49af685d7a..9cf40d42e6 100644
--- a/src/pdf/SkPDFShader.cpp
+++ b/src/pdf/SkPDFShader.cpp
@@ -991,8 +991,7 @@ static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc,
SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()),
SkScalarRoundToInt(deviceBounds.height()));
- sk_sp<SkPDFDevice> patternDevice(
- SkPDFDevice::CreateUnflipped(size, dpi, doc));
+ sk_sp<SkPDFDevice> patternDevice = SkPDFDevice::MakeUnflipped(size, dpi, doc);
SkCanvas canvas(patternDevice.get());
SkRect patternBBox;