deweese 2003/08/31 10:27:13 Modified: samples/tests/spec/scripting/textcontent numberOfChars.svg sources/org/apache/batik/bridge SVGTextElementBridge.java sources/org/apache/batik/dom/svg SVGTextContentSupport.java sources/org/apache/batik/swing/gvt JGVTComponent.java sources/org/apache/batik/swing/svg JSVGComponent.java test-resources/org/apache/batik/test samplesRendering.xml Added: lib README.xerces_2_5_0.txt samples/tests/spec/scripting text_content.svg test-references/samples/tests/spec/scripting text_content.png Removed: lib README.xerces_2_3_0.txt Log: 1) The Text content interfaces now include all characters but throw DOM exceptions when the glyphs for a particular character aren't visible. 2) JSVGCanvas/Component are back to using getBounds for rendering region (this makes it work with a standard JScrollPane (although it will create an offscreen buffer the full size of the document - not just the visible portion of the document). 3) New test of text_content interfaces. Revision Changes Path 1.1 xml-batik/lib/README.xerces_2_5_0.txt Index: README.xerces_2_5_0.txt =================================================================== The xerces_2_5_0.jar file comes from the Apache Xerces project: http://xml.apache.org/dist/xerces-j/ 1.1 xml-batik/samples/tests/spec/scripting/text_content.svg Index: text_content.svg =================================================================== <?xml version="1.0" standalone="no"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"> <!-- ============================================================================ The Apache Software License, Version 1.1 ============================================================================ Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modifica- tion, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The end-user documentation included with the redistribution, if any, must include the following acknowledgment: "This product includes software developed by the Apache Software Foundation (http://www.apache.org/)." Alternately, this acknowledgment may appear in the software itself, if and wherever such third-party acknowledgments normally appear. 4. The names "Batik" and "Apache Software Foundation" must not be used to endorse or promote products derived from this software without prior written permission. For written permission, please contact [EMAIL PROTECTED] 5. Products derived from this software may not be called "Apache", nor may "Apache" appear in their name, without prior written permission of the Apache Software Foundation. THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU- DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. This software consists of voluntary contributions made by many individuals on behalf of the Apache Software Foundation. For more information on the Apache Software Foundation, please see <http://www.apache.org/>. --> <!-- ====================================================================== --> <!-- Tests text content interface for the various text cases --> <!-- --> <!-- @author [EMAIL PROTECTED] --> <!-- @version $Id: text_content.svg,v 1.1 2003/08/31 17:27:12 deweese Exp $ --> <!-- ====================================================================== --> <?xml-stylesheet type="text/css" href="../../resources/style/test.css" ?> <svg id="body" width="450" height="500" viewBox="0 0 450 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <script language="text/ecmascript"><![CDATA[ var svgns = "http://www.w3.org/2000/svg"; var xlinkns = "http://www.w3.org/1999/xlink"; var ids = new Array("simple", "tspans", "dxdy", "xy", "tp_start", "tp_middle", "tp_end", "test", "tp_ag_middle", "ag1", "ag2", "ag3", "ag4", "ligature", "tp_lig", "lig2", "tp_lig2"); for (var i=0; i<ids.length; i++) { var elem = document.getElementById(ids[i]); showCharactersInfo(elem); showTextInfo(elem); } function showTextInfo(elt) { var group = elt; var text = elt; while (group.localName != "g") { if (text.localName != "text") text = text.parentNode; group = group.parentNode; } var bbox = text.getBBox(); var x=bbox.x+bbox.width+10; var y=bbox.y+bbox.height*.6 var t = document.createElementNS(svgns, "text"); t.setAttribute("x", ""+x); t.setAttribute("y", ""+y); t.setAttribute("font-size", "10"); var str = "len: " + elt.getComputedTextLength(); var idx = str.indexOf('.'); if (idx >= 0) { idx += 4; if (idx > str.length) idx = str.length; str = str.substring(0,idx); } var tn = document.createTextNode(str); t.appendChild(tn); group.appendChild(t); } function showCharactersInfo(elt) { var numChar = elt.getNumberOfChars(); for(var i=0; i<numChar; i++) { showCharacterBBox(elt, i); showCharacterStartEndPosition(elt, i); } } function showCharacterBBox(elt, index) { var group = elt; while (group.localName != "g") group = group.parentNode; try { var box = elt.getExtentOfChar(index); var mat = elt.getTransformToElement(group); var root = document.getRootElement(); var pt0 = root.createSVGPoint(); pt0.x = box.getX(); pt0.y = box.getY(); pt0 = pt0.matrixTransform(mat); var pt1 = root.createSVGPoint(); pt1.x = box.getX()+box.getWidth(); pt1.y = box.getY(); pt1 = pt1.matrixTransform(mat); var pt2 = root.createSVGPoint(); pt2.x = box.getX()+box.getWidth(); pt2.y = box.getY()+box.getHeight(); pt2 = pt2.matrixTransform(mat); var pt3 = root.createSVGPoint(); pt3.x = box.getX(); pt3.y = box.getY()+box.getHeight(); pt3 = pt3.matrixTransform(mat); var p = document.createElementNS(svgns,"path"); p.setAttribute("d","M" + pt0.x + "," + pt0.y + "L" + pt1.x + "," + pt1.y + "L" + pt2.x + "," + pt2.y + "L" + pt3.x + "," + pt3.y + "z"); p.setAttributeNS(null,"stroke","grey"); p.setAttributeNS(null,"fill","none"); group.appendChild(p); } catch (e) { // System.err.println("Err: " + e); } } function showCharacterStartEndPosition(elt, index) { var group = elt; while (group.localName != "g") group = group.parentNode; // var mat = elt.getTransformToElement(group); try { var p1 = elt.getStartPositionOfChar(index); var u = document.createElementNS(svgns,"use"); u.setAttributeNS(xlinkns,"href","#dot"); u.setAttributeNS(null,"transform", "translate("+p1.x+","+p1.y+")"); group.appendChild(u); var p2 = elt.getEndPositionOfChar(index); u = document.createElementNS(svgns,"use"); u.setAttributeNS(xlinkns,"href","#box"); u.setAttributeNS(null,"transform", "translate("+p2.x+","+p2.y+")"); group.appendChild(u); u = document.createElementNS(svgns,"use"); u.setAttributeNS(xlinkns,"href","#line"); var ang = elt.getRotationOfChar(index); var x = ( p1.x + p2.x )/2; var y = ( p1.y + p2.y )/2; u.setAttributeNS(null,"transform", "translate("+x+","+y+") rotate("+ang+")"); group.appendChild(u); } catch (e) { // System.err.println("Err: " + e); } } function regardStart() { regardTestInstance.scriptDone(); } ]]></script> <title>Text content interface test.</title> <text x="50%" y="45" class="title">Text content interface test</text> <defs> <rect id="box" x="-2.5" y="-2.5" width="5" height="5" stroke="red" fill="none"/> <rect id="dot" x="-1" y="-1" width="2" height="2" stroke="none" fill="green"/> <line stroke-width="1" id="line" stroke="#0CF" x1="-2.5" y1="0" x2="2.5" y2="0" /> <path id="Path1" style="fill:none; stroke:blue;" transform="scale(0.30,0.50)" d="M 50 100 C50 0 350 0 350 100"/> <font horiz-adv-x="600" id="stroke"> <font-face font-family="Stroke" font-weight="normal" units-per-em="1000" ascent="1000" descent="250" alphabetic="0"/> <missing-glyph horiz-adv-x="600" d="M0 0 V75 H50 V0 z"/> <glyph id="MyABC" unicode="ABC" glyph-name="ABC" horiz-adv-x="1800" d="M661,-13l-300,750c-3,8 -10,12 -18,13c-8,0 -15,-5 -19,-12l-320,-750c-4,-10 0,-22 11,-26c10,-4 22,0 26,11c0,0 63,147 131,308l329,0c64,-160 123,-307 123,-307c4,-10 16,-15 26,-11c10,4 15,16 11,26zM190,320c68,159 137,320 153,358c15,-38 80,-199 143,-358l-296,0z M675,750c-11,0 -20,-9 -20,-20l0,-750c0,-11 9,-20 20,-20l224,0c158,0 241,111 241,221c0,81 -45,162 -132,200c87,33 132,104 132,175c0,96 -83,194 -241,194l-224,0zM900,710c138,0 201,-80 201,-154c0,-74 -63,-154 -201,-154c0,0 -170,0 -204,0c0,151 0,292 0,308c33,0 204,0 204,0zM900,362c138,0 201,-94 201,-181c0,-87 -63,-181 -201,-181c0,0 -170,0 -204,0c0,19 0,181 0,362c33,0 204,0 204,0z M1100,355c0,-218 126,-395 282,-395c93,0 180,64 233,172c5,10 1,22 -9,27c-10,5 -22,1 -27,-9c-46,-93 -119,-149 -197,-149c-133,0 -242,159 -242,355c0,196 108,355 242,355c78,0 151,-56 197,-149c5,-10 17,-14 27,-9c10,5 14,17 9,27c-52,107 -139,172 -233,172c-155,0 -282,-177 -282,-395z"/> <glyph id="MyDE" unicode="DE" glyph-name="DE" horiz-adv-x="1080" d="M20,750c-11,0 -20,-9 -20,-20l0,-750c0,-11 9,-20 20,-20l224,0c165,0 241,205 241,395c0,190 -75,395 -241,395l-224,0zM244,710c132,0 201,-179 201,-355c0,-176 -69,-355 -201,-355c0,0 -170,0 -204,0c0,37 0,673 0,710c33,0 204,0 204,0z M920,0c0,0 -344,0 -380,0c0,19 0,192 0,362l251,0c11,0 20,9 20,20c0,11 -9,20 -20,20l-251,0c0,151 0,291 0,308c36,0 380,0 380,0c11,0 20,9 20,20c0,11 -9,20 -20,20l-400,0c-11,0 -20,-9 -20,-20l0,-750c0,-11 9,-20 20,-20l400,0c11,0 20,9 20,20c0,11 -9,20 -20,20z"/> <glyph id="MyA" unicode="A" glyph-name="A" horiz-adv-x="780" d="M661,-13l-300,750c-3,8 -10,12 -18,13c-8,0 -15,-5 -19,-12l-320,-750c-4,-10 0,-22 11,-26c10,-4 22,0 26,11c0,0 63,147 131,308l329,0c64,-160 123,-307 123,-307c4,-10 16,-15 26,-11c10,4 15,16 11,26zM190,320c68,159 137,320 153,358c15,-38 80,-199 143,-358l-296,0z"/> <glyph id="MyB" unicode="B" glyph-name="B" horiz-adv-x="630" d="M20,750c-11,0 -20,-9 -20,-20l0,-750c0,-11 9,-20 20,-20l224,0c158,0 241,111 241,221c0,81 -45,162 -132,200c87,33 132,104 132,175c0,96 -83,194 -241,194l-224,0zM244,710c138,0 201,-80 201,-154c0,-74 -63,-154 -201,-154c0,0 -170,0 -204,0c0,151 0,292 0,308c33,0 204,0 204,0zM244,362c138,0 201,-94 201,-181c0,-87 -63,-181 -201,-181c0,0 -170,0 -204,0c0,19 0,181 0,362c33,0 204,0 204,0z"/> <glyph id="MyC" unicode="C" glyph-name="C" horiz-adv-x="650" d="M0,355c0,-218 126,-395 282,-395c93,0 180,64 233,172c5,10 1,22 -9,27c-10,5 -22,1 -27,-9c-46,-93 -119,-149 -197,-149c-133,0 -242,159 -242,355c0,196 108,355 242,355c78,0 151,-56 197,-149c5,-10 17,-14 27,-9c10,5 14,17 9,27c-52,107 -139,172 -233,172c-155,0 -282,-177 -282,-395z"/> <glyph id="MyD" unicode="D" glyph-name="D" horiz-adv-x="630" d="M20,750c-11,0 -20,-9 -20,-20l0,-750c0,-11 9,-20 20,-20l224,0c165,0 241,205 241,395c0,190 -75,395 -241,395l-224,0zM244,710c132,0 201,-179 201,-355c0,-176 -69,-355 -201,-355c0,0 -170,0 -204,0c0,37 0,673 0,710c33,0 204,0 204,0z"/> <glyph id="MyE" unicode="E" glyph-name="E" horiz-adv-x="580" d="M420,0c0,0 -344,0 -380,0c0,19 0,192 0,362l251,0c11,0 20,9 20,20c0,11 -9,20 -20,20l-251,0c0,151 0,291 0,308c36,0 380,0 380,0c11,0 20,9 20,20c0,11 -9,20 -20,20l-400,0c-11,0 -20,-9 -20,-20l0,-750c0,-11 9,-20 20,-20l400,0c11,0 20,9 20,20c0,11 -9,20 -20,20z"/> </font> <altGlyphDef id="MyAltGlyphDef1"> <glyphRef xlink:href="#MyA"/> <glyphRef xlink:href="#MyB"/> <glyphRef xlink:href="#MyC"/> <glyphRef xlink:href="#MyD"/> <glyphRef xlink:href="#MyE"/> </altGlyphDef> <altGlyphDef id="MyAGTest"> <glyphRef xlink:href="#MyA"/> <glyphRef xlink:href="#MyB"/> <glyphRef xlink:href="#MyC"/> <glyphRef xlink:href="#MyD"/> </altGlyphDef> <altGlyphDef id="MyAltGlyphDef4"> <altGlyphItem> <glyphRef xlink:href="#MyA"/> <glyphRef xlink:href="#NoSuchId"/> <glyphRef xlink:href="#MyC"/> </altGlyphItem> <altGlyphItem> <glyphRef xlink:href="#MyA"/> <glyphRef xlink:href="#MyB"/> <glyphRef xlink:href="#MyC"/> <glyphRef xlink:href="#MyD"/> <glyphRef xlink:href="#MyE"/> </altGlyphItem> </altGlyphDef> <altGlyphDef id="MyAltGlyphDef5"> <altGlyphItem> <glyphRef xlink:href="#MyA"/> <glyphRef xlink:href="#NoSuchId"/> <glyphRef xlink:href="#MyA"/> </altGlyphItem> <altGlyphItem> <glyphRef xlink:href="#MyB"/> <glyphRef xlink:href="#MyB"/> <glyphRef xlink:href="#NoSuchId"/> </altGlyphItem> </altGlyphDef> </defs> <defs> </defs> <g id="test-content" style="font-size:18"> <text id="simple" x="25" y="100">Simple Text</text> <text x="25" y="130">Using <tspan id="tspans" fill="blue">Tspan</tspan></text> <text id="dxdy" x="25" y="160">Tspan <tspan fill="blue" dx="2 -1 0 -1 2" dy="-5 10 -5 -5 10" >Dx/Dy</tspan></text> <text id="xy" x="25" y="190">Tspan <tspan fill="blue" x="85" y="195" >X/Y</tspan></text> <g transform="translate(230,65)"> <use xlink:href="#Path1" style="fill:none; stroke:blue; stroke-width:2"/> <text id="tp_start" style="text-anchor:start"> <textPath xlink:href="#Path1" startOffset="50%">Text <tspan fill="red" dy="-10">on</tspan><tspan dy="10"> a Path</tspan></textPath> </text> </g> <g transform="translate(230,125)"> <use xlink:href="#Path1" style="fill:none; stroke:blue; stroke-width:2"/> <text id="tp_middle" style="text-anchor:middle"> <textPath xlink:href="#Path1" startOffset="50%">Text <tspan fill="red" dy="-10">on</tspan><tspan dy="10"> a Path</tspan></textPath> </text> </g> <g transform="translate(230,185)"> <use xlink:href="#Path1" style="fill:none; stroke:blue; stroke-width:2"/> <text id="tp_end" style="text-anchor:end"> <textPath xlink:href="#Path1" startOffset="50%">Text <tspan fill="red" dy="-10">on</tspan><tspan dy="10" > a Path</tspan></textPath> </text> </g> <g transform="translate(10,210)"> <use xlink:href="#Path1" style="fill:none; stroke:blue; stroke-width:2"/> <text id="tp_ag_middle" style="text-anchor:middle"> <textPath xlink:href="#Path1" startOffset="50%">glyphRefs: "<altGlyph rotate="10,10,10,10,10" dx="0,2,2,2,2" dy="0,2,2,-2,-2" fill="green" xlink:href="#MyAltGlyphDef1">No Match</altGlyph >"</textPath> </text> </g> <text x="170" y="270" id="test" >phRefs: "<altGlyph rotate="10,10,10,10,10" dx="0,2,2,2,2" dy="0,2,2,-2,-2" fill="green" xlink:href="#MyAGTest">No Match</altGlyph ></text> <text id="ag1" x="5" y="300">5 valid glyphRefs: "<altGlyph fill="green" xlink:href="#MyAltGlyphDef1">No Match</altGlyph>"</text> <text id="ag2" x="5" y="330">2 altGlyphItems, both <tspan fill="red">invalid</tspan>: "<altGlyph fill="red" xlink:href="#MyAltGlyphDef5">No Match</altGlyph>"</text> <text id="ag3" x="5" y="360">2 altGlyphItems, 2nd valid: "<altGlyph fill="green" xlink:href="#MyAltGlyphDef4">No Match</altGlyph>"</text> <text id="ag4" x="5" y="390">5 glyphRefs, dx/dy/rotate: "<altGlyph rotate="10,10,10,10,10" dx="0,2,2,2,2" dy="0,2,2,-2,-2" fill="green" xlink:href="#MyAltGlyphDef1">No Match</altGlyph>"</text> <text id="ligature" x="5" y="420">ligature <tspan font-family="stroke" fill="green">ABCDE</tspan></text> <g transform="translate(10,430)"> <use xlink:href="#Path1" style="fill:none; stroke:blue; stroke-width:2"/> <text id="tp_lig" style="text-anchor:middle"> <textPath xlink:href="#Path1" startOffset="50%">ligature <tspan font-family="stroke" fill="green">ABCDE</tspan></textPath></text> </g> <text id="lig2" x="235" y="420">ligature <tspan font-family="stroke" fill="green">ABC</tspan></text> <g transform="translate(235,430)"> <use xlink:href="#Path1" style="fill:none; stroke:blue; stroke-width:2"/> <text id="tp_lig2" style="text-anchor:middle"> <textPath xlink:href="#Path1" startOffset="65%">ligature <tspan font-family="stroke" fill="green">ABCDE</tspan></textPath></text> </g> </g> </svg> 1.4 +268 -275 xml-batik/samples/tests/spec/scripting/textcontent/numberOfChars.svg Index: numberOfChars.svg =================================================================== RCS file: /home/cvs/xml-batik/samples/tests/spec/scripting/textcontent/numberOfChars.svg,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- numberOfChars.svg 20 Aug 2003 11:31:45 -0000 1.3 +++ numberOfChars.svg 31 Aug 2003 17:27:12 -0000 1.4 @@ -81,275 +81,267 @@ </defs> <script><![CDATA[ - var interval; - var currentFile; - var display; - - function showNumberOfChars(evt) - { - var elt = evt.target; - - while (( elt != null ) && ( elt.getLocalName() != "text" )){ - elt = elt.getParentNode(); - } - - if ( (elt != null) && ( elt.getLocalName() == "text" ) - && !elt.hasAttributeNS(null,"class") ) - { - var doc = elt.getOwnerDocument(); - - var t = doc.getElementById('numberOfChars'); - - var textnode = t.getFirstChild(); - - textnode.setData("Node has "+elt.getNumberOfChars()+" characters"); - - t = doc.getElementById("extraInfo"); - textNode = t.getFirstChild(); - textNode.setData(""); - - startCharactersBBox(elt); - } - } - - function startCharactersBBox(elt){ - - rendering = elt; - currentIndex = 0; - display = 0 ; - run(); - - if ( interval == null ){ - interval = setInterval('run()',500); - } - } - - function run(){ - - - var doc = rendering.getOwnerDocument(); - var group = doc.getElementById('bboxGroup'); - - while (group.hasChildNodes() ){ - group.removeChild(group.getFirstChild()); - } - - if ( display == 0 ) { - showCharactersBBox(rendering,currentIndex); - } - if ( display == 1 ) { - showCharactersStartPosition(rendering,currentIndex); - - showCharactersEndPosition(rendering,currentIndex); - } - if ( display == 2 ) { - showRotationAngle(rendering,currentIndex); - } - - if ( display == 3 ) { - showTextLength(rendering,currentIndex); - } - - //selectAllText(rendering); - currentIndex++; - - if ( currentIndex >= rendering.getNumberOfChars() ){ - currentIndex = 0; - display++; - } - - if ( display == 4 ){ - display = 0 ; - var t = doc.getElementById("extraInfo"); - textNode = t.getFirstChild(); - textNode.setData(""); - } - - } - function selectAllText(rendering){ - rendering.selectSubString(0,rendering.getNumberOfChars()); - } - - function showCharactersBBox(elt, index) - { - var doc = elt.getOwnerDocument(); - - var group = doc.getElementById('bboxGroup'); - - var box = elt.getExtentOfChar(index); - var mat = elt.getTransformToElement(group); - var root = doc.getRootElement(); - var pt0 = root.createSVGPoint(); - pt0.x = box.getX(); - pt0.y = box.getY(); - pt0 = pt0.matrixTransform(mat); - - var pt1 = root.createSVGPoint(); - pt1.x = box.getX()+box.getWidth(); - pt1.y = box.getY(); - pt1 = pt1.matrixTransform(mat); - - var pt2 = root.createSVGPoint(); - pt2.x = box.getX()+box.getWidth(); - pt2.y = box.getY()+box.getHeight(); - pt2 = pt2.matrixTransform(mat); - - var pt3 = root.createSVGPoint(); - pt3.x = box.getX(); - pt3.y = box.getY()+box.getHeight(); - pt3 = pt3.matrixTransform(mat); - - var p = doc.createElementNS - ("http://www.w3.org/2000/svg","path"); - p.setAttribute("d","M" + pt0.x + "," + pt0.y + - "L" + pt1.x + "," + pt1.y + - "L" + pt2.x + "," + pt2.y + - "L" + pt3.x + "," + pt3.y + "z"); - p.setAttributeNS(null,"stroke","red"); - group.appendChild(p); - - } - - function showCharactersStartPosition(elt, index) - { - var doc = elt.getOwnerDocument(); - - var group = doc.getElementById('bboxGroup'); - var root = doc.getRootElement(); - - //while (group.hasChildNodes() ){ - // group.removeChild(group.getFirstChild()); - //} - - var u = doc.createElementNS("http://www.w3.org/2000/svg","use"); - - var point = elt.getStartPositionOfChar(index); - var mat = elt.getTransformToElement(group); - point = point.matrixTransform(mat); - u.setAttributeNS(null,"transform","translate("+point.getX()+","+point.getY()+")"); - u.setAttributeNS("http://www.w3.org/1999/xlink","href","#arrow"); - u.setAttributeNS(null,"stroke","green"); - group.appendChild(u); - - } - - function showRotationAngle(elt, index) - { - var doc = elt.getOwnerDocument(); - - var angle = elt.getRotationOfChar(index); - - var text = doc.getElementById("extraInfo"); - - var textNode = text.getFirstChild(); - - textNode.setData("angle : "+angle); - - var group = doc.getElementById('bboxGroup'); - - var u = doc.createElementNS("http://www.w3.org/2000/svg","use"); - var mat = elt.getTransformToElement(group); - var root = doc.getRootElement(); - - var point1 = elt.getStartPositionOfChar(index); - point1 = point1.matrixTransform(mat); - var point2 = elt.getEndPositionOfChar(index); - point2 = point2.matrixTransform(mat); - - x = ( point1.getX() + point2.getX() )/2; - y = ( point1.getY() + point2.getY() )/2; - - u.setAttributeNS(null,"transform","translate("+x+","+y+") rotate("+angle+") "); - u.setAttributeNS("http://www.w3.org/1999/xlink","href","#line"); - u.setAttributeNS(null,"stroke","green"); - group.appendChild(u); - - } - - function showCharactersEndPosition(elt, index) - { - var doc = elt.getOwnerDocument(); - - var group = doc.getElementById('bboxGroup'); - - //while (group.hasChildNodes() ){ - // group.removeChild(group.getFirstChild()); - //} - - var u = doc.createElementNS("http://www.w3.org/2000/svg","use"); - - var point = elt.getEndPositionOfChar(index); - var mat = elt.getTransformToElement(group); - point = point.matrixTransform(mat); - - u.setAttributeNS(null,"transform","translate("+point.getX()+","+point.getY()+")"); - u.setAttributeNS("http://www.w3.org/1999/xlink","href","#arrow"); - u.setAttributeNS(null,"stroke","blue"); - group.appendChild(u); - - } - - function showTextLength(elt,index){ - - var doc = elt.getOwnerDocument(); - - var group = doc.getElementById('bboxGroup'); - - while (group.hasChildNodes() ){ - group.removeChild(group.getFirstChild()); - } - - var point = elt.getStartPositionOfChar(0); - var mat = elt.getTransformToElement(group); - point = point.matrixTransform(mat); - var length = elt.getSubStringLength(0,index+1); - - var text = doc.getElementById("extraInfo"); - var textNode = text.getFirstChild(); - textNode.setData("Length : "+length); - - var u = doc.createElementNS("http://www.w3.org/2000/svg","line"); - u.setAttributeNS(null,"x1",point.getX()); - u.setAttributeNS(null,"y1",point.getY()); - u.setAttributeNS(null,"x2",(point.getX()+length)); - u.setAttributeNS(null,"y2",point.getY()); - u.setAttributeNS(null,"stroke","red"); - group.appendChild(u); - } - - function switchTo(evt,filename){ - - if ( interval != null ){ - clearInterval(interval); - } - interval = null; - - var doc = evt.target.getOwnerDocument(); - - if ( currentFile == null ){ - currentFile = doc.getElementById('first'); - } - if ( currentFile == evt.target ){ - return; - } - currentFile.removeAttributeNS(null,'fill'); - currentFile = evt.target; - currentFile.setAttributeNS(null,'fill','black'); - - var group = doc.getElementById('bboxGroup'); - - while (group.hasChildNodes() ){ - group.removeChild(group.getFirstChild()); - } - - var use = doc.getElementById('filename'); - use.setAttributeNS("http://www.w3.org/1999/xlink","href",filename); - - var container = doc.getElementById('container'); - container.removeChild(use); - container.appendChild(use); - - } + var interval; + var currentFile; + var display; + var svgns = "http://www.w3.org/2000/svg"; + var xlinkns = "http://www.w3.org/1999/xlink"; + function showNumberOfChars(evt) +{ + var elt = evt.target; + + while (( elt != null ) && ( elt.getLocalName() != "text" )){ + elt = elt.getParentNode(); + } + + if ( (elt != null) && ( elt.getLocalName() == "text" ) + && !elt.hasAttributeNS(null,"class") ) + { + var doc = elt.getOwnerDocument(); + + var t = doc.getElementById('numberOfChars'); + + var textnode = t.getFirstChild(); + + textnode.setData("Node has "+elt.getNumberOfChars()+" characters"); + + t = doc.getElementById("extraInfo"); + textNode = t.getFirstChild(); + textNode.setData(""); + + startCharactersBBox(elt); + } +} + + function startCharactersBBox(elt){ + + rendering = elt; + currentIndex = 0; + display = 0 ; + run(); + + if ( interval == null ){ + interval = setInterval('run()',500); + } + } + + function run(){ + + + var doc = rendering.getOwnerDocument(); + var group = doc.getElementById('bboxGroup'); + + while (group.hasChildNodes() ){ + group.removeChild(group.getFirstChild()); + } + + if ( display == 0 ) { + showCharactersBBox(rendering,currentIndex); + } + if ( display == 1 ) { + showCharactersStartPosition(rendering,currentIndex); + showCharactersEndPosition(rendering,currentIndex); + } + if ( display == 2 ) { + showRotationAngle(rendering,currentIndex); + } + + if ( display == 3 ) { + showTextLength(rendering,currentIndex); + } + + //selectAllText(rendering); + currentIndex++; + var it = doc.getElementById("charIndex"); + var itn = it.getFirstChild(); + itn.setData("Character: " + currentIndex); + + if ( currentIndex >= rendering.getNumberOfChars() ){ + currentIndex = 0; + display++; + } + + if ( display == 4 ){ + display = 0 ; + var t = doc.getElementById("extraInfo"); + var textNode = t.getFirstChild(); + textNode.setData(""); + } + + } + + function selectAllText(rendering){ + rendering.selectSubString(0,rendering.getNumberOfChars()); + } + + function showCharactersBBox(elt, index) { + var doc = elt.getOwnerDocument(); + + var group = doc.getElementById('bboxGroup'); + + try { + var box = elt.getExtentOfChar(index); + var mat = elt.getTransformToElement(group); + var root = doc.getRootElement(); + + var pt0 = root.createSVGPoint(); + pt0.x = box.getX(); + pt0.y = box.getY(); + pt0 = pt0.matrixTransform(mat); + + var pt1 = root.createSVGPoint(); + pt1.x = box.getX()+box.getWidth(); + pt1.y = box.getY(); + pt1 = pt1.matrixTransform(mat); + + var pt2 = root.createSVGPoint(); + pt2.x = box.getX()+box.getWidth(); + pt2.y = box.getY()+box.getHeight(); + pt2 = pt2.matrixTransform(mat); + + var pt3 = root.createSVGPoint(); + pt3.x = box.getX(); + pt3.y = box.getY()+box.getHeight(); + pt3 = pt3.matrixTransform(mat); + + var p = doc.createElementNS(svgns,"path"); + p.setAttribute("d","M" + pt0.x + "," + pt0.y + + "L" + pt1.x + "," + pt1.y + + "L" + pt2.x + "," + pt2.y + + "L" + pt3.x + "," + pt3.y + "z"); + p.setAttributeNS(null,"stroke","red"); + group.appendChild(p); + } catch (e) { } + } + + function showCharactersStartPosition(elt, index) { + var doc = elt.getOwnerDocument(); + var group = doc.getElementById('bboxGroup'); + + try { + var point = elt.getStartPositionOfChar(index); + var mat = elt.getTransformToElement(group); + point = point.matrixTransform(mat); + var u = doc.createElementNS(svgns,"use"); + u.setAttributeNS(null,"transform", + "translate("+point.x+","+point.y+")"); + u.setAttributeNS(xlinkns,"href","#arrow"); + u.setAttributeNS(null,"stroke","green"); + group.appendChild(u); + } catch (e) { } + } + + function showRotationAngle(elt, index) { + var doc = elt.getOwnerDocument(); + var text = doc.getElementById("extraInfo"); + var textNode = text.getFirstChild(); + try { + var angle = elt.getRotationOfChar(index); + + textNode.setData("angle : "+angle); + + var group = doc.getElementById('bboxGroup'); + + var point1 = elt.getStartPositionOfChar(index); + var point2 = elt.getEndPositionOfChar(index); + + var u = doc.createElementNS(svgns,"use"); + var mat = elt.getTransformToElement(group); + + point1 = point1.matrixTransform(mat); + point2 = point2.matrixTransform(mat); + + x = ( point1.getX() + point2.getX() )/2; + y = ( point1.getY() + point2.getY() )/2; + + u.setAttributeNS(null,"transform", + "translate("+x+","+y+") rotate("+angle+")"); + u.setAttributeNS(xlinkns,"href","#line"); + u.setAttributeNS(null,"stroke","green"); + group.appendChild(u); + } catch (e) { + textNode.setData("angle : <not visible>"); + } + } + + function showCharactersEndPosition(elt, index) { + var doc = elt.getOwnerDocument(); + + var group = doc.getElementById('bboxGroup'); + + try { + var point = elt.getEndPositionOfChar(index); + var mat = elt.getTransformToElement(group); + point = point.matrixTransform(mat); + + var u = doc.createElementNS(svgns,"use"); + u.setAttributeNS(null,"transform", + "translate("+point.x+","+point.y+")"); + u.setAttributeNS(xlinkns,"href","#arrow"); + u.setAttributeNS(null,"stroke","blue"); + group.appendChild(u); + } catch (e) { } + } + + function showTextLength(elt,index) { + + var doc = elt.getOwnerDocument(); + + var group = doc.getElementById('bboxGroup'); + + try { + var length = elt.getSubStringLength(0,index+1); + var text = doc.getElementById("extraInfo"); + var textNode = text.getFirstChild(); + textNode.setData("Length : "+length); + + var point = elt.getStartPositionOfChar(0); + var mat = elt.getTransformToElement(group); + point = point.matrixTransform(mat); + + var u = doc.createElementNS + (svgns,"line"); + u.setAttributeNS(null,"x1",point.getX()); + u.setAttributeNS(null,"y1",point.getY()); + u.setAttributeNS(null,"x2",(point.getX()+length)); + u.setAttributeNS(null,"y2",point.getY()); + u.setAttributeNS(null,"stroke","red"); + group.appendChild(u); + } catch (e) { } + } + + function switchTo(evt,filename){ + + if ( interval != null ){ + clearInterval(interval); + } + interval = null; + + var doc = evt.target.getOwnerDocument(); + + if ( currentFile == null ){ + currentFile = doc.getElementById('first'); + } + if ( currentFile == evt.target ){ + return; + } + currentFile.removeAttributeNS(null,'fill'); + currentFile = evt.target; + currentFile.setAttributeNS(null,'fill','black'); + + var group = doc.getElementById('bboxGroup'); + + while (group.hasChildNodes() ){ + group.removeChild(group.getFirstChild()); + } + + var use = doc.getElementById('filename'); + use.setAttributeNS(xlinkns,"href",filename); + + var container = doc.getElementById('container'); + container.removeChild(use); + container.appendChild(use); + } ]]></script> <svg id="container" x="0" y="0" width="450" height="500" viewBox="0 0 450 500" > @@ -369,12 +361,13 @@ <use xlink:href="../../../../batikLogo.svg#Batik_Tag_Box" /> -<text class="filename" id="numberOfChars" x="90%" y="520" style="text-anchor:end"> -no text selected -</text> -<text class="filename" id="extraInfo" x="90%" y="535" style="text-anchor:end"> -no text selected +<text class="filename" id="numberOfChars" x="90%" y="520" + style="text-anchor:end">no text selected </text> +<text class="filename" id="charIndex" x="90%" y="535" style="text-anchor:end" + >no text selected</text> +<text class="filename" id="extraInfo" x="90%" y="550" style="text-anchor:end" + >no text selected</text> <g fill="gray"> <text id="first" fill="black" class="filename" x="5%" y="530" onclick="switchTo(evt,'../../text/textOnPath.svg#content')" >textOnPath</text> <text class="filename" x="5%" y="545" onclick="switchTo(evt,'../../text/textStyles.svg#testContent')" >textStyles</text> 1.89 +158 -430 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.88 retrieving revision 1.89 diff -u -r1.88 -r1.89 --- SVGTextElementBridge.java 22 Aug 2003 21:22:44 -0000 1.88 +++ SVGTextElementBridge.java 31 Aug 2003 17:27:12 -0000 1.89 @@ -2228,84 +2228,7 @@ int lastChar = getLastCharacterIndexForElement(aci,element); - //retrieve the text run for the text node - List list = getTextRuns((TextNode)node); - - int visible = 0; - - for(int k = firstChar ; k <= lastChar ; k++ ){ - - for( int l = 0 ; l < list.size() ; l++ ){ - StrokingTextPainter.TextRun run = - (StrokingTextPainter.TextRun)list.get(l); - - TextSpanLayout layout = run.getLayout(); - - if ( layout.hasCharacterIndex(k) ){ - if ( layout.isOnATextPath() ){ - - GVTGlyphVector vector = layout.getGlyphVector(); - - //alt glyph ? - if ( layout.isAltGlyph() ){ - //get the number of glyph visible here - int glyphs = vector.getNumGlyphs(); - int visibleGlyphs = 0; - for( int h=0 ; h < glyphs ; h++ ){ - if ( vector.isGlyphVisible(h)){ - visibleGlyphs++; - } - } - //get the number of character associated - //to this run - int charactersInRun = 1; - while ( layout.hasCharacterIndex( k+1 )){ - charactersInRun++; - k++; - } - visible += (charactersInRun*visibleGlyphs/glyphs); - } - else{ - int lastGlyphIndexFound = -1; - do{ - int glyphIndex = layout.getGlyphIndex(k); - if( glyphIndex == -1 ){ - //probable missing glyph - if ( layout.isLeftToRight() ){ - glyphIndex = 1 + lastGlyphIndexFound; - } - else{ - glyphIndex = ( lastGlyphIndexFound == -1) - ? vector.getNumGlyphs()-1 - : lastGlyphIndexFound -1; - } - } - lastGlyphIndexFound = glyphIndex; - if ( vector.isGlyphVisible( glyphIndex ) ){ - visible++; - } - - k++; - }while (k <= lastChar && layout.hasCharacterIndex(k) ); - //got one too far; - k--; - } - - } - else{ - visible++; - while ( k < lastChar && layout.hasCharacterIndex(k+1) ){ - k++; - visible++; - } - } - } - } - } - - //return( lastChar - firstChar + 1 ); - return visible; - + return( lastChar - firstChar + 1 ); } @@ -2315,7 +2238,8 @@ */ protected Rectangle2D getExtentOfChar(Element element,int charnum ){ - AttributedCharacterIterator aci = ((TextNode)node).getAttributedCharacterIterator(); + AttributedCharacterIterator aci; + aci = ((TextNode)node).getAttributedCharacterIterator(); int firstChar = getFirstCharacterIndexForElement(aci,element); @@ -2326,41 +2250,41 @@ List list = getTextRuns((TextNode)node); //find the character 'charnum' in the text run - CharacterInformation info = getCharacterInformation(list, firstChar,charnum, aci); + CharacterInformation info; + info = getCharacterInformation(list, firstChar,charnum, aci); - if ( info != null ){ + if ( info == null ) + return null; - //retrieve the glyphvector containing the glyph - //for 'charnum' - GVTGlyphVector it = info.layout.getGlyphVector(); + //retrieve the glyphvector containing the glyph + //for 'charnum' + GVTGlyphVector it = info.layout.getGlyphVector(); - Shape b; + Shape b = null; - if ( info.glyphIndexStart == info.glyphIndexEnd ){ + if ( info.glyphIndexStart == info.glyphIndexEnd ){ + if (it.isGlyphVisible(info.glyphIndexStart)) b = it.getGlyphOutline(info.glyphIndexStart); - } - else{ - GeneralPath path = new GeneralPath(); - for( int k = info.glyphIndexStart ; - k <= info.glyphIndexEnd; - k++){ - - path.append(it.getGlyphOutline(k),false); + } else { + GeneralPath path = null; + for( int k = info.glyphIndexStart ; + k <= info.glyphIndexEnd; + k++){ + if (it.isGlyphVisible(k)) { + if (path == null) + path = new GeneralPath(it.getGlyphOutline(k)); + else + path.append(it.getGlyphOutline(k),false); } - b = path; } - - //get the transform for the node - // AffineTransform at = getCTM(); - // b = at.createTransformedShape(b); - - //return the bounding box of the outline - return b.getBounds2D(); - + b = path; } - else{ + + if (b == null) return null; - } + + //return the bounding box of the outline + return b.getBounds2D(); } @@ -2381,43 +2305,35 @@ List list = getTextRuns((TextNode)node); //find the character 'charnum' in the text run - CharacterInformation info = getCharacterInformation(list, firstChar,charnum, aci); + CharacterInformation info; + info = getCharacterInformation(list, firstChar,charnum, aci); - if ( info != null ){ - return getStartPoint( info ); - } - else{ + if ( info == null ) return null; - } + + return getStartPoint( info ); } protected Point2D getStartPoint(CharacterInformation info){ GVTGlyphVector it = info.layout.getGlyphVector(); + if (!it.isGlyphVisible(info.glyphIndexStart)) + return null; Point2D b = it.getGlyphPosition(info.glyphIndexStart); - Point2D.Float result = new Point2D.Float(); - AffineTransform glyphTransform; glyphTransform = it.getGlyphTransform(info.glyphIndexStart); - float x = 0,y = 0; //glyph are defined starting at position (0,0) - if ( glyphTransform != null ){ - + Point2D.Float result = new Point2D.Float(0, 0); + if ( glyphTransform != null ) //apply the glyph transformation to the start point - glyphTransform.transform(new Point2D.Double(x,y),result); - x = result.x; - y = result.y; - } + glyphTransform.transform(result,result); - x += b.getX(); - y += b.getY(); - - result.x = x; - result.y = y; + result.x += b.getX(); + result.y += b.getY(); return result; } @@ -2427,7 +2343,8 @@ */ protected Point2D getEndPositionOfChar(Element element,int charnum ){ - AttributedCharacterIterator aci = ((TextNode)node).getAttributedCharacterIterator(); + AttributedCharacterIterator aci; + aci = ((TextNode)node).getAttributedCharacterIterator(); int firstChar = getFirstCharacterIndexForElement(aci,element); @@ -2438,43 +2355,36 @@ List list = getTextRuns((TextNode)node); //find the glyph information for the character 'charnum' - CharacterInformation info = getCharacterInformation(list, firstChar,charnum, aci); + CharacterInformation info; + info = getCharacterInformation(list, firstChar,charnum, aci); - if ( info != null ){ - return getEndPoint(info); - } - else{ + if ( info == null ) return null; - } + return getEndPoint(info); } protected Point2D getEndPoint(CharacterInformation info){ GVTGlyphVector it = info.layout.getGlyphVector(); + if (!it.isGlyphVisible(info.glyphIndexEnd)) + return null; Point2D b = it.getGlyphPosition(info.glyphIndexEnd); - Point2D.Float result = new Point2D.Float(); - AffineTransform glyphTransform; glyphTransform = it.getGlyphTransform(info.glyphIndexEnd); GVTGlyphMetrics metrics = it.getGlyphMetrics(info.glyphIndexEnd); - float x = 0,y = 0; - - x = metrics.getHorizontalAdvance(); + + Point2D.Float result = new Point2D.Float + (metrics.getHorizontalAdvance(), 0); - if ( glyphTransform != null ){ - - glyphTransform.transform(new Point2D.Float(x,y),result); - x = result.x; - y = result.y; - } - x += b.getX(); - y += b.getY(); - result.x = x; - result.y = y; + if ( glyphTransform != null ) + glyphTransform.transform(result,result); + + result.x += b.getX(); + result.y += b.getY(); return result; } @@ -2484,7 +2394,8 @@ */ protected float getRotationOfChar(Element element, int charnum){ - AttributedCharacterIterator aci = ((TextNode)node).getAttributedCharacterIterator(); + AttributedCharacterIterator aci; + aci = ((TextNode)node).getAttributedCharacterIterator(); //first the first character for the element int firstChar = getFirstCharacterIndexForElement(aci,element); @@ -2495,58 +2406,49 @@ List list = getTextRuns((TextNode)node); //find the glyph information for the character 'charnum' - CharacterInformation info = getCharacterInformation(list, firstChar,charnum, aci); + CharacterInformation info; + info = getCharacterInformation(list, firstChar,charnum, aci); - double angle = 0.0; int nbGlyphs = 0; if ( info != null ){ - GVTGlyphVector it = info.layout.getGlyphVector(); for( int k = info.glyphIndexStart ; k <= info.glyphIndexEnd ; k++ ){ + if (!it.isGlyphVisible(k)) continue; nbGlyphs++; - double glyphAngle = 0.0; - //the glyph transform contains only a scale and a rotate. AffineTransform glyphTransform = it.getGlyphTransform(k); + if ( glyphTransform == null ) continue; - if ( glyphTransform != null ){ - double cosTheta = glyphTransform.getScaleX(); - double sinTheta = glyphTransform.getShearX(); + double glyphAngle = 0.0; + double cosTheta = glyphTransform.getScaleX(); + double sinTheta = glyphTransform.getShearX(); - //extract the angle - if ( cosTheta == 0.0 ){ - if ( sinTheta > 0 ){ - glyphAngle = Math.PI; - } - else{ - glyphAngle = -Math.PI; - } - } - else{ - glyphAngle = Math.atan(sinTheta/cosTheta); - if ( cosTheta < 0 ){ - glyphAngle += Math.PI; - } - } - //get a degrees value for the angle - //SVG angle are clock wise java anticlockwise + //extract the angle + if ( cosTheta == 0.0 ){ + if ( sinTheta > 0 ) glyphAngle = Math.PI; + else glyphAngle = -Math.PI; + } else { + glyphAngle = Math.atan(sinTheta/cosTheta); + if ( cosTheta < 0 ) + glyphAngle += Math.PI; + } + //get a degrees value for the angle + //SVG angle are clock wise java anticlockwise + + glyphAngle = (Math.toDegrees( - glyphAngle ) ) % 360.0; - glyphAngle = (Math.toDegrees( - glyphAngle ) ) % 360.0; - //remove the orientation from the value angle += glyphAngle - info.getComputedOrientationAngle(); - } - - } } + if (nbGlyphs == 0) return 0; return (float)(angle / nbGlyphs ); } @@ -2567,7 +2469,8 @@ int nchars){ float length = 0; - AttributedCharacterIterator aci = ((TextNode)node).getAttributedCharacterIterator(); + AttributedCharacterIterator aci; + aci = ((TextNode)node).getAttributedCharacterIterator(); TextNode textNode = (TextNode)node; int firstChar = getFirstCharacterIndexForElement(aci,element); @@ -2577,40 +2480,72 @@ List list = getTextRuns(textNode); - CharacterInformation currentInfo = getCharacterInformation - (list, firstChar,charnum,aci); + CharacterInformation currentInfo; + currentInfo = getCharacterInformation(list, firstChar,charnum,aci); CharacterInformation lastCharacterInRunInfo = null; int chIndex = currentInfo.characterIndex+1; - - for( int k = charnum +1; k < charnum +nchars ; k++){ - - //reach the next run - if ( currentInfo.layout.hasCharacterIndex(chIndex) ){ - chIndex++; - continue; + GVTGlyphVector vector = currentInfo.layout.getGlyphVector(); + float [] advs = currentInfo.layout.getGlyphAdvances(); + boolean [] glyphTrack = new boolean[advs.length]; + for( int k = charnum +1; k < charnum +nchars ; k++) { + if (currentInfo.layout.isOnATextPath() ){ + for (int gi = currentInfo.glyphIndexStart; + gi <= currentInfo.glyphIndexEnd; gi++) { + if ((vector.isGlyphVisible(gi)) && !glyphTrack[gi]) + length += advs[gi+1]-advs[gi]; + glyphTrack[gi] = true; + } + CharacterInformation newInfo; + newInfo = getCharacterInformation(list, firstChar, k, aci); + if (newInfo.layout != currentInfo.layout) { + vector = newInfo.layout.getGlyphVector(); + advs = newInfo.layout.getGlyphAdvances(); + glyphTrack = new boolean[advs.length]; + chIndex = currentInfo.characterIndex+1; + } + currentInfo = newInfo; + } else { + //reach the next run + if ( currentInfo.layout.hasCharacterIndex(chIndex) ){ + chIndex++; + continue; + } + + lastCharacterInRunInfo = getCharacterInformation + (list,firstChar,k-1,aci); + + //if the text run change compute the distance between the + //first character of the run and the last + length += distanceFirstLastCharacterInRun + (currentInfo,lastCharacterInRunInfo); + + currentInfo = getCharacterInformation(list,firstChar,k,aci); + chIndex = currentInfo.characterIndex+1; + vector = currentInfo.layout.getGlyphVector(); + advs = currentInfo.layout.getGlyphAdvances(); + glyphTrack = new boolean[advs.length]; + lastCharacterInRunInfo = null; } + } - lastCharacterInRunInfo = getCharacterInformation - (list,firstChar,k-1,aci); - - //if the text run change compute the distance between the - //first character of the run and the last + if (currentInfo.layout.isOnATextPath() ){ + for (int gi = currentInfo.glyphIndexStart; + gi <= currentInfo.glyphIndexEnd; gi++) { + if ((vector.isGlyphVisible(gi)) && !glyphTrack[gi]) + length += advs[gi+1]-advs[gi]; + glyphTrack[gi] = true; + } + } else { + if ( lastCharacterInRunInfo == null ){ + lastCharacterInRunInfo = getCharacterInformation + (list,firstChar,charnum+nchars-1,aci); + } + //add the length between the end position of the last character + //and the first character in the run length += distanceFirstLastCharacterInRun (currentInfo,lastCharacterInRunInfo); - - currentInfo = getCharacterInformation(list,firstChar,k,aci); - chIndex = currentInfo.characterIndex+1; - lastCharacterInRunInfo = null; } - if ( lastCharacterInRunInfo == null ){ - lastCharacterInRunInfo = getCharacterInformation - (list,firstChar,charnum+nchars-1,aci); - } - //add the length between the end position of the last character - //and the first character in the run - length += distanceFirstLastCharacterInRun(currentInfo,lastCharacterInRunInfo); - return length; } @@ -2667,10 +2602,9 @@ * TODO : report the selection to the selection * manager in JSVGComponent. */ - protected void selectSubString(Element element, int charnum, int nchars){ - - AttributedCharacterIterator aci = - ((TextNode)node).getAttributedCharacterIterator(); + protected void selectSubString(Element element, int charnum, int nchars) { + AttributedCharacterIterator aci; + aci = ((TextNode)node).getAttributedCharacterIterator(); TextNode textNode = (TextNode)node; int firstChar = getFirstCharacterIndexForElement(aci,element); @@ -2682,13 +2616,12 @@ int lastChar = getLastCharacterIndexForElement(aci,element); - CharacterInformation firstInfo = getCharacterInformation - (list, firstChar,charnum,aci); - CharacterInformation lastInfo = getCharacterInformation - (list, firstChar,charnum+nchars-1,aci); + CharacterInformation firstInfo, lastInfo; + firstInfo = getCharacterInformation(list, firstChar,charnum,aci); + lastInfo = getCharacterInformation(list, firstChar,charnum+nchars-1,aci); - Mark firstMark = textNode.getMarkerForChar(firstInfo.characterIndex,true); - Mark lastMark; + Mark firstMark, lastMark; + firstMark = textNode.getMarkerForChar(firstInfo.characterIndex,true); if ( lastInfo != null && lastInfo.characterIndex <= lastChar ){ lastMark = textNode.getMarkerForChar(lastInfo.characterIndex,false); @@ -2811,142 +2744,13 @@ * character */ protected CharacterInformation getCharacterInformation - (List list,int startIndex, int charnum, AttributedCharacterIterator aci) + (List list,int startIndex, int charnum, + AttributedCharacterIterator aci) { - int visible = 0; - int k = 0; - StrokingTextPainter.TextRun run = null; - - for( k = startIndex ; (visible < (charnum+1)) ; k++ ){ - if (k > aci.getEndIndex()) return null; - for( int l = 0 ; l < list.size() && (visible < (charnum+1)) ; l++){ - run = (StrokingTextPainter.TextRun)list.get(l); - - TextSpanLayout layout = run.getLayout(); - - if ( layout.hasCharacterIndex(k) ) { - if ( layout.isOnATextPath() ){ - - GVTGlyphVector vector = layout.getGlyphVector(); - - //alt glyph ? - if ( layout.isAltGlyph() ){ - //get the number of glyph visible here - int glyphs = vector.getNumGlyphs(); - int visibleGlyphs = 0; - for( int h=0 ; h < glyphs ; h++ ){ - if ( vector.isGlyphVisible(h)){ - visibleGlyphs++; - } - } - //get the number of character associated - //to this run - int charactersInRun = 1; - while ( layout.hasCharacterIndex( k+1 )){ - charactersInRun++; - k++; - } - visible += (charactersInRun*visibleGlyphs/glyphs); - - if ( visible > charnum +1 ){ - visible = charnum +1; - } - - } - else{ - int lastGlyphIndexFound = -1; - do{ - int glyphIndex = layout.getGlyphIndex(k); - if( glyphIndex == -1 ){ - //probable missing glyph - if ( layout.isLeftToRight() ){ - glyphIndex = 1 + lastGlyphIndexFound; - } - else{ - glyphIndex = ( lastGlyphIndexFound == -1) - ? vector.getNumGlyphs()-1 - : lastGlyphIndexFound -1; - } - } - lastGlyphIndexFound = glyphIndex; - if ( vector.isGlyphVisible( glyphIndex ) ){ - visible++; - } - k++; - }while ((visible < (charnum+1)) && layout.hasCharacterIndex(k) ); - //got one too far - k--; - } - } - else{ - visible++; - while ( (visible < (charnum+1)) && layout.hasCharacterIndex(k+1) ){ - k++; - visible++; - } - } - } - } - } - - if ( visible != charnum+1 ){ - return null; - } - CharacterInformation info = new CharacterInformation(); - info.characterIndex = k-1; - info.layout = run.getLayout(); - - //check is it is a altGlyph - if ( info.layout.isAltGlyph() ){ - - //first visible glyph, last visible glyph - info.glyphIndexStart = 0; - info.glyphIndexEnd = info.layout.getGlyphCount()-1; - boolean visibleGlyph = false; - GVTGlyphVector vector = info.layout.getGlyphVector(); - for( int j = 0 ; j < vector.getNumGlyphs() ; j++ ){ - if ( !visibleGlyph && vector.isGlyphVisible(j) ){ - info.glyphIndexStart = j; - visibleGlyph = true; - } - if ( visibleGlyph && (!vector.isGlyphVisible(j)) ){ - info.glyphIndexEnd = j-1; - break; - } - } + info.characterIndex = startIndex+charnum; - } - else{ - - info.glyphIndexStart = info.layout.getGlyphIndex - (info.characterIndex); - - //special case when the missing glyph does not have a unicode - //associated to it, it will return -1 - if ( info.glyphIndexStart == -1 ){ - if ( info.layout.isLeftToRight() ){ - info.glyphIndexStart = info.layout.getGlyphIndex( info.characterIndex-1 )+1; - } - else{ - info.glyphIndexStart = info.layout.getGlyphIndex( info.characterIndex+1 ) -1; - if ( info.glyphIndexStart == -2 ){ - info.glyphIndexStart = info.layout.getGlyphCount()-1; - } - } - } - info.glyphIndexEnd = info.glyphIndexStart; - - } - - return info; - /* - CharacterInformation info = new CharacterInformation(); - - info.characterIndex = characterIndex; - boolean found = false; - - for (int i = 0 ; i < list.size() && !found ; i++) { + for (int i = 0; i < list.size(); i++) { StrokingTextPainter.TextRun run = (StrokingTextPainter.TextRun)list.get(i); @@ -2956,14 +2760,11 @@ aci.setIndex(info.characterIndex); //check is it is a altGlyph - if ( aci.getAttribute(GVTAttributedCharacterIterator. - TextAttribute.ALT_GLYPH_HANDLER) != null ){ - + if (aci.getAttribute(GVTAttributedCharacterIterator. + TextAttribute.ALT_GLYPH_HANDLER) != null){ info.glyphIndexStart = 0; info.glyphIndexEnd = info.layout.getGlyphCount()-1; - } - else{ - + } else { info.glyphIndexStart = info.layout.getGlyphIndex (info.characterIndex); @@ -2977,16 +2778,10 @@ info.glyphIndexEnd = info.glyphIndexStart; } } - found = true; + return info; } } - if ( !found ){ - return( null ); - } - else{ - return( info ); - } - */ + return null; } /** @@ -3013,71 +2808,4 @@ return layout.getComputedOrientationAngle(characterIndex); } } - /* - protected int countCharacter(AttributedCharacterIterator aci, Element element){ - - int firstChar = getFirstCharacterIndexForElement(aci,element); - - if (firstChar == -1) - return 0; // Element not part of aci (no chars in elem usually) - - int lastChar = getLastCharacterIndexForElement(aci,element); - - if (!(( element instanceof SVGTextElement ) || - ( element instanceof SVGTextPathElement ))){ - //is tref,tspan,altGlyph,a - return ( lastChar - firstChar + 1 ); - } - else if ( element instanceof SVGTextPathElement ){ - - return getNumberOfVisibleCharacter(firstChar,lastChar); - } - else{ - //text element - int counted = 0; - int currentChar = firstChar; - - while ( currentChar > lastChar ){ - - aci.setIndex(currentChar); - - Element child = aci.get(GVTAttributedCharacterIterator. - TextAttribute.TEXT_COMPOUND_DELIMITER); - - if( child == element ){ - //character associated to the <text> element - //directly - int last = aci.runLimit(GVTAttributedCharacterIterator. - TextAttribute.TEXT_COMPOUND_DELIMITER); - - counted = last - currentChar+1; - currentChar = last+1; - } - else{ - //character associated to a child of text - int lastCharChild = getLastCharacterIndexForElement(aci,child); - - counted+= countCharacter(aci,child); - //go to the next child or back to - //the <text> element characters - currentChar = lastCharChild+1; - - } - } - } - } - - protected int getNumberOfVisibleCharacters(int first, int last){ - - //get the layouts - List list = getTextRuns(textNode); - - StrokingTextPainter.TextRun lastRunUsed = null; - for( int i = first ; i <= last ; i++ ){ - if ( lastRunUsed != null ){ - - } - } - } - */ } 1.5 +56 -16 xml-batik/sources/org/apache/batik/dom/svg/SVGTextContentSupport.java Index: SVGTextContentSupport.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/dom/svg/SVGTextContentSupport.java,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- SVGTextContentSupport.java 20 Aug 2003 11:31:45 -0000 1.4 +++ SVGTextContentSupport.java 31 Aug 2003 17:27:12 -0000 1.5 @@ -50,6 +50,9 @@ package org.apache.batik.dom.svg; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + import org.w3c.dom.DOMException; import org.w3c.dom.Element; import org.w3c.dom.svg.SVGMatrix; @@ -92,34 +95,42 @@ } final SVGTextContent context = (SVGTextContent)svgelt.getSVGContext(); - + Rectangle2D r2d = getExtent(svgelt, context, charnum); + return new SVGRect() { public float getX() { - return (float)context.getExtentOfChar(charnum).getX(); + return (float)SVGTextContentSupport.getExtent + (svgelt, context, charnum).getX(); } public void setX(float x) throws DOMException { throw svgelt.createDOMException (DOMException.NO_MODIFICATION_ALLOWED_ERR, "readonly.rect", null); } + public float getY() { - return (float)context.getExtentOfChar(charnum).getY(); + return (float)SVGTextContentSupport.getExtent + (svgelt, context, charnum).getY(); } public void setY(float y) throws DOMException { throw svgelt.createDOMException (DOMException.NO_MODIFICATION_ALLOWED_ERR, "readonly.rect", null); } + public float getWidth() { - return (float)context.getExtentOfChar(charnum).getWidth(); + return (float)SVGTextContentSupport.getExtent + (svgelt, context, charnum).getWidth(); } public void setWidth(float width) throws DOMException { throw svgelt.createDOMException (DOMException.NO_MODIFICATION_ALLOWED_ERR, "readonly.rect", null); } + public float getHeight() { - return (float)context.getExtentOfChar(charnum).getHeight(); + return (float)SVGTextContentSupport.getExtent + (svgelt, context, charnum).getHeight(); } public void setHeight(float height) throws DOMException { throw svgelt.createDOMException @@ -127,14 +138,22 @@ "readonly.rect", null); } }; + } - } - + protected static Rectangle2D getExtent + (SVGOMElement svgelt, SVGTextContent context, int charnum) { + Rectangle2D r2d = context.getExtentOfChar(charnum); + if (r2d == null) throw svgelt.createDOMException + (DOMException.INDEX_SIZE_ERR, "",null); + return r2d; + } + /** * To implement [EMAIL PROTECTED] * org.w3c.dom.svg.SVGTextContentElement#getStartPositionOfChar(int charnum)}. */ - public static SVGPoint getStartPositionOfChar(Element elt,final int charnum) throws DOMException { + public static SVGPoint getStartPositionOfChar + (Element elt, final int charnum) throws DOMException { final SVGOMElement svgelt = (SVGOMElement)elt; @@ -146,23 +165,34 @@ } final SVGTextContent context = (SVGTextContent)svgelt.getSVGContext(); + Point2D p2d = getStartPos(svgelt, context, charnum); return new SVGTextPoint(svgelt){ public float getX(){ - return (float)context.getStartPositionOfChar(charnum).getX(); + return (float)SVGTextContentSupport.getStartPos + (this.svgelt, context, charnum).getX(); } public float getY(){ - return (float)context.getStartPositionOfChar(charnum).getY(); + return (float)SVGTextContentSupport.getStartPos + (this.svgelt, context, charnum).getY(); } }; - } + protected static Point2D getStartPos + (SVGOMElement svgelt, SVGTextContent context, int charnum) { + Point2D p2d = context.getStartPositionOfChar(charnum); + if (p2d == null) throw svgelt.createDOMException + (DOMException.INDEX_SIZE_ERR, "",null); + return p2d; + } + /** * To implement [EMAIL PROTECTED] * org.w3c.dom.svg.SVGTextContentElement#getEndPositionOfChar(int charnum)}. */ - public static SVGPoint getEndPositionOfChar(Element elt,final int charnum) throws DOMException { + public static SVGPoint getEndPositionOfChar + (Element elt,final int charnum) throws DOMException { final SVGOMElement svgelt = (SVGOMElement)elt; @@ -174,16 +204,26 @@ } final SVGTextContent context = (SVGTextContent)svgelt.getSVGContext(); + Point2D p2d = getEndPos(svgelt, context, charnum); return new SVGTextPoint(svgelt){ public float getX(){ - return (float)context.getEndPositionOfChar(charnum).getX(); + return (float)SVGTextContentSupport.getEndPos + (this.svgelt, context, charnum).getX(); } public float getY(){ - return (float)context.getEndPositionOfChar(charnum).getY(); + return (float)SVGTextContentSupport.getEndPos + (this.svgelt, context, charnum).getY(); } }; + } + protected static Point2D getEndPos + (SVGOMElement svgelt, SVGTextContent context, int charnum) { + Point2D p2d = context.getEndPositionOfChar(charnum); + if (p2d == null) throw svgelt.createDOMException + (DOMException.INDEX_SIZE_ERR, "",null); + return p2d; } /** @@ -203,7 +243,7 @@ final SVGTextContent context = (SVGTextContent)svgelt.getSVGContext(); - context.selectSubString(charnum,nchars); + context.selectSubString(charnum, nchars); } /** 1.41 +11 -6 xml-batik/sources/org/apache/batik/swing/gvt/JGVTComponent.java Index: JGVTComponent.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/swing/gvt/JGVTComponent.java,v retrieving revision 1.40 retrieving revision 1.41 diff -u -r1.40 -r1.41 --- JGVTComponent.java 14 Aug 2003 00:53:51 -0000 1.40 +++ JGVTComponent.java 31 Aug 2003 17:27:12 -0000 1.41 @@ -469,12 +469,17 @@ return progressivePaint; } + public Rectangle getRenderRect() { + Dimension d = getSize(); + return new Rectangle(0, 0, d.width, d.height); + } + /** * Repaints immediately the component. */ public void immediateRepaint() { if (EventQueue.isDispatchThread()) { - Rectangle visRect = getVisibleRect(); + Rectangle visRect = getRenderRect(); if (doubleBufferedRendering) repaint(visRect.x, visRect.y, visRect.width, visRect.height); @@ -485,7 +490,7 @@ try { EventQueue.invokeAndWait(new Runnable() { public void run() { - Rectangle visRect = getVisibleRect(); + Rectangle visRect = getRenderRect(); if (doubleBufferedRendering) repaint(visRect.x, visRect.y, visRect.width, visRect.height); @@ -507,7 +512,7 @@ Graphics2D g2d = (Graphics2D)g; - Rectangle visRect = getVisibleRect(); + Rectangle visRect = getRenderRect(); g2d.setComposite(AlphaComposite.SrcOver); g2d.setPaint(getBackground()); g2d.fillRect(visRect.x, visRect.y, @@ -650,7 +655,7 @@ * Renders the GVT tree. */ protected void renderGVTTree() { - Rectangle visRect = getVisibleRect(); + Rectangle visRect = getRenderRect(); if (gvtRoot == null || visRect.width <= 0 || visRect.height <= 0) { return; } @@ -804,7 +809,7 @@ public void run() { if (progressivePaintThread == thisThread) { - Rectangle vRect = getVisibleRect(); + Rectangle vRect = getRenderRect(); repaint(vRect.x, vRect.y, vRect.width, vRect.height); } 1.83 +4 -4 xml-batik/sources/org/apache/batik/swing/svg/JSVGComponent.java Index: JSVGComponent.java =================================================================== RCS file: /home/cvs/xml-batik/sources/org/apache/batik/swing/svg/JSVGComponent.java,v retrieving revision 1.82 retrieving revision 1.83 diff -u -r1.82 -r1.83 --- JSVGComponent.java 22 Aug 2003 10:49:06 -0000 1.82 +++ JSVGComponent.java 31 Aug 2003 17:27:12 -0000 1.83 @@ -715,7 +715,7 @@ disableInteractions = true; initialTransform = new AffineTransform(); setRenderingTransform(initialTransform, false); - Rectangle vRect = getVisibleRect(); + Rectangle vRect = getRenderRect(); repaint(vRect.x, vRect.y, vRect.width, vRect.height); return; @@ -996,7 +996,7 @@ return; } - final Rectangle visRect = getVisibleRect(); + final Rectangle visRect = getRenderRect(); if ((gvtRoot == null) || (visRect.width <= 0) || (visRect.height <= 0)) { @@ -1718,7 +1718,7 @@ List l = e.getDirtyAreas(); if (l != null) { - Rectangle visRect = getVisibleRect(); + Rectangle visRect = getRenderRect(); List ml = mergeRectangles (l, visRect.x, visRect.y, visRect.width - 1, visRect.height - 1); 1.1 xml-batik/test-references/samples/tests/spec/scripting/text_content.png <<Binary file>> 1.112 +2 -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.111 retrieving revision 1.112 diff -u -r1.111 -r1.112 --- samplesRendering.xml 14 Aug 2003 00:53:52 -0000 1.111 +++ samplesRendering.xml 31 Aug 2003 17:27:13 -0000 1.112 @@ -414,5 +414,6 @@ <test id="samples/tests/spec/scripting/rectResizeOnClick.svg" /> <test id="samples/tests/spec/scripting/setProperty.svg" /> <test id="samples/tests/spec/scripting/styling.svg" /> + <test id="samples/tests/spec/scripting/text_content.svg" /> </testGroup> </testSuite>
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]