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.

Block.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. /*
  2. * $Id$
  3. * ============================================================================
  4. * The Apache Software License, Version 1.1
  5. * ============================================================================
  6. *
  7. * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without modifica-
  10. * tion, are permitted provided that the following conditions are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright notice,
  13. * this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright notice,
  16. * this list of conditions and the following disclaimer in the documentation
  17. * and/or other materials provided with the distribution.
  18. *
  19. * 3. The end-user documentation included with the redistribution, if any, must
  20. * include the following acknowledgment: "This product includes software
  21. * developed by the Apache Software Foundation (http://www.apache.org/)."
  22. * Alternately, this acknowledgment may appear in the software itself, if
  23. * and wherever such third-party acknowledgments normally appear.
  24. *
  25. * 4. The names "FOP" and "Apache Software Foundation" must not be used to
  26. * endorse or promote products derived from this software without prior
  27. * written permission. For written permission, please contact
  28. * apache@apache.org.
  29. *
  30. * 5. Products derived from this software may not be called "Apache", nor may
  31. * "Apache" appear in their name, without prior written permission of the
  32. * Apache Software Foundation.
  33. *
  34. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
  35. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
  36. * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  37. * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
  38. * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
  39. * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  40. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  41. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  42. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  43. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  44. * ============================================================================
  45. *
  46. * This software consists of voluntary contributions made by many individuals
  47. * on behalf of the Apache Software Foundation and was originally created by
  48. * James Tauber <jtauber@jtauber.com>. For more information on the Apache
  49. * Software Foundation, please see <http://www.apache.org/>.
  50. */
  51. package org.apache.fop.fo.flow;
  52. // FOP
  53. import org.apache.fop.fo.FObjMixed;
  54. import org.apache.fop.fo.FObj;
  55. import org.apache.fop.fo.PropertyList;
  56. import org.apache.fop.fo.Status;
  57. import org.apache.fop.fo.FONode;
  58. import org.apache.fop.layout.Area;
  59. import org.apache.fop.layout.BlockArea;
  60. import org.apache.fop.layout.AccessibilityProps;
  61. import org.apache.fop.layout.AuralProps;
  62. import org.apache.fop.layout.BorderAndPadding;
  63. import org.apache.fop.layout.BackgroundProps;
  64. import org.apache.fop.layout.HyphenationProps;
  65. import org.apache.fop.layout.MarginProps;
  66. import org.apache.fop.layout.RelativePositionProps;
  67. import org.apache.fop.apps.FOPException;
  68. /*
  69. Modified by Mark Lillywhite mark-fop@inomial.com. The changes
  70. here are based on memory profiling and do not change functionality.
  71. Essentially, the Block object had a pointer to a BlockArea object
  72. that it created. The BlockArea was not referenced after the Block
  73. was finished except to determine the size of the BlockArea, however
  74. a reference to the BlockArea was maintained and this caused a lot of
  75. GC problems, and was a major reason for FOP memory leaks. So,
  76. the reference to BlockArea was made local, the required information
  77. is now stored (instead of a reference to the complex BlockArea object)
  78. and it appears that there are a lot of changes in this file, in fact
  79. there are only a few sematic changes; mostly I just got rid of
  80. "this." from blockArea since BlockArea is now local.
  81. */
  82. public class Block extends FObjMixed {
  83. public static class Maker extends FObj.Maker {
  84. public FObj make(FObj parent, PropertyList propertyList,
  85. String systemId, int line, int column)
  86. throws FOPException {
  87. return new Block(parent, propertyList, systemId, line, column);
  88. }
  89. }
  90. public static FObj.Maker maker() {
  91. return new Block.Maker();
  92. }
  93. int align;
  94. int alignLast;
  95. int breakAfter;
  96. int lineHeight;
  97. int startIndent;
  98. int endIndent;
  99. int spaceBefore;
  100. int spaceAfter;
  101. int textIndent;
  102. int keepWithNext;
  103. int areaHeight = 0;
  104. int contentWidth = 0;
  105. int infLoopThreshhold = 50;
  106. String id;
  107. int span;
  108. boolean breakStatusBeforeChecked = false;
  109. // this may be helpful on other FOs too
  110. boolean anythingLaidOut = false;
  111. //Added to see how long it's been since nothing was laid out.
  112. int noLayoutCount = 0;
  113. public Block(FObj parent, PropertyList propertyList,
  114. String systemId, int line, int column)
  115. throws FOPException {
  116. super(parent, propertyList, systemId, line, column);
  117. this.span = this.properties.get("span").getEnum();
  118. }
  119. public String getName() {
  120. return "fo:block";
  121. }
  122. public int layout(Area area) throws FOPException {
  123. if (!breakStatusBeforeChecked) {
  124. breakStatusBeforeChecked = true;
  125. // no break if first in area tree, or leading in context
  126. // area
  127. int breakBeforeStatus = propMgr.checkBreakBefore(area);
  128. if (breakBeforeStatus != Status.OK) {
  129. return breakBeforeStatus;
  130. }
  131. }
  132. BlockArea blockArea;
  133. if (!anythingLaidOut) {
  134. noLayoutCount++;
  135. }
  136. if (noLayoutCount > infLoopThreshhold) {
  137. throw new FOPException(
  138. "No meaningful layout in block after many attempts. "+
  139. "Infinite loop is assumed. Processing halted.",
  140. systemId, line, column);
  141. }
  142. // log.error(" b:LAY[" + marker + "] ");
  143. if (this.marker == BREAK_AFTER) {
  144. return Status.OK;
  145. }
  146. if (this.marker == START) {
  147. noLayoutCount=0; // Reset the "loop counter".
  148. // Common Accessibility Properties
  149. AccessibilityProps mAccProps = propMgr.getAccessibilityProps();
  150. // Common Aural Properties
  151. AuralProps mAurProps = propMgr.getAuralProps();
  152. // Common Border, Padding, and Background Properties
  153. BorderAndPadding bap = propMgr.getBorderAndPadding();
  154. BackgroundProps bProps = propMgr.getBackgroundProps();
  155. // Common Font Properties
  156. //this.fontState = propMgr.getFontState(area.getFontInfo());
  157. // Common Hyphenation Properties
  158. HyphenationProps mHyphProps = propMgr.getHyphenationProps();
  159. // Common Margin Properties-Block
  160. MarginProps mProps = propMgr.getMarginProps();
  161. // Common Relative Position Properties
  162. RelativePositionProps mRelProps = propMgr.getRelativePositionProps();
  163. this.align = this.properties.get("text-align").getEnum();
  164. this.alignLast = this.properties.get("text-align-last").getEnum();
  165. this.breakAfter = this.properties.get("break-after").getEnum();
  166. this.lineHeight =
  167. this.properties.get("line-height").getLength().mvalue();
  168. this.startIndent =
  169. this.properties.get("start-indent").getLength().mvalue();
  170. this.endIndent =
  171. this.properties.get("end-indent").getLength().mvalue();
  172. this.spaceBefore =
  173. this.properties.get("space-before.optimum").getLength().mvalue();
  174. this.spaceAfter =
  175. this.properties.get("space-after.optimum").getLength().mvalue();
  176. this.textIndent =
  177. this.properties.get("text-indent").getLength().mvalue();
  178. this.keepWithNext =
  179. this.properties.get("keep-with-next").getEnum();
  180. this.id = this.properties.get("id").getString();
  181. if (area instanceof BlockArea) {
  182. area.end();
  183. }
  184. if (area.getIDReferences() != null) {
  185. try {
  186. area.getIDReferences().createID(id);
  187. }
  188. catch(FOPException e) {
  189. if (!e.isLocationSet()) {
  190. e.setLocation(systemId, line, column);
  191. }
  192. throw e;
  193. }
  194. }
  195. this.marker = 0;
  196. }
  197. if ((spaceBefore != 0) && (this.marker == 0)) {
  198. area.addDisplaySpace(spaceBefore);
  199. }
  200. if (anythingLaidOut) {
  201. this.textIndent = 0;
  202. }
  203. if (marker == 0 && area.getIDReferences() != null) {
  204. area.getIDReferences().configureID(id, area);
  205. }
  206. int spaceLeft = area.spaceLeft();
  207. blockArea =
  208. new BlockArea(propMgr.getFontState(area.getFontInfo()),
  209. area.getAllocationWidth(), area.spaceLeft(),
  210. startIndent, endIndent, textIndent, align,
  211. alignLast, lineHeight);
  212. blockArea.setGeneratedBy(this);
  213. this.areasGenerated++;
  214. if (this.areasGenerated == 1)
  215. blockArea.isFirst(true);
  216. // markers
  217. // if (this.hasMarkers())
  218. // blockArea.addMarkers(this.getMarkers());
  219. blockArea.setParent(area); // BasicLink needs it
  220. blockArea.setPage(area.getPage());
  221. blockArea.setBackground(propMgr.getBackgroundProps());
  222. blockArea.setBorderAndPadding(propMgr.getBorderAndPadding());
  223. blockArea.setHyphenation(propMgr.getHyphenationProps());
  224. blockArea.start();
  225. blockArea.setAbsoluteHeight(area.getAbsoluteHeight());
  226. blockArea.setIDReferences(area.getIDReferences());
  227. blockArea.setTableCellXOffset(area.getTableCellXOffset());
  228. int numChildren = this.children.size();
  229. for (int i = this.marker; i < numChildren; i++) {
  230. FONode fo = (FONode)children.get(i);
  231. int status = fo.layout(blockArea);
  232. if (Status.isIncomplete(status)) {
  233. this.marker = i;
  234. if (status == Status.AREA_FULL_NONE) {
  235. if (i == 0) {
  236. // Nothing was laid out.
  237. anythingLaidOut = false;
  238. return status;
  239. } else {
  240. // A previous child has already been laid out.
  241. area.addChild(blockArea);
  242. area.setMaxHeight(area.getMaxHeight() - spaceLeft
  243. + blockArea.getMaxHeight());
  244. area.increaseHeight(blockArea.getHeight());
  245. anythingLaidOut = true;
  246. return Status.AREA_FULL_SOME;
  247. }
  248. }
  249. // Something has been laid out.
  250. area.addChild(blockArea);
  251. area.setMaxHeight(area.getMaxHeight() - spaceLeft
  252. + blockArea.getMaxHeight());
  253. area.increaseHeight(blockArea.getHeight());
  254. anythingLaidOut = true;
  255. return status;
  256. }
  257. anythingLaidOut = true;
  258. }
  259. blockArea.end();
  260. blockArea.isLast(true);
  261. area.addChild(blockArea);
  262. area.setMaxHeight(area.getMaxHeight() - spaceLeft
  263. + blockArea.getMaxHeight());
  264. area.increaseHeight(blockArea.getHeight());
  265. if (spaceAfter != 0) {
  266. area.addDisplaySpace(spaceAfter);
  267. }
  268. if (area instanceof BlockArea) {
  269. area.start();
  270. }
  271. areaHeight= blockArea.getHeight();
  272. contentWidth= blockArea.getContentWidth();
  273. // no break if last in area tree, or trailing in context
  274. // area
  275. int breakAfterStatus = propMgr.checkBreakAfter(area);
  276. if (breakAfterStatus != Status.OK) {
  277. this.marker = BREAK_AFTER;
  278. blockArea = null;
  279. return breakAfterStatus;
  280. }
  281. if (keepWithNext != 0) {
  282. return Status.KEEP_WITH_NEXT;
  283. }
  284. return Status.OK;
  285. }
  286. public int getAreaHeight() {
  287. return areaHeight;
  288. }
  289. /**
  290. * Return the content width of the boxes generated by this FO.
  291. */
  292. public int getContentWidth() {
  293. return contentWidth; // getAllocationWidth()??
  294. }
  295. public int getSpan() {
  296. return this.span;
  297. }
  298. public void resetMarker() {
  299. anythingLaidOut = false;
  300. super.resetMarker();
  301. }
  302. }