1 51 package org.apache.fop.render.svg; 52 53 import org.apache.fop.layout.*; 54 import org.apache.fop.layout.inline.*; 55 import org.apache.fop.datatypes.IDReferences; 56 import org.apache.fop.datatypes.ColorType; 57 import org.apache.fop.image.*; 58 import org.apache.fop.svg.SVGArea; 59 import org.apache.fop.svg.SVGUtilities; 60 import org.apache.fop.apps.FOPException; 61 62 import org.w3c.dom.Node ; 63 import org.w3c.dom.ProcessingInstruction ; 64 import org.w3c.dom.svg.SVGSVGElement; 65 import org.w3c.dom.svg.SVGDocument; 66 import org.w3c.dom.Document ; 67 import org.w3c.dom.Element ; 68 import org.w3c.dom.DOMImplementation ; 69 70 import org.apache.batik.dom.svg.SVGDOMImplementation; 71 import org.apache.batik.dom.util.XMLSupport; 72 import org.apache.batik.transcoder.svg2svg.SVGTranscoder; 73 import org.apache.batik.transcoder.TranscoderInput; 74 import org.apache.batik.transcoder.TranscoderOutput; 75 import org.apache.batik.transcoder.TranscoderException; 76 77 import java.awt.Color ; 78 import java.awt.Image ; 79 import java.awt.image.BufferedImage ; 80 import java.awt.geom.Rectangle2D ; 81 import java.util.Map ; 82 import java.net.URL ; 83 import java.net.MalformedURLException ; 84 import java.io.OutputStream ; 85 import java.io.IOException ; 86 import java.io.OutputStreamWriter ; 87 import javax.swing.ImageIcon ; 88 89 import org.apache.fop.render.AbstractRenderer; 90 91 public class SVGRenderer extends AbstractRenderer { 92 static final String svgNS = SVGDOMImplementation.SVG_NAMESPACE_URI; 93 Document svgDocument; 94 Element svgRoot; 95 Element currentPageG = null; 96 Element lastLink = null; 97 98 float totalWidth = 0; 99 float totalHeight = 0; 100 101 protected int pageWidth = 0; 102 protected int pageHeight = 0; 103 protected int pageNumber = 0; 104 105 protected Map fontNames = new java.util.HashMap (); 106 protected Map fontStyles = new java.util.HashMap (); 107 protected Color saveColor = null; 108 109 112 protected String currentFontName; 113 114 117 protected int currentFontSize; 118 119 122 protected float currentRed = 0; 123 protected float currentGreen = 0; 124 protected float currentBlue = 0; 125 126 129 protected java.util.Map options; 130 131 134 public void setOptions(java.util.Map options) { 135 this.options = options; 136 } 137 138 public SVGRenderer() { 139 } 140 141 153 protected void addLine(int x1, int y1, int x2, int y2, int th, float r, 154 float g, float b) { 155 Element line = SVGUtilities.createLine(svgDocument, x1 / 1000f, pageHeight - (y1 / 1000f), x2 / 1000f, pageHeight - (y2 / 1000f)); 156 line.setAttributeNS(null, "style", "stroke-width:" + (Math.abs(th) / 1000f) 157 + ";stroke:rgb(" + ((int)(255 * r)) + "," + ((int)(255 * g)) + "," + ((int)(255 * b)) + ")"); 158 currentPageG.appendChild(line); 159 } 160 161 172 protected void addRect(int x, int y, int w, int h, float r, float g, 173 float b) { 174 Element rect = SVGUtilities.createRect(svgDocument, x / 1000f, pageHeight - (y / 1000f), w / 1000f, h / 1000f); 175 rect.setAttributeNS(null, "style", "stroke:rgb(" + ((int)(255 * r)) + "," + ((int)(255 * g)) + "," + ((int)(255 * b)) + ")"); 176 currentPageG.appendChild(rect); 177 } 178 179 193 protected void addRect(int x, int y, int w, int h, float r, float g, 194 float b, float fr, float fg, float fb) { 195 Element rect = SVGUtilities.createRect(svgDocument, x / 1000f, pageHeight - (y / 1000f), w / 1000f, h / 1000f); 196 rect.setAttributeNS(null, "style", "stroke:rgb(" + ((int)(255 * r)) + "," + ((int)(255 * g)) + "," + ((int)(255 * b)) + ");fill:rgb(" + ((int)(255 * fr)) + "," + ((int)(255 * fg)) + "," + ((int)(255 * fb)) + ")"); 197 currentPageG.appendChild(rect); 198 } 199 200 209 protected void addRect(int x, int y, int w, int h, 210 boolean drawAsOutline) { 211 int startx = (x + 500) / 1000; 212 int starty = pageHeight - ((y + 500) / 1000); 213 int endx = (x + w + 500) / 1000; 214 int endy = pageHeight - ((y + h + 500) / 1000); 215 if (drawAsOutline) { 216 Element rect = SVGUtilities.createRect(svgDocument, startx, starty, endx - startx, endy - starty); 217 rect.setAttributeNS(null, "style", "fill:none"); 218 currentPageG.appendChild(rect); 219 } else { 220 Element rect = SVGUtilities.createRect(svgDocument, startx, starty, endx - startx, starty - endy); 221 rect.setAttributeNS(null, "style", "stroke:none"); 222 currentPageG.appendChild(rect); 223 } 224 } 225 226 protected void addFilledRect(int x, int y, int w, int h, 227 ColorType col) { 228 float r = col.red(); 229 float g = col.green(); 230 float b = col.blue(); 231 addRect(x, y, w, h, r, g, b, r, g, b); 232 } 233 234 protected void drawFrame() { 235 int width = pageWidth; 236 int height = pageHeight; 237 Element rect = SVGUtilities.createRect(svgDocument, 0, 0, width, height); 238 rect.setAttributeNS(null, "style", "fill:none;stroke:black"); 239 currentPageG.appendChild(rect); 240 } 241 242 public void render(Page page, OutputStream stream) 243 throws IOException { 244 pageNumber++; 245 this.render(page); 246 } 247 248 public void render(Page page) 249 throws IOException { 250 idReferences = page.getIDReferences(); 251 252 int lastWidth = pageWidth; 253 int lastHeight = pageHeight; 254 255 pageWidth = (int)((float)page.getWidth() / 1000f + .5); 256 pageHeight = (int)((float)page.getHeight() / 1000f + .5); 257 258 if(lastLink != null && currentPageG != null) { 259 lastLink.setAttributeNS(null, "xlink:href", "#svgView(viewBox(0, "+ (totalHeight) + ", " + pageWidth + ", " + pageHeight + "))"); 260 currentPageG.appendChild(lastLink); 261 } 262 263 totalHeight += pageHeight; 264 if(totalWidth < pageWidth) { 265 totalWidth = pageWidth; 266 } 267 268 currentPageG = SVGUtilities.createG(svgDocument); 269 currentPageG.setAttributeNS(null, "id", "Page-" + pageNumber); 270 currentPageG.setAttributeNS(null, "style", "font-family:sanserif;font-size:12"); 271 svgRoot.appendChild(currentPageG); 272 273 drawFrame(); 274 275 renderPage(page); 276 277 currentPageG.setAttributeNS(null, "transform", "translate(0," + (totalHeight - pageHeight) + ")"); 278 279 Element lastPageLink = svgDocument.createElementNS(svgNS, "a"); 280 if(lastLink != null) { 281 lastPageLink.setAttributeNS(null, "xlink:href", "#svgView(viewBox(0, " + (totalHeight - pageHeight - lastHeight) + ", " + lastWidth + ", " + lastHeight + "))"); 282 } else { 283 lastPageLink.setAttributeNS(null, "xlink:href", "#svgView(viewBox(0, " + (totalHeight - pageHeight) + ", " + pageWidth + ", " + pageHeight + "))"); 284 } 285 currentPageG.appendChild(lastPageLink); 286 Element rect = SVGUtilities.createRect(svgDocument, 0, 0, pageWidth / 2, pageHeight); 287 rect.setAttributeNS(null, "style", "fill:blue;visibility:hidden"); 288 lastPageLink.appendChild(rect); 289 290 lastLink = svgDocument.createElementNS(svgNS, "a"); 291 rect = SVGUtilities.createRect(svgDocument, pageWidth / 2, 0, pageWidth / 2, pageHeight); 292 rect.setAttributeNS(null, "style", "fill:blue;visibility:hidden"); 293 lastLink.appendChild(rect); 294 295 300 301 } 302 303 public void renderPage(Page page) { 304 305 this.currentFontName = ""; 306 this.currentFontSize = 0; 307 308 renderRegions(page); 309 } 310 311 protected void doFrame(org.apache.fop.layout.Area area) { 312 int w, h; 313 int rx = this.currentAreaContainerXPosition; 314 w = area.getContentWidth(); 315 316 if (area instanceof BlockArea) { 317 rx += ((BlockArea)area).getStartIndent(); 318 } 319 320 h = area.getContentHeight(); 321 int ry = this.currentYPosition; 322 323 rx = rx - area.getPaddingLeft(); 324 ry = ry + area.getPaddingTop(); 325 w = w + area.getPaddingLeft() + area.getPaddingRight(); 326 h = h + area.getPaddingTop() + area.getPaddingBottom(); 327 328 doBackground(area, rx, ry, w, h); 329 330 rx = rx - area.getBorderLeftWidth(); 331 ry = ry + area.getBorderTopWidth(); 332 w = w + area.getBorderLeftWidth() + area.getBorderRightWidth(); 333 h = h + area.getBorderTopWidth() + area.getBorderBottomWidth(); 334 335 BorderAndPadding bp = area.getBorderAndPadding(); 336 ColorType borderColor; 337 338 if (area.getBorderTopWidth() != 0) { 339 borderColor = bp.getBorderColor(BorderAndPadding.TOP); 340 addLine(rx, ry, rx + w, ry, area.getBorderTopWidth(), 341 borderColor.red(), borderColor.green(), 342 borderColor.blue()); 343 } 344 345 if (area.getBorderLeftWidth() != 0) { 346 borderColor = bp.getBorderColor(BorderAndPadding.LEFT); 347 addLine(rx, ry, rx, ry - h, area.getBorderLeftWidth(), 348 borderColor.red(), borderColor.green(), 349 borderColor.blue()); 350 } 351 352 if (area.getBorderRightWidth() != 0) { 353 borderColor = bp.getBorderColor(BorderAndPadding.RIGHT); 354 addLine(rx + w, ry, rx + w, ry - h, 355 area.getBorderRightWidth(), borderColor.red(), 356 borderColor.green(), 357 borderColor.blue()); 358 } 359 360 if (area.getBorderBottomWidth() != 0) { 361 borderColor = bp.getBorderColor(BorderAndPadding.BOTTOM); 362 addLine(rx, ry - h, rx + w, ry - h, area.getBorderBottomWidth(), 363 borderColor.red(), borderColor.green(), 364 borderColor.blue()); 365 } 366 } 367 368 protected Rectangle2D getBounds(org.apache.fop.layout.Area a) { 369 return new Rectangle2D.Double (currentAreaContainerXPosition, 370 currentYPosition, 371 a.getAllocationWidth(), a.getHeight()); 372 } 373 374 public void setupFontInfo(FontInfo fontInfo) throws FOPException { 375 BufferedImage fontImage = 377 new BufferedImage (100, 100, BufferedImage.TYPE_INT_RGB); 378 org.apache.fop.render.awt.FontSetup.setup(fontInfo, fontImage.createGraphics()); 379 } 380 381 public void renderDisplaySpace(DisplaySpace space) { 382 int d = space.getSize(); 383 this.currentYPosition -= d; 384 } 385 386 399 protected void drawImageScaled(int x, int y, int w, int h, 400 FopImage image, 401 FontState fs) { 402 } 404 405 418 protected void drawImageClipped(int x, int y, 419 int clipX, int clipY, 420 int clipW, int clipH, 421 FopImage image, 422 FontState fs) { 423 } 425 426 public void renderImageArea(ImageArea area) { 427 428 int x = currentXPosition + area.getXOffset(); 429 int y = currentYPosition; 430 int w = area.getContentWidth(); 431 int h = area.getHeight(); 432 this.currentYPosition -= h; 433 434 FopImage img = area.getImage(); 435 436 if (img == null) { 437 log.error("Error while loading image : area.getImage() is null"); 438 439 addRect(x, y, w, h, true); 441 } else { 442 if (img instanceof SVGImage) { 443 try { 444 SVGDocument svg = ((SVGImage)img).getSVGDocument(); 445 renderSVGDocument(svg, x / 1000f, pageHeight - y / 1000f); 446 } catch (FopImageException e) {} 447 448 } else { 449 450 String urlString = img.getURL(); 451 try { 452 URL url = new URL (urlString); 453 454 ImageIcon icon = new ImageIcon (url); 455 Image image = icon.getImage(); 456 457 int startx = (x + 500) / 1000; 458 int starty = pageHeight - ((y + 500) / 1000); 459 int endx = (x + w + 500) / 1000; 460 int endy = pageHeight - ((y + h + 500) / 1000); 461 462 466 } catch (MalformedURLException mue) { 467 } 470 } 471 } 472 473 this.currentXPosition += area.getContentWidth(); 474 } 475 476 public void renderWordArea(WordArea area) { 477 char ch; 478 StringBuffer pdf = new StringBuffer (); 479 480 String name = area.getFontState().getFontFamily(); 481 int size = area.getFontState().getFontSize(); 482 boolean underlined = area.getUnderlined(); 483 484 float red = area.getRed(); 485 float green = area.getGreen(); 486 float blue = area.getBlue(); 487 488 if ((!name.equals(this.currentFontName)) 489 || (size != this.currentFontSize)) { 490 this.currentFontName = name; 491 this.currentFontSize = size; 492 } 493 494 if ((red != this.currentRed) || (green != this.currentGreen) 495 || (blue != this.currentBlue)) { 496 this.currentRed = red; 497 this.currentGreen = green; 498 this.currentBlue = blue; 499 } 500 501 int rx = this.currentXPosition; 502 int bl = this.currentYPosition; 503 504 String s = area.getText(); 505 506 if (saveColor != null) { 507 if (saveColor.getRed() != red || saveColor.getGreen() != green 508 || saveColor.getBlue() != blue) { 509 saveColor = new Color (red, green, blue); 510 } 511 } else { 512 saveColor = new Color (red, green, blue); 513 } 514 515 Element text = SVGUtilities.createText(svgDocument, rx / 1000f, pageHeight - bl / 1000f, s); 516 String st = null; 517 if(!"sans-serif".equals(this.currentFontName)) { 518 st = "font-family:" + this.currentFontName; 519 } 520 if(this.currentFontSize != 12000) { 521 if(st == null) { 522 st = ""; 523 } else { 524 st += ";"; 525 } 526 st += "font-size:" + (this.currentFontSize / 1000f); 527 } 528 if(red != 0 || green != 0 || blue != 0) { 529 if(st == null) { 530 st = ""; 531 } else { 532 st += ";"; 533 } 534 st += "fill:rgb(" + ((int)(255 * red)) + "," + ((int)(255 * green)) + "," + ((int)(255 * blue)) + ")"; 535 } 536 String fweight = area.getFontState().getFontWeight(); 537 if(!"normal".equals(fweight)) { 538 if(st == null) { 539 st = ""; 540 } else { 541 st += ";"; 542 } 543 st += "font-weight:" + fweight; 544 } 545 String fstyle = area.getFontState().getFontStyle(); 546 if(!"normal".equals(fstyle)) { 547 if(st == null) { 548 st = ""; 549 } else { 550 st += ";"; 551 } 552 st += "font-style:" + fstyle; 553 } 554 555 if(st != null) { 556 text.setAttributeNS(null, "style", st); 557 } 558 currentPageG.appendChild(text); 559 560 this.currentXPosition += area.getContentWidth(); 561 } 562 563 public void renderInlineSpace(InlineSpace space) { 564 this.currentXPosition += space.getSize(); 565 } 566 567 571 public void renderLeaderArea(LeaderArea area) { 572 573 int rx = this.currentXPosition; 574 int ry = this.currentYPosition; 575 int w = area.getLeaderLength(); 576 int h = area.getHeight(); 577 int th = area.getRuleThickness(); 578 int st = area.getRuleStyle(); float r = area.getRed(); 580 float g = area.getGreen(); 581 float b = area.getBlue(); 582 583 585 addRect(rx, ry, w, th, false); 586 587 this.currentXPosition += area.getContentWidth(); 588 } 589 590 public void renderSVGArea(SVGArea area) { 591 592 float x = this.currentXPosition / 1000f; 593 float y = pageHeight - this.currentYPosition / 1000f; 594 int w = area.getContentWidth(); 595 int h = area.getHeight(); 596 597 Document doc = area.getSVGDocument(); 598 renderSVGDocument(doc, x, y); 599 this.currentXPosition += area.getContentWidth(); 600 } 601 602 protected void renderSVGDocument(Document doc, float x, float y) { 603 SVGSVGElement svg = ((SVGDocument)doc).getRootElement(); 604 Element view = svgDocument.createElementNS(svgNS, "svg"); 605 Node newsvg = svgDocument.importNode(svg, true); 606 view.setAttributeNS(null, "x", "" + x); 608 view.setAttributeNS(null, "y", "" + y); 609 610 Element ele = (Element)newsvg; 612 ele.setAttributeNS(XMLSupport.XMLNS_NAMESPACE_URI, "xmlns", svgNS); 613 if(ele.hasAttributeNS(null, "xmlns")) { 614 ele.removeAttributeNS(null, "xmlns"); 615 } 616 617 view.appendChild(newsvg); 618 currentPageG.appendChild(view); 619 } 620 621 public void setProducer(String producer) { 622 } 624 625 public static Color colorType2Color(ColorType ct) { 626 if (ct == null) { 627 return null; 628 } 629 return new Color (ct.red(), ct.green(), ct.blue()); 630 } 631 632 public void renderForeignObjectArea(ForeignObjectArea area) { 633 area.getObject().render(this); 634 } 635 636 public void startRenderer(OutputStream outputStream) 637 throws IOException { 638 DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); 639 svgDocument = impl.createDocument(svgNS, "svg", null); 640 ProcessingInstruction pi = 641 svgDocument.createProcessingInstruction( 642 "xml", 643 " version=\"1.0\" encoding=\"ISO-8859-1\""); 644 svgRoot = svgDocument.getDocumentElement(); 645 svgDocument.insertBefore(pi, svgRoot); 646 } 647 648 public void stopRenderer(OutputStream outputStream) 649 throws IOException { 650 svgRoot.setAttributeNS(null, "width", "" + totalWidth); 651 svgRoot.setAttributeNS(null, "height", "" + totalHeight); 652 SVGTranscoder svgT = new SVGTranscoder(); 654 TranscoderInput input = new TranscoderInput(svgDocument); 655 TranscoderOutput output = new TranscoderOutput(new OutputStreamWriter (outputStream)); 656 try { 657 svgT.transcode(input, output); 658 } catch(TranscoderException e) { 659 log.error("could not write svg file :" + e.getMessage(), e); 660 } 661 outputStream.flush(); 662 663 svgDocument = null; 664 svgRoot = null; 665 currentPageG = null; 666 lastLink = null; 667 668 totalWidth = 0; 669 totalHeight = 0; 670 671 pageNumber = 0; 672 } 673 674 } 675 | Popular Tags |