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.

GraphicsObject.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  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.afp.modca;
  19. import java.awt.Color;
  20. import java.io.IOException;
  21. import java.io.OutputStream;
  22. import java.util.List;
  23. import org.apache.xmlgraphics.java2d.color.ColorConverter;
  24. import org.apache.xmlgraphics.java2d.color.ColorUtil;
  25. import org.apache.fop.afp.AFPDataObjectInfo;
  26. import org.apache.fop.afp.AFPObjectAreaInfo;
  27. import org.apache.fop.afp.Factory;
  28. import org.apache.fop.afp.StructuredData;
  29. import org.apache.fop.afp.fonts.CharacterSet;
  30. import org.apache.fop.afp.goca.GraphicsAreaBegin;
  31. import org.apache.fop.afp.goca.GraphicsAreaEnd;
  32. import org.apache.fop.afp.goca.GraphicsBox;
  33. import org.apache.fop.afp.goca.GraphicsChainedSegment;
  34. import org.apache.fop.afp.goca.GraphicsCharacterString;
  35. import org.apache.fop.afp.goca.GraphicsData;
  36. import org.apache.fop.afp.goca.GraphicsEndProlog;
  37. import org.apache.fop.afp.goca.GraphicsFillet;
  38. import org.apache.fop.afp.goca.GraphicsFullArc;
  39. import org.apache.fop.afp.goca.GraphicsImage;
  40. import org.apache.fop.afp.goca.GraphicsLine;
  41. import org.apache.fop.afp.goca.GraphicsSetArcParameters;
  42. import org.apache.fop.afp.goca.GraphicsSetCharacterSet;
  43. import org.apache.fop.afp.goca.GraphicsSetCurrentPosition;
  44. import org.apache.fop.afp.goca.GraphicsSetFractionalLineWidth;
  45. import org.apache.fop.afp.goca.GraphicsSetLineType;
  46. import org.apache.fop.afp.goca.GraphicsSetLineWidth;
  47. import org.apache.fop.afp.goca.GraphicsSetPatternSymbol;
  48. import org.apache.fop.afp.goca.GraphicsSetProcessColor;
  49. /**
  50. * Top-level GOCA graphics object.
  51. *
  52. * Acts as container and factory of all other graphic objects
  53. */
  54. public class GraphicsObject extends AbstractDataObject {
  55. /** the graphics data */
  56. private GraphicsData currentData;
  57. /** list of objects contained within this container */
  58. protected List<GraphicsData> objects
  59. = new java.util.ArrayList<GraphicsData>();
  60. /** the graphics state */
  61. private final GraphicsState graphicsState = new GraphicsState();
  62. /** color converter */
  63. private ColorConverter colorConverter;
  64. /**
  65. * Default constructor
  66. *
  67. * @param factory the object factory
  68. * @param name the name of graphics object
  69. */
  70. public GraphicsObject(Factory factory, String name) {
  71. super(factory, name);
  72. }
  73. /** {@inheritDoc} */
  74. @Override
  75. public void setViewport(AFPDataObjectInfo dataObjectInfo) {
  76. super.setViewport(dataObjectInfo);
  77. AFPObjectAreaInfo objectAreaInfo = dataObjectInfo.getObjectAreaInfo();
  78. int width = objectAreaInfo.getWidth();
  79. int height = objectAreaInfo.getHeight();
  80. int widthRes = objectAreaInfo.getWidthRes();
  81. int heightRes = objectAreaInfo.getHeightRes();
  82. final int leftEdge = 0;
  83. final int topEdge = 0;
  84. GraphicsDataDescriptor graphicsDataDescriptor = factory.createGraphicsDataDescriptor(
  85. leftEdge, width, topEdge, height, widthRes, heightRes);
  86. getObjectEnvironmentGroup().setDataDescriptor(graphicsDataDescriptor);
  87. }
  88. /** @param object the structured data */
  89. public void addObject(StructuredData object) {
  90. if (currentData == null) {
  91. newData();
  92. } else if (currentData.getDataLength() + object.getDataLength()
  93. >= GraphicsData.MAX_DATA_LEN) {
  94. // graphics data full so transfer current incomplete segment to new data
  95. GraphicsChainedSegment currentSegment
  96. = (GraphicsChainedSegment)currentData.removeCurrentSegment();
  97. currentSegment.setName(newData().createSegmentName());
  98. currentData.addSegment(currentSegment);
  99. }
  100. currentData.addObject(object);
  101. }
  102. /**
  103. * Gets the current graphics data, creating a new one if necessary
  104. *
  105. * @return the current graphics data
  106. */
  107. private GraphicsData getData() {
  108. if (this.currentData == null) {
  109. return newData();
  110. }
  111. return this.currentData;
  112. }
  113. /**
  114. * Creates a new graphics data
  115. *
  116. * @return a newly created graphics data
  117. */
  118. private GraphicsData newData() {
  119. if (currentData != null) {
  120. currentData.setComplete(true);
  121. }
  122. this.currentData = factory.createGraphicsData();
  123. objects.add(currentData);
  124. return currentData;
  125. }
  126. /**
  127. * Sets the current color
  128. *
  129. * @param color the active color to use
  130. */
  131. public void setColor(Color color) {
  132. if (!ColorUtil.isSameColor(color, graphicsState.color)) {
  133. addObject(new GraphicsSetProcessColor(colorConverter.convert(color)));
  134. graphicsState.color = color;
  135. }
  136. }
  137. /**
  138. * Sets the color converter
  139. *
  140. * @param colorConverter ColorConverter to filter the color
  141. * when creating a GraphicsSetProcessColor.
  142. */
  143. public void setColorConverter(ColorConverter colorConverter) {
  144. this.colorConverter = colorConverter;
  145. }
  146. /**
  147. * Sets the current position
  148. *
  149. * @param coords the x and y coordinates of the current position
  150. */
  151. public void setCurrentPosition(int[] coords) {
  152. addObject(new GraphicsSetCurrentPosition(coords));
  153. }
  154. /**
  155. * Sets the line width
  156. *
  157. * @param lineWidth the line width multiplier
  158. */
  159. public void setLineWidth(int lineWidth) {
  160. if ((float) lineWidth != graphicsState.lineWidth) {
  161. addObject(new GraphicsSetLineWidth(lineWidth));
  162. graphicsState.lineWidth = (float) lineWidth;
  163. }
  164. }
  165. /**
  166. * Sets the line width
  167. *
  168. * @param lineWidth the line width multiplier
  169. */
  170. public void setLineWidth(float lineWidth) {
  171. float epsilon = Float.intBitsToFloat(0x00800000); // Float.MIN_NORMAL (JDK1.6)
  172. if (Math.abs(graphicsState.lineWidth - lineWidth) > epsilon) {
  173. addObject(new GraphicsSetFractionalLineWidth(lineWidth));
  174. graphicsState.lineWidth = lineWidth;
  175. }
  176. }
  177. /**
  178. * Sets the line type
  179. *
  180. * @param lineType the line type
  181. */
  182. public void setLineType(byte lineType) {
  183. if (lineType != graphicsState.lineType) {
  184. addObject(new GraphicsSetLineType(lineType));
  185. graphicsState.lineType = lineType;
  186. }
  187. }
  188. /**
  189. * Sets whether the following shape is to be filled.
  190. *
  191. * @param fill true if the following shape is to be filled
  192. */
  193. public void setFill(boolean fill) {
  194. setPatternSymbol(fill
  195. ? GraphicsSetPatternSymbol.SOLID_FILL
  196. : GraphicsSetPatternSymbol.NO_FILL);
  197. }
  198. /**
  199. * Sets the fill pattern of the next shape.
  200. *
  201. * @param patternSymbol the fill pattern of the next shape
  202. */
  203. public void setPatternSymbol(byte patternSymbol) {
  204. if (patternSymbol != graphicsState.patternSymbol) {
  205. addObject(new GraphicsSetPatternSymbol(patternSymbol));
  206. graphicsState.patternSymbol = patternSymbol;
  207. }
  208. }
  209. /**
  210. * Sets the character set to use
  211. *
  212. * @param characterSet the character set (font) reference
  213. */
  214. public void setCharacterSet(int characterSet) {
  215. if (characterSet != graphicsState.characterSet) {
  216. graphicsState.characterSet = characterSet;
  217. }
  218. addObject(new GraphicsSetCharacterSet(characterSet));
  219. }
  220. /**
  221. * Adds a line at the given x/y coordinates
  222. *
  223. * @param coords the x/y coordinates (can be a series)
  224. */
  225. public void addLine(int[] coords) {
  226. addLine(coords, false);
  227. }
  228. /**
  229. * Adds a line at the given x/y coordinates
  230. *
  231. * @param coords the x/y coordinates (can be a series)
  232. * @param relative relative true for a line at current position (relative to)
  233. */
  234. public void addLine(int[] coords, boolean relative) {
  235. addObject(new GraphicsLine(coords, relative));
  236. }
  237. /**
  238. * Adds a box at the given coordinates
  239. *
  240. * @param coords the x/y coordinates
  241. */
  242. public void addBox(int[] coords) {
  243. addObject(new GraphicsBox(coords));
  244. }
  245. /**
  246. * Adds a fillet (curve) at the given coordinates
  247. *
  248. * @param coords the x/y coordinates
  249. */
  250. public void addFillet(int[] coords) {
  251. addFillet(coords, false);
  252. }
  253. /**
  254. * Adds a fillet (curve) at the given coordinates
  255. *
  256. * @param coords the x/y coordinates
  257. * @param relative relative true for a fillet (curve) at current position (relative to)
  258. */
  259. public void addFillet(int[] coords, boolean relative) {
  260. addObject(new GraphicsFillet(coords, relative));
  261. }
  262. /**
  263. * Sets the arc parameters
  264. *
  265. * @param xmaj the maximum value of the x coordinate
  266. * @param ymin the minimum value of the y coordinate
  267. * @param xmin the minimum value of the x coordinate
  268. * @param ymaj the maximum value of the y coordinate
  269. */
  270. public void setArcParams(int xmaj, int ymin, int xmin, int ymaj) {
  271. addObject(new GraphicsSetArcParameters(xmaj, ymin, xmin, ymaj));
  272. }
  273. /**
  274. * Adds a full arc
  275. *
  276. * @param x the x coordinate
  277. * @param y the y coordinate
  278. * @param mh the integer portion of the multiplier
  279. * @param mhr the fractional portion of the multiplier
  280. */
  281. public void addFullArc(int x, int y, int mh, int mhr) {
  282. addObject(new GraphicsFullArc(x, y, mh, mhr));
  283. }
  284. /**
  285. * Adds an image
  286. *
  287. * @param x the x coordinate
  288. * @param y the y coordinate
  289. * @param width the image width
  290. * @param height the image height
  291. * @param imgData the image data
  292. */
  293. public void addImage(int x, int y, int width, int height, byte[] imgData) {
  294. addObject(new GraphicsImage(x, y, width, height, imgData));
  295. }
  296. /**
  297. * Adds a string
  298. *
  299. * @param str the string
  300. * @param x the x coordinate
  301. * @param y the y coordinate
  302. * @param charSet the character set associated with the string
  303. */
  304. public void addString(String str, int x, int y, CharacterSet charSet) {
  305. addObject(new GraphicsCharacterString(str, x, y, charSet));
  306. }
  307. /**
  308. * Begins a graphics area (start of fill)
  309. */
  310. public void beginArea() {
  311. addObject(new GraphicsAreaBegin());
  312. }
  313. /**
  314. * Ends a graphics area (end of fill)
  315. */
  316. public void endArea() {
  317. addObject(new GraphicsAreaEnd());
  318. }
  319. /**
  320. * Ends the prolog.
  321. */
  322. public void endProlog() {
  323. addObject(new GraphicsEndProlog());
  324. }
  325. /** {@inheritDoc} */
  326. @Override
  327. public String toString() {
  328. return "GraphicsObject: " + getName();
  329. }
  330. /**
  331. * Creates a new graphics segment
  332. */
  333. public void newSegment() {
  334. getData().newSegment();
  335. graphicsState.lineWidth = 0; //Looks like a new segment invalidates the graphics state
  336. graphicsState.color = Color.BLACK;
  337. }
  338. /** {@inheritDoc} */
  339. @Override
  340. public void setComplete(boolean complete) {
  341. for (GraphicsData completedObject : objects) {
  342. completedObject.setComplete(true);
  343. }
  344. super.setComplete(complete);
  345. }
  346. /** {@inheritDoc} */
  347. @Override
  348. protected void writeStart(OutputStream os) throws IOException {
  349. super.writeStart(os);
  350. byte[] data = new byte[17];
  351. copySF(data, Type.BEGIN, Category.GRAPHICS);
  352. os.write(data);
  353. }
  354. /** {@inheritDoc} */
  355. @Override
  356. protected void writeContent(OutputStream os) throws IOException {
  357. super.writeContent(os);
  358. writeObjects(objects, os);
  359. }
  360. /** {@inheritDoc} */
  361. @Override
  362. protected void writeEnd(OutputStream os) throws IOException {
  363. byte[] data = new byte[17];
  364. copySF(data, Type.END, Category.GRAPHICS);
  365. os.write(data);
  366. }
  367. /** the internal graphics state */
  368. private static final class GraphicsState {
  369. private GraphicsState() {
  370. }
  371. /** the current color */
  372. private Color color;
  373. /** the current line type */
  374. private byte lineType;
  375. /** the current line width */
  376. private float lineWidth;
  377. /** the current fill pattern */
  378. private byte patternSymbol;
  379. /** the current character set */
  380. private int characterSet;
  381. }
  382. }