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.

PropertyList.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
  4. * For details on use and redistribution please refer to the
  5. * LICENSE file included with these sources.
  6. */
  7. package org.apache.fop.fo;
  8. import java.util.HashMap;
  9. import org.apache.fop.fo.properties.WritingMode;
  10. import org.apache.fop.apps.FOPException;
  11. public class PropertyList extends HashMap {
  12. private byte[] wmtable = null; // writing-mode values
  13. public static final int LEFT = 0;
  14. public static final int RIGHT = 1;
  15. public static final int TOP = 2;
  16. public static final int BOTTOM = 3;
  17. public static final int HEIGHT = 4;
  18. public static final int WIDTH = 5;
  19. public static final int START = 0;
  20. public static final int END = 1;
  21. public static final int BEFORE = 2;
  22. public static final int AFTER = 3;
  23. public static final int BLOCKPROGDIM = 4;
  24. public static final int INLINEPROGDIM = 5;
  25. private static final String[] sAbsNames = new String[] {
  26. "left", "right", "top", "bottom", "height", "width"
  27. };
  28. private static final String[] sRelNames = new String[] {
  29. "start", "end", "before", "after", "block-progression-dimension",
  30. "inline-progression-dimension"
  31. };
  32. static private final HashMap wmtables = new HashMap(4);
  33. {
  34. wmtables.put(new Integer(WritingMode.LR_TB), /* lr-tb */
  35. new byte[] {
  36. START, END, BEFORE, AFTER, BLOCKPROGDIM, INLINEPROGDIM
  37. });
  38. wmtables.put(new Integer(WritingMode.RL_TB), /* rl-tb */
  39. new byte[] {
  40. END, START, BEFORE, AFTER, BLOCKPROGDIM, INLINEPROGDIM
  41. });
  42. wmtables.put(new Integer(WritingMode.TB_RL), /* tb-rl */
  43. new byte[] {
  44. AFTER, BEFORE, START, END, INLINEPROGDIM, BLOCKPROGDIM
  45. });
  46. }
  47. private PropertyListBuilder builder;
  48. private PropertyList parentPropertyList = null;
  49. String namespace = "";
  50. String element = "";
  51. FObj fobj = null;
  52. public PropertyList(PropertyList parentPropertyList, String space,
  53. String el) {
  54. this.parentPropertyList = parentPropertyList;
  55. this.namespace = space;
  56. this.element = el;
  57. }
  58. public void setFObj(FObj fobj) {
  59. this.fobj = fobj;
  60. }
  61. public FObj getFObj() {
  62. return this.fobj;
  63. }
  64. public FObj getParentFObj() {
  65. if (parentPropertyList != null) {
  66. return parentPropertyList.getFObj();
  67. } else
  68. return null;
  69. }
  70. /**
  71. * Return the value explicitly specified on this FO.
  72. * @param propertyName The name of the property whose value is desired.
  73. * It may be a compound name, such as space-before.optimum.
  74. * @return The value if the property is explicitly set or set by
  75. * a shorthand property, otherwise null.
  76. */
  77. public Property getExplicitOrShorthand(String propertyName) {
  78. /* Handle request for one part of a compound property */
  79. int sepchar = propertyName.indexOf('.');
  80. String baseName;
  81. if (sepchar > -1) {
  82. baseName = propertyName.substring(0, sepchar);
  83. } else
  84. baseName = propertyName;
  85. Property p = getExplicitBaseProp(baseName);
  86. if (p == null) {
  87. p = builder.getShorthand(this, namespace, element, baseName);
  88. }
  89. if (p != null && sepchar > -1) {
  90. return builder.getSubpropValue(namespace, element, baseName, p,
  91. propertyName.substring(sepchar
  92. + 1));
  93. }
  94. return p;
  95. }
  96. /**
  97. * Return the value explicitly specified on this FO.
  98. * @param propertyName The name of the property whose value is desired.
  99. * It may be a compound name, such as space-before.optimum.
  100. * @return The value if the property is explicitly set, otherwise null.
  101. */
  102. public Property getExplicit(String propertyName) {
  103. /* Handle request for one part of a compound property */
  104. int sepchar = propertyName.indexOf('.');
  105. if (sepchar > -1) {
  106. String baseName = propertyName.substring(0, sepchar);
  107. Property p = getExplicitBaseProp(baseName);
  108. if (p != null) {
  109. return this.builder.getSubpropValue(namespace, element,
  110. baseName, p,
  111. propertyName.substring(sepchar
  112. + 1));
  113. } else
  114. return null;
  115. }
  116. return (Property)super.get(propertyName);
  117. }
  118. /**
  119. * Return the value explicitly specified on this FO.
  120. * @param propertyName The name of the base property whose value is desired.
  121. * @return The value if the property is explicitly set, otherwise null.
  122. */
  123. public Property getExplicitBaseProp(String propertyName) {
  124. return (Property)super.get(propertyName);
  125. }
  126. /**
  127. * Return the value of this property inherited by this FO.
  128. * Implements the inherited-property-value function.
  129. * The property must be inheritable!
  130. * @param propertyName The name of the property whose value is desired.
  131. * @return The inherited value, otherwise null.
  132. */
  133. public Property getInherited(String propertyName) {
  134. if (builder != null) {
  135. if (parentPropertyList != null
  136. && builder.isInherited(namespace, element,
  137. propertyName)) {
  138. return parentPropertyList.get(propertyName);
  139. } else {
  140. // return the "initial" value
  141. try {
  142. return builder.makeProperty(this, namespace, element,
  143. propertyName);
  144. } catch (org.apache.fop.apps.FOPException e) {
  145. //log.error("Exception in getInherited(): property="
  146. // + propertyName + " : " + e);
  147. }
  148. }
  149. }
  150. return null; // No builder or exception in makeProperty!
  151. }
  152. /*
  153. * If the property is a relative property with a corresponding absolute
  154. * value specified, the absolute value is used. This is also true of
  155. * the inheritance priority (I think...)
  156. * If the property is an "absolute" property and it isn't specified, then
  157. * we try to compute it from the corresponding relative property: this
  158. * happends in computeProperty.
  159. */
  160. private Property findProperty(String propertyName, boolean bTryInherit) {
  161. Property p = null;
  162. if (builder.isCorrespondingForced(this, namespace, element,
  163. propertyName)) {
  164. p = builder.computeProperty(this, namespace, element,
  165. propertyName);
  166. } else {
  167. p = getExplicitBaseProp(propertyName);
  168. if (p == null) {
  169. p = this.builder.computeProperty(this, namespace, element,
  170. propertyName);
  171. }
  172. if (p == null) { // check for shorthand specification
  173. p = builder.getShorthand(this, namespace, element,
  174. propertyName);
  175. }
  176. if (p == null
  177. && bTryInherit) { // else inherit (if has parent and is inheritable)
  178. if (this.parentPropertyList != null
  179. && builder.isInherited(namespace, element,
  180. propertyName)) {
  181. p = parentPropertyList.findProperty(propertyName, true);
  182. }
  183. }
  184. }
  185. return p;
  186. }
  187. /**
  188. * Return the property on the current FlowObject if it is specified, or if a
  189. * corresponding property is specified. If neither is specified, it returns null.
  190. */
  191. public Property getSpecified(String propertyName) {
  192. return get(propertyName, false, false);
  193. }
  194. /**
  195. * Return the property on the current FlowObject. If it isn't set explicitly,
  196. * this will try to compute it based on other properties, or if it is
  197. * inheritable, to return the inherited value. If all else fails, it returns
  198. * the default value.
  199. */
  200. public Property get(String propertyName) {
  201. return get(propertyName, true, true);
  202. }
  203. /**
  204. * Return the property on the current FlowObject. Depending on the passed flags,
  205. * this will try to compute it based on other properties, or if it is
  206. * inheritable, to return the inherited value. If all else fails, it returns
  207. * the default value.
  208. */
  209. private Property get(String propertyName, boolean bTryInherit,
  210. boolean bTryDefault) {
  211. if (builder == null) {
  212. //log.error("OH OH, builder has not been set");
  213. }
  214. /* Handle request for one part of a compound property */
  215. int sepchar = propertyName.indexOf('.');
  216. String subpropName = null;
  217. if (sepchar > -1) {
  218. subpropName = propertyName.substring(sepchar + 1);
  219. propertyName = propertyName.substring(0, sepchar);
  220. }
  221. Property p = findProperty(propertyName, bTryInherit);
  222. if (p == null && bTryDefault) { // default value for this FO!
  223. try {
  224. p = this.builder.makeProperty(this, namespace, element,
  225. propertyName);
  226. } catch (FOPException e) {
  227. // don't know what to do here
  228. }
  229. }
  230. /*
  231. // if value is inherit then get computed value from
  232. // parent
  233. // namespaces??
  234. if(p != null && "inherit".equals(p.getString())) {
  235. if (this.parentPropertyList != null) {
  236. p = parentPropertyList.get(propertyName, true, false);
  237. }
  238. }
  239. */
  240. if (subpropName != null && p != null) {
  241. return this.builder.getSubpropValue(namespace, element,
  242. propertyName, p, subpropName);
  243. } else
  244. return p;
  245. }
  246. public void setBuilder(PropertyListBuilder builder) {
  247. this.builder = builder;
  248. }
  249. public String getNameSpace() {
  250. return namespace;
  251. }
  252. public String getElement() {
  253. return element;
  254. }
  255. /**
  256. * Return the "nearest" specified value for the given property.
  257. * Implements the from-nearest-specified-value function.
  258. * @param propertyName The name of the property whose value is desired.
  259. * @return The computed value if the property is explicitly set on some
  260. * ancestor of the current FO, else the initial value.
  261. */
  262. public Property getNearestSpecified(String propertyName) {
  263. Property p = null;
  264. for (PropertyList plist = this; p == null && plist != null;
  265. plist = plist.parentPropertyList) {
  266. p = plist.getExplicit(propertyName);
  267. }
  268. if (p == null) {
  269. // If no explicit setting found, return initial (default) value.
  270. try {
  271. p = this.builder.makeProperty(this, namespace, element,
  272. propertyName);
  273. } catch (FOPException e) {
  274. //log.error("Exception in getNearestSpecified(): property="
  275. // + propertyName + " : " + e);
  276. }
  277. }
  278. return p;
  279. }
  280. /**
  281. * Return the value of this property on the parent of this FO.
  282. * Implements the from-parent function.
  283. * @param propertyName The name of the property whose value is desired.
  284. * @return The computed value on the parent or the initial value if this
  285. * FO is the root or is in a different namespace from its parent.
  286. */
  287. public Property getFromParent(String propertyName) {
  288. if (parentPropertyList != null) {
  289. return parentPropertyList.get(propertyName);
  290. } else if (builder != null) {
  291. // return the "initial" value
  292. try {
  293. return builder.makeProperty(this, namespace, element,
  294. propertyName);
  295. } catch (org.apache.fop.apps.FOPException e) {
  296. //log.error("Exception in getFromParent(): property="
  297. // + propertyName + " : " + e);
  298. }
  299. }
  300. return null; // No builder or exception in makeProperty!
  301. }
  302. /**
  303. * Given an absolute direction (top, bottom, left, right),
  304. * return the corresponding writing model relative direction name
  305. * for the flow object. Uses the stored writingMode.
  306. */
  307. public String wmAbsToRel(int absdir) {
  308. if (wmtable != null) {
  309. return sRelNames[wmtable[absdir]];
  310. } else
  311. return "";
  312. }
  313. /**
  314. * Given a writing mode relative direction (start, end, before, after)
  315. * return the corresponding absolute direction name
  316. * for the flow object. Uses the stored writingMode.
  317. */
  318. public String wmRelToAbs(int reldir) {
  319. if (wmtable != null) {
  320. for (int i = 0; i < wmtable.length; i++) {
  321. if (wmtable[i] == reldir)
  322. return sAbsNames[i];
  323. }
  324. }
  325. return "";
  326. }
  327. /**
  328. * Set the writing mode traits for the FO with this property list.
  329. */
  330. public void setWritingMode(int writingMode) {
  331. this.wmtable = (byte[])wmtables.get(new Integer(writingMode));
  332. }
  333. }