[graphite] Use new Transform concat functions in text code

Uses Transform::Identity() and preTranslate() in places to simplify code
and reduce matrix copying/multiplications.

Reworks DirectMaskSubRun's boundsAndTransform() function to use
preTranslate() and concatInverse() to similarly reduce matrix copies
and multiplications. It keeps fInitialPositionMatrix as an SkMatrix as
long as possible, and similarly does not copy localToDevice until its
determined that concatInverse() and preTranslate() need to be used
(vs. the integer-only translation).

Change-Id: Ia2ba266f952d3c71fb3afc30f3ba0b904bb4bede
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/555002
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
This commit is contained in:
Michael Ludwig 2022-07-01 11:42:24 -04:00 committed by SkCQ
parent afe25662ee
commit d289afdd6c
2 changed files with 32 additions and 31 deletions

View File

@ -648,10 +648,9 @@ void Device::drawGeometry(const Transform& localToDevice,
// TODO: The tessellating path renderers haven't implemented perspective yet, so transform to
// device space so we draw something approximately correct (barring local coord issues).
if (geometry.isShape() && localToDevice.type() == Transform::Type::kProjection) {
static const Transform kIdentity{SkM44()};
SkPath devicePath = geometry.shape().asPath();
devicePath.transform(localToDevice.matrix().asM33());
this->drawGeometry(kIdentity, Geometry(Shape(devicePath)), paint, style, flags);
this->drawGeometry(Transform::Identity(), Geometry(Shape(devicePath)), paint, style, flags);
return;
}
@ -764,7 +763,7 @@ void Device::drawClipShape(const Transform& localToDevice,
if (localToDevice.type() == Transform::Type::kProjection) {
SkPath devicePath = geometry.shape().asPath();
devicePath.transform(localToDevice.matrix().asM33());
fDC->recordDraw(*renderer, Transform({}), Geometry(Shape(devicePath)), clip, order,
fDC->recordDraw(*renderer, Transform::Identity(), Geometry(Shape(devicePath)), clip, order,
nullptr, nullptr);
} else {
fDC->recordDraw(*renderer, localToDevice, geometry, clip, order, nullptr, nullptr);

View File

@ -1552,33 +1552,37 @@ std::tuple<bool, int> DirectMaskSubRun::regenerateAtlas(int begin, int end,
std::tuple<Rect, Transform> DirectMaskSubRun::boundsAndDeviceMatrix(const Transform& localToDevice,
SkPoint drawOrigin) const {
SkM44 positionMatrix(localToDevice.matrix());
positionMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
SkM44 initialMatrix(fInitialPositionMatrix);
const SkPoint offset = {positionMatrix.rc(0,3) - initialMatrix.rc(0,3),
positionMatrix.rc(1,3) - initialMatrix.rc(1,3)};
const bool compatibleMatrix = positionMatrix.rc(0,0) == initialMatrix.rc(0,0) &&
positionMatrix.rc(0,1) == initialMatrix.rc(0,1) &&
positionMatrix.rc(1,0) == initialMatrix.rc(1,0) &&
positionMatrix.rc(1,1) == initialMatrix.rc(1,1) &&
// The baked-in matrix differs from the current localToDevice by a translation if the upper 2x2
// remains the same, and there's no perspective. Since there's no projection, Z is irrelevant
// so it's okay that fInitialPositionMatrix is an SkMatrix and has discarded the 3rd row/col,
// and can ignore those values in localToDevice.
const SkM44& positionMatrix = localToDevice.matrix();
const bool compatibleMatrix = positionMatrix.rc(0,0) == fInitialPositionMatrix.rc(0,0) &&
positionMatrix.rc(0,1) == fInitialPositionMatrix.rc(0,1) &&
positionMatrix.rc(1,0) == fInitialPositionMatrix.rc(1,0) &&
positionMatrix.rc(1,1) == fInitialPositionMatrix.rc(1,1) &&
localToDevice.type() != Transform::Type::kProjection &&
!fInitialPositionMatrix.hasPerspective();
if (compatibleMatrix && SkScalarIsInt(offset.x()) && SkScalarIsInt(offset.y())) {
// Handle the integer offset case.
// The offset should be integer, but make sure.
SkM44 translate = SkM44::Translate(SkScalarRoundToInt(offset.x()),
SkScalarRoundToInt(offset.y()));
return {Rect(fGlyphDeviceBounds.rect()), Transform(translate)};
} else if (SkM44 inverse; initialMatrix.invert(&inverse)) {
SkM44 viewDifference = positionMatrix * inverse;
return {Rect(fGlyphDeviceBounds.rect()), Transform(viewDifference)};
if (compatibleMatrix) {
const SkV4 mappedOrigin = positionMatrix.map(drawOrigin.x(), drawOrigin.y(), 0.f, 1.f);
const SkV2 offset = {mappedOrigin.x - fInitialPositionMatrix.getTranslateX(),
mappedOrigin.y - fInitialPositionMatrix.getTranslateY()};
if (SkScalarIsInt(offset.x) && SkScalarIsInt(offset.y)) {
// The offset is an integer (but make sure), which means the generated mask can be
// accessed without changing how texels would be sampled.
return {Rect(fGlyphDeviceBounds.rect()),
Transform(SkM44::Translate(SkScalarRoundToInt(offset.x),
SkScalarRoundToInt(offset.y)))};
}
}
// initialPositionMatrix is singular. Do nothing.
static const Transform kInvalid{SkM44(SkM44::kNaN_Constructor)};
return {Rect::InfiniteInverted(), kInvalid};
// Otherwise compute the relative transformation from fInitialPositionMatrix to localToDevice,
// with the drawOrigin applied. If fInitialPositionMatrix or the concatenation is not invertible
// the returned Transform is marked invalid and the draw will be automatically dropped.
return {Rect(fGlyphDeviceBounds.rect()),
localToDevice.preTranslate(drawOrigin.x(), drawOrigin.y())
.concatInverse(SkM44(fInitialPositionMatrix))};
}
template<typename VertexData>
@ -1949,9 +1953,8 @@ std::tuple<bool, int> TransformedMaskSubRun::regenerateAtlas(int begin, int end,
std::tuple<Rect, Transform> TransformedMaskSubRun::boundsAndDeviceMatrix(
const Transform& localToDevice, SkPoint drawOrigin) const {
SkM44 positionMatrix(localToDevice.matrix());
positionMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
return {Rect(fVertexFiller.localRect()), Transform(positionMatrix)};
return {Rect(fVertexFiller.localRect()),
localToDevice.preTranslate(drawOrigin.x(), drawOrigin.y())};
}
void TransformedMaskSubRun::fillVertexData(DrawWriter*,
@ -2286,9 +2289,8 @@ SDFTSubRun::regenerateAtlas(int begin, int end, Recorder *recorder) const {
std::tuple<Rect, Transform> SDFTSubRun::boundsAndDeviceMatrix(const Transform& localToDevice,
SkPoint drawOrigin) const {
SkM44 positionMatrix(localToDevice.matrix());
positionMatrix.preTranslate(drawOrigin.x(), drawOrigin.y());
return {Rect(fVertexFiller.localRect()), Transform(positionMatrix)};
return {Rect(fVertexFiller.localRect()),
localToDevice.preTranslate(drawOrigin.x(), drawOrigin.y())};
}
void SDFTSubRun::fillVertexData(DrawWriter*,