SkEdgeBuilder::Combine SkBasicEdgeBuilder::combineVertical(const SkEdge* edge, SkEdge* last) { // We only consider edges that were originally lines to be vertical to avoid numerical issues // (crbug.com/1154864). if (last->fEdgeType != SkEdge::Type::kLine || last->fDxDy || edge->fX != last->fX) { return kNo_Combine;
} if (edge->fWinding == last->fWinding) { if (edge->fLastY + 1 == last->fFirstY) {
last->fFirstY = edge->fFirstY; return kPartial_Combine;
} if (edge->fFirstY == last->fLastY + 1) {
last->fLastY = edge->fLastY; return kPartial_Combine;
} return kNo_Combine;
} if (edge->fFirstY == last->fFirstY) { if (edge->fLastY == last->fLastY) { return kTotal_Combine;
} if (edge->fLastY < last->fLastY) {
last->fFirstY = edge->fLastY + 1; return kPartial_Combine;
}
last->fFirstY = last->fLastY + 1;
last->fLastY = edge->fLastY;
last->fWinding = edge->fWinding; return kPartial_Combine;
} if (edge->fLastY == last->fLastY) { if (edge->fFirstY > last->fFirstY) {
last->fLastY = edge->fFirstY - 1; return kPartial_Combine;
}
last->fLastY = last->fFirstY - 1;
last->fFirstY = edge->fFirstY;
last->fWinding = edge->fWinding; return kPartial_Combine;
} return kNo_Combine;
}
SkEdgeBuilder::Combine SkAnalyticEdgeBuilder::combineVertical(const SkAnalyticEdge* edge,
SkAnalyticEdge* last) { auto approximately_equal = [](SkFixed a, SkFixed b) { return SkAbs32(a - b) < 0x100;
};
// We only consider edges that were originally lines to be vertical to avoid numerical issues // (crbug.com/1154864). if (last->fEdgeType != SkAnalyticEdge::Type::kLine || last->fDX || edge->fX != last->fX) { return kNo_Combine;
} if (edge->fWinding == last->fWinding) { if (edge->fLowerY == last->fUpperY) {
last->fUpperY = edge->fUpperY;
last->fY = last->fUpperY; return kPartial_Combine;
} if (approximately_equal(edge->fUpperY, last->fLowerY)) {
last->fLowerY = edge->fLowerY; return kPartial_Combine;
} return kNo_Combine;
} if (approximately_equal(edge->fUpperY, last->fUpperY)) { if (approximately_equal(edge->fLowerY, last->fLowerY)) { return kTotal_Combine;
} if (edge->fLowerY < last->fLowerY) {
last->fUpperY = edge->fLowerY;
last->fY = last->fUpperY; return kPartial_Combine;
}
last->fUpperY = last->fLowerY;
last->fY = last->fUpperY;
last->fLowerY = edge->fLowerY;
last->fWinding = edge->fWinding; return kPartial_Combine;
} if (approximately_equal(edge->fLowerY, last->fLowerY)) { if (edge->fUpperY > last->fUpperY) {
last->fLowerY = edge->fUpperY; return kPartial_Combine;
}
last->fLowerY = last->fUpperY;
last->fUpperY = edge->fUpperY;
last->fY = last->fUpperY;
last->fWinding = edge->fWinding; return kPartial_Combine;
} return kNo_Combine;
}
staticbool is_vertical(const SkEdge* edge) { // We only consider edges that were originally lines to be vertical to avoid numerical issues // (crbug.com/1154864). return edge->fDxDy == 0
&& edge->fEdgeType == SkEdge::Type::kLine;
}
staticbool is_vertical(const SkAnalyticEdge* edge) { // We only consider edges that were originally lines to be vertical to avoid numerical issues // (crbug.com/1154864). return edge->fDX == 0
&& edge->fEdgeType == SkAnalyticEdge::Type::kLine;
}
// TODO: we can deallocate the edge if edge->setFoo() fails // or when we don't use it (kPartial_Combine or kTotal_Combine).
// TODO: maybe get rid of buildPoly() entirely? int SkEdgeBuilder::buildPoly(const SkPathRaw& raw, const SkIRect* iclip, bool canCullToTheRight) {
size_t maxEdgeCount = raw.fPoints.size(); if (iclip) { // clipping can turn 1 line into (up to) kMaxClippedLineSegments, since // we turn portions that are clipped out on the left/right into vertical // segments.
SkSafeMath safe;
maxEdgeCount = safe.mul(maxEdgeCount, SkLineClipper::kMaxClippedLineSegments); if (!safe) { return0;
}
}
SkPathEdgeIter iter(raw); if (iclip) {
SkRect clip = this->recoverClip(*iclip);
while (auto e = iter.next()) { switch (e.fEdge) { case SkPathEdgeIter::Edge::kLine: {
SkPoint lines[SkLineClipper::kMaxPoints]; int lineCount = SkLineClipper::ClipLine(e.fPts, clip, lines, canCullToTheRight);
SkASSERT(lineCount <= SkLineClipper::kMaxClippedLineSegments); for (int i = 0; i < lineCount; i++) {
this->addLine(lines + i);
} break;
} default:
SkDEBUGFAIL("unexpected verb"); break;
}
}
} else { while (auto e = iter.next()) { switch (e.fEdge) { case SkPathEdgeIter::Edge::kLine: {
this->addLine(e.fPts); break;
} default:
SkDEBUGFAIL("unexpected verb"); break;
}
}
}
fEdgeList = fList.begin(); return fList.size();
}
SkPathEdgeIter iter(raw);
SkAutoConicToQuads quadder;
constexpr float kConicTol = 0.25f;
SkPoint monoY[10];
SkPoint monoX[5]; auto handle_quad = [this, &monoX](const SkPoint pts[3]) { int n = SkChopQuadAtYExtrema(pts, monoX); for (int i = 0; i <= n; i++) {
this->addQuad(&monoX[i * 2]);
}
};
while (auto e = iter.next()) { switch (e.fEdge) { case SkPathEdgeIter::Edge::kLine:
this->addLine(e.fPts); break; case SkPathEdgeIter::Edge::kQuad: {
handle_quad(e.fPts); break;
} case SkPathEdgeIter::Edge::kConic: { const SkPoint* quadPts =
quadder.computeQuads(e.fPts, iter.conicWeight(), kConicTol); for (int i = 0; i < quadder.countQuads(); ++i) {
handle_quad(quadPts);
quadPts += 2;
}
} break; case SkPathEdgeIter::Edge::kCubic: { int n = SkChopCubicAtYExtrema(e.fPts, monoY); for (int i = 0; i <= n; i++) {
this->addCubic(&monoY[i * 3]);
} break;
} default:
SkDEBUGFAIL("Unknown edge type"); break;
}
}
fEdgeList = fList.begin(); return fList.size();
}
int SkEdgeBuilder::buildEdges(const SkPathRaw& raw, const SkIRect* shiftedClip) { // If we're convex, then we need both edges, even if the right edge is past the clip. constbool canCullToTheRight = !raw.isKnownToBeConvex();
// We can use our buildPoly() optimization if all the segments are lines. // (Edges are homogeneous and stored contiguously in memory, no need for indirection.) constint count = SkPath::kLine_SegmentMask == raw.segmentMasks()
? this->buildPoly(raw, shiftedClip, canCullToTheRight)
: this->build (raw, shiftedClip, canCullToTheRight);
SkASSERT(count >= 0);
// If we can't cull to the right, we should have count > 1 (or 0). if (!canCullToTheRight) {
SkASSERT(count != 1);
} return count;
}
int SkEdgeBuilder::buildEdges(const SkPath& path, const SkIRect* shiftedClip) { if (auto raw = SkPathPriv::Raw(path, SkResolveConvexity::kYes)) { return buildEdges(*raw, shiftedClip);
} return0; // no edges were built
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-08-26)
¤
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.