protected Map getAttributeMap(BridgeContext ctx,
Element element,
TextPath textPath,
Integer bidiLevel,
Map result) {
SVGTextContentElement tce = null;
if (element instanceof SVGTextContentElement) {
// 'a' elements aren't SVGTextContentElements, so they shouldn't
// be checked for 'textLength' or 'lengthAdjust' attributes.
tce = (SVGTextContentElement) element;
}
Map inheritMap = null;
String s;
if (SVG_NAMESPACE_URI.equals(element.getNamespaceURI()) &&
element.getLocalName().equals(SVG_ALT_GLYPH_TAG)) {
result.put(ALT_GLYPH_HANDLER,
new SVGAltGlyphHandler(ctx, element));
}
// Add null TPI objects to the text (after we set it on the
// Text we will swap in the correct values.
TextPaintInfo pi = new TextPaintInfo();
// Set some basic props so we can get bounds info for complex paints.
pi.visible = true;
pi.fillPaint = Color.black;
result.put(PAINT_INFO, pi);
elemTPI.put(element, pi);
if (textPath != null) {
result.put(TEXTPATH, textPath);
}
// Text-anchor
TextNode.Anchor a = TextUtilities.convertTextAnchor(element);
result.put(ANCHOR_TYPE, a);
// Font family
List fontList = getFontList(ctx, element, result);
result.put(GVT_FONTS, fontList);
// Text baseline adjustment.
Object bs = TextUtilities.convertBaselineShift(element);
if (bs != null) {
result.put(BASELINE_SHIFT, bs);
}
// Unicode-bidi mode
Value val = CSSUtilities.getComputedStyle
(element, SVGCSSEngine.UNICODE_BIDI_INDEX);
s = val.getStringValue();
if (s.charAt(0) == 'n') {
if (bidiLevel != null)
result.put(TextAttribute.BIDI_EMBEDDING, bidiLevel);
} else {
// Text direction
// XXX: this needs to coordinate with the unicode-bidi
// property, so that when an explicit reversal
// occurs, the BIDI_EMBEDDING level is
// appropriately incremented or decremented.
// Note that direction is implicitly handled by unicode
// BiDi algorithm in most cases, this property
// is only needed when one wants to override the
// normal writing direction for a string/substring.
val = CSSUtilities.getComputedStyle
(element, SVGCSSEngine.DIRECTION_INDEX);
String rs = val.getStringValue();
int cbidi = 0;
if (bidiLevel != null) cbidi = bidiLevel.intValue();
// We don't care if it was embed or override we just want
// it's level here. So map override to positive value.
if (cbidi < 0) cbidi = -cbidi;
switch (rs.charAt(0)) {
case 'l':
result.put(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_LTR);
if ((cbidi & 0x1) == 1) cbidi++; // was odd now even
else cbidi+=2; // next greater even number
break;
case 'r':
result.put(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_RTL);
if ((cbidi & 0x1) == 1) cbidi+=2; // next greater odd number
else cbidi++; // was even now odd
break;
}
switch (s.charAt(0)) {
case 'b': // bidi-override
cbidi = -cbidi; // For bidi-override we want a negative number.
break;
}
result.put(TextAttribute.BIDI_EMBEDDING, new Integer(cbidi));
}
// Writing mode
val = CSSUtilities.getComputedStyle
(element, SVGCSSEngine.WRITING_MODE_INDEX);
s = val.getStringValue();
switch (s.charAt(0)) {
case 'l':
result.put(GVTAttributedCharacterIterator.
TextAttribute.WRITING_MODE,
GVTAttributedCharacterIterator.
TextAttribute.WRITING_MODE_LTR);
break;
case 'r':
result.put(GVTAttributedCharacterIterator.
TextAttribute.WRITING_MODE,
GVTAttributedCharacterIterator.
TextAttribute.WRITING_MODE_RTL);
break;
case 't':
result.put(GVTAttributedCharacterIterator.
TextAttribute.WRITING_MODE,
GVTAttributedCharacterIterator.
TextAttribute.WRITING_MODE_TTB);
break;
}
// glyph-orientation-vertical
val = CSSUtilities.getComputedStyle
(element, SVGCSSEngine.GLYPH_ORIENTATION_VERTICAL_INDEX);
int primitiveType = val.getPrimitiveType();
switch ( primitiveType ) {
case CSSPrimitiveValue.CSS_IDENT: // auto
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION,
GVTAttributedCharacterIterator.
TextAttribute.ORIENTATION_AUTO);
break;
case CSSPrimitiveValue.CSS_DEG:
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION,
GVTAttributedCharacterIterator.
TextAttribute.ORIENTATION_ANGLE);
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION_ANGLE,
new Float(val.getFloatValue()));
break;
case CSSPrimitiveValue.CSS_RAD:
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION,
GVTAttributedCharacterIterator.
TextAttribute.ORIENTATION_ANGLE);
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION_ANGLE,
new Float( Math.toDegrees( val.getFloatValue() ) ));
break;
case CSSPrimitiveValue.CSS_GRAD:
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION,
GVTAttributedCharacterIterator.
TextAttribute.ORIENTATION_ANGLE);
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION_ANGLE,
new Float(val.getFloatValue() * 9 / 5));
break;
default:
// Cannot happen
throw new IllegalStateException("unexpected primitiveType (V):" + primitiveType );
}
// glyph-orientation-horizontal
val = CSSUtilities.getComputedStyle
(element, SVGCSSEngine.GLYPH_ORIENTATION_HORIZONTAL_INDEX);
primitiveType = val.getPrimitiveType();
switch ( primitiveType ) {
case CSSPrimitiveValue.CSS_DEG:
result.put(GVTAttributedCharacterIterator.
TextAttribute.HORIZONTAL_ORIENTATION_ANGLE,
new Float(val.getFloatValue()));
break;
case CSSPrimitiveValue.CSS_RAD:
result.put(GVTAttributedCharacterIterator.
TextAttribute.HORIZONTAL_ORIENTATION_ANGLE,
new Float( Math.toDegrees( val.getFloatValue() ) ));
break;
case CSSPrimitiveValue.CSS_GRAD:
result.put(GVTAttributedCharacterIterator.
TextAttribute.HORIZONTAL_ORIENTATION_ANGLE,
new Float(val.getFloatValue() * 9 / 5));
break;
default:
// Cannot happen
throw new IllegalStateException("unexpected primitiveType (H):" + primitiveType );
}
// text spacing properties...
// Letter Spacing
Float sp = TextUtilities.convertLetterSpacing(element);
if (sp != null) {
result.put(GVTAttributedCharacterIterator.
TextAttribute.LETTER_SPACING,
sp);
result.put(GVTAttributedCharacterIterator.
TextAttribute.CUSTOM_SPACING,
Boolean.TRUE);
}
// Word spacing
sp = TextUtilities.convertWordSpacing(element);
if (sp != null) {
result.put(GVTAttributedCharacterIterator.
TextAttribute.WORD_SPACING,
sp);
result.put(GVTAttributedCharacterIterator.
TextAttribute.CUSTOM_SPACING,
Boolean.TRUE);
}
// Kerning
sp = TextUtilities.convertKerning(element);
if (sp != null) {
result.put(GVTAttributedCharacterIterator.TextAttribute.KERNING,
sp);
result.put(GVTAttributedCharacterIterator.
TextAttribute.CUSTOM_SPACING,
Boolean.TRUE);
}
if (tce == null) {
return inheritMap;
}
try {
// textLength
AbstractSVGAnimatedLength textLength =
(AbstractSVGAnimatedLength) tce.getTextLength();
if (textLength.isSpecified()) {
if (inheritMap == null) {
inheritMap = new HashMap();
}
Object value = new Float(textLength.getCheckedValue());
result.put
(GVTAttributedCharacterIterator.TextAttribute.BBOX_WIDTH,
value);
inheritMap.put
(GVTAttributedCharacterIterator.TextAttribute.BBOX_WIDTH,
value);
// lengthAdjust
SVGOMAnimatedEnumeration _lengthAdjust =
(SVGOMAnimatedEnumeration) tce.getLengthAdjust();
if (_lengthAdjust.getCheckedVal() ==
SVGTextContentElement.LENGTHADJUST_SPACINGANDGLYPHS) {
result.put(GVTAttributedCharacterIterator.
TextAttribute.LENGTH_ADJUST,
GVTAttributedCharacterIterator.