Implement GlyphPathBag for caching Paths per char, after a applyTextPropertiesToPaint(paint, font)

Path glyph = bag.getOrCreateAndCache(currentChar, current);
This commit is contained in:
Mikael Sand
2017-07-25 19:46:02 +03:00
parent 9e0de800bd
commit 48cfe71aca
2 changed files with 59 additions and 7 deletions
@@ -0,0 +1,48 @@
package com.horcrux.svg;
import android.graphics.Paint;
import android.graphics.Path;
import java.util.ArrayList;
class GlyphPathBag {
private ArrayList<Path> paths = new ArrayList<>();
private int[][] data = new int[255][];
Paint paint;
GlyphPathBag(Paint paint) {
this.paint = paint;
// Make indexed-by-one, to allow zero to represent non-cached
paths.add(new Path());
}
Path getOrCreateAndCache(char ch, String current) {
int index = getIndex(ch);
Path cached;
if (index != 0) {
cached = paths.get(index);
} else {
cached = new Path();
paint.getTextPath(current, 0, 1, 0, 0, cached);
int[] bin = data[ch >> 8];
if (bin == null) {
bin = data[ch >> 8] = new int[255];
}
bin[ch & 0xFF] = paths.size();
paths.add(cached);
}
Path glyph = new Path();
glyph.addPath(cached);
return glyph;
}
private int getIndex(char ch) {
int[] bin = data[ch >> 8];
if (bin == null) return 0;
return bin[ch & 0xFF];
}
}
@@ -98,6 +98,7 @@ class TSpanShadowNode extends TextShadowNode {
GlyphContext gc = getTextRootGlyphContext();
FontData font = gc.getFont();
applyTextPropertiesToPaint(paint, font);
GlyphPathBag bag = new GlyphPathBag(paint);
/*
Determine the startpoint-on-the-path for the first glyph using attribute startOffset
@@ -127,7 +128,6 @@ class TSpanShadowNode extends TextShadowNode {
double distance = 0;
PathMeasure pm = null;
double renderMethodScaling = 1;
if (textPath != null) {
pm = new PathMeasure(textPath.getPath(), false);
distance = pm.getLength();
@@ -142,12 +142,10 @@ class TSpanShadowNode extends TextShadowNode {
// https://svgwg.org/svg2-draft/text.html#TextPathElementSpacingAttribute
}
*/
final TextPathMethod method = textPath.getMethod();
if (method == TextPathMethod.stretch) {
renderMethodScaling = distance / textMeasure;
}
}
double renderMethodScaling = getRenderMethodScaling(textMeasure, distance);
/*
*
* Three properties affect the space between characters and words:
@@ -427,8 +425,7 @@ class TSpanShadowNode extends TextShadowNode {
mid.preRotate((float) r);
Path glyph = new Path();
paint.getTextPath(current, 0, 1, 0, 0, glyph);
Path glyph = bag.getOrCreateAndCache(currentChar, current);
glyph.transform(mid);
path.addPath(glyph);
}
@@ -436,6 +433,13 @@ class TSpanShadowNode extends TextShadowNode {
return path;
}
private double getRenderMethodScaling(double textMeasure, double distance) {
if (textPath != null && textPath.getMethod() == TextPathMethod.stretch) {
return distance / textMeasure;
}
return 1;
}
private double getAbsoluteStartOffset(double distance, double size, String startOffset) {
return PropHelper.fromRelative(startOffset, distance, 0, mScale, size);
}