protected Map getAttributeMap(BridgeContext ctx,
Element element,
GraphicsNode node,
TextPath textPath) {
CSSOMReadOnlyStyleDeclaration cssDecl
= CSSUtilities.getComputedStyle(element);
UnitProcessor.Context uctx = UnitProcessor.createContext(ctx, element);
Map result = new HashMap();
CSSPrimitiveValue v;
String s;
float f;
short t;
boolean verticalText = false;
result.put(GVTAttributedCharacterIterator.TextAttribute.TEXT_COMPOUND_DELIMITER, element);
if (element.getTagName().equals(SVG_ALT_GLYPH_TAG)) {
result.put(GVTAttributedCharacterIterator.TextAttribute.ALT_GLYPH_HANDLER,
new SVGAltGlyphHandler(ctx, element));
}
if (textPath != null) {
result.put(GVTAttributedCharacterIterator.TextAttribute.TEXTPATH, textPath);
}
// Text-anchor
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_TEXT_ANCHOR_PROPERTY);
s = v.getStringValue();
TextNode.Anchor a;
switch (s.charAt(0)) {
case 's':
a = TextNode.Anchor.START;
break;
case 'm':
a = TextNode.Anchor.MIDDLE;
break;
default:
a = TextNode.Anchor.END;
}
result.put(GVTAttributedCharacterIterator.TextAttribute.ANCHOR_TYPE, a);
// Font size, in user space units.
float fs = TextUtilities.convertFontSize(element, ctx, cssDecl, uctx);
result.put(TextAttribute.SIZE, new Float(fs));
// Font weight
// TODO: improve support for relative values
// (e.g. "lighter", "bolder")
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_FONT_WEIGHT_PROPERTY);
String fontWeightString;
if (v.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT) {
fontWeightString = v.getStringValue();
//System.out.println("CSS Font Weight "+v.getStringValue());
if (v.getStringValue().charAt(0) == 'n') {
result.put(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_REGULAR);
} else if (v.getStringValue().charAt(0) == 'l') {
result.put(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_LIGHT);
} else {
result.put(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_BOLD);
}
} else {
//System.out.println("CSS Font Weight "+v.getFloatValue(CSSPrimitiveValue.CSS_NUMBER));
fontWeightString = "" + v.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
switch ((int)v.getFloatValue(CSSPrimitiveValue.CSS_NUMBER)) {
case 100:
result.put(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_EXTRA_LIGHT);
break;
case 200:
result.put(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_LIGHT);
break;
case 300:
result.put(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_DEMILIGHT);
break;
case 400:
result.put(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_REGULAR);
break;
case 500:
result.put(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_SEMIBOLD);
break;
case 600:
result.put(TextAttribute.WEIGHT,
//TextAttribute.WEIGHT_DEMIBOLD);
TextAttribute.WEIGHT_BOLD);
break;
case 700:
result.put(TextAttribute.WEIGHT,
TextAttribute.WEIGHT_BOLD);
break;
case 800:
result.put(TextAttribute.WEIGHT,
//TextAttribute.WEIGHT_EXTRABOLD);
TextAttribute.WEIGHT_BOLD);
break;
case 900:
result.put(TextAttribute.WEIGHT,
//TextAttribute.WEIGHT_ULTRABOLD);
TextAttribute.WEIGHT_BOLD);
}
}
// Font style
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_FONT_STYLE_PROPERTY);
String fontStyleString = v.getStringValue();
switch (fontStyleString.charAt(0)) {
case 'n':
result.put(TextAttribute.POSTURE,
TextAttribute.POSTURE_REGULAR);
break;
case 'o':
case 'i':
result.put(TextAttribute.POSTURE,
TextAttribute.POSTURE_OBLIQUE);
}
// Font stretch
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_FONT_STRETCH_PROPERTY);
String fontStretchString = v.getStringValue();
switch (fontStretchString.charAt(0)) {
case 'u':
if (fontStretchString.charAt(6) == 'c') {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_CONDENSED);
} else {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_EXTENDED);
}
break;
case 'e':
if (fontStretchString.charAt(6) == 'c') {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_CONDENSED);
} else {
if (fontStretchString.length() == 8) {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_SEMI_EXTENDED);
} else {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_EXTENDED);
}
}
break;
case 's':
if (fontStretchString.charAt(6) == 'c') {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_SEMI_CONDENSED);
} else {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_SEMI_EXTENDED);
}
break;
default:
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_REGULAR);
}
// Font family
CSSValueList ff = (CSSValueList)cssDecl.getPropertyCSSValueInternal
(CSS_FONT_FAMILY_PROPERTY);
// make a list of GVTFontFamily objects
Vector fontFamilyList = new Vector();
for (int i = 0; i < ff.getLength(); i++) {
v = (CSSPrimitiveValue)ff.item(i);
String fontFamilyName = v.getStringValue();
GVTFontFamily fontFamily
= SVGFontUtilities.getFontFamily(element, ctx, fontFamilyName,
fontWeightString, fontStyleString);
fontFamilyList.add(fontFamily);
}
result.put(GVTAttributedCharacterIterator.TextAttribute.GVT_FONT_FAMILIES,
fontFamilyList);
// Text baseline adjustment.
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_BASELINE_SHIFT_PROPERTY);
if (v.getPrimitiveType() == CSSPrimitiveValue.CSS_IDENT) {
s = v.getStringValue();
//System.out.println("Baseline-shift: "+s);
switch (s.charAt(2)) {
case 'p': //suPerscript
result.put(GVTAttributedCharacterIterator.
TextAttribute.BASELINE_SHIFT,
TextAttribute.SUPERSCRIPT_SUPER);
break;
case 'b': //suBscript
result.put(GVTAttributedCharacterIterator.
TextAttribute.BASELINE_SHIFT,
TextAttribute.SUPERSCRIPT_SUB);
break;
case 's': //baSeline
break;
}
} else if (v.getPrimitiveType() == CSSPrimitiveValue.CSS_PERCENTAGE) {
f = v.getFloatValue(v.getPrimitiveType());
result.put(GVTAttributedCharacterIterator.TextAttribute.BASELINE_SHIFT,
new Float(f*fs/100f));
} else {
f = UnitProcessor.cssOtherLengthToUserSpace
(v, CSS_BASELINE_SHIFT_PROPERTY, uctx);
result.put(GVTAttributedCharacterIterator.TextAttribute.BASELINE_SHIFT, new Float(f));
}
// Unicode-bidi mode
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_UNICODE_BIDI_PROPERTY);
s = v.getStringValue();
if (s.charAt(0) == 'n') {
result.put(TextAttribute.BIDI_EMBEDDING,
new Integer(0));
} 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.
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_DIRECTION_PROPERTY);
String rs = v.getStringValue();
switch (rs.charAt(0)) {
case 'l':
result.put(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_LTR);
switch (s.charAt(0)) {
case 'b': // bidi-override
result.put(TextAttribute.BIDI_EMBEDDING,
new Integer(-2));
break;
case 'e': // embed
result.put(TextAttribute.BIDI_EMBEDDING,
new Integer(2));
break;
}
break;
case 'r':
result.put(TextAttribute.RUN_DIRECTION,
TextAttribute.RUN_DIRECTION_RTL);
switch (s.charAt(0)) {
case 'b': // bidi-override
result.put(TextAttribute.BIDI_EMBEDDING,
new Integer(-1));
break;
case 'e': // embed
result.put(TextAttribute.BIDI_EMBEDDING,
new Integer(1));
break;
}
break;
}
}
// Writing mode
boolean horizontal = true;
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_WRITING_MODE_PROPERTY);
s = v.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);
horizontal = false;
break;
}
// glyph-orientation-vertical
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_GLYPH_ORIENTATION_VERTICAL_PROPERTY);
// why is it that getStringValue() throws an exception?
s = v.getCssText();
switch (s.charAt(0)) {
case 'a':
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION,
GVTAttributedCharacterIterator.
TextAttribute.ORIENTATION_AUTO);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '.':
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION,
GVTAttributedCharacterIterator.
TextAttribute.ORIENTATION_ANGLE);
result.put(GVTAttributedCharacterIterator.
TextAttribute.VERTICAL_ORIENTATION_ANGLE,
new Float(s));
break;
}
// Font stretch
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_FONT_STRETCH_PROPERTY);
s = v.getStringValue();
switch (s.charAt(0)) {
case 'u':
if (s.charAt(6) == 'c') {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_CONDENSED);
} else {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_EXTENDED);
}
break;
case 'e':
if (s.charAt(6) == 'c') {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_CONDENSED);
} else {
if (s.length() == 8) {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_SEMI_EXTENDED);
} else {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_EXTENDED);
}
}
break;
case 's':
if (s.charAt(6) == 'c') {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_SEMI_CONDENSED);
} else {
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_SEMI_EXTENDED);
}
break;
default:
result.put(TextAttribute.WIDTH,
TextAttribute.WIDTH_REGULAR);
}
// text spacing properties...
// Letter Spacing
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_LETTER_SPACING_PROPERTY);
t = v.getPrimitiveType();
if (t != CSSPrimitiveValue.CSS_IDENT) {
if (horizontal) {
f = UnitProcessor.cssHorizontalCoordinateToUserSpace
(v, CSS_LETTER_SPACING_PROPERTY, uctx);
} else {
f = UnitProcessor.cssVerticalCoordinateToUserSpace
(v, CSS_LETTER_SPACING_PROPERTY, uctx);
}
result.put(GVTAttributedCharacterIterator.
TextAttribute.LETTER_SPACING,
new Float(f));
result.put(GVTAttributedCharacterIterator.
TextAttribute.CUSTOM_SPACING,
Boolean.TRUE);
}
// Word spacing
v = (CSSPrimitiveValue)cssDecl.getPropertyCSSValueInternal
(CSS_WORD_SPACING_PROPERTY);
t = v.getPrimitiveType();
if (t != CSSPrimitiveValue.CSS_IDENT) {
if (horizontal) {
f = UnitProcessor.cssHorizontalCoordinateToUserSpace