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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  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. /**
  23. * class representing a PDF Function.
  24. *
  25. * PDF Functions represent parameterized mathematical formulas and sampled representations with
  26. * arbitrary resolution. Functions are used in two areas: device-dependent
  27. * rasterization information for halftoning and transfer
  28. * functions, and color specification for smooth shading (a PDF 1.3 feature).
  29. *
  30. * All PDF Functions have a FunctionType (0,2,3, or 4), a Domain, and a Range.
  31. */
  32. public class PDFPattern extends PDFPathPaint {
  33. /**
  34. * The resources associated with this pattern
  35. */
  36. protected PDFResources resources = null;
  37. /**
  38. * Either one (1) for tiling, or two (2) for shading.
  39. */
  40. protected int patternType = 2; // Default
  41. /**
  42. * The name of the pattern such as "Pa1" or "Pattern1"
  43. */
  44. protected String patternName = null;
  45. /**
  46. * 1 for colored pattern, 2 for uncolored
  47. */
  48. protected int paintType = 2;
  49. /**
  50. * 1 for constant spacing, 2 for no distortion, and 3 for fast rendering
  51. */
  52. protected int tilingType = 1;
  53. /**
  54. * List of Doubles representing the Bounding box rectangle
  55. */
  56. protected List bBox = null;
  57. /**
  58. * Horizontal spacing
  59. */
  60. protected double xStep = -1;
  61. /**
  62. * Vertical spacing
  63. */
  64. protected double yStep = -1;
  65. /**
  66. * The Shading object comprising the Type 2 pattern
  67. */
  68. protected PDFShading shading = null;
  69. /**
  70. * List of Integers represetning the Extended unique Identifier
  71. */
  72. protected List xUID = null;
  73. /**
  74. * TODO use PDFGState
  75. * String representing the extended Graphics state.
  76. * Probably will never be used like this.
  77. */
  78. protected StringBuffer extGState = null;
  79. /**
  80. * List of Doubles representing the Transformation matrix.
  81. */
  82. protected List matrix = null;
  83. /**
  84. * The stream of a pattern
  85. */
  86. protected StringBuffer patternDataStream = null;
  87. /**
  88. * Create a tiling pattern (type 1).
  89. *
  90. * @param theResources the resources associated with this pattern
  91. * @param thePatternType the type of pattern, which is 1 for tiling.
  92. * @param thePaintType 1 or 2, colored or uncolored.
  93. * @param theTilingType 1, 2, or 3, constant spacing, no distortion, or faster tiling
  94. * @param theBBox List of Doubles: The pattern cell bounding box
  95. * @param theXStep horizontal spacing
  96. * @param theYStep vertical spacing
  97. * @param theMatrix Optional List of Doubles transformation matrix
  98. * @param theXUID Optional vector of Integers that uniquely identify the pattern
  99. * @param thePatternDataStream The stream of pattern data to be tiled.
  100. */
  101. public PDFPattern( // CSOK: ParameterNumber
  102. PDFResources theResources, int thePatternType, // 1
  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 theShading the PDF 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 theShading,
  131. List theXUID, StringBuffer theExtGState,
  132. List theMatrix) {
  133. super();
  134. this.patternType = 2; // thePatternType;
  135. this.shading = theShading;
  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(((Integer)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.getFilterList().addDefaultFilters(
  240. getDocument().getFilterMap(),
  241. PDFFilterList.CONTENT_FILTER);
  242. encodedStream = pdfStream.encodeStream();
  243. p.append(pdfStream.getFilterList().buildFilterDictEntries());
  244. p.append("/Length " + (encodedStream.getSize() + 1)
  245. + " \n");
  246. }
  247. } else {
  248. // if (this.patternType ==2)
  249. // Smooth Shading...
  250. if (this.shading != null) {
  251. p.append("/Shading " + this.shading.referencePDF() + " \n");
  252. }
  253. if (this.xUID != null) {
  254. vectorSize = this.xUID.size();
  255. p.append("/XUID [ ");
  256. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  257. p.append(((Integer)this.xUID.get(tempInt)) + " ");
  258. }
  259. p.append("] \n");
  260. }
  261. if (this.extGState != null) {
  262. p.append("/ExtGState " + this.extGState + " \n");
  263. }
  264. if (this.matrix != null) {
  265. vectorSize = this.matrix.size();
  266. p.append("/Matrix [ ");
  267. for (tempInt = 0; tempInt < vectorSize; tempInt++) {
  268. p.append(PDFNumber.doubleOut(
  269. ((Double)this.matrix.get(tempInt)).doubleValue(), 8));
  270. p.append(" ");
  271. }
  272. p.append("] \n");
  273. }
  274. } // end of if patterntype =1...else 2.
  275. p.append(">> \n");
  276. buffer = encode(p.toString());
  277. int length = buffer.length;
  278. stream.write(buffer);
  279. // stream representing the function
  280. if (pdfStream != null) {
  281. length += pdfStream.outputStreamData(encodedStream, stream);
  282. }
  283. return length;
  284. }
  285. /**
  286. * Output PDF bytes, not used.
  287. * @return returns null
  288. */
  289. public byte[] toPDF() { return null; }
  290. /** {@inheritDoc} */
  291. protected boolean contentEquals(PDFObject obj) {
  292. if (obj == null) {
  293. return false;
  294. }
  295. if (obj == this) {
  296. return true;
  297. }
  298. if (!(obj instanceof PDFPattern)) {
  299. return false;
  300. }
  301. PDFPattern patt = (PDFPattern)obj;
  302. if (patternType != patt.patternType) {
  303. return false;
  304. }
  305. if (paintType != patt.paintType) {
  306. return false;
  307. }
  308. if (tilingType != patt.tilingType) {
  309. return false;
  310. }
  311. if (xStep != patt.xStep) {
  312. return false;
  313. }
  314. if (yStep != patt.yStep) {
  315. return false;
  316. }
  317. if (bBox != null) {
  318. if (!bBox.equals(patt.bBox)) {
  319. return false;
  320. }
  321. } else if (patt.bBox != null) {
  322. return false;
  323. }
  324. if (bBox != null) {
  325. if (!bBox.equals(patt.bBox)) {
  326. return false;
  327. }
  328. } else if (patt.bBox != null) {
  329. return false;
  330. }
  331. if (xUID != null) {
  332. if (!xUID.equals(patt.xUID)) {
  333. return false;
  334. }
  335. } else if (patt.xUID != null) {
  336. return false;
  337. }
  338. if (extGState != null) {
  339. if (!extGState.equals(patt.extGState)) {
  340. return false;
  341. }
  342. } else if (patt.extGState != null) {
  343. return false;
  344. }
  345. if (matrix != null) {
  346. if (!matrix.equals(patt.matrix)) {
  347. return false;
  348. }
  349. } else if (patt.matrix != null) {
  350. return false;
  351. }
  352. if (resources != null) {
  353. if (!resources.equals(patt.resources)) {
  354. return false;
  355. }
  356. } else if (patt.resources != null) {
  357. return false;
  358. }
  359. if (shading != null) {
  360. if (!shading.equals(patt.shading)) {
  361. return false;
  362. }
  363. } else if (patt.shading != null) {
  364. return false;
  365. }
  366. if (patternDataStream != null) {
  367. if (!patternDataStream.equals(patt.patternDataStream)) {
  368. return false;
  369. }
  370. } else if (patt.patternDataStream != null) {
  371. return false;
  372. }
  373. return true;
  374. }
  375. }