/** Fills the given AttributedStringBuffer. */ protected void fillAttributedStringBuffer( BridgeContext ctx, Element element, boolean top, Integer bidiLevel, Map initialAttributes, AttributedStringBuffer asb, List lnLocs) { // 'requiredFeatures', 'requiredExtensions', 'systemLanguage' & // 'display="none". if ((!SVGUtilities.matchUserAgent(element, ctx.getUserAgent())) || (!CSSUtilities.convertDisplay(element))) { return; } String s = XMLSupport.getXMLSpace(element); boolean preserve = s.equals(SVG_PRESERVE_VALUE); boolean prevEndsWithSpace; Element nodeElement = element; int elementStartChar = asb.length(); if (top) { endLimit = startLen = asb.length(); } if (preserve) { endLimit = startLen; } Map map = initialAttributes == null ? new HashMap() : new HashMap(initialAttributes); initialAttributes = getAttributeMap(ctx, element, null, bidiLevel, map); Object o = map.get(TextAttribute.BIDI_EMBEDDING); Integer subBidiLevel = bidiLevel; if (o != null) { subBidiLevel = (Integer) o; } int lineBreak = -1; if (lnLocs.size() != 0) { lineBreak = ((Integer) lnLocs.get(lnLocs.size() - 1)).intValue(); } for (Node n = getFirstChild(element); n != null; n = getNextSibling(n)) { if (preserve) { prevEndsWithSpace = false; } else { int len = asb.length(); if (len == startLen) { prevEndsWithSpace = true; } else { prevEndsWithSpace = (asb.getLastChar() == ' '); int idx = lnLocs.size() - 1; if (!prevEndsWithSpace && (idx >= 0)) { Integer i = (Integer) lnLocs.get(idx); if (i.intValue() == len) { prevEndsWithSpace = true; } } } } switch (n.getNodeType()) { case Node.ELEMENT_NODE: // System.out.println("Element: " + n); if (!SVG_NAMESPACE_URI.equals(n.getNamespaceURI())) break; nodeElement = (Element) n; String ln = n.getLocalName(); if (ln.equals(SVG12Constants.SVG_FLOW_LINE_TAG)) { int before = asb.length(); fillAttributedStringBuffer( ctx, nodeElement, false, subBidiLevel, initialAttributes, asb, lnLocs); // System.out.println("Line: " + asb.length() + // " - '" + asb + "'"); lineBreak = asb.length(); lnLocs.add(new Integer(lineBreak)); if (before != lineBreak) { initialAttributes = null; } } else if (ln.equals(SVG12Constants.SVG_FLOW_SPAN_TAG) || ln.equals(SVG12Constants.SVG_ALT_GLYPH_TAG)) { int before = asb.length(); fillAttributedStringBuffer( ctx, nodeElement, false, subBidiLevel, initialAttributes, asb, lnLocs); if (asb.length() != before) { initialAttributes = null; } } else if (ln.equals(SVG_A_TAG)) { if (ctx.isInteractive()) { NodeEventTarget target = (NodeEventTarget) nodeElement; UserAgent ua = ctx.getUserAgent(); SVGAElementBridge.CursorHolder ch; ch = new SVGAElementBridge.CursorHolder(CursorManager.DEFAULT_CURSOR); target.addEventListenerNS( XMLConstants.XML_EVENTS_NAMESPACE_URI, SVG_EVENT_CLICK, new SVGAElementBridge.AnchorListener(ua, ch), false, null); target.addEventListenerNS( XMLConstants.XML_EVENTS_NAMESPACE_URI, SVG_EVENT_MOUSEOVER, new SVGAElementBridge.CursorMouseOverListener(ua, ch), false, null); target.addEventListenerNS( XMLConstants.XML_EVENTS_NAMESPACE_URI, SVG_EVENT_MOUSEOUT, new SVGAElementBridge.CursorMouseOutListener(ua, ch), false, null); } int before = asb.length(); fillAttributedStringBuffer( ctx, nodeElement, false, subBidiLevel, initialAttributes, asb, lnLocs); if (asb.length() != before) { initialAttributes = null; } } else if (ln.equals(SVG_TREF_TAG)) { String uriStr = XLinkSupport.getXLinkHref((Element) n); Element ref = ctx.getReferencedElement((Element) n, uriStr); s = TextUtilities.getElementContent(ref); s = normalizeString(s, preserve, prevEndsWithSpace); if (s.length() != 0) { int trefStart = asb.length(); Map m = new HashMap(); getAttributeMap(ctx, nodeElement, null, bidiLevel, m); asb.append(s, m); int trefEnd = asb.length() - 1; TextPaintInfo tpi; tpi = (TextPaintInfo) elemTPI.get(nodeElement); tpi.startChar = trefStart; tpi.endChar = trefEnd; } } break; case Node.TEXT_NODE: case Node.CDATA_SECTION_NODE: s = n.getNodeValue(); s = normalizeString(s, preserve, prevEndsWithSpace); if (s.length() != 0) { asb.append(s, map); if (preserve) { endLimit = asb.length(); } initialAttributes = null; } } } if (top) { boolean strippedSome = false; while ((endLimit < asb.length()) && (asb.getLastChar() == ' ')) { int idx = lnLocs.size() - 1; int len = asb.length(); if (idx >= 0) { Integer i = (Integer) lnLocs.get(idx); if (i.intValue() >= len) { i = new Integer(len - 1); lnLocs.set(idx, i); idx--; while (idx >= 0) { i = (Integer) lnLocs.get(idx); if (i.intValue() < len - 1) break; lnLocs.remove(idx); idx--; } } } asb.stripLast(); strippedSome = true; } if (strippedSome) { Iterator iter = elemTPI.values().iterator(); while (iter.hasNext()) { TextPaintInfo tpi = (TextPaintInfo) iter.next(); if (tpi.endChar >= asb.length()) { tpi.endChar = asb.length() - 1; if (tpi.startChar > tpi.endChar) tpi.startChar = tpi.endChar; } } } } int elementEndChar = asb.length() - 1; TextPaintInfo tpi = (TextPaintInfo) elemTPI.get(element); tpi.startChar = elementStartChar; tpi.endChar = elementEndChar; }
protected AttributedString gatherFlowPara(BridgeContext ctx, Element div) { TextPaintInfo divTPI = new TextPaintInfo(); // Set some basic props so we can get bounds info for complex paints. divTPI.visible = true; divTPI.fillPaint = Color.black; elemTPI.put(div, divTPI); AttributedStringBuffer asb = new AttributedStringBuffer(); List paraEnds = new ArrayList(); List paraElems = new ArrayList(); List lnLocs = new ArrayList(); for (Node n = getFirstChild(div); n != null; n = getNextSibling(n)) { if (n.getNodeType() != Node.ELEMENT_NODE || !getNamespaceURI().equals(n.getNamespaceURI())) { continue; } Element e = (Element) n; String ln = e.getLocalName(); if (ln.equals(SVG12Constants.SVG_FLOW_PARA_TAG)) { fillAttributedStringBuffer(ctx, e, true, null, null, asb, lnLocs); paraElems.add(e); paraEnds.add(new Integer(asb.length())); } else if (ln.equals(SVG12Constants.SVG_FLOW_REGION_BREAK_TAG)) { fillAttributedStringBuffer(ctx, e, true, null, null, asb, lnLocs); paraElems.add(e); paraEnds.add(new Integer(asb.length())); } } divTPI.startChar = 0; divTPI.endChar = asb.length() - 1; // Layer in the PARAGRAPH/LINE_BREAK Attributes so we can // break up text chunks. AttributedString ret = asb.toAttributedString(); if (ret == null) return null; // Note: The Working Group (in conjunction with XHTML working // group) has decided that multiple line elements collapse. int prevLN = 0; Iterator lnIter = lnLocs.iterator(); while (lnIter.hasNext()) { int nextLN = ((Integer) lnIter.next()).intValue(); if (nextLN == prevLN) continue; // System.out.println("Attr: [" + prevLN + "," + nextLN + "]"); ret.addAttribute(FLOW_LINE_BREAK, new Object(), prevLN, nextLN); prevLN = nextLN; } int start = 0; int end; List emptyPara = null; for (int i = 0; i < paraElems.size(); i++, start = end) { Element elem = (Element) paraElems.get(i); end = ((Integer) paraEnds.get(i)).intValue(); if (start == end) { if (emptyPara == null) emptyPara = new LinkedList(); emptyPara.add(makeBlockInfo(ctx, elem)); continue; } // System.out.println("Para: [" + start + ", " + end + "]"); ret.addAttribute(FLOW_PARAGRAPH, makeBlockInfo(ctx, elem), start, end); if (emptyPara != null) { ret.addAttribute(FLOW_EMPTY_PARAGRAPH, emptyPara, start, end); emptyPara = null; } } return ret; }