void SkDrawPaint::setupPaint(SkPaint* paint) const { if (antiAlias != -1) paint->setAntiAlias(SkToBool(antiAlias)); if (color != NULL) paint->setColor(color->getColor()); if (fakeBold != -1) paint->setFakeBoldText(SkToBool(fakeBold)); if (filterBitmap != -1) paint->setFilterLevel(filterBitmap ? SkPaint::kLow_FilterLevel : SkPaint::kNone_FilterLevel); // stroke is legacy; style setting if present overrides stroke if (stroke != -1) paint->setStyle(SkToBool(stroke) ? SkPaint::kStroke_Style : SkPaint::kFill_Style); if (style != -1) paint->setStyle((SkPaint::Style) style); if (linearText != -1) paint->setLinearText(SkToBool(linearText)); if (maskFilter == NULL) paint->setMaskFilter(NULL); else if (maskFilter != (SkDrawMaskFilter*) -1) SkSafeUnref(paint->setMaskFilter(maskFilter->getMaskFilter())); if (pathEffect == NULL) paint->setPathEffect(NULL); else if (pathEffect != (SkDrawPathEffect*) -1) SkSafeUnref(paint->setPathEffect(pathEffect->getPathEffect())); if (shader == NULL) paint->setShader(NULL); else if (shader != (SkDrawShader*) -1) SkSafeUnref(paint->setShader(shader->getShader())); if (strikeThru != -1) paint->setStrikeThruText(SkToBool(strikeThru)); if (strokeCap != -1) paint->setStrokeCap((SkPaint::Cap) strokeCap); if (strokeJoin != -1) paint->setStrokeJoin((SkPaint::Join) strokeJoin); if (SkScalarIsNaN(strokeMiter) == false) paint->setStrokeMiter(strokeMiter); if (SkScalarIsNaN(strokeWidth) == false) paint->setStrokeWidth(strokeWidth); if (textAlign != -1) paint->setTextAlign((SkPaint::Align) textAlign); if (SkScalarIsNaN(textScaleX) == false) paint->setTextScaleX(textScaleX); if (SkScalarIsNaN(textSize) == false) paint->setTextSize(textSize); if (SkScalarIsNaN(textSkewX) == false) paint->setTextSkewX(textSkewX); if (typeface == NULL) paint->setTypeface(NULL); else if (typeface != (SkDrawTypeface*) -1) SkSafeUnref(paint->setTypeface(typeface->getTypeface())); if (underline != -1) paint->setUnderlineText(SkToBool(underline)); if (xfermode != -1) paint->setXfermodeMode((SkXfermode::Mode) xfermode); }
bool ValidPoints(const SkPoint* pts, int count) { for (int index = 0; index < count; ++index) { if (SkScalarIsNaN(pts[index].fX)) { return false; } if (SkScalarIsNaN(pts[index].fY)) { return false; } } return true; }
SkColor SkDrawColor::getColor() { if (fDirty) { if (SkScalarIsNaN(fValue) == false) color = HSV_to_RGB(color, kGetValue, fValue); if (SkScalarIsNaN(fSaturation) == false) color = HSV_to_RGB(color, kGetSaturation, fSaturation); if (SkScalarIsNaN(fHue) == false) color = HSV_to_RGB(color, kGetHue, fHue); fDirty = false; } return color; }
bool ValidBounds(const SkPathOpsBounds& bounds) { if (SkScalarIsNaN(bounds.fLeft)) { return false; } if (SkScalarIsNaN(bounds.fTop)) { return false; } if (SkScalarIsNaN(bounds.fRight)) { return false; } return !SkScalarIsNaN(bounds.fBottom); }
static void center_of_mass(const SegmentArray& segments, SkPoint* c) { SkScalar area = 0; SkPoint center = {0, 0}; int count = segments.count(); SkPoint p0 = {0, 0}; if (count > 2) { // We translate the polygon so that the first point is at the origin. // This avoids some precision issues with small area polygons far away // from the origin. p0 = segments[0].endPt(); SkPoint pi; SkPoint pj; // the first and last iteration of the below loop would compute // zeros since the starting / ending point is (0,0). So instead we start // at i=1 and make the last iteration i=count-2. pj = segments[1].endPt() - p0; for (int i = 1; i < count - 1; ++i) { pi = pj; const SkPoint pj = segments[i + 1].endPt() - p0; SkScalar t = SkScalarMul(pi.fX, pj.fY) - SkScalarMul(pj.fX, pi.fY); area += t; center.fX += (pi.fX + pj.fX) * t; center.fY += (pi.fY + pj.fY) * t; } } // If the poly has no area then we instead return the average of // its points. if (SkScalarNearlyZero(area)) { SkPoint avg; avg.set(0, 0); for (int i = 0; i < count; ++i) { const SkPoint& pt = segments[i].endPt(); avg.fX += pt.fX; avg.fY += pt.fY; } SkScalar denom = SK_Scalar1 / count; avg.scale(denom); *c = avg; } else { area *= 3; area = SkScalarDiv(SK_Scalar1, area); center.fX = SkScalarMul(center.fX, area); center.fY = SkScalarMul(center.fY, area); // undo the translate of p0 to the origin. *c = center + p0; } SkASSERT(!SkScalarIsNaN(c->fX) && !SkScalarIsNaN(c->fY)); }
/** From Numerical Recipes in C. Q = -1/2 (B + sign(B) sqrt[B*B - 4*A*C]) x1 = Q / A x2 = C / Q */ int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2]) { SkASSERT(roots); if (A == 0) { return valid_unit_divide(-C, B, roots); } SkScalar* r = roots; SkScalar R = B*B - 4*A*C; if (R < 0 || SkScalarIsNaN(R)) { // complex roots return 0; } R = SkScalarSqrt(R); SkScalar Q = (B < 0) ? -(B-R)/2 : -(B+R)/2; r += valid_unit_divide(Q, A, r); r += valid_unit_divide(C, Q, r); if (r - roots == 2) { if (roots[0] > roots[1]) SkTSwap<SkScalar>(roots[0], roots[1]); else if (roots[0] == roots[1]) // nearly-equal? r -= 1; // skip the double root } return (int)(r - roots); }
bool SkAnimatorScript::IsNaN(const char* function, size_t len, SkTDArray<SkScriptValue>& params, void* eng, SkScriptValue* value) { if (SK_LITERAL_STR_EQUAL("isNaN", function, len) == false) return false; if (params.count() != 1) return false; SkScriptValue* scriptValue = params.begin(); value->fType = SkType_Int; value->fOperand.fS32 = scriptValue->fType == SkType_Float ? SkScalarIsNaN(scriptValue->fOperand.fScalar) : 0; return true; }
bool SkDataInput::add() { SkASSERT(name.size() > 0); const char* dataName = name.c_str(); if (fInt != (int) SK_NaN32) fParent->fEvent.setS32(dataName, fInt); else if (SkScalarIsNaN(fFloat) == false) fParent->fEvent.setScalar(dataName, fFloat); else if (string.size() > 0) fParent->fEvent.setString(dataName, string); // else // SkASSERT(0); return false; }
bool SkAnimatorScript::IsFinite(const char* function, size_t len, SkTDArray<SkScriptValue>& params, void* eng, SkScriptValue* value) { if (SK_LITERAL_STR_EQUAL(function, "isFinite", len) == false) return false; if (params.count() != 1) return false; SkScriptValue* scriptValue = params.begin(); SkDisplayTypes type = scriptValue->fType; SkScalar scalar = scriptValue->fOperand.fScalar; value->fType = SkType_Int; value->fOperand.fS32 = type == SkType_Float ? SkScalarIsNaN(scalar) == false && SkScalarAbs(scalar) != SK_ScalarInfinity : type == SkType_Int; return true; }
sk_sp<SkShader> SkShader::MakeCompose(sk_sp<SkShader> dst, sk_sp<SkShader> src, SkBlendMode mode, float lerpT) { if (!src || !dst || SkScalarIsNaN(lerpT)) { return nullptr; } lerpT = SkScalarPin(lerpT, 0, 1); if (lerpT == 0) { return dst; } else if (lerpT == 1) { if (mode == SkBlendMode::kSrc) { return src; } if (mode == SkBlendMode::kDst) { return dst; } } return sk_sp<SkShader>(new SkComposeShader(std::move(dst), std::move(src), mode, lerpT)); }
bool SkDrawPath::getProperty(int index, SkScriptValue* value) const { switch (index) { case SK_PROPERTY(length): if (SkScalarIsNaN(fLength)) { const SkPath& path = ((SkDrawPath*) this)->getPath(); SkPathMeasure pathMeasure(path, false); fLength = pathMeasure.getLength(); } value->fType = SkType_Float; value->fOperand.fScalar = fLength; break; case SK_PROPERTY(fillType): value->fType = SkType_FillType; value->fOperand.fS32 = (int) fPath.getFillType(); break; default: SkASSERT(0); return false; } return true; }
/** From Numerical Recipes in C. Q = -1/2 (B + sign(B) sqrt[B*B - 4*A*C]) x1 = Q / A x2 = C / Q */ int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2]) { SkASSERT(roots); if (A == 0) return valid_unit_divide(-C, B, roots); SkScalar* r = roots; #ifdef SK_SCALAR_IS_FLOAT float R = B*B - 4*A*C; if (R < 0 || SkScalarIsNaN(R)) { // complex roots return 0; } R = sk_float_sqrt(R); #else Sk64 RR, tmp; RR.setMul(B,B); tmp.setMul(A,C); tmp.shiftLeft(2); RR.sub(tmp); if (RR.isNeg()) return 0; SkFixed R = RR.getSqrt(); #endif SkScalar Q = (B < 0) ? -(B-R)/2 : -(B+R)/2; r += valid_unit_divide(Q, A, r); r += valid_unit_divide(C, Q, r); if (r - roots == 2) { if (roots[0] > roots[1]) SkTSwap<SkScalar>(roots[0], roots[1]); else if (roots[0] == roots[1]) // nearly-equal? r -= 1; // skip the double root } return (int)(r - roots); }
static int valid_unit_divide(SkScalar numer, SkScalar denom, SkScalar* ratio) { SkASSERT(ratio); if (numer < 0) { numer = -numer; denom = -denom; } if (denom == 0 || numer == 0 || numer >= denom) { return 0; } SkScalar r = SkScalarDiv(numer, denom); if (SkScalarIsNaN(r)) { return 0; } SkASSERT(r >= 0 && r < SK_Scalar1); if (r == 0) { // catch underflow if numer <<<< denom return 0; } *ratio = r; return 1; }
static void verify_floats(const float* floats, int count) { for (int i = 0; i < count; ++i) { SkASSERT(!SkScalarIsNaN(SkFloatToScalar(floats[i]))); } }