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.

PDFPattern.java 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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.pdf;
  19. import java.io.IOException;
  20. import java.io.OutputStream;
  21. import java.util.List;
  22. import org.apache.fop.render.shading.Pattern;
  23. /**
  24. * class representing a PDF Function.
  25. *
  26. * PDF Functions represent parameterized mathematical formulas and sampled representations with
  27. * arbitrary resolution. Functions are used in two areas: device-dependent
  28. * rasterization information for halftoning and transfer
  29. * functions, and color specification for smooth shading (a PDF 1.3 feature).
  30. *
  31. * All PDF Functions have a FunctionType (0,2,3, or 4), a Domain, and a Range.
  32. */
  33. public class PDFPattern extends PDFPathPaint implements Pattern {
  34. /**
  35. * The resources associated with this pattern
  36. */
  37. protected PDFResources resources = null;
  38. /**
  39. * Either one (1) for tiling, or two (2) for shading.
  40. */
  41. protected int patternType = 2; // Default
  42. /**
  43. * The name of the pattern such as "Pa1" or "Pattern1"
  44. */
  45. protected String patternName = null;
  46. /**
  47. * 1 for colored pattern, 2 for uncolored
  48. */
  49. protected int paintType = 2;
  50. /**
  51. * 1 for constant spacing, 2 for no distortion, and 3 for fast rendering
  52. */
  53. protected int tilingType = 1;
  54. /**
  55. * List of Doubles representing the Bounding box rectangle
  56. */
  57. protected List bBox = null;
  58. /**
  59. * Horizontal spacing
  60. */
  61. protected double xStep = -1;
  62. /**
  63. * Vertical spacing
  64. */
  65. protected double yStep = -1;
  66. /**
  67. * The Shading object comprising the Type 2 pattern
  68. */
  69. protected PDFShading shading = null;
  70. /**
  71. * List of Integers represetning the Extended unique Identifier
  72. */
  73. protected List xUID = null;
  74. /**
  75. * TODO use PDFGState
  76. * String representing the extended Graphics state.
  77. * Probably will never be used like this.
  78. */
  79. protected StringBuffer extGState = null;
  80. /**
  81. * List of Doubles representing the Transformation matrix.
  82. */
  83. protected List matrix = null;
  84. /**
  85. * The stream of a pattern
  86. */
  87. protected StringBuffer patternDataStream = null;
  88. /**
  89. * Create a tiling pattern (type 1).
  90. *
  91. * @param theResources the resources associated with this pattern
  92. * @param thePatternType the type of pattern, which is 1 for tiling.
  93. * @param thePaintType 1 or 2, colored or uncolored.
  94. * @param theTilingType 1, 2, or 3, constant spacing, no distortion, or faster tiling
  95. * @param theBBox List of Doubles: The pattern cell bounding box
  96. * @param theXStep horizontal spacing
  97. * @param theYStep vertical spacing
  98. * @param theMatrix Optional List of Doubles transformation matrix
  99. * @param theXUID Optional vector of Integers that uniquely identify the pattern
  100. * @param thePatternDataStream The stream of pattern data to be tiled.
  101. */
  102. public PDFPattern(PDFResources theResources, int thePatternType,
  103. int thePaintType, int theTilingType, List theBBox,
  104. double theXStep, double theYStep,
  105. List theMatrix, List theXUID,
  106. StringBuffer thePatternDataStream) {
  107. super();
  108. this.resources = theResources;
  109. // This next parameter is implicit to all constructors, and is
  110. // not directly passed.
  111. this.patternType = 1; // thePatternType;
  112. this.paintType = thePaintType;
  113. this.tilingType = theTilingType;
  114. this.bBox = theBBox;
  115. this.xStep = theXStep;
  116. this.yStep = theYStep;
  117. this.matrix = theMatrix;
  118. this.xUID = theXUID;
  119. this.patternDataStream = thePatternDataStream;
  120. }
  121. /**
  122. * Create a type 2 pattern (smooth shading)
  123. *
  124. * @param thePatternType the type of the pattern, which is 2, smooth shading
  125. * @param shading the Shading object that comprises this pattern
  126. * @param theXUID optional:the extended unique Identifier if used.
  127. * @param theExtGState optional: the extended graphics state, if used.
  128. * @param theMatrix Optional:List of Doubles that specify the matrix.
  129. */
  130. public PDFPattern(int thePatternType, PDFShading shading,
  131. List theXUID, StringBuffer theExtGState,
  132. List theMatrix) {
  133. super();
  134. this.patternType = 2; // thePatternType;
  135. this.shading = shading;
  136. this.xUID = theXUID;
  137. // this isn't really implemented, so it should always be null.
  138. // I just don't want to have to add a new parameter once it is implemented.
  139. this.extGState = theExtGState; // always null
  140. this.matrix = theMatrix;
  141. }
  142. /**
  143. * Get the name of the pattern
  144. *
  145. * @return String representing the name of the pattern.
  146. */
  147. public String getName() {
  148. return (this.patternName);
  149. }
  150. /**
  151. * Sets the name of the pattern.
  152. * @param name the name of the pattern. Can be anything
  153. * without spaces. "Pattern1" or "Pa1" are good examples.
  154. */
  155. public void setName(String name) {
  156. if (name.indexOf(" ") >= 0) {
  157. throw new IllegalArgumentException(
  158. "Pattern name must not contain any spaces");
  159. }
  160. this.patternName = name;
  161. }
  162. /**
  163. * Get the PDF command for setting to this pattern.
  164. *
  165. * @param fillNotStroke if true fill otherwise stroke
  166. * @return the PDF string for setting the pattern
  167. */
  168. public String getColorSpaceOut(boolean fillNotStroke) {
  169. if (fillNotStroke) { // fill but no stroke
  170. return ("/Pattern cs /" + this.getName() + " scn \n");
  171. } else { // stroke (or border)
  172. return ("/Pattern CS /" + this.getName() + " SCN \n");
  173. }
  174. }
  175. /**
  176. * represent as PDF. Whatever the FunctionType is, the correct
  177. * representation spits out. The sets of required and optional
  178. * attributes are different for each type, but if a required
  179. * attribute's object was constructed as null, then no error
  180. * is raised. Instead, the malformed PDF that was requested
  181. * by the construction is dutifully output.
  182. * This policy should be reviewed.
  183. *
  184. * @param stream the stream to write to
  185. * @throws IOException if there is an error writing to the stream
  186. * @return the PDF string.
  187. */
  188. public int output(OutputStream stream) throws IOException {
  189. int vectorSize = 0;
  190. int tempInt = 0;
  191. byte[] buffer;
  192. StringBuffer p = new StringBuffer(64);
  193. p.append("<< \n/Type /Pattern \n");
  194. if (this.resources != null) {
  195. p.append("/Resources " + this.resources.referencePDF() + " \n");
  196. }
  197. p.append("/PatternType " + this.patternType + " \n");
  198. PDFStream pdfStream = null;
  199. StreamCache encodedStream = null;
  200. if (this.patternType == 1) {
  201. p.append("/PaintType " + this.paintType + " \n");
  202. p.append("/TilingType " + this.tilingType + " \n");
  203. if (this.bBox != null) {
  204. vectorSize = this.bBox.size();
  205. p.append("/BBox [ ");
  206. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  207. p.append(PDFNumber.doubleOut((Double)this.bBox.get(tempInt)));
  208. p.append(" ");
  209. }
  210. p.append("] \n");
  211. }
  212. p.append("/XStep " + PDFNumber.doubleOut(new Double(this.xStep))
  213. + " \n");
  214. p.append("/YStep " + PDFNumber.doubleOut(new Double(this.yStep))
  215. + " \n");
  216. if (this.matrix != null) {
  217. vectorSize = this.matrix.size();
  218. p.append("/Matrix [ ");
  219. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  220. p.append(PDFNumber.doubleOut(
  221. ((Double)this.matrix.get(tempInt)).doubleValue(), 8));
  222. p.append(" ");
  223. }
  224. p.append("] \n");
  225. }
  226. if (this.xUID != null) {
  227. vectorSize = this.xUID.size();
  228. p.append("/XUID [ ");
  229. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  230. p.append((this.xUID.get(tempInt)) + " ");
  231. }
  232. p.append("] \n");
  233. }
  234. // don't forget the length of the stream.
  235. if (this.patternDataStream != null) {
  236. pdfStream = new PDFStream();
  237. pdfStream.setDocument(getDocumentSafely());
  238. pdfStream.add(this.patternDataStream.toString());
  239. pdfStream.setObjectNumber(getObjectNumber());
  240. pdfStream.getFilterList().addDefaultFilters(
  241. getDocument().getFilterMap(),
  242. PDFFilterList.CONTENT_FILTER);
  243. getDocument().applyEncryption(pdfStream);
  244. encodedStream = pdfStream.encodeStream();
  245. p.append(pdfStream.getFilterList().buildFilterDictEntries());
  246. p.append("/Length " + encodedStream.getSize() + " \n");
  247. }
  248. } else {
  249. // if (this.patternType ==2)
  250. // Smooth Shading...
  251. if (this.shading != null) {
  252. p.append("/Shading " + this.shading.referencePDF() + " \n");
  253. }
  254. if (this.xUID != null) {
  255. vectorSize = this.xUID.size();
  256. p.append("/XUID [ ");
  257. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  258. p.append((this.xUID.get(tempInt)) + " ");
  259. }
  260. p.append("] \n");
  261. }
  262. if (this.extGState != null) {
  263. p.append("/ExtGState " + this.extGState + " \n");
  264. }
  265. if (this.matrix != null) {
  266. vectorSize = this.matrix.size();
  267. p.append("/Matrix [ ");
  268. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  269. p.append(PDFNumber.doubleOut(
  270. ((Double)this.matrix.get(tempInt)).doubleValue(), 8));
  271. p.append(" ");
  272. }
  273. p.append("] \n");
  274. }
  275. } // end of if patterntype =1...else 2.
  276. p.append(">> \n");
  277. buffer = encode(p.toString());
  278. int length = buffer.length;
  279. stream.write(buffer);
  280. // stream representing the function
  281. if (pdfStream != null) {
  282. length += pdfStream.outputStreamData(encodedStream, stream);
  283. }
  284. return length;
  285. }
  286. /**
  287. * Output PDF bytes, not used.
  288. * @return returns null
  289. */
  290. public byte[] toPDF() { return null; }
  291. /** {@inheritDoc} */
  292. protected boolean contentEquals(PDFObject obj) {
  293. if (obj == null) {
  294. return false;
  295. }
  296. if (obj == this) {
  297. return true;
  298. }
  299. if (!(obj instanceof PDFPattern)) {
  300. return false;
  301. }
  302. PDFPattern patt = (PDFPattern)obj;
  303. if (patternType != patt.patternType) {
  304. return false;
  305. }
  306. if (paintType != patt.paintType) {
  307. return false;
  308. }
  309. if (tilingType != patt.tilingType) {
  310. return false;
  311. }
  312. if (xStep != patt.xStep) {
  313. return false;
  314. }
  315. if (yStep != patt.yStep) {
  316. return false;
  317. }
  318. if (bBox != null) {
  319. if (!bBox.equals(patt.bBox)) {
  320. return false;
  321. }
  322. } else if (patt.bBox != null) {
  323. return false;
  324. }
  325. if (bBox != null) {
  326. if (!bBox.equals(patt.bBox)) {
  327. return false;
  328. }
  329. } else if (patt.bBox != null) {
  330. return false;
  331. }
  332. if (xUID != null) {
  333. if (!xUID.equals(patt.xUID)) {
  334. return false;
  335. }
  336. } else if (patt.xUID != null) {
  337. return false;
  338. }
  339. if (extGState != null) {
  340. if (!extGState.equals(patt.extGState)) {
  341. return false;
  342. }
  343. } else if (patt.extGState != null) {
  344. return false;
  345. }
  346. if (matrix != null) {
  347. if (!matrix.equals(patt.matrix)) {
  348. return false;
  349. }
  350. } else if (patt.matrix != null) {
  351. return false;
  352. }
  353. if (resources != null) {
  354. if (!resources.equals(patt.resources)) {
  355. return false;
  356. }
  357. } else if (patt.resources != null) {
  358. return false;
  359. }
  360. if (shading != null) {
  361. if (!shading.equals(patt.shading)) {
  362. return false;
  363. }
  364. } else if (patt.shading != null) {
  365. return false;
  366. }
  367. if (patternDataStream != null) {
  368. if (!patternDataStream.equals(patt.patternDataStream)) {
  369. return false;
  370. }
  371. } else if (patt.patternDataStream != null) {
  372. return false;
  373. }
  374. return true;
  375. }
  376. }