diff --git a/android/src/main/java/com/horcrux/svg/FontData.java b/android/src/main/java/com/horcrux/svg/FontData.java index 71e9ea73..c8e64303 100644 --- a/android/src/main/java/com/horcrux/svg/FontData.java +++ b/android/src/main/java/com/horcrux/svg/FontData.java @@ -29,7 +29,6 @@ class FontData { final TextAnchor textAnchor; final TextDecoration textDecoration; - final AlignmentBaseline alignmentBaseline; final double kerning; final double wordSpacing; @@ -46,7 +45,6 @@ class FontData { textAnchor = TextAnchor.start; textDecoration = TextDecoration.None; - alignmentBaseline = AlignmentBaseline.baseline; manualKerning = false; kerning = DEFAULT_KERNING; @@ -87,7 +85,6 @@ class FontData { textAnchor = font.hasKey(TEXT_ANCHOR) ? TextAnchor.valueOf(font.getString(TEXT_ANCHOR)) : parent.textAnchor; textDecoration = font.hasKey(TEXT_DECORATION) ? TextDecoration.getEnum(font.getString(TEXT_DECORATION)) : parent.textDecoration; - alignmentBaseline = font.hasKey(ALIGNMENT_BASELINE) ? AlignmentBaseline.getEnum(font.getString(ALIGNMENT_BASELINE)) : parent.alignmentBaseline; final boolean hasKerning = font.hasKey(KERNING); manualKerning = hasKerning || parent.manualKerning; diff --git a/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java b/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java index 74882811..7e1bd10f 100644 --- a/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/TSpanShadowNode.java @@ -336,84 +336,86 @@ class TSpanShadowNode extends TextShadowNode { text-before-edge = text-top text-after-edge = text-bottom */ - double baselineShift; - switch (font.alignmentBaseline) { - // https://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling - default: - case baseline: - // Use the dominant baseline choice of the parent. - // Match the box’s corresponding baseline to that of its parent. - baselineShift = 0; - break; + double baselineShift = 0; + if (mAlignmentBaseline != null) { + switch (mAlignmentBaseline) { + // https://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling + default: + case baseline: + // Use the dominant baseline choice of the parent. + // Match the box’s corresponding baseline to that of its parent. + baselineShift = 0; + break; - case textBottom: - // Match the bottom of the box to the bottom of the parent’s content area. - // text-after-edge = text-bottom - // text-after-edge = descender depth - baselineShift = descent; - break; + case textBottom: + // Match the bottom of the box to the bottom of the parent’s content area. + // text-after-edge = text-bottom + // text-after-edge = descender depth + baselineShift = descent; + break; - case alphabetic: - // Match the box’s alphabetic baseline to that of its parent. - // alphabetic = 0 - baselineShift = 0; - break; + case alphabetic: + // Match the box’s alphabetic baseline to that of its parent. + // alphabetic = 0 + baselineShift = 0; + break; - case ideographic: - // Match the box’s ideographic character face under-side baseline to that of its parent. - // ideographic = descender depth - baselineShift = descent; - break; + case ideographic: + // Match the box’s ideographic character face under-side baseline to that of its parent. + // ideographic = descender depth + baselineShift = descent; + break; - case middle: - // Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent. - // middle = x height / 2 - Rect bounds = new Rect(); - // this will just retrieve the bounding rect for 'x' - paint.getTextBounds("x", 0, 1, bounds); - int xHeight = bounds.height(); - baselineShift = xHeight / 2; - break; + case middle: + // Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent. + // middle = x height / 2 + Rect bounds = new Rect(); + // this will just retrieve the bounding rect for 'x' + paint.getTextBounds("x", 0, 1, bounds); + int xHeight = bounds.height(); + baselineShift = xHeight / 2; + break; - case central: - // Match the box’s central baseline to the central baseline of its parent. - // central = (ascender height - descender depth) / 2 - baselineShift = (ascent - descent) / 2; - break; + case central: + // Match the box’s central baseline to the central baseline of its parent. + // central = (ascender height - descender depth) / 2 + baselineShift = (ascent - descent) / 2; + break; - case mathematical: - // Match the box’s mathematical baseline to that of its parent. - // Hanging and mathematical baselines - // There are no obvious formulas to calculate the position of these baselines. - // At the time of writing FOP puts the hanging baseline at 80% of the ascender - // height and the mathematical baseline at 50%. - baselineShift = ascent / 2; - break; + case mathematical: + // Match the box’s mathematical baseline to that of its parent. + // Hanging and mathematical baselines + // There are no obvious formulas to calculate the position of these baselines. + // At the time of writing FOP puts the hanging baseline at 80% of the ascender + // height and the mathematical baseline at 50%. + baselineShift = ascent / 2; + break; - case textTop: - // Match the top of the box to the top of the parent’s content area. - // text-before-edge = text-top - // text-before-edge = ascender height - baselineShift = ascent; - break; + case textTop: + // Match the top of the box to the top of the parent’s content area. + // text-before-edge = text-top + // text-before-edge = ascender height + baselineShift = ascent; + break; - case bottom: - // Align the top of the aligned subtree with the top of the line box. - baselineShift = bottom; - break; + case bottom: + // Align the top of the aligned subtree with the top of the line box. + baselineShift = bottom; + break; - case center: - // Align the center of the aligned subtree with the center of the line box. - baselineShift = totalHeight / 2; - break; + case center: + // Align the center of the aligned subtree with the center of the line box. + baselineShift = totalHeight / 2; + break; - case top: - // Align the bottom of the aligned subtree with the bottom of the line box. - baselineShift = top; - break; + case top: + // Align the bottom of the aligned subtree with the bottom of the line box. + baselineShift = top; + break; + } } - mid.preTranslate((float) -halfway, (float) (dy + baselineShift)); + mid.preTranslate((float) -halfway, (float) (dy - baselineShift)); mid.preScale((float) renderMethodScaling, (float) renderMethodScaling); mid.postTranslate(0, (float) y); } else { diff --git a/android/src/main/java/com/horcrux/svg/TextPathShadowNode.java b/android/src/main/java/com/horcrux/svg/TextPathShadowNode.java index 9ef406e7..6223e1f7 100644 --- a/android/src/main/java/com/horcrux/svg/TextPathShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/TextPathShadowNode.java @@ -26,6 +26,7 @@ class TextPathShadowNode extends TextShadowNode { private @Nullable String mStartOffset; private TextPathMethod mMethod = TextPathMethod.align; private TextPathSpacing mSpacing = TextPathSpacing.exact; + private TextPathSide mSide; @ReactProp(name = "href") public void setHref(String href) { @@ -51,6 +52,12 @@ class TextPathShadowNode extends TextShadowNode { markUpdated(); } + @ReactProp(name = "side") + public void setSide(@Nullable String side) { + mSide = TextPathSide.valueOf(side); + markUpdated(); + } + TextPathMethod getMethod() { return mMethod; } @@ -59,6 +66,10 @@ class TextPathShadowNode extends TextShadowNode { return mSpacing; } + public TextPathSide getSide() { + return mSide; + } + String getStartOffset() { return mStartOffset; } diff --git a/android/src/main/java/com/horcrux/svg/TextShadowNode.java b/android/src/main/java/com/horcrux/svg/TextShadowNode.java index 01d45f6d..dd9d7c77 100644 --- a/android/src/main/java/com/horcrux/svg/TextShadowNode.java +++ b/android/src/main/java/com/horcrux/svg/TextShadowNode.java @@ -24,12 +24,19 @@ import javax.annotation.Nullable; */ class TextShadowNode extends GroupShadowNode { + AlignmentBaseline mAlignmentBaseline; private @Nullable ReadableArray mPositionX; private @Nullable ReadableArray mPositionY; private @Nullable ReadableArray mRotate; private @Nullable ReadableArray mDeltaX; private @Nullable ReadableArray mDeltaY; + @ReactProp(name = "alignmentBaseline") + public void setMethod(@Nullable String alignment) { + mAlignmentBaseline = AlignmentBaseline.valueOf(alignment); + markUpdated(); + } + @ReactProp(name = "rotate") public void setRotate(@Nullable ReadableArray rotate) { mRotate = rotate; diff --git a/elements/TextPath.js b/elements/TextPath.js index 24627f23..a286ac1d 100644 --- a/elements/TextPath.js +++ b/elements/TextPath.js @@ -15,7 +15,7 @@ export default class extends Shape { static propTypes = textPathProps; render() { - let {children, href, startOffset, method, spacing, side, ...props} = this.props; + let {children, href, startOffset, method, spacing, side, alignmentBaseline, ...props} = this.props; if (href) { let matched = href.match(idExpReg); @@ -23,11 +23,11 @@ export default class extends Shape { href = matched[1]; startOffset = `${startOffset || 0}`; return