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 22KB

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