mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-04 23:54:53 +00:00
[Android] Attempt to fix text-anchor subtree advance/extent calculation
Related to https://github.com/react-native-community/react-native-svg/issues/600 https://github.com/react-native-community/react-native-svg/issues/570
This commit is contained in:
@@ -21,6 +21,7 @@ import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Typeface;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
@@ -106,6 +107,50 @@ class TSpanView extends TextView {
|
||||
return mPath;
|
||||
}
|
||||
|
||||
double getSubtreeTextChunksTotalAdvance(Paint paint) {
|
||||
double advance = 0;
|
||||
|
||||
if (mContent == null) {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child instanceof TextView) {
|
||||
TextView text = (TextView)child;
|
||||
advance += text.getSubtreeTextChunksTotalAdvance(paint);
|
||||
}
|
||||
}
|
||||
return advance;
|
||||
}
|
||||
|
||||
String line = mContent;
|
||||
final int length = line.length();
|
||||
|
||||
if (length == 0) {
|
||||
return advance;
|
||||
}
|
||||
|
||||
GlyphContext gc = getTextRootGlyphContext();
|
||||
FontData font = gc.getFont();
|
||||
applyTextPropertiesToPaint(paint, font);
|
||||
|
||||
double letterSpacing = font.letterSpacing;
|
||||
final boolean allowOptionalLigatures = letterSpacing == 0 &&
|
||||
font.fontVariantLigatures == FontVariantLigatures.normal;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
String required = "'rlig', 'liga', 'clig', 'calt', 'locl', 'ccmp', 'mark', 'mkmk',";
|
||||
String defaultFeatures = required + "'kern', ";
|
||||
if (allowOptionalLigatures) {
|
||||
String additionalLigatures = "'hlig', 'cala', ";
|
||||
paint.setFontFeatureSettings(defaultFeatures + additionalLigatures + font.fontFeatureSettings);
|
||||
} else {
|
||||
String disableDiscretionaryLigatures = "'liga' 0, 'clig' 0, 'dlig' 0, 'hlig' 0, 'cala' 0, ";
|
||||
paint.setFontFeatureSettings(defaultFeatures + disableDiscretionaryLigatures + font.fontFeatureSettings);
|
||||
}
|
||||
}
|
||||
|
||||
return paint.measureText(line);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private Path getLinePath(String line, Paint paint, Canvas canvas) {
|
||||
final int length = line.length();
|
||||
@@ -311,8 +356,10 @@ class TSpanView extends TextView {
|
||||
attributes, such as a ‘dx’ attribute value on a ‘tspan’ element.
|
||||
*/
|
||||
final TextAnchor textAnchor = font.textAnchor;
|
||||
final double textMeasure = paint.measureText(line);
|
||||
TextView anchorRoot = getTextAnchorRoot();
|
||||
final double textMeasure = anchorRoot.getSubtreeTextChunksTotalAdvance(paint);
|
||||
double offset = getTextAnchorOffset(textAnchor, textMeasure);
|
||||
applyTextPropertiesToPaint(paint, font);
|
||||
|
||||
int side = 1;
|
||||
double startOfRendering = 0;
|
||||
|
||||
@@ -14,6 +14,7 @@ import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Region;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
@@ -38,6 +39,7 @@ class TextView extends GroupView {
|
||||
@Nullable ArrayList<SVGLength> mRotate;
|
||||
@Nullable ArrayList<SVGLength> mDeltaX;
|
||||
@Nullable ArrayList<SVGLength> mDeltaY;
|
||||
double cachedAdvance = Double.NaN;
|
||||
|
||||
public TextView(ReactContext reactContext) {
|
||||
super(reactContext);
|
||||
@@ -48,6 +50,7 @@ class TextView extends GroupView {
|
||||
if (mPath == null) {
|
||||
return;
|
||||
}
|
||||
cachedAdvance = Double.NaN;
|
||||
super.invalidate();
|
||||
clearChildCache();
|
||||
}
|
||||
@@ -207,4 +210,42 @@ class TextView extends GroupView {
|
||||
boolean isTextNode = !(this instanceof TextPathView) && !(this instanceof TSpanView);
|
||||
getTextRootGlyphContext().pushContext(isTextNode, this, mFont, mPositionX, mPositionY, mDeltaX, mDeltaY, mRotate);
|
||||
}
|
||||
|
||||
TextView getTextAnchorRoot() {
|
||||
GlyphContext gc = getTextRootGlyphContext();
|
||||
FontData font = gc.getFont();
|
||||
TextProperties.TextAnchor textAnchor = font.textAnchor;
|
||||
if (textAnchor == TextProperties.TextAnchor.start) {
|
||||
return this;
|
||||
}
|
||||
ViewParent parent = this.getParent();
|
||||
if (parent instanceof TextView) {
|
||||
TextView parentText = (TextView)parent;
|
||||
GlyphContext parentGc = parentText.getGlyphContext();
|
||||
FontData parentFont = parentGc.getFont();
|
||||
if (parentFont.textAnchor == TextProperties.TextAnchor.start) {
|
||||
return this;
|
||||
} else {
|
||||
return parentText.getTextAnchorRoot();
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
double getSubtreeTextChunksTotalAdvance(Paint paint) {
|
||||
if (!Double.isNaN(cachedAdvance)) {
|
||||
return cachedAdvance;
|
||||
}
|
||||
double advance = 0;
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child instanceof TextView) {
|
||||
TextView text = (TextView)child;
|
||||
advance += text.getSubtreeTextChunksTotalAdvance(paint);
|
||||
}
|
||||
}
|
||||
cachedAdvance = advance;
|
||||
return advance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user