1 17 18 19 20 package org.apache.fop.render.java2d; 21 22 import java.awt.BasicStroke ; 24 import java.awt.Color ; 25 import java.awt.Graphics ; 26 import java.awt.Graphics2D ; 27 import java.awt.RenderingHints ; 28 import java.awt.color.ColorSpace ; 29 import java.awt.font.GlyphVector ; 30 import java.awt.geom.AffineTransform ; 31 import java.awt.geom.GeneralPath ; 32 import java.awt.geom.Line2D ; 33 import java.awt.geom.Point2D ; 34 import java.awt.geom.Rectangle2D ; 35 import java.awt.image.BufferedImage ; 36 import java.awt.image.ColorModel ; 37 import java.awt.image.ComponentColorModel ; 38 import java.awt.image.DataBuffer ; 39 import java.awt.image.DataBufferByte ; 40 import java.awt.image.PixelInterleavedSampleModel ; 41 import java.awt.image.Raster ; 42 import java.awt.image.SampleModel ; 43 import java.awt.image.WritableRaster ; 44 import java.awt.print.PageFormat ; 45 import java.awt.print.Printable ; 46 import java.awt.print.PrinterException ; 47 import java.io.IOException ; 48 import java.io.OutputStream ; 49 import java.util.Iterator ; 50 import java.util.List ; 51 import java.util.Map ; 52 import java.util.Stack ; 53 54 import org.w3c.dom.Document ; 55 56 import org.apache.avalon.framework.configuration.Configuration; 57 import org.apache.avalon.framework.configuration.ConfigurationException; 58 import org.apache.fop.apps.FOPException; 59 import org.apache.fop.apps.FOUserAgent; 60 import org.apache.fop.area.CTM; 61 import org.apache.fop.area.PageViewport; 62 import org.apache.fop.area.Trait; 63 import org.apache.fop.area.inline.Image; 64 import org.apache.fop.area.inline.InlineArea; 65 import org.apache.fop.area.inline.Leader; 66 import org.apache.fop.area.inline.SpaceArea; 67 import org.apache.fop.area.inline.TextArea; 68 import org.apache.fop.area.inline.WordArea; 69 import org.apache.fop.fo.Constants; 70 import org.apache.fop.fonts.Font; 71 import org.apache.fop.fonts.FontInfo; 72 import org.apache.fop.fonts.Typeface; 73 import org.apache.fop.image.FopImage; 74 import org.apache.fop.image.ImageFactory; 75 import org.apache.fop.image.XMLImage; 76 import org.apache.fop.pdf.PDFAMode; 77 import org.apache.fop.render.AbstractPathOrientedRenderer; 78 import org.apache.fop.render.Graphics2DAdapter; 79 import org.apache.fop.render.RendererContext; 80 import org.apache.fop.render.pdf.CTMHelper; 81 import org.apache.fop.util.CharUtilities; 82 83 107 public abstract class Java2DRenderer extends AbstractPathOrientedRenderer implements Printable { 108 109 110 public static final String JAVA2D_TRANSPARENT_PAGE_BACKGROUND = "transparent-page-background"; 111 112 113 protected double scaleFactor = 1; 114 115 116 protected int pageWidth = 0; 117 118 119 protected int pageHeight = 0; 120 121 122 protected List pageViewportList = new java.util.ArrayList (); 123 124 125 private int currentPageNumber = 0; 126 127 128 private int numberOfPages; 129 130 131 protected boolean antialiasing = true; 132 133 134 protected boolean qualityRendering = true; 135 136 137 protected boolean transparentPageBackground = false; 138 139 140 protected Java2DGraphicsState state; 141 142 private Stack stateStack = new Stack (); 143 144 145 private boolean renderingDone; 146 147 private GeneralPath currentPath = null; 148 149 150 public Java2DRenderer() { 151 } 152 153 157 public void configure(Configuration cfg) throws ConfigurationException { 158 super.configure(cfg); 159 160 String s = cfg.getChild(JAVA2D_TRANSPARENT_PAGE_BACKGROUND, true).getValue(null); 161 if (s != null) { 162 this.transparentPageBackground = "true".equalsIgnoreCase(s); 163 } 164 } 165 166 169 public void setUserAgent(FOUserAgent foUserAgent) { 170 super.setUserAgent(foUserAgent); 171 userAgent.setRendererOverride(this); 173 String s = (String )userAgent.getRendererOptions().get(JAVA2D_TRANSPARENT_PAGE_BACKGROUND); 174 if (s != null) { 175 this.transparentPageBackground = "true".equalsIgnoreCase(s); 176 } 177 } 178 179 180 public FOUserAgent getUserAgent() { 181 return userAgent; 182 } 183 184 187 public void setupFontInfo(FontInfo inFontInfo) { 188 fontInfo = inFontInfo; 191 BufferedImage fontImage = new BufferedImage (100, 100, 192 BufferedImage.TYPE_INT_RGB); 193 Graphics2D g = fontImage.createGraphics(); 194 g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 196 RenderingHints.VALUE_FRACTIONALMETRICS_ON); 197 FontSetup.setup(fontInfo, g); 198 } 199 200 201 public Graphics2DAdapter getGraphics2DAdapter() { 202 return new Java2DGraphics2DAdapter(state); 203 } 204 205 209 public void setScaleFactor(double newScaleFactor) { 210 scaleFactor = newScaleFactor; 211 } 212 213 214 public double getScaleFactor() { 215 return scaleFactor; 216 } 217 218 219 public void startRenderer(OutputStream out) throws IOException { 220 } 222 223 224 public void stopRenderer() throws IOException { 225 log.debug("Java2DRenderer stopped"); 226 renderingDone = true; 227 numberOfPages = currentPageNumber; 228 if (numberOfPages == 0) { 230 new FOPException("No page could be rendered"); 231 } 232 } 233 234 235 public boolean isRenderingDone() { 236 return this.renderingDone; 237 } 238 239 242 public int getCurrentPageNumber() { 243 return currentPageNumber; 244 } 245 246 249 public void setCurrentPageNumber(int c) { 250 this.currentPageNumber = c; 251 } 252 253 256 public int getNumberOfPages() { 257 return numberOfPages; 258 } 259 260 264 public void clearViewportList() { 265 pageViewportList.clear(); 266 setCurrentPageNumber(0); 267 } 268 269 281 public void renderPage(PageViewport pageViewport) throws IOException { 282 pageViewportList.add(pageViewport.clone()); 284 currentPageNumber++; 285 } 286 287 294 public BufferedImage getPageImage(PageViewport pageViewport) { 295 296 this.currentPageViewport = pageViewport; 297 try { 298 Rectangle2D bounds = pageViewport.getViewArea(); 299 pageWidth = (int) Math.round(bounds.getWidth() / 1000f); 300 pageHeight = (int) Math.round(bounds.getHeight() / 1000f); 301 302 log.info( 303 "Rendering Page " + pageViewport.getPageNumberString() 304 + " (pageWidth " + pageWidth + ", pageHeight " 305 + pageHeight + ")"); 306 307 double scaleX = scaleFactor 308 * (25.4 / FOUserAgent.DEFAULT_TARGET_RESOLUTION) 309 / userAgent.getTargetPixelUnitToMillimeter(); 310 double scaleY = scaleFactor 311 * (25.4 / FOUserAgent.DEFAULT_TARGET_RESOLUTION) 312 / userAgent.getTargetPixelUnitToMillimeter(); 313 int bitmapWidth = (int) ((pageWidth * scaleX) + 0.5); 314 int bitmapHeight = (int) ((pageHeight * scaleY) + 0.5); 315 316 317 BufferedImage currentPageImage = getBufferedImage(bitmapWidth, bitmapHeight); 318 319 Graphics2D graphics = currentPageImage.createGraphics(); 320 graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, 321 RenderingHints.VALUE_FRACTIONALMETRICS_ON); 322 if (antialiasing) { 323 graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 324 RenderingHints.VALUE_ANTIALIAS_ON); 325 graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, 326 RenderingHints.VALUE_TEXT_ANTIALIAS_ON); 327 } 328 if (qualityRendering) { 329 graphics.setRenderingHint(RenderingHints.KEY_RENDERING, 330 RenderingHints.VALUE_RENDER_QUALITY); 331 } 332 333 AffineTransform at = graphics.getTransform(); 335 at.scale(scaleX, scaleY); 336 graphics.setTransform(at); 337 338 if (!transparentPageBackground) { 340 graphics.setColor(Color.white); 341 graphics.fillRect(0, 0, pageWidth, pageHeight); 342 } 343 graphics.setColor(Color.black); 344 graphics.drawRect(-1, -1, pageWidth + 2, pageHeight + 2); 345 graphics.drawLine(pageWidth + 2, 0, pageWidth + 2, pageHeight + 2); 346 graphics.drawLine(pageWidth + 3, 1, pageWidth + 3, pageHeight + 3); 347 graphics.drawLine(0, pageHeight + 2, pageWidth + 2, pageHeight + 2); 348 graphics.drawLine(1, pageHeight + 3, pageWidth + 3, pageHeight + 3); 349 350 state = new Java2DGraphicsState(graphics, this.fontInfo, at); 351 try { 352 currentBPPosition = 0; 354 currentIPPosition = 0; 355 356 renderPageAreas(pageViewport.getPage()); 358 } finally { 359 state = null; 360 } 361 362 return currentPageImage; 363 } finally { 364 this.currentPageViewport = null; 365 } 366 } 367 368 375 protected BufferedImage getBufferedImage(int bitmapWidth, int bitmapHeight) { 376 return new BufferedImage ( 377 bitmapWidth, bitmapHeight, BufferedImage.TYPE_INT_ARGB); 378 } 379 380 386 public PageViewport getPageViewport(int pageNum) throws FOPException { 387 if (pageNum < 0 || pageNum >= pageViewportList.size()) { 388 throw new FOPException("Requested page number is out of range: " + pageNum 389 + "; only " + pageViewportList.size() 390 + " page(s) available."); 391 } 392 return (PageViewport) pageViewportList.get(pageNum); 393 } 394 395 403 public BufferedImage getPageImage(int pageNum) throws FOPException { 404 return getPageImage(getPageViewport(pageNum)); 405 } 406 407 408 protected void saveGraphicsState() { 409 stateStack.push(state); 411 state = new Java2DGraphicsState(state); 412 } 413 414 415 protected void restoreGraphicsState() { 416 state.dispose(); 417 state = (Java2DGraphicsState)stateStack.pop(); 418 } 419 420 423 protected void startVParea(CTM ctm, Rectangle2D clippingRect) { 424 425 saveGraphicsState(); 426 427 if (clippingRect != null) { 428 clipRect((float)clippingRect.getX() / 1000f, 429 (float)clippingRect.getY() / 1000f, 430 (float)clippingRect.getWidth() / 1000f, 431 (float)clippingRect.getHeight() / 1000f); 432 } 433 434 state.transform(new AffineTransform (CTMHelper.toPDFArray(ctm))); 437 } 438 439 442 protected void endVParea() { 443 restoreGraphicsState(); 444 } 445 446 449 protected List breakOutOfStateStack() { 450 log.debug("Block.FIXED --> break out"); 451 List breakOutList; 452 breakOutList = new java.util.ArrayList (); 453 while (!stateStack.isEmpty()) { 454 breakOutList.add(0, state); 455 state = (Java2DGraphicsState)stateStack.pop(); 457 } 458 return breakOutList; 459 } 460 461 465 protected void restoreStateStackAfterBreakOut(List breakOutList) { 466 log.debug("Block.FIXED --> restoring context after break-out"); 467 468 Iterator i = breakOutList.iterator(); 469 while (i.hasNext()) { 470 Java2DGraphicsState s = (Java2DGraphicsState)i.next(); 471 stateStack.push(state); 472 state = s; 473 } 474 } 475 476 479 protected void updateColor(Color col, boolean fill) { 480 state.updateColor(col); 481 } 482 483 486 protected void clip() { 487 if (currentPath == null) { 488 throw new IllegalStateException ("No current path available!"); 489 } 490 state.updateClip(currentPath); 491 currentPath = null; 492 } 493 494 497 protected void closePath() { 498 currentPath.closePath(); 499 } 500 501 504 protected void lineTo(float x, float y) { 505 if (currentPath == null) { 506 currentPath = new GeneralPath (); 507 } 508 currentPath.lineTo(x, y); 509 } 510 511 514 protected void moveTo(float x, float y) { 515 if (currentPath == null) { 516 currentPath = new GeneralPath (); 517 } 518 currentPath.moveTo(x, y); 519 } 520 521 524 protected void clipRect(float x, float y, float width, float height) { 525 state.updateClip(new Rectangle2D.Float (x, y, width, height)); 526 } 527 528 531 protected void fillRect(float x, float y, float width, float height) { 532 state.getGraph().fill(new Rectangle2D.Float (x, y, width, height)); 533 } 534 535 538 protected void drawBorderLine(float x1, float y1, float x2, float y2, 539 boolean horz, boolean startOrBefore, int style, Color col) { 540 Graphics2D g2d = state.getGraph(); 541 drawBorderLine(new Rectangle2D.Float (x1, y1, x2 - x1, y2 - y1), 542 horz, startOrBefore, style, col, g2d); 543 } 544 545 555 public static void drawBorderLine(Rectangle2D.Float lineRect, 556 boolean horz, boolean startOrBefore, int style, Color col, Graphics2D g2d) { 557 float x1 = lineRect.x; 558 float y1 = lineRect.y; 559 float x2 = x1 + lineRect.width; 560 float y2 = y1 + lineRect.height; 561 float w = lineRect.width; 562 float h = lineRect.height; 563 if ((w < 0) || (h < 0)) { 564 log.error("Negative extent received. Border won't be painted."); 565 return; 566 } 567 switch (style) { 568 case Constants.EN_DASHED: 569 g2d.setColor(col); 570 if (horz) { 571 float unit = Math.abs(2 * h); 572 int rep = (int)(w / unit); 573 if (rep % 2 == 0) { 574 rep++; 575 } 576 unit = w / rep; 577 float ym = y1 + (h / 2); 578 BasicStroke s = new BasicStroke (h, BasicStroke.CAP_BUTT, 579 BasicStroke.JOIN_MITER, 10.0f, new float[] {unit}, 0); 580 g2d.setStroke(s); 581 g2d.draw(new Line2D.Float (x1, ym, x2, ym)); 582 } else { 583 float unit = Math.abs(2 * w); 584 int rep = (int)(h / unit); 585 if (rep % 2 == 0) { 586 rep++; 587 } 588 unit = h / rep; 589 float xm = x1 + (w / 2); 590 BasicStroke s = new BasicStroke (w, BasicStroke.CAP_BUTT, 591 BasicStroke.JOIN_MITER, 10.0f, new float[] {unit}, 0); 592 g2d.setStroke(s); 593 g2d.draw(new Line2D.Float (xm, y1, xm, y2)); 594 } 595 break; 596 case Constants.EN_DOTTED: 597 g2d.setColor(col); 598 if (horz) { 599 float unit = Math.abs(2 * h); 600 int rep = (int)(w / unit); 601 if (rep % 2 == 0) { 602 rep++; 603 } 604 unit = w / rep; 605 float ym = y1 + (h / 2); 606 BasicStroke s = new BasicStroke (h, BasicStroke.CAP_ROUND, 607 BasicStroke.JOIN_MITER, 10.0f, new float[] {0, unit}, 0); 608 g2d.setStroke(s); 609 g2d.draw(new Line2D.Float (x1, ym, x2, ym)); 610 } else { 611 float unit = Math.abs(2 * w); 612 int rep = (int)(h / unit); 613 if (rep % 2 == 0) { 614 rep++; 615 } 616 unit = h / rep; 617 float xm = x1 + (w / 2); 618 BasicStroke s = new BasicStroke (w, BasicStroke.CAP_ROUND, 619 BasicStroke.JOIN_MITER, 10.0f, new float[] {0, unit}, 0); 620 g2d.setStroke(s); 621 g2d.draw(new Line2D.Float (xm, y1, xm, y2)); 622 } 623 break; 624 case Constants.EN_DOUBLE: 625 g2d.setColor(col); 626 if (horz) { 627 float h3 = h / 3; 628 float ym1 = y1 + (h3 / 2); 629 float ym2 = ym1 + h3 + h3; 630 BasicStroke s = new BasicStroke (h3); 631 g2d.setStroke(s); 632 g2d.draw(new Line2D.Float (x1, ym1, x2, ym1)); 633 g2d.draw(new Line2D.Float (x1, ym2, x2, ym2)); 634 } else { 635 float w3 = w / 3; 636 float xm1 = x1 + (w3 / 2); 637 float xm2 = xm1 + w3 + w3; 638 BasicStroke s = new BasicStroke (w3); 639 g2d.setStroke(s); 640 g2d.draw(new Line2D.Float (xm1, y1, xm1, y2)); 641 g2d.draw(new Line2D.Float (xm2, y1, xm2, y2)); 642 } 643 break; 644 case Constants.EN_GROOVE: 645 case Constants.EN_RIDGE: 646 float colFactor = (style == EN_GROOVE ? 0.4f : -0.4f); 647 if (horz) { 648 Color uppercol = lightenColor(col, -colFactor); 649 Color lowercol = lightenColor(col, colFactor); 650 float h3 = h / 3; 651 float ym1 = y1 + (h3 / 2); 652 g2d.setStroke(new BasicStroke (h3)); 653 g2d.setColor(uppercol); 654 g2d.draw(new Line2D.Float (x1, ym1, x2, ym1)); 655 g2d.setColor(col); 656 g2d.draw(new Line2D.Float (x1, ym1 + h3, x2, ym1 + h3)); 657 g2d.setColor(lowercol); 658 g2d.draw(new Line2D.Float (x1, ym1 + h3 + h3, x2, ym1 + h3 + h3)); 659 } else { 660 Color leftcol = lightenColor(col, -colFactor); 661 Color rightcol = lightenColor(col, colFactor); 662 float w3 = w / 3; 663 float xm1 = x1 + (w3 / 2); 664 g2d.setStroke(new BasicStroke (w3)); 665 g2d.setColor(leftcol); 666 g2d.draw(new Line2D.Float (xm1, y1, xm1, y2)); 667 g2d.setColor(col); 668 g2d.draw(new Line2D.Float (xm1 + w3, y1, xm1 + w3, y2)); 669 g2d.setColor(rightcol); 670 g2d.draw(new Line2D.Float (xm1 + w3 + w3, y1, xm1 + w3 + w3, y2)); 671 } 672 break; 673 case Constants.EN_INSET: 674 case Constants.EN_OUTSET: 675 colFactor = (style == EN_OUTSET ? 0.4f : -0.4f); 676 if (horz) { 677 col = lightenColor(col, (startOrBefore ? 1 : -1) * colFactor); 678 g2d.setStroke(new BasicStroke (h)); 679 float ym1 = y1 + (h / 2); 680 g2d.setColor(col); 681 g2d.draw(new Line2D.Float (x1, ym1, x2, ym1)); 682 } else { 683 col = lightenColor(col, (startOrBefore ? 1 : -1) * colFactor); 684 float xm1 = x1 + (w / 2); 685 g2d.setStroke(new BasicStroke (w)); 686 g2d.setColor(col); 687 g2d.draw(new Line2D.Float (xm1, y1, xm1, y2)); 688 } 689 break; 690 case Constants.EN_HIDDEN: 691 break; 692 default: 693 g2d.setColor(col); 694 if (horz) { 695 float ym = y1 + (h / 2); 696 g2d.setStroke(new BasicStroke (h)); 697 g2d.draw(new Line2D.Float (x1, ym, x2, ym)); 698 } else { 699 float xm = x1 + (w / 2); 700 g2d.setStroke(new BasicStroke (w)); 701 g2d.draw(new Line2D.Float (xm, y1, xm, y2)); 702 } 703 } 704 } 705 706 709 public void renderText(TextArea text) { 710 renderInlineAreaBackAndBorders(text); 711 712 int rx = currentIPPosition + text.getBorderAndPaddingWidthStart(); 713 int bl = currentBPPosition + text.getOffset() + text.getBaselineOffset(); 714 int saveIP = currentIPPosition; 715 716 Font font = getFontFromArea(text); 717 state.updateFont(font.getFontName(), font.getFontSize()); 718 saveGraphicsState(); 719 AffineTransform at = new AffineTransform (); 720 at.translate(rx / 1000f, bl / 1000f); 721 state.transform(at); 722 renderText(text, state.getGraph(), font); 723 restoreGraphicsState(); 724 725 currentIPPosition = saveIP + text.getAllocIPD(); 726 728 Typeface tf = (Typeface) fontInfo.getFonts().get(font.getFontName()); 730 int fontsize = text.getTraitAsInteger(Trait.FONT_SIZE); 731 renderTextDecoration(tf, fontsize, text, bl, rx); 732 } 733 734 741 public static void renderText(TextArea text, Graphics2D g2d, Font font) { 742 743 Color col = (Color ) text.getTrait(Trait.COLOR); 744 g2d.setColor(col); 745 746 float textCursor = 0; 747 748 Iterator iter = text.getChildAreas().iterator(); 749 while (iter.hasNext()) { 750 InlineArea child = (InlineArea)iter.next(); 751 if (child instanceof WordArea) { 752 WordArea word = (WordArea)child; 753 String s = word.getWord(); 754 int[] letterAdjust = word.getLetterAdjustArray(); 755 GlyphVector gv = g2d.getFont().createGlyphVector(g2d.getFontRenderContext(), s); 756 double additionalWidth = 0.0; 757 if (letterAdjust == null 758 && text.getTextLetterSpaceAdjust() == 0 759 && text.getTextWordSpaceAdjust() == 0) { 760 } else { 762 int[] offsets = getGlyphOffsets(s, font, text, letterAdjust); 763 float cursor = 0.0f; 764 for (int i = 0; i < offsets.length; i++) { 765 Point2D pt = gv.getGlyphPosition(i); 766 pt.setLocation(cursor, pt.getY()); 767 gv.setGlyphPosition(i, pt); 768 cursor += offsets[i] / 1000f; 769 } 770 additionalWidth = cursor - gv.getLogicalBounds().getWidth(); 771 } 772 g2d.drawGlyphVector(gv, textCursor, 0); 773 textCursor += gv.getLogicalBounds().getWidth() + additionalWidth; 774 } else if (child instanceof SpaceArea) { 775 SpaceArea space = (SpaceArea)child; 776 String s = space.getSpace(); 777 char sp = s.charAt(0); 778 int tws = (space.isAdjustable() 779 ? text.getTextWordSpaceAdjust() 780 + 2 * text.getTextLetterSpaceAdjust() 781 : 0); 782 783 textCursor += (font.getCharWidth(sp) + tws) / 1000f; 784 } else { 785 throw new IllegalStateException ("Unsupported child element: " + child); 786 } 787 } 788 } 789 790 private static int[] getGlyphOffsets(String s, Font font, TextArea text, 791 int[] letterAdjust) { 792 int textLen = s.length(); 793 int[] offsets = new int[textLen]; 794 for (int i = 0; i < textLen; i++) { 795 final char c = s.charAt(i); 796 final char mapped = font.mapChar(c); 797 int wordSpace; 798 799 if (CharUtilities.isAdjustableSpace(mapped)) { 800 wordSpace = text.getTextWordSpaceAdjust(); 801 } else { 802 wordSpace = 0; 803 } 804 int cw = font.getWidth(mapped); 805 int ladj = (letterAdjust != null && i < textLen - 1 ? letterAdjust[i + 1] : 0); 806 int tls = (i < textLen - 1 ? text.getTextLetterSpaceAdjust() : 0); 807 offsets[i] = cw + ladj + tls + wordSpace; 808 } 809 return offsets; 810 } 811 812 818 public void renderLeader(Leader area) { 819 renderInlineAreaBackAndBorders(area); 820 821 824 float startx = (currentIPPosition + area.getBorderAndPaddingWidthStart()) / 1000f; 825 float starty = ((currentBPPosition + area.getOffset()) / 1000f); 826 float endx = (currentIPPosition + area.getBorderAndPaddingWidthStart() 827 + area.getIPD()) / 1000f; 828 829 Color col = (Color ) area.getTrait(Trait.COLOR); 830 state.updateColor(col); 831 832 Line2D line = new Line2D.Float (); 833 line.setLine(startx, starty, endx, starty); 834 float ruleThickness = area.getRuleThickness() / 1000f; 835 836 int style = area.getRuleStyle(); 837 switch (style) { 838 case EN_SOLID: 839 case EN_DASHED: 840 case EN_DOUBLE: 841 drawBorderLine(startx, starty, endx, starty + ruleThickness, 842 true, true, style, col); 843 break; 844 case EN_DOTTED: 845 state.updateStroke(ruleThickness, style); 847 float rt2 = ruleThickness / 2f; 848 line.setLine(line.getX1(), line.getY1() + rt2, line.getX2(), line.getY2() + rt2); 849 state.getGraph().draw(line); 850 break; 851 case EN_GROOVE: 852 case EN_RIDGE: 853 float half = area.getRuleThickness() / 2000f; 854 855 state.updateColor(lightenColor(col, 0.6f)); 856 moveTo(startx, starty); 857 lineTo(endx, starty); 858 lineTo(endx, starty + 2 * half); 859 lineTo(startx, starty + 2 * half); 860 closePath(); 861 state.getGraph().fill(currentPath); 862 currentPath = null; 863 state.updateColor(col); 864 if (style == EN_GROOVE) { 865 moveTo(startx, starty); 866 lineTo(endx, starty); 867 lineTo(endx, starty + half); 868 lineTo(startx + half, starty + half); 869 lineTo(startx, starty + 2 * half); 870 } else { 871 moveTo(endx, starty); 872 lineTo(endx, starty + 2 * half); 873 lineTo(startx, starty + 2 * half); 874 lineTo(startx, starty + half); 875 lineTo(endx - half, starty + half); 876 } 877 closePath(); 878 state.getGraph().fill(currentPath); 879 currentPath = null; 880 881 case EN_NONE: 882 break; 884 default: 885 } 887 super.renderLeader(area); 888 } 889 890 894 public void renderImage(Image image, Rectangle2D pos) { 895 String url = image.getURL(); 897 drawImage(url, pos); 898 } 899 900 904 protected void drawImage(String url, Rectangle2D pos, Map foreignAttributes) { 905 906 int x = currentIPPosition + (int)Math.round(pos.getX()); 907 int y = currentBPPosition + (int)Math.round(pos.getY()); 908 url = ImageFactory.getURL(url); 909 910 ImageFactory fact = userAgent.getFactory().getImageFactory(); 911 FopImage fopimage = fact.getImage(url, userAgent); 912 913 if (fopimage == null) { 914 return; 915 } 916 if (!fopimage.load(FopImage.DIMENSIONS)) { 917 return; 918 } 919 int w = fopimage.getWidth(); 920 int h = fopimage.getHeight(); 921 String mime = fopimage.getMimeType(); 922 if ("text/xml".equals(mime)) { 923 if (!fopimage.load(FopImage.ORIGINAL_DATA)) { 924 return; 925 } 926 Document doc = ((XMLImage) fopimage).getDocument(); 927 String ns = ((XMLImage) fopimage).getNameSpace(); 928 renderDocument(doc, ns, pos, foreignAttributes); 929 930 } else if ("image/svg+xml".equals(mime)) { 931 if (!fopimage.load(FopImage.ORIGINAL_DATA)) { 932 return; 933 } 934 Document doc = ((XMLImage) fopimage).getDocument(); 935 String ns = ((XMLImage) fopimage).getNameSpace(); 936 937 renderDocument(doc, ns, pos, foreignAttributes); 938 } else if ("image/eps".equals(mime)) { 939 log.warn("EPS images are not supported by this renderer"); 940 } else { 941 if (!fopimage.load(FopImage.BITMAP)) { 942 log.warn("Loading of bitmap failed: " + url); 943 return; 944 } 945 946 byte[] raw = fopimage.getBitmaps(); 947 948 ColorModel cm = new ComponentColorModel ( 950 ColorSpace.getInstance(ColorSpace.CS_LINEAR_RGB), 951 new int[] {8, 8, 8}, 952 false, false, 953 ColorModel.OPAQUE, DataBuffer.TYPE_BYTE); 954 SampleModel sampleModel = new PixelInterleavedSampleModel ( 955 DataBuffer.TYPE_BYTE, w, h, 3, w * 3, new int[] {0, 1, 2}); 956 DataBuffer dbuf = new DataBufferByte (raw, w * h * 3); 957 958 WritableRaster raster = Raster.createWritableRaster(sampleModel, 959 dbuf, null); 960 961 java.awt.Image awtImage; 962 awtImage = new BufferedImage (cm, raster, false, null); 964 965 state.getGraph().drawImage(awtImage, 966 (int)(x / 1000f), (int)(y / 1000f), 967 (int)(pos.getWidth() / 1000f), (int)(pos.getHeight() / 1000f), null); 968 } 969 } 970 971 975 protected RendererContext createRendererContext(int x, int y, int width, int height, 976 Map foreignAttributes) { 977 RendererContext context = super.createRendererContext( 978 x, y, width, height, foreignAttributes); 979 context.setProperty(Java2DRendererContextConstants.JAVA2D_STATE, state); 980 return context; 981 } 982 983 987 public int print(Graphics g, PageFormat pageFormat, int pageIndex) 988 throws PrinterException { 989 if (pageIndex >= getNumberOfPages()) { 990 return NO_SUCH_PAGE; 991 } 992 993 if (state != null) { 994 throw new IllegalStateException ("state must be null"); 995 } 996 Graphics2D graphics = (Graphics2D ) g; 997 try { 998 PageViewport viewport = getPageViewport(pageIndex); 999 AffineTransform at = graphics.getTransform(); 1000 state = new Java2DGraphicsState(graphics, this.fontInfo, at); 1001 1002 currentBPPosition = 0; 1004 currentIPPosition = 0; 1005 1006 renderPageAreas(viewport.getPage()); 1007 return PAGE_EXISTS; 1008 } catch (FOPException e) { 1009 log.error(e); 1010 return NO_SUCH_PAGE; 1011 } finally { 1012 state = null; 1013 } 1014 } 1015 1016 1017 protected void beginTextObject() { 1018 } 1020 1021 1022 protected void endTextObject() { 1023 } 1025 1026} 1027 | Popular Tags |