/* * Copyright 2012 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file.
*/ #include"src/pathops/SkOpEdgeBuilder.h"
bool SkOpEdgeBuilder::walk() {
uint8_t* verbPtr = fPathVerbs.begin();
uint8_t* endOfFirstHalf = &verbPtr[fSecondHalf];
SkPoint* pointsPtr = fPathPts.begin();
SkScalar* weightPtr = fWeights.begin();
SkPath::Verb verb;
SkOpContour* contour = fContourBuilder.contour(); int moveToPtrBump = 0; while ((verb = (SkPath::Verb) *verbPtr) != SkPath::kDone_Verb) { if (verbPtr == endOfFirstHalf) {
fOperand = true;
}
verbPtr++; switch (verb) { case SkPath::kMove_Verb: if (contour && contour->count()) { if (fAllowOpenContours) {
complete();
} elseif (!close()) { returnfalse;
}
} if (!contour) {
fContourBuilder.setContour(contour = fContoursHead->appendContour());
}
contour->init(fGlobalState, fOperand,
fXorMask[fOperand] == kEvenOdd_PathOpsMask);
pointsPtr += moveToPtrBump;
moveToPtrBump = 1; continue; case SkPath::kLine_Verb:
fContourBuilder.addLine(pointsPtr); break; case SkPath::kQuad_Verb:
{
SkVector vec1 = pointsPtr[1] - pointsPtr[0];
SkVector vec2 = pointsPtr[2] - pointsPtr[1]; if (vec1.dot(vec2) < 0) {
SkPoint pair[5]; if (SkChopQuadAtMaxCurvature(pointsPtr, pair) == 1) { goto addOneQuad;
} if (!SkIsFinite(&pair[0].fX, std::size(pair) * 2)) { returnfalse;
} for (unsigned index = 0; index < std::size(pair); ++index) {
pair[index] = force_small_to_zero(pair[index]);
}
SkPoint cStorage[2][2];
SkPath::Verb v1 = SkReduceOrder::Quad(&pair[0], cStorage[0]);
SkPath::Verb v2 = SkReduceOrder::Quad(&pair[2], cStorage[1]);
SkPoint* curve1 = v1 != SkPath::kLine_Verb ? &pair[0] : cStorage[0];
SkPoint* curve2 = v2 != SkPath::kLine_Verb ? &pair[2] : cStorage[1]; if (can_add_curve(v1, curve1) && can_add_curve(v2, curve2)) {
fContourBuilder.addCurve(v1, curve1);
fContourBuilder.addCurve(v2, curve2); break;
}
}
}
addOneQuad:
fContourBuilder.addQuad(pointsPtr); break; case SkPath::kConic_Verb: {
SkVector vec1 = pointsPtr[1] - pointsPtr[0];
SkVector vec2 = pointsPtr[2] - pointsPtr[1];
SkScalar weight = *weightPtr++; if (vec1.dot(vec2) < 0) { // FIXME: max curvature for conics hasn't been implemented; use placeholder
SkScalar maxCurvature = SkFindQuadMaxCurvature(pointsPtr); if (0 < maxCurvature && maxCurvature < 1) {
SkConic conic(pointsPtr, weight);
SkConic pair[2]; if (!conic.chopAt(maxCurvature, pair)) { // if result can't be computed, use original
fContourBuilder.addConic(pointsPtr, weight); break;
}
SkPoint cStorage[2][3];
SkPath::Verb v1 = SkReduceOrder::Conic(pair[0], cStorage[0]);
SkPath::Verb v2 = SkReduceOrder::Conic(pair[1], cStorage[1]);
SkPoint* curve1 = v1 != SkPath::kLine_Verb ? pair[0].fPts : cStorage[0];
SkPoint* curve2 = v2 != SkPath::kLine_Verb ? pair[1].fPts : cStorage[1]; if (can_add_curve(v1, curve1) && can_add_curve(v2, curve2)) {
fContourBuilder.addCurve(v1, curve1, pair[0].fW);
fContourBuilder.addCurve(v2, curve2, pair[1].fW); break;
}
}
}
fContourBuilder.addConic(pointsPtr, weight);
} break; case SkPath::kCubic_Verb:
{ // Split complex cubics (such as self-intersecting curves or // ones with difficult curvature) in two before proceeding. // This can be required for intersection to succeed.
SkScalar splitT[3]; int breaks = SkDCubic::ComplexBreak(pointsPtr, splitT); if (!breaks) {
fContourBuilder.addCubic(pointsPtr); break;
}
SkASSERT(breaks <= (int) std::size(splitT)); struct Splitsville { double fT[2];
SkPoint fPts[4];
SkPoint fReduced[4];
SkPath::Verb fVerb; bool fCanAdd;
} splits[4];
SkASSERT(std::size(splits) == std::size(splitT) + 1);
SkTQSort(splitT, splitT + breaks); for (int index = 0; index <= breaks; ++index) {
Splitsville* split = &splits[index];
split->fT[0] = index ? splitT[index - 1] : 0;
split->fT[1] = index < breaks ? splitT[index] : 1;
SkDCubic part = SkDCubic::SubDivide(pointsPtr, split->fT[0], split->fT[1]); if (!part.toFloatPoints(split->fPts)) { returnfalse;
}
split->fVerb = SkReduceOrder::Cubic(split->fPts, split->fReduced);
SkPoint* curve = SkPath::kCubic_Verb == split->fVerb
? split->fPts : split->fReduced;
split->fCanAdd = can_add_curve(split->fVerb, curve);
} for (int index = 0; index <= breaks; ++index) {
Splitsville* split = &splits[index]; if (!split->fCanAdd) { continue;
} int prior = index; while (prior > 0 && !splits[prior - 1].fCanAdd) {
--prior;
} if (prior < index) {
split->fT[0] = splits[prior].fT[0];
split->fPts[0] = splits[prior].fPts[0];
} int next = index; int breakLimit = std::min(breaks, (int) std::size(splits) - 1); while (next < breakLimit && !splits[next + 1].fCanAdd) {
++next;
} if (next > index) {
split->fT[1] = splits[next].fT[1];
split->fPts[3] = splits[next].fPts[3];
} if (prior < index || next > index) {
split->fVerb = SkReduceOrder::Cubic(split->fPts, split->fReduced);
}
SkPoint* curve = SkPath::kCubic_Verb == split->fVerb
? split->fPts : split->fReduced; if (!can_add_curve(split->fVerb, curve)) { returnfalse;
}
fContourBuilder.addCurve(split->fVerb, curve);
}
} break; case SkPath::kClose_Verb:
SkASSERT(contour); if (!close()) { returnfalse;
}
contour = nullptr; continue; default:
SkDEBUGFAIL("bad verb"); returnfalse;
}
SkASSERT(contour); if (contour->count()) {
contour->debugValidate();
}
pointsPtr += SkPathOpsVerbToPoints(verb);
}
fContourBuilder.flush(); if (contour && contour->count() &&!fAllowOpenContours && !close()) { returnfalse;
} returntrue;
}
Messung V0.5
¤ 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.0.1Bemerkung:
(vorverarbeitet)
¤
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.