Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

HemfPlusMisc.java 12KB

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