protected Map getAttributeMap()

in batik-bridge/src/main/java/org/apache/batik/bridge/SVGTextElementBridge.java [1558:1846]


    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;

            // 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, 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,
                    val.getFloatValue());
            break;
        case CSSPrimitiveValue.CSS_RAD:
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.VERTICAL_ORIENTATION,
                       GVTAttributedCharacterIterator.
                       TextAttribute.ORIENTATION_ANGLE);
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.VERTICAL_ORIENTATION_ANGLE,
                    (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,
                    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,
                    val.getFloatValue());
            break;
        case CSSPrimitiveValue.CSS_RAD:
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.HORIZONTAL_ORIENTATION_ANGLE,
                    (float) Math.toDegrees(val.getFloatValue()));
            break;
        case CSSPrimitiveValue.CSS_GRAD:
            result.put(GVTAttributedCharacterIterator.
                       TextAttribute.HORIZONTAL_ORIENTATION_ANGLE,
                    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 = 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.
                               TextAttribute.ADJUST_ALL);
                    inheritMap.put(GVTAttributedCharacterIterator.
                                   TextAttribute.LENGTH_ADJUST,
                                   GVTAttributedCharacterIterator.
                                   TextAttribute.ADJUST_ALL);
                } else {
                    result.put(GVTAttributedCharacterIterator.
                               TextAttribute.LENGTH_ADJUST,
                               GVTAttributedCharacterIterator.
                               TextAttribute.ADJUST_SPACING);
                    inheritMap.put(GVTAttributedCharacterIterator.
                                   TextAttribute.LENGTH_ADJUST,
                                   GVTAttributedCharacterIterator.
                                   TextAttribute.ADJUST_SPACING);
                    result.put(GVTAttributedCharacterIterator.
                               TextAttribute.CUSTOM_SPACING,
                               Boolean.TRUE);
                    inheritMap.put(GVTAttributedCharacterIterator.
                                   TextAttribute.CUSTOM_SPACING,
                                   Boolean.TRUE);
                }
            }
        } catch (LiveAttributeException ex) {
            throw new BridgeException(ctx, ex);
        }

        return inheritMap;
    }