drawGlyphRunRSXform: post-compose shader local matrix adjustments
Bug: skia:11113 Change-Id: Ic34a0c80b44031d77d361d35e64301297b3f3189 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/347047 Commit-Queue: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@google.com> Reviewed-by: Mike Reed <reed@google.com>
This commit is contained in:
parent
6e9bf51dd8
commit
ff49f92e26
@ -31,7 +31,7 @@ private:
|
||||
SkFontStyle::kNormal_Width,
|
||||
SkFontStyle::kUpright_Slant);
|
||||
SkFont font(ToolUtils::create_portable_typeface(nullptr, style), kFontSZ);
|
||||
font.setEdging(SkFont::Edging::kAlias);
|
||||
font.setEdging(SkFont::Edging::kAntiAlias);
|
||||
|
||||
static constexpr char txt[] = "TEST";
|
||||
SkGlyphID glyphs[16];
|
||||
@ -95,7 +95,8 @@ private:
|
||||
->drawRect({0, 0, kTileSize.width()*0.9f, kTileSize.height()*0.9f}, p);
|
||||
|
||||
return surface->makeImageSnapshot()
|
||||
->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, SkSamplingOptions(), &lm)
|
||||
->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
|
||||
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone), &lm)
|
||||
->makeWithLocalMatrix(outer_lm);
|
||||
}
|
||||
|
||||
|
@ -395,6 +395,43 @@ bool SkBaseDevice::peekPixels(SkPixmap* pmap) {
|
||||
|
||||
#include "src/core/SkUtils.h"
|
||||
|
||||
|
||||
// TODO: This does not work for arbitrary shader DAGs (when there is no single leaf local matrix).
|
||||
// What we really need is proper post-LM plumbing for shaders.
|
||||
static sk_sp<SkShader> make_post_inverse_lm(const SkShader* shader, const SkMatrix& m) {
|
||||
SkMatrix inverse;
|
||||
if (!shader || !m.invert(&inverse)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Normal LMs pre-compose. In order to push a post local matrix, we shoot for
|
||||
// something along these lines (where all new components are pre-composed):
|
||||
//
|
||||
// new_lm X current_lm == current_lm X inv(current_lm) X new_lm X current_lm
|
||||
//
|
||||
// We also have two sources of local matrices:
|
||||
// - the actual shader lm
|
||||
// - outer lms applied via SkLocalMatrixShader
|
||||
|
||||
SkMatrix outer_lm;
|
||||
const auto nested_shader = as_SB(shader)->makeAsALocalMatrixShader(&outer_lm);
|
||||
if (nested_shader) {
|
||||
// unfurl the shader
|
||||
shader = nested_shader.get();
|
||||
} else {
|
||||
outer_lm.reset();
|
||||
}
|
||||
|
||||
const auto lm = *as_SB(shader)->totalLocalMatrix(nullptr);
|
||||
SkMatrix lm_inv;
|
||||
if (!lm.invert(&lm_inv)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Note: since we unfurled the shader above, we don't need to apply an outer_lm inverse
|
||||
return shader->makeWithLocalMatrix(lm_inv * inverse * lm * outer_lm);
|
||||
}
|
||||
|
||||
void SkBaseDevice::drawGlyphRunRSXform(const SkFont& font, const SkGlyphID glyphs[],
|
||||
const SkRSXform xform[], int count, SkPoint origin,
|
||||
const SkPaint& paint) {
|
||||
@ -426,15 +463,7 @@ void SkBaseDevice::drawGlyphRunRSXform(const SkFont& font, const SkGlyphID glyph
|
||||
// (i.e. the shader that cares about the ctm) so we have to undo our little ctm trick
|
||||
// with a localmatrixshader so that the shader draws as if there was no change to the ctm.
|
||||
SkPaint transformingPaint{paint};
|
||||
auto shader = transformingPaint.getShader();
|
||||
if (shader) {
|
||||
SkMatrix inverse;
|
||||
if (glyphToDevice.invert(&inverse)) {
|
||||
transformingPaint.setShader(shader->makeWithLocalMatrix(inverse));
|
||||
} else {
|
||||
transformingPaint.setShader(nullptr); // can't handle this xform
|
||||
}
|
||||
}
|
||||
transformingPaint.setShader(make_post_inverse_lm(paint.getShader(), glyphToDevice));
|
||||
|
||||
this->setLocalToDevice(originalLocalToDevice * SkM44(glyphToDevice));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user