/* * Copyright 2006 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file.
*/
static SkIRect safeRoundOut(const SkRect& src) { // roundOut will pin huge floats to max/min int
SkIRect dst = src.roundOut();
// intersect with a smaller huge rect, so the rect will not be considered empty for being // too large. e.g. { -SK_MaxS32 ... SK_MaxS32 } is considered empty because its width // exceeds signed 32bit. const int32_t limit = SK_MaxS32 >> SK_SUPERSAMPLE_SHIFT;
(void)dst.intersect({ -limit, -limit, limit, limit});
return dst;
}
staticint overflows_short_shift(int value, int shift) { constint s = 16 + shift; return (SkLeftShift(value, s) >> s) - value;
}
/** Would any of the coordinates of this rectangle not fit in a short, when left-shifted by shift?
*/ staticint rect_overflows_short_shift(SkIRect rect, int shift) {
SkASSERT(!overflows_short_shift(8191, shift));
SkASSERT(overflows_short_shift(8192, shift));
SkASSERT(!overflows_short_shift(32767, 0));
SkASSERT(overflows_short_shift(32768, 0));
// Since we expect these to succeed, we bit-or together // for a tiny extra bit of speed. return overflows_short_shift(rect.fLeft, shift) |
overflows_short_shift(rect.fRight, shift) |
overflows_short_shift(rect.fTop, shift) |
overflows_short_shift(rect.fBottom, shift);
}
constbool isInverse = path.isInverseFillType();
SkIRect ir = safeRoundOut(path.getBounds()); if (ir.isEmpty()) { if (isInverse) {
blitter->blitRegion(origClip);
} return;
}
// If the intersection of the path bounds and the clip bounds // will overflow 32767 when << by SHIFT, we can't supersample, // so draw without antialiasing.
SkIRect clippedIR; if (isInverse) { // If the path is an inverse fill, it's going to fill the entire // clip, and we care whether the entire clip exceeds our limits.
clippedIR = origClip.getBounds();
} else { if (!clippedIR.intersect(ir, origClip.getBounds())) { return;
}
} if (rect_overflows_short_shift(clippedIR, SK_SUPERSAMPLE_SHIFT)) {
SkScan::FillPath(path, origClip, blitter); return;
}
// Our antialiasing can't handle a clip larger than 32767, so we restrict // the clip to that limit here. (the runs[] uses int16_t for its index). // // A more general solution (one that could also eliminate the need to // disable aa based on ir bounds (see overflows_short_shift) would be // to tile the clip/target...
SkRegion tmpClipStorage; const SkRegion* clipRgn = &origClip;
{ staticconst int32_t kMaxClipCoord = 32767; const SkIRect& bounds = origClip.getBounds(); if (bounds.fRight > kMaxClipCoord || bounds.fBottom > kMaxClipCoord) {
SkIRect limit = { 0, 0, kMaxClipCoord, kMaxClipCoord };
tmpClipStorage.op(origClip, limit, SkRegion::kIntersect_Op);
clipRgn = &tmpClipStorage;
}
} // for here down, use clipRgn, not origClip
SkScanClipper clipper(blitter, clipRgn, ir);
if (clipper.getBlitter() == nullptr) { // clipped out if (isInverse) {
blitter->blitRegion(*clipRgn);
} return;
}
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.