First letterSpacing implementation attempt

This commit is contained in:
Mikael Sand
2017-06-20 22:04:41 +03:00
parent a168a2ae6d
commit dac969b944
5 changed files with 47 additions and 7 deletions

View File

@@ -37,6 +37,8 @@ public class GlyphContext {
private float mHeight;
private int mContextLength = 0;
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) {
mScale = scale;
@@ -171,7 +173,11 @@ public class GlyphContext {
public ReadableMap getGlyphFont() {
String fontFamily = null;
float fontSize = DEFAULT_FONT_SIZE;
float kerning = DEFAULT_KERNING;
float letterSpacing = DEFAULT_LETTER_SPACING;
boolean fontSizeSet = false;
boolean kerningSet = false;
boolean letterSpacingSet = false;
String fontWeight = null;
String fontStyle = null;
@@ -189,6 +195,18 @@ public class GlyphContext {
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")) {
fontWeight = font.getString("fontWeight");
}
@@ -196,7 +214,7 @@ public class GlyphContext {
fontStyle = font.getString("fontStyle");
}
if (fontFamily != null && fontSizeSet && fontWeight != null && fontStyle != null) {
if (fontFamily != null && fontSizeSet && kerningSet && letterSpacingSet && fontWeight != null && fontStyle != null) {
break;
}
}
@@ -206,6 +224,8 @@ public class GlyphContext {
map.putDouble("fontSize", fontSize);
map.putString("fontWeight", fontWeight);
map.putString("fontStyle", fontStyle);
map.putDouble("kerning", kerning);
map.putDouble("letterSpacing", letterSpacing);
return map;
}

View File

@@ -39,6 +39,8 @@ public class TSpanShadowNode extends TextShadowNode {
private static final String PROP_FONT_SIZE = "fontSize";
private static final String PROP_FONT_STYLE = "fontStyle";
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")
public void setContent(@Nullable String content) {
@@ -101,12 +103,12 @@ public class TSpanShadowNode extends TextShadowNode {
paint.getTextPath(letter, 0, 1, 0, 0, glyph);
PointF glyphDelta = getGlyphDeltaFromContext();
PointF glyphPoint = getGlyphPointFromContext(glyphPosition * 1.2f, width);
PointF glyphPoint = getGlyphPointFromContext(glyphPosition, width);
glyphPosition += width;
Matrix matrix = new Matrix();
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()) {
break;
@@ -132,10 +134,22 @@ public class TSpanShadowNode extends TextShadowNode {
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 isItalic = font.hasKey(PROP_FONT_STYLE) && "italic".equals(font.getString(PROP_FONT_STYLE));

View File

@@ -23,7 +23,9 @@ function fontDiffer(a, b) {
return a.fontSize !== b.fontSize ||
a.fontFamily !== b.fontFamily ||
a.fontStyle !== b.fontStyle ||
a.fontWeight !== b.fontWeight;
a.fontWeight !== b.fontWeight ||
a.kerning !== b.kerning ||
a.letterSpacing !== b.letterSpacing;
}
const ViewBoxAttributes = {

View File

@@ -55,7 +55,9 @@ export function extractFont(props) {
fontFamily: extractSingleFontFamily(props.fontFamily),
fontSize: isNaN(fontSize) ? null : fontSize,
fontWeight: props.fontWeight,
fontStyle: props.fontStyle
fontStyle: props.fontStyle,
kerning: props.kerning,
letterSpacing: props.letterSpacing,
};
if (typeof props.font === 'string') {

View File

@@ -53,6 +53,8 @@ const fontProps = {
fontSize: numberProp,
fontWeight: numberProp,
fontStyle: PropTypes.string,
letterSpacing: PropTypes.string,
kerning: PropTypes.string,
font: PropTypes.object
};