mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-20 14:05:09 +00:00
First letterSpacing implementation attempt
This commit is contained in:
@@ -37,6 +37,8 @@ public class GlyphContext {
|
|||||||
private float mHeight;
|
private float mHeight;
|
||||||
private int mContextLength = 0;
|
private int mContextLength = 0;
|
||||||
private static final float DEFAULT_FONT_SIZE = 12f;
|
private static final float DEFAULT_FONT_SIZE = 12f;
|
||||||
|
private static final float DEFAULT_KERNING = 0f;
|
||||||
|
private static final float DEFAULT_LETTER_SPACING = 0f;
|
||||||
|
|
||||||
GlyphContext(float scale, float width, float height) {
|
GlyphContext(float scale, float width, float height) {
|
||||||
mScale = scale;
|
mScale = scale;
|
||||||
@@ -171,7 +173,11 @@ public class GlyphContext {
|
|||||||
public ReadableMap getGlyphFont() {
|
public ReadableMap getGlyphFont() {
|
||||||
String fontFamily = null;
|
String fontFamily = null;
|
||||||
float fontSize = DEFAULT_FONT_SIZE;
|
float fontSize = DEFAULT_FONT_SIZE;
|
||||||
|
float kerning = DEFAULT_KERNING;
|
||||||
|
float letterSpacing = DEFAULT_LETTER_SPACING;
|
||||||
boolean fontSizeSet = false;
|
boolean fontSizeSet = false;
|
||||||
|
boolean kerningSet = false;
|
||||||
|
boolean letterSpacingSet = false;
|
||||||
String fontWeight = null;
|
String fontWeight = null;
|
||||||
String fontStyle = null;
|
String fontStyle = null;
|
||||||
|
|
||||||
@@ -189,6 +195,18 @@ public class GlyphContext {
|
|||||||
fontSizeSet = true;
|
fontSizeSet = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: add support for other length units
|
||||||
|
if (!kerningSet && font.hasKey("kerning")) {
|
||||||
|
kerning = Float.valueOf(font.getString("kerning"));
|
||||||
|
kerningSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add support for other length units
|
||||||
|
if (!letterSpacingSet && font.hasKey("letterSpacing")) {
|
||||||
|
letterSpacing = Float.valueOf(font.getString("letterSpacing"));
|
||||||
|
letterSpacingSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (fontWeight == null && font.hasKey("fontWeight")) {
|
if (fontWeight == null && font.hasKey("fontWeight")) {
|
||||||
fontWeight = font.getString("fontWeight");
|
fontWeight = font.getString("fontWeight");
|
||||||
}
|
}
|
||||||
@@ -196,7 +214,7 @@ public class GlyphContext {
|
|||||||
fontStyle = font.getString("fontStyle");
|
fontStyle = font.getString("fontStyle");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fontFamily != null && fontSizeSet && fontWeight != null && fontStyle != null) {
|
if (fontFamily != null && fontSizeSet && kerningSet && letterSpacingSet && fontWeight != null && fontStyle != null) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,6 +224,8 @@ public class GlyphContext {
|
|||||||
map.putDouble("fontSize", fontSize);
|
map.putDouble("fontSize", fontSize);
|
||||||
map.putString("fontWeight", fontWeight);
|
map.putString("fontWeight", fontWeight);
|
||||||
map.putString("fontStyle", fontStyle);
|
map.putString("fontStyle", fontStyle);
|
||||||
|
map.putDouble("kerning", kerning);
|
||||||
|
map.putDouble("letterSpacing", letterSpacing);
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ public class TSpanShadowNode extends TextShadowNode {
|
|||||||
private static final String PROP_FONT_SIZE = "fontSize";
|
private static final String PROP_FONT_SIZE = "fontSize";
|
||||||
private static final String PROP_FONT_STYLE = "fontStyle";
|
private static final String PROP_FONT_STYLE = "fontStyle";
|
||||||
private static final String PROP_FONT_WEIGHT = "fontWeight";
|
private static final String PROP_FONT_WEIGHT = "fontWeight";
|
||||||
|
private static final String PROP_KERNING = "kerning";
|
||||||
|
private static final String PROP_LETTER_SPACING = "letterSpacing";
|
||||||
|
|
||||||
@ReactProp(name = "content")
|
@ReactProp(name = "content")
|
||||||
public void setContent(@Nullable String content) {
|
public void setContent(@Nullable String content) {
|
||||||
@@ -101,12 +103,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 * 1.2f, width);
|
PointF glyphPoint = getGlyphPointFromContext(glyphPosition, 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 + width / 2);
|
matrix = mBezierTransformer.getTransformAtDistance(glyphPoint.x * 1.2f + glyphDelta.x + width / 2);
|
||||||
|
|
||||||
if (textPathHasReachedEnd()) {
|
if (textPathHasReachedEnd()) {
|
||||||
break;
|
break;
|
||||||
@@ -132,10 +134,22 @@ public class TSpanShadowNode extends TextShadowNode {
|
|||||||
|
|
||||||
paint.setTextAlign(Paint.Align.LEFT);
|
paint.setTextAlign(Paint.Align.LEFT);
|
||||||
|
|
||||||
float fontSize = (float)font.getDouble(PROP_FONT_SIZE);
|
float fontSize = (float)font.getDouble(PROP_FONT_SIZE) * mScale;
|
||||||
|
float kerning = (float)font.getDouble(PROP_KERNING);
|
||||||
|
float letterSpacing = (float)font.getDouble(PROP_LETTER_SPACING);
|
||||||
|
|
||||||
paint.setTextSize(fontSize * mScale);
|
if (mBezierTransformer == null) {
|
||||||
|
letterSpacing *= mScale;
|
||||||
|
} else {
|
||||||
|
// What is going on here? This helps get closer to how e.g. chrome renders things
|
||||||
|
// But, still off, depending on the font size and letter-spacing.
|
||||||
|
letterSpacing *= java.lang.Math.pow(120 / fontSize, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
paint.setTextSize(fontSize);
|
||||||
|
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
|
||||||
|
paint.setLetterSpacing(letterSpacing / fontSize); // setLetterSpacing is only available from LOLLIPOP and on
|
||||||
|
}
|
||||||
|
|
||||||
boolean isBold = font.hasKey(PROP_FONT_WEIGHT) && "bold".equals(font.getString(PROP_FONT_WEIGHT));
|
boolean isBold = font.hasKey(PROP_FONT_WEIGHT) && "bold".equals(font.getString(PROP_FONT_WEIGHT));
|
||||||
boolean isItalic = font.hasKey(PROP_FONT_STYLE) && "italic".equals(font.getString(PROP_FONT_STYLE));
|
boolean isItalic = font.hasKey(PROP_FONT_STYLE) && "italic".equals(font.getString(PROP_FONT_STYLE));
|
||||||
|
|||||||
@@ -23,7 +23,9 @@ function fontDiffer(a, b) {
|
|||||||
return a.fontSize !== b.fontSize ||
|
return a.fontSize !== b.fontSize ||
|
||||||
a.fontFamily !== b.fontFamily ||
|
a.fontFamily !== b.fontFamily ||
|
||||||
a.fontStyle !== b.fontStyle ||
|
a.fontStyle !== b.fontStyle ||
|
||||||
a.fontWeight !== b.fontWeight;
|
a.fontWeight !== b.fontWeight ||
|
||||||
|
a.kerning !== b.kerning ||
|
||||||
|
a.letterSpacing !== b.letterSpacing;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ViewBoxAttributes = {
|
const ViewBoxAttributes = {
|
||||||
|
|||||||
@@ -55,7 +55,9 @@ export function extractFont(props) {
|
|||||||
fontFamily: extractSingleFontFamily(props.fontFamily),
|
fontFamily: extractSingleFontFamily(props.fontFamily),
|
||||||
fontSize: isNaN(fontSize) ? null : fontSize,
|
fontSize: isNaN(fontSize) ? null : fontSize,
|
||||||
fontWeight: props.fontWeight,
|
fontWeight: props.fontWeight,
|
||||||
fontStyle: props.fontStyle
|
fontStyle: props.fontStyle,
|
||||||
|
kerning: props.kerning,
|
||||||
|
letterSpacing: props.letterSpacing,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeof props.font === 'string') {
|
if (typeof props.font === 'string') {
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ const fontProps = {
|
|||||||
fontSize: numberProp,
|
fontSize: numberProp,
|
||||||
fontWeight: numberProp,
|
fontWeight: numberProp,
|
||||||
fontStyle: PropTypes.string,
|
fontStyle: PropTypes.string,
|
||||||
|
letterSpacing: PropTypes.string,
|
||||||
|
kerning: PropTypes.string,
|
||||||
font: PropTypes.object
|
font: PropTypes.object
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user