SkScalar SkPath1DPathEffect::next(SkPath* dst, SkScalar distance, SkPathMeasure& meas) const { switch (fStyle) { case kTranslate_Style: { SkPoint pos; if (meas.getPosTan(distance, &pos, nullptr)) { dst->addPath(fPath, pos.fX, pos.fY); } } break; case kRotate_Style: { SkMatrix matrix; if (meas.getMatrix(distance, &matrix)) { dst->addPath(fPath, matrix); } } break; case kMorph_Style: morphpath(dst, fPath, meas, distance); break; default: SkDEBUGFAIL("unknown Style enum"); break; } return fAdvance; }
void SkBaseDevice::drawTextOnPath(const SkDraw& draw, const void* text, size_t byteLength, const SkPath& follow, const SkMatrix* matrix, const SkPaint& paint) { SkASSERT(byteLength == 0 || text != nullptr); // nothing to draw if (text == nullptr || byteLength == 0 || draw.fRC->isEmpty()) { return; } SkTextToPathIter iter((const char*)text, byteLength, paint, true); SkPathMeasure meas(follow, false); SkScalar hOffset = 0; // need to measure first if (paint.getTextAlign() != SkPaint::kLeft_Align) { SkScalar pathLen = meas.getLength(); if (paint.getTextAlign() == SkPaint::kCenter_Align) { pathLen = SkScalarHalf(pathLen); } hOffset += pathLen; } const SkPath* iterPath; SkScalar xpos; SkMatrix scaledMatrix; SkScalar scale = iter.getPathScale(); scaledMatrix.setScale(scale, scale); while (iter.next(&iterPath, &xpos)) { if (iterPath) { SkPath tmp; SkMatrix m(scaledMatrix); tmp.setIsVolatile(true); m.postTranslate(xpos + hOffset, 0); if (matrix) { m.postConcat(*matrix); } morphpath(&tmp, *iterPath, meas, m); this->drawPath(draw, tmp, iter.getPaint(), nullptr, true); } } }
void TextArt::EnvelopeWarp::morph(SkPath& bSkeleton, SkPathMeasure& bMeasure, SkPathCrossing& bCrossing, SkPath& tSkeleton, SkPathMeasure& tMeasure, SkPathCrossing& tCrossing, SkPath& glypthPath, SkPathMeasure& lineMeasure, SkMatrix& scaleMatrix, SkScalar xpos, SkScalar hBOffset, SkScalar hTOffset, SkPath& warpedPath) { SkRect glypthBound; glypthBound = glypthPath.getBounds(); SkScalar k1 = 1.0; if (!isSymmetric_) { SkScalar hBOffsetTmp = 0.0; SkScalar hTOffsetTmp = 0.0; if (isTopBased_) { glypthBound.fTop = 0; glypthBound.fBottom = -boundsRect_.height(); SkMatrix compositeTMatrix(scaleMatrix); compositeTMatrix.postTranslate(xpos + hTOffset, 0); compositeTMatrix.postConcat(matrix_); if ( getK(glypthBound, bCrossing, tCrossing, tMeasure, compositeTMatrix, k1, hBOffsetTmp, hTOffsetTmp) ) { k1 = 1/k1; hBOffset = hBOffsetTmp; hTOffset = xpos + hTOffset; } } else { glypthBound.fTop = -boundsRect_.height(); glypthBound.fBottom = 0; SkMatrix compositeBMatrix(scaleMatrix); compositeBMatrix.postTranslate(xpos + hBOffset, 0); compositeBMatrix.postConcat(matrix_); if ( getK(glypthBound, bCrossing, tCrossing, bMeasure, compositeBMatrix, k1, hBOffsetTmp, hTOffsetTmp) ) { //use distance to Left on Top Skeleton for positioning Top glypthn hTOffset = hTOffsetTmp; hBOffset = xpos + hBOffset; } } } else { hBOffset = xpos + hBOffset; hTOffset = hBOffset; } SkMatrix compositeBMatrix(scaleMatrix); compositeBMatrix.postTranslate(hBOffset, 0); compositeBMatrix.postConcat(matrix_); //warp Glypth by bottom line k1_ = isTopBased_ ? k1 : SkIntToScalar(1); isTop = false; SkPath bWarped; morphpath(&bWarped, glypthPath, bMeasure, compositeBMatrix); bWarped_.addPath(bWarped); if (!tSkeleton_.isEmpty()) { SkMatrix compositeTMatrix(scaleMatrix); compositeTMatrix.postTranslate(hTOffset, 0); compositeTMatrix.postConcat(matrix_); //warp Glypth by top line k1_ = !isTopBased_ ? k1 : SkIntToScalar(1); isTop = true; SkPath tWarped; morphpath(&tWarped, glypthPath, tMeasure, compositeTMatrix); tWarped_.addPath(tWarped); //convert Glypth to Path to allow weighting SkPath lineMorphed; morphpath(&lineMorphed, glypthPath, lineMeasure, scaleMatrix); weight(lineMorphed, tWarped, bWarped, &warpedPath); } else warpedPath.addPath(bWarped_); }