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.

PDFProfile.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  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.text.MessageFormat;
  20. /**
  21. * This class allows tracks the enabled PDF profiles (PDF/A and PDF/X) and provides methods to
  22. * the libarary and its users to enable the generation of PDFs conforming to the enabled PDF
  23. * profiles.
  24. * <p>
  25. * Some profile from PDF/X and PDF/A can be active simultaneously (example: PDF/A-1 and
  26. * PDF/X-3:2003).
  27. */
  28. public class PDFProfile {
  29. /**
  30. * Indicates the PDF/A mode currently active. Defaults to "no restrictions", i.e.
  31. * PDF/A not active.
  32. */
  33. protected PDFAMode pdfAMode = PDFAMode.DISABLED;
  34. protected PDFUAMode pdfUAMode = PDFUAMode.DISABLED;
  35. /**
  36. * Indicates the PDF/X mode currently active. Defaults to "no restrictions", i.e.
  37. * PDF/X not active.
  38. */
  39. protected PDFXMode pdfXMode = PDFXMode.DISABLED;
  40. protected PDFVTMode pdfVTMode = PDFVTMode.DISABLED;
  41. private PDFDocument doc;
  42. /**
  43. * Main constructor
  44. * @param doc the PDF document
  45. */
  46. public PDFProfile(PDFDocument doc) {
  47. this.doc = doc;
  48. }
  49. /**
  50. * Validates if the requested profile combination is compatible.
  51. */
  52. protected void validateProfileCombination() {
  53. if (pdfAMode != PDFAMode.DISABLED) {
  54. if (pdfAMode == PDFAMode.PDFA_1B) {
  55. if (pdfXMode != PDFXMode.DISABLED && pdfXMode != PDFXMode.PDFX_3_2003 && pdfXMode != PDFXMode.PDFX_4) {
  56. throw new PDFConformanceException(
  57. pdfAMode + " and " + pdfXMode + " are not compatible!");
  58. }
  59. }
  60. }
  61. if (pdfVTMode != PDFVTMode.DISABLED && pdfXMode != PDFXMode.PDFX_4) {
  62. throw new PDFConformanceException(pdfVTMode.name() + " requires " + PDFXMode.PDFX_4.getName() + " enabled");
  63. }
  64. }
  65. /** @return the PDFDocument this profile is attached to */
  66. public PDFDocument getDocument() {
  67. return this.doc;
  68. }
  69. /** @return the PDF/A mode */
  70. public PDFAMode getPDFAMode() {
  71. return this.pdfAMode;
  72. }
  73. public PDFUAMode getPDFUAMode() {
  74. return this.pdfUAMode;
  75. }
  76. /** @return true if any PDF/A mode is active */
  77. public boolean isPDFAActive() {
  78. return getPDFAMode() != PDFAMode.DISABLED;
  79. }
  80. /**
  81. * Sets the PDF/A mode
  82. * @param mode the PDF/A mode
  83. */
  84. public void setPDFAMode(PDFAMode mode) {
  85. if (mode == null) {
  86. mode = PDFAMode.DISABLED;
  87. }
  88. this.pdfAMode = mode;
  89. validateProfileCombination();
  90. }
  91. public void setPDFUAMode(PDFUAMode mode) {
  92. if (mode == null) {
  93. mode = PDFUAMode.DISABLED;
  94. }
  95. this.pdfUAMode = mode;
  96. validateProfileCombination();
  97. }
  98. /** @return the PDF/X mode */
  99. public PDFXMode getPDFXMode() {
  100. return this.pdfXMode;
  101. }
  102. public PDFVTMode getPDFVTMode() {
  103. return this.pdfVTMode;
  104. }
  105. /** @return true if any PDF/X mode is active */
  106. public boolean isPDFXActive() {
  107. return getPDFXMode() != PDFXMode.DISABLED;
  108. }
  109. public boolean isPDFVTActive() {
  110. return getPDFVTMode() != PDFVTMode.DISABLED;
  111. }
  112. /**
  113. * Sets the PDF/X mode
  114. * @param mode the PDF/X mode
  115. */
  116. public void setPDFXMode(PDFXMode mode) {
  117. if (mode == null) {
  118. mode = PDFXMode.DISABLED;
  119. }
  120. this.pdfXMode = mode;
  121. validateProfileCombination();
  122. }
  123. /**
  124. * Sets the PDF/X mode
  125. * @param mode the PDF/X mode
  126. */
  127. public void setPDFVTMode(PDFVTMode mode) {
  128. if (mode == null) {
  129. mode = PDFVTMode.DISABLED;
  130. }
  131. this.pdfVTMode = mode;
  132. validateProfileCombination();
  133. }
  134. /** {@inheritDoc} */
  135. public String toString() {
  136. StringBuffer sb = new StringBuffer();
  137. if (isPDFAActive() && isPDFXActive()) {
  138. sb.append("[").append(getPDFAMode()).append(",").append(getPDFXMode()).append("]");
  139. } else if (isPDFAActive()) {
  140. sb.append(getPDFAMode());
  141. } else if (isPDFXActive()) {
  142. sb.append(getPDFXMode());
  143. } else if (getPDFUAMode().isEnabled()) {
  144. sb.append(getPDFUAMode());
  145. } else {
  146. sb.append(super.toString());
  147. }
  148. return sb.toString();
  149. }
  150. //---------=== Info and validation methods ===---------
  151. private String format(String pattern, Object[] args) {
  152. return MessageFormat.format(pattern, args);
  153. }
  154. private String format(String pattern, Object arg) {
  155. return format(pattern, new Object[] {arg});
  156. }
  157. /** Checks if encryption is allowed. */
  158. public void verifyEncryptionAllowed() {
  159. final String err = "{0} doesn't allow encrypted PDFs";
  160. if (isPDFAActive()) {
  161. throw new PDFConformanceException(format(err, getPDFAMode()));
  162. }
  163. if (isPDFXActive()) {
  164. throw new PDFConformanceException(format(err, getPDFXMode()));
  165. }
  166. }
  167. /** Checks if PostScript XObjects are allowed. */
  168. public void verifyPSXObjectsAllowed() {
  169. final String err = "PostScript XObjects are prohibited when {0}"
  170. + " is active. Convert EPS graphics to another format.";
  171. if (isPDFAActive()) {
  172. throw new PDFConformanceException(format(err, getPDFAMode()));
  173. }
  174. if (isPDFXActive()) {
  175. throw new PDFConformanceException(format(err, getPDFXMode()));
  176. }
  177. }
  178. /**
  179. * Checks if the use of transparency is allowed.
  180. * @param context Context information for the user to identify the problem spot
  181. */
  182. public void verifyTransparencyAllowed(String context) {
  183. Object profile = isTransparencyAllowed();
  184. if (profile != null) {
  185. throw new TransparencyDisallowedException(profile, context);
  186. }
  187. }
  188. /**
  189. * Returns {@code null} if transparency is allowed, otherwise returns the profile that
  190. * prevents it.
  191. *
  192. * @return {@code null}, or an object whose {@code toString} method returns the name
  193. * of the profile that disallows transparency
  194. */
  195. public Object isTransparencyAllowed() {
  196. if (pdfAMode.isPart1()) {
  197. return getPDFAMode();
  198. }
  199. if (getPDFXMode() == PDFXMode.PDFX_3_2003) {
  200. return getPDFXMode();
  201. }
  202. return null;
  203. }
  204. /** Checks if the right PDF version is set. */
  205. public void verifyPDFVersion() {
  206. String err = "PDF version must be 1.4 for {0}";
  207. if (getPDFAMode().isPart1()
  208. && !Version.V1_4.equals(getDocument().getPDFVersion())) {
  209. throw new PDFConformanceException(format(err, getPDFAMode()));
  210. }
  211. if (getPDFXMode() == PDFXMode.PDFX_3_2003
  212. && !Version.V1_4.equals(getDocument().getPDFVersion())) {
  213. throw new PDFConformanceException(format(err, getPDFXMode()));
  214. }
  215. }
  216. /**
  217. * Checks a few things required for tagged PDF.
  218. */
  219. public void verifyTaggedPDF() {
  220. if (getPDFAMode().isLevelA() || getPDFUAMode().isEnabled()) {
  221. final String err = "{0} requires the {1} dictionary entry to be set";
  222. String mode = getPDFAMode().toString();
  223. if (getPDFUAMode().isEnabled()) {
  224. mode = getPDFUAMode().toString();
  225. }
  226. PDFDictionary markInfo = getDocument().getRoot().getMarkInfo();
  227. if (markInfo == null) {
  228. throw new PDFConformanceException(format(
  229. "{0} requires that the accessibility option in the configuration file be enabled", mode));
  230. }
  231. if (!Boolean.TRUE.equals(markInfo.get("Marked"))) {
  232. throw new PDFConformanceException(format(err,
  233. new Object[] {mode, "Marked"}));
  234. }
  235. if (getDocument().getRoot().getStructTreeRoot() == null) {
  236. throw new PDFConformanceException(format(err,
  237. new Object[] {mode, "StructTreeRoot"}));
  238. }
  239. if (getDocument().getRoot().getLanguage() == null) {
  240. throw new PDFConformanceException(format(err,
  241. new Object[] {mode, "Lang"}));
  242. }
  243. }
  244. }
  245. /** @return true if the ID entry must be present in the trailer. */
  246. public boolean isIDEntryRequired() {
  247. return isPDFAActive() || isPDFXActive();
  248. }
  249. /** @return true if all fonts need to be embedded. */
  250. public boolean isFontEmbeddingRequired() {
  251. return isPDFAActive() || isPDFXActive() || getPDFUAMode().isEnabled();
  252. }
  253. /** Checks if a title may be absent. */
  254. public void verifyTitleAbsent() {
  255. final String err = "{0} requires the title to be set.";
  256. if (getPDFUAMode().isEnabled()) {
  257. throw new PDFConformanceException(format(err, getPDFUAMode()));
  258. }
  259. if (isPDFXActive()) {
  260. throw new PDFConformanceException(format(err, getPDFXMode()));
  261. }
  262. }
  263. /** @return true if the ModDate Info entry must be present. */
  264. public boolean isModDateRequired() {
  265. return getPDFXMode() != PDFXMode.DISABLED;
  266. }
  267. /** @return true if the Trapped Info entry must be present. */
  268. public boolean isTrappedEntryRequired() {
  269. return getPDFXMode() != PDFXMode.DISABLED;
  270. }
  271. /** @return true if annotations are allowed */
  272. public boolean isAnnotationAllowed() {
  273. return !isPDFXActive();
  274. }
  275. /** Checks if annotations are allowed. */
  276. public void verifyAnnotAllowed() {
  277. if (!isAnnotationAllowed()) {
  278. final String err = "{0} does not allow annotations inside the printable area.";
  279. //Note: this rule is simplified. Refer to the standard for details.
  280. throw new PDFConformanceException(format(err, getPDFXMode()));
  281. }
  282. }
  283. /** Checks if Actions are allowed. */
  284. public void verifyActionAllowed() {
  285. if (isPDFXActive()) {
  286. final String err = "{0} does not allow Actions.";
  287. throw new PDFConformanceException(format(err, getPDFXMode()));
  288. }
  289. }
  290. /** Checks if embedded files are allowed. */
  291. public void verifyEmbeddedFilesAllowed() {
  292. final String err = "{0} does not allow embedded files.";
  293. if (isPDFAActive() && getPDFAMode().getPart() < 3) {
  294. throw new PDFConformanceException(format(err, getPDFAMode()));
  295. }
  296. if (isPDFXActive()) {
  297. //Implicit since file specs are forbidden
  298. throw new PDFConformanceException(format(err, getPDFXMode()));
  299. }
  300. }
  301. }