Seemingly pixel-perfect rendering of toap examples from svg spec.

Set paint flags for anti-alias, kerning for text, subpixel positioning of text.
Add half of width of glyph to distance calculation for mBezierTransformer.getTransformAtDistance and preTranslate the glyph corresponding amount backwards (gives correct angles on glyphs when rendering text on a path)
Add magical constant ratios of 1.2 into getBezierTransformer and getGlyphPointFromContext calls (should probably be based on some dpi ratio calculation)
This commit is contained in:
Mikael Sand
2017-06-19 22:04:12 +03:00
parent fe1b9b2ea8
commit b094bc80f0
3 changed files with 9 additions and 4 deletions
@@ -16,6 +16,7 @@ import android.graphics.Paint;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.Base64; import android.util.Base64;
import com.facebook.react.uimanager.DisplayMetricsHolder; import com.facebook.react.uimanager.DisplayMetricsHolder;
@@ -135,6 +136,10 @@ public class SvgViewShadowNode extends LayoutShadowNode {
Paint paint = new Paint(); Paint paint = new Paint();
paint.setFlags(Paint.ANTI_ALIAS_FLAG | Paint.DEV_KERN_TEXT_FLAG | Paint.SUBPIXEL_TEXT_FLAG);
paint.setTypeface(Typeface.DEFAULT);
for (int i = 0; i < getChildCount(); i++) { for (int i = 0; i < getChildCount(); i++) {
if (!(getChildAt(i) instanceof VirtualNode)) { if (!(getChildAt(i) instanceof VirtualNode)) {
continue; continue;
@@ -101,12 +101,12 @@ public class TSpanShadowNode extends TextShadowNode {
paint.getTextPath(letter, 0, 1, 0, 0, glyph); paint.getTextPath(letter, 0, 1, 0, 0, glyph);
PointF glyphDelta = getGlyphDeltaFromContext(); PointF glyphDelta = getGlyphDeltaFromContext();
PointF glyphPoint = getGlyphPointFromContext(glyphPosition, width); PointF glyphPoint = getGlyphPointFromContext(glyphPosition * 1.2f, width);
glyphPosition += width; glyphPosition += width;
Matrix matrix = new Matrix(); Matrix matrix = new Matrix();
if (mBezierTransformer != null) { if (mBezierTransformer != null) {
matrix = mBezierTransformer.getTransformAtDistance(glyphPoint.x + glyphDelta.x); matrix = mBezierTransformer.getTransformAtDistance(glyphPoint.x + glyphDelta.x + width / 2);
if (textPathHasReachedEnd()) { if (textPathHasReachedEnd()) {
break; break;
@@ -114,7 +114,7 @@ public class TSpanShadowNode extends TextShadowNode {
continue; continue;
} }
matrix.preTranslate(0, glyphDelta.y); matrix.preTranslate(-width / 2, glyphDelta.y);
matrix.postTranslate(0, glyphPoint.y); matrix.postTranslate(0, glyphPoint.y);
} else { } else {
matrix.setTranslate(glyphPoint.x + glyphDelta.x, glyphPoint.y + glyphDelta.y); matrix.setTranslate(glyphPoint.x + glyphDelta.x, glyphPoint.y + glyphDelta.y);
@@ -52,7 +52,7 @@ public class TextPathShadowNode extends TextShadowNode {
} }
PathShadowNode path = (PathShadowNode)template; PathShadowNode path = (PathShadowNode)template;
return new BezierTransformer(path.getBezierCurves(), relativeOnWidth(mStartOffset)); return new BezierTransformer(path.getBezierCurves(), relativeOnWidth(mStartOffset) / 1.2f);
} }
@Override @Override