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:
parent
420a75d685
commit
b34d62ba9a
@ -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); }
|
||||
|
Loading…
Reference in New Issue
Block a user