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.

BlockContainerLayoutManager.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. * $Id: BlockContainerLayoutManager.java,v 1.13 2003/03/05 20:38:26 jeremias Exp $
  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.layoutmgr;
  52. import java.util.List;
  53. import java.awt.geom.Rectangle2D;
  54. import org.apache.fop.area.Area;
  55. import org.apache.fop.area.BlockViewport;
  56. import org.apache.fop.area.Block;
  57. import org.apache.fop.fo.PropertyManager;
  58. import org.apache.fop.fo.properties.CommonAbsolutePosition;
  59. import org.apache.fop.fo.properties.CommonBorderAndPadding;
  60. import org.apache.fop.fo.properties.CommonMarginBlock;
  61. import org.apache.fop.fo.PropertyList;
  62. import org.apache.fop.area.CTM;
  63. import org.apache.fop.datatypes.FODimension;
  64. import org.apache.fop.datatypes.Length;
  65. import org.apache.fop.datatypes.PercentBase;
  66. import org.apache.fop.traits.MinOptMax;
  67. /**
  68. * LayoutManager for a block FO.
  69. */
  70. public class BlockContainerLayoutManager extends BlockStackingLayoutManager {
  71. private BlockViewport viewportBlockArea;
  72. private Block curBlockArea;
  73. private List childBreaks = new java.util.ArrayList();
  74. private CommonAbsolutePosition abProps;
  75. private CommonBorderAndPadding borderProps;
  76. private CommonMarginBlock marginProps;
  77. private FODimension relDims;
  78. private CTM absoluteCTM;
  79. private boolean clip = false;
  80. private int overflow;
  81. private PropertyManager propManager;
  82. private Length width;
  83. private Length height;
  84. // When viewport should grow with the content.
  85. private boolean autoHeight = true;
  86. /**
  87. * Create a new block container layout manager.
  88. */
  89. public BlockContainerLayoutManager() {
  90. }
  91. public void setOverflow(int of) {
  92. overflow = of;
  93. }
  94. protected void initProperties(PropertyManager pm) {
  95. propManager = pm;
  96. abProps = pm.getAbsolutePositionProps();
  97. if (abProps.absolutePosition == AbsolutePosition.ABSOLUTE) {
  98. Rectangle2D rect = new Rectangle2D.Double(abProps.left,
  99. abProps.top, abProps.right - abProps.left,
  100. abProps.bottom - abProps.top);
  101. relDims = new FODimension(0, 0);
  102. absoluteCTM = CTM.getCTMandRelDims(pm.getAbsRefOrient(),
  103. pm.getWritingMode(), rect, relDims);
  104. }
  105. marginProps = pm.getMarginProps();
  106. borderProps = pm.getBorderAndPadding();
  107. height = pm.getPropertyList().get(PR_BLOCK_PROGRESSION_DIMENSION | CP_OPTIMUM).getLength();
  108. width = pm.getPropertyList().get(PR_INLINE_PROGRESSION_DIMENSION | CP_OPTIMUM).getLength();
  109. }
  110. protected int getRotatedIPD() {
  111. PropertyList props = propManager.getPropertyList();
  112. int height = props.get(PR_HEIGHT).getLength().getValue();
  113. height = props.get(PR_INLINE_PROGRESSION_DIMENSION | CP_OPTIMUM).getLength().getValue();
  114. return height;
  115. }
  116. public BreakPoss getNextBreakPoss(LayoutContext context) {
  117. if (abProps.absolutePosition == AbsolutePosition.ABSOLUTE) {
  118. return getAbsoluteBreakPoss(context);
  119. }
  120. int bIndents = borderProps.getBPPaddingAndBorder(false);
  121. int iIndents = marginProps.startIndent + marginProps.endIndent;
  122. int ipd = context.getRefIPD();
  123. int bpd = context.getStackLimit().opt;
  124. if (!width.isAuto()) {
  125. ipd = width.getValue() + iIndents;
  126. }
  127. if (!height.isAuto()) {
  128. bpd = height.getValue() + bIndents;
  129. }
  130. Rectangle2D rect = new Rectangle2D.Double(0, 0, ipd, bpd);
  131. relDims = new FODimension(0, 0);
  132. absoluteCTM = CTM.getCTMandRelDims(propManager.getAbsRefOrient(),
  133. propManager.getWritingMode(), rect, relDims);
  134. double[] vals = absoluteCTM.toArray();
  135. ipd -= iIndents;
  136. MinOptMax stackLimit;
  137. boolean rotated = vals[0] == 0.0;
  138. if (rotated) {
  139. // rotated 90 degrees
  140. if (relDims.ipd > context.getRefIPD()) {
  141. relDims.ipd = context.getRefIPD();
  142. }
  143. stackLimit = new MinOptMax(relDims.ipd);
  144. if (width.isAuto()) {
  145. relDims.bpd = context.getStackLimit().opt;
  146. }
  147. absoluteCTM = new CTM(vals[0], vals[1], vals[2], vals[3], 0, 0);
  148. } else {
  149. if (vals[0] == -1.0) {
  150. absoluteCTM = new CTM(vals[0], vals[1], vals[2], vals[3], 0, 0);
  151. }
  152. stackLimit = context.getStackLimit();
  153. }
  154. LayoutProcessor curLM ; // currently active LM
  155. MinOptMax stackSize = new MinOptMax();
  156. // if starting add space before
  157. // stackSize.add(spaceBefore);
  158. BreakPoss lastPos = null;
  159. fobj.setLayoutDimension(PercentBase.BLOCK_IPD, ipd);
  160. fobj.setLayoutDimension(PercentBase.BLOCK_BPD, bpd - bIndents);
  161. fobj.setLayoutDimension(PercentBase.REFERENCE_AREA_IPD, ipd);
  162. fobj.setLayoutDimension(PercentBase.REFERENCE_AREA_BPD, bpd - bIndents);
  163. while ((curLM = getChildLM()) != null) {
  164. // Make break positions and return blocks!
  165. // Set up a LayoutContext
  166. BreakPoss bp;
  167. LayoutContext childLC = new LayoutContext(0);
  168. childLC.setStackLimit(
  169. MinOptMax.subtract(stackLimit,
  170. stackSize));
  171. childLC.setRefIPD(ipd);
  172. boolean over = false;
  173. while (!curLM.isFinished()) {
  174. if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
  175. stackSize.add(bp.getStackingSize());
  176. if (stackSize.opt > stackLimit.max) {
  177. // reset to last break
  178. if (lastPos != null) {
  179. reset(lastPos.getPosition());
  180. } else {
  181. curLM.resetPosition(null);
  182. }
  183. over = true;
  184. break;
  185. }
  186. lastPos = bp;
  187. childBreaks.add(bp);
  188. if (bp.nextBreakOverflows()) {
  189. over = true;
  190. break;
  191. }
  192. childLC.setStackLimit(MinOptMax.subtract(
  193. stackLimit, stackSize));
  194. }
  195. }
  196. if (!rotated) {
  197. BreakPoss breakPoss;
  198. breakPoss = new BreakPoss(new LeafPosition(this,
  199. childBreaks.size() - 1));
  200. breakPoss.setStackingSize(stackSize);
  201. if (over) {
  202. breakPoss.setFlag(BreakPoss.NEXT_OVERFLOWS, true);
  203. }
  204. return breakPoss;
  205. }
  206. }
  207. setFinished(true);
  208. if (rotated) {
  209. BreakPoss breakPoss;
  210. breakPoss = new BreakPoss(new LeafPosition(this,
  211. childBreaks.size() - 1));
  212. breakPoss.setStackingSize(new MinOptMax(ipd));
  213. return breakPoss;
  214. }
  215. return null;
  216. }
  217. public BreakPoss getAbsoluteBreakPoss(LayoutContext context) {
  218. LayoutProcessor curLM ; // currently active LM
  219. MinOptMax stackSize = new MinOptMax();
  220. int ipd = relDims.ipd;
  221. while ((curLM = getChildLM()) != null) {
  222. // Make break positions and return blocks!
  223. // Set up a LayoutContext
  224. BreakPoss bp;
  225. LayoutContext childLC = new LayoutContext(0);
  226. childLC.setStackLimit(new MinOptMax(1000000));
  227. childLC.setRefIPD(ipd);
  228. while (!curLM.isFinished()) {
  229. if ((bp = curLM.getNextBreakPoss(childLC)) != null) {
  230. stackSize.add(bp.getStackingSize());
  231. childBreaks.add(bp);
  232. }
  233. }
  234. }
  235. setFinished(true);
  236. BreakPoss breakPoss = new BreakPoss(
  237. new LeafPosition(this, childBreaks.size() - 1));
  238. // absolutely positioned areas do not contribute
  239. // to the normal stacking
  240. breakPoss.setStackingSize(new MinOptMax(0));
  241. if (stackSize.opt > relDims.bpd) {
  242. if (overflow == Overflow.HIDDEN) {
  243. clip = true;
  244. } else if (overflow == Overflow.ERROR_IF_OVERFLOW) {
  245. getLogger().error("contents overflows block-container viewport: clipping");
  246. clip = true;
  247. }
  248. }
  249. return breakPoss;
  250. }
  251. public void addAreas(PositionIterator parentIter,
  252. LayoutContext layoutContext) {
  253. getParentArea(null);
  254. addID();
  255. addMarkers(true, true);
  256. LayoutProcessor childLM;
  257. int iStartPos = 0;
  258. LayoutContext lc = new LayoutContext(0);
  259. while (parentIter.hasNext()) {
  260. LeafPosition lfp = (LeafPosition) parentIter.next();
  261. // Add the block areas to Area
  262. PositionIterator breakPosIter =
  263. new BreakPossPosIter(childBreaks, iStartPos,
  264. lfp.getLeafPos() + 1);
  265. iStartPos = lfp.getLeafPos() + 1;
  266. while ((childLM = breakPosIter.getNextChildLM()) != null) {
  267. childLM.addAreas(breakPosIter, lc);
  268. }
  269. }
  270. flush();
  271. addMarkers(true, true);
  272. childBreaks.clear();
  273. viewportBlockArea = null;
  274. curBlockArea = null;
  275. }
  276. /**
  277. * Get the parent area for children of this block container.
  278. * This returns the current block container area
  279. * and creates it if required.
  280. *
  281. * @see org.apache.fop.layoutmgr.LayoutProcessor#getParentArea(Area)
  282. */
  283. public Area getParentArea(Area childArea) {
  284. if (curBlockArea == null) {
  285. viewportBlockArea = new BlockViewport();
  286. TraitSetter.addBorders(viewportBlockArea,
  287. propManager.getBorderAndPadding());
  288. TraitSetter.addBackground(viewportBlockArea,
  289. propManager.getBackgroundProps());
  290. if (abProps.absolutePosition == AbsolutePosition.ABSOLUTE) {
  291. viewportBlockArea.setXOffset(abProps.left);
  292. viewportBlockArea.setYOffset(abProps.top);
  293. viewportBlockArea.setWidth(abProps.right - abProps.left);
  294. viewportBlockArea.setHeight(abProps.bottom - abProps.top);
  295. viewportBlockArea.setCTM(absoluteCTM);
  296. viewportBlockArea.setClip(clip);
  297. autoHeight = false;
  298. } else {
  299. double[] vals = absoluteCTM.toArray();
  300. boolean rotated = vals[0] == 0.0;
  301. if (rotated) {
  302. viewportBlockArea.setWidth(relDims.ipd);
  303. viewportBlockArea.setHeight(relDims.bpd);
  304. viewportBlockArea.setCTM(absoluteCTM);
  305. viewportBlockArea.setClip(clip);
  306. autoHeight = false;
  307. } else if (vals[0] == -1.0) {
  308. // need to set bpd to actual size for rotation
  309. // and stacking
  310. viewportBlockArea.setWidth(relDims.ipd);
  311. if (!height.isAuto()) {
  312. viewportBlockArea.setHeight(relDims.bpd);
  313. autoHeight = false;
  314. }
  315. viewportBlockArea.setCTM(absoluteCTM);
  316. viewportBlockArea.setClip(clip);
  317. } else {
  318. viewportBlockArea.setWidth(relDims.ipd);
  319. if (!height.isAuto()) {
  320. viewportBlockArea.setHeight(relDims.bpd);
  321. autoHeight = false;
  322. }
  323. }
  324. }
  325. curBlockArea = new Block();
  326. if (abProps.absolutePosition == AbsolutePosition.ABSOLUTE) {
  327. viewportBlockArea.setPositioning(Block.ABSOLUTE);
  328. }
  329. // Set up dimensions
  330. // Must get dimensions from parent area
  331. Area parentArea = parentLM.getParentArea(curBlockArea);
  332. //int referenceIPD = parentArea.getIPD();
  333. curBlockArea.setIPD(relDims.ipd);
  334. // Get reference IPD from parentArea
  335. setCurrentArea(viewportBlockArea); // ??? for generic operations
  336. }
  337. return curBlockArea;
  338. }
  339. /**
  340. * Add the child to the block container.
  341. *
  342. * @see org.apache.fop.layoutmgr.LayoutProcessor#addChild(Area)
  343. */
  344. public void addChild(Area childArea) {
  345. if (curBlockArea != null) {
  346. curBlockArea.addBlock((Block) childArea);
  347. }
  348. }
  349. public void resetPosition(Position resetPos) {
  350. if (resetPos == null) {
  351. reset(null);
  352. }
  353. }
  354. /*
  355. * Force current area to be added to parent area.
  356. */
  357. protected void flush() {
  358. viewportBlockArea.addBlock(curBlockArea, autoHeight);
  359. // Fake a 0 height for absolute positioned blocks.
  360. int height = viewportBlockArea.getHeight();
  361. if (viewportBlockArea.getPositioning() == Block.ABSOLUTE) {
  362. viewportBlockArea.setHeight(0);
  363. }
  364. super.flush();
  365. // Restore the right height.
  366. if (viewportBlockArea.getPositioning() == Block.ABSOLUTE) {
  367. viewportBlockArea.setHeight(height);
  368. }
  369. }
  370. }