mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-05-24 19:48:46 +00:00
Implement GlyphPathBag for caching Paths per char, after a applyTextPropertiesToPaint(paint, font)
Path glyph = bag.getOrCreateAndCache(currentChar, current);
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user