pull out clip code that will be shared

This clip code will be shared with direct-to-op text drawing
path.

Change-Id: I6744a93cb75b555e91b3b016d5604d3ba81b02fe
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/355977
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2021-01-19 14:43:33 -05:00 committed by Skia Commit-Bot
parent 420a75d685
commit b34d62ba9a

View File

@ -602,51 +602,76 @@ int DirectMaskSubRun::glyphCount() const {
return fGlyphs.glyphs().count();
}
namespace {
enum ClipMethod {
kClippedOut,
kUnclipped,
kGPUClipped,
kGeometryClipped
};
std::tuple<ClipMethod, SkIRect>
calculate_clip(const GrClip* clip, SkRect deviceBounds, SkRect glyphBounds) {
if (clip == nullptr && !deviceBounds.intersects(glyphBounds)) {
return {kClippedOut, SkIRect::MakeEmpty()};
} else if (clip != nullptr) {
switch (auto result = clip->preApply(glyphBounds, GrAA::kNo); result.fEffect) {
case GrClip::Effect::kClippedOut:
return {kClippedOut, SkIRect::MakeEmpty()};
case GrClip::Effect::kUnclipped:
return {kUnclipped, SkIRect::MakeEmpty()};
case GrClip::Effect::kClipped: {
if (result.fIsRRect && result.fRRect.isRect()) {
SkRect r = result.fRRect.rect();
if (result.fAA == GrAA::kNo || GrClip::IsPixelAligned(r)) {
SkIRect clipRect = SkIRect::MakeEmpty();
// Clip geometrically during onPrepare using clipRect.
r.round(&clipRect);
if (clipRect.contains(glyphBounds)) {
// If fully within the clip, signal no clipping using the empty rect.
return {kUnclipped, SkIRect::MakeEmpty()};
}
// Use the clipRect to clip the geometry.
return {kGeometryClipped, clipRect};
}
// Partial pixel clipped at this point. Have the GPU handle it.
}
}
break;
}
}
return {kGPUClipped, SkIRect::MakeEmpty()};
}
} // namespace
std::tuple<const GrClip*, GrOp::Owner>
DirectMaskSubRun::makeAtlasTextOp(const GrClip* clip, const SkMatrixProvider& viewMatrix,
const SkGlyphRunList& glyphRunList,
GrSurfaceDrawContext* rtc) const {
GrSurfaceDrawContext* rtc) const {
SkASSERT(this->glyphCount() != 0);
const SkMatrix& drawMatrix = viewMatrix.localToDevice();
const SkPoint drawOrigin = glyphRunList.origin();
// We can clip geometrically using clipRect and ignore clip if we're not using SDFs or
// transformed glyphs, and we have an axis-aligned rectangular non-AA clip.
SkIRect clipRect = SkIRect::MakeEmpty();
// We only need to do clipping work if the SubRun isn't contained by the clip
// We can clip geometrically using clipRect and ignore clip when an axis-aligned rectangular
// non-AA clip is used. If clipRect is empty, and clip is nullptr, then there is no clipping
// needed.
const SkRect subRunBounds = this->deviceRect(drawMatrix, drawOrigin);
const SkRect renderTargetBounds = SkRect::MakeWH(rtc->width(), rtc->height());
const SkRect deviceBounds = SkRect::MakeWH(rtc->width(), rtc->height());
auto [clipMethod, clipRect] = calculate_clip(clip, deviceBounds, subRunBounds);
if (clip == nullptr && !renderTargetBounds.intersects(subRunBounds)) {
// If the SubRun is completely outside, don't add an op for it.
return {nullptr, nullptr};
} else if (clip != nullptr) {
switch (auto result = clip->preApply(subRunBounds, GrAA::kNo); result.fEffect) {
case GrClip::Effect::kClippedOut:
// Return nullptr op to indicate no op needed.
return {nullptr, nullptr};
case GrClip::Effect::kUnclipped:
clipRect = SkIRect::MakeEmpty();
clip = nullptr;
break;
case GrClip::Effect::kClipped: {
if (result.fIsRRect && result.fRRect.isRect()) {
SkRect r = result.fRRect.rect();
if (result.fAA == GrAA::kNo || GrClip::IsPixelAligned(r)) {
// Clip geometrically during onPrepare using clipRect.
r.round(&clipRect);
if (clipRect.contains(subRunBounds)) {
// If fully within the clip, signal no clipping using the empty rect.
clipRect = SkIRect::MakeEmpty();
}
clip = nullptr;
}
}
}
switch (clipMethod) {
case kClippedOut:
// Returning nullptr as op means skip this op.
return {nullptr, nullptr};
case kUnclipped:
case kGeometryClipped:
// GPU clip is not needed.
clip = nullptr;
break;
case kGPUClipped:
// Use the the GPU clip; clipRect is ignored.
break;
}
}
if (!clipRect.isEmpty()) { SkASSERT(clip == nullptr); }