1 51 package org.apache.fop.render.ps; 52 53 import org.apache.fop.svg.SVGArea; 55 import org.apache.fop.render.AbstractRenderer; 56 import org.apache.fop.image.ImageArea; 57 import org.apache.fop.image.FopImage; 58 import org.apache.fop.image.FopImageException; 59 import org.apache.fop.image.JpegImage; 60 import org.apache.fop.layout.*; 61 import org.apache.fop.layout.inline.*; 62 import org.apache.fop.datatypes.*; 63 import org.apache.fop.fo.properties.*; 64 import org.apache.fop.fonts.Glyphs; 65 import org.apache.fop.render.pdf.Font; 66 import org.apache.fop.image.*; 67 import org.apache.fop.apps.FOPException; 68 69 import org.apache.batik.bridge.*; 70 import org.apache.batik.gvt.*; 71 72 import org.w3c.dom.*; 74 import org.w3c.dom.svg.SVGDocument; 75 import org.w3c.dom.svg.SVGSVGElement; 76 77 import java.io.IOException; 79 import java.io.OutputStream; 80 import java.util.Iterator; 81 import java.util.List; 82 import java.util.Map; 83 import java.awt.geom.AffineTransform; 84 85 115 116 125 public class PSRenderer extends AbstractRenderer { 126 127 130 protected String producer; 131 132 int imagecount = 0; int pagecount = 0; 134 135 private boolean enableComments = true; 136 private boolean autoRotateLandscape = false; 137 138 141 protected PSStream out; 142 private boolean ioTrouble = false; 143 144 private String currentFontName; 145 private int currentFontSize; 146 private int pageHeight; 147 private int pageWidth; 148 private float currRed; 149 private float currGreen; 150 private float currBlue; 151 152 private FontInfo fontInfo; 153 154 private int psLevel = 3; 155 156 protected java.util.Map options; 157 158 159 164 public void setProducer(String producer) { 165 this.producer = producer; 166 } 167 168 169 172 public void setOptions(java.util.Map options) { 173 this.options = options; 174 } 175 176 177 182 public void setPSLevel(int level) { 183 switch (level) { 184 case 2: 185 case 3: 186 this.psLevel = level; 187 break; 188 default: 189 throw new IllegalArgumentException("Only PostScript Levels 2 and 3 are supported"); 190 } 191 } 192 193 194 public int getPSLevel() { 195 return this.psLevel; 196 } 197 198 public void setAutoRotateLandscape(boolean value) { 199 this.autoRotateLandscape = value; 200 } 201 202 public boolean isAutoRotateLandscape() { 203 return this.autoRotateLandscape; 204 } 205 206 209 protected void write(String cmd) { 210 try { 211 out.write(cmd); 212 } catch (IOException e) { 213 if (!ioTrouble) 214 e.printStackTrace(); 215 ioTrouble = true; 216 } 217 } 218 219 222 protected void comment(String comment) { 223 if (this.enableComments) 224 write(comment); 225 } 226 227 protected void writeProcs() { 228 write("%%BeginResource: procset FOPprocs"); 229 write("%%Title: Utility procedures"); 230 write("/FOPprocs 20 dict dup begin"); 231 write("/bd{bind def}bind def"); 232 write("/ld{load def}bd"); 233 write("/M/moveto ld"); 234 write("/RM/rmoveto ld"); 235 write("/t/show ld"); 236 write("/A/ashow ld"); 237 write("/cp/closepath ld"); 238 write("/re {4 2 roll M"); write("1 index 0 rlineto"); 240 write("0 exch rlineto"); 241 write("neg 0 rlineto"); 242 write("cp } bd"); 243 244 write("/ux 0.0 def"); 245 write("/uy 0.0 def"); 246 247 write("/F {"); 249 write(" /Tp exch def"); 250 write(" /Tf exch def"); 252 write(" Tf findfont Tp scalefont setfont"); 253 write(" /cf Tf def /cs Tp def /cw ( ) stringwidth pop def"); 254 write("} bd"); 255 256 write("/ULS {currentpoint /uy exch def /ux exch def} bd"); 257 write("/ULE {"); 258 write(" /Tcx currentpoint pop def"); 259 write(" gsave"); 260 write(" newpath"); 261 write(" cf findfont cs scalefont dup"); 262 write(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup"); 263 write(" /UnderlinePosition get Ts mul /To exch def"); 264 write(" /UnderlineThickness get Ts mul /Tt exch def"); 265 write(" ux uy To add moveto Tcx uy To add lineto"); 266 write(" Tt setlinewidth stroke"); 267 write(" grestore"); 268 write("} bd"); 269 270 write("/OLE {"); 271 write(" /Tcx currentpoint pop def"); 272 write(" gsave"); 273 write(" newpath"); 274 write(" cf findfont cs scalefont dup"); 275 write(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup"); 276 write(" /UnderlinePosition get Ts mul /To exch def"); 277 write(" /UnderlineThickness get Ts mul /Tt exch def"); 278 write(" ux uy To add cs add moveto Tcx uy To add cs add lineto"); 279 write(" Tt setlinewidth stroke"); 280 write(" grestore"); 281 write("} bd"); 282 283 write("/SOE {"); 284 write(" /Tcx currentpoint pop def"); 285 write(" gsave"); 286 write(" newpath"); 287 write(" cf findfont cs scalefont dup"); 288 write(" /FontMatrix get 0 get /Ts exch def /FontInfo get dup"); 289 write(" /UnderlinePosition get Ts mul /To exch def"); 290 write(" /UnderlineThickness get Ts mul /Tt exch def"); 291 write(" ux uy To add cs 10 mul 26 idiv add moveto Tcx uy To add cs 10 mul 26 idiv add lineto"); 292 write(" Tt setlinewidth stroke"); 293 write(" grestore"); 294 write("} bd"); 295 write("end def"); 296 write("%%EndResource"); 297 } 298 299 protected void writeFontDict(FontInfo fontInfo) { 300 write("%%BeginResource: procset FOPFonts"); 301 write("%%Title: Font setup (shortcuts) for this file"); 302 write("/FOPFonts 100 dict dup begin"); 303 Map fonts = fontInfo.getFonts(); 306 Iterator enum = fonts.keySet().iterator(); 307 while (enum.hasNext()) { 308 String key = (String)enum.next(); 309 Font fm = (Font)fonts.get(key); 310 write("/" + key + " /" + fm.fontName() + " def"); 311 } 312 write("end def"); 313 write("%%EndResource"); 314 defineWinAnsiEncoding(); 315 316 enum = fonts.keySet().iterator(); 318 while (enum.hasNext()) { 319 String key = (String)enum.next(); 320 Font fm = (Font)fonts.get(key); 321 if (null == fm.encoding()) { 322 } else if ("WinAnsiEncoding".equals(fm.encoding())) { 325 write("/" + fm.fontName() + " findfont"); 326 write("dup length dict begin"); 327 write(" {1 index /FID ne {def} {pop pop} ifelse} forall"); 328 write(" /Encoding " + fm.encoding() + " def"); 329 write(" currentdict"); 330 write("end"); 331 write("/" + fm.fontName() + " exch definefont pop"); 332 } else { 333 log.warn("Only WinAnsiEncoding is supported. Font '" 334 + fm.fontName() + "' asks for: " + fm.encoding()); 335 } 336 } 337 } 338 339 private void defineWinAnsiEncoding() { 340 write("/WinAnsiEncoding ["); 341 StringBuffer sb = new StringBuffer(); 342 for (int i = 0; i < Glyphs.winAnsiEncoding.length; i++) { 343 if (i > 0) { 344 if ((i % 5) == 0) { 345 write(sb.toString()); 346 sb.setLength(0); 347 } else { 348 sb.append(" "); 349 } 350 } 351 final char ch = Glyphs.winAnsiEncoding[i]; 352 final String glyphname = Glyphs.charToGlyphName(ch); 353 if ("".equals(glyphname)) { 354 sb.append("/" + Glyphs.notdef); 355 } else { 356 sb.append("/"); 357 sb.append(glyphname); 358 } 359 } 360 write(sb.toString()); 361 write("] def"); 362 } 363 364 365 366 protected void movetoCurrPosition() { 367 write(this.currentXPosition + " " + this.currentYPosition + " M"); 368 } 369 370 375 public void setupFontInfo(FontInfo fontInfo) 376 throws FOPException { 377 378 org.apache.fop.render.pdf.FontSetup.setup(fontInfo); 379 this.fontInfo = fontInfo; 380 } 381 382 protected void addFilledRect(int x, int y, int w, int h, 383 ColorType col) { 384 if (h < 0) { 386 h = -h; 387 } 388 389 write("newpath"); 390 write(x + " " + y + " " + w + " " + -h + " re"); 391 399 useColor(col); 400 write("fill"); 401 } 402 403 408 public void renderDisplaySpace(DisplaySpace space) { 409 this.currentYPosition -= space.getSize(); 411 } 412 413 416 public void renderForeignObjectArea(ForeignObjectArea area) { 417 this.currentXPosition = this.currentXPosition + area.getXOffset(); 419 int plOffset = 0; 420 Area parent = area.getParent(); 421 if (parent instanceof LineArea) { 422 plOffset = ((LineArea)parent).getPlacementOffset(); 423 } 424 this.currentYPosition += plOffset; 425 area.getObject().render(this); 426 this.currentXPosition += area.getEffectiveWidth(); 427 this.currentYPosition -= plOffset; 428 } 429 430 435 public void renderSVGArea(SVGArea area) { 436 int x = this.currentXPosition; 437 int y = this.currentYPosition; 438 renderSVGDocument(area.getSVGDocument(), x, y, area.getFontState()); 439 } 440 441 442 450 protected void renderSVGDocument(Document doc, int x, int y, 451 FontState fs) { 452 org.apache.fop.svg.SVGUserAgent userAgent 453 = new org.apache.fop.svg.SVGUserAgent(new AffineTransform()); 454 userAgent.setLogger(log); 455 456 GVTBuilder builder = new GVTBuilder(); 457 BridgeContext ctx = new BridgeContext(userAgent); 458 459 GraphicsNode root; 460 try { 461 root = builder.build(ctx, doc); 462 } catch (Exception e) { 463 log.error("svg graphic could not be built: " 464 + e.getMessage(), e); 465 return; 466 } 467 float w = (float)ctx.getDocumentSize().getWidth() * 1000f; 469 float h = (float)ctx.getDocumentSize().getHeight() * 1000f; 470 471 SVGSVGElement svg = ((SVGDocument) doc).getRootElement(); 473 AffineTransform at = ViewBox.getPreserveAspectRatioTransform(svg, 474 w/1000f , h/1000f ); 475 476 ctx = null; 477 builder = null; 478 479 float sx = 1, sy = -1; 480 int xOffset = x, yOffset = y; 481 482 comment("% --- SVG Area"); 483 write("gsave"); 484 if (w != 0 && h != 0) { 485 write("newpath"); 486 write(x + " " + y + " M"); 487 write((x + w) + " " + y + " rlineto"); 488 write((x + w) + " " + (y - h) + " rlineto"); 489 write(x + " " + (y - h) + " rlineto"); 490 write("closepath"); 491 write("clippath"); 492 } 493 write(xOffset + " " + yOffset + " translate"); 497 write((at.getTranslateX() * 1000) + " " 498 + (-at.getTranslateY() * 1000) + " translate"); 499 write(sx * at.getScaleX() + " " + sy * at.getScaleY() + " scale"); 500 501 PSGraphics2D graphics = new PSGraphics2D(false, fs, 502 this, currentFontName, 503 currentFontSize, 504 currentXPosition, 505 currentYPosition); 506 graphics.setGraphicContext(new org.apache.batik.ext.awt.g2d.GraphicContext()); 507 try { 508 root.paint(graphics); 509 } catch (Exception e) { 510 log.error("svg graphic could not be rendered: " 511 + e.getMessage(), e); 512 } 513 514 write("grestore"); 515 516 comment("% --- SVG Area end"); 517 } 518 519 532 protected void drawImageScaled(int x, int y, int w, int h, 533 FopImage image, 534 FontState fs) { 535 if (image instanceof SVGImage) { 537 try { 538 renderSVGDocument(((SVGImage)image).getSVGDocument(), x, y, fs); 539 } catch (FopImageException e) { 540 log.error("Error rendering SVG image", e); 541 } 542 } else if (image instanceof EPSImage) { 543 renderEPS(image, x, y, w, h); 544 } else { 545 renderBitmap(image, x, y, w, h); 546 } 547 } 548 549 562 protected void drawImageClipped(int x, int y, 563 int clipX, int clipY, 564 int clipW, int clipH, 565 FopImage image, 566 FontState fs) { 567 write("gsave"); 569 write(clipX + " " + clipY + " " + clipW + " " + clipH + " re"); 570 write("clippath"); 571 572 try { 573 int w = image.getWidth() * 1000; 574 int h = image.getHeight() * 1000; 575 576 drawImageScaled(x, y, w, h, image, fs); 577 } catch (FopImageException e) { 578 log.error("Error getting image extents", e); 579 } 580 write("grestore"); 581 } 582 583 public void renderEPS(FopImage img, int x, int y, int w, int h) { 584 try { 585 EPSImage eimg = (EPSImage)img; 586 int[] bbox = eimg.getBBox(); 587 int bboxw = bbox[2] - bbox[0]; 588 int bboxh = bbox[3] - bbox[1]; 589 590 591 write("%%BeginDocument: " + eimg.getDocName()); 592 write("BeginEPSF"); 593 594 write(x + " " + (y - h) + " translate"); 595 write("0.0 rotate"); 596 write((long)(w/bboxw) + " " + (long)(h/bboxh) + " scale"); 597 write(-bbox[0] + " " + (-bbox[1]) + " translate"); 598 write(bbox[0] + " " + bbox[1] + " " + bboxw + " " + bboxh + " rectclip"); 599 write("newpath"); 600 out.writeByteArr(img.getBitmaps()); 601 write("%%EndDocument"); 602 write("EndEPSF"); 603 write(""); 604 } catch (Exception e) { 605 e.printStackTrace(); 606 log.error("PSRenderer.renderImageArea(): Error rendering bitmap (" 607 + e.getMessage() + ")", e); 608 } 609 } 610 611 public void renderBitmap(FopImage img, int x, int y, int w, int h) { 612 try { 613 boolean iscolor = img.getColorSpace().getColorSpace() 614 != ColorSpace.DEVICE_GRAY; 615 byte[] imgmap = img.getBitmaps(); 616 617 write("gsave"); 618 if (img.getColorSpace().getColorSpace() == ColorSpace.DEVICE_CMYK) 619 write("/DeviceCMYK setcolorspace"); 620 else if (img.getColorSpace().getColorSpace() == ColorSpace.DEVICE_GRAY) 621 write("/DeviceGray setcolorspace"); 622 else 623 write("/DeviceRGB setcolorspace"); 624 625 write(x + " " + (y - h) + " translate"); 626 write(w + " " + h + " scale"); 627 628 write("{{"); 629 if (img instanceof JpegImage) { 633 write("/RawData currentfile /ASCII85Decode filter def"); 634 write("/Data RawData << >> /DCTDecode filter def"); 635 } else { 636 if (this.psLevel >= 3) { 637 write("/RawData currentfile /ASCII85Decode filter def"); 638 write("/Data RawData /FlateDecode filter def"); 639 } else { 640 write("/RawData currentfile /ASCII85Decode filter def"); 641 write("/Data RawData /RunLengthDecode filter def"); 642 } 643 } 644 write("<<"); 645 write(" /ImageType 1"); 646 write(" /Width " + img.getWidth()); 647 write(" /Height " + img.getHeight()); 648 write(" /BitsPerComponent 8"); 649 if (img.getColorSpace().getColorSpace() == ColorSpace.DEVICE_CMYK) { 650 if (img.invertImage()) 651 write(" /Decode [1 0 1 0 1 0 1 0]"); 652 else 653 write(" /Decode [0 1 0 1 0 1 0 1]"); 654 } else if (iscolor) { 655 write(" /Decode [0 1 0 1 0 1]"); 656 } else { 657 write(" /Decode [0 1]"); 658 } 659 write(" /ImageMatrix [" + img.getWidth() + " 0 0 -" 661 + img.getHeight() + " 0 " + img.getHeight() + "]"); 662 663 write(" /DataSource Data"); 664 write(">>"); 665 write("image"); 666 670 write("} stopped {handleerror} if"); 671 write(" RawData flushfile"); 672 write("} exec"); 673 674 689 try { 690 OutputStream out = this.out; 692 out = new ASCII85OutputStream(out); 693 if (img instanceof JpegImage) { 694 } else { 696 if (this.psLevel >= 3) { 697 out = new FlateEncodeOutputStream(out); 698 } else { 699 out = new RunLengthEncodeOutputStream(out); 700 } 701 } 702 out.write(imgmap); 703 if (out instanceof Finalizable) { 704 ((Finalizable)out).finalizeStream(); 705 } else { 706 out.flush(); 707 } 708 } catch (IOException e) { 709 if (!ioTrouble) 710 e.printStackTrace(); 711 ioTrouble = true; 712 } 713 714 write(""); 715 write("grestore"); 716 } catch (FopImageException e) { 717 log.error("PSRenderer.renderImageArea(): Error rendering bitmap (" 718 + e.getMessage() + ")", e); 719 } 720 } 721 722 727 public void renderImageArea(ImageArea area) { 728 int x = this.currentXPosition + area.getXOffset(); 730 int ploffset = 0; 731 if (area.getParent() instanceof LineArea) { 732 ploffset = ((LineArea)area.getParent()).getPlacementOffset(); 733 } 734 int y = this.currentYPosition + ploffset; 735 int w = area.getContentWidth(); 736 int h = area.getHeight(); 737 738 this.currentXPosition += w; 740 741 FopImage img = area.getImage(); 742 743 if (img == null) { 744 log.error("Error while loading image: area.getImage() is null"); 745 } else { 746 drawImageScaled(x, y, w, h, img, area.getFontState()); 747 } 748 } 749 750 751 756 781 782 787 public void renderWordArea(WordArea area) { 788 movetoCurrPosition(); 789 FontState fs = area.getFontState(); 790 String fontWeight = fs.getFontWeight(); 791 StringBuffer sb = new StringBuffer(); 792 String s = area.getText(); 793 int l = s.length(); 794 795 for (int i = 0; i < l; i++) { 796 char ch = s.charAt(i); 797 char mch = fs.mapChar(ch); 798 799 if (mch > 127) { 800 sb = sb.append("\\" + Integer.toOctalString(mch)); 801 } else { 802 final String escape = "\\()[]{}"; 803 if (escape.indexOf(mch) >= 0) { 804 sb.append("\\"); 805 } 806 sb = sb.append(mch); 807 } 808 } 809 810 String psString = null; 811 if (area.getFontState().getLetterSpacing() > 0) { 812 float f = area.getFontState().getLetterSpacing(); 814 psString = (new StringBuffer().append(f).append(" 0.0 (") 815 .append(sb.toString()).append(") A")).toString(); 816 } else { 817 psString = (new StringBuffer("(").append(sb.toString()) 818 .append(") t")).toString(); 819 } 820 821 822 824 useFont(fs.getFontName(), fs.getFontSize()); 826 useColor(area.getRed(), area.getGreen(), area.getBlue()); 827 if (area.getUnderlined() || area.getLineThrough() 828 || area.getOverlined()) 829 write("ULS"); 830 write(psString); 831 if (area.getUnderlined()) 832 write("ULE"); 833 if (area.getLineThrough()) 834 write("SOE"); 835 if (area.getOverlined()) 836 write("OLE"); 837 this.currentXPosition += area.getContentWidth(); 838 } 839 840 public void useFont(String name, int size) { 841 if ((currentFontName != name) || (currentFontSize != size)) { 842 write(name + " " + size + " F"); 843 currentFontName = name; 844 currentFontSize = size; 845 } 846 } 847 848 853 public void renderInlineSpace(InlineSpace space) { 854 if (space.getUnderlined() || space.getLineThrough() 856 || space.getOverlined()) { 857 movetoCurrPosition(); 859 write("ULS"); 860 861 write(space.getSize() + " 0 RM"); 862 863 if (space.getUnderlined()) 865 write("ULE"); 866 if (space.getLineThrough()) 867 write("SOE"); 868 if (space.getOverlined()) 869 write("OLE"); 870 } 871 this.currentXPosition += space.getSize(); 872 } 873 874 879 public void renderLineArea(LineArea area) { 880 int rx = this.currentAreaContainerXPosition + area.getStartIndent(); 881 int ry = this.currentYPosition; 882 int w = area.getContentWidth(); 883 int h = area.getHeight(); 884 885 this.currentYPosition -= area.getPlacementOffset(); 886 this.currentXPosition = rx; 887 888 int bl = this.currentYPosition; 889 movetoCurrPosition(); 891 892 String fontWeight = area.getFontState().getFontWeight(); 893 List children = area.getChildren(); 895 for (int i = 0; i < children.size(); i++) { 896 Box b = (Box)children.get(i); 897 this.currentYPosition = ry - area.getPlacementOffset(); 898 b.render(this); 899 } 900 902 this.currentYPosition = ry - h; 903 this.currentXPosition = rx; 904 } 905 906 911 public void renderPage(Page page) { 912 this.pagecount++; 913 this.idReferences = page.getIDReferences(); 914 915 write("%%Page: " + page.getNumber() + " " + this.pagecount); 916 917 final long pagewidth = page.getWidth(); 918 final long pageheight = page.getHeight(); 919 final double pspagewidth = pagewidth / 1000f; 920 final double pspageheight = pageheight / 1000f; 921 boolean rotate = false; 922 if (isAutoRotateLandscape() && (pageheight < pagewidth)) { 923 rotate = true; 924 write("%%PageBoundingBox: 0 0 " + 925 Math.round(pspageheight) + " " + 926 Math.round(pspagewidth)); 927 write("%%PageOrientation: Landscape"); 928 } else { 929 write("%%PageBoundingBox: 0 0 " + 930 Math.round(pspagewidth) + " " + 931 Math.round(pspageheight)); 932 if (isAutoRotateLandscape()) { 933 write("%%PageOrientation: Portrait"); 934 } 935 } 936 937 write("%%BeginPageSetup"); 938 if (rotate) { 939 write(Math.round(pspageheight) + " 0 translate"); 940 write("90 rotate"); 941 } 942 write("0.001 0.001 scale"); 943 write("%%EndPageSetup"); 944 renderRegions(page); 945 write("showpage"); 946 write("%%PageTrailer"); 947 write("%%EndPage"); } 949 950 955 public void renderLeaderArea(LeaderArea area) { 956 int rx = this.currentXPosition; 957 int ry = this.currentYPosition; 958 int w = area.getContentWidth(); 959 int th = area.getRuleThickness(); 960 int th2 = th / 2; 961 int th3 = th / 3; 962 int th4 = th / 4; 963 964 switch (area.getLeaderPattern()) { 965 case LeaderPattern.SPACE: 966 968 break; 969 case LeaderPattern.RULE: 970 if (area.getRuleStyle() == RuleStyle.NONE) 971 break; 972 useColor(area.getRed(), area.getGreen(), area.getBlue()); 973 write("gsave"); 974 write("0 setlinecap"); 975 switch (area.getRuleStyle()) { 976 case RuleStyle.DOTTED: 977 write("newpath"); 978 write("[1000 3000] 0 setdash"); 979 write(th + " setlinewidth"); 980 write(rx + " " + ry + " M"); 981 write(w + " 0 rlineto"); 982 useColor(area.getRed(), area.getGreen(), area.getBlue()); 983 write("stroke"); 984 break; 985 case RuleStyle.DASHED: 986 write("newpath"); 987 write("[3000 3000] 0 setdash"); 988 write(th + " setlinewidth"); 989 write(rx + " " + ry + " M"); 990 write(w + " 0 rlineto"); 991 useColor(area.getRed(), area.getGreen(), area.getBlue()); 992 write("stroke"); 993 break; 994 case RuleStyle.SOLID: 995 write("newpath"); 996 write(th + " setlinewidth"); 997 write(rx + " " + ry + " M"); 998 write(w + " 0 rlineto"); 999 useColor(area.getRed(), area.getGreen(), area.getBlue()); 1000 write("stroke"); 1001 break; 1002 case RuleStyle.DOUBLE: 1003 write("newpath"); 1004 write(th3 + " setlinewidth"); 1005 write(rx + " " + (ry - th3) + " M"); 1006 write(w + " 0 rlineto"); 1007 write(rx + " " + (ry + th3) + " M"); 1008 write(w + " 0 rlineto"); 1009 useColor(area.getRed(), area.getGreen(), area.getBlue()); 1010 write("stroke"); 1011 break; 1012 case RuleStyle.GROOVE: 1013 write(th2 + " setlinewidth"); 1014 write("newpath"); 1015 write(rx + " " + (ry - th4) + " M"); 1016 write(w + " 0 rlineto"); 1017 useColor(area.getRed(), area.getGreen(), area.getBlue()); 1018 write("stroke"); 1019 write("newpath"); 1020 write(rx + " " + (ry + th4) + " M"); 1021 write(w + " 0 rlineto"); 1022 useColor(1, 1, 1); write("stroke"); 1024 break; 1025 case RuleStyle.RIDGE: 1026 write(th2 + " setlinewidth"); 1027 write("newpath"); 1028 write(rx + " " + (ry - th4) + " M"); 1029 write(w + " 0 rlineto"); 1030 useColor(1, 1, 1); write("stroke"); 1032 write("newpath"); 1033 write(rx + " " + (ry + th4) + " M"); 1034 write(w + " 0 rlineto"); 1035 useColor(area.getRed(), area.getGreen(), area.getBlue()); 1036 write("stroke"); 1037 break; 1038 } 1039 write("grestore"); 1040 break; 1041 case LeaderPattern.DOTS: 1042 comment("% --- Leader dots NYI"); 1043 log.error("Leader dots: Not yet implemented"); 1044 break; 1045 case LeaderPattern.USECONTENT: 1046 comment("% --- Leader use-content NYI"); 1047 log.error("Leader use-content: Not yet implemented"); 1048 break; 1049 } 1050 this.currentXPosition += area.getContentWidth(); 1051 write(area.getContentWidth() + " 0 RM"); 1052 } 1053 1054 protected void doFrame(Area area) { 1055 int w, h; 1056 int rx = this.currentAreaContainerXPosition; 1057 w = area.getContentWidth(); 1058 BorderAndPadding bap = area.getBorderAndPadding(); 1059 1060 if (area instanceof BlockArea) 1061 rx += ((BlockArea)area).getStartIndent(); 1062 1063 h = area.getContentHeight(); 1064 int ry = this.currentYPosition; 1065 1066 rx = rx - area.getPaddingLeft(); 1067 ry = ry + area.getPaddingTop(); 1068 w = w + area.getPaddingLeft() + area.getPaddingRight(); 1069 h = h + area.getPaddingTop() + area.getPaddingBottom(); 1070 1071 rx = rx - area.getBorderLeftWidth(); 1072 ry = ry + area.getBorderTopWidth(); 1073 w = w + area.getBorderLeftWidth() + area.getBorderRightWidth(); 1074 h = h + area.getBorderTopWidth() + area.getBorderBottomWidth(); 1075 1076 doBackground(area, rx, ry, w, h); 1077 1078 if (area.getBorderTopWidth() != 0) { 1079 write("newpath"); 1080 write(rx + " " + ry + " M"); 1081 write(w + " 0 rlineto"); 1082 write(area.getBorderTopWidth() + " setlinewidth"); 1083 write("0 setlinecap"); 1084 useColor(bap.getBorderColor(BorderAndPadding.TOP)); 1085 write("stroke"); 1086 } 1087 if (area.getBorderLeftWidth() != 0) { 1088 write("newpath"); 1089 write(rx + " " + ry + " M"); 1090 write("0 " + (-h) + " rlineto"); 1091 write(area.getBorderLeftWidth() + " setlinewidth"); 1092 write("0 setlinecap"); 1093 useColor(bap.getBorderColor(BorderAndPadding.LEFT)); 1094 write("stroke"); 1095 } 1096 if (area.getBorderRightWidth() != 0) { 1097 write("newpath"); 1098 write((rx + w) + " " + ry + " M"); 1099 write("0 " + (-h) + " rlineto"); 1100 write(area.getBorderRightWidth() + " setlinewidth"); 1101 write("0 setlinecap"); 1102 useColor(bap.getBorderColor(BorderAndPadding.RIGHT)); 1103 write("stroke"); 1104 } 1105 if (area.getBorderBottomWidth() != 0) { 1106 write("newpath"); 1107 write(rx + " " + (ry - h) + " M"); 1108 write(w + " 0 rlineto"); 1109 write(area.getBorderBottomWidth() + " setlinewidth"); 1110 write("0 setlinecap"); 1111 useColor(bap.getBorderColor(BorderAndPadding.BOTTOM)); 1112 write("stroke"); 1113 } 1114 } 1115 1116 private void useColor(ColorType col) { 1117 useColor(col.red(), col.green(), col.blue()); 1118 } 1119 1120 private void useColor(float red, float green, float blue) { 1121 if ((red != currRed) || (green != currGreen) || (blue != currBlue)) { 1122 write(red + " " + green + " " + blue + " setrgbcolor"); 1123 currRed = red; 1124 currGreen = green; 1125 currBlue = blue; 1126 } 1127 } 1128 1129 1133 public void startRenderer(OutputStream outputStream) 1134 throws IOException { 1135 log.debug("rendering areas to PostScript"); 1136 1137 this.pagecount = 0; 1138 this.out = new PSStream(outputStream); 1139 write("%!PS-Adobe-3.0"); 1140 if (this.producer == null) { 1141 this.producer = org.apache.fop.apps.Version.getVersion(); 1142 } 1143 write("%%Creator: "+this.producer); 1144 write("%%Pages: (atend)"); 1145 write("%%DocumentProcessColors: Black"); 1146 write("%%DocumentSuppliedResources: procset FOPFonts"); 1147 write("%%EndComments"); 1148 write("%%BeginDefaults"); 1149 write("%%EndDefaults"); 1150 write("%%BeginProlog"); 1151 write("%%EndProlog"); 1152 write("%%BeginSetup"); 1153 writeProcs(); 1154 writeFontDict(fontInfo); 1155 1156 1157 write("%%BeginResource: procset EPSprocs"); 1158 write("%%Title: EPS encapsulation procs"); 1159 1160 write("/BeginEPSF { %def"); 1161 write("/b4_Inc_state save def % Save state for cleanup"); 1162 write("/dict_count countdictstack def % Count objects on dict stack"); 1163 write("/op_count count 1 sub def % Count objects on operand stack"); 1164 write("userdict begin % Push userdict on dict stack"); 1165 write("/showpage { } def % Redefine showpage, { } = null proc"); 1166 write("0 setgray 0 setlinecap % Prepare graphics state"); 1167 write("1 setlinewidth 0 setlinejoin"); 1168 write("10 setmiterlimit [ ] 0 setdash newpath"); 1169 write("/languagelevel where % If level not equal to 1 then"); 1170 write("{pop languagelevel % set strokeadjust and"); 1171 write("1 ne % overprint to their defaults."); 1172 write("{false setstrokeadjust false setoverprint"); 1173 write("} if"); 1174 write("} if"); 1175 write("} bind def"); 1176 1177 write("/EndEPSF { %def"); 1178 write("count op_count sub {pop} repeat % Clean up stacks"); 1179 write("countdictstack dict_count sub {end} repeat"); 1180 write("b4_Inc_state restore"); 1181 write("} bind def"); 1182 write("%%EndResource"); 1183 1184 write("FOPprocs begin"); 1185 write("FOPFonts begin"); 1186 1187 write("%%EndSetup"); 1188 } 1189 1190 1194 public void stopRenderer(OutputStream outputStream) 1195 throws IOException { 1196 write("%%Trailer"); 1197 write("%%Pages: "+this.pagecount); 1198 write("%%EOF"); 1199 this.out.flush(); 1200 log.debug("written out PostScript"); 1201 } 1202 1203 public void render(Page page, OutputStream outputStream) { 1204 this.renderPage(page); 1205 } 1206} 1207 | Popular Tags |