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.

Shading.java 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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. package org.apache.fop.render.gradient;
  18. import java.util.Arrays;
  19. import java.util.List;
  20. import org.apache.fop.pdf.PDFDeviceColorSpace;
  21. import org.apache.fop.render.gradient.GradientMaker.DoubleFormatter;
  22. public class Shading {
  23. public interface FunctionRenderer {
  24. void outputFunction(StringBuilder out);
  25. }
  26. /**
  27. * Required: The Type of shading (1,2,3,4,5,6,7)
  28. */
  29. private final int shadingType;
  30. /**
  31. * A ColorSpace representing the colorspace. "DeviceRGB" is an example.
  32. */
  33. private final PDFDeviceColorSpace colorSpace;
  34. /**
  35. * Required for Type 2: An Array of four numbers specifying
  36. * the starting and ending coordinate pairs
  37. * Required for Type 3: An Array of six numbers [x0,y0,r0,x1,y1,r1]
  38. * specifying the centers and radii of
  39. * the starting and ending circles.
  40. */
  41. private final List<Double> coords;
  42. /**
  43. * Required for Type 1, 2, and 3:
  44. * The object of the color mapping function (usually type 2 or 3).
  45. * Optional for Type 4,5,6, and 7: When it's nearly the same thing.
  46. */
  47. private final Function function;
  48. /**
  49. * Required for Type 2+3: An Array of two boolean values specifying
  50. * whether to extend the start and end colors past the start
  51. * and end points, respectively.
  52. * Default is false, false.
  53. */
  54. private final List<Boolean> extend;
  55. /**
  56. * Required for Type 4,5,6, and 7: Specifies the number of bits used
  57. * to represent each vertex coordinate.
  58. * Allowed to be 1,2,4,8,12,16,24, or 32.
  59. */
  60. private final int bitsPerCoordinate;
  61. /**
  62. * Required for Type 4,5,6, and 7: Specifies the number of bits used
  63. * to represent the edge flag for each vertex.
  64. * Allowed to be 2,4,or 8, while the Edge flag itself is allowed to
  65. * be 0,1 or 2.
  66. */
  67. private final int bitsPerFlag;
  68. /**
  69. * Optional: A flag whether or not to filter the shading function
  70. * to prevent aliasing artifacts. Default is false.
  71. */
  72. private final boolean antiAlias;
  73. /**
  74. * Required for Type 4,5,6, and 7: Specifies the number of bits used
  75. * to represent each color coordinate.
  76. * Allowed to be 1,2,4,8,12, or 16
  77. */
  78. private final int bitsPerComponent;
  79. /**
  80. * Required for Type 5:The number of vertices in each "row" of
  81. * the lattice; it must be greater than or equal to 2.
  82. */
  83. private final int verticesPerRow;
  84. public Shading(int shadingType, PDFDeviceColorSpace colorSpace,
  85. List<Double> coords, Function function) {
  86. this.shadingType = shadingType;
  87. this.colorSpace = colorSpace;
  88. this.antiAlias = false;
  89. this.coords = coords;
  90. this.function = function;
  91. this.extend = Arrays.asList(true, true);
  92. this.bitsPerCoordinate = 0;
  93. this.bitsPerFlag = 0;
  94. this.bitsPerComponent = 0;
  95. this.verticesPerRow = 0;
  96. }
  97. public int getShadingType() {
  98. return shadingType;
  99. }
  100. public PDFDeviceColorSpace getColorSpace() {
  101. return colorSpace;
  102. }
  103. public List<Double> getCoords() {
  104. return coords;
  105. }
  106. public Function getFunction() {
  107. return function;
  108. }
  109. public List<Boolean> getExtend() {
  110. return extend;
  111. }
  112. public int getBitsPerCoordinate() {
  113. return bitsPerCoordinate;
  114. }
  115. public int getBitsPerFlag() {
  116. return bitsPerFlag;
  117. }
  118. public boolean isAntiAlias() {
  119. return antiAlias;
  120. }
  121. public int getBitsPerComponent() {
  122. return bitsPerComponent;
  123. }
  124. public int getVerticesPerRow() {
  125. return verticesPerRow;
  126. }
  127. public void output(StringBuilder out, DoubleFormatter doubleFormatter, FunctionRenderer functionRenderer) {
  128. out.append("<<\n/ShadingType " + shadingType + "\n");
  129. if (colorSpace != null) {
  130. out.append("/ColorSpace /" + colorSpace.getName() + "\n");
  131. }
  132. if (antiAlias) {
  133. out.append("/AntiAlias " + antiAlias + "\n");
  134. }
  135. switch (shadingType) {
  136. // Function based shading
  137. case 1: outputShadingType1(out, doubleFormatter, functionRenderer); break;
  138. // Axial shading
  139. case 2:
  140. // Radial shading
  141. case 3: outputShadingType2or3(out, doubleFormatter, functionRenderer); break;
  142. // Free-form Gouraud-shaded triangle meshes
  143. case 4:
  144. // Coons patch meshes
  145. case 6:
  146. // Tensor product patch meshes
  147. case 7: outputShadingType4or6or7(out, doubleFormatter, functionRenderer); break;
  148. // Lattice Free form gouraud-shaded triangle mesh
  149. case 5: outputShadingType5(out, doubleFormatter, functionRenderer); break;
  150. default: throw new UnsupportedOperationException("Shading type " + shadingType);
  151. }
  152. out.append(">>");
  153. }
  154. private void outputShadingType1(StringBuilder out, DoubleFormatter doubleFormatter,
  155. Shading.FunctionRenderer functionRenderer) {
  156. outputFunction(out, functionRenderer);
  157. }
  158. private void outputShadingType2or3(StringBuilder out, DoubleFormatter doubleFormatter,
  159. Shading.FunctionRenderer functionRenderer) {
  160. if (coords != null) {
  161. out.append("/Coords ");
  162. GradientMaker.outputDoubles(out, doubleFormatter, coords);
  163. out.append("\n");
  164. }
  165. out.append("/Extend [ ");
  166. for (Boolean b : extend) {
  167. out.append(b);
  168. out.append(" ");
  169. }
  170. out.append("]\n");
  171. outputFunction(out, functionRenderer);
  172. }
  173. private void outputShadingType4or6or7(StringBuilder out, DoubleFormatter doubleFormatter,
  174. Shading.FunctionRenderer functionRenderer) {
  175. if (bitsPerCoordinate > 0) {
  176. out.append("/BitsPerCoordinate " + bitsPerCoordinate + "\n");
  177. } else {
  178. out.append("/BitsPerCoordinate 1 \n");
  179. }
  180. if (bitsPerComponent > 0) {
  181. out.append("/BitsPerComponent " + bitsPerComponent + "\n");
  182. } else {
  183. out.append("/BitsPerComponent 1 \n");
  184. }
  185. if (bitsPerFlag > 0) {
  186. out.append("/BitsPerFlag " + bitsPerFlag + "\n");
  187. } else {
  188. out.append("/BitsPerFlag 2 \n");
  189. }
  190. outputFunction(out, functionRenderer);
  191. }
  192. private void outputShadingType5(StringBuilder out, DoubleFormatter doubleFormatter,
  193. Shading.FunctionRenderer functionRenderer) {
  194. if (bitsPerCoordinate > 0) {
  195. out.append("/BitsPerCoordinate " + bitsPerCoordinate + "\n");
  196. } else {
  197. out.append("/BitsPerCoordinate 1 \n");
  198. }
  199. if (bitsPerComponent > 0) {
  200. out.append("/BitsPerComponent " + bitsPerComponent + "\n");
  201. } else {
  202. out.append("/BitsPerComponent 1 \n");
  203. }
  204. outputFunction(out, functionRenderer);
  205. if (verticesPerRow > 0) {
  206. out.append("/VerticesPerRow " + verticesPerRow + "\n");
  207. } else {
  208. out.append("/VerticesPerRow 2 \n");
  209. }
  210. }
  211. private void outputFunction(StringBuilder out, FunctionRenderer functionRenderer) {
  212. if (function != null) {
  213. out.append("/Function ");
  214. functionRenderer.outputFunction(out);
  215. out.append("\n");
  216. }
  217. }
  218. }