SkPDF: SkPDFMakeShader takes the paint color.
This allows alpha blending and also alpha shaders with color blended in. fixes GMs: composeshader_alpha, composeshader_bitmap Change-Id: I3ab9cbef216f7733798d2e29541b4211c627dab2 Reviewed-on: https://skia-review.googlesource.com/24760 Commit-Queue: Hal Canary <halcanary@google.com> Reviewed-by: Ben Wagner <bungeman@google.com>
This commit is contained in:
parent
b7648a2758
commit
7e872caaf6
@ -216,8 +216,8 @@ struct PDFShaderBench : public Benchmark {
|
|||||||
SkNullWStream nullStream;
|
SkNullWStream nullStream;
|
||||||
SkPDFDocument doc(&nullStream, nullptr, 72,
|
SkPDFDocument doc(&nullStream, nullptr, 72,
|
||||||
SkDocument::PDFMetadata(), nullptr, false);
|
SkDocument::PDFMetadata(), nullptr, false);
|
||||||
sk_sp<SkPDFObject> shader =
|
sk_sp<SkPDFObject> shader = SkPDFMakeShader(&doc, fShader.get(), SkMatrix::I(),
|
||||||
SkPDFMakeShader(&doc, fShader.get(), SkMatrix::I(), {0, 0, 400,400});
|
{0, 0, 400, 400}, SK_ColorBLACK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2180,7 +2180,7 @@ void SkPDFDevice::populateGraphicStateEntryFromPaint(
|
|||||||
SkIRect bounds;
|
SkIRect bounds;
|
||||||
clipStackBounds.roundOut(&bounds);
|
clipStackBounds.roundOut(&bounds);
|
||||||
|
|
||||||
pdfShader = SkPDFMakeShader(fDocument, shader, transform, bounds);
|
pdfShader = SkPDFMakeShader(fDocument, shader, transform, bounds, paint.getColor());
|
||||||
|
|
||||||
if (pdfShader.get()) {
|
if (pdfShader.get()) {
|
||||||
// pdfShader has been canonicalized so we can directly compare
|
// pdfShader has been canonicalized so we can directly compare
|
||||||
|
@ -19,19 +19,22 @@
|
|||||||
#include "SkPDFUtils.h"
|
#include "SkPDFUtils.h"
|
||||||
#include "SkScalar.h"
|
#include "SkScalar.h"
|
||||||
#include "SkStream.h"
|
#include "SkStream.h"
|
||||||
|
#include "SkSurface.h"
|
||||||
#include "SkTemplates.h"
|
#include "SkTemplates.h"
|
||||||
|
|
||||||
|
|
||||||
static void draw_image_matrix(SkCanvas* canvas, const SkImage* img, const SkMatrix& matrix) {
|
static void draw_image_matrix(SkCanvas* canvas, const SkImage* img,
|
||||||
|
const SkMatrix& matrix, const SkPaint& paint) {
|
||||||
SkAutoCanvasRestore acr(canvas, true);
|
SkAutoCanvasRestore acr(canvas, true);
|
||||||
canvas->concat(matrix);
|
canvas->concat(matrix);
|
||||||
canvas->drawImage(img, 0, 0);
|
canvas->drawImage(img, 0, 0, &paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void draw_bitmap_matrix(SkCanvas* canvas, const SkBitmap& bm, const SkMatrix& matrix) {
|
static void draw_bitmap_matrix(SkCanvas* canvas, const SkBitmap& bm,
|
||||||
|
const SkMatrix& matrix, const SkPaint& paint) {
|
||||||
SkAutoCanvasRestore acr(canvas, true);
|
SkAutoCanvasRestore acr(canvas, true);
|
||||||
canvas->concat(matrix);
|
canvas->concat(matrix);
|
||||||
canvas->drawBitmap(bm, 0, 0);
|
canvas->drawBitmap(bm, 0, 0, &paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc,
|
static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc,
|
||||||
@ -87,19 +90,21 @@ static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc,
|
|||||||
SkScalar width = SkIntToScalar(image->width());
|
SkScalar width = SkIntToScalar(image->width());
|
||||||
SkScalar height = SkIntToScalar(image->height());
|
SkScalar height = SkIntToScalar(image->height());
|
||||||
|
|
||||||
|
SkPaint paint;
|
||||||
|
paint.setColor(key.fPaintColor);
|
||||||
// Tiling is implied. First we handle mirroring.
|
// Tiling is implied. First we handle mirroring.
|
||||||
if (tileModes[0] == SkShader::kMirror_TileMode) {
|
if (tileModes[0] == SkShader::kMirror_TileMode) {
|
||||||
SkMatrix xMirror;
|
SkMatrix xMirror;
|
||||||
xMirror.setScale(-1, 1);
|
xMirror.setScale(-1, 1);
|
||||||
xMirror.postTranslate(2 * width, 0);
|
xMirror.postTranslate(2 * width, 0);
|
||||||
draw_image_matrix(&canvas, image, xMirror);
|
draw_image_matrix(&canvas, image, xMirror, paint);
|
||||||
patternBBox.fRight += width;
|
patternBBox.fRight += width;
|
||||||
}
|
}
|
||||||
if (tileModes[1] == SkShader::kMirror_TileMode) {
|
if (tileModes[1] == SkShader::kMirror_TileMode) {
|
||||||
SkMatrix yMirror;
|
SkMatrix yMirror;
|
||||||
yMirror.setScale(SK_Scalar1, -SK_Scalar1);
|
yMirror.setScale(SK_Scalar1, -SK_Scalar1);
|
||||||
yMirror.postTranslate(0, 2 * height);
|
yMirror.postTranslate(0, 2 * height);
|
||||||
draw_image_matrix(&canvas, image, yMirror);
|
draw_image_matrix(&canvas, image, yMirror, paint);
|
||||||
patternBBox.fBottom += height;
|
patternBBox.fBottom += height;
|
||||||
}
|
}
|
||||||
if (tileModes[0] == SkShader::kMirror_TileMode &&
|
if (tileModes[0] == SkShader::kMirror_TileMode &&
|
||||||
@ -107,7 +112,7 @@ static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc,
|
|||||||
SkMatrix mirror;
|
SkMatrix mirror;
|
||||||
mirror.setScale(-1, -1);
|
mirror.setScale(-1, -1);
|
||||||
mirror.postTranslate(2 * width, 2 * height);
|
mirror.postTranslate(2 * width, 2 * height);
|
||||||
draw_image_matrix(&canvas, image, mirror);
|
draw_image_matrix(&canvas, image, mirror, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then handle Clamping, which requires expanding the pattern canvas to
|
// Then handle Clamping, which requires expanding the pattern canvas to
|
||||||
@ -171,12 +176,12 @@ static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc,
|
|||||||
SkMatrix leftMatrix;
|
SkMatrix leftMatrix;
|
||||||
leftMatrix.setScale(-deviceBounds.left(), 1);
|
leftMatrix.setScale(-deviceBounds.left(), 1);
|
||||||
leftMatrix.postTranslate(deviceBounds.left(), 0);
|
leftMatrix.postTranslate(deviceBounds.left(), 0);
|
||||||
draw_bitmap_matrix(&canvas, left, leftMatrix);
|
draw_bitmap_matrix(&canvas, left, leftMatrix, paint);
|
||||||
|
|
||||||
if (tileModes[1] == SkShader::kMirror_TileMode) {
|
if (tileModes[1] == SkShader::kMirror_TileMode) {
|
||||||
leftMatrix.postScale(SK_Scalar1, -SK_Scalar1);
|
leftMatrix.postScale(SK_Scalar1, -SK_Scalar1);
|
||||||
leftMatrix.postTranslate(0, 2 * height);
|
leftMatrix.postTranslate(0, 2 * height);
|
||||||
draw_bitmap_matrix(&canvas, left, leftMatrix);
|
draw_bitmap_matrix(&canvas, left, leftMatrix, paint);
|
||||||
}
|
}
|
||||||
patternBBox.fLeft = 0;
|
patternBBox.fLeft = 0;
|
||||||
}
|
}
|
||||||
@ -189,12 +194,12 @@ static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc,
|
|||||||
SkMatrix rightMatrix;
|
SkMatrix rightMatrix;
|
||||||
rightMatrix.setScale(deviceBounds.right() - width, 1);
|
rightMatrix.setScale(deviceBounds.right() - width, 1);
|
||||||
rightMatrix.postTranslate(width, 0);
|
rightMatrix.postTranslate(width, 0);
|
||||||
draw_bitmap_matrix(&canvas, right, rightMatrix);
|
draw_bitmap_matrix(&canvas, right, rightMatrix, paint);
|
||||||
|
|
||||||
if (tileModes[1] == SkShader::kMirror_TileMode) {
|
if (tileModes[1] == SkShader::kMirror_TileMode) {
|
||||||
rightMatrix.postScale(SK_Scalar1, -SK_Scalar1);
|
rightMatrix.postScale(SK_Scalar1, -SK_Scalar1);
|
||||||
rightMatrix.postTranslate(0, 2 * height);
|
rightMatrix.postTranslate(0, 2 * height);
|
||||||
draw_bitmap_matrix(&canvas, right, rightMatrix);
|
draw_bitmap_matrix(&canvas, right, rightMatrix, paint);
|
||||||
}
|
}
|
||||||
patternBBox.fRight = deviceBounds.width();
|
patternBBox.fRight = deviceBounds.width();
|
||||||
}
|
}
|
||||||
@ -210,12 +215,12 @@ static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc,
|
|||||||
SkMatrix topMatrix;
|
SkMatrix topMatrix;
|
||||||
topMatrix.setScale(SK_Scalar1, -deviceBounds.top());
|
topMatrix.setScale(SK_Scalar1, -deviceBounds.top());
|
||||||
topMatrix.postTranslate(0, deviceBounds.top());
|
topMatrix.postTranslate(0, deviceBounds.top());
|
||||||
draw_bitmap_matrix(&canvas, top, topMatrix);
|
draw_bitmap_matrix(&canvas, top, topMatrix, paint);
|
||||||
|
|
||||||
if (tileModes[0] == SkShader::kMirror_TileMode) {
|
if (tileModes[0] == SkShader::kMirror_TileMode) {
|
||||||
topMatrix.postScale(-1, 1);
|
topMatrix.postScale(-1, 1);
|
||||||
topMatrix.postTranslate(2 * width, 0);
|
topMatrix.postTranslate(2 * width, 0);
|
||||||
draw_bitmap_matrix(&canvas, top, topMatrix);
|
draw_bitmap_matrix(&canvas, top, topMatrix, paint);
|
||||||
}
|
}
|
||||||
patternBBox.fTop = 0;
|
patternBBox.fTop = 0;
|
||||||
}
|
}
|
||||||
@ -228,12 +233,12 @@ static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc,
|
|||||||
SkMatrix bottomMatrix;
|
SkMatrix bottomMatrix;
|
||||||
bottomMatrix.setScale(SK_Scalar1, deviceBounds.bottom() - height);
|
bottomMatrix.setScale(SK_Scalar1, deviceBounds.bottom() - height);
|
||||||
bottomMatrix.postTranslate(0, height);
|
bottomMatrix.postTranslate(0, height);
|
||||||
draw_bitmap_matrix(&canvas, bottom, bottomMatrix);
|
draw_bitmap_matrix(&canvas, bottom, bottomMatrix, paint);
|
||||||
|
|
||||||
if (tileModes[0] == SkShader::kMirror_TileMode) {
|
if (tileModes[0] == SkShader::kMirror_TileMode) {
|
||||||
bottomMatrix.postScale(-1, 1);
|
bottomMatrix.postScale(-1, 1);
|
||||||
bottomMatrix.postTranslate(2 * width, 0);
|
bottomMatrix.postTranslate(2 * width, 0);
|
||||||
draw_bitmap_matrix(&canvas, bottom, bottomMatrix);
|
draw_bitmap_matrix(&canvas, bottom, bottomMatrix, paint);
|
||||||
}
|
}
|
||||||
patternBBox.fBottom = deviceBounds.height();
|
patternBBox.fBottom = deviceBounds.height();
|
||||||
}
|
}
|
||||||
@ -252,7 +257,8 @@ static sk_sp<SkPDFStream> make_image_shader(SkPDFDocument* doc,
|
|||||||
static sk_sp<SkPDFObject> make_fallback_shader(SkPDFDocument* doc,
|
static sk_sp<SkPDFObject> make_fallback_shader(SkPDFDocument* doc,
|
||||||
SkShader* shader,
|
SkShader* shader,
|
||||||
const SkMatrix& canvasTransform,
|
const SkMatrix& canvasTransform,
|
||||||
const SkIRect& surfaceBBox) {
|
const SkIRect& surfaceBBox,
|
||||||
|
SkColor paintColor) {
|
||||||
// TODO(vandebo) This drops SKComposeShader on the floor. We could
|
// TODO(vandebo) This drops SKComposeShader on the floor. We could
|
||||||
// handle compose shader by pulling things up to a layer, drawing with
|
// handle compose shader by pulling things up to a layer, drawing with
|
||||||
// the first shader, applying the xfer mode and drawing again with the
|
// the first shader, applying the xfer mode and drawing again with the
|
||||||
@ -262,7 +268,8 @@ static sk_sp<SkPDFObject> make_fallback_shader(SkPDFDocument* doc,
|
|||||||
SkMatrix::I(),
|
SkMatrix::I(),
|
||||||
surfaceBBox,
|
surfaceBBox,
|
||||||
{{0, 0, 0, 0}, 0}, // don't need the key; won't de-dup.
|
{{0, 0, 0, 0}, 0}, // don't need the key; won't de-dup.
|
||||||
{SkShader::kClamp_TileMode, SkShader::kClamp_TileMode}};
|
{SkShader::kClamp_TileMode, SkShader::kClamp_TileMode},
|
||||||
|
paintColor};
|
||||||
|
|
||||||
key.fShaderTransform = shader->getLocalMatrix();
|
key.fShaderTransform = shader->getLocalMatrix();
|
||||||
|
|
||||||
@ -287,31 +294,40 @@ static sk_sp<SkPDFObject> make_fallback_shader(SkPDFDocument* doc,
|
|||||||
SkSize scale = {SkIntToScalar(size.width()) / shaderRect.width(),
|
SkSize scale = {SkIntToScalar(size.width()) / shaderRect.width(),
|
||||||
SkIntToScalar(size.height()) / shaderRect.height()};
|
SkIntToScalar(size.height()) / shaderRect.height()};
|
||||||
|
|
||||||
SkBitmap bitmap;
|
auto surface = SkSurface::MakeRasterN32Premul(size.width(), size.height());
|
||||||
bitmap.allocN32Pixels(size.width(), size.height());
|
SkCanvas* canvas = surface->getCanvas();
|
||||||
bitmap.eraseColor(SK_ColorTRANSPARENT);
|
canvas->clear(SK_ColorTRANSPARENT);
|
||||||
|
|
||||||
SkPaint p;
|
SkPaint p;
|
||||||
p.setShader(sk_ref_sp(shader));
|
p.setShader(sk_ref_sp(shader));
|
||||||
|
p.setColor(paintColor);
|
||||||
|
|
||||||
SkCanvas canvas(bitmap);
|
canvas->scale(scale.width(), scale.height());
|
||||||
canvas.scale(scale.width(), scale.height());
|
canvas->translate(-shaderRect.x(), -shaderRect.y());
|
||||||
canvas.translate(-shaderRect.x(), -shaderRect.y());
|
canvas->drawPaint(p);
|
||||||
canvas.drawPaint(p);
|
|
||||||
|
|
||||||
key.fShaderTransform.setTranslate(shaderRect.x(), shaderRect.y());
|
key.fShaderTransform.setTranslate(shaderRect.x(), shaderRect.y());
|
||||||
key.fShaderTransform.preScale(1 / scale.width(), 1 / scale.height());
|
key.fShaderTransform.preScale(1 / scale.width(), 1 / scale.height());
|
||||||
|
|
||||||
SkASSERT (!bitmap.isNull());
|
sk_sp<SkImage> image = surface->makeImageSnapshot();
|
||||||
bitmap.setImmutable();
|
|
||||||
sk_sp<SkImage> image = SkImage::MakeFromBitmap(bitmap);
|
|
||||||
return make_image_shader(doc, key, image.get());
|
return make_image_shader(doc, key, image.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SkColor adjust_color(SkShader* shader, SkColor paintColor) {
|
||||||
|
if (SkImage* img = shader->isAImage(nullptr, nullptr)) {
|
||||||
|
if (img->isAlphaOnly()) {
|
||||||
|
return paintColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// only preserve the alpha.
|
||||||
|
return paintColor & SK_ColorBLACK;
|
||||||
|
}
|
||||||
|
|
||||||
sk_sp<SkPDFObject> SkPDFMakeShader(SkPDFDocument* doc,
|
sk_sp<SkPDFObject> SkPDFMakeShader(SkPDFDocument* doc,
|
||||||
SkShader* shader,
|
SkShader* shader,
|
||||||
const SkMatrix& canvasTransform,
|
const SkMatrix& canvasTransform,
|
||||||
const SkIRect& surfaceBBox) {
|
const SkIRect& surfaceBBox,
|
||||||
|
SkColor paintColor) {
|
||||||
SkASSERT(shader);
|
SkASSERT(shader);
|
||||||
SkASSERT(doc);
|
SkASSERT(doc);
|
||||||
if (SkShader::kNone_GradientType != shader->asAGradient(nullptr)) {
|
if (SkShader::kNone_GradientType != shader->asAGradient(nullptr)) {
|
||||||
@ -326,7 +342,8 @@ sk_sp<SkPDFObject> SkPDFMakeShader(SkPDFDocument* doc,
|
|||||||
SkMatrix::I(),
|
SkMatrix::I(),
|
||||||
surfaceBBox,
|
surfaceBBox,
|
||||||
{{0, 0, 0, 0}, 0},
|
{{0, 0, 0, 0}, 0},
|
||||||
{SkShader::kClamp_TileMode, SkShader::kClamp_TileMode}};
|
{SkShader::kClamp_TileMode, SkShader::kClamp_TileMode},
|
||||||
|
adjust_color(shader, paintColor)};
|
||||||
|
|
||||||
SkASSERT(shader->asAGradient(nullptr) == SkShader::kNone_GradientType) ;
|
SkASSERT(shader->asAGradient(nullptr) == SkShader::kNone_GradientType) ;
|
||||||
if (SkImage* skimg = shader->isAImage(&key.fShaderTransform, key.fImageTileModes)) {
|
if (SkImage* skimg = shader->isAImage(&key.fShaderTransform, key.fImageTileModes)) {
|
||||||
@ -341,5 +358,5 @@ sk_sp<SkPDFObject> SkPDFMakeShader(SkPDFDocument* doc,
|
|||||||
return pdfShader;
|
return pdfShader;
|
||||||
}
|
}
|
||||||
// Don't bother to de-dup fallback shader.
|
// Don't bother to de-dup fallback shader.
|
||||||
return make_fallback_shader(doc, shader, canvasTransform, surfaceBBox);
|
return make_fallback_shader(doc, shader, canvasTransform, surfaceBBox, key.fPaintColor);
|
||||||
}
|
}
|
||||||
|
@ -34,11 +34,14 @@ struct SkIRect;
|
|||||||
* positioned, relative to where the page is drawn.)
|
* positioned, relative to where the page is drawn.)
|
||||||
* @param surfceBBox The bounding box of the drawing surface (with matrix
|
* @param surfceBBox The bounding box of the drawing surface (with matrix
|
||||||
* already applied).
|
* already applied).
|
||||||
|
* @param paintColor Color+Alpha of the paint. Color is usually ignored,
|
||||||
|
* unless it is a alpha shader.
|
||||||
*/
|
*/
|
||||||
sk_sp<SkPDFObject> SkPDFMakeShader(SkPDFDocument* doc,
|
sk_sp<SkPDFObject> SkPDFMakeShader(SkPDFDocument* doc,
|
||||||
SkShader* shader,
|
SkShader* shader,
|
||||||
const SkMatrix& ctm,
|
const SkMatrix& ctm,
|
||||||
const SkIRect& surfaceBBox);
|
const SkIRect& surfaceBBox,
|
||||||
|
SkColor paintColor);
|
||||||
|
|
||||||
SK_BEGIN_REQUIRE_DENSE
|
SK_BEGIN_REQUIRE_DENSE
|
||||||
struct SkPDFImageShaderKey {
|
struct SkPDFImageShaderKey {
|
||||||
@ -47,6 +50,7 @@ struct SkPDFImageShaderKey {
|
|||||||
SkIRect fBBox;
|
SkIRect fBBox;
|
||||||
SkBitmapKey fBitmapKey;
|
SkBitmapKey fBitmapKey;
|
||||||
SkShader::TileMode fImageTileModes[2];
|
SkShader::TileMode fImageTileModes[2];
|
||||||
|
SkColor fPaintColor;
|
||||||
};
|
};
|
||||||
SK_END_REQUIRE_DENSE
|
SK_END_REQUIRE_DENSE
|
||||||
|
|
||||||
@ -58,6 +62,7 @@ inline bool operator==(const SkPDFImageShaderKey& a, const SkPDFImageShaderKey&
|
|||||||
&& a.fBBox == b.fBBox
|
&& a.fBBox == b.fBBox
|
||||||
&& a.fBitmapKey == b.fBitmapKey
|
&& a.fBitmapKey == b.fBitmapKey
|
||||||
&& a.fImageTileModes[0] == b.fImageTileModes[0]
|
&& a.fImageTileModes[0] == b.fImageTileModes[0]
|
||||||
&& a.fImageTileModes[1] == b.fImageTileModes[1];
|
&& a.fImageTileModes[1] == b.fImageTileModes[1]
|
||||||
|
&& a.fPaintColor == b.fPaintColor;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user