Implement baselineShift and verticalAlign (preferred).

Transverse Box Alignment, specifies how an inline-level box is aligned within the line, and by how much the box is shifted up from its alignment point.
 https://drafts.csswg.org/css-inline/#propdef-vertical-align
 https://www.w3.org/TR/css-inline-3/#propdef-baseline-shift
 https://www.w3.org/TR/css-inline-3/#transverse-alignment
This commit is contained in:
Mikael Sand
2017-08-04 16:29:06 +03:00
parent 2939584d1b
commit fe7e8b2b65
5 changed files with 155 additions and 0 deletions

View File

@@ -438,6 +438,7 @@ class TSpanShadowNode extends TextShadowNode {
final double descenderDepth = fm.descent;
final double totalHeight = top + bottom;
double baselineShift = 0;
String baselineShiftString = getBaselineShift();
AlignmentBaseline baseline = getAlignmentBaseline();
if (baseline != null) {
// TODO alignment-baseline, test / verify behavior
@@ -525,6 +526,59 @@ class TSpanShadowNode extends TextShadowNode {
baselineShift = top;
break;
}
/*
2.2.2. Alignment Shift: baseline-shift longhand
This property specifies by how much the box is shifted up from its alignment point.
It does not apply when alignment-baseline is top or bottom.
Authors should use the vertical-align shorthand instead of this property.
Values have the following meanings:
<length>
Raise (positive value) or lower (negative value) by the specified length.
<percentage>
Raise (positive value) or lower (negative value) by the specified percentage of the line-height.
TODO sub
Lower by the offset appropriate for subscripts of the parents box.
(The UA should use the parents font data to find this offset whenever possible.)
TODO super
Raise by the offset appropriate for superscripts of the parents box.
(The UA should use the parents font data to find this offset whenever possible.)
User agents may additionally support the keyword baseline as computing to 0
if is necessary for them to support legacy SVG content.
Issue: We would prefer to remove this,
and are looking for feedback from SVG user agents as to whether its necessary.
https://www.w3.org/TR/css-inline-3/#propdef-baseline-shift
*/
if (baselineShiftString != null) {
switch (baseline) {
case top:
case bottom:
break;
default:
switch (baselineShiftString) {
case "sub":
// TODO
break;
case "super":
// TODO
break;
case "baseline":
break;
default:
baselineShift -= PropHelper.fromRelative(baselineShiftString, fontSize, 0, mScale, fontSize);
}
break;
}
}
}
final Matrix start = new Matrix();

View File

@@ -26,6 +26,7 @@ import javax.annotation.Nullable;
class TextShadowNode extends GroupShadowNode {
String mTextLength = null;
String mBaselineShift = null;
TextLengthAdjust mLengthAdjust = TextLengthAdjust.spacing;
private AlignmentBaseline mAlignmentBaseline;
private @Nullable ReadableArray mPositionX;
@@ -52,6 +53,34 @@ class TextShadowNode extends GroupShadowNode {
markUpdated();
}
@ReactProp(name = "baselineShift")
public void setBaselineShift(@Nullable String baselineShift) {
mBaselineShift = baselineShift;
markUpdated();
}
@ReactProp(name = "verticalAlign")
public void setVerticalAlign(@Nullable String verticalAlign) {
if (verticalAlign != null) {
verticalAlign = verticalAlign.trim();
int i = verticalAlign.lastIndexOf(' ');
try {
mAlignmentBaseline = AlignmentBaseline.getEnum(verticalAlign.substring(i));
} catch (IllegalArgumentException e) {
mAlignmentBaseline = AlignmentBaseline.baseline;
}
try {
mBaselineShift = verticalAlign.substring(0, i);
} catch (IndexOutOfBoundsException e) {
mBaselineShift = null;
}
} else {
mAlignmentBaseline = AlignmentBaseline.baseline;
mBaselineShift = null;
}
markUpdated();
}
@ReactProp(name = "rotate")
public void setRotate(@Nullable ReadableArray rotate) {
mRotate = rotate;
@@ -122,9 +151,30 @@ class TextShadowNode extends GroupShadowNode {
parent = parent.getParent();
}
}
if (mAlignmentBaseline == null) {
mAlignmentBaseline = AlignmentBaseline.baseline;
}
return mAlignmentBaseline;
}
String getBaselineShift() {
if (mBaselineShift == null) {
ReactShadowNode parent = this.getParent();
while (parent != null) {
if (parent instanceof TextShadowNode) {
TextShadowNode node = (TextShadowNode)parent;
final String baselineShift = node.mBaselineShift;
if (baselineShift != null) {
mBaselineShift = baselineShift;
return baselineShift;
}
}
parent = parent.getParent();
}
}
return mBaselineShift;
}
void releaseCachedPath() {
traverseChildren(new NodeRunnable() {
public void run(VirtualNode node) {

View File

@@ -112,6 +112,8 @@ const PathAttributes = {
const TextSpecificAttributes = {
...RenderableAttributes,
alignmentBaseline: true,
baselineShift: true,
verticalAlign: true,
lengthAdjust: true,
textLength: true,
};

View File

@@ -94,6 +94,8 @@ export default function(props, container) {
dx,
dy,
alignmentBaseline,
baselineShift,
verticalAlign,
} = props;
let {
rotate,
@@ -137,5 +139,7 @@ export default function(props, container) {
deltaX,
deltaY,
alignmentBaseline,
baselineShift,
verticalAlign,
};
}

View File

@@ -197,6 +197,29 @@ const lengthAdjust = PropTypes.oneOf(['spacing', 'spacingAndGlyphs']);
*/
const textLength = PropTypes.string;
/*
2.2. Transverse Box Alignment: the vertical-align property
Name: vertical-align
Value: <baseline-shift> || <alignment-baseline>
Initial: baseline
Applies to: inline-level boxes
Inherited: no
Percentages: N/A
Media: visual
Computed value: as specified
Canonical order: per grammar
Animation type: discrete
This shorthand property specifies how an inline-level box is aligned within the line.
Values are the same as for its longhand properties, see below.
Authors should use this property (vertical-align) instead of its longhands.
https://www.w3.org/TR/css-inline-3/#transverse-alignment
https://drafts.csswg.org/css-inline/#propdef-vertical-align
*/
const verticalAlign = PropTypes.string;
/*
Name: alignment-baseline
@@ -217,10 +240,32 @@ const textLength = PropTypes.string;
*/
const alignmentBaseline = PropTypes.oneOf(['baseline', 'text-bottom', 'alphabetic', 'ideographic', 'middle', 'central', 'mathematical', 'text-top', 'bottom', 'center', 'top', 'text-before-edge', 'text-after-edge', 'before-edge', 'after-edge', 'hanging']);
/*
2.2.2. Alignment Shift: baseline-shift longhand
Name: baseline-shift
Value: <length> | <percentage> | sub | super
Initial: 0
Applies to: inline-level boxes
Inherited: no
Percentages: refer to the used value of line-height
Media: visual
Computed value: absolute length, percentage, or keyword specified
Animation type: discrete
This property specifies by how much the box is shifted up from its alignment point.
It does not apply when alignment-baseline is top or bottom.
https://www.w3.org/TR/css-inline-3/#propdef-baseline-shift
*/
const baselineShift = PropTypes.oneOfType([PropTypes.oneOf(['sub', 'super', 'baseline']), PropTypes.arrayOf(numberProp), PropTypes.string]);
const textSpecificProps = {
...pathProps,
...fontProps,
alignmentBaseline,
baselineShift,
verticalAlign,
lengthAdjust,
textLength,
};