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.

Trait.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689
  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.area;
  19. import java.awt.Color;
  20. import java.io.Serializable;
  21. import org.apache.xmlgraphics.image.loader.ImageInfo;
  22. import org.apache.fop.fonts.FontTriplet;
  23. import org.apache.fop.traits.BorderProps;
  24. import org.apache.fop.traits.Direction;
  25. import org.apache.fop.traits.WritingMode;
  26. import org.apache.fop.util.ColorUtil;
  27. import static org.apache.fop.fo.Constants.EN_NOREPEAT;
  28. import static org.apache.fop.fo.Constants.EN_REPEAT;
  29. import static org.apache.fop.fo.Constants.EN_REPEATX;
  30. import static org.apache.fop.fo.Constants.EN_REPEATY;
  31. // properties should be serialized by the holder
  32. /**
  33. * Area traits used for rendering.
  34. * This class represents an area trait that specifies a value for rendering.
  35. */
  36. public final class Trait implements Serializable {
  37. private static final long serialVersionUID = 3234280285391611437L;
  38. private Trait() {
  39. }
  40. /** Id reference line, not resolved. (not sure if this is needed.) */
  41. //public static final Integer ID_LINK = new Integer(0);
  42. /**
  43. * Internal link trait.
  44. * Contains the PageViewport key and the PROD_ID of the target area
  45. */
  46. public static final Integer INTERNAL_LINK = 1;
  47. /** * External link. A URL link to an external resource. */
  48. public static final Integer EXTERNAL_LINK = 2;
  49. /** The font triplet for the current font. */
  50. public static final Integer FONT = 3;
  51. /** Font size for the current font. */
  52. public static final Integer FONT_SIZE = 4;
  53. /** The current color. */
  54. public static final Integer COLOR = 7;
  55. /** The ID of the FO that produced an area. */
  56. public static final Integer PROD_ID = 8;
  57. /** Background trait for an area. */
  58. public static final Integer BACKGROUND = 9;
  59. /** Underline trait used when rendering inline parent. */
  60. public static final Integer UNDERLINE = 10;
  61. /** Overline trait used when rendering inline parent. */
  62. public static final Integer OVERLINE = 11;
  63. /** Linethrough trait used when rendering inline parent. */
  64. public static final Integer LINETHROUGH = 12;
  65. /** Shadow offset. */
  66. //public static final Integer OFFSET = new Integer(13);
  67. /** The shadow for text. */
  68. //public static final Integer SHADOW = new Integer(14);
  69. /** The border start. */
  70. public static final Integer BORDER_START = 15;
  71. /** The border end. */
  72. public static final Integer BORDER_END = 16;
  73. /** The border before. */
  74. public static final Integer BORDER_BEFORE = 17;
  75. /** The border after. */
  76. public static final Integer BORDER_AFTER = 18;
  77. /** The padding start. */
  78. public static final Integer PADDING_START = 19;
  79. /** The padding end. */
  80. public static final Integer PADDING_END = 20;
  81. /** The padding before. */
  82. public static final Integer PADDING_BEFORE = 21;
  83. /** The padding after. */
  84. public static final Integer PADDING_AFTER = 22;
  85. /** The space start. */
  86. public static final Integer SPACE_START = 23;
  87. /** The space end. */
  88. public static final Integer SPACE_END = 24;
  89. /** break before */
  90. //public static final Integer BREAK_BEFORE = new Integer(25);
  91. /** break after */
  92. //public static final Integer BREAK_AFTER = new Integer(26);
  93. /** The start-indent trait. */
  94. public static final Integer START_INDENT = 27;
  95. /** The end-indent trait. */
  96. public static final Integer END_INDENT = 28;
  97. /** The space-before trait. */
  98. public static final Integer SPACE_BEFORE = 29;
  99. /** The space-after trait. */
  100. public static final Integer SPACE_AFTER = 30;
  101. /** The is-reference-area trait. */
  102. public static final Integer IS_REFERENCE_AREA = 31;
  103. /** The is-viewport-area trait. */
  104. public static final Integer IS_VIEWPORT_AREA = 32;
  105. /** Blinking trait used when rendering inline parent. */
  106. public static final Integer BLINK = 33;
  107. /** Trait for color of underline decorations when rendering inline parent. */
  108. public static final Integer UNDERLINE_COLOR = 34;
  109. /** Trait for color of overline decorations when rendering inline parent. */
  110. public static final Integer OVERLINE_COLOR = 35;
  111. /** Trait for color of linethrough decorations when rendering inline parent. */
  112. public static final Integer LINETHROUGH_COLOR = 36;
  113. /** For navigation in the document structure. */
  114. public static final Integer STRUCTURE_TREE_ELEMENT = 37;
  115. /** writing mode trait */
  116. public static final Integer WRITING_MODE = 38;
  117. /** inline progression direction trait */
  118. public static final Integer INLINE_PROGRESSION_DIRECTION = 39;
  119. /** block progression direction trait */
  120. public static final Integer BLOCK_PROGRESSION_DIRECTION = 40;
  121. /** column progression direction trait */
  122. public static final Integer COLUMN_PROGRESSION_DIRECTION = 41;
  123. /** shift direction trait */
  124. public static final Integer SHIFT_DIRECTION = 42;
  125. /** For optional content groups. */
  126. public static final Integer LAYER = 43;
  127. /** Maximum value used by trait keys */
  128. public static final int MAX_TRAIT_KEY = 43;
  129. private static final TraitInfo[] TRAIT_INFO = new TraitInfo[MAX_TRAIT_KEY + 1];
  130. private static class TraitInfo {
  131. private String name;
  132. private Class clazz; // Class of trait data
  133. public TraitInfo(String name, Class clazz) {
  134. this.name = name;
  135. this.clazz = clazz;
  136. }
  137. public String getName() {
  138. return this.name;
  139. }
  140. public Class getClazz() {
  141. return this.clazz;
  142. }
  143. }
  144. private static void put(Integer key, TraitInfo info) {
  145. TRAIT_INFO[key] = info;
  146. }
  147. static {
  148. // Create a hashmap mapping trait code to name for external representation
  149. //put(ID_LINK, new TraitInfo("id-link", String.class));
  150. put(STRUCTURE_TREE_ELEMENT, new TraitInfo("structure-tree-element", String.class));
  151. put(INTERNAL_LINK, new TraitInfo("internal-link", InternalLink.class));
  152. put(EXTERNAL_LINK, new TraitInfo("external-link", ExternalLink.class));
  153. put(FONT, new TraitInfo("font", FontTriplet.class));
  154. put(FONT_SIZE, new TraitInfo("font-size", Integer.class));
  155. put(COLOR, new TraitInfo("color", Color.class));
  156. put(PROD_ID, new TraitInfo("prod-id", String.class));
  157. put(BACKGROUND, new TraitInfo("background", Background.class));
  158. put(UNDERLINE, new TraitInfo("underline-score", Boolean.class));
  159. put(UNDERLINE_COLOR, new TraitInfo("underline-score-color", Color.class));
  160. put(OVERLINE, new TraitInfo("overline-score", Boolean.class));
  161. put(OVERLINE_COLOR, new TraitInfo("overline-score-color", Color.class));
  162. put(LINETHROUGH, new TraitInfo("through-score", Boolean.class));
  163. put(LINETHROUGH_COLOR, new TraitInfo("through-score-color", Color.class));
  164. put(BLINK, new TraitInfo("blink", Boolean.class));
  165. //put(OFFSET, new TraitInfo("offset", Integer.class));
  166. //put(SHADOW, new TraitInfo("shadow", Integer.class));
  167. put(BORDER_START, new TraitInfo("border-start", BorderProps.class));
  168. put(BORDER_END, new TraitInfo("border-end", BorderProps.class));
  169. put(BORDER_BEFORE, new TraitInfo("border-before", BorderProps.class));
  170. put(BORDER_AFTER, new TraitInfo("border-after", BorderProps.class));
  171. put(PADDING_START, new TraitInfo("padding-start", Integer.class));
  172. put(PADDING_END, new TraitInfo("padding-end", Integer.class));
  173. put(PADDING_BEFORE, new TraitInfo("padding-before", Integer.class));
  174. put(PADDING_AFTER, new TraitInfo("padding-after", Integer.class));
  175. put(SPACE_START, new TraitInfo("space-start", Integer.class));
  176. put(SPACE_END, new TraitInfo("space-end", Integer.class));
  177. //put(BREAK_BEFORE, new TraitInfo("break-before", Integer.class));
  178. //put(BREAK_AFTER, new TraitInfo("break-after", Integer.class));
  179. put(START_INDENT, new TraitInfo("start-indent", Integer.class));
  180. put(END_INDENT, new TraitInfo("end-indent", Integer.class));
  181. put(SPACE_BEFORE, new TraitInfo("space-before", Integer.class));
  182. put(SPACE_AFTER, new TraitInfo("space-after", Integer.class));
  183. put(IS_REFERENCE_AREA, new TraitInfo("is-reference-area", Boolean.class));
  184. put(IS_VIEWPORT_AREA, new TraitInfo("is-viewport-area", Boolean.class));
  185. put(WRITING_MODE,
  186. new TraitInfo("writing-mode", WritingMode.class));
  187. put(INLINE_PROGRESSION_DIRECTION,
  188. new TraitInfo("inline-progression-direction", Direction.class));
  189. put(BLOCK_PROGRESSION_DIRECTION,
  190. new TraitInfo("block-progression-direction", Direction.class));
  191. put(SHIFT_DIRECTION,
  192. new TraitInfo("shift-direction", Direction.class));
  193. put(LAYER, new TraitInfo("layer", String.class));
  194. }
  195. /**
  196. * Get the trait name for a trait code.
  197. *
  198. * @param traitCode the trait code to get the name for
  199. * @return the trait name
  200. */
  201. public static String getTraitName(Object traitCode) {
  202. return TRAIT_INFO[(Integer)traitCode].getName();
  203. }
  204. /**
  205. * Get the data storage class for the trait.
  206. *
  207. * @param traitCode the trait code to lookup
  208. * @return the class type for the trait
  209. */
  210. public static Class getTraitClass(Object traitCode) {
  211. return TRAIT_INFO[(Integer)traitCode].getClazz();
  212. }
  213. /**
  214. * Class for internal link traits.
  215. * Stores PageViewport key and producer ID
  216. */
  217. public static class InternalLink implements Serializable {
  218. private static final long serialVersionUID = -8993505060996723039L;
  219. /** The unique key of the PageViewport. */
  220. private String pvKey;
  221. /** The PROD_ID of the link target */
  222. private String idRef;
  223. /**
  224. * Create an InternalLink to the given PageViewport and target ID
  225. *
  226. * @param pvKey the PageViewport key
  227. * @param idRef the target ID
  228. */
  229. public InternalLink(String pvKey, String idRef) {
  230. setPVKey(pvKey);
  231. setIDRef(idRef);
  232. }
  233. /**
  234. * Create an InternalLink based on the given XML attribute value.
  235. * This is typically called when data are read from an XML area tree.
  236. *
  237. * @param attrValue attribute value to be parsed by InternalLink.parseXMLAttribute
  238. */
  239. public InternalLink(String attrValue) {
  240. String[] values = parseXMLAttribute(attrValue);
  241. setPVKey(values[0]);
  242. setIDRef(values[1]);
  243. }
  244. /**
  245. * Sets the key of the targeted PageViewport.
  246. *
  247. * @param pvKey the PageViewport key
  248. */
  249. public void setPVKey(String pvKey) {
  250. this.pvKey = pvKey;
  251. }
  252. /**
  253. * Returns the key of the targeted PageViewport.
  254. *
  255. * @return the PageViewport key
  256. */
  257. public String getPVKey() {
  258. return pvKey;
  259. }
  260. /**
  261. * Sets the target ID.
  262. *
  263. * @param idRef the target ID
  264. */
  265. public void setIDRef(String idRef) {
  266. this.idRef = idRef;
  267. }
  268. /**
  269. * Returns the target ID.
  270. *
  271. * @return the target ID
  272. */
  273. public String getIDRef() {
  274. return idRef;
  275. }
  276. /**
  277. * Returns the attribute value for this object as
  278. * used in the area tree XML.
  279. *
  280. * @return a string of the type "(thisPVKey,thisIDRef)"
  281. */
  282. public String xmlAttribute() {
  283. return makeXMLAttribute(pvKey, idRef);
  284. }
  285. /**
  286. * Returns the XML attribute value for the given PV key and ID ref.
  287. * This value is used in the area tree XML.
  288. *
  289. * @param pvKey the PageViewport key of the link target
  290. * @param idRef the ID of the link target
  291. * @return a string of the type "(thisPVKey,thisIDRef)"
  292. */
  293. public static String makeXMLAttribute(String pvKey, String idRef) {
  294. return "(" + (pvKey == null ? "" : pvKey) + ","
  295. + (idRef == null ? "" : idRef) + ")";
  296. }
  297. /**
  298. * Parses XML attribute value from the area tree into
  299. * PageViewport key + IDRef strings. If the attribute value is
  300. * formatted like "(s1,s2)", then s1 and s2 are considered to be
  301. * the PV key and the IDRef, respectively.
  302. * Otherwise, the entire string is the PV key and the IDRef is null.
  303. *
  304. * @param attrValue the atribute value (PV key and possibly IDRef)
  305. * @return a 2-String array containing the PV key and the IDRef.
  306. * Both may be null.
  307. */
  308. public static String[] parseXMLAttribute(String attrValue) {
  309. String[] result = {null, null};
  310. if (attrValue != null) {
  311. int len = attrValue.length();
  312. if (len >= 2 && attrValue.charAt(0) == '(' && attrValue.charAt(len - 1) == ')'
  313. && attrValue.indexOf(',') != -1) {
  314. String value = attrValue.substring(1, len - 1); // remove brackets
  315. int delimIndex = value.indexOf(',');
  316. result[0] = value.substring(0, delimIndex).trim(); // PV key
  317. result[1] = value.substring(delimIndex + 1, value.length()).trim(); // IDRef
  318. } else {
  319. // PV key only, e.g. from old area tree XML:
  320. result[0] = attrValue;
  321. }
  322. }
  323. return result;
  324. }
  325. /**
  326. * Return the human-friendly string for debugging.
  327. * {@inheritDoc}
  328. */
  329. @Override
  330. public String toString() {
  331. StringBuffer sb = new StringBuffer();
  332. sb.append("pvKey=").append(pvKey);
  333. sb.append(",idRef=").append(idRef);
  334. return sb.toString();
  335. }
  336. }
  337. /**
  338. * External Link trait structure
  339. */
  340. public static class ExternalLink implements Serializable {
  341. private static final long serialVersionUID = -3720707599232620946L;
  342. private String destination;
  343. private boolean newWindow;
  344. /**
  345. * Constructs an ExternalLink object with the given destination
  346. *
  347. * @param destination target of the link
  348. * @param newWindow true if the target should be opened in a new window
  349. */
  350. public ExternalLink(String destination, boolean newWindow) {
  351. this.destination = destination;
  352. this.newWindow = newWindow;
  353. }
  354. /**
  355. * Create an <code>ExternalLink</code> from a trait value/attribute value in the
  356. * area tree
  357. * @param traitValue the value to use (should match the result of {@link #toString()}
  358. * @return an <code>ExternalLink</code> instance corresponding to the given value
  359. */
  360. protected static ExternalLink makeFromTraitValue(String traitValue) {
  361. String dest = null;
  362. boolean newWindow = false;
  363. String[] values = traitValue.split(",");
  364. for (int i = 0, c = values.length; i < c; i++) {
  365. String v = values[i];
  366. if (v.startsWith("dest=")) {
  367. dest = v.substring(5);
  368. } else if (v.startsWith("newWindow=")) {
  369. newWindow = Boolean.valueOf(v.substring(10));
  370. } else {
  371. throw new IllegalArgumentException(
  372. "Malformed trait value for Trait.ExternalLink: " + traitValue);
  373. }
  374. }
  375. return new ExternalLink(dest, newWindow);
  376. }
  377. /**
  378. * Get the target/destination of the link
  379. * @return the destination of the link
  380. */
  381. public String getDestination() {
  382. return this.destination;
  383. }
  384. /**
  385. * Check if the target has to be displayed in a new window
  386. * @return <code>true</code> if the target has to be displayed in a new window
  387. */
  388. public boolean newWindow() {
  389. return this.newWindow;
  390. }
  391. /**
  392. * Return a String representation of the object.
  393. * @return a <code>String</code> of the form
  394. * "org.apache.fop.area.Trait.ExternalLink[dest=someURL,newWindow=false]"
  395. */
  396. @Override
  397. public String toString() {
  398. StringBuffer sb = new StringBuffer(64);
  399. sb.append("newWindow=").append(newWindow);
  400. sb.append(",dest=").append(this.destination);
  401. return sb.toString();
  402. }
  403. }
  404. /**
  405. * Background trait structure.
  406. * Used for storing back trait information which are related.
  407. */
  408. public static class Background implements Serializable {
  409. private static final long serialVersionUID = 8452078676273242870L;
  410. /** The background color if any. */
  411. private Color color;
  412. /** The background image url if any. */
  413. private String url;
  414. /** The background image if any. */
  415. private ImageInfo imageInfo;
  416. /** Background repeat enum for images. */
  417. private int repeat;
  418. /** Background horizontal offset for images. */
  419. private int horiz;
  420. /** Background vertical offset for images. */
  421. private int vertical;
  422. private int imageTargetWidth;
  423. private int imageTargetHeight;
  424. /**
  425. * Returns the background color.
  426. * @return background color, null if n/a
  427. */
  428. public Color getColor() {
  429. return color;
  430. }
  431. /**
  432. * Returns the horizontal offset for images.
  433. * @return the horizontal offset
  434. */
  435. public int getHoriz() {
  436. return horiz;
  437. }
  438. /**
  439. * Returns the image repetition behaviour for images.
  440. * @return the image repetition behaviour
  441. */
  442. public int getRepeat() {
  443. return repeat;
  444. }
  445. /**
  446. * Returns the URL to the background image
  447. * @return URL to the background image, null if n/a
  448. */
  449. public String getURL() {
  450. return url;
  451. }
  452. /**
  453. * Returns the ImageInfo object representing the background image
  454. * @return the background image, null if n/a
  455. */
  456. public ImageInfo getImageInfo() {
  457. return imageInfo;
  458. }
  459. /**
  460. * Returns the vertical offset for images.
  461. * @return the vertical offset
  462. */
  463. public int getVertical() {
  464. return vertical;
  465. }
  466. /**
  467. * Sets the color.
  468. * @param color The color to set
  469. */
  470. public void setColor(Color color) {
  471. this.color = color;
  472. }
  473. /**
  474. * Sets the horizontal offset.
  475. * @param horiz The horizontal offset to set
  476. */
  477. public void setHoriz(int horiz) {
  478. this.horiz = horiz;
  479. }
  480. /**
  481. * Sets the image repetition behaviour for images.
  482. * @param repeat The image repetition behaviour to set
  483. */
  484. public void setRepeat(int repeat) {
  485. this.repeat = repeat;
  486. }
  487. /**
  488. * Sets the image repetition behaviour for images.
  489. * @param repeat The image repetition behaviour to set
  490. */
  491. public void setRepeat(String repeat) {
  492. setRepeat(getConstantForRepeat(repeat));
  493. }
  494. /**
  495. * Sets the URL to the background image.
  496. * @param url The URL to set
  497. */
  498. public void setURL(String url) {
  499. this.url = url;
  500. }
  501. /**
  502. * Sets the ImageInfo of the image to use as the background image.
  503. * @param info The background image's info object
  504. */
  505. public void setImageInfo(ImageInfo info) {
  506. this.imageInfo = info;
  507. }
  508. /**
  509. * Sets the vertical offset for images.
  510. * @param vertical The vertical offset to set
  511. */
  512. public void setVertical(int vertical) {
  513. this.vertical = vertical;
  514. }
  515. private String getRepeatString() {
  516. switch (getRepeat()) {
  517. case EN_REPEAT: return "repeat";
  518. case EN_REPEATX: return "repeat-x";
  519. case EN_REPEATY: return "repeat-y";
  520. case EN_NOREPEAT: return "no-repeat";
  521. default: throw new IllegalStateException("Illegal repeat style: " + getRepeat());
  522. }
  523. }
  524. private static int getConstantForRepeat(String repeat) {
  525. if ("repeat".equalsIgnoreCase(repeat)) {
  526. return EN_REPEAT;
  527. } else if ("repeat-x".equalsIgnoreCase(repeat)) {
  528. return EN_REPEATX;
  529. } else if ("repeat-y".equalsIgnoreCase(repeat)) {
  530. return EN_REPEATY;
  531. } else if ("no-repeat".equalsIgnoreCase(repeat)) {
  532. return EN_NOREPEAT;
  533. } else {
  534. throw new IllegalStateException("Illegal repeat style: " + repeat);
  535. }
  536. }
  537. /**
  538. * Return the string for debugging.
  539. * {@inheritDoc}
  540. */
  541. @Override
  542. public String toString() {
  543. StringBuffer sb = new StringBuffer();
  544. if (color != null) {
  545. sb.append("color=").append(ColorUtil.colorToString(color));
  546. }
  547. if (url != null) {
  548. if (color != null) {
  549. sb.append(",");
  550. }
  551. sb.append("url=").append(url);
  552. sb.append(",repeat=").append(getRepeatString());
  553. sb.append(",horiz=").append(horiz);
  554. sb.append(",vertical=").append(vertical);
  555. }
  556. if (imageTargetWidth != 0) {
  557. sb.append(",target-width=").append(Integer.toString(imageTargetWidth));
  558. }
  559. if (imageTargetHeight != 0) {
  560. sb.append(",target-height=").append(Integer.toString(imageTargetHeight));
  561. }
  562. return sb.toString();
  563. }
  564. public void setImageTargetWidth(int value) {
  565. imageTargetWidth = value;
  566. }
  567. public int getImageTargetWidth() {
  568. return imageTargetWidth;
  569. }
  570. public void setImageTargetHeight(int value) {
  571. imageTargetHeight = value;
  572. }
  573. public int getImageTargetHeight() {
  574. return imageTargetHeight;
  575. }
  576. }
  577. }