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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427
  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. // Java
  20. import java.util.List;
  21. import java.io.OutputStream;
  22. import java.io.IOException;
  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 {
  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( // CSOK: ParameterNumber
  103. PDFResources theResources, int thePatternType, // 1
  104. int thePaintType, int theTilingType, List theBBox,
  105. double theXStep, double theYStep,
  106. List theMatrix, List theXUID,
  107. StringBuffer thePatternDataStream) {
  108. super();
  109. this.resources = theResources;
  110. // This next parameter is implicit to all constructors, and is
  111. // not directly passed.
  112. this.patternType = 1; // thePatternType;
  113. this.paintType = thePaintType;
  114. this.tilingType = theTilingType;
  115. this.bBox = theBBox;
  116. this.xStep = theXStep;
  117. this.yStep = theYStep;
  118. this.matrix = theMatrix;
  119. this.xUID = theXUID;
  120. this.patternDataStream = thePatternDataStream;
  121. }
  122. /**
  123. * Create a type 2 pattern (smooth shading)
  124. *
  125. * @param thePatternType the type of the pattern, which is 2, smooth shading
  126. * @param theShading the PDF Shading object that comprises this pattern
  127. * @param theXUID optional:the extended unique Identifier if used.
  128. * @param theExtGState optional: the extended graphics state, if used.
  129. * @param theMatrix Optional:List of Doubles that specify the matrix.
  130. */
  131. public PDFPattern(int thePatternType, PDFShading theShading,
  132. List theXUID, StringBuffer theExtGState,
  133. List theMatrix) {
  134. super();
  135. this.patternType = 2; // thePatternType;
  136. this.shading = theShading;
  137. this.xUID = theXUID;
  138. // this isn't really implemented, so it should always be null.
  139. // I just don't want to have to add a new parameter once it is implemented.
  140. this.extGState = theExtGState; // always null
  141. this.matrix = theMatrix;
  142. }
  143. /**
  144. * Get the name of the pattern
  145. *
  146. * @return String representing the name of the pattern.
  147. */
  148. public String getName() {
  149. return (this.patternName);
  150. }
  151. /**
  152. * Sets the name of the pattern.
  153. * @param name the name of the pattern. Can be anything
  154. * without spaces. "Pattern1" or "Pa1" are good examples.
  155. */
  156. public void setName(String name) {
  157. if (name.indexOf(" ") >= 0) {
  158. throw new IllegalArgumentException(
  159. "Pattern name must not contain any spaces");
  160. }
  161. this.patternName = name;
  162. }
  163. /**
  164. * Get the PDF command for setting to this pattern.
  165. *
  166. * @param fillNotStroke if true fill otherwise stroke
  167. * @return the PDF string for setting the pattern
  168. */
  169. public String getColorSpaceOut(boolean fillNotStroke) {
  170. if (fillNotStroke) { // fill but no stroke
  171. return ("/Pattern cs /" + this.getName() + " scn \n");
  172. } else { // stroke (or border)
  173. return ("/Pattern CS /" + this.getName() + " SCN \n");
  174. }
  175. }
  176. /**
  177. * represent as PDF. Whatever the FunctionType is, the correct
  178. * representation spits out. The sets of required and optional
  179. * attributes are different for each type, but if a required
  180. * attribute's object was constructed as null, then no error
  181. * is raised. Instead, the malformed PDF that was requested
  182. * by the construction is dutifully output.
  183. * This policy should be reviewed.
  184. *
  185. * @param stream the stream to write to
  186. * @throws IOException if there is an error writing to the stream
  187. * @return the PDF string.
  188. */
  189. protected int output(OutputStream stream) throws IOException {
  190. int vectorSize = 0;
  191. int tempInt = 0;
  192. byte[] buffer;
  193. StringBuffer p = new StringBuffer(64);
  194. p.append(getObjectID());
  195. p.append("<< \n/Type /Pattern \n");
  196. if (this.resources != null) {
  197. p.append("/Resources " + this.resources.referencePDF() + " \n");
  198. }
  199. p.append("/PatternType " + this.patternType + " \n");
  200. PDFStream pdfStream = null;
  201. StreamCache encodedStream = null;
  202. if (this.patternType == 1) {
  203. p.append("/PaintType " + this.paintType + " \n");
  204. p.append("/TilingType " + this.tilingType + " \n");
  205. if (this.bBox != null) {
  206. vectorSize = this.bBox.size();
  207. p.append("/BBox [ ");
  208. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  209. p.append(PDFNumber.doubleOut((Double)this.bBox.get(tempInt)));
  210. p.append(" ");
  211. }
  212. p.append("] \n");
  213. }
  214. p.append("/XStep " + PDFNumber.doubleOut(new Double(this.xStep))
  215. + " \n");
  216. p.append("/YStep " + PDFNumber.doubleOut(new Double(this.yStep))
  217. + " \n");
  218. if (this.matrix != null) {
  219. vectorSize = this.matrix.size();
  220. p.append("/Matrix [ ");
  221. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  222. p.append(PDFNumber.doubleOut(
  223. ((Double)this.matrix.get(tempInt)).doubleValue(), 8));
  224. p.append(" ");
  225. }
  226. p.append("] \n");
  227. }
  228. if (this.xUID != null) {
  229. vectorSize = this.xUID.size();
  230. p.append("/XUID [ ");
  231. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  232. p.append(((Integer)this.xUID.get(tempInt)) + " ");
  233. }
  234. p.append("] \n");
  235. }
  236. // don't forget the length of the stream.
  237. if (this.patternDataStream != null) {
  238. pdfStream = new PDFStream();
  239. pdfStream.setDocument(getDocumentSafely());
  240. pdfStream.add(this.patternDataStream.toString());
  241. pdfStream.getFilterList().addDefaultFilters(
  242. getDocument().getFilterMap(),
  243. PDFFilterList.CONTENT_FILTER);
  244. encodedStream = pdfStream.encodeStream();
  245. p.append(pdfStream.getFilterList().buildFilterDictEntries());
  246. p.append("/Length " + (encodedStream.getSize() + 1)
  247. + " \n");
  248. }
  249. } else {
  250. // if (this.patternType ==2)
  251. // Smooth Shading...
  252. if (this.shading != null) {
  253. p.append("/Shading " + this.shading.referencePDF() + " \n");
  254. }
  255. if (this.xUID != null) {
  256. vectorSize = this.xUID.size();
  257. p.append("/XUID [ ");
  258. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  259. p.append(((Integer)this.xUID.get(tempInt)) + " ");
  260. }
  261. p.append("] \n");
  262. }
  263. if (this.extGState != null) {
  264. p.append("/ExtGState " + this.extGState + " \n");
  265. }
  266. if (this.matrix != null) {
  267. vectorSize = this.matrix.size();
  268. p.append("/Matrix [ ");
  269. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  270. p.append(PDFNumber.doubleOut(
  271. ((Double)this.matrix.get(tempInt)).doubleValue(), 8));
  272. p.append(" ");
  273. }
  274. p.append("] \n");
  275. }
  276. } // end of if patterntype =1...else 2.
  277. p.append(">> \n");
  278. buffer = encode(p.toString());
  279. int length = buffer.length;
  280. stream.write(buffer);
  281. // stream representing the function
  282. if (pdfStream != null) {
  283. length += pdfStream.outputStreamData(encodedStream, stream);
  284. }
  285. buffer = encode("\nendobj\n");
  286. stream.write(buffer);
  287. length += buffer.length;
  288. return length;
  289. }
  290. /**
  291. * Output PDF bytes, not used.
  292. * @return returns null
  293. */
  294. public byte[] toPDF() { return null; }
  295. /** {@inheritDoc} */
  296. protected boolean contentEquals(PDFObject obj) {
  297. if (obj == null) {
  298. return false;
  299. }
  300. if (obj == this) {
  301. return true;
  302. }
  303. if (!(obj instanceof PDFPattern)) {
  304. return false;
  305. }
  306. PDFPattern patt = (PDFPattern)obj;
  307. if (patternType != patt.patternType) {
  308. return false;
  309. }
  310. if (paintType != patt.paintType) {
  311. return false;
  312. }
  313. if (tilingType != patt.tilingType) {
  314. return false;
  315. }
  316. if (xStep != patt.xStep) {
  317. return false;
  318. }
  319. if (yStep != patt.yStep) {
  320. return false;
  321. }
  322. if (bBox != null) {
  323. if (!bBox.equals(patt.bBox)) {
  324. return false;
  325. }
  326. } else if (patt.bBox != null) {
  327. return false;
  328. }
  329. if (bBox != null) {
  330. if (!bBox.equals(patt.bBox)) {
  331. return false;
  332. }
  333. } else if (patt.bBox != null) {
  334. return false;
  335. }
  336. if (xUID != null) {
  337. if (!xUID.equals(patt.xUID)) {
  338. return false;
  339. }
  340. } else if (patt.xUID != null) {
  341. return false;
  342. }
  343. if (extGState != null) {
  344. if (!extGState.equals(patt.extGState)) {
  345. return false;
  346. }
  347. } else if (patt.extGState != null) {
  348. return false;
  349. }
  350. if (matrix != null) {
  351. if (!matrix.equals(patt.matrix)) {
  352. return false;
  353. }
  354. } else if (patt.matrix != null) {
  355. return false;
  356. }
  357. if (resources != null) {
  358. if (!resources.equals(patt.resources)) {
  359. return false;
  360. }
  361. } else if (patt.resources != null) {
  362. return false;
  363. }
  364. if (shading != null) {
  365. if (!shading.equals(patt.shading)) {
  366. return false;
  367. }
  368. } else if (patt.shading != null) {
  369. return false;
  370. }
  371. if (patternDataStream != null) {
  372. if (!patternDataStream.equals(patt.patternDataStream)) {
  373. return false;
  374. }
  375. } else if (patt.patternDataStream != null) {
  376. return false;
  377. }
  378. return true;
  379. }
  380. }