// Check for integer translate with the same 2x2 matrix. // Returns the translation, and true if the change from initial matrix to the position matrix // support using direct glyph masks.
std::tuple<bool, SkVector> can_use_direct( const SkMatrix& initialPositionMatrix, const SkMatrix& positionMatrix) { // The existing direct glyph info can be used if the initialPositionMatrix, and the // positionMatrix have the same 2x2, and the translation between them is integer. // Calculate the translation in source space to a translation in device space by mapping // (0, 0) through both the initial position matrix and the position matrix; take the difference.
SkVector translation = positionMatrix.mapOrigin() - initialPositionMatrix.mapOrigin(); return {initialPositionMatrix.getScaleX() == positionMatrix.getScaleX() &&
initialPositionMatrix.getScaleY() == positionMatrix.getScaleY() &&
initialPositionMatrix.getSkewX() == positionMatrix.getSkewX() &&
initialPositionMatrix.getSkewY() == positionMatrix.getSkewY() &&
SkScalarIsInt(translation.x()) && SkScalarIsInt(translation.y()),
translation};
}
static SkColor compute_canonical_color(const SkPaint& paint, bool lcd) {
SkColor canonicalColor = SkPaintPriv::ComputeLuminanceColor(paint); if (lcd) { // This is the correct computation for canonicalColor, but there are tons of cases where LCD // can be modified. For now we just regenerate if any run in a textblob has LCD. // TODO figure out where all of these modifications are and see if we can incorporate that // logic at a higher level *OR* use sRGB //canonicalColor = SkMaskGamma::CanonicalColor(canonicalColor);
// TODO we want to figure out a way to be able to use the canonical color on LCD text, // see the note above. We pick a placeholder value for LCD text to ensure we always match // the same key return SK_ColorTRANSPARENT;
} else { // A8, though can have mixed BMP text but it shouldn't matter because BMP text won't have // gamma corrected masks anyways, nor color
U8CPU lum = SkComputeLuminance(SkColorGetR(canonicalColor),
SkColorGetG(canonicalColor),
SkColorGetB(canonicalColor)); // reduce to our finite number of bits
canonicalColor = SkMaskGamma::CanonicalColor(SkColorSetRGB(lum, lum, lum));
} return canonicalColor;
}
} // namespace
namespace sktext::gpu { // -- TextBlob::Key ------------------------------------------------------------------------------ auto TextBlob::Key::Make(const GlyphRunList& glyphRunList, const SkPaint& paint, const SkMatrix& drawMatrix, const SkStrikeDeviceInfo& strikeDevice) -> std::tuple<bool, Key> {
SkASSERT(strikeDevice.fSubRunControl != nullptr);
SkMaskFilterBase::BlurRec blurRec; // It might be worth caching these things, but its not clear at this time // TODO for animated mask filters, this will fill up our cache. We need a safeguard here const SkMaskFilter* maskFilter = paint.getMaskFilter(); bool canCache = glyphRunList.canCache() &&
!(paint.getPathEffect() ||
(maskFilter && !as_MFB(maskFilter)->asABlur(&blurRec)));
TextBlob::Key key; if (canCache) { bool hasLCD = glyphRunList.anyRunsLCD();
// We canonicalize all non-lcd draws to use kUnknown_SkPixelGeometry
SkPixelGeometry pixelGeometry = hasLCD ? strikeDevice.fSurfaceProps.pixelGeometry()
: kUnknown_SkPixelGeometry;
// Do any runs use direct drawing types?.
key.fHasSomeDirectSubRuns = false;
SkPoint glyphRunListLocation = glyphRunList.sourceBoundsWithOrigin().center(); for (auto& run : glyphRunList) {
SkScalar approximateDeviceTextSize =
SkFontPriv::ApproximateTransformedTextSize(run.font(), drawMatrix,
glyphRunListLocation);
key.fHasSomeDirectSubRuns |=
strikeDevice.fSubRunControl->isDirect(approximateDeviceTextSize, paint,
drawMatrix);
}
if (key.fHasSomeDirectSubRuns) { // Store the fractional offset of the position. We know that the matrix can't be // perspective at this point.
SkPoint mappedOrigin = drawMatrix.mapOrigin();
key.fPositionMatrix = drawMatrix;
key.fPositionMatrix.setTranslateX(
mappedOrigin.x() - SkScalarFloorToScalar(mappedOrigin.x()));
key.fPositionMatrix.setTranslateY(
mappedOrigin.y() - SkScalarFloorToScalar(mappedOrigin.y()));
} else { // For path and SDFT, the matrix doesn't matter.
key.fPositionMatrix = SkMatrix::I();
}
}
return {canCache, key};
}
bool TextBlob::Key::operator==(const TextBlob::Key& that) const { if (fUniqueID != that.fUniqueID) { returnfalse; } if (fCanonicalColor != that.fCanonicalColor) { returnfalse; } if (fStyle != that.fStyle) { returnfalse; } if (fStyle != SkPaint::kFill_Style) { if (fFrameWidth != that.fFrameWidth ||
fMiterLimit != that.fMiterLimit ||
fJoin != that.fJoin) { returnfalse;
}
} if (fPixelGeometry != that.fPixelGeometry) { returnfalse; } if (fHasBlur != that.fHasBlur) { returnfalse; } if (fHasBlur) { if (fBlurRec.fStyle != that.fBlurRec.fStyle || fBlurRec.fSigma != that.fBlurRec.fSigma) { returnfalse;
}
}
if (fScalerContextFlags != that.fScalerContextFlags) { returnfalse; }
// DirectSubRuns do not support perspective when used with a TextBlob. SDFT, Transformed, // Path, and Drawable do support perspective. if (fPositionMatrix.hasPerspective() && fHasSomeDirectSubRuns) { returnfalse; }
if (fHasSomeDirectSubRuns != that.fHasSomeDirectSubRuns) { returnfalse; }
if (fHasSomeDirectSubRuns) { auto [compatible, _] = can_use_direct(fPositionMatrix, that.fPositionMatrix); return compatible;
}
returntrue;
}
// -- TextBlob ----------------------------------------------------------------------------------- void TextBlob::operatordelete(void* p) { ::operatordelete(p); } void* TextBlob::operatornew(size_t) { SK_ABORT("All blobs are created by placement new."); } void* TextBlob::operatornew(size_t, void* p) { return p; }
bool TextBlob::canReuse(const SkPaint& paint, const SkMatrix& positionMatrix) const { // A singular matrix will create a TextBlob with no SubRuns, but unknown glyphs can also // cause empty runs. If there are no subRuns, then regenerate when the matrices don't match. if (fSubRuns->isEmpty() && fSubRuns->initialPosition() != positionMatrix) { returnfalse;
}
// If we have LCD text then our canonical color will be set to transparent, in this case we have // to regenerate the blob on any color change // We use the grPaint to get any color filter effects if (fKey.fCanonicalColor == SK_ColorTRANSPARENT &&
fInitialLuminance != SkPaintPriv::ComputeLuminanceColor(paint)) { returnfalse;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.