Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

FObj.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001-2002 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. // FOP
  9. import org.apache.fop.layout.AreaClass;
  10. import org.apache.fop.apps.FOPException;
  11. import org.apache.fop.apps.StructureHandler;
  12. import org.apache.fop.layoutmgr.LayoutManager;
  13. import org.apache.fop.fo.properties.FOPropertyMapping;
  14. import org.apache.fop.fo.flow.Marker;
  15. // Java
  16. import java.util.Iterator;
  17. import org.xml.sax.Attributes;
  18. import java.util.Iterator;
  19. import java.util.ListIterator;
  20. import java.util.ArrayList;
  21. import java.util.List;
  22. import java.util.HashMap;
  23. import java.util.HashSet;
  24. /**
  25. * base class for representation of formatting objects and their processing
  26. */
  27. public class FObj extends FONode {
  28. protected StructureHandler structHandler;
  29. public PropertyList properties;
  30. protected PropertyManager propMgr;
  31. protected String areaClass = AreaClass.UNASSIGNED;
  32. protected String id = null;
  33. /**
  34. * value of marker before layout begins
  35. */
  36. public static final int START = -1000;
  37. /**
  38. * value of marker after break-after
  39. */
  40. public static final int BREAK_AFTER = -1001;
  41. /**
  42. * where the layout was up to.
  43. * for FObjs it is the child number
  44. * for FOText it is the character number
  45. */
  46. protected int marker = START;
  47. protected ArrayList children = new ArrayList(); // made public for searching for id's
  48. protected boolean isInTableCell = false;
  49. protected int forcedStartOffset = 0;
  50. protected int forcedWidth = 0;
  51. protected int widows = 0;
  52. protected int orphans = 0;
  53. // count of areas generated-by/returned-by
  54. public int areasGenerated = 0;
  55. // markers
  56. protected HashMap markers;
  57. public FObj(FONode parent) {
  58. super(parent);
  59. markers = new HashMap();
  60. if (parent instanceof FObj) {
  61. this.areaClass = ((FObj) parent).areaClass;
  62. }
  63. }
  64. public void setName(String str) {
  65. name = "fo:" + str;
  66. }
  67. protected static PropertyListBuilder plb = null;
  68. protected PropertyListBuilder getListBuilder() {
  69. if (plb == null) {
  70. plb = new PropertyListBuilder();
  71. plb.addList(FOPropertyMapping.getGenericMappings());
  72. for (Iterator iter =
  73. FOPropertyMapping.getElementMappings().iterator();
  74. iter.hasNext();) {
  75. String elem = (String) iter.next();
  76. plb.addElementList(elem,
  77. FOPropertyMapping.getElementMapping(elem));
  78. }
  79. }
  80. return plb;
  81. }
  82. /**
  83. * Handle the attributes for this element.
  84. * The attributes must be used immediately as the sax attributes
  85. * will be altered for the next element.
  86. */
  87. public void handleAttrs(Attributes attlist) throws FOPException {
  88. String uri = "http://www.w3.org/1999/XSL/Format";
  89. FONode par = parent;
  90. while (par != null && !(par instanceof FObj)) {
  91. par = par.parent;
  92. }
  93. PropertyList props = null;
  94. if (par != null) {
  95. props = ((FObj) par).properties;
  96. }
  97. properties = getListBuilder().makeList(uri, name, attlist, props,
  98. (FObj) par);
  99. properties.setFObj(this);
  100. this.propMgr = makePropertyManager(properties);
  101. setWritingMode();
  102. }
  103. protected PropertyManager makePropertyManager(
  104. PropertyList propertyList) {
  105. return new PropertyManager(propertyList);
  106. }
  107. protected void addChild(FONode child) {
  108. children.add(child);
  109. }
  110. public void setStructHandler(StructureHandler st) {
  111. structHandler = st;
  112. }
  113. /**
  114. * lets outside sources access the property list
  115. * first used by PageNumberCitation to find the "id" property
  116. * @param name - the name of the desired property to obtain
  117. * @return the property
  118. */
  119. public Property getProperty(String name) {
  120. return (properties.get(name));
  121. }
  122. protected void setupID() {
  123. Property prop = this.properties.get("id");
  124. if (prop != null) {
  125. String str = prop.getString();
  126. if (str != null && !str.equals("")) {
  127. HashSet idrefs = structHandler.getIDReferences();
  128. if (!idrefs.contains(str)) {
  129. id = str;
  130. idrefs.add(id);
  131. } else {
  132. getLogger().warn("duplicate id:" + str + " ignored");
  133. }
  134. }
  135. }
  136. }
  137. public String getID() {
  138. return id;
  139. }
  140. /**
  141. * Return the "content width" of the areas generated by this FO.
  142. * This is used by percent-based properties to get the dimension of
  143. * the containing block.
  144. * If an FO has a property with a percentage value, that value
  145. * is usually calculated on the basis of the corresponding dimension
  146. * of the area which contains areas generated by the FO.
  147. * NOTE: subclasses of FObj should implement this to return a reasonable
  148. * value!
  149. */
  150. public int getContentWidth() {
  151. return 0;
  152. }
  153. public boolean generatesReferenceAreas() {
  154. return false;
  155. }
  156. public boolean generatesInlineAreas() {
  157. return true;
  158. }
  159. /**
  160. * Set writing mode for this FO.
  161. * Find nearest ancestor, including self, which generates
  162. * reference areas and use the value of its writing-mode property.
  163. * If no such ancestor is found, use the value on the root FO.
  164. */
  165. protected void setWritingMode() {
  166. FObj p;
  167. FONode parent;
  168. for (p = this; !p.generatesReferenceAreas() &&
  169. (parent = p.getParent()) != null &&
  170. (parent instanceof FObj); p = (FObj) parent) {
  171. }
  172. this.properties.setWritingMode(
  173. p.getProperty("writing-mode").getEnum());
  174. }
  175. /**
  176. * Return a LayoutManager responsible for laying out this FObj's content.
  177. * Must override in subclasses if their content can be laid out.
  178. * @param list the list to add the layout manager(s) to
  179. */
  180. public void addLayoutManager(List list) {
  181. }
  182. /**
  183. * Return an iterator over all the children of this FObj.
  184. * @return A ListIterator.
  185. */
  186. public ListIterator getChildren() {
  187. if (children != null) {
  188. return children.listIterator();
  189. }
  190. return null;
  191. }
  192. /**
  193. * Return an iterator over the object's children starting
  194. * at the pased node.
  195. * @param childNode First node in the iterator
  196. * @return A ListIterator or null if childNode isn't a child of
  197. * this FObj.
  198. */
  199. public ListIterator getChildren(FONode childNode) {
  200. int i = children.indexOf(childNode);
  201. if (i >= 0) {
  202. return children.listIterator(i);
  203. } else {
  204. return null;
  205. }
  206. }
  207. public void setIsInTableCell() {
  208. this.isInTableCell = true;
  209. // made recursive by Eric Schaeffer
  210. for (int i = 0; i < this.children.size(); i++) {
  211. Object obj = this.children.get(i);
  212. if (obj instanceof FObj) {
  213. FObj child = (FObj) obj;
  214. child.setIsInTableCell();
  215. }
  216. }
  217. }
  218. public void forceStartOffset(int offset) {
  219. this.forcedStartOffset = offset;
  220. // made recursive by Eric Schaeffer
  221. for (int i = 0; i < this.children.size(); i++) {
  222. Object obj = this.children.get(i);
  223. if (obj instanceof FObj) {
  224. FObj child = (FObj) obj;
  225. child.forceStartOffset(offset);
  226. }
  227. }
  228. }
  229. public void forceWidth(int width) {
  230. this.forcedWidth = width;
  231. // made recursive by Eric Schaeffer
  232. for (int i = 0; i < this.children.size(); i++) {
  233. Object obj = this.children.get(i);
  234. if (obj instanceof FObj) {
  235. FObj child = (FObj) obj;
  236. child.forceWidth(width);
  237. }
  238. }
  239. }
  240. public void resetMarker() {
  241. this.marker = START;
  242. int numChildren = this.children.size();
  243. for (int i = 0; i < numChildren; i++) {
  244. Object obj = this.children.get(i);
  245. if (obj instanceof FObj) {
  246. FObj child = (FObj) obj;
  247. child.resetMarker();
  248. }
  249. }
  250. }
  251. public void setWidows(int wid) {
  252. widows = wid;
  253. }
  254. public void setOrphans(int orph) {
  255. orphans = orph;
  256. }
  257. public void removeAreas() {
  258. // still to do
  259. }
  260. /**
  261. * At the start of a new span area layout may be partway through a
  262. * nested FO, and balancing requires rollback to this known point.
  263. * The snapshot records exactly where layout is at.
  264. * @param snapshot a ArrayList of markers (Integer)
  265. * @returns the updated ArrayList of markers (Integers)
  266. */
  267. public ArrayList getMarkerSnapshot(ArrayList snapshot) {
  268. snapshot.add(new Integer(this.marker));
  269. // terminate if no kids or child not yet accessed
  270. if (this.marker < 0) {
  271. return snapshot;
  272. } else if (children.isEmpty()) {
  273. return snapshot;
  274. } else {
  275. return ( (FObj) children.get(this.marker)).getMarkerSnapshot(
  276. snapshot);
  277. }
  278. }
  279. /**
  280. * When balancing occurs, the flow layout() method restarts at the
  281. * point specified by the current marker snapshot, which is retrieved
  282. * and restored using this method.
  283. * @param snapshot the ArrayList of saved markers (Integers)
  284. */
  285. public void rollback(ArrayList snapshot) {
  286. this.marker = ((Integer) snapshot.get(0)).intValue();
  287. snapshot.remove(0);
  288. if (this.marker == START) {
  289. // make sure all the children of this FO are also reset
  290. resetMarker();
  291. return;
  292. } else if ((this.marker == -1) || children.isEmpty()) {
  293. return;
  294. }
  295. int numChildren = this.children.size();
  296. if (this.marker <= START) {
  297. return;
  298. }
  299. for (int i = this.marker + 1; i < numChildren; i++) {
  300. Object obj = this.children.get(i);
  301. if (obj instanceof FObj) {
  302. FObj child = (FObj) obj;
  303. child.resetMarker();
  304. }
  305. }
  306. ((FObj) children.get(this.marker)).rollback(snapshot);
  307. }
  308. public void addMarker(Marker marker) throws FOPException {
  309. String mcname = marker.getMarkerClassName();
  310. if (!markers.containsKey(mcname) && children.isEmpty()) {
  311. markers.put(mcname, marker);
  312. } else {
  313. getLogger().error("fo:marker must be an initial child," + "and 'marker-class-name' must be unique for same parent");
  314. throw new FOPException(
  315. "fo:marker must be an initial child," + "and 'marker-class-name' must be unique for same parent");
  316. }
  317. }
  318. public boolean hasMarkers() {
  319. return !markers.isEmpty();
  320. }
  321. public ArrayList getMarkers() {
  322. return new ArrayList(markers.values());
  323. }
  324. /**
  325. * lets layout managers access FO properties via PropertyManager
  326. * @return the property manager for this FO
  327. */
  328. public PropertyManager getPropertyManager() {
  329. return this.propMgr;
  330. }
  331. }