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.

PDFRoot.java 9.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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.IOException;
  20. import java.io.OutputStream;
  21. import java.util.Locale;
  22. import org.apache.fop.util.LanguageTags;
  23. /**
  24. * Class representing a Root (/Catalog) object.
  25. */
  26. public class PDFRoot extends PDFDictionary {
  27. /**
  28. * Use no page mode setting, default
  29. */
  30. public static final int PAGEMODE_USENONE = 0;
  31. /**
  32. * Use outlines page mode to show bookmarks
  33. */
  34. public static final int PAGEMODE_USEOUTLINES = 1;
  35. /**
  36. * Use thumbs page mode to show thumbnail images
  37. */
  38. public static final int PAGEMODE_USETHUMBS = 2;
  39. /**
  40. * Full screen page mode
  41. */
  42. public static final int PAGEMODE_FULLSCREEN = 3;
  43. private final PDFDocument document;
  44. private PDFDPartRoot dPartRoot;
  45. private PDFArray af;
  46. private static final PDFName[] PAGEMODE_NAMES = new PDFName[] {
  47. new PDFName("UseNone"),
  48. new PDFName("UseOutlines"),
  49. new PDFName("UseThumbs"),
  50. new PDFName("FullScreen"),
  51. };
  52. /**
  53. * create a Root (/Catalog) object. NOTE: The PDFRoot
  54. * object must be created before the PDF document is
  55. * generated, but it is not assigned an object ID until
  56. * it is about to be written (immediately before the xref
  57. * table as part of the trailer). (mark-fop@inomial.com)
  58. *
  59. * @param document TODO
  60. * @param pages the PDFPages object
  61. */
  62. public PDFRoot(PDFDocument document, PDFPages pages) {
  63. this.document = document;
  64. setObjectNumber(document);
  65. put("Type", new PDFName("Catalog"));
  66. setRootPages(pages);
  67. setLanguage("x-unknown");
  68. }
  69. /** {@inheritDoc} */
  70. public int output(OutputStream stream) throws IOException {
  71. if (document.getProfile().getPDFUAMode().isEnabled()) {
  72. PDFDictionary d = new PDFDictionary();
  73. d.put("DisplayDocTitle", true);
  74. put("ViewerPreferences", d);
  75. }
  76. getDocument().getProfile().verifyTaggedPDF();
  77. return super.output(stream);
  78. }
  79. /**
  80. * Set the page mode for the PDF document.
  81. *
  82. * @param mode the page mode (one of PAGEMODE_*)
  83. */
  84. public void setPageMode(int mode) {
  85. put("PageMode", PAGEMODE_NAMES[mode]);
  86. }
  87. /**
  88. * Returns the currently active /PageMode.
  89. * @return the /PageMode (one of PAGEMODE_*)
  90. */
  91. public int getPageMode() {
  92. PDFName mode = (PDFName)get("PageMode");
  93. if (mode != null) {
  94. for (int i = 0; i < PAGEMODE_NAMES.length; i++) {
  95. if (PAGEMODE_NAMES[i].equals(mode)) {
  96. return i;
  97. }
  98. }
  99. throw new IllegalStateException("Unknown /PageMode encountered: " + mode);
  100. } else {
  101. return PAGEMODE_USENONE;
  102. }
  103. }
  104. /**
  105. * add a /Page object to the root /Pages object
  106. *
  107. * @param page the /Page object to add
  108. */
  109. public void addPage(PDFPage page) {
  110. PDFPages pages = getRootPages();
  111. pages.addPage(page);
  112. }
  113. /**
  114. * set the root /Pages object
  115. *
  116. * @param pages the /Pages object to set as root
  117. */
  118. public void setRootPages(PDFPages pages) {
  119. put("Pages", pages.makeReference());
  120. }
  121. /**
  122. * Returns the /PageLabels object.
  123. * @return the /PageLabels object if set, null otherwise.
  124. * @since PDF 1.3
  125. */
  126. public PDFPages getRootPages() {
  127. PDFReference ref = (PDFReference)get("Pages");
  128. return (ref != null ? (PDFPages)ref.getObject() : null);
  129. }
  130. /**
  131. * Sets the /PageLabels object.
  132. * @param pageLabels the /PageLabels object
  133. */
  134. public void setPageLabels(PDFPageLabels pageLabels) {
  135. put("PageLabels", pageLabels.makeReference());
  136. }
  137. /**
  138. * Returns the /PageLabels object.
  139. * @return the /PageLabels object if set, null otherwise.
  140. * @since PDF 1.3
  141. */
  142. public PDFPageLabels getPageLabels() {
  143. PDFReference ref = (PDFReference)get("PageLabels");
  144. return (ref != null ? (PDFPageLabels)ref.getObject() : null);
  145. }
  146. /**
  147. * Set the root outline for the PDF document.
  148. *
  149. * @param out the root PDF Outline
  150. */
  151. public void setRootOutline(PDFOutline out) {
  152. put("Outlines", out.makeReference());
  153. //Set /PageMode to /UseOutlines by default if no other mode has been set
  154. PDFName mode = (PDFName)get("PageMode");
  155. if (mode == null) {
  156. setPageMode(PAGEMODE_USEOUTLINES);
  157. }
  158. }
  159. /**
  160. * Get the root PDF outline for the document.
  161. *
  162. * @return the root PDF Outline
  163. */
  164. public PDFOutline getRootOutline() {
  165. PDFReference ref = (PDFReference)get("Outlines");
  166. return (ref != null ? (PDFOutline)ref.getObject() : null);
  167. }
  168. /**
  169. * Set the /Names object.
  170. * @param names the Names object
  171. * @since PDF 1.2
  172. */
  173. public void setNames(PDFNames names) {
  174. put("Names", names.makeReference());
  175. }
  176. /**
  177. * Returns the /Names object.
  178. * @return the Names object if set, null otherwise.
  179. * @since PDF 1.2
  180. */
  181. public PDFNames getNames() {
  182. PDFReference ref = (PDFReference)get("Names");
  183. return (ref != null ? (PDFNames)ref.getObject() : null);
  184. }
  185. /**
  186. * Set the optional Metadata object.
  187. * @param meta the Metadata object
  188. * @since PDF 1.4
  189. */
  190. public void setMetadata(PDFMetadata meta) {
  191. if (getDocumentSafely().getPDFVersion().compareTo(Version.V1_4) >= 0) {
  192. put("Metadata", meta.makeReference());
  193. }
  194. }
  195. /**
  196. * Returns the /Metadata object
  197. * @return the /Metadata object if set, null otherwise.
  198. * @since PDF 1.4
  199. */
  200. public PDFMetadata getMetadata() {
  201. PDFReference ref = (PDFReference)get("Metadata");
  202. return (ref != null ? (PDFMetadata)ref.getObject() : null);
  203. }
  204. /**
  205. * Returns the /OutputIntents array.
  206. * @return the /OutputIntents array or null if it doesn't exist
  207. * @since PDF 1.4
  208. */
  209. public PDFArray getOutputIntents() {
  210. return (PDFArray)get("OutputIntents");
  211. }
  212. /**
  213. * Adds an OutputIntent to the PDF
  214. * @param outputIntent the OutputIntent dictionary
  215. * @since PDF 1.4
  216. */
  217. public void addOutputIntent(PDFOutputIntent outputIntent) {
  218. if (getDocumentSafely().getPDFVersion().compareTo(Version.V1_4) >= 0) {
  219. PDFArray outputIntents = getOutputIntents();
  220. if (outputIntents == null) {
  221. outputIntents = new PDFArray(this);
  222. put("OutputIntents", outputIntents);
  223. }
  224. outputIntents.add(outputIntent);
  225. }
  226. }
  227. /**
  228. * Sets the "Version" entry. If this version is greater than that specified in the header, this
  229. * version takes precedence.
  230. *
  231. * @param version the PDF document version
  232. * @since PDF 1.4
  233. */
  234. void setVersion(Version version) {
  235. put("Version", new PDFName(version.toString()));
  236. }
  237. /**
  238. * Returns the language identifier of the document.
  239. * @return the language identifier of the document (or null if not set or undefined)
  240. * @since PDF 1.4
  241. */
  242. public String getLanguage() {
  243. return (String)get("Lang");
  244. }
  245. /**
  246. * Sets the locale of the document.
  247. * @param locale the locale of the document.
  248. */
  249. public void setLanguage(Locale locale) {
  250. if (locale == null) {
  251. throw new NullPointerException("locale must not be null");
  252. }
  253. setLanguage(LanguageTags.toLanguageTag(locale));
  254. }
  255. private void setLanguage(String lang) {
  256. put("Lang", lang);
  257. }
  258. /**
  259. * Sets the StructTreeRoot object. Used for accessibility.
  260. * @param structTreeRoot of this document
  261. */
  262. public void setStructTreeRoot(PDFStructTreeRoot structTreeRoot) {
  263. if (structTreeRoot == null) {
  264. throw new NullPointerException("structTreeRoot must not be null");
  265. }
  266. put("StructTreeRoot", structTreeRoot);
  267. }
  268. /**
  269. * Returns the StructTreeRoot object.
  270. * @return the structure tree root (or null if accessibility is not enabled)
  271. */
  272. public PDFStructTreeRoot getStructTreeRoot() {
  273. return (PDFStructTreeRoot)get("StructTreeRoot");
  274. }
  275. /**
  276. * Marks this document as conforming to the Tagged PDF conventions.
  277. */
  278. public void makeTagged() {
  279. PDFDictionary dict = new PDFDictionary();
  280. dict.put("Marked", Boolean.TRUE);
  281. put("MarkInfo", dict); //new PDFMarkInfo()
  282. }
  283. /**
  284. * Returns the MarkInfo dictionary.
  285. * @return the MarkInfo dictionary (or null if it's not present)
  286. */
  287. public PDFDictionary getMarkInfo() {
  288. return (PDFDictionary)get("MarkInfo");
  289. }
  290. public PDFDPartRoot getDPartRoot() {
  291. if (dPartRoot == null) {
  292. dPartRoot = getDocument().getFactory().makeDPartRoot();
  293. put("DPartRoot", dPartRoot.makeReference());
  294. }
  295. return dPartRoot;
  296. }
  297. public void addAF(PDFFileSpec fileSpec) {
  298. if (af == null) {
  299. af = new PDFArray();
  300. put("AF", af);
  301. }
  302. af.add(fileSpec);
  303. fileSpec.put("AFRelationship", new PDFName("Data"));
  304. }
  305. }