From b82ac3660c20fbad3391ccef0e17a8e242702450 Mon Sep 17 00:00:00 2001 From: Hal Canary Date: Thu, 2 May 2019 10:47:46 -0400 Subject: [PATCH] SkPDF: fix repeat tilemode with alpha Also fix the corners of clamp mode with alpha. Also, add a GM. Bug:chromium:957275 Change-Id: Icd288ff522e7ea70662380791f5ee2de628a5ef2 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/211594 Auto-Submit: Hal Canary Commit-Queue: Ben Wagner Reviewed-by: Ben Wagner --- gm/tilemodes_alpha.cpp | 27 +++++++++++++++++++++++++++ gn/gm.gni | 1 + src/pdf/SkPDFShader.cpp | 36 +++++++++++++++++++++++------------- 3 files changed, 51 insertions(+), 13 deletions(-) create mode 100644 gm/tilemodes_alpha.cpp diff --git a/gm/tilemodes_alpha.cpp b/gm/tilemodes_alpha.cpp new file mode 100644 index 0000000000..5f73eef96c --- /dev/null +++ b/gm/tilemodes_alpha.cpp @@ -0,0 +1,27 @@ +// Copyright 2019 Google LLC. +// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. +#include "gm/gm.h" +#include "tools/Resources.h" +// http://crbug.com/957275 +DEF_SIMPLE_GM(tilemodes_alpha, canvas, 512, 512) { + sk_sp image = GetResourceAsImage("images/mandrill_64.png"); + if (!image) { + return; + } + constexpr SkTileMode kModes[4] = { + SkTileMode::kClamp, + SkTileMode::kRepeat, + SkTileMode::kMirror, + SkTileMode::kDecal, + }; + for (int y = 0; y < 4; ++y) { + for (int x = 0; x < 4; ++x) { + SkRect rect = SkRect::MakeXYWH(128 * x + 1, 128 * y + 1, 126, 126); + SkMatrix matrix = SkMatrix::MakeTrans(rect.x(), rect.y()); + SkPaint paint; + paint.setAlphaf(0.5f); + paint.setShader(image->makeShader(kModes[x], kModes[y], &matrix)); + canvas->drawRect(rect, paint); + } + } +} diff --git a/gn/gm.gni b/gn/gm.gni index 73cb5fa799..900a0d75ce 100644 --- a/gn/gm.gni +++ b/gn/gm.gni @@ -351,6 +351,7 @@ gm_sources = [ "$_gm/tiledscaledbitmap.cpp", "$_gm/tileimagefilter.cpp", "$_gm/tilemodes.cpp", + "$_gm/tilemodes_alpha.cpp", "$_gm/tilemodes_scaled.cpp", "$_gm/tinybitmap.cpp", "$_gm/transparency.cpp", diff --git a/src/pdf/SkPDFShader.cpp b/src/pdf/SkPDFShader.cpp index 252e5b04be..ee249d50a0 100644 --- a/src/pdf/SkPDFShader.cpp +++ b/src/pdf/SkPDFShader.cpp @@ -9,6 +9,7 @@ #include "src/pdf/SkPDFShader.h" #include "include/core/SkData.h" +#include "include/core/SkMath.h" #include "include/core/SkScalar.h" #include "include/core/SkStream.h" #include "include/core/SkSurface.h" @@ -37,6 +38,13 @@ static void draw_bitmap_matrix(SkCanvas* canvas, const SkBitmap& bm, canvas->drawBitmap(bm, 0, 0, &paint); } +SkColor mix(SkColor c, U8CPU alpha) { + return SkColorSetARGB(SkMulDiv255Round(alpha, SkColorGetA(c)), + SkColorGetR(c), + SkColorGetG(c), + SkColorGetB(c)); +} + static SkPDFIndirectReference make_image_shader(SkPDFDocument* doc, const SkPDFImageShaderKey& key, SkImage* image) { @@ -81,16 +89,17 @@ static SkPDFIndirectReference make_image_shader(SkPDFDocument* doc, // Undo the translation in the final matrix finalMatrix.preTranslate(deviceBounds.left(), deviceBounds.top()); + SkPaint paint; + paint.setColor(key.fPaintColor); + // If the bitmap is out of bounds (i.e. clamp mode where we only see the // stretched sides), canvas will clip this out and the extraneous data // won't be saved to the PDF. - canvas.drawImage(image, 0, 0); + canvas.drawImage(image, 0, 0, &paint); SkScalar width = SkIntToScalar(image->width()); SkScalar height = SkIntToScalar(image->height()); - SkPaint paint; - paint.setColor(key.fPaintColor); // Tiling is implied. First we handle mirroring. if (tileModes[0] == SkTileMode::kMirror) { SkMatrix xMirror; @@ -130,34 +139,35 @@ static SkPDFIndirectReference make_image_shader(SkPDFDocument* doc, // (Which are just a rectangles of the corner colors.) if (tileModes[0] == SkTileMode::kClamp && tileModes[1] == SkTileMode::kClamp) { SkASSERT(!bitmap.drawsNothing()); - SkPaint paint; + U8CPU alpha = SkColorGetA(key.fPaintColor); + SkPaint paint2; SkRect rect; rect = SkRect::MakeLTRB(deviceBounds.left(), deviceBounds.top(), 0, 0); if (!rect.isEmpty()) { - paint.setColor(bitmap.getColor(0, 0)); - canvas.drawRect(rect, paint); + paint2.setColor(mix(bitmap.getColor(0, 0), alpha)); + canvas.drawRect(rect, paint2); } rect = SkRect::MakeLTRB(width, deviceBounds.top(), deviceBounds.right(), 0); if (!rect.isEmpty()) { - paint.setColor(bitmap.getColor(bitmap.width() - 1, 0)); - canvas.drawRect(rect, paint); + paint2.setColor(mix(bitmap.getColor(bitmap.width() - 1, 0), alpha)); + canvas.drawRect(rect, paint2); } rect = SkRect::MakeLTRB(width, height, deviceBounds.right(), deviceBounds.bottom()); if (!rect.isEmpty()) { - paint.setColor(bitmap.getColor(bitmap.width() - 1, - bitmap.height() - 1)); - canvas.drawRect(rect, paint); + paint2.setColor(mix(bitmap.getColor(bitmap.width() - 1, + bitmap.height() - 1), alpha)); + canvas.drawRect(rect, paint2); } rect = SkRect::MakeLTRB(deviceBounds.left(), height, 0, deviceBounds.bottom()); if (!rect.isEmpty()) { - paint.setColor(bitmap.getColor(0, bitmap.height() - 1)); - canvas.drawRect(rect, paint); + paint2.setColor(mix(bitmap.getColor(0, bitmap.height() - 1), alpha)); + canvas.drawRect(rect, paint2); } }