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.

PDFCIDFont.java 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  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.pdf;
  19. import java.io.ByteArrayOutputStream;
  20. import java.io.IOException;
  21. import java.util.Set;
  22. import org.apache.fop.fonts.CIDFontType;
  23. // based on work by Takayuki Takeuchi
  24. /**
  25. * Class representing a "character identifier" font (p 210 and onwards).
  26. */
  27. public class PDFCIDFont extends PDFObject {
  28. private String basefont;
  29. private CIDFontType cidtype;
  30. private Integer dw;
  31. private PDFWArray w;
  32. private int[] dw2;
  33. private PDFWArray w2;
  34. private PDFCIDSystemInfo systemInfo;
  35. private PDFCIDFontDescriptor descriptor;
  36. private PDFCMap cmap;
  37. /**
  38. * /CIDToGIDMap (only for CIDFontType2, see p 212)
  39. * can be either "Identity" (default) or a PDFStream
  40. */
  41. private PDFStream cidMap;
  42. /**
  43. * Create the /Font object
  44. * @param basefont Name of the basefont
  45. * @param cidtype CID type
  46. * @param dw default width
  47. * @param w array of character widths
  48. * @param registry name of the issuer
  49. * @param ordering Unique name of the font
  50. * @param supplement Supplement number
  51. * @param descriptor CID font descriptor
  52. */
  53. public PDFCIDFont(String basefont, CIDFontType cidtype, int dw,
  54. int[] w, String registry, String ordering,
  55. int supplement, PDFCIDFontDescriptor descriptor) {
  56. this(basefont, cidtype, dw,
  57. new PDFWArray(w),
  58. new PDFCIDSystemInfo(registry, ordering, supplement),
  59. descriptor);
  60. }
  61. /**
  62. * Create the /Font object
  63. * @param basefont Name of the basefont
  64. * @param cidtype CID type
  65. * @param dw default width
  66. * @param w array of character widths
  67. * @param systemInfo CID system info
  68. * @param descriptor CID font descriptor
  69. */
  70. public PDFCIDFont(String basefont, CIDFontType cidtype, int dw,
  71. int[] w, PDFCIDSystemInfo systemInfo,
  72. PDFCIDFontDescriptor descriptor) {
  73. this(basefont, cidtype, dw,
  74. new PDFWArray(w),
  75. systemInfo,
  76. descriptor);
  77. }
  78. /**
  79. * Create the /Font object
  80. * @param basefont Name of the basefont
  81. * @param cidtype CID type
  82. * @param dw default width
  83. * @param w array of character widths
  84. * @param systemInfo CID system info
  85. * @param descriptor CID font descriptor
  86. */
  87. public PDFCIDFont(String basefont, CIDFontType cidtype, int dw,
  88. PDFWArray w, PDFCIDSystemInfo systemInfo,
  89. PDFCIDFontDescriptor descriptor) {
  90. super();
  91. this.basefont = basefont;
  92. this.cidtype = cidtype;
  93. this.dw = dw;
  94. this.w = w;
  95. this.dw2 = null;
  96. this.w2 = null;
  97. systemInfo.setParent(this);
  98. this.systemInfo = systemInfo;
  99. this.descriptor = descriptor;
  100. this.cidMap = null;
  101. this.cmap = null;
  102. }
  103. /**
  104. * Set the /DW attribute
  105. * @param dw the default width
  106. */
  107. public void setDW(int dw) {
  108. this.dw = dw;
  109. }
  110. /**
  111. * Set the /W array
  112. * @param w the width array
  113. */
  114. public void setW(PDFWArray w) {
  115. this.w = w;
  116. }
  117. /**
  118. * Set the (two elements) /DW2 array
  119. * @param dw2 the default metrics for vertical writing
  120. */
  121. public void setDW2(int[] dw2) {
  122. this.dw2 = dw2;
  123. }
  124. /**
  125. * Set the two elements of the /DW2 array
  126. * @param posY position vector
  127. * @param displacementY displacement vector
  128. */
  129. public void setDW2(int posY, int displacementY) {
  130. this.dw2 = new int[] {
  131. posY, displacementY
  132. };
  133. }
  134. /**
  135. * Set the CMap used as /ToUnicode cmap
  136. * @param cmap character map
  137. */
  138. public void setCMAP(PDFCMap cmap) {
  139. this.cmap = cmap;
  140. }
  141. /**
  142. * Set the /W2 array
  143. * @param w2 array of metrics for vertical writing
  144. */
  145. public void setW2(PDFWArray w2) {
  146. this.w2 = w2;
  147. }
  148. /**
  149. * Set the /CIDToGIDMap (to be used only for CIDFontType2)
  150. * @param map mapping information
  151. */
  152. public void setCIDMap(PDFStream map) {
  153. this.cidMap = map;
  154. }
  155. /**
  156. * Set the /CIDToGIDMap (to be used only for CIDFontType2) to "Identity"
  157. */
  158. public void setCIDMapIdentity() {
  159. this.cidMap = null; // not an error here, simply use the default
  160. }
  161. /**
  162. * Returns the PDF name for a certain CID font type.
  163. * @param cidFontType CID font type
  164. * @return corresponding PDF name
  165. */
  166. protected String getPDFNameForCIDFontType(CIDFontType cidFontType) {
  167. if (cidFontType == CIDFontType.CIDTYPE0) {
  168. return cidFontType.getName();
  169. } else if (cidFontType == CIDFontType.CIDTYPE2) {
  170. return cidFontType.getName();
  171. } else {
  172. throw new IllegalArgumentException("Unsupported CID font type: "
  173. + cidFontType.getName());
  174. }
  175. }
  176. /**
  177. * {@inheritDoc}
  178. */
  179. public String toPDFString() {
  180. StringBuffer p = new StringBuffer(128);
  181. p.append("<< /Type /Font");
  182. p.append("\n/BaseFont /");
  183. p.append(this.basefont);
  184. p.append(" \n/CIDToGIDMap ");
  185. if (cidMap != null) {
  186. p.append(cidMap.referencePDF());
  187. } else {
  188. p.append("/Identity");
  189. //This is the default. We still write it because PDF/A requires it.
  190. }
  191. p.append(" \n/Subtype /");
  192. p.append(getPDFNameForCIDFontType(this.cidtype));
  193. p.append("\n");
  194. p.append(systemInfo.toPDFString());
  195. p.append("\n/FontDescriptor ");
  196. p.append(this.descriptor.referencePDF());
  197. if (cmap != null) {
  198. p.append("\n/ToUnicode ");
  199. p.append(cmap.referencePDF());
  200. }
  201. if (dw != null) {
  202. p.append("\n/DW ");
  203. p.append(this.dw);
  204. }
  205. if (w != null) {
  206. p.append("\n/W ");
  207. p.append(w.toPDFString());
  208. }
  209. if (dw2 != null) {
  210. p.append("\n/DW2 ["); // always two values, see p 211
  211. p.append(this.dw2[0]);
  212. p.append(this.dw2[1]);
  213. p.append("]");
  214. }
  215. if (w2 != null) {
  216. p.append("\n/W2 ");
  217. p.append(w2.toPDFString());
  218. }
  219. p.append("\n>>");
  220. return p.toString();
  221. }
  222. /**
  223. * {@inheritDoc}
  224. */
  225. public byte[] toPDF() {
  226. ByteArrayOutputStream bout = new ByteArrayOutputStream(128);
  227. try {
  228. bout.write(encode("<< /Type /Font\n"));
  229. bout.write(encode("/BaseFont /"));
  230. bout.write(encode(this.basefont));
  231. bout.write(encode(" \n"));
  232. bout.write(encode("/CIDToGIDMap "));
  233. bout.write(encode(cidMap != null ? cidMap.referencePDF() : "/Identity"));
  234. bout.write(encode(" \n"));
  235. bout.write(encode("/Subtype /"));
  236. bout.write(encode(getPDFNameForCIDFontType(this.cidtype)));
  237. bout.write(encode("\n"));
  238. bout.write(encode("/CIDSystemInfo "));
  239. bout.write(systemInfo.toPDF());
  240. bout.write(encode("\n"));
  241. bout.write(encode("/FontDescriptor "));
  242. bout.write(encode(this.descriptor.referencePDF()));
  243. bout.write(encode("\n"));
  244. if (cmap != null) {
  245. bout.write(encode("/ToUnicode "));
  246. bout.write(encode(cmap.referencePDF()));
  247. bout.write(encode("\n"));
  248. }
  249. if (dw != null) {
  250. bout.write(encode("/DW "));
  251. bout.write(encode(this.dw.toString()));
  252. bout.write(encode("\n"));
  253. }
  254. if (w != null) {
  255. bout.write(encode("/W "));
  256. bout.write(encode(w.toPDFString()));
  257. bout.write(encode("\n"));
  258. }
  259. if (dw2 != null) {
  260. bout.write(encode("/DW2 [")); // always two values, see p 211
  261. bout.write(encode(Integer.toString(this.dw2[0])));
  262. bout.write(encode(Integer.toString(this.dw2[1])));
  263. bout.write(encode("]\n"));
  264. }
  265. if (w2 != null) {
  266. bout.write(encode("/W2 "));
  267. bout.write(encode(w2.toPDFString()));
  268. bout.write(encode("\n"));
  269. }
  270. bout.write(encode(">>"));
  271. } catch (IOException ioe) {
  272. log.error("Ignored I/O exception", ioe);
  273. }
  274. return bout.toByteArray();
  275. }
  276. @Override
  277. public void getChildren(Set<PDFObject> children) {
  278. super.getChildren(children);
  279. if (cidMap != null) {
  280. children.add(cidMap);
  281. cidMap.getChildren(children);
  282. }
  283. children.add(descriptor);
  284. descriptor.getChildren(children);
  285. if (cmap != null) {
  286. children.add(cmap);
  287. cmap.getChildren(children);
  288. }
  289. }
  290. }