You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

PCLDocumentHandler.java 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.render.pcl;
  19. import java.awt.Color;
  20. import java.awt.Dimension;
  21. import java.awt.Graphics2D;
  22. import java.awt.Rectangle;
  23. import java.awt.RenderingHints;
  24. import java.awt.image.BufferedImage;
  25. import java.io.IOException;
  26. import org.apache.commons.logging.Log;
  27. import org.apache.commons.logging.LogFactory;
  28. import org.apache.xmlgraphics.util.UnitConv;
  29. import org.apache.fop.apps.FopFactoryConfig;
  30. import org.apache.fop.apps.MimeConstants;
  31. import org.apache.fop.fonts.FontInfo;
  32. import org.apache.fop.render.intermediate.AbstractBinaryWritingIFDocumentHandler;
  33. import org.apache.fop.render.intermediate.IFContext;
  34. import org.apache.fop.render.intermediate.IFDocumentHandlerConfigurator;
  35. import org.apache.fop.render.intermediate.IFException;
  36. import org.apache.fop.render.intermediate.IFPainter;
  37. import org.apache.fop.render.java2d.Java2DPainter;
  38. import org.apache.fop.render.java2d.Java2DUtil;
  39. import org.apache.fop.render.pcl.PCLRendererConfig.PCLRendererConfigParser;
  40. import org.apache.fop.render.pcl.extensions.PCLElementMapping;
  41. /**
  42. * {@link org.apache.fop.render.intermediate.IFDocumentHandler} implementation
  43. * that produces PCL 5.
  44. */
  45. public class PCLDocumentHandler extends AbstractBinaryWritingIFDocumentHandler
  46. implements PCLConstants {
  47. /** logging instance */
  48. private static Log log = LogFactory.getLog(PCLDocumentHandler.class);
  49. /** Utility class for handling all sorts of peripheral tasks around PCL generation. */
  50. protected PCLRenderingUtil pclUtil;
  51. /** The PCL generator */
  52. private PCLGenerator gen;
  53. private PCLPageDefinition currentPageDefinition;
  54. /** contains the pageWith of the last printed page */
  55. private long pageWidth = 0;
  56. /** contains the pageHeight of the last printed page */
  57. private long pageHeight = 0;
  58. /** the current page image (only set when all-bitmap painting is activated) */
  59. private BufferedImage currentImage;
  60. /**
  61. * Default constructor.
  62. */
  63. public PCLDocumentHandler(IFContext context) {
  64. super(context);
  65. this.pclUtil = new PCLRenderingUtil(context.getUserAgent());
  66. }
  67. /** {@inheritDoc} */
  68. public boolean supportsPagesOutOfOrder() {
  69. return false;
  70. }
  71. /** {@inheritDoc} */
  72. public String getMimeType() {
  73. return MimeConstants.MIME_PCL;
  74. }
  75. /** {@inheritDoc} */
  76. public IFDocumentHandlerConfigurator getConfigurator() {
  77. return new PCLRendererConfigurator(getUserAgent(), new PCLRendererConfigParser());
  78. }
  79. /** {@inheritDoc} */
  80. @Override
  81. public void setDefaultFontInfo(FontInfo fontInfo) {
  82. FontInfo fi = Java2DUtil.buildDefaultJava2DBasedFontInfo(fontInfo, getUserAgent());
  83. setFontInfo(fi);
  84. }
  85. PCLRenderingUtil getPCLUtil() {
  86. return this.pclUtil;
  87. }
  88. PCLGenerator getPCLGenerator() {
  89. return this.gen;
  90. }
  91. /** @return the target resolution */
  92. protected int getResolution() {
  93. int resolution = Math.round(getUserAgent().getTargetResolution());
  94. if (resolution <= 300) {
  95. return 300;
  96. } else {
  97. return 600;
  98. }
  99. }
  100. //----------------------------------------------------------------------------------------------
  101. /** {@inheritDoc} */
  102. @Override
  103. public void startDocument() throws IFException {
  104. super.startDocument();
  105. try {
  106. this.gen = new PCLGenerator(this.outputStream, getResolution());
  107. this.gen.setDitheringQuality(pclUtil.getDitheringQuality());
  108. if (!pclUtil.isPJLDisabled()) {
  109. gen.universalEndOfLanguage();
  110. gen.writeText("@PJL COMMENT Produced by " + getUserAgent().getProducer() + "\n");
  111. if (getUserAgent().getTitle() != null) {
  112. gen.writeText("@PJL JOB NAME = \"" + getUserAgent().getTitle() + "\"\n");
  113. }
  114. gen.writeText("@PJL SET RESOLUTION = " + getResolution() + "\n");
  115. gen.writeText("@PJL ENTER LANGUAGE = PCL\n");
  116. }
  117. gen.resetPrinter();
  118. gen.setUnitOfMeasure(getResolution());
  119. gen.setRasterGraphicsResolution(getResolution());
  120. } catch (IOException e) {
  121. throw new IFException("I/O error in startDocument()", e);
  122. }
  123. }
  124. /** {@inheritDoc} */
  125. @Override
  126. public void endDocumentHeader() throws IFException {
  127. }
  128. /** {@inheritDoc} */
  129. @Override
  130. public void endDocument() throws IFException {
  131. try {
  132. gen.separateJobs();
  133. gen.resetPrinter();
  134. if (!pclUtil.isPJLDisabled()) {
  135. gen.universalEndOfLanguage();
  136. }
  137. } catch (IOException ioe) {
  138. throw new IFException("I/O error in endDocument()", ioe);
  139. }
  140. super.endDocument();
  141. }
  142. /** {@inheritDoc} */
  143. public void startPageSequence(String id) throws IFException {
  144. //nop
  145. }
  146. /** {@inheritDoc} */
  147. public void endPageSequence() throws IFException {
  148. //nop
  149. }
  150. /** {@inheritDoc} */
  151. public void startPage(int index, String name, String pageMasterName, Dimension size)
  152. throws IFException {
  153. try {
  154. //Paper source
  155. Object paperSource = getContext().getForeignAttribute(
  156. PCLElementMapping.PCL_PAPER_SOURCE);
  157. if (paperSource != null) {
  158. gen.selectPaperSource(Integer.parseInt(paperSource.toString()));
  159. }
  160. //Output bin
  161. Object outputBin = getContext().getForeignAttribute(
  162. PCLElementMapping.PCL_OUTPUT_BIN);
  163. if (outputBin != null) {
  164. gen.selectOutputBin(Integer.parseInt(outputBin.toString()));
  165. }
  166. // Is Page duplex?
  167. Object pageDuplex = getContext().getForeignAttribute(
  168. PCLElementMapping.PCL_DUPLEX_MODE);
  169. if (pageDuplex != null) {
  170. gen.selectDuplexMode(Integer.parseInt(pageDuplex.toString()));
  171. }
  172. //Page size
  173. final long pagewidth = size.width;
  174. final long pageheight = size.height;
  175. selectPageFormat(pagewidth, pageheight);
  176. } catch (IOException ioe) {
  177. throw new IFException("I/O error in startPage()", ioe);
  178. }
  179. }
  180. /** {@inheritDoc} */
  181. public IFPainter startPageContent() throws IFException {
  182. if (pclUtil.getRenderingMode() == PCLRenderingMode.BITMAP) {
  183. return createAllBitmapPainter();
  184. } else {
  185. return new PCLPainter(this, this.currentPageDefinition);
  186. }
  187. }
  188. private IFPainter createAllBitmapPainter() {
  189. double scale = gen.getMaximumBitmapResolution()
  190. / FopFactoryConfig.DEFAULT_TARGET_RESOLUTION;
  191. Rectangle printArea = this.currentPageDefinition.getLogicalPageRect();
  192. int bitmapWidth = (int)Math.ceil(
  193. UnitConv.mpt2px(printArea.width, gen.getMaximumBitmapResolution()));
  194. int bitmapHeight = (int)Math.ceil(
  195. UnitConv.mpt2px(printArea.height, gen.getMaximumBitmapResolution()));
  196. this.currentImage = createBufferedImage(bitmapWidth, bitmapHeight);
  197. Graphics2D graphics2D = this.currentImage.createGraphics();
  198. if (!PCLGenerator.isJAIAvailable()) {
  199. RenderingHints hints = new RenderingHints(null);
  200. //These hints don't seem to make a difference :-( Not seeing any dithering on Sun Java.
  201. hints.put(RenderingHints.KEY_DITHERING,
  202. RenderingHints.VALUE_DITHER_ENABLE);
  203. graphics2D.addRenderingHints(hints);
  204. }
  205. //Ensure white page background
  206. graphics2D.setBackground(Color.WHITE);
  207. graphics2D.clearRect(0, 0, bitmapWidth, bitmapHeight);
  208. graphics2D.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
  209. RenderingHints.VALUE_FRACTIONALMETRICS_ON);
  210. graphics2D.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
  211. RenderingHints.VALUE_STROKE_PURE);
  212. graphics2D.scale(scale / 1000f, scale / 1000f);
  213. graphics2D.translate(-printArea.x, -printArea.y);
  214. return new Java2DPainter(graphics2D, getContext(), getFontInfo());
  215. }
  216. private BufferedImage createBufferedImage(int bitmapWidth, int bitmapHeight) {
  217. int bitmapType;
  218. if (PCLGenerator.isJAIAvailable()) {
  219. //TYPE_BYTE_GRAY was used to work around the lack of dithering when using
  220. //TYPE_BYTE_BINARY. Adding RenderingHints didn't help.
  221. bitmapType = BufferedImage.TYPE_BYTE_GRAY;
  222. //bitmapType = BufferedImage.TYPE_INT_RGB; //Use to enable Batik gradients
  223. } else {
  224. bitmapType = BufferedImage.TYPE_BYTE_BINARY;
  225. }
  226. return new BufferedImage(
  227. bitmapWidth, bitmapHeight, bitmapType);
  228. }
  229. /** {@inheritDoc} */
  230. public void endPageContent() throws IFException {
  231. if (this.currentImage != null) {
  232. try {
  233. Rectangle printArea = this.currentPageDefinition.getLogicalPageRect();
  234. gen.setCursorPos(0, 0);
  235. gen.paintBitmap(this.currentImage, printArea.getSize(), true);
  236. } catch (IOException ioe) {
  237. throw new IFException("I/O error while encoding page image", ioe);
  238. } finally {
  239. this.currentImage = null;
  240. }
  241. }
  242. }
  243. /** {@inheritDoc} */
  244. public void endPage() throws IFException {
  245. try {
  246. //Eject page
  247. gen.formFeed();
  248. } catch (IOException ioe) {
  249. throw new IFException("I/O error in endPage()", ioe);
  250. }
  251. }
  252. /** {@inheritDoc} */
  253. public void handleExtensionObject(Object extension) throws IFException {
  254. if (false) {
  255. //TODO Handle extensions
  256. } else {
  257. log.debug("Don't know how to handle extension object. Ignoring: "
  258. + extension + " (" + extension.getClass().getName() + ")");
  259. }
  260. }
  261. private void selectPageFormat(long pagewidth, long pageheight) throws IOException {
  262. //Only set the page format if it changes (otherwise duplex printing won't work)
  263. if ((pagewidth != this.pageWidth) || (pageheight != this.pageHeight)) {
  264. this.pageWidth = pagewidth;
  265. this.pageHeight = pageheight;
  266. this.currentPageDefinition = PCLPageDefinition.getPageDefinition(
  267. pagewidth, pageheight, 1000);
  268. if (this.currentPageDefinition == null) {
  269. this.currentPageDefinition = PCLPageDefinition.getDefaultPageDefinition();
  270. log.warn("Paper type could not be determined. Falling back to: "
  271. + this.currentPageDefinition.getName());
  272. }
  273. if (log.isDebugEnabled()) {
  274. log.debug("page size: " + currentPageDefinition.getPhysicalPageSize());
  275. log.debug("logical page: " + currentPageDefinition.getLogicalPageRect());
  276. }
  277. if (this.currentPageDefinition.isLandscapeFormat()) {
  278. gen.writeCommand("&l1O"); //Landscape Orientation
  279. } else {
  280. gen.writeCommand("&l0O"); //Portrait Orientation
  281. }
  282. gen.selectPageSize(this.currentPageDefinition.getSelector());
  283. gen.clearHorizontalMargins();
  284. gen.setTopMargin(0);
  285. }
  286. }
  287. }