void SkConvertQuadToCubic(const SkPoint src[3], SkPoint dst[4]) { SkScalar two = SkIntToScalar(2); SkScalar one_third = SkScalarDiv(SK_Scalar1, SkIntToScalar(3)); dst[0].set(src[0].fX, src[0].fY); dst[1].set( SkScalarMul(SkScalarMulAdd(src[1].fX, two, src[0].fX), one_third), SkScalarMul(SkScalarMulAdd(src[1].fY, two, src[0].fY), one_third)); dst[2].set( SkScalarMul(SkScalarMulAdd(src[1].fX, two, src[2].fX), one_third), SkScalarMul(SkScalarMulAdd(src[1].fY, two, src[2].fY), one_third)); dst[3].set(src[2].fX, src[2].fY); }
static SkScalar eval_quad(const SkScalar src[], SkScalar t) { SkASSERT(src); SkASSERT(t >= 0 && t <= SK_Scalar1); #ifdef DIRECT_EVAL_OF_POLYNOMIALS SkScalar C = src[0]; SkScalar A = src[4] - 2 * src[2] + C; SkScalar B = 2 * (src[2] - C); return SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C); #else SkScalar ab = SkScalarInterp(src[0], src[2], t); SkScalar bc = SkScalarInterp(src[2], src[4], t); return SkScalarInterp(ab, bc, t); #endif }
virtual void performTest() { SkPoint* dst = fDst; const SkPoint* src = fSrc; int count = fCount; float mx = fMatrix[SkMatrix::kMScaleX]; float my = fMatrix[SkMatrix::kMScaleY]; float tx = fMatrix[SkMatrix::kMTransX]; float ty = fMatrix[SkMatrix::kMTransY]; do { dst->fY = SkScalarMulAdd(src->fY, my, ty); dst->fX = SkScalarMulAdd(src->fX, mx, tx); src += 1; dst += 1; } while (--count); }
static SkScalar eval_cubic_2ndDerivative(const SkScalar src[], SkScalar t) { SkScalar A = src[6] + 3*(src[2] - src[4]) - src[0]; SkScalar B = src[4] - 2 * src[2] + src[0]; return SkScalarMulAdd(A, t, B); }
static SkScalar eval_quad_derivative(const SkScalar src[], SkScalar t) { SkScalar A = src[4] - 2 * src[2] + src[0]; SkScalar B = src[2] - src[0]; return 2 * SkScalarMulAdd(A, t, B); }
static int winding_mono_quad(const SkPoint pts[], SkScalar x, SkScalar y) { SkScalar y0 = pts[0].fY; SkScalar y2 = pts[2].fY; int dir = 1; if (y0 > y2) { SkTSwap(y0, y2); dir = -1; } if (y < y0 || y >= y2) { return 0; } // bounds check on X (not required, but maybe faster) #if 0 if (pts[0].fX > x && pts[1].fX > x && pts[2].fX > x) { return 0; } #endif SkScalar roots[2]; int n = SkFindUnitQuadRoots(pts[0].fY - 2 * pts[1].fY + pts[2].fY, 2 * (pts[1].fY - pts[0].fY), pts[0].fY - y, roots); SkASSERT(n <= 1); SkScalar xt; if (0 == n) { SkScalar mid = SkScalarAve(y0, y2); // Need [0] and [2] if dir == 1 // and [2] and [0] if dir == -1 xt = y < mid ? pts[1 - dir].fX : pts[dir - 1].fX; } else { SkScalar t = roots[0]; SkScalar C = pts[0].fX; SkScalar A = pts[2].fX - 2 * pts[1].fX + C; SkScalar B = 2 * (pts[1].fX - C); xt = SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C); } return xt < x ? dir : 0; }
static SkScalar eval_cubic(const SkScalar src[], SkScalar t) { SkASSERT(src); SkASSERT(t >= 0 && t <= SK_Scalar1); if (t == 0) { return src[0]; } #ifdef DIRECT_EVAL_OF_POLYNOMIALS SkScalar D = src[0]; SkScalar A = src[6] + 3*(src[2] - src[4]) - D; SkScalar B = 3*(src[4] - src[2] - src[2] + D); SkScalar C = 3*(src[2] - D); return SkScalarMulAdd(SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C), t, D); #else SkScalar ab = SkScalarInterp(src[0], src[2], t); SkScalar bc = SkScalarInterp(src[2], src[4], t); SkScalar cd = SkScalarInterp(src[4], src[6], t); SkScalar abc = SkScalarInterp(ab, bc, t); SkScalar bcd = SkScalarInterp(bc, cd, t); return SkScalarInterp(abc, bcd, t); #endif }
static SkScalar eval_cubic_coeff(SkScalar A, SkScalar B, SkScalar C, SkScalar D, SkScalar t) { return SkScalarMulAdd(SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C), t, D); }
/** return At^2 + Bt + C */ static SkScalar eval_quadratic(SkScalar A, SkScalar B, SkScalar C, SkScalar t) { SkASSERT(t >= 0 && t <= SK_Scalar1); return SkScalarMulAdd(SkScalarMulAdd(A, t, B), t, C); }
void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, SkScalar x, SkScalar y, const SkPaint& paint) { SkPaint textPaint = calculateTextPaint(paint); updateGSFromPaint(textPaint, true); // We want the text in glyph id encoding and a writable buffer, so we end // up making a copy either way. size_t numGlyphs = paint.textToGlyphs(text, len, NULL); uint16_t* glyphIDs = (uint16_t*)sk_malloc_flags(numGlyphs * 2, SK_MALLOC_TEMP | SK_MALLOC_THROW); SkAutoFree autoFreeGlyphIDs(glyphIDs); if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) { paint.textToGlyphs(text, len, glyphIDs); textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); } else { SkASSERT((len & 1) == 0); SkASSERT(len / 2 == numGlyphs); memcpy(glyphIDs, text, len); } SkScalar width; SkScalar* widthPtr = NULL; if (textPaint.isUnderlineText() || textPaint.isStrikeThruText()) widthPtr = &width; SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); alignText(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y, widthPtr); fContent.writeText("BT\n"); setTextTransform(x, y, textPaint.getTextSkewX()); size_t consumedGlyphCount = 0; while (numGlyphs > consumedGlyphCount) { updateFont(textPaint, glyphIDs[consumedGlyphCount]); SkPDFFont* font = fGraphicStack[fGraphicStackIndex].fFont; size_t availableGlyphs = font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount, numGlyphs - consumedGlyphCount); SkString encodedString = SkPDFString::formatString(glyphIDs + consumedGlyphCount, availableGlyphs, font->multiByteGlyphs()); fContent.writeText(encodedString.c_str()); consumedGlyphCount += availableGlyphs; fContent.writeText(" Tj\n"); } fContent.writeText("ET\n"); // Draw underline and/or strikethrough if the paint has them. // drawPosText() and drawTextOnPath() don't draw underline or strikethrough // because the raster versions don't. Use paint instead of textPaint // because we may have changed strokeWidth to do fakeBold text. if (paint.isUnderlineText() || paint.isStrikeThruText()) { SkScalar textSize = paint.getTextSize(); SkScalar height = SkScalarMul(textSize, kStdUnderline_Thickness); if (paint.isUnderlineText()) { SkScalar top = SkScalarMulAdd(textSize, kStdUnderline_Offset, y); SkRect r = SkRect::MakeXYWH(x, top - height, width, height); drawRect(d, r, paint); } if (paint.isStrikeThruText()) { SkScalar top = SkScalarMulAdd(textSize, kStdStrikeThru_Offset, y); SkRect r = SkRect::MakeXYWH(x, top - height, width, height); drawRect(d, r, paint); } } }