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.

HwmfText.java 24KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  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.hwmf.record;
  16. import static org.apache.poi.hwmf.record.HwmfDraw.boundsToString;
  17. import static org.apache.poi.hwmf.record.HwmfDraw.pointToString;
  18. import static org.apache.poi.hwmf.record.HwmfDraw.readPointS;
  19. import static org.apache.poi.hwmf.record.HwmfDraw.readRectS;
  20. import java.awt.geom.Point2D;
  21. import java.awt.geom.Rectangle2D;
  22. import java.io.IOException;
  23. import java.nio.charset.Charset;
  24. import java.util.ArrayList;
  25. import java.util.List;
  26. import org.apache.commons.codec.Charsets;
  27. import org.apache.poi.hwmf.draw.HwmfDrawProperties;
  28. import org.apache.poi.hwmf.draw.HwmfGraphics;
  29. import org.apache.poi.hwmf.record.HwmfMisc.WmfSetMapMode;
  30. import org.apache.poi.util.BitField;
  31. import org.apache.poi.util.BitFieldFactory;
  32. import org.apache.poi.util.IOUtils;
  33. import org.apache.poi.util.LittleEndianConsts;
  34. import org.apache.poi.util.LittleEndianInputStream;
  35. import org.apache.poi.util.LocaleUtil;
  36. import org.apache.poi.util.POILogFactory;
  37. import org.apache.poi.util.POILogger;
  38. public class HwmfText {
  39. private static final POILogger logger = POILogFactory.getLogger(HwmfText.class);
  40. private static final int MAX_RECORD_LENGTH = 1_000_000;
  41. /**
  42. * The META_SETTEXTCHAREXTRA record defines inter-character spacing for text justification in the
  43. * playback device context. Spacing is added to the white space between each character, including
  44. * break characters, when a line of justified text is output.
  45. */
  46. public static class WmfSetTextCharExtra implements HwmfRecord {
  47. /**
  48. * A 16-bit unsigned integer that defines the amount of extra space, in
  49. * logical units, to be added to each character. If the current mapping mode is not MM_TEXT,
  50. * this value is transformed and rounded to the nearest pixel. For details about setting the
  51. * mapping mode, see META_SETMAPMODE
  52. */
  53. private int charExtra;
  54. @Override
  55. public HwmfRecordType getWmfRecordType() {
  56. return HwmfRecordType.setTextCharExtra;
  57. }
  58. @Override
  59. public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
  60. charExtra = leis.readUShort();
  61. return LittleEndianConsts.SHORT_SIZE;
  62. }
  63. @Override
  64. public void draw(HwmfGraphics ctx) {
  65. }
  66. }
  67. /**
  68. * The META_SETTEXTCOLOR record defines the text foreground color in the playback device context.
  69. */
  70. public static class WmfSetTextColor implements HwmfRecord {
  71. protected final HwmfColorRef colorRef = new HwmfColorRef();
  72. @Override
  73. public HwmfRecordType getWmfRecordType() {
  74. return HwmfRecordType.setTextColor;
  75. }
  76. @Override
  77. public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
  78. return colorRef.init(leis);
  79. }
  80. @Override
  81. public void draw(HwmfGraphics ctx) {
  82. ctx.getProperties().setTextColor(colorRef);
  83. }
  84. @Override
  85. public String toString() {
  86. return "{ colorRef: "+colorRef+" }";
  87. }
  88. }
  89. /**
  90. * The META_SETTEXTJUSTIFICATION record defines the amount of space to add to break characters
  91. * in a string of justified text.
  92. */
  93. public static class WmfSetTextJustification implements HwmfRecord {
  94. /**
  95. * A 16-bit unsigned integer that specifies the number of space characters in the line.
  96. */
  97. private int breakCount;
  98. /**
  99. * A 16-bit unsigned integer that specifies the total extra space, in logical
  100. * units, to be added to the line of text. If the current mapping mode is not MM_TEXT, the value
  101. * identified by the BreakExtra member is transformed and rounded to the nearest pixel. For
  102. * details about setting the mapping mode, see {@link WmfSetMapMode}.
  103. */
  104. private int breakExtra;
  105. @Override
  106. public HwmfRecordType getWmfRecordType() {
  107. return HwmfRecordType.setBkColor;
  108. }
  109. @Override
  110. public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
  111. breakCount = leis.readUShort();
  112. breakExtra = leis.readUShort();
  113. return 2*LittleEndianConsts.SHORT_SIZE;
  114. }
  115. @Override
  116. public void draw(HwmfGraphics ctx) {
  117. }
  118. }
  119. /**
  120. * The META_TEXTOUT record outputs a character string at the specified location by using the font,
  121. * background color, and text color that are defined in the playback device context.
  122. */
  123. public static class WmfTextOut implements HwmfRecord {
  124. /**
  125. * A 16-bit signed integer that defines the length of the string, in bytes, pointed to by String.
  126. */
  127. private int stringLength;
  128. /**
  129. * The size of this field MUST be a multiple of two. If StringLength is an odd
  130. * number, then this field MUST be of a size greater than or equal to StringLength + 1.
  131. * A variable-length string that specifies the text to be drawn.
  132. * The string does not need to be null-terminated, because StringLength specifies the
  133. * length of the string.
  134. * The string is written at the location specified by the XStart and YStart fields.
  135. */
  136. private byte[] rawTextBytes;
  137. protected Point2D reference = new Point2D.Double();
  138. @Override
  139. public HwmfRecordType getWmfRecordType() {
  140. return HwmfRecordType.textOut;
  141. }
  142. @Override
  143. public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
  144. stringLength = leis.readShort();
  145. rawTextBytes = IOUtils.safelyAllocate(stringLength+(stringLength&1), MAX_RECORD_LENGTH);
  146. leis.readFully(rawTextBytes);
  147. // A 16-bit signed integer that defines the vertical (y-axis) coordinate, in logical
  148. // units, of the point where drawing is to start.
  149. int yStart = leis.readShort();
  150. // A 16-bit signed integer that defines the horizontal (x-axis) coordinate, in
  151. // logical units, of the point where drawing is to start.
  152. int xStart = leis.readShort();
  153. reference.setLocation(xStart, yStart);
  154. return 3*LittleEndianConsts.SHORT_SIZE+rawTextBytes.length;
  155. }
  156. @Override
  157. public void draw(HwmfGraphics ctx) {
  158. ctx.drawString(getTextBytes(), stringLength, reference);
  159. }
  160. public String getText(Charset charset) {
  161. return new String(getTextBytes(), charset);
  162. }
  163. /**
  164. *
  165. * @return a copy of a trimmed byte array of rawTextBytes bytes.
  166. * This includes only the bytes from 0..stringLength.
  167. * This does not include the extra optional padding on the byte array.
  168. */
  169. private byte[] getTextBytes() {
  170. byte[] ret = IOUtils.safelyAllocate(stringLength, MAX_RECORD_LENGTH);
  171. System.arraycopy(rawTextBytes, 0, ret, 0, stringLength);
  172. return ret;
  173. }
  174. }
  175. public static class WmfExtTextOutOptions {
  176. /**
  177. * Indicates that the background color that is defined in the playback device context
  178. * SHOULD be used to fill the rectangle.
  179. */
  180. private static final BitField ETO_OPAQUE = BitFieldFactory.getInstance(0x0002);
  181. /**
  182. * Indicates that the text SHOULD be clipped to the rectangle.
  183. */
  184. private static final BitField ETO_CLIPPED = BitFieldFactory.getInstance(0x0004);
  185. /**
  186. * Indicates that the string to be output SHOULD NOT require further processing
  187. * with respect to the placement of the characters, and an array of character
  188. * placement values SHOULD be provided. This character placement process is
  189. * useful for fonts in which diacritical characters affect character spacing.
  190. */
  191. private static final BitField ETO_GLYPH_INDEX = BitFieldFactory.getInstance(0x0010);
  192. /**
  193. * Indicates that the text MUST be laid out in right-to-left reading order, instead of
  194. * the default left-to-right order. This SHOULD be applied only when the font that is
  195. * defined in the playback device context is either Hebrew or Arabic.
  196. */
  197. private static final BitField ETO_RTLREADING = BitFieldFactory.getInstance(0x0080);
  198. /**
  199. * This bit indicates that the record does not specify a bounding rectangle for the
  200. * text output.
  201. */
  202. private static final BitField ETO_NO_RECT = BitFieldFactory.getInstance(0x0100);
  203. /**
  204. * This bit indicates that the codes for characters in an output text string are 8 bits,
  205. * derived from the low bytes of 16-bit Unicode UTF16-LE character codes, in which
  206. * the high byte is assumed to be 0.
  207. */
  208. private static final BitField ETO_SMALL_CHARS = BitFieldFactory.getInstance(0x0200);
  209. /**
  210. * Indicates that to display numbers, digits appropriate to the locale SHOULD be used.
  211. */
  212. private static final BitField ETO_NUMERICSLOCAL = BitFieldFactory.getInstance(0x0400);
  213. /**
  214. * Indicates that to display numbers, European digits SHOULD be used.
  215. */
  216. private static final BitField ETO_NUMERICSLATIN = BitFieldFactory.getInstance(0x0800);
  217. /**
  218. * This bit indicates that no special operating system processing for glyph placement
  219. * should be performed on right-to-left strings; that is, all glyph positioning
  220. * SHOULD be taken care of by drawing and state records in the metafile
  221. */
  222. private static final BitField ETO_IGNORELANGUAGE = BitFieldFactory.getInstance(0x1000);
  223. /**
  224. * Indicates that both horizontal and vertical character displacement values
  225. * SHOULD be provided.
  226. */
  227. private static final BitField ETO_PDY = BitFieldFactory.getInstance(0x2000);
  228. /** This bit is reserved and SHOULD NOT be used. */
  229. private static final BitField ETO_REVERSE_INDEX_MAP = BitFieldFactory.getInstance(0x10000);
  230. protected int flag;
  231. public int init(LittleEndianInputStream leis) {
  232. flag = leis.readUShort();
  233. return LittleEndianConsts.SHORT_SIZE;
  234. }
  235. public boolean isOpaque() {
  236. return ETO_OPAQUE.isSet(flag);
  237. }
  238. public boolean isClipped() {
  239. return ETO_CLIPPED.isSet(flag);
  240. }
  241. public boolean isYDisplaced() {
  242. return ETO_PDY.isSet(flag);
  243. }
  244. }
  245. /**
  246. * The META_EXTTEXTOUT record outputs text by using the font, background color, and text color that
  247. * are defined in the playback device context. Optionally, dimensions can be provided for clipping,
  248. * opaquing, or both.
  249. */
  250. public static class WmfExtTextOut implements HwmfRecord {
  251. /**
  252. * The location, in logical units, where the text string is to be placed.
  253. */
  254. protected final Point2D reference = new Point2D.Double();
  255. /**
  256. * A 16-bit signed integer that defines the length of the string.
  257. */
  258. protected int stringLength;
  259. /**
  260. * A 16-bit unsigned integer that defines the use of the application-defined
  261. * rectangle. This member can be a combination of one or more values in the
  262. * ExtTextOutOptions Flags (ETO_*)
  263. */
  264. protected final WmfExtTextOutOptions options;
  265. /**
  266. * An optional 8-byte Rect Object (section 2.2.2.18) that defines the
  267. * dimensions, in logical coordinates, of a rectangle that is used for clipping, opaquing, or both.
  268. *
  269. * The corners are given in the order left, top, right, bottom.
  270. * Each value is a 16-bit signed integer that defines the coordinate, in logical coordinates, of
  271. * the upper-left corner of the rectangle
  272. */
  273. protected final Rectangle2D bounds = new Rectangle2D.Double();
  274. /**
  275. * A variable-length string that specifies the text to be drawn. The string does
  276. * not need to be null-terminated, because StringLength specifies the length of the string. If
  277. * the length is odd, an extra byte is placed after it so that the following member (optional Dx) is
  278. * aligned on a 16-bit boundary.
  279. */
  280. protected byte[] rawTextBytes;
  281. /**
  282. * An optional array of 16-bit signed integers that indicate the distance between
  283. * origins of adjacent character cells. For example, Dx[i] logical units separate the origins of
  284. * character cell i and character cell i + 1. If this field is present, there MUST be the same
  285. * number of values as there are characters in the string.
  286. */
  287. protected final List<Integer> dx = new ArrayList<>();
  288. public WmfExtTextOut() {
  289. this(new WmfExtTextOutOptions());
  290. }
  291. protected WmfExtTextOut(WmfExtTextOutOptions options) {
  292. this.options = options;
  293. }
  294. @Override
  295. public HwmfRecordType getWmfRecordType() {
  296. return HwmfRecordType.extTextOut;
  297. }
  298. @Override
  299. public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
  300. // -6 bytes of record function and length header
  301. final int remainingRecordSize = (int)(recordSize-6);
  302. int size = readPointS(leis, reference);
  303. stringLength = leis.readShort();
  304. size += LittleEndianConsts.SHORT_SIZE;
  305. size += options.init(leis);
  306. // Check if we have a rectangle
  307. if ((options.isOpaque() || options.isClipped()) && size+8<=remainingRecordSize) {
  308. // the bounding rectangle is optional and only read when options are given
  309. size += readRectS(leis, bounds);
  310. }
  311. rawTextBytes = IOUtils.safelyAllocate(stringLength+(stringLength&1), MAX_RECORD_LENGTH);
  312. leis.readFully(rawTextBytes);
  313. size += rawTextBytes.length;
  314. if (size >= remainingRecordSize) {
  315. logger.log(POILogger.INFO, "META_EXTTEXTOUT doesn't contain character tracking info");
  316. return size;
  317. }
  318. int dxLen = Math.min(stringLength, (remainingRecordSize-size)/LittleEndianConsts.SHORT_SIZE);
  319. if (dxLen < stringLength) {
  320. logger.log(POILogger.WARN, "META_EXTTEXTOUT tracking info doesn't cover all characters");
  321. }
  322. for (int i=0; i<dxLen; i++) {
  323. dx.add((int)leis.readShort());
  324. size += LittleEndianConsts.SHORT_SIZE;
  325. }
  326. return size;
  327. }
  328. @Override
  329. public void draw(HwmfGraphics ctx) {
  330. ctx.drawString(rawTextBytes, stringLength, reference, null, bounds, options, dx, false);
  331. }
  332. public String getText(Charset charset) throws IOException {
  333. return new String(rawTextBytes, charset).substring(0, stringLength);
  334. }
  335. public Point2D getReference() {
  336. return reference;
  337. }
  338. public Rectangle2D getBounds() {
  339. return bounds;
  340. }
  341. protected boolean isUnicode() {
  342. return false;
  343. }
  344. @Override
  345. public String toString() {
  346. String text = "";
  347. try {
  348. text = getText(isUnicode() ? Charsets.UTF_16LE : LocaleUtil.CHARSET_1252);
  349. } catch (IOException ignored) {
  350. }
  351. return
  352. "{ reference: " + pointToString(reference) +
  353. ", bounds: " + boundsToString(bounds) +
  354. ", text: '"+text.replaceAll("\\p{Cntrl}",".")+"'"+
  355. "}";
  356. }
  357. }
  358. public enum HwmfTextAlignment {
  359. LEFT,
  360. RIGHT,
  361. CENTER
  362. }
  363. public enum HwmfTextVerticalAlignment {
  364. TOP,
  365. BOTTOM,
  366. BASELINE
  367. }
  368. /**
  369. * The META_SETTEXTALIGN record defines text-alignment values in the playback device context.
  370. */
  371. public static class WmfSetTextAlign implements HwmfRecord {
  372. /**
  373. * The drawing position in the playback device context MUST be updated after each text
  374. * output call. It MUST be used as the reference point.<p>
  375. *
  376. * If the flag is not set, the option TA_NOUPDATECP is active, i.e. the drawing position
  377. * in the playback device context MUST NOT be updated after each text output call.
  378. * The reference point MUST be passed to the text output function.
  379. */
  380. @SuppressWarnings("unused")
  381. private static final BitField TA_UPDATECP = BitFieldFactory.getInstance(0x0001);
  382. /**
  383. * The text MUST be laid out in right-to-left reading order, instead of the default
  384. * left-to-right order. This SHOULD be applied only when the font that is defined in the
  385. * playback device context is either Hebrew or Arabic.
  386. */
  387. @SuppressWarnings("unused")
  388. private static final BitField TA_RTLREADING = BitFieldFactory.getInstance(0x0100);
  389. private static final BitField ALIGN_MASK = BitFieldFactory.getInstance(0x0006);
  390. /**
  391. * Flag TA_LEFT (0x0000):
  392. * The reference point MUST be on the left edge of the bounding rectangle,
  393. * if all bits of the align mask (latin mode) are unset.
  394. *
  395. * Flag VTA_TOP (0x0000):
  396. * The reference point MUST be on the top edge of the bounding rectangle,
  397. * if all bits of the valign mask are unset.
  398. */
  399. private static final int ALIGN_LEFT = 0;
  400. /**
  401. * Flag TA_RIGHT (0x0002):
  402. * The reference point MUST be on the right edge of the bounding rectangle.
  403. *
  404. * Flag VTA_BOTTOM (0x0002):
  405. * The reference point MUST be on the bottom edge of the bounding rectangle.
  406. */
  407. private static final int ALIGN_RIGHT = 1;
  408. /**
  409. * Flag TA_CENTER (0x0006) / VTA_CENTER (0x0006):
  410. * The reference point MUST be aligned horizontally with the center of the bounding
  411. * rectangle.
  412. */
  413. private static final int ALIGN_CENTER = 3;
  414. private static final BitField VALIGN_MASK = BitFieldFactory.getInstance(0x0018);
  415. /**
  416. * Flag TA_TOP (0x0000):
  417. * The reference point MUST be on the top edge of the bounding rectangle,
  418. * if all bits of the valign mask are unset.
  419. *
  420. * Flag VTA_RIGHT (0x0000):
  421. * The reference point MUST be on the right edge of the bounding rectangle,
  422. * if all bits of the align mask (asian mode) are unset.
  423. */
  424. private static final int VALIGN_TOP = 0;
  425. /**
  426. * Flag TA_BOTTOM (0x0008):
  427. * The reference point MUST be on the bottom edge of the bounding rectangle.
  428. *
  429. * Flag VTA_LEFT (0x0008):
  430. * The reference point MUST be on the left edge of the bounding rectangle.
  431. */
  432. private static final int VALIGN_BOTTOM = 1;
  433. /**
  434. * Flag TA_BASELINE (0x0018) / VTA_BASELINE (0x0018):
  435. * The reference point MUST be on the baseline of the text.
  436. */
  437. private static final int VALIGN_BASELINE = 3;
  438. /**
  439. * A 16-bit unsigned integer that defines text alignment.
  440. * This value MUST be a combination of one or more TextAlignmentMode Flags
  441. * for text with a horizontal baseline, and VerticalTextAlignmentMode Flags
  442. * for text with a vertical baseline.
  443. */
  444. protected int textAlignmentMode;
  445. @Override
  446. public HwmfRecordType getWmfRecordType() {
  447. return HwmfRecordType.setTextAlign;
  448. }
  449. @Override
  450. public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
  451. textAlignmentMode = leis.readUShort();
  452. return LittleEndianConsts.SHORT_SIZE;
  453. }
  454. @Override
  455. public void draw(HwmfGraphics ctx) {
  456. HwmfDrawProperties props = ctx.getProperties();
  457. props.setTextAlignLatin(getAlignLatin());
  458. props.setTextVAlignLatin(getVAlignLatin());
  459. props.setTextAlignAsian(getAlignAsian());
  460. props.setTextVAlignAsian(getVAlignAsian());
  461. }
  462. @Override
  463. public String toString() {
  464. return
  465. "{ align: '"+ getAlignLatin() + "'" +
  466. ", valign: '"+ getVAlignLatin() + "'" +
  467. ", alignAsian: '"+ getAlignAsian() + "'" +
  468. ", valignAsian: '"+ getVAlignAsian() + "'" +
  469. "}";
  470. }
  471. private HwmfTextAlignment getAlignLatin() {
  472. switch (ALIGN_MASK.getValue(textAlignmentMode)) {
  473. default:
  474. case ALIGN_LEFT:
  475. return HwmfTextAlignment.LEFT;
  476. case ALIGN_CENTER:
  477. return HwmfTextAlignment.CENTER;
  478. case ALIGN_RIGHT:
  479. return HwmfTextAlignment.RIGHT;
  480. }
  481. }
  482. private HwmfTextVerticalAlignment getVAlignLatin() {
  483. switch (VALIGN_MASK.getValue(textAlignmentMode)) {
  484. default:
  485. case VALIGN_TOP:
  486. return HwmfTextVerticalAlignment.TOP;
  487. case VALIGN_BASELINE:
  488. return HwmfTextVerticalAlignment.BASELINE;
  489. case VALIGN_BOTTOM:
  490. return HwmfTextVerticalAlignment.BOTTOM;
  491. }
  492. }
  493. private HwmfTextAlignment getAlignAsian() {
  494. switch (getVAlignLatin()) {
  495. default:
  496. case TOP:
  497. return HwmfTextAlignment.RIGHT;
  498. case BASELINE:
  499. return HwmfTextAlignment.CENTER;
  500. case BOTTOM:
  501. return HwmfTextAlignment.LEFT;
  502. }
  503. }
  504. private HwmfTextVerticalAlignment getVAlignAsian() {
  505. switch (getAlignLatin()) {
  506. default:
  507. case LEFT:
  508. return HwmfTextVerticalAlignment.TOP;
  509. case CENTER:
  510. return HwmfTextVerticalAlignment.BASELINE;
  511. case RIGHT:
  512. return HwmfTextVerticalAlignment.BOTTOM;
  513. }
  514. }
  515. }
  516. public static class WmfCreateFontIndirect implements HwmfRecord, HwmfObjectTableEntry {
  517. protected final HwmfFont font;
  518. public WmfCreateFontIndirect() {
  519. this(new HwmfFont());
  520. }
  521. protected WmfCreateFontIndirect(HwmfFont font) {
  522. this.font = font;
  523. }
  524. @Override
  525. public HwmfRecordType getWmfRecordType() {
  526. return HwmfRecordType.createFontIndirect;
  527. }
  528. @Override
  529. public int init(LittleEndianInputStream leis, long recordSize, int recordFunction) throws IOException {
  530. return font.init(leis, recordSize);
  531. }
  532. @Override
  533. public void draw(HwmfGraphics ctx) {
  534. ctx.addObjectTableEntry(this);
  535. }
  536. @Override
  537. public void applyObject(HwmfGraphics ctx) {
  538. ctx.getProperties().setFont(font);
  539. }
  540. public HwmfFont getFont() {
  541. return font;
  542. }
  543. @Override
  544. public String toString() {
  545. return "{ font: "+font+" } ";
  546. }
  547. }
  548. }