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.

HemfPlusMisc.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  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. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. ==================================================================== */
  15. package org.apache.poi.hemf.record.emfplus;
  16. import static org.apache.poi.hemf.record.emfplus.HemfPlusDraw.readRectF;
  17. import java.awt.geom.AffineTransform;
  18. import java.awt.geom.Point2D;
  19. import java.awt.geom.Rectangle2D;
  20. import java.io.IOException;
  21. import org.apache.poi.hemf.record.emf.HemfFill;
  22. import org.apache.poi.util.BitField;
  23. import org.apache.poi.util.BitFieldFactory;
  24. import org.apache.poi.util.LittleEndian;
  25. import org.apache.poi.util.LittleEndianConsts;
  26. import org.apache.poi.util.LittleEndianInputStream;
  27. public class HemfPlusMisc {
  28. public interface EmfPlusObjectId {
  29. BitField OBJECT_ID = BitFieldFactory.getInstance(0x00FF);
  30. int getFlags();
  31. /**
  32. * The index in the EMF+ Object Table to associate with the object
  33. * created by this record. The value MUST be zero to 63, inclusive.
  34. */
  35. default int getObjectId() {
  36. return OBJECT_ID.getValue(getFlags());
  37. }
  38. }
  39. public enum CombineMode {
  40. CombineModeReplace(0x00000000),
  41. CombineModeIntersect(0x00000001),
  42. CombineModeUnion(0x00000002),
  43. CombineModeXOR(0x00000003),
  44. CombineModeExclude(0x00000004),
  45. CombineModeComplement(0x00000005)
  46. ;
  47. public final int id;
  48. CombineMode(int id) {
  49. this.id = id;
  50. }
  51. public static CombineMode valueOf(int id) {
  52. for (CombineMode wrt : values()) {
  53. if (wrt.id == id) return wrt;
  54. }
  55. return null;
  56. }
  57. }
  58. public static abstract class EmfPlusFlagOnly implements HemfPlusRecord {
  59. private int flags;
  60. private HemfPlusRecordType recordType;
  61. @Override
  62. public int getFlags() {
  63. return flags;
  64. }
  65. @Override
  66. public final HemfPlusRecordType getEmfPlusRecordType() {
  67. return recordType;
  68. }
  69. @Override
  70. public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
  71. this.flags = flags;
  72. assert(dataSize == 0);
  73. recordType = HemfPlusRecordType.getById(recordId);
  74. return 0;
  75. }
  76. }
  77. public static class EmfPlusEOF extends EmfPlusFlagOnly {
  78. }
  79. /**
  80. * The EmfPlusSetPixelOffsetMode record specifies how pixels are centered with respect to the
  81. * coordinates of the drawing surface.
  82. */
  83. public static class EmfPlusSetPixelOffsetMode extends EmfPlusFlagOnly {
  84. }
  85. /**
  86. * The EmfPlusSetAntiAliasMode record specifies the anti-aliasing mode for text output.
  87. */
  88. public static class EmfPlusSetAntiAliasMode extends EmfPlusFlagOnly {
  89. }
  90. /**
  91. * The EmfPlusSetCompositingMode record specifies how source colors are combined with background colors.
  92. */
  93. public static class EmfPlusSetCompositingMode extends EmfPlusFlagOnly {
  94. }
  95. /**
  96. * The EmfPlusSetCompositingQuality record specifies the desired level of quality for creating
  97. * composite images from multiple objects.
  98. */
  99. public static class EmfPlusSetCompositingQuality extends EmfPlusFlagOnly {
  100. }
  101. /**
  102. * The EmfPlusSetInterpolationMode record specifies how image scaling, including stretching and
  103. * shrinking, is performed.
  104. */
  105. public static class EmfPlusSetInterpolationMode extends EmfPlusFlagOnly {
  106. }
  107. /**
  108. * The EmfPlusGetDC record specifies that subsequent EMF records encountered in the metafile
  109. * SHOULD be processed.
  110. */
  111. public static class EmfPlusGetDC extends EmfPlusFlagOnly {
  112. }
  113. /**
  114. * The EmfPlusSetTextRenderingHint record specifies the quality of text rendering, including the type
  115. * of anti-aliasing.
  116. */
  117. public static class EmfPlusSetTextRenderingHint extends EmfPlusFlagOnly {
  118. }
  119. /**
  120. * The EmfPlusResetWorldTransform record resets the current world space transform to the identify matrix.
  121. */
  122. public static class EmfPlusResetWorldTransform extends EmfPlusFlagOnly {
  123. }
  124. /**
  125. * The EmfPlusSetWorldTransform record sets the world transform according to the values in a
  126. * specified transform matrix.
  127. */
  128. public static class EmfPlusSetWorldTransform implements HemfPlusRecord {
  129. private int flags;
  130. private final AffineTransform matrixData = new AffineTransform();
  131. @Override
  132. public HemfPlusRecordType getEmfPlusRecordType() {
  133. return HemfPlusRecordType.setWorldTransform;
  134. }
  135. @Override
  136. public int getFlags() {
  137. return flags;
  138. }
  139. @Override
  140. public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
  141. this.flags = flags;
  142. return HemfFill.readXForm(leis, matrixData);
  143. }
  144. }
  145. /**
  146. * The EmfPlusMultiplyWorldTransform record multiplies the current world space transform by a
  147. * specified transform matrix.
  148. */
  149. public static class EmfPlusMultiplyWorldTransform extends EmfPlusSetWorldTransform {
  150. @Override
  151. public HemfPlusRecordType getEmfPlusRecordType() {
  152. return HemfPlusRecordType.multiplyWorldTransform;
  153. }
  154. }
  155. /**
  156. * The EmfPlusSetPageTransform record specifies scaling factors and units for converting page space
  157. * coordinates to device space coordinates.
  158. */
  159. public static class EmfPlusSetPageTransform implements HemfPlusRecord {
  160. private int flags;
  161. private double pageScale;
  162. @Override
  163. public HemfPlusRecordType getEmfPlusRecordType() {
  164. return HemfPlusRecordType.setPageTransform;
  165. }
  166. @Override
  167. public int getFlags() {
  168. return flags;
  169. }
  170. @Override
  171. public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
  172. this.flags = flags;
  173. pageScale = leis.readFloat();
  174. return LittleEndianConsts.INT_SIZE;
  175. }
  176. }
  177. /**
  178. * The EmfPlusSetClipRegion record combines the current clipping region with another graphics region.
  179. */
  180. public static class EmfPlusSetClipRegion extends EmfPlusSetClipPath {
  181. }
  182. /**
  183. * The EmfPlusSetClipPath record combines the current clipping region with a graphics path.
  184. */
  185. public static class EmfPlusSetClipPath extends EmfPlusFlagOnly implements EmfPlusObjectId {
  186. private static final BitField COMBINE_MODE = BitFieldFactory.getInstance(0x0F00);
  187. public CombineMode getCombineMode() {
  188. return CombineMode.valueOf(COMBINE_MODE.getValue(getFlags()));
  189. }
  190. }
  191. /** The EmfPlusSetClipRect record combines the current clipping region with a rectangle. */
  192. public static class EmfPlusSetClipRect implements HemfPlusRecord {
  193. private static final BitField COMBINE_MODE = BitFieldFactory.getInstance(0x0F00);
  194. private int flags;
  195. private final Rectangle2D clipRect = new Rectangle2D.Double();
  196. @Override
  197. public HemfPlusRecordType getEmfPlusRecordType() {
  198. return HemfPlusRecordType.setClipRect;
  199. }
  200. @Override
  201. public int getFlags() {
  202. return flags;
  203. }
  204. public CombineMode getCombineMode() {
  205. return CombineMode.valueOf(COMBINE_MODE.getValue(getFlags()));
  206. }
  207. @Override
  208. public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
  209. this.flags = flags;
  210. // An EmfPlusRectF object that defines the rectangle to use in the CombineMode operation.
  211. return readRectF(leis, clipRect);
  212. }
  213. }
  214. /** The EmfPlusResetClip record resets the current clipping region for the world space to infinity. */
  215. public static class EmfPlusResetClip extends EmfPlusFlagOnly {
  216. }
  217. /**
  218. * The EmfPlusSave record saves the graphics state, identified by a specified index, on a stack of saved
  219. * graphics states.
  220. */
  221. public static class EmfPlusSave implements HemfPlusRecord {
  222. private int flags;
  223. private int stackIndex;
  224. @Override
  225. public HemfPlusRecordType getEmfPlusRecordType() {
  226. return HemfPlusRecordType.save;
  227. }
  228. @Override
  229. public int getFlags() {
  230. return flags;
  231. }
  232. @Override
  233. public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
  234. this.flags = flags;
  235. // A 32-bit unsigned integer that specifies a level to associate with the graphics state.
  236. // The level value can be used by a subsequent EmfPlusRestore record operation to retrieve the graphics state.
  237. stackIndex = leis.readInt();
  238. return LittleEndianConsts.INT_SIZE;
  239. }
  240. }
  241. /**
  242. * The EmfPlusRestore record restores the graphics state, identified by a specified index, from a stack
  243. * of saved graphics states.
  244. */
  245. public static class EmfPlusRestore extends EmfPlusSave {
  246. @Override
  247. public HemfPlusRecordType getEmfPlusRecordType() {
  248. return HemfPlusRecordType.restore;
  249. }
  250. }
  251. /** The EmfPlusSetRenderingOrigin record specifies the rendering origin for graphics output. */
  252. public static class EmfPlusSetRenderingOrigin implements HemfPlusRecord {
  253. int flags;
  254. Point2D origin = new Point2D.Double();
  255. @Override
  256. public HemfPlusRecordType getEmfPlusRecordType() {
  257. return HemfPlusRecordType.setRenderingOrigin;
  258. }
  259. @Override
  260. public int getFlags() {
  261. return flags;
  262. }
  263. public Point2D getOrigin() {
  264. return origin;
  265. }
  266. @Override
  267. public long init(LittleEndianInputStream leis, long dataSize, long recordId, int flags) throws IOException {
  268. this.flags = flags;
  269. // A 32-bit unsigned integer that defines the horizontal coordinate value of the rendering origin.
  270. double x = leis.readUInt();
  271. // A 32-bit unsigned integer that defines the vertical coordinate value of the rendering origin.
  272. double y = leis.readUInt();
  273. origin.setLocation(x,y);
  274. return LittleEndianConsts.INT_SIZE*2;
  275. }
  276. }
  277. }