static bool verify_query(SkIRect query, DataRect rects[], SkTDArray<void*>& found) { SkTDArray<void*> expected; // manually intersect with every rectangle for (int i = 0; i < NUM_RECTS; ++i) { if (SkIRect::IntersectsNoEmptyCheck(query, rects[i].rect)) { expected.push(rects[i].data); } } if (expected.count() != found.count()) { return false; } if (0 == expected.count()) { return true; } // Just cast to long since sorting by the value of the void*'s was being problematic... SkTQSort(reinterpret_cast<long*>(expected.begin()), reinterpret_cast<long*>(expected.end() - 1)); SkTQSort(reinterpret_cast<long*>(found.begin()), reinterpret_cast<long*>(found.end() - 1)); return found == expected; }
bool ActiveTrapezoids::withinActiveTrapezoid(const SkPoint &pt, Trapezoid **trap) { DebugPrintf("Entering withinActiveTrapezoid()\n"); // This is where a good search data structure would be helpful. Trapezoid **t; for (t = fTrapezoids.begin(); t < fTrapezoids.end(); ++t) { if ((**t).left()->compare(pt) <= 0) { // The point is to the left of the left edge of this trapezoid. DebugPrintf("withinActiveTrapezoid: Before a trapezoid\n"); *trap = *t; // Return the place where a new trapezoid would go. // We have a bug with the sorting -- look through everything. continue; // return false; // Outside all trapezoids, since they are sorted. } // The point is to the right of the left edge of this trapezoid. if ((**t).right()->compare(pt) < 0) { // The point is to the left of the right edge. DebugPrintf("withinActiveTrapezoid: Within an Active Trapezoid\n"); *trap = *t; return true; } } // The point is to the right of all trapezoids. DebugPrintf("withinActiveTrapezoid: After all trapezoids\n"); *trap = NULL; return false; }
void SkSVGParser::Delete(SkTDArray<SkSVGElement*>& fChildren) { SkSVGElement** ptr; for (ptr = fChildren.begin(); ptr < fChildren.end(); ptr++) { Delete((*ptr)->fChildren); delete *ptr; } }
void operate(const SkPath& one, const SkPath& two, ShapeOp op, SkPath& result) { result.reset(); result.setFillType(SkPath::kEvenOdd_FillType); // turn path into list of segments SkTArray<Op::Contour> contours; // FIXME: add self-intersecting cubics' T values to segment Op::EdgeBuilder builder(one, contours); const int aXorMask = builder.xorMask(); builder.addOperand(two); const int bXorMask = builder.xorMask(); builder.finish(); SkTDArray<Op::Contour*> contourList; makeContourList(contours, contourList); Op::Contour** currentPtr = contourList.begin(); if (!currentPtr) { return; } Op::Contour** listEnd = contourList.end(); // find all intersections between segments do { Op::Contour** nextPtr = currentPtr; Op::Contour* current = *currentPtr++; Op::Contour* next; do { next = *nextPtr++; } while (addIntersectTs(current, next) && nextPtr != listEnd); } while (currentPtr != listEnd); // eat through coincident edges coincidenceCheck(contourList); fixOtherTIndex(contourList); // construct closed contours Op::PathWrapper wrapper(result); bridgeOp(contourList, op, aXorMask, bXorMask, wrapper); }
virtual bool onClick(Click* click) { if (Click::kUp_State == click->fState) { if (click->isType("maker")) { if (SkPoint::Distance(click->fOrig, click->fCurr) > SkIntToScalar(3)) { *fList.append() = fDraw; } else { fDraw->unref(); } fDraw = NULL; } return true; } if (Click::kDown_State == click->fState) { SkPaint p = fFactory->getPaint(); p.setColor(this->randColor()); fFactory->setPaint(p); } if (click->isType("maker")) { this->setDraw(fFactory->create(click->fOrig, click->fCurr))->unref(); } else if (click->isType("dragger")) { for (Draw** iter = fList.begin(); iter < fList.end(); iter++) { if ((*iter)->isSelected()) { (*iter)->offset(click->fCurr.x() - click->fPrev.x(), click->fCurr.y() - click->fPrev.y()); } } } this->inval(NULL); return true; }
bool SortContourList(SkOpContourHead** contourList, bool evenOdd, bool oppEvenOdd) { SkTDArray<SkOpContour* > list; SkOpContour* contour = *contourList; do { if (contour->count()) { contour->setOppXor(contour->operand() ? evenOdd : oppEvenOdd); *list.append() = contour; } } while ((contour = contour->next())); int count = list.count(); if (!count) { return false; } if (count > 1) { SkTQSort<SkOpContour>(list.begin(), list.end() - 1); } contour = list[0]; SkOpContourHead* contourHead = static_cast<SkOpContourHead*>(contour); contour->globalState()->setContourHead(contourHead); *contourList = contourHead; for (int index = 1; index < count; ++index) { SkOpContour* next = list[index]; contour->setNext(next); contour = next; } contour->setNext(nullptr); return true; }
void ActiveTrapezoids::insert(Trapezoid *t) { Trapezoid **tp; for (tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp) if (**tp > *t) break; fTrapezoids.insert(tp - fTrapezoids.begin(), 1, &t); // SHOULD VERIFY THAT ALL TRAPEZOIDS ARE PROPERLY SORTED }
Draw* hitTestList(SkScalar x, SkScalar y) const { Draw** first = fList.begin(); for (Draw** iter = fList.end(); iter > first;) { --iter; if ((*iter)->hitTest(x, y)) { return *iter; } } return NULL; }
virtual void onDraw(SkCanvas* canvas) { this->drawBG(canvas); for (Draw** iter = fList.begin(); iter < fList.end(); iter++) { (*iter)->draw(canvas); } if (fDraw) { fDraw->draw(canvas); } }
virtual void onDraw(SkCanvas* canvas) { this->drawBG(canvas); test_clearonlayers(canvas); return; // test_strokerect(canvas); return; for (Draw** iter = fList.begin(); iter < fList.end(); iter++) { (*iter)->draw(canvas); } if (fDraw) { fDraw->draw(canvas); } }
void ActiveTrapezoids::remove(Trapezoid *t) { DebugPrintf("Removing a trapezoid..."); for (Trapezoid **tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp) { if (*tp == t) { fTrapezoids.remove(tp - fTrapezoids.begin()); DebugPrintf(" done.\n"); return; } } DebugPrintf(" Arghh! Panic!\n"); SkASSERT(t == 0); // Cannot find t in active trapezoid list. }
static void encodeFound(TestState& state) { if (verbose()) { if (state.fPixelWorst.count()) { SkTDArray<SortByPixel*> worst; for (int index = 0; index < state.fPixelWorst.count(); ++index) { *worst.append() = &state.fPixelWorst[index]; } SkTQSort<SortByPixel>(worst.begin(), worst.end() - 1); for (int index = 0; index < state.fPixelWorst.count(); ++index) { const TestResult& result = *worst[index]; SkDebugf("%d %s pixelError=%d\n", result.fDirNo, result.fFilename, result.fPixelError); } } if (state.fSlowest.count()) { SkTDArray<SortByTime*> slowest; for (int index = 0; index < state.fSlowest.count(); ++index) { *slowest.append() = &state.fSlowest[index]; } if (slowest.count() > 0) { SkTQSort<SortByTime>(slowest.begin(), slowest.end() - 1); for (int index = 0; index < slowest.count(); ++index) { const TestResult& result = *slowest[index]; SkDebugf("%d %s time=%d\n", result.fDirNo, result.fFilename, result.fTime); } } } } TestRunner testRunner; for (int index = 0; index < state.fPixelWorst.count(); ++index) { const TestResult& result = state.fPixelWorst[index]; SkString filename(result.fFilename); if (!filename.endsWith(".skp")) { filename.append(".skp"); } *testRunner.fRunnables.append() = new TestRunnableEncode(&testSkpClipEncode, result.fDirNo, filename.c_str(), &testRunner); } testRunner.render(); }
bool SkConcaveToTriangles(size_t numPts, const SkPoint pts[], SkTDArray<SkPoint> *triangles) { DebugPrintf("SkConcaveToTriangles()\n"); SkTDArray<Vertex> vertices; vertices.setCount(numPts); if (!ConvertPointsToVertices(numPts, pts, vertices.begin())) return false; triangles->setReserve(numPts); triangles->setCount(0); return Triangulate(vertices.begin(), vertices.end() - 1, triangles); }
// FIXME : add this as a member of SkPath void Simplify(const SkPath& path, SkPath* result) { #if DEBUG_SORT || DEBUG_SWAP_TOP gDebugSortCount = gDebugSortCountDefault; #endif // returns 1 for evenodd, -1 for winding, regardless of inverse-ness result->reset(); result->setFillType(SkPath::kEvenOdd_FillType); SkPathWriter simple(*result); // turn path into list of segments SkTArray<SkOpContour> contours; SkOpEdgeBuilder builder(path, contours); builder.finish(); SkTDArray<SkOpContour*> contourList; MakeContourList(contours, contourList, false, false); SkOpContour** currentPtr = contourList.begin(); if (!currentPtr) { return; } SkOpContour** listEnd = contourList.end(); // find all intersections between segments do { SkOpContour** nextPtr = currentPtr; SkOpContour* current = *currentPtr++; if (current->containsCubics()) { AddSelfIntersectTs(current); } SkOpContour* next; do { next = *nextPtr++; } while (AddIntersectTs(current, next) && nextPtr != listEnd); } while (currentPtr != listEnd); // eat through coincident edges CoincidenceCheck(&contourList, 0); FixOtherTIndex(&contourList); SortSegments(&contourList); #if DEBUG_ACTIVE_SPANS DebugShowActiveSpans(contourList); #endif // construct closed contours if (builder.xorMask() == kWinding_PathOpsMask ? bridgeWinding(contourList, &simple) : !bridgeXor(contourList, &simple)) { // if some edges could not be resolved, assemble remaining fragments SkPath temp; temp.setFillType(SkPath::kEvenOdd_FillType); SkPathWriter assembled(temp); Assemble(simple, &assembled); *result = *assembled.nativePath(); } }
virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) { for (Draw** iter = fList.begin(); iter < fList.end(); iter++) { (*iter)->setSelected(false); } Click* c = new Click(this); Draw* d = this->hitTestList(x, y); if (d) { d->setSelected(true); c->setType("dragger"); } else { c->setType("maker"); } return c; }
template <typename T> void SkRTConfRegistry::set(const char *name, T value) { SkTDArray<SkRTConfBase *> *confArray; if (!fConfs.find(name, &confArray)) { SkDebugf("WARNING: Attempting to set configuration value \"%s\", but I've never heard of that.\n", name); return; } for (SkRTConfBase **confBase = confArray->begin(); confBase != confArray->end(); confBase++) { // static_cast here is okay because there's only one kind of child class. SkRTConf<T> *concrete = static_cast<SkRTConf<T> *>(*confBase); if (concrete) { concrete->set(value); } } }
Trapezoid* ActiveTrapezoids::getTrapezoidWithEdge(const Vertex *edge) { DebugPrintf("Entering getTrapezoidWithEdge(): looking through %d\n", fTrapezoids.count()); DebugPrintf("trying to find %p: ", edge); Trapezoid **tp; for (tp = fTrapezoids.begin(); tp < fTrapezoids.end(); ++tp) { SkASSERT(tp != NULL); SkASSERT(*tp != NULL); DebugPrintf("%p and %p, ", (**tp).left(), (**tp).right()); if ((**tp).left() == edge || (**tp).right() == edge) { DebugPrintf("\ngetTrapezoidWithEdge found the trapezoid\n"); return *tp; } } DebugPrintf("getTrapezoidWithEdge found no trapezoid\n"); return NULL; }
bool SkAnimatorScript::EvalRGB(const char* function, size_t len, SkTDArray<SkScriptValue>& params, void* eng, SkScriptValue* value) { if (SK_LITERAL_STR_EQUAL("rgb", function, len) == false) return false; if (params.count() != 3) return false; SkScriptEngine* engine = (SkScriptEngine*) eng; unsigned result = 0xFF000000; int shift = 16; for (SkScriptValue* valuePtr = params.begin(); valuePtr < params.end(); valuePtr++) { engine->convertTo(SkType_Int, valuePtr); result |= SkClampMax(valuePtr->fOperand.fS32, 255) << shift; shift -= 8; } value->fOperand.fS32 = result; value->fType = SkType_Int; return true; }
void SkRecordDraw(const SkRecord& record, SkCanvas* canvas, const SkBBoxHierarchy* bbh, SkDrawPictureCallback* callback) { SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); if (NULL != bbh) { // Draw only ops that affect pixels in the canvas's current clip. SkIRect devBounds; canvas->getClipDeviceBounds(&devBounds); SkTDArray<void*> ops; bbh->search(devBounds, &ops); // FIXME: QuadTree doesn't send these back in the order we inserted them. :( // Also remove the sort in SkPictureData::getActiveOps()? if (ops.count() > 0) { SkTQSort(ops.begin(), ops.end() - 1, SkTCompareLT<void*>()); } SkRecords::Draw draw(canvas); for (int i = 0; i < ops.count(); i++) { if (NULL != callback && callback->abortDrawing()) { return; } record.visit<void>((uintptr_t)ops[i], draw); // See FillBounds below. } } else { // Draw all ops. for (SkRecords::Draw draw(canvas); draw.index() < record.count(); draw.next()) { if (NULL != callback && callback->abortDrawing()) { return; } record.visit<void>(draw.index(), draw); } } }
/* check start and end of each contour if not the same, record them match them up connect closest reassemble contour pieces into new path */ void Assemble(const SkPathWriter& path, SkPathWriter* simple) { SkChunkAlloc allocator(4096); // FIXME: constant-ize, tune SkOpContourHead contour; SkOpGlobalState globalState(nullptr, &contour SkDEBUGPARAMS(nullptr)); #if DEBUG_SHOW_TEST_NAME SkDebugf("</div>\n"); #endif #if DEBUG_PATH_CONSTRUCTION SkDebugf("%s\n", __FUNCTION__); #endif SkOpEdgeBuilder builder(path, &contour, &allocator, &globalState); builder.finish(&allocator); SkTDArray<const SkOpContour* > runs; // indices of partial contours const SkOpContour* eContour = builder.head(); do { if (!eContour->count()) { continue; } const SkPoint& eStart = eContour->start(); const SkPoint& eEnd = eContour->end(); #if DEBUG_ASSEMBLE SkDebugf("%s contour", __FUNCTION__); if (!SkDPoint::ApproximatelyEqual(eStart, eEnd)) { SkDebugf("[%d]", runs.count()); } else { SkDebugf(" "); } SkDebugf(" start=(%1.9g,%1.9g) end=(%1.9g,%1.9g)\n", eStart.fX, eStart.fY, eEnd.fX, eEnd.fY); #endif if (SkDPoint::ApproximatelyEqual(eStart, eEnd)) { eContour->toPath(simple); continue; } *runs.append() = eContour; } while ((eContour = eContour->next())); int count = runs.count(); if (count == 0) { return; } SkTDArray<int> sLink, eLink; sLink.append(count); eLink.append(count); int rIndex, iIndex; for (rIndex = 0; rIndex < count; ++rIndex) { sLink[rIndex] = eLink[rIndex] = SK_MaxS32; } const int ends = count * 2; // all starts and ends const int entries = (ends - 1) * count; // folded triangle : n * (n - 1) / 2 SkTDArray<double> distances; distances.append(entries); for (rIndex = 0; rIndex < ends - 1; ++rIndex) { const SkOpContour* oContour = runs[rIndex >> 1]; const SkPoint& oPt = rIndex & 1 ? oContour->end() : oContour->start(); const int row = rIndex < count - 1 ? rIndex * ends : (ends - rIndex - 2) * ends - rIndex - 1; for (iIndex = rIndex + 1; iIndex < ends; ++iIndex) { const SkOpContour* iContour = runs[iIndex >> 1]; const SkPoint& iPt = iIndex & 1 ? iContour->end() : iContour->start(); double dx = iPt.fX - oPt.fX; double dy = iPt.fY - oPt.fY; double dist = dx * dx + dy * dy; distances[row + iIndex] = dist; // oStart distance from iStart } } SkTDArray<int> sortedDist; sortedDist.append(entries); for (rIndex = 0; rIndex < entries; ++rIndex) { sortedDist[rIndex] = rIndex; } SkTQSort<int>(sortedDist.begin(), sortedDist.end() - 1, DistanceLessThan(distances.begin())); int remaining = count; // number of start/end pairs for (rIndex = 0; rIndex < entries; ++rIndex) { int pair = sortedDist[rIndex]; int row = pair / ends; int col = pair - row * ends; int thingOne = row < col ? row : ends - row - 2; int ndxOne = thingOne >> 1; bool endOne = thingOne & 1; int* linkOne = endOne ? eLink.begin() : sLink.begin(); if (linkOne[ndxOne] != SK_MaxS32) { continue; } int thingTwo = row < col ? col : ends - row + col - 1; int ndxTwo = thingTwo >> 1; bool endTwo = thingTwo & 1; int* linkTwo = endTwo ? eLink.begin() : sLink.begin(); if (linkTwo[ndxTwo] != SK_MaxS32) { continue; } SkASSERT(&linkOne[ndxOne] != &linkTwo[ndxTwo]); bool flip = endOne == endTwo; linkOne[ndxOne] = flip ? ~ndxTwo : ndxTwo; linkTwo[ndxTwo] = flip ? ~ndxOne : ndxOne; if (!--remaining) { break; } } SkASSERT(!remaining); #if DEBUG_ASSEMBLE for (rIndex = 0; rIndex < count; ++rIndex) { int s = sLink[rIndex]; int e = eLink[rIndex]; SkDebugf("%s %c%d <- s%d - e%d -> %c%d\n", __FUNCTION__, s < 0 ? 's' : 'e', s < 0 ? ~s : s, rIndex, rIndex, e < 0 ? 'e' : 's', e < 0 ? ~e : e); } #endif rIndex = 0; do { bool forward = true; bool first = true; int sIndex = sLink[rIndex]; SkASSERT(sIndex != SK_MaxS32); sLink[rIndex] = SK_MaxS32; int eIndex; if (sIndex < 0) { eIndex = sLink[~sIndex]; sLink[~sIndex] = SK_MaxS32; } else { eIndex = eLink[sIndex]; eLink[sIndex] = SK_MaxS32; } SkASSERT(eIndex != SK_MaxS32); #if DEBUG_ASSEMBLE SkDebugf("%s sIndex=%c%d eIndex=%c%d\n", __FUNCTION__, sIndex < 0 ? 's' : 'e', sIndex < 0 ? ~sIndex : sIndex, eIndex < 0 ? 's' : 'e', eIndex < 0 ? ~eIndex : eIndex); #endif do { const SkOpContour* contour = runs[rIndex]; if (first) { first = false; const SkPoint* startPtr = &contour->start(); simple->deferredMove(startPtr[0]); } if (forward) { contour->toPartialForward(simple); } else { contour->toPartialBackward(simple); } #if DEBUG_ASSEMBLE SkDebugf("%s rIndex=%d eIndex=%s%d close=%d\n", __FUNCTION__, rIndex, eIndex < 0 ? "~" : "", eIndex < 0 ? ~eIndex : eIndex, sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex)); #endif if (sIndex == ((rIndex != eIndex) ^ forward ? eIndex : ~eIndex)) { simple->close(); break; } if (forward) { eIndex = eLink[rIndex]; SkASSERT(eIndex != SK_MaxS32); eLink[rIndex] = SK_MaxS32; if (eIndex >= 0) { SkASSERT(sLink[eIndex] == rIndex); sLink[eIndex] = SK_MaxS32; } else { SkASSERT(eLink[~eIndex] == ~rIndex); eLink[~eIndex] = SK_MaxS32; } } else { eIndex = sLink[rIndex]; SkASSERT(eIndex != SK_MaxS32); sLink[rIndex] = SK_MaxS32; if (eIndex >= 0) { SkASSERT(eLink[eIndex] == rIndex); eLink[eIndex] = SK_MaxS32; } else { SkASSERT(sLink[~eIndex] == ~rIndex); sLink[~eIndex] = SK_MaxS32; } } rIndex = eIndex; if (rIndex < 0) { forward ^= 1; rIndex = ~rIndex; } } while (true); for (rIndex = 0; rIndex < count; ++rIndex) { if (sLink[rIndex] != SK_MaxS32) { break; } } } while (rIndex < count); #if DEBUG_ASSEMBLE for (rIndex = 0; rIndex < count; ++rIndex) { SkASSERT(sLink[rIndex] == SK_MaxS32); SkASSERT(eLink[rIndex] == SK_MaxS32); } #endif }
// intersect the end of the cubic with the other. Try lines from the end to control and opposite // end to determine range of t on opposite cubic. static bool intersectEnd(const Cubic& cubic1, bool start, const Cubic& cubic2, const _Rect& bounds2, Intersections& i) { // bool selfIntersect = cubic1 == cubic2; _Line line; int t1Index = start ? 0 : 3; line[0] = cubic1[t1Index]; // don't bother if the two cubics are connnected #if 0 if (!selfIntersect && (line[0].approximatelyEqual(cubic2[0]) || line[0].approximatelyEqual(cubic2[3]))) { return false; } #endif bool result = false; SkTDArray<double> tVals; // OPTIMIZE: replace with hard-sized array for (int index = 0; index < 4; ++index) { if (index == t1Index) { continue; } _Vector dxy1 = cubic1[index] - line[0]; dxy1 /= gPrecisionUnit; line[1] = line[0] + dxy1; _Rect lineBounds; lineBounds.setBounds(line); if (!bounds2.intersects(lineBounds)) { continue; } Intersections local; if (!intersect(cubic2, line, local)) { continue; } for (int idx2 = 0; idx2 < local.used(); ++idx2) { double foundT = local.fT[0][idx2]; if (approximately_less_than_zero(foundT) || approximately_greater_than_one(foundT)) { continue; } if (local.fPt[idx2].approximatelyEqual(line[0])) { if (i.swapped()) { // FIXME: insert should respect swap i.insert(foundT, start ? 0 : 1, line[0]); } else { i.insert(start ? 0 : 1, foundT, line[0]); } result = true; } else { *tVals.append() = local.fT[0][idx2]; } } } if (tVals.count() == 0) { return result; } QSort<double>(tVals.begin(), tVals.end() - 1); double tMin1 = start ? 0 : 1 - LINE_FRACTION; double tMax1 = start ? LINE_FRACTION : 1; int tIdx = 0; do { int tLast = tIdx; while (tLast + 1 < tVals.count() && roughly_equal(tVals[tLast + 1], tVals[tIdx])) { ++tLast; } double tMin2 = SkTMax(tVals[tIdx] - LINE_FRACTION, 0.0); double tMax2 = SkTMin(tVals[tLast] + LINE_FRACTION, 1.0); int lastUsed = i.used(); result |= intersect3(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i); if (lastUsed == i.used()) { tMin2 = SkTMax(tVals[tIdx] - (1.0 / gPrecisionUnit), 0.0); tMax2 = SkTMin(tVals[tLast] + (1.0 / gPrecisionUnit), 1.0); result |= intersect3(cubic1, tMin1, tMax1, cubic2, tMin2, tMax2, 1, i); } tIdx = tLast + 1; } while (tIdx < tVals.count()); return result; }
void SkDisplayMath::executeFunction(SkDisplayable* target, int index, SkTDArray<SkScriptValue>& parameters, SkDisplayTypes type, SkScriptValue* scriptValue) { if (scriptValue == NULL) return; SkASSERT(target == this); SkScriptValue* array = parameters.begin(); SkScriptValue* end = parameters.end(); SkScalar input = parameters[0].fOperand.fScalar; SkScalar scalarResult; switch (index) { case SK_FUNCTION(abs): scalarResult = SkScalarAbs(input); break; case SK_FUNCTION(acos): scalarResult = SkScalarACos(input); break; case SK_FUNCTION(asin): scalarResult = SkScalarASin(input); break; case SK_FUNCTION(atan): scalarResult = SkScalarATan2(input, SK_Scalar1); break; case SK_FUNCTION(atan2): scalarResult = SkScalarATan2(input, parameters[1].fOperand.fScalar); break; case SK_FUNCTION(ceil): scalarResult = SkIntToScalar(SkScalarCeil(input)); break; case SK_FUNCTION(cos): scalarResult = SkScalarCos(input); break; case SK_FUNCTION(exp): scalarResult = SkScalarExp(input); break; case SK_FUNCTION(floor): scalarResult = SkIntToScalar(SkScalarFloor(input)); break; case SK_FUNCTION(log): scalarResult = SkScalarLog(input); break; case SK_FUNCTION(max): scalarResult = -SK_ScalarMax; while (array < end) { scalarResult = SkMaxScalar(scalarResult, array->fOperand.fScalar); array++; } break; case SK_FUNCTION(min): scalarResult = SK_ScalarMax; while (array < end) { scalarResult = SkMinScalar(scalarResult, array->fOperand.fScalar); array++; } break; case SK_FUNCTION(pow): // not the greatest -- but use x^y = e^(y * ln(x)) scalarResult = SkScalarLog(input); scalarResult = SkScalarMul(parameters[1].fOperand.fScalar, scalarResult); scalarResult = SkScalarExp(scalarResult); break; case SK_FUNCTION(random): scalarResult = fRandom.nextUScalar1(); break; case SK_FUNCTION(round): scalarResult = SkIntToScalar(SkScalarRound(input)); break; case SK_FUNCTION(sin): scalarResult = SkScalarSin(input); break; case SK_FUNCTION(sqrt): { SkASSERT(parameters.count() == 1); SkASSERT(type == SkType_Float); scalarResult = SkScalarSqrt(input); } break; case SK_FUNCTION(tan): scalarResult = SkScalarTan(input); break; default: SkASSERT(0); scalarResult = SK_ScalarNaN; } scriptValue->fOperand.fScalar = scalarResult; scriptValue->fType = SkType_Float; }
// Enhance the polygon with trapezoids. bool ConvertPointsToVertices(size_t numPts, const SkPoint *pts, Vertex *vta) { DebugPrintf("ConvertPointsToVertices()\n"); // Clear everything. DebugPrintf("Zeroing vertices\n"); sk_bzero(vta, numPts * sizeof(*vta)); // Initialize vertices. DebugPrintf("Initializing vertices\n"); SetVertexPoints(numPts, pts, vta); InitializeVertexTopology(numPts, vta); PrintVertices(numPts, vta); SkTDArray<VertexPtr> vtptr; vtptr.setCount(numPts); for (int i = numPts; i-- != 0;) vtptr[i].vt = vta + i; PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta); DebugPrintf("Sorting vertrap ptr array [%d] %p %p\n", vtptr.count(), &vtptr[0], &vtptr[vtptr.count() - 1] ); // SkTHeapSort(vtptr.begin(), vtptr.count()); BubbleSort(vtptr.begin(), vtptr.count()); DebugPrintf("Done sorting\n"); PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta); DebugPrintf("Traversing sorted vertrap ptrs\n"); ActiveTrapezoids incompleteTrapezoids; for (VertexPtr *vtpp = vtptr.begin(); vtpp < vtptr.end(); ++vtpp) { DebugPrintf("%d: sorted vertrap %d\n", vtpp - vtptr.begin(), vtpp->vt - vta); Vertex *vt = vtpp->vt; Vertex *e0, *e1; Trapezoid *t; switch (vt->classify(&e0, &e1)) { case Vertex::MONOTONE: monotone: DebugPrintf("MONOTONE %d %d\n", e0 - vta, e1 - vta); // We should find one edge. t = incompleteTrapezoids.getTrapezoidWithEdge(e0); if (t == NULL) { // One of the edges is flat. DebugPrintf("Monotone: cannot find a trapezoid with e0: " "trying convex\n"); goto convex; } t->setBottom(vt); // This trapezoid is now complete. incompleteTrapezoids.remove(t); if (e0 == t->left()) // Replace the left edge. incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right()); else // Replace the right edge. incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e1); break; case Vertex::CONVEX: // Start of a new trapezoid. convex: // We don't expect to find any edges. DebugPrintf("CONVEX %d %d\n", e0 - vta, e1 - vta); if (incompleteTrapezoids.withinActiveTrapezoid( vt->point(), &t)) { // Complete trapezoid. SkASSERT(t != NULL); t->setBottom(vt); incompleteTrapezoids.remove(t); // Introduce two new trapezoids. incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), e0); incompleteTrapezoids.insertNewTrapezoid(vt, e1, t->right()); } else { // Insert a new trapezoid. incompleteTrapezoids.insertNewTrapezoid(vt, e0, e1); } break; case Vertex::CONCAVE: // End of a trapezoid. DebugPrintf("CONCAVE %d %d\n", e0 - vta, e1 - vta); // We should find two edges. t = incompleteTrapezoids.getTrapezoidWithEdge(e0); if (t == NULL) { DebugPrintf("Concave: cannot find a trapezoid with e0: " " trying monotone\n"); goto monotone; } SkASSERT(t != NULL); if (e0 == t->left() && e1 == t->right()) { DebugPrintf( "Concave edges belong to the same trapezoid.\n"); // Edges belong to the same trapezoid. // Complete trapezoid & transfer it from the active list. t->setBottom(vt); incompleteTrapezoids.remove(t); } else { // Edges belong to different trapezoids DebugPrintf( "Concave edges belong to different trapezoids.\n"); // Complete left and right trapezoids. Trapezoid *s = incompleteTrapezoids.getTrapezoidWithEdge( e1); if (s == NULL) { DebugPrintf( "Concave: cannot find a trapezoid with e1: " " trying monotone\n"); goto monotone; } t->setBottom(vt); s->setBottom(vt); incompleteTrapezoids.remove(t); incompleteTrapezoids.remove(s); // Merge the two trapezoids into one below this vertex. incompleteTrapezoids.insertNewTrapezoid(vt, t->left(), s->right()); } break; } } RemoveDegenerateTrapezoids(numPts, vta); DebugPrintf("Done making trapezoids\n"); PrintVertexPtrs(vtptr.count(), vtptr.begin(), vta); size_t k = incompleteTrapezoids.count(); if (k > 0) { FailureMessage("%d incomplete trapezoids\n", k); return false; } return true; }