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.

HwmfFont.java 18KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  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 java.io.IOException;
  17. import java.nio.charset.StandardCharsets;
  18. import org.apache.poi.common.usermodel.fonts.FontCharset;
  19. import org.apache.poi.common.usermodel.fonts.FontFamily;
  20. import org.apache.poi.common.usermodel.fonts.FontInfo;
  21. import org.apache.poi.common.usermodel.fonts.FontPitch;
  22. import org.apache.poi.util.BitField;
  23. import org.apache.poi.util.BitFieldFactory;
  24. import org.apache.poi.util.LittleEndianConsts;
  25. import org.apache.poi.util.LittleEndianInputStream;
  26. /**
  27. * The Font object specifies the attributes of a logical font
  28. */
  29. public class HwmfFont implements FontInfo {
  30. /**
  31. * The output precision defines how closely the output must match the requested font's height,
  32. * width, character orientation, escapement, pitch, and font type.
  33. */
  34. public enum WmfOutPrecision {
  35. /**
  36. * A value that specifies default behavior.
  37. */
  38. OUT_DEFAULT_PRECIS(0x00000000),
  39. /**
  40. * A value that is returned when rasterized fonts are enumerated.
  41. */
  42. OUT_STRING_PRECIS(0x00000001),
  43. /**
  44. * A value that is returned when TrueType and other outline fonts, and
  45. * vector fonts are enumerated.
  46. */
  47. OUT_STROKE_PRECIS(0x00000003),
  48. /**
  49. * A value that specifies the choice of a TrueType font when the system
  50. * contains multiple fonts with the same name.
  51. */
  52. OUT_TT_PRECIS(0x00000004),
  53. /**
  54. * A value that specifies the choice of a device font when the system
  55. * contains multiple fonts with the same name.
  56. */
  57. OUT_DEVICE_PRECIS(0x00000005),
  58. /**
  59. * A value that specifies the choice of a rasterized font when the system
  60. * contains multiple fonts with the same name.
  61. */
  62. OUT_RASTER_PRECIS(0x00000006),
  63. /**
  64. * A value that specifies the requirement for only TrueType fonts. If
  65. * there are no TrueType fonts installed in the system, default behavior is specified.
  66. */
  67. OUT_TT_ONLY_PRECIS(0x00000007),
  68. /**
  69. * A value that specifies the requirement for TrueType and other outline fonts.
  70. */
  71. OUT_OUTLINE_PRECIS (0x00000008),
  72. /**
  73. * A value that specifies a preference for TrueType and other outline fonts.
  74. */
  75. OUT_SCREEN_OUTLINE_PRECIS (0x00000009),
  76. /**
  77. * A value that specifies a requirement for only PostScript fonts. If there
  78. * are no PostScript fonts installed in the system, default behavior is specified.
  79. */
  80. OUT_PS_ONLY_PRECIS (0x0000000A);
  81. int flag;
  82. WmfOutPrecision(int flag) {
  83. this.flag = flag;
  84. }
  85. public static WmfOutPrecision valueOf(int flag) {
  86. for (WmfOutPrecision op : values()) {
  87. if (op.flag == flag) {
  88. return op;
  89. }
  90. }
  91. return null;
  92. }
  93. }
  94. /**
  95. * ClipPrecision Flags specify clipping precision, which defines how to clip characters that are
  96. * partially outside a clipping region. These flags can be combined to specify multiple options.
  97. */
  98. public static class WmfClipPrecision {
  99. /** Specifies that default clipping MUST be used. */
  100. private static final BitField CLIP_DEFAULT_PRECIS = BitFieldFactory.getInstance(0x0000);
  101. /** This value SHOULD NOT be used. */
  102. private static final BitField CLIP_CHARACTER_PRECIS = BitFieldFactory.getInstance(0x0001);
  103. /** This value MAY be returned when enumerating rasterized, TrueType and vector fonts. */
  104. private static final BitField CLIP_STROKE_PRECIS = BitFieldFactory.getInstance(0x0002);
  105. /**
  106. * This value is used to control font rotation, as follows:
  107. * If set, the rotation for all fonts SHOULD be determined by the orientation of the coordinate system;
  108. * that is, whether the orientation is left-handed or right-handed.
  109. *
  110. * If clear, device fonts SHOULD rotate counterclockwise, but the rotation of other fonts
  111. * SHOULD be determined by the orientation of the coordinate system.
  112. */
  113. private static final BitField CLIP_LH_ANGLES = BitFieldFactory.getInstance(0x0010);
  114. /** This value SHOULD NOT be used. */
  115. private static final BitField CLIP_TT_ALWAYS = BitFieldFactory.getInstance(0x0020);
  116. /** This value specifies that font association SHOULD< be turned off. */
  117. private static final BitField CLIP_DFA_DISABLE = BitFieldFactory.getInstance(0x0040);
  118. /**
  119. * This value specifies that font embedding MUST be used to render document content;
  120. * embedded fonts are read-only.
  121. */
  122. private static final BitField CLIP_EMBEDDED = BitFieldFactory.getInstance(0x0080);
  123. int flag;
  124. public int init(LittleEndianInputStream leis) {
  125. flag = leis.readUByte();
  126. return LittleEndianConsts.BYTE_SIZE;
  127. }
  128. @Override
  129. public String toString() {
  130. return
  131. (((flag&0x3) == 0 ? "default " : " ")+
  132. (CLIP_CHARACTER_PRECIS.isSet(flag) ? "char " : " ")+
  133. (CLIP_STROKE_PRECIS.isSet(flag) ? "stroke " : " ")+
  134. (CLIP_LH_ANGLES.isSet(flag) ? "angles " : " ")+
  135. (CLIP_TT_ALWAYS.isSet(flag) ? "tt_always " : " ")+
  136. (CLIP_DFA_DISABLE.isSet(flag) ? "dfa " : " ")+
  137. (CLIP_EMBEDDED.isSet(flag) ? "embedded " : " ")
  138. ).trim()
  139. ;
  140. }
  141. }
  142. /**
  143. * The output quality defines how carefully to attempt to match the logical font attributes to those of an actual
  144. * physical font.
  145. */
  146. public enum WmfFontQuality {
  147. /**
  148. * Specifies that the character quality of the font does not matter, so DRAFT_QUALITY can be used.
  149. */
  150. DEFAULT_QUALITY (0x00),
  151. /**
  152. * Specifies that the character quality of the font is less important than the
  153. * matching of logical attribuetes. For rasterized fonts, scaling SHOULD be enabled, which
  154. * means that more font sizes are available.
  155. */
  156. DRAFT_QUALITY (0x01),
  157. /**
  158. * Specifies that the character quality of the font is more important than the
  159. * matching of logical attributes. For rasterized fonts, scaling SHOULD be disabled, and the font
  160. * closest in size SHOULD be chosen.
  161. */
  162. PROOF_QUALITY (0x02),
  163. /**
  164. * Specifies that anti-aliasing SHOULD NOT be used when rendering text.
  165. */
  166. NONANTIALIASED_QUALITY (0x03),
  167. /**
  168. * Specifies that anti-aliasing SHOULD be used when rendering text, if the font supports it.
  169. */
  170. ANTIALIASED_QUALITY (0x04),
  171. /**
  172. * Specifies that ClearType anti-aliasing SHOULD be used when rendering text, if the font supports it.
  173. *
  174. * Fonts that do not support ClearType anti-aliasing include type 1 fonts, PostScript fonts,
  175. * OpenType fonts without TrueType outlines, rasterized fonts, vector fonts, and device fonts.
  176. */
  177. CLEARTYPE_QUALITY (0x05);
  178. int flag;
  179. WmfFontQuality(int flag) {
  180. this.flag = flag;
  181. }
  182. public static WmfFontQuality valueOf(int flag) {
  183. for (WmfFontQuality fq : values()) {
  184. if (fq.flag == flag) {
  185. return fq;
  186. }
  187. }
  188. return null;
  189. }
  190. }
  191. /**
  192. * A 16-bit signed integer that specifies the height, in logical units, of the font's
  193. * character cell. The character height is computed as the character cell height minus the
  194. * internal leading. The font mapper SHOULD interpret the height as follows.
  195. *
  196. * negative value:
  197. * The font mapper SHOULD transform this value into device units and match its
  198. * absolute value against the character height of available fonts.
  199. *
  200. * zero value:
  201. * A default height value MUST be used when creating a physical font.
  202. *
  203. * positive value:
  204. * The font mapper SHOULD transform this value into device units and match it
  205. * against the cell height of available fonts.
  206. *
  207. * For all height comparisons, the font mapper SHOULD find the largest physical
  208. * font that does not exceed the requested size.
  209. */
  210. protected int height;
  211. /**
  212. * A 16-bit signed integer that defines the average width, in logical units, of
  213. * characters in the font. If Width is 0x0000, the aspect ratio of the device SHOULD be matched
  214. * against the digitization aspect ratio of the available fonts to find the closest match,
  215. * determined by the absolute value of the difference.
  216. */
  217. protected int width;
  218. /**
  219. * A 16-bit signed integer that defines the angle, in tenths of degrees, between the
  220. * escapement vector and the x-axis of the device. The escapement vector is parallel
  221. * to the base line of a row of text.
  222. */
  223. protected int escapement;
  224. /**
  225. * A 16-bit signed integer that defines the angle, in tenths of degrees,
  226. * between each character's base line and the x-axis of the device.
  227. */
  228. protected int orientation;
  229. /**
  230. * A 16-bit signed integer that defines the weight of the font in the range 0
  231. * through 1000. For example, 400 is normal and 700 is bold. If this value is 0x0000,
  232. * a default weight SHOULD be used.
  233. */
  234. protected int weight;
  235. /**
  236. * A 8-bit Boolean value that specifies the italic attribute of the font.
  237. * 0 = not italic / 1 = italic.
  238. */
  239. protected boolean italic;
  240. /**
  241. * An 8-bit Boolean value that specifies the underline attribute of the font.
  242. * 0 = not underlined / 1 = underlined
  243. */
  244. protected boolean underline;
  245. /**
  246. * An 8-bit Boolean value that specifies the strike out attribute of the font.
  247. * 0 = not striked out / 1 = striked out
  248. */
  249. protected boolean strikeOut;
  250. /**
  251. * An 8-bit unsigned integer that defines the character set.
  252. * It SHOULD be set to a value in the {@link WmfCharset} Enumeration.
  253. *
  254. * The DEFAULT_CHARSET value MAY be used to allow the name and size of a font to fully
  255. * describe the logical font. If the specified font name does not exist, a font in another character
  256. * set MAY be substituted. The DEFAULT_CHARSET value is set to a value based on the current
  257. * system locale. For example, when the system locale is United States, it is set to ANSI_CHARSET.
  258. * If a typeface name in the FaceName field is specified, the CharSet value MUST match the
  259. * character set of that typeface.
  260. */
  261. protected FontCharset charSet;
  262. /**
  263. * An 8-bit unsigned integer that defines the output precision.
  264. */
  265. protected WmfOutPrecision outPrecision;
  266. /**
  267. * An 8-bit unsigned integer that defines the clipping precision.
  268. * These flags can be combined to specify multiple options.
  269. *
  270. * @see WmfClipPrecision
  271. */
  272. protected final WmfClipPrecision clipPrecision = new WmfClipPrecision();
  273. /**
  274. * An 8-bit unsigned integer that defines the output quality.
  275. */
  276. protected WmfFontQuality quality;
  277. /**
  278. * A PitchAndFamily object that defines the pitch and the family of the font.
  279. * Font families specify the look of fonts in a general way and are intended for
  280. * specifying fonts when the exact typeface wanted is not available.
  281. */
  282. protected int pitchAndFamily;
  283. /**
  284. * Font families specify the look of fonts in a general way and are
  285. * intended for specifying fonts when the exact typeface wanted is not available.
  286. * (LSB 4 bits)
  287. */
  288. protected FontFamily family;
  289. /**
  290. * A property of a font that describes the pitch (MSB 2 bits)
  291. */
  292. protected FontPitch pitch;
  293. /**
  294. * A null-terminated string of 8-bit Latin-1 [ISO/IEC-8859-1] ANSI
  295. * characters that specifies the typeface name of the font. The length of this string MUST NOT
  296. * exceed 32 8-bit characters, including the terminating null.
  297. */
  298. protected String facename;
  299. public int init(LittleEndianInputStream leis, long recordSize) throws IOException {
  300. height = leis.readShort();
  301. width = leis.readShort();
  302. escapement = leis.readShort();
  303. orientation = leis.readShort();
  304. weight = leis.readShort();
  305. italic = leis.readByte() != 0;
  306. underline = leis.readByte() != 0;
  307. strikeOut = leis.readByte() != 0;
  308. charSet = FontCharset.valueOf(leis.readUByte());
  309. outPrecision = WmfOutPrecision.valueOf(leis.readUByte());
  310. clipPrecision.init(leis);
  311. quality = WmfFontQuality.valueOf(leis.readUByte());
  312. pitchAndFamily = leis.readUByte();
  313. StringBuilder sb = new StringBuilder();
  314. int readBytes = readString(leis, sb, 32);
  315. if (readBytes == -1) {
  316. throw new IOException("Font facename can't be determined.");
  317. }
  318. facename = sb.toString();
  319. return 5*LittleEndianConsts.SHORT_SIZE+8*LittleEndianConsts.BYTE_SIZE+readBytes;
  320. }
  321. public void initDefaults() {
  322. height = -12;
  323. width = 0;
  324. escapement = 0;
  325. weight = 400;
  326. italic = false;
  327. underline = false;
  328. strikeOut = false;
  329. charSet = FontCharset.ANSI;
  330. outPrecision = WmfOutPrecision.OUT_DEFAULT_PRECIS;
  331. quality = WmfFontQuality.ANTIALIASED_QUALITY;
  332. pitchAndFamily = FontFamily.FF_DONTCARE.getFlag() | (FontPitch.DEFAULT.getNativeId() << 6);
  333. facename = "SansSerif";
  334. }
  335. public int getHeight() {
  336. return height;
  337. }
  338. public int getWidth() {
  339. return width;
  340. }
  341. public int getEscapement() {
  342. return escapement;
  343. }
  344. public int getOrientation() {
  345. return orientation;
  346. }
  347. public int getWeight() {
  348. return weight;
  349. }
  350. public boolean isItalic() {
  351. return italic;
  352. }
  353. public boolean isUnderline() {
  354. return underline;
  355. }
  356. public boolean isStrikeOut() {
  357. return strikeOut;
  358. }
  359. public WmfOutPrecision getOutPrecision() {
  360. return outPrecision;
  361. }
  362. public WmfClipPrecision getClipPrecision() {
  363. return clipPrecision;
  364. }
  365. public WmfFontQuality getQuality() {
  366. return quality;
  367. }
  368. public int getPitchAndFamily() {
  369. return pitchAndFamily;
  370. }
  371. @Override
  372. public FontFamily getFamily() {
  373. return FontFamily.valueOf(pitchAndFamily & 0xF);
  374. }
  375. @Override
  376. public void setFamily(FontFamily family) {
  377. throw new UnsupportedOperationException("setCharset not supported by HwmfFont.");
  378. }
  379. @Override
  380. public FontPitch getPitch() {
  381. return FontPitch.valueOf((pitchAndFamily >>> 6) & 3);
  382. }
  383. @Override
  384. public void setPitch(FontPitch pitch) {
  385. throw new UnsupportedOperationException("setPitch not supported by HwmfFont.");
  386. }
  387. @Override
  388. public Integer getIndex() {
  389. return null;
  390. }
  391. @Override
  392. public void setIndex(int index) {
  393. throw new UnsupportedOperationException("setIndex not supported by HwmfFont.");
  394. }
  395. @Override
  396. public String getTypeface() {
  397. return facename;
  398. }
  399. @Override
  400. public void setTypeface(String typeface) {
  401. throw new UnsupportedOperationException("setTypeface not supported by HwmfFont.");
  402. }
  403. @Override
  404. public FontCharset getCharset() {
  405. return charSet;
  406. }
  407. @Override
  408. public void setCharset(FontCharset charset) {
  409. throw new UnsupportedOperationException("setCharset not supported by HwmfFont.");
  410. }
  411. @Override
  412. public String toString() {
  413. return "{ height: "+height+
  414. ", width: "+width+
  415. ", escapment: "+escapement+
  416. ", weight: "+weight+
  417. ", italic: "+italic+
  418. ", underline: "+underline+
  419. ", strikeOut: "+strikeOut+
  420. ", charset: '"+charSet+"'"+
  421. ", outPrecision: '"+outPrecision+"'"+
  422. ", clipPrecision: '"+clipPrecision+"'"+
  423. ", quality: '"+quality+"'"+
  424. ", pitch: '"+getPitch()+"'"+
  425. ", family: '"+getFamily()+"'"+
  426. ", facename: '"+facename+"'"+
  427. "}";
  428. }
  429. protected int readString(LittleEndianInputStream leis, StringBuilder sb, int limit) throws IOException {
  430. byte buf[] = new byte[limit], b, readBytes = 0;
  431. do {
  432. if (readBytes == limit) {
  433. return -1;
  434. }
  435. buf[readBytes++] = b = leis.readByte();
  436. } while (b != 0 && b != -1 && readBytes <= limit);
  437. sb.append(new String(buf, 0, readBytes-1, StandardCharsets.ISO_8859_1));
  438. return readBytes;
  439. }
  440. }