aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'src/pdf')
-rw-r--r--src/pdf/SkPDFDevice.cpp57
1 files changed, 55 insertions, 2 deletions
diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp
index 3125904797..bbc09f7ed6 100644
--- a/src/pdf/SkPDFDevice.cpp
+++ b/src/pdf/SkPDFDevice.cpp
@@ -87,6 +87,17 @@ sk_sp<SkImage> mask_to_greyscale_image(SkMask* mask) {
return img;
}
+sk_sp<SkImage> alpha_image_to_greyscale_image(const SkImage* mask) {
+ int w = mask->width(), h = mask->height();
+ SkBitmap greyBitmap;
+ greyBitmap.allocPixels(SkImageInfo::Make(w, h, kGray_8_SkColorType, kOpaque_SkAlphaType));
+ if (!mask->readPixels(SkImageInfo::MakeA8(w, h),
+ greyBitmap.getPixels(), greyBitmap.rowBytes(), 0, 0)) {
+ return nullptr;
+ }
+ return SkImage::MakeFromBitmap(greyBitmap);
+}
+
static void draw_points(SkCanvas::PointMode mode,
size_t count,
const SkPoint* points,
@@ -613,8 +624,7 @@ void SkPDFDevice::internalDrawPaint(const SkPaint& paint,
if (!contentEntry) {
return;
}
- SkRect bbox = SkRect::MakeWH(SkIntToScalar(this->width()),
- SkIntToScalar(this->height()));
+ SkRect bbox = SkRect::Make(fPageSize);
SkMatrix inverse;
if (!contentEntry->fState.fMatrix.invert(&inverse)) {
return;
@@ -2201,6 +2211,49 @@ void SkPDFDevice::internalDrawImageRect(SkKeyedImage imageSubset,
}
}
+ // TODO(halcanary) support isAlphaOnly & getMaskFilter.
+ bool imageAlphaOnly = imageSubset.image()->isAlphaOnly() && !paint.getMaskFilter();
+ if (imageAlphaOnly) {
+ if (SkColorFilter* colorFilter = paint.getColorFilter()) {
+ sk_sp<SkImage> img = color_filter(imageSubset.image().get(), colorFilter);
+ paint.setColorFilter(nullptr);
+ imageSubset = SkKeyedImage(std::move(img));
+ if (!imageSubset) {
+ return;
+ }
+ imageAlphaOnly = imageSubset.image()->isAlphaOnly();
+ // The colorfilter can make a alphonly image no longer be alphaonly.
+ }
+ }
+ if (imageAlphaOnly) {
+ sk_sp<SkImage> mask = alpha_image_to_greyscale_image(imageSubset.image().get());
+ if (!mask) {
+ return;
+ }
+ // PDF doesn't seem to allow masking vector graphics with an Image XObject.
+ // Must mask with a Form XObject.
+ sk_sp<SkPDFDevice> maskDevice = this->makeCongruentDevice();
+ {
+ SkCanvas canvas(maskDevice.get());
+ canvas.concat(transform);
+ canvas.concat(ctm);
+ // TODO(halcanary): investigate sub-pixel clipping.
+ canvas.drawImage(mask, 0, 0);
+ }
+ remove_color_filter(&paint);
+ if (!ctm.isIdentity() && paint.getShader()) {
+ transform_shader(&paint, ctm); // Since we are using identity matrix.
+ }
+ ScopedContentEntry content(this, this->cs(), SkMatrix::I(), paint);
+ if (!content.entry()) {
+ return;
+ }
+ this->addSMaskGraphicState(std::move(maskDevice), content.stream());
+ SkPDFUtils::AppendRectangle(SkRect::Make(fPageSize), content.stream());
+ SkPDFUtils::PaintPath(SkPaint::kFill_Style, SkPath::kWinding_FillType, content.stream());
+ this->clearMaskOnGraphicState(content.stream());
+ return;
+ }
if (paint.getMaskFilter()) {
paint.setShader(imageSubset.image()->makeShader(&transform));
SkPath path;