deweese 2005/01/03 02:48:07 Modified: samples anne.svg samples/tests/spec/text textAnchor.svg textAnchor2.svg textAnchor3.svg samples/tests/spec12/text flowText.svg flowText2.svg flowText3.svg flowText4.svg flowText5.svg sources/org/apache/batik/bridge DocumentLoader.java SVGTextElementBridge.java sources/org/apache/batik/bridge/svg12 SVGFlowRootElementBridge.java sources/org/apache/batik/extension/svg BatikFlowTextElementBridge.java sources/org/apache/batik/gvt/flow FlowGlyphLayout.java test-references/samples/tests/spec/linking anchor.png anchorInsideText.png pointerEvents.png pointerEvents2.png test-references/samples/tests/spec/structure symbolViewBoxClip.png symbolViewBoxOverflow.png toolTips.png test-references/samples/tests/spec/text smallFonts.png test-references/samples/tests/spec12/text flowText2.png test-resources/org/apache/batik/test samplesRendering.xml Added: samples/tests/spec/text xmlSpace.svg test-references/samples/tests/spec/text xmlSpace.png Log: 1) The document loader caching was a memory leak because it always used hard references. It now uses soft references. 2) Reworked the xml:space support so it behaves a bit more rationally. The code is also simplier. Still have no idea what the specification really wants! PR: 32872 Revision Changes Path 1.11 +4 -2 xml-batik/samples/anne.svg Index: anne.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/anne.svg,v retrieving revision 1.10 retrieving revision 1.11 diff -u -r1.10 -r1.11 --- anne.svg 18 Aug 2004 07:11:34 -0000 1.10 +++ anne.svg 3 Jan 2005 10:48:05 -0000 1.11 @@ -26,7 +26,9 @@ <!-- @version $Id$ --> <!-- ========================================================================= --> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="450" height="500" viewBox="0 0 450 500"> +<svg width="450" height="500" viewBox="0 0 450 500" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" > <!-- ============================================================= --> <!-- Test content --> <!-- ============================================================= --> 1.4 +4 -2 xml-batik/samples/tests/spec/text/textAnchor.svg Index: textAnchor.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/tests/spec/text/textAnchor.svg,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- textAnchor.svg 18 Aug 2004 07:12:21 -0000 1.3 +++ textAnchor.svg 3 Jan 2005 10:48:05 -0000 1.4 @@ -27,7 +27,9 @@ <!-- ====================================================================== --> <?xml-stylesheet type="text/css" href="../../resources/style/test.css" ?> -<svg width="450" height="500" viewBox="0 0 450 500" > +<svg width="450" height="500" viewBox="0 0 450 500" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" > <text class="title" x="50%" y="40">text-anchor on <tspan></text> 1.5 +4 -2 xml-batik/samples/tests/spec/text/textAnchor2.svg Index: textAnchor2.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/tests/spec/text/textAnchor2.svg,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- textAnchor2.svg 18 Aug 2004 07:12:21 -0000 1.4 +++ textAnchor2.svg 3 Jan 2005 10:48:05 -0000 1.5 @@ -27,7 +27,9 @@ <!-- ====================================================================== --> <?xml-stylesheet type="text/css" href="../../resources/style/test.css" ?> -<svg width="450" height="500" viewBox="0 0 450 500" > +<svg width="450" height="500" viewBox="0 0 450 500" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" > <text class="title" x="50%" y="30">text-anchor on a single <tspan></text> 1.4 +4 -2 xml-batik/samples/tests/spec/text/textAnchor3.svg Index: textAnchor3.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/tests/spec/text/textAnchor3.svg,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- textAnchor3.svg 18 Aug 2004 07:12:21 -0000 1.3 +++ textAnchor3.svg 3 Jan 2005 10:48:05 -0000 1.4 @@ -27,7 +27,9 @@ <!-- ====================================================================== --> <?xml-stylesheet type="text/css" href="../../resources/style/test.css" ?> -<svg width="450" height="500" viewBox="0 0 450 500" > +<svg width="450" height="500" viewBox="0 0 450 500" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" > <text class="title" x="50%" y="30">text-anchor on a single <tspan></text> 1.1 xml-batik/samples/tests/spec/text/xmlSpace.svg Index: xmlSpace.svg =================================================================== <?xml version="1.0" encoding="UTF-8" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <!-- Copyright 2004 The Apache Software Foundation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- ====================================================================== --> <!-- Tests "proper" handling of xml:space --> <!-- --> <!-- @author [EMAIL PROTECTED] --> <!-- @version $Id: xmlSpace.svg,v 1.1 2005/01/03 10:48:05 deweese Exp $ --> <!-- ====================================================================== --> <?xml-stylesheet type="text/css" href="../../resources/style/test.css" ?> <svg width="450" height="500" viewBox="0 0 450 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:foo="http://graphics.apache.org/batik/foo"> <text class="title" x="50%" y="40">Test of xml:space handling</text> <font horiz-adv-x="600" id="stroke"> <font-face font-family="BlockSpace" font-weight="normal" units-per-em="1000" ascent="1000" descent="250" alphabetic="0"/> <missing-glyph horiz-adv-x="600" d="M0 0 V800 H500 V0 z"/> <glyph unicode=" " glyph-name=" " horiz-adv-x="600" d="M20 0 V800 H520 V0 z M 50 30 H490 V770 H50 z"/> </font> <style type="text/css"><![CDATA[ .cap { font: normal normal 8 monospaced; stroke: none; stroke-width: 0; fill: black } ]]> </style> <g font="20 BlockSpace"> <text x="10" y=" 75"> X X </text> <text class="cap" x="120" y="75">no xml:space attr</text> <text x="10" y="100" xml:space="default"> X X </text> <text class="cap" x="120" y="100">xml:space="default"</text> <text x="10" y="150" xml:space="preserve"> X X <tspan fill="red" xml:space="default"/></text> <text class="cap" x="120" y="140">Empty tspan at end <tspan x="120" dy="1.2em">xml:space="default"</tspan></text> <text x="10" y="175" xml:space="preserve"> X X<tspan fill="red" xml:space="default"> </tspan></text> <text class="cap" x="120" y="165">tspan end 2spc <tspan x="120" dy="1.2em">xml:space="default"</tspan></text> <text x="10" y="200" xml:space="preserve"> X X <tspan fill="red" xml:space="default"> </tspan></text> <text class="cap" x="120" y="190">tspan end <tspan x="120" dy="1.2em">xml:space="default"</tspan></text> <text x="10" y="225" xml:space="preserve"><tspan fill="red" xml:space="default"> </tspan> X X </text> <text class="cap" x="120" y="215">tspan start <tspan x="120" dy="1.2em">xml:space="default"</tspan></text> <text x="10" y="250" xml:space="preserve"> <tspan fill="red" xml:space="default"> </tspan>X X </text> <text class="cap" x="120" y="240">tspan near start <tspan x="120" dy="1.2em">xml:space="default"</tspan></text> <text x="10" y="275" xml:space="preserve"> X<tspan fill="red" xml:space="default"> </tspan> X </text> <text class="cap" x="120" y="265">tspan middle front <tspan x="120" dy="1.2em">xml:space="default"</tspan></text> <text x="10" y="300" xml:space="preserve"> X <tspan fill="red" xml:space="default"> </tspan>X </text> <text class="cap" x="120" y="290">tspan middle end <tspan x="120" dy="1.2em">xml:space="default"</tspan></text> <text x="10" y="325" xml:space="preserve"> <foo:xxx/> X X </text> <text class="cap" x="120" y="315">unknown element <tspan x="120" dy="1.2em">start</tspan></text> <text x="10" y="350" xml:space="preserve"> X <foo:xxx/> X </text> <text class="cap" x="120" y="340">unknown element <tspan x="120" dy="1.2em">middle</tspan></text> <text x="10" y="375" xml:space="preserve"> X X <foo:xxx/> </text> <text class="cap" x="120" y="365">unknown element <tspan x="120" dy="1.2em">end</tspan></text> <!-- --> <text x="235" y="100" xml:space="preserve"> X X </text> <text class="cap" x="345" y="100">xml:space="preserve"</text> <text x="235" y="150" xml:space="default"> X X <tspan fill="red" xml:space="preserve"/></text> <text class="cap" x="345" y="140">Empty tspan at end <tspan x="345" dy="1.2em">xml:space="preserve"</tspan></text> <text x="235" y="175" xml:space="default"> X X<tspan fill="red" xml:space="preserve"> </tspan></text> <text class="cap" x="345" y="165">tspan end 2spc <tspan x="345" dy="1.2em">xml:space="preserve"</tspan></text> <text x="235" y="200" xml:space="default"> X X <tspan fill="red" xml:space="preserve"> </tspan></text> <text class="cap" x="345" y="190">tspan end <tspan x="345" dy="1.2em">xml:space="preserve"</tspan></text> <text x="235" y="225" xml:space="default"><tspan fill="red" xml:space="preserve"> </tspan> X X </text> <text class="cap" x="345" y="215">tspan start <tspan x="345" dy="1.2em">xml:space="preserve"</tspan></text> <text x="235" y="250" xml:space="default"> <tspan fill="red" xml:space="preserve"> </tspan>X X </text> <text class="cap" x="345" y="240">tspan near start <tspan x="345" dy="1.2em">xml:space="preserve"</tspan></text> <text x="235" y="275" xml:space="default"> X<tspan fill="red" xml:space="preserve"> </tspan> X </text> <text class="cap" x="345" y="265">tspan middle front <tspan x="345" dy="1.2em">xml:space="preserve"</tspan></text> <text x="235" y="300" xml:space="default"> X <tspan fill="red" xml:space="preserve"> </tspan>X </text> <text class="cap" x="345" y="290">tspan middle end <tspan x="345" dy="1.2em">xml:space="preserve"</tspan></text> <text x="235" y="325" xml:space="default"> <foo:xxx/> X X </text> <text class="cap" x="345" y="315">unknown element <tspan x="345" dy="1.2em">start</tspan></text> <text x="235" y="350" xml:space="default"> X <foo:xxx/> X </text> <text class="cap" x="345" y="340">unknown element <tspan x="345" dy="1.2em">middle</tspan></text> <text x="236" y="375" xml:space="default"> X X <foo:xxx/> </text> <text class="cap" x="345" y="365">unknown element <tspan x="345" dy="1.2em">end</tspan></text> </g> </svg> 1.3 +2 -2 xml-batik/samples/tests/spec12/text/flowText.svg Index: flowText.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/tests/spec12/text/flowText.svg,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- flowText.svg 30 Nov 2004 03:23:58 -0000 1.2 +++ flowText.svg 3 Jan 2005 10:48:05 -0000 1.3 @@ -46,7 +46,7 @@ <line x1="243" y1="70" x2="243" y2="490" stroke="grey" fill="none"/> <line x1="423" y1="70" x2="423" y2="490" stroke="grey" fill="none"/> - <flowRoot font-size="20" xml:space="preserve"> + <flowRoot font-size="20"> <flowRegion> <rect x="17" y="80" width="200" height="400"/> <rect x="233" y="80" width="200" height="400"/> 1.2 +2 -2 xml-batik/samples/tests/spec12/text/flowText2.svg Index: flowText2.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/tests/spec12/text/flowText2.svg,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- flowText2.svg 18 Nov 2004 01:46:52 -0000 1.1 +++ flowText2.svg 3 Jan 2005 10:48:05 -0000 1.2 @@ -53,7 +53,7 @@ <line x1="243" y1="70" x2="243" y2="490" stroke="grey" fill="none"/> <line x1="423" y1="70" x2="423" y2="490" stroke="grey" fill="none"/> - <flowRoot font-size="20" xml:space="preserve"> + <flowRoot font-size="20"> <flowRegion> <path d="M 67,80 l-50,400 h200 l-50,-400 z"/> <!-- <rect x="17" y="80" width="200" height="400"/> --> 1.2 +2 -2 xml-batik/samples/tests/spec12/text/flowText3.svg Index: flowText3.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/tests/spec12/text/flowText3.svg,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- flowText3.svg 18 Nov 2004 01:46:52 -0000 1.1 +++ flowText3.svg 3 Jan 2005 10:48:05 -0000 1.2 @@ -48,7 +48,7 @@ <line x1="243" y1="70" x2="243" y2="490" stroke="grey" fill="none"/> <line x1="423" y1="70" x2="423" y2="490" stroke="grey" fill="none"/> - <flowRoot font-size="20" xml:space="preserve"> + <flowRoot font-size="20"> <flowRegion> <path d="M 17,80 v400 h200 v-400 z M 220,80 v400 h10 v-400 z 1.2 +3 -3 xml-batik/samples/tests/spec12/text/flowText4.svg Index: flowText4.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/tests/spec12/text/flowText4.svg,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- flowText4.svg 18 Nov 2004 01:46:52 -0000 1.1 +++ flowText4.svg 3 Jan 2005 10:48:05 -0000 1.2 @@ -43,7 +43,7 @@ font-size="500" font-weight="bold" text-anchor="middle" >B</text> - <flowRoot font-size="10" xml:space="preserve"> + <flowRoot font-size="10"> <flowRegion> <text x="225" y="450" font-size="500" font-weight="bold" text-anchor="middle">B</text> <!-- <rect x="17" y="80" width="200" height="400"/> @@ -52,7 +52,7 @@ <flowDiv> <flowPara indent="20" margin-top="3" margin-bottom="5" >This is an <flowSpan font-size="40" fill="crimson">ex­ample</flowSpan> of a very long string that is split ‍across multi­ple lines via text wrap­ping.</flowPara> - <flowPara text-align="middle" margin-top="5" margin-left="10" margin-right="10" margin-bottom="5"><flowLine>Now check if text wrapping handles a number of tricky</flowLine> situations: a­very­long­runon­word­that­spans­multiple­lines­<flowSpan font-weight="bold">with­<flowSpan fill="crimson">embedded­</flowSpan>span</flowSpan>­elements & <flowSpan fill="green" dy="-.3em" font-size="80%">super</flowSpan><flowSpan dy=".3em"> or </flowSpan><flowSpan fill="darkgreen" dy=".3em" font-size="80%">sub</flowSpan><flowSpan dy="-.3em"> scripts.</flowSpan></flowPara> + <flowPara text-align="middle" margin-top="5" margin-left="10" margin-right="10" margin-bottom="5"><flowLine>Now check if text wrapping handles a number of tricky </flowLine>situations: a­very­long­runon­word­that­spans­multiple­lines­<flowSpan font-weight="bold">with­<flowSpan fill="crimson">embedded­</flowSpan>span</flowSpan>­elements & <flowSpan fill="green" dy="-.3em" font-size="80%">super</flowSpan><flowSpan dy=".3em"> or </flowSpan><flowSpan fill="darkgreen" dy=".3em" font-size="80%">sub</flowSpan><flowSpan dy="-.3em"> scripts.</flowSpan></flowPara> <flowPara margin-top="5" text-align="end">Now we are just <flowSpan font-size="30" fill="blue">about</flowSpan> to go to the next flow rect <flowSpan font-size="10">(note if the 'about' were included on the last line of the previous flow rect the line would not have fit and the whole line would have moved here).</flowSpan></flowPara> <flowPara margin="10" text-align="full"> I'll keep going because I want to make sure that it properly stops when it hits the end of all of the the flow regions defined. Also the last line includes text in a larger font size so it will not fit. Thus the end of this sentence will be cut off because the line size gets <flowSpan font-size="35">tall</flowSpan>er</flowPara> </flowDiv> 1.2 +3 -3 xml-batik/samples/tests/spec12/text/flowText5.svg Index: flowText5.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/tests/spec12/text/flowText5.svg,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- flowText5.svg 18 Nov 2004 01:46:52 -0000 1.1 +++ flowText5.svg 3 Jan 2005 10:48:05 -0000 1.2 @@ -42,7 +42,7 @@ <use width="400" height="400" xlink:href="../../../batikLogo.svg#Batik_Squiggle" opacity="0.5"/> <g transform="rotate(-45, 200, 200)"> - <flowRoot font-size="15.75" xml:space="preserve"> + <flowRoot font-size="15.75"> <flowRegion> <use transform="rotate(45, 200, 200)" width="400" height="400" xlink:href="../../../batikLogo.svg#Batik_Squiggle" /> </flowRegion> @@ -72,7 +72,7 @@ <use xlink:href="../../../batikLogo.svg#Batik_Squiggle_Green"/> </g> <g transform="rotate(-45, 200, 200)"> - <flowRoot font-size="16.5" xml:space="preserve"> + <flowRoot font-size="16.5"> <flowRegion> <use transform="rotate(45, 200, 200), scale(.73,.73)" xlink:href="../../../batikLogo.svg#Batik_Squiggle_Blue"/> 1.23 +33 -13 xml-batik/sources/org/apache/batik/bridge/DocumentLoader.java Index: DocumentLoader.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/DocumentLoader.java,v retrieving revision 1.22 retrieving revision 1.23 diff -u -r1.22 -r1.23 --- DocumentLoader.java 18 Aug 2004 07:12:31 -0000 1.22 +++ DocumentLoader.java 3 Jan 2005 10:48:05 -0000 1.23 @@ -24,6 +24,8 @@ import org.apache.batik.dom.svg.SAXSVGDocumentFactory; import org.apache.batik.dom.svg.SVGDocumentFactory; import org.apache.batik.dom.util.DocumentDescriptor; +import org.apache.batik.util.CleanerThread; + import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.svg.SVGDocument; @@ -80,9 +82,12 @@ if (n != -1) { uri = uri.substring(0, n); } - DocumentState state = (DocumentState)cacheMap.get(uri); + DocumentState state; + synchronized (cacheMap) { + state = (DocumentState)cacheMap.get(uri); + } if (state != null) - return state.document; + return state.getDocument(); return null; } @@ -101,9 +106,11 @@ DocumentDescriptor desc = documentFactory.getDocumentDescriptor(); DocumentState state = new DocumentState(uri, document, desc); - cacheMap.put(uri, state); + synchronized (cacheMap) { + cacheMap.put(uri, state); + } - return state.document; + return state.getDocument(); } /** @@ -122,9 +129,11 @@ DocumentDescriptor desc = documentFactory.getDocumentDescriptor(); DocumentState state = new DocumentState(uri, document, desc); - cacheMap.put(uri, state); + synchronized (cacheMap) { + cacheMap.put(uri, state); + } - return state.document; + return state.getDocument(); } /** @@ -139,7 +148,9 @@ */ public void dispose() { // new Exception("purge the cache").printStackTrace(); - cacheMap.clear(); + synchronized (cacheMap) { + cacheMap.clear(); + } } /** @@ -152,7 +163,10 @@ */ public int getLineNumber(Element e) { String uri = ((SVGDocument)e.getOwnerDocument()).getURL(); - DocumentState state = (DocumentState)cacheMap.get(uri); + DocumentState state; + synchronized (cacheMap) { + state = (DocumentState)cacheMap.get(uri); + } if (state == null) { return -1; } else { @@ -163,20 +177,25 @@ /** * A simple class that contains a Document and its number of nodes. */ - private static class DocumentState { + private class DocumentState extends CleanerThread.SoftReferenceCleared { private String uri; - private Document document; private DocumentDescriptor desc; public DocumentState(String uri, Document document, DocumentDescriptor desc) { + super(document); this.uri = uri; - this.document = document; this.desc = desc; } + public void cleared() { + synchronized (cacheMap) { + cacheMap.remove(uri); + } + } + public DocumentDescriptor getDocumentDescriptor() { return desc; } @@ -186,7 +205,8 @@ } public Document getDocument() { - return document; + return (Document)get(); } } + } 1.102 +103 -82 xml-batik/sources/org/apache/batik/bridge/SVGTextElementBridge.java Index: SVGTextElementBridge.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/SVGTextElementBridge.java,v retrieving revision 1.101 retrieving revision 1.102 diff -u -r1.101 -r1.102 --- SVGTextElementBridge.java 2 Dec 2004 01:24:36 -0000 1.101 +++ SVGTextElementBridge.java 3 Jan 2005 10:48:05 -0000 1.102 @@ -771,6 +771,15 @@ return asb.toAttributedString(); } + + /** + * This is used to store the end of the last piece of text + * content from an element with xml:space="preserve". When + * we are stripping trailing spaces we need to make sure + * we don't strip anything before this point. + */ + protected int endLimit; + /** * Fills the given AttributedStringBuffer. */ @@ -780,7 +789,8 @@ TextPath textPath, Integer bidiLevel, AttributedStringBuffer asb) { - // 'requiredFeatures', 'requiredExtensions' and 'systemLanguage' + // 'requiredFeatures', 'requiredExtensions', 'systemLanguage' & + // 'display="none". if ((!SVGUtilities.matchUserAgent(element, ctx.getUserAgent())) || (!CSSUtilities.convertDisplay(element))) { return; @@ -788,12 +798,14 @@ String s = XMLSupport.getXMLSpace(element); boolean preserve = s.equals(SVG_PRESERVE_VALUE); - boolean first = true; - boolean last; - boolean stripFirst = !preserve; - boolean stripLast = !preserve; + boolean prevEndsWithSpace; Element nodeElement = element; + if (top) + endLimit = 0; + if (preserve) + endLimit = asb.length(); + Map map = getAttributeMap(ctx, element, textPath, bidiLevel); Object o = map.get(TextAttribute.BIDI_EMBEDDING); Integer subBidiLevel = bidiLevel; @@ -804,12 +816,15 @@ n != null; n = n.getNextSibling()) { - last = n.getNextSibling() == null; - - int lastChar = asb.getLastChar(); - stripFirst = !preserve && first && - (top || lastChar == ' ' || lastChar == -1); - + if (preserve) { + prevEndsWithSpace = false; + } else { + if (asb.length() == 0) + prevEndsWithSpace = true; + else + prevEndsWithSpace = (asb.getLastChar() == ' '); + } + switch (n.getNodeType()) { case Node.ELEMENT_NODE: if (!SVG_NAMESPACE_URI.equals(n.getNamespaceURI())) @@ -844,14 +859,10 @@ String uriStr = XLinkSupport.getXLinkHref((Element)n); Element ref = ctx.getReferencedElement((Element)n, uriStr); s = TextUtilities.getElementContent(ref); - s = normalizeString(s, preserve, stripFirst, last && top); + s = normalizeString(s, preserve, prevEndsWithSpace); if (s != null) { - stripLast = !preserve && s.charAt(0) == ' '; - if (stripLast && !asb.isEmpty()) { - asb.stripLast(); - } Map m = getAttributeMap(ctx, nodeElement, - textPath, bidiLevel); + textPath, bidiLevel); asb.append(s, m); } } else if (ln.equals(SVG_A_TAG)) { @@ -872,15 +883,16 @@ case Node.TEXT_NODE: case Node.CDATA_SECTION_NODE: s = n.getNodeValue(); - s = normalizeString(s, preserve, stripFirst, last && top); - if (s != null) { - stripLast = !preserve && s.charAt(0) == ' '; - if (stripLast && !asb.isEmpty()) - asb.stripLast(); - asb.append(s, map); - } + s = normalizeString(s, preserve, prevEndsWithSpace); + asb.append(s, map); + if (preserve) + endLimit = asb.length(); } - first = false; + } + + if (top) { + while ((endLimit < asb.length()) && (asb.getLastChar() == ' ')) + asb.stripLast(); } } @@ -889,9 +901,8 @@ */ protected String normalizeString(String s, boolean preserve, - boolean stripfirst, - boolean striplast) { - StringBuffer sb = new StringBuffer(); + boolean stripfirst) { + StringBuffer sb = new StringBuffer(s.length()); if (preserve) { for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); @@ -905,57 +916,45 @@ sb.append(c); } } - } else { - boolean space = false; - int idx = 0; - if (stripfirst) { - loop: while (idx < s.length()) { - switch (s.charAt(idx)) { - default: - break loop; - case 10: - case 13: - case ' ': - case '\t': - idx++; - } - } - } - for (int i = idx; i < s.length(); i++) { - char c = s.charAt(i); - switch (c) { + return sb.toString(); + } + + int idx = 0; + if (stripfirst) { + loop: while (idx < s.length()) { + switch (s.charAt(idx)) { + default: + break loop; case 10: case 13: - break; case ' ': case '\t': - if (!space) { - sb.append(' '); - space = true; - } - break; - default: - sb.append(c); - space = false; + idx++; } } - if (striplast) { - int len; - while ((len = sb.length()) > 0) { - if (sb.charAt(len - 1) == ' ') { - sb.deleteCharAt(len - 1); - } else { - break; - } + } + + boolean space = false; + for (int i = idx; i < s.length(); i++) { + char c = s.charAt(i); + switch (c) { + case 10: + case 13: + break; + case ' ': + case '\t': + if (!space) { + sb.append(' '); + space = true; } + break; + default: + sb.append(c); + space = false; } } - if (sb.length() > 0) { - return sb.toString(); - } else if (stripfirst && striplast) { - return " "; - } - return null; + + return sb.toString(); } /** @@ -1030,20 +1029,42 @@ } /** - * Strips the last string last character. + * Strips the last string character. + */ + public void stripFirst() { + String s = (String)strings.get(0); + if (s.charAt(s.length() - 1) != ' ') + return; + + length--; + + if (s.length() == 1) { + attributes.remove(0); + strings.remove(0); + count--; + return; + } + + strings.set(0, s.substring(1)); + } + + /** + * Strips the last string character. */ public void stripLast() { - String s = (String)strings.remove(count - 1); - if (s.charAt(s.length() - 1) == ' ') { - if (s.length() == 1) { - attributes.remove(--count); - return; - } - strings.add(s.substring(0, s.length() - 1)); - length--; - } else { - strings.add(s); + String s = (String)strings.get(count - 1); + if (s.charAt(s.length() - 1) != ' ') + return; + + length--; + + if (s.length() == 1) { + attributes.remove(--count); + strings.remove(count); + return; } + + strings.set(count-1, s.substring(0, s.length() - 1)); } /** 1.3 +62 -35 xml-batik/sources/org/apache/batik/bridge/svg12/SVGFlowRootElementBridge.java Index: SVGFlowRootElementBridge.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/bridge/svg12/SVGFlowRootElementBridge.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- SVGFlowRootElementBridge.java 2 Dec 2004 01:24:37 -0000 1.2 +++ SVGFlowRootElementBridge.java 3 Jan 2005 10:48:05 -0000 1.3 @@ -281,10 +281,10 @@ 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); - // System.out.println("Attr: [" + prevLN + "," + nextLN + "]"); prevLN = nextLN; } @@ -359,6 +359,8 @@ } } + protected int startLen; + /** * Fills the given AttributedStringBuffer. */ @@ -368,18 +370,24 @@ Integer bidiLevel, AttributedStringBuffer asb, List lnLocs) { - // 'requiredFeatures', 'requiredExtensions' and 'systemLanguage' - if (!SVGUtilities.matchUserAgent(element, ctx.getUserAgent())) { + // '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 first = true; - boolean last; - boolean stripFirst = !preserve; - boolean stripLast = !preserve; + boolean prevEndsWithSpace; Element nodeElement = element; + if (top) + endLimit = startLen = asb.length(); + + if (preserve) + endLimit = startLen; + Map map = getAttributeMap(ctx, element, null, bidiLevel); Object o = map.get(TextAttribute.BIDI_EMBEDDING); Integer subBidiLevel = bidiLevel; @@ -394,28 +402,33 @@ n != null; n = n.getNextSibling()) { - last = n.getNextSibling() == null; - - int lastChar = asb.getLastChar(); - stripFirst = (!preserve && first && - (lastChar == ' ' || lastChar == -1)); - // Strip spaces at start of para/regionBk - if (top && first) - stripFirst = true; - // Strip spaces after lineBreak. - if (asb.length() == lineBreak) - stripFirst = true; + 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 ((!getNamespaceURI().equals(n.getNamespaceURI())) && - (!SVG_NAMESPACE_URI.equals(n.getNamespaceURI()))) { + if (!SVG_NAMESPACE_URI.equals(n.getNamespaceURI())) break; - } nodeElement = (Element)n; + String ln = n.getLocalName(); + if (ln.equals(SVG12Constants.SVG_FLOW_LINE_TAG)) { fillAttributedStringBuffer(ctx, nodeElement, false, subBidiLevel, @@ -456,32 +469,46 @@ String uriStr = XLinkSupport.getXLinkHref((Element)n); Element ref = ctx.getReferencedElement((Element)n, uriStr); s = TextUtilities.getElementContent(ref); - s = normalizeString(s, false, stripFirst, last && top); + s = normalizeString(s, preserve, prevEndsWithSpace); if (s != null) { - stripLast = !preserve && s.charAt(0) == ' '; - if (stripLast && !asb.isEmpty()) { - asb.stripLast(); - } Map m = getAttributeMap(ctx, nodeElement, null, bidiLevel); asb.append(s, m); } - } + } break; case Node.TEXT_NODE: case Node.CDATA_SECTION_NODE: s = n.getNodeValue(); - s = normalizeString(s, false, stripFirst, last && top); - if (s != null) { - stripLast = !preserve && s.charAt(0) == ' '; - if (stripLast && !asb.isEmpty()) { - asb.stripLast(); + s = normalizeString(s, preserve, prevEndsWithSpace); + asb.append(s, map); + if (preserve) + endLimit = asb.length(); + } + } + + if (top) { + 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.append(s, map); } + asb.stripLast(); } - first = false; } } 1.2 +34 -28 xml-batik/sources/org/apache/batik/extension/svg/BatikFlowTextElementBridge.java Index: BatikFlowTextElementBridge.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/extension/svg/BatikFlowTextElementBridge.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- BatikFlowTextElementBridge.java 18 Nov 2004 01:46:58 -0000 1.1 +++ BatikFlowTextElementBridge.java 3 Jan 2005 10:48:05 -0000 1.2 @@ -31,6 +31,7 @@ import org.apache.batik.bridge.Bridge; import org.apache.batik.bridge.BridgeContext; import org.apache.batik.bridge.BridgeException; +import org.apache.batik.bridge.CSSUtilities; import org.apache.batik.bridge.SVGAElementBridge; import org.apache.batik.bridge.SVGTextElementBridge; import org.apache.batik.bridge.SVGUtilities; @@ -530,18 +531,23 @@ Integer bidiLevel, AttributedStringBuffer asb, List lnLocs) { - // 'requiredFeatures', 'requiredExtensions' and 'systemLanguage' - if (!SVGUtilities.matchUserAgent(element, ctx.getUserAgent())) { + // '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 first = true; - boolean last; - boolean stripFirst = !preserve; - boolean stripLast = !preserve; + boolean prevEndsWithSpace; Element nodeElement = element; + if (top) + endLimit = 0; + if (preserve) + endLimit = asb.length(); + Map map = getAttributeMap(ctx, element, null, bidiLevel); Object o = map.get(TextAttribute.BIDI_EMBEDDING); Integer subBidiLevel = bidiLevel; @@ -552,22 +558,26 @@ n != null; n = n.getNextSibling()) { - last = n.getNextSibling() == null; - - int lastChar = asb.getLastChar(); - stripFirst = !preserve && first && - (top || lastChar == ' ' || lastChar == -1); + if (preserve) { + prevEndsWithSpace = false; + } else { + if (asb.length() == 0) + prevEndsWithSpace = true; + else + prevEndsWithSpace = (asb.getLastChar() == ' '); + } switch (n.getNodeType()) { case Node.ELEMENT_NODE: // System.out.println("Element: " + n); if ((!getNamespaceURI().equals(n.getNamespaceURI())) && - (!SVG_NAMESPACE_URI.equals(n.getNamespaceURI()))) { + (!SVG_NAMESPACE_URI.equals(n.getNamespaceURI()))) break; - } nodeElement = (Element)n; + String ln = n.getLocalName(); + if (ln.equals(BATIK_EXT_FLOW_LINE_TAG)) { fillAttributedStringBuffer(ctx, nodeElement, false, subBidiLevel, @@ -607,12 +617,8 @@ String uriStr = XLinkSupport.getXLinkHref((Element)n); Element ref = ctx.getReferencedElement((Element)n, uriStr); s = TextUtilities.getElementContent(ref); - s = normalizeString(s, preserve, stripFirst, last && top); + s = normalizeString(s, preserve, prevEndsWithSpace); if (s != null) { - stripLast = !preserve && s.charAt(0) == ' '; - if (stripLast && !asb.isEmpty()) { - asb.stripLast(); - } Map m = getAttributeMap(ctx, nodeElement, null, bidiLevel); asb.append(s, m); @@ -623,16 +629,16 @@ case Node.TEXT_NODE: case Node.CDATA_SECTION_NODE: s = n.getNodeValue(); - s = normalizeString(s, preserve, stripFirst, last && top); - if (s != null) { - stripLast = !preserve && s.charAt(0) == ' '; - if (stripLast && !asb.isEmpty()) { - asb.stripLast(); - } - asb.append(s, map); - } + s = normalizeString(s, preserve, prevEndsWithSpace); + asb.append(s, map); + if (preserve) + endLimit = asb.length(); } - first = false; + } + + if (top) { + while ((endLimit < asb.length()) && (asb.getLastChar() == ' ')) + asb.stripLast(); } } 1.4 +2 -1 xml-batik/sources/org/apache/batik/gvt/flow/FlowGlyphLayout.java Index: FlowGlyphLayout.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/gvt/flow/FlowGlyphLayout.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- FlowGlyphLayout.java 4 Dec 2004 18:40:45 -0000 1.3 +++ FlowGlyphLayout.java 3 Jan 2005 10:48:05 -0000 1.4 @@ -100,6 +100,7 @@ prevBotMargin = bi.getBottomMargin(); numWords += wordInfos[chunk].length; } + Iterator frIter = flowRects.iterator(); RegionInfo currentRegion = null; int currWord = 0; 1.7 +84 -81 xml-batik/test-references/samples/tests/spec/linking/anchor.png <<Binary file>> 1.4 +78 -97 xml-batik/test-references/samples/tests/spec/linking/anchorInsideText.png <<Binary file>> 1.6 +47 -40 xml-batik/test-references/samples/tests/spec/linking/pointerEvents.png <<Binary file>> 1.6 +119 -103 xml-batik/test-references/samples/tests/spec/linking/pointerEvents2.png <<Binary file>> 1.7 +103 -88 xml-batik/test-references/samples/tests/spec/structure/symbolViewBoxClip.png <<Binary file>> 1.7 +190 -189 xml-batik/test-references/samples/tests/spec/structure/symbolViewBoxOverflow.png <<Binary file>> 1.7 +102 -95 xml-batik/test-references/samples/tests/spec/structure/toolTips.png <<Binary file>> 1.12 +138 -124 xml-batik/test-references/samples/tests/spec/text/smallFonts.png <<Binary file>> 1.1 xml-batik/test-references/samples/tests/spec/text/xmlSpace.png <<Binary file>> 1.2 +131 -131 xml-batik/test-references/samples/tests/spec12/text/flowText2.png <<Binary file>> 1.124 +4 -1 xml-batik/test-resources/org/apache/batik/test/samplesRendering.xml Index: samplesRendering.xml =================================================================== RCS file: /home/cvs/xml-batik/test-resources/org/apache/batik/test/samplesRendering.xml,v retrieving revision 1.123 retrieving revision 1.124 diff -u -r1.123 -r1.124 --- samplesRendering.xml 4 Dec 2004 18:40:45 -0000 1.123 +++ samplesRendering.xml 3 Jan 2005 10:48:06 -0000 1.124 @@ -350,6 +350,9 @@ <test id="samples/tests/spec/text/textPosition.svg" /> <test id="samples/tests/spec/text/textPosition2.svg" /> <test id="samples/tests/spec/text/textGlyphOrientationHorizontal.svg"/> + <test id="samples/tests/spec/text/xmlSpace.svg"> + <property name="Validating" class="java.lang.Boolean" value="false" /> + </test> </testGroup> <testGroup id="tests.spec.scripting">
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]