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 <halcanary@google.com>
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
This commit is contained in:
Hal Canary 2019-05-02 10:47:46 -04:00 committed by Skia Commit-Bot
parent 347034865b
commit b82ac3660c
3 changed files with 51 additions and 13 deletions

27
gm/tilemodes_alpha.cpp Normal file
View File

@ -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<SkImage> 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);
}
}
}

View File

@ -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",

View File

@ -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);
}
}