Improve Text on a path layout rules conformance.

Correct glyph point and delta x / y calculation and context handling.
Remove incorrect whitespace from getLinePath method call.
Correct the y coordinate of the text's origin when rendering glyphs into paths using getTextPath.
Remove strange postTranslate transform.

https://www.w3.org/TR/SVG11/text.html#TextOnAPath
This commit is contained in:
Mikael Sand
2017-06-19 01:43:04 +03:00
parent e9747bee01
commit 64ed6861e2
3 changed files with 30 additions and 22 deletions
@@ -25,6 +25,7 @@ public class GlyphContext {
private ArrayList<ReadableMap> mFontContext;
private ArrayList<PointF> mLocationContext;
private ArrayList<PointF> mDeltaContext;
private ArrayList<ArrayList<Float>> mDeltaXContext;
private ArrayList<ArrayList<Float>> mDeltaYContext;
private ArrayList<Float> mXContext;
@@ -42,6 +43,7 @@ public class GlyphContext {
mCurrentLocation = new PointF();
mFontContext = new ArrayList<>();
mLocationContext = new ArrayList<>();
mDeltaContext = new ArrayList<>();
mDeltaXContext = new ArrayList<>();
mDeltaYContext = new ArrayList<>();
mXContext = new ArrayList<>();
@@ -59,6 +61,7 @@ public class GlyphContext {
}
mLocationContext.add(location);
mDeltaContext.add(new PointF(0, 0));
mFontContext.add(font);
mDeltaXContext.add(getFloatArrayListFromReadableArray(deltaX));
mDeltaYContext.add(getFloatArrayListFromReadableArray(deltaY));
@@ -72,6 +75,7 @@ public class GlyphContext {
float x = mXContext.get(mContextLength - 1);
mFontContext.remove(mContextLength - 1);
mLocationContext.remove(mContextLength - 1);
mDeltaContext.remove(mContextLength - 1);
mDeltaXContext.remove(mContextLength - 1);
mDeltaYContext.remove(mContextLength - 1);
mXContext.remove(mContextLength - 1);
@@ -87,23 +91,28 @@ public class GlyphContext {
}
public PointF getNextGlyphPoint(float offset, float glyphWidth) {
float dx = getNextDelta(mDeltaXContext);
mCurrentLocation.x += dx;
float dy = getNextDelta(mDeltaYContext);
mCurrentLocation.y += dy;
for (PointF point: mLocationContext) {
point.x += dx;
point.y += dy;
}
mXContext.set(mXContext.size() - 1, mCurrentLocation.x + offset + glyphWidth);
return new PointF(mCurrentLocation.x + offset, mCurrentLocation.y);
}
public PointF getNextGlyphDelta() {
float dx = getNextDelta(mDeltaXContext);
float dy = getNextDelta(mDeltaYContext);
if (mContextLength > 0) {
for (PointF point: mDeltaContext) {
point.x += dx;
point.y += dy;
}
return mDeltaContext.get(mContextLength - 1);
}
return new PointF(dx, dy);
}
private float getNextDelta(ArrayList<ArrayList<Float>> deltaContext) {
float value = 0;
boolean valueSet = false;
@@ -78,7 +78,7 @@ public class TSpanShadowNode extends TextShadowNode {
pushGlyphContext();
applyTextPropertiesToPaint(paint);
getLinePath(mContent + " ", paint, path);
getLinePath(mContent + "", paint, path);
mCache = path;
popGlyphContext();
@@ -99,13 +99,14 @@ public class TSpanShadowNode extends TextShadowNode {
Path glyph = new Path();
float width = widths[index];
paint.getTextPath(letter, 0, 1, 0, -paint.ascent(), glyph);
paint.getTextPath(letter, 0, 1, 0, 0, glyph);
PointF glyphDelta = getGlyphDeltaFromContext();
PointF glyphPoint = getGlyphPointFromContext(glyphPosition, width);
glyphPosition += width;
Matrix matrix = new Matrix();
if (mBezierTransformer != null) {
matrix = mBezierTransformer.getTransformAtDistance(glyphPoint.x);
matrix = mBezierTransformer.getTransformAtDistance(glyphPoint.x + glyphDelta.x);
if (textPathHasReachedEnd()) {
break;
@@ -113,22 +114,16 @@ public class TSpanShadowNode extends TextShadowNode {
continue;
}
matrix.preTranslate(0, glyphDelta.y);
matrix.postTranslate(0, glyphPoint.y);
} else {
matrix.setTranslate(glyphPoint.x, glyphPoint.y);
matrix.setTranslate(glyphPoint.x + glyphDelta.x, glyphPoint.y + glyphDelta.y);
}
glyph.transform(matrix);
path.addPath(glyph);
}
if (mBezierTransformer != null) {
Matrix matrix = new Matrix();
matrix.postTranslate(0, paint.ascent() * 1.1f);
path.transform(matrix);
}
return path;
}
@@ -200,6 +200,10 @@ public class TextShadowNode extends GroupShadowNode {
return getTextRoot().getGlyphContext().getNextGlyphPoint(offset, glyphWidth);
}
protected PointF getGlyphDeltaFromContext() {
return getTextRoot().getGlyphContext().getNextGlyphDelta();
}
private Matrix getAlignMatrix(Path path) {
RectF box = new RectF();
path.computeBounds(box, true);