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]

Reply via email to