Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(133)

Unified Diff: src/core/SkDevice.cpp

Issue 925343003: use common impl for drawTextOnPath (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: move includes to the top Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/core/SkBitmapDevice.cpp ('k') | src/core/SkDraw.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkDevice.cpp
diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp
index bc6c892079622f956f00441d7b153c644974dd25..2f510700753d1c51d41e92ae83fbb204f61aa344 100644
--- a/src/core/SkDevice.cpp
+++ b/src/core/SkDevice.cpp
@@ -10,8 +10,11 @@
#include "SkDraw.h"
#include "SkMetaData.h"
#include "SkPatchUtils.h"
+#include "SkPathMeasure.h"
+#include "SkRasterClip.h"
#include "SkShader.h"
#include "SkTextBlob.h"
+#include "SkTextToPathIter.h"
SkBaseDevice::SkBaseDevice()
: fLeakyProperties(SkNEW_ARGS(SkDeviceProperties, (SkDeviceProperties::kLegacyLCD_InitType)))
@@ -212,6 +215,129 @@ bool SkBaseDevice::EXPERIMENTAL_drawPicture(SkCanvas*, const SkPicture*, const S
//////////////////////////////////////////////////////////////////////////////////////////
robertphillips 2015/02/17 18:50:47 morph_points ?
+static void morphpoints(SkPoint dst[], const SkPoint src[], int count,
+ SkPathMeasure& meas, const SkMatrix& matrix) {
+ SkMatrix::MapXYProc proc = matrix.getMapXYProc();
+
+ for (int i = 0; i < count; i++) {
+ SkPoint pos;
+ SkVector tangent;
+
+ proc(matrix, src[i].fX, src[i].fY, &pos);
+ SkScalar sx = pos.fX;
+ SkScalar sy = pos.fY;
+
+ if (!meas.getPosTan(sx, &pos, &tangent)) {
+ // set to 0 if the measure failed, so that we just set dst == pos
+ tangent.set(0, 0);
+ }
+
+ /* This is the old way (that explains our approach but is way too slow
+ SkMatrix matrix;
+ SkPoint pt;
+
+ pt.set(sx, sy);
+ matrix.setSinCos(tangent.fY, tangent.fX);
+ matrix.preTranslate(-sx, 0);
+ matrix.postTranslate(pos.fX, pos.fY);
+ matrix.mapPoints(&dst[i], &pt, 1);
+ */
+ dst[i].set(pos.fX - SkScalarMul(tangent.fY, sy),
+ pos.fY + SkScalarMul(tangent.fX, sy));
+ }
+}
+
+/* TODO
+
+ Need differentially more subdivisions when the follow-path is curvy. Not sure how to
+ determine that, but we need it. I guess a cheap answer is let the caller tell us,
+ but that seems like a cop-out. Another answer is to get Rob Johnson to figure it out.
+ */
robertphillips 2015/02/17 18:50:47 morph_path ?
+static void morphpath(SkPath* dst, const SkPath& src, SkPathMeasure& meas,
+ const SkMatrix& matrix) {
+ SkPath::Iter iter(src, false);
+ SkPoint srcP[4], dstP[3];
+ SkPath::Verb verb;
+
+ while ((verb = iter.next(srcP)) != SkPath::kDone_Verb) {
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ morphpoints(dstP, srcP, 1, meas, matrix);
+ dst->moveTo(dstP[0]);
+ break;
+ case SkPath::kLine_Verb:
+ // turn lines into quads to look bendy
+ srcP[0].fX = SkScalarAve(srcP[0].fX, srcP[1].fX);
+ srcP[0].fY = SkScalarAve(srcP[0].fY, srcP[1].fY);
+ morphpoints(dstP, srcP, 2, meas, matrix);
+ dst->quadTo(dstP[0], dstP[1]);
+ break;
+ case SkPath::kQuad_Verb:
+ morphpoints(dstP, &srcP[1], 2, meas, matrix);
+ dst->quadTo(dstP[0], dstP[1]);
+ break;
robertphillips 2015/02/17 18:50:47 kConic_Verb ?
+ case SkPath::kCubic_Verb:
+ morphpoints(dstP, &srcP[1], 3, meas, matrix);
+ dst->cubicTo(dstP[0], dstP[1], dstP[2]);
+ break;
+ case SkPath::kClose_Verb:
+ dst->close();
+ break;
+ default:
+ SkDEBUGFAIL("unknown verb");
+ break;
+ }
+ }
+}
+
+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 != NULL);
+
+ // nothing to draw
+ if (text == NULL || 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(), NULL, true);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
uint32_t SkBaseDevice::filterTextFlags(const SkPaint& paint) const {
uint32_t flags = paint.getFlags();
« no previous file with comments | « src/core/SkBitmapDevice.cpp ('k') | src/core/SkDraw.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698