Changeset 6002 in josm for trunk/src/com/kitfox/svg/Text.java
- Timestamp:
- 2013-06-11T01:01:28+02:00 (13 years ago)
- File:
-
- 1 edited
-
trunk/src/com/kitfox/svg/Text.java (modified) (28 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/com/kitfox/svg/Text.java
r4256 r6002 1 1 /* 2 * Stop.java 2 * SVG Salamander 3 * Copyright (c) 2004, Mark McKay 4 * All rights reserved. 3 5 * 6 * Redistribution and use in source and binary forms, with or 7 * without modification, are permitted provided that the following 8 * conditions are met: 4 9 * 5 * The Salamander Project - 2D and 3D graphics libraries in Java 6 * Copyright (C) 2004 Mark McKay 10 * - Redistributions of source code must retain the above 11 * copyright notice, this list of conditions and the following 12 * disclaimer. 13 * - Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials 16 * provided with the distribution. 7 17 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 21 * 22 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other 23 * projects can be found at http://www.kitfox.com 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 22 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 23 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 27 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 29 * OF THE POSSIBILITY OF SUCH DAMAGE. 30 * 31 * Mark McKay can be contacted at mark@kitfox.com. Salamander and other 32 * projects can be found at http://www.kitfox.com 24 33 * 25 34 * Created on January 26, 2004, 1:56 AM 26 35 */ 27 28 36 package com.kitfox.svg; 29 37 30 38 import com.kitfox.svg.xml.StyleAttribute; 31 import java.awt.*; 32 import java.awt.font.*; 33 import java.awt.geom.*; 34 import java.util.*; 35 import java.util.regex.*; 39 import java.awt.Graphics2D; 40 import java.awt.Shape; 41 import java.awt.font.FontRenderContext; 42 import java.awt.geom.AffineTransform; 43 import java.awt.geom.GeneralPath; 44 import java.awt.geom.Rectangle2D; 45 import java.util.Iterator; 46 import java.util.LinkedList; 47 import java.util.regex.Matcher; 48 import java.util.regex.Pattern; 36 49 37 50 //import org.apache.batik.ext.awt.geom.ExtendedGeneralPath; 38 39 51 /** 40 52 * @author Mark McKay … … 43 55 public class Text extends ShapeElement 44 56 { 57 public static final String TAG_NAME = "text"; 45 58 46 59 float x = 0; 47 60 float y = 0; 48 61 AffineTransform transform = null; 49 50 62 String fontFamily; 51 63 float fontSize; 52 53 64 //List of strings and tspans containing the content of this node 54 65 LinkedList content = new LinkedList(); 55 56 66 Shape textShape; 57 58 67 public static final int TXAN_START = 0; 59 68 public static final int TXAN_MIDDLE = 1; 60 69 public static final int TXAN_END = 2; 61 70 int textAnchor = TXAN_START; 62 63 71 public static final int TXST_NORMAL = 0; 64 72 public static final int TXST_ITALIC = 1; 65 73 public static final int TXST_OBLIQUE = 2; 66 74 int fontStyle; 67 68 75 public static final int TXWE_NORMAL = 0; 69 76 public static final int TXWE_BOLD = 1; … … 80 87 public static final int TXWE_900 = 12; 81 88 int fontWeight; 82 83 /** Creates a new instance of Stop */ 89 90 /** 91 * Creates a new instance of Stop 92 */ 84 93 public Text() 85 94 { 86 95 } 87 96 97 public String getTagName() 98 { 99 return TAG_NAME; 100 } 101 88 102 public void appendText(String text) 89 103 { 90 104 content.addLast(text); 91 105 } 92 106 93 107 public void appendTspan(Tspan tspan) throws SVGElementException 94 108 { 95 109 super.loaderAddChild(null, tspan); 96 110 content.addLast(tspan); 97 // tspan.setParent(this); 98 } 99 111 } 112 100 113 /** 101 114 * Discard cached information … … 105 118 build(); 106 119 } 107 120 108 121 public java.util.List getContent() 109 122 { 110 123 return content; 111 124 } 112 /* 113 public void loaderStartElement(SVGLoaderHelper helper, Attributes attrs, SVGElement parent) 114 { 115 //Load style string 116 super.loaderStartElement(helper, attrs, parent); 117 118 String x = attrs.getValue("x"); 119 String y = attrs.getValue("y"); 120 //String transform = attrs.getValue("transform"); 121 122 this.x = XMLParseUtil.parseFloat(x); 123 this.y = XMLParseUtil.parseFloat(y); 124 } 125 */ 125 126 126 /** 127 127 * Called after the start element but before the end element to indicate … … 131 131 { 132 132 super.loaderAddChild(helper, child); 133 133 134 134 content.addLast(child); 135 135 } 136 136 137 137 /** 138 138 * Called during load process to add text scanned within a tag … … 141 141 { 142 142 Matcher matchWs = Pattern.compile("\\s*").matcher(text); 143 if (!matchWs.matches()) content.addLast(text); 144 } 145 143 if (!matchWs.matches()) 144 { 145 content.addLast(text); 146 } 147 } 148 146 149 public void build() throws SVGException 147 150 { 148 151 super.build(); 149 152 150 153 StyleAttribute sty = new StyleAttribute(); 151 152 if (getPres(sty.setName("x"))) x = sty.getFloatValueWithUnits(); 153 154 if (getPres(sty.setName("y"))) y = sty.getFloatValueWithUnits(); 155 156 if (getStyle(sty.setName("font-family"))) fontFamily = sty.getStringValue(); 157 else fontFamily = "Sans Serif"; 158 159 if (getStyle(sty.setName("font-size"))) fontSize = sty.getFloatValueWithUnits(); 160 else fontSize = 12f; 161 154 155 if (getPres(sty.setName("x"))) 156 { 157 x = sty.getFloatValueWithUnits(); 158 } 159 160 if (getPres(sty.setName("y"))) 161 { 162 y = sty.getFloatValueWithUnits(); 163 } 164 165 if (getStyle(sty.setName("font-family"))) 166 { 167 fontFamily = sty.getStringValue(); 168 } else 169 { 170 fontFamily = "Sans Serif"; 171 } 172 173 if (getStyle(sty.setName("font-size"))) 174 { 175 fontSize = sty.getFloatValueWithUnits(); 176 } else 177 { 178 fontSize = 12f; 179 } 180 162 181 if (getStyle(sty.setName("font-style"))) 163 182 { … … 166 185 { 167 186 fontStyle = TXST_NORMAL; 168 } 169 else if ("italic".equals(s)) 187 } else if ("italic".equals(s)) 170 188 { 171 189 fontStyle = TXST_ITALIC; 172 } 173 else if ("oblique".equals(s)) 190 } else if ("oblique".equals(s)) 174 191 { 175 192 fontStyle = TXST_OBLIQUE; 176 193 } 177 } 178 else fontStyle = TXST_NORMAL; 179 194 } else 195 { 196 fontStyle = TXST_NORMAL; 197 } 198 180 199 if (getStyle(sty.setName("font-weight"))) 181 200 { … … 184 203 { 185 204 fontWeight = TXWE_NORMAL; 186 } 187 else if ("bold".equals(s)) 205 } else if ("bold".equals(s)) 188 206 { 189 207 fontWeight = TXWE_BOLD; 190 208 } 191 } 192 else fontWeight = TXWE_BOLD; 193 209 } else 210 { 211 fontWeight = TXWE_BOLD; 212 } 213 194 214 if (getStyle(sty.setName("text-anchor"))) 195 215 { 196 216 String s = sty.getStringValue(); 197 if (s.equals("middle")) textAnchor = TXAN_MIDDLE; 198 else if (s.equals("end")) textAnchor = TXAN_END; 199 else textAnchor = TXAN_START; 200 } 201 else textAnchor = TXAN_START; 202 217 if (s.equals("middle")) 218 { 219 textAnchor = TXAN_MIDDLE; 220 } else if (s.equals("end")) 221 { 222 textAnchor = TXAN_END; 223 } else 224 { 225 textAnchor = TXAN_START; 226 } 227 } else 228 { 229 textAnchor = TXAN_START; 230 } 231 203 232 //text anchor 204 233 //text-decoration 205 234 //text-rendering 206 235 207 236 buildFont(); 208 237 } 209 238 210 239 protected void buildFont() throws SVGException 211 240 { … … 232 261 break; 233 262 } 234 263 235 264 //Get font 236 265 Font font = diagram.getUniverse().getFont(fontFamily); … … 238 267 { 239 268 // System.err.println("Could not load font"); 240 241 java.awt.Font sysFont = new java.awt.Font(fontFamily, style | weight, (int)fontSize); 269 270 java.awt.Font sysFont = new java.awt.Font(fontFamily, style | weight, (int) fontSize); 242 271 buildSysFont(sysFont); 243 272 return; 244 273 } 245 274 246 275 // font = new java.awt.Font(font.getFamily(), style | weight, font.getSize()); 247 276 248 277 // Area textArea = new Area(); 249 278 GeneralPath textPath = new GeneralPath(); 250 279 textShape = textPath; 251 280 252 281 float cursorX = x, cursorY = y; 253 282 254 283 FontFace fontFace = font.getFontFace(); 255 284 //int unitsPerEm = fontFace.getUnitsPerEm(); 256 285 int ascent = fontFace.getAscent(); 257 float fontScale = fontSize / (float)ascent; 258 286 float fontScale = fontSize / (float) ascent; 287 259 288 // AffineTransform oldXform = g.getTransform(); 260 289 AffineTransform xform = new AffineTransform(); 261 290 262 291 for (Iterator it = content.iterator(); it.hasNext();) 263 292 { 264 293 Object obj = it.next(); 265 294 266 295 if (obj instanceof String) 267 296 { 268 String text = (String)obj; 269 297 String text = (String) obj; 298 if (text != null) 299 { 300 text = text.trim(); 301 } 302 270 303 strokeWidthScalar = 1f / fontScale; 271 304 272 305 for (int i = 0; i < text.length(); i++) 273 306 { … … 276 309 xform.scale(fontScale, fontScale); 277 310 // g.transform(xform); 278 311 279 312 String unicode = text.substring(i, i + 1); 280 313 MissingGlyph glyph = font.getGlyph(unicode); 281 314 282 315 Shape path = glyph.getPath(); 283 316 if (path != null) … … 287 320 } 288 321 // else glyph.render(g); 289 322 290 323 cursorX += fontScale * glyph.getHorizAdvX(); 291 324 292 325 // g.setTransform(oldXform); 293 326 } 294 327 295 328 strokeWidthScalar = 1f; 296 } 297 else if (obj instanceof Tspan) 298 { 299 Tspan tspan = (Tspan)obj; 300 329 } else if (obj instanceof Tspan) 330 { 331 Tspan tspan = (Tspan) obj; 332 301 333 xform.setToIdentity(); 302 334 xform.setToTranslation(cursorX, cursorY); … … 304 336 // tspan.setCursorX(cursorX); 305 337 // tspan.setCursorY(cursorY); 306 338 307 339 Shape tspanShape = tspan.getShape(); 308 340 tspanShape = xform.createTransformedShape(tspanShape); … … 312 344 // cursorY = tspan.getCursorY(); 313 345 } 314 315 } 316 346 347 } 348 317 349 switch (textAnchor) 318 350 { … … 333 365 } 334 366 } 335 367 336 368 private void buildSysFont(java.awt.Font font) throws SVGException 337 369 { 338 370 GeneralPath textPath = new GeneralPath(); 339 371 textShape = textPath; 340 372 341 373 float cursorX = x, cursorY = y; 342 374 343 375 // FontMetrics fm = g.getFontMetrics(font); 344 376 FontRenderContext frc = new FontRenderContext(null, true, true); 345 377 346 378 // FontFace fontFace = font.getFontFace(); 347 379 //int unitsPerEm = fontFace.getUnitsPerEm(); 348 380 // int ascent = fm.getAscent(); 349 381 // float fontScale = fontSize / (float)ascent; 350 382 351 383 // AffineTransform oldXform = g.getTransform(); 352 384 AffineTransform xform = new AffineTransform(); 353 385 354 386 for (Iterator it = content.iterator(); it.hasNext();) 355 387 { 356 388 Object obj = it.next(); 357 389 358 390 if (obj instanceof String) 359 391 { 360 String text = (String)obj; 361 392 String text = (String) obj; 393 362 394 Shape textShape = font.createGlyphVector(frc, text).getOutline(cursorX, cursorY); 363 395 textPath.append(textShape, false); 364 396 // renderShape(g, textShape); 365 397 // g.drawString(text, cursorX, cursorY); 366 398 367 399 Rectangle2D rect = font.getStringBounds(text, frc); 368 cursorX += (float)rect.getWidth(); 369 } 370 else if (obj instanceof Tspan) 400 cursorX += (float) rect.getWidth(); 401 } else if (obj instanceof Tspan) 371 402 { 372 403 /* 373 Tspan tspan = (Tspan)obj; 404 Tspan tspan = (Tspan)obj; 374 405 375 xform.setToIdentity(); 376 xform.setToTranslation(cursorX, cursorY); 406 xform.setToIdentity(); 407 xform.setToTranslation(cursorX, cursorY); 377 408 378 Shape tspanShape = tspan.getShape(); 379 tspanShape = xform.createTransformedShape(tspanShape); 380 textArea.add(new Area(tspanShape)); 409 Shape tspanShape = tspan.getShape(); 410 tspanShape = xform.createTransformedShape(tspanShape); 411 textArea.add(new Area(tspanShape)); 381 412 382 cursorX += tspanShape.getBounds2D().getWidth(); 413 cursorX += tspanShape.getBounds2D().getWidth(); 383 414 */ 384 385 386 Tspan tspan = (Tspan)obj; 415 416 417 Tspan tspan = (Tspan) obj; 387 418 tspan.setCursorX(cursorX); 388 419 tspan.setCursorY(cursorY); … … 390 421 cursorX = tspan.getCursorX(); 391 422 cursorY = tspan.getCursorY(); 392 393 } 394 } 395 423 424 } 425 } 426 396 427 switch (textAnchor) 397 428 { … … 412 443 } 413 444 } 414 415 445 416 446 public void render(Graphics2D g) throws SVGException 417 447 { … … 420 450 finishLayer(g); 421 451 } 422 452 423 453 public Shape getShape() 424 454 { 425 455 return shapeToParent(textShape); 426 456 } 427 457 428 458 public Rectangle2D getBoundingBox() throws SVGException 429 459 { 430 460 return boundsToParent(includeStrokeInBounds(textShape.getBounds2D())); 431 461 } 432 462 433 463 /** 434 * Updates all attributes in this diagram associated with a time event. 435 * Ie, all attributes with track information. 464 * Updates all attributes in this diagram associated with a time event. Ie, 465 * all attributes with track information. 466 * 436 467 * @return - true if this node has changed state as a result of the time 437 468 * update … … 441 472 // if (trackManager.getNumTracks() == 0) return false; 442 473 boolean changeState = super.updateTime(curTime); 443 474 444 475 //Get current values for parameters 445 476 StyleAttribute sty = new StyleAttribute(); 446 477 boolean shapeChange = false; 447 478 448 479 if (getPres(sty.setName("x"))) 449 480 { … … 455 486 } 456 487 } 457 488 458 489 if (getPres(sty.setName("y"))) 459 490 { … … 465 496 } 466 497 } 467 498 468 499 if (getPres(sty.setName("font-family"))) 469 500 { … … 475 506 } 476 507 } 477 508 478 509 if (getPres(sty.setName("font-size"))) 479 510 { … … 485 516 } 486 517 } 487 488 518 519 489 520 if (getStyle(sty.setName("font-style"))) 490 521 { … … 494 525 { 495 526 newVal = TXST_NORMAL; 496 } 497 else if ("italic".equals(s)) 527 } else if ("italic".equals(s)) 498 528 { 499 529 newVal = TXST_ITALIC; 500 } 501 else if ("oblique".equals(s)) 530 } else if ("oblique".equals(s)) 502 531 { 503 532 newVal = TXST_OBLIQUE; … … 509 538 } 510 539 } 511 540 512 541 if (getStyle(sty.setName("font-weight"))) 513 542 { … … 517 546 { 518 547 newVal = TXWE_NORMAL; 519 } 520 else if ("bold".equals(s)) 548 } else if ("bold".equals(s)) 521 549 { 522 550 newVal = TXWE_BOLD; … … 528 556 } 529 557 } 530 558 531 559 if (shapeChange) 532 560 { … … 535 563 // return true; 536 564 } 537 565 538 566 return changeState || shapeChange; 539 567 }
Note:
See TracChangeset
for help on using the changeset viewer.
