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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. /*
  2. * Copyright 1999-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /* $Id$ */
  17. package org.apache.fop.pdf;
  18. // Java
  19. import java.util.List;
  20. import java.util.ArrayList;
  21. /**
  22. * PDF Color object.
  23. * This is used to output color to a PDF content stream.
  24. */
  25. public class PDFColor extends PDFPathPaint {
  26. // could be 3.0 as well.
  27. private static double blackFactor = 2.0;
  28. private double red = -1.0;
  29. private double green = -1.0;
  30. private double blue = -1.0;
  31. private double cyan = -1.0;
  32. private double magenta = -1.0;
  33. private double yellow = -1.0;
  34. private double black = -1.0;
  35. /**
  36. * Create a PDF color with double values ranging from 0 to 1
  37. *
  38. * @param theRed the red double value
  39. * @param theGreen the green double value
  40. * @param theBlue the blue double value
  41. */
  42. public PDFColor(double theRed, double theGreen, double theBlue) {
  43. // super(theNumber);
  44. this.colorSpace = new PDFColorSpace(PDFColorSpace.DEVICE_RGB);
  45. this.red = theRed;
  46. this.green = theGreen;
  47. this.blue = theBlue;
  48. }
  49. /**
  50. * Create a PDF color with int values ranging from 0 to 255
  51. *
  52. * @param theRed the red integer value
  53. * @param theGreen the green integer value
  54. * @param theBlue the blue integer value
  55. */
  56. public PDFColor(int theRed, int theGreen, int theBlue) {
  57. this(((double)theRed) / 255d, ((double)theGreen) / 255d,
  58. ((double)theBlue) / 255d);
  59. }
  60. /**
  61. * Create a PDF color with CMYK values.
  62. *
  63. * @param theCyan the cyan value
  64. * @param theMagenta the magenta value
  65. * @param theYellow the yellow value
  66. * @param theBlack the black value
  67. */
  68. public PDFColor(double theCyan, double theMagenta, double theYellow,
  69. double theBlack) {
  70. // super(theNumber);//?
  71. this.colorSpace = new PDFColorSpace(PDFColorSpace.DEVICE_CMYK);
  72. this.cyan = theCyan;
  73. this.magenta = theMagenta;
  74. this.yellow = theYellow;
  75. this.black = theBlack;
  76. }
  77. /**
  78. * Return a vector representation of the color
  79. * in the appropriate colorspace.
  80. *
  81. * @return a list containing the Double values of the color
  82. */
  83. public List getVector() {
  84. List theColorVector = new ArrayList();
  85. if (this.colorSpace.getColorSpace() == PDFColorSpace.DEVICE_RGB) {
  86. // RGB
  87. theColorVector.add(new Double(this.red));
  88. theColorVector.add(new Double(this.green));
  89. theColorVector.add(new Double(this.blue));
  90. } else if (this.colorSpace.getColorSpace()
  91. == PDFColorSpace.DEVICE_CMYK) {
  92. // CMYK
  93. theColorVector.add(new Double(this.cyan));
  94. theColorVector.add(new Double(this.magenta));
  95. theColorVector.add(new Double(this.yellow));
  96. theColorVector.add(new Double(this.black));
  97. } else {
  98. // GRAY
  99. theColorVector.add(new Double(this.black));
  100. }
  101. return (theColorVector);
  102. }
  103. /**
  104. * Get the red component.
  105. *
  106. * @return the red double value
  107. */
  108. public double red() {
  109. return (this.red);
  110. }
  111. /**
  112. * Get the green component.
  113. *
  114. * @return the green double value
  115. */
  116. public double green() {
  117. return (this.green);
  118. }
  119. /**
  120. * Get the blue component.
  121. *
  122. * @return the blue double value
  123. */
  124. public double blue() {
  125. return (this.blue);
  126. }
  127. /**
  128. * Get the red integer component.
  129. *
  130. * @return the red integer value
  131. */
  132. public int red255() {
  133. return (int)(this.red * 255d);
  134. }
  135. /**
  136. * Get the green integer component.
  137. *
  138. * @return the green integer value
  139. */
  140. public int green255() {
  141. return (int)(this.green * 255d);
  142. }
  143. /**
  144. * Get the blue integer component.
  145. *
  146. * @return the blue integer value
  147. */
  148. public int blue255() {
  149. return (int)(this.blue * 255d);
  150. }
  151. /**
  152. * Get the cyan component.
  153. *
  154. * @return the cyan double value
  155. */
  156. public double cyan() {
  157. return (this.cyan);
  158. }
  159. /**
  160. * Get the magenta component.
  161. *
  162. * @return the magenta double value
  163. */
  164. public double magenta() {
  165. return (this.magenta);
  166. }
  167. /**
  168. * Get the yellow component.
  169. *
  170. * @return the yellow double value
  171. */
  172. public double yellow() {
  173. return (this.yellow);
  174. }
  175. /**
  176. * Get the black component.
  177. *
  178. * @return the black double value
  179. */
  180. public double black() {
  181. return (this.black);
  182. }
  183. /**
  184. * Set the color space for this color.
  185. * If the new color space is different the values are converted
  186. * to the new color space.
  187. *
  188. * @param theColorSpace the new color space
  189. */
  190. public void setColorSpace(int theColorSpace) {
  191. int theOldColorSpace = this.colorSpace.getColorSpace();
  192. if (theOldColorSpace != theColorSpace) {
  193. if (theOldColorSpace == PDFColorSpace.DEVICE_RGB) {
  194. if (theColorSpace == PDFColorSpace.DEVICE_CMYK) {
  195. this.convertRGBtoCMYK();
  196. } else {
  197. // convert to Gray?
  198. this.convertRGBtoGRAY();
  199. }
  200. } else if (theOldColorSpace == PDFColorSpace.DEVICE_CMYK) {
  201. if (theColorSpace == PDFColorSpace.DEVICE_RGB) {
  202. this.convertCMYKtoRGB();
  203. } else {
  204. // convert to Gray?
  205. this.convertCMYKtoGRAY();
  206. }
  207. } else {
  208. // used to be Gray
  209. if (theColorSpace == PDFColorSpace.DEVICE_RGB) {
  210. this.convertGRAYtoRGB();
  211. } else {
  212. // convert to CMYK?
  213. this.convertGRAYtoCMYK();
  214. }
  215. }
  216. this.colorSpace.setColorSpace(theColorSpace);
  217. }
  218. }
  219. /**
  220. * Get the PDF output string for this color.
  221. * This returns the string to be inserted into PDF for setting
  222. * the current color.
  223. *
  224. * @param fillNotStroke whether to return fill or stroke command
  225. * @return the PDF string for setting the fill/stroke color
  226. */
  227. public String getColorSpaceOut(boolean fillNotStroke) {
  228. StringBuffer p = new StringBuffer("");
  229. double tempDouble;
  230. if (this.colorSpace.getColorSpace()
  231. == PDFColorSpace.DEVICE_RGB) { // colorspace is RGB
  232. // according to pdfspec 12.1 p.399
  233. // if the colors are the same then just use the g or G operator
  234. boolean same = false;
  235. if (this.red == this.green && this.red == this.blue) {
  236. same = true;
  237. }
  238. // output RGB
  239. if (fillNotStroke) {
  240. // fill
  241. if (same) {
  242. p.append(PDFNumber.doubleOut(this.red) + " g\n");
  243. } else {
  244. p.append(PDFNumber.doubleOut(this.red) + " "
  245. + PDFNumber.doubleOut(this.green) + " "
  246. + PDFNumber.doubleOut(this.blue)
  247. + " rg\n");
  248. }
  249. } else {
  250. // stroke/border
  251. if (same) {
  252. p.append(PDFNumber.doubleOut(this.red) + " G\n");
  253. } else {
  254. p.append(PDFNumber.doubleOut(this.red) + " "
  255. + PDFNumber.doubleOut(this.green) + " "
  256. + PDFNumber.doubleOut(this.blue)
  257. + " RG\n");
  258. }
  259. }
  260. } else if (this.colorSpace.getColorSpace()
  261. == PDFColorSpace.DEVICE_CMYK) {
  262. // colorspace is CMYK
  263. if (fillNotStroke) {
  264. // fill
  265. p.append(PDFNumber.doubleOut(this.cyan) + " "
  266. + PDFNumber.doubleOut(this.magenta) + " "
  267. + PDFNumber.doubleOut(this.yellow) + " "
  268. + PDFNumber.doubleOut(this.black) + " k\n");
  269. } else {
  270. // stroke
  271. p.append(PDFNumber.doubleOut(this.cyan) + " "
  272. + PDFNumber.doubleOut(this.magenta) + " "
  273. + PDFNumber.doubleOut(this.yellow) + " "
  274. + PDFNumber.doubleOut(this.black) + " K\n");
  275. }
  276. } else {
  277. // means we're in DeviceGray or Unknown.
  278. // assume we're in DeviceGray, because otherwise we're screwed.
  279. if (fillNotStroke) {
  280. p.append(PDFNumber.doubleOut(this.black) + " g\n");
  281. } else {
  282. p.append(PDFNumber.doubleOut(this.black) + " G\n");
  283. }
  284. }
  285. return (p.toString());
  286. }
  287. /**
  288. * Convert the color from CMYK to RGB.
  289. */
  290. protected void convertCMYKtoRGB() {
  291. // convert CMYK to RGB
  292. this.red = 1.0 - this.cyan;
  293. this.green = 1.0 - this.green;
  294. this.blue = 1.0 - this.yellow;
  295. this.red = (this.black / PDFColor.blackFactor) + this.red;
  296. this.green = (this.black / PDFColor.blackFactor) + this.green;
  297. this.blue = (this.black / PDFColor.blackFactor) + this.blue;
  298. }
  299. /**
  300. * Convert the color from RGB to CMYK.
  301. */
  302. protected void convertRGBtoCMYK() {
  303. // convert RGB to CMYK
  304. this.cyan = 1.0 - this.red;
  305. this.magenta = 1.0 - this.green;
  306. this.yellow = 1.0 - this.blue;
  307. this.black = 0.0;
  308. /*
  309. * If you want to calculate black, uncomment this
  310. * //pick the lowest color
  311. * tempDouble = this.red;
  312. *
  313. * if (this.green < tempDouble)
  314. * tempDouble = this.green;
  315. *
  316. * if (this.blue < tempDouble)
  317. * tempDouble = this.blue;
  318. *
  319. * this.black = tempDouble / this.blackFactor;
  320. */
  321. }
  322. /**
  323. * Convert the color from Gray to RGB.
  324. */
  325. protected void convertGRAYtoRGB() {
  326. this.red = 1.0 - this.black;
  327. this.green = 1.0 - this.black;
  328. this.blue = 1.0 - this.black;
  329. }
  330. /**
  331. * Convert the color from Gray to CMYK.
  332. */
  333. protected void convertGRAYtoCMYK() {
  334. this.cyan = this.black;
  335. this.magenta = this.black;
  336. this.yellow = this.black;
  337. // this.black=0.0;//?
  338. }
  339. /**
  340. * Convert the color from CMYK to Gray.
  341. */
  342. protected void convertCMYKtoGRAY() {
  343. double tempDouble = 0.0;
  344. // pick the lowest color
  345. tempDouble = this.cyan;
  346. if (this.magenta < tempDouble) {
  347. tempDouble = this.magenta;
  348. }
  349. if (this.yellow < tempDouble) {
  350. tempDouble = this.yellow;
  351. }
  352. this.black = (tempDouble / PDFColor.blackFactor);
  353. }
  354. /**
  355. * Convert the color from RGB to Gray.
  356. */
  357. protected void convertRGBtoGRAY() {
  358. double tempDouble = 0.0;
  359. // pick the lowest color
  360. tempDouble = this.red;
  361. if (this.green < tempDouble) {
  362. tempDouble = this.green;
  363. }
  364. if (this.blue < tempDouble) {
  365. tempDouble = this.blue;
  366. }
  367. this.black = 1.0 - (tempDouble / PDFColor.blackFactor);
  368. }
  369. /**
  370. * Create pdf.
  371. * Not used for this object.
  372. *
  373. * @return the bytes for the pdf
  374. */
  375. public byte[] toPDF() {
  376. return (new byte[0]);
  377. }
  378. /**
  379. * Check for equality of color with another object.
  380. *
  381. * @param obj the object to compare
  382. * @return true if colors are equal
  383. */
  384. public boolean equals(Object obj) {
  385. if (!(obj instanceof PDFColor)) {
  386. return false;
  387. }
  388. PDFColor color = (PDFColor)obj;
  389. if (color.red == this.red && color.green == this.green
  390. && color.blue == this.blue) {
  391. return true;
  392. }
  393. return false;
  394. }
  395. }