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.

InlineStackingLayoutManager.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618
  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.layoutmgr;
  52. import java.util.Iterator;
  53. import java.util.ListIterator;
  54. import java.util.HashMap;
  55. import org.apache.fop.fo.FObj;
  56. import org.apache.fop.fo.PropertyManager;
  57. import org.apache.fop.layout.BorderAndPadding;
  58. import org.apache.fop.layout.BackgroundProps;
  59. import org.apache.fop.traits.InlineProps;
  60. import org.apache.fop.area.Area;
  61. import org.apache.fop.area.inline.InlineArea;
  62. import org.apache.fop.area.inline.InlineParent;
  63. import org.apache.fop.area.inline.Space;
  64. /**
  65. * LayoutManager for objects which stack children in the inline direction,
  66. * such as Inline or Line
  67. */
  68. public class InlineStackingLayoutManager extends AbstractLayoutManager {
  69. private static class StackingIter extends PositionIterator {
  70. StackingIter(Iterator parentIter) {
  71. super(parentIter);
  72. }
  73. protected LayoutProcessor getLM(Object nextObj) {
  74. return ((Position) nextObj).getPosition().getLM();
  75. }
  76. protected Position getPos(Object nextObj) {
  77. return ((Position) nextObj).getPosition();
  78. }
  79. }
  80. /**
  81. * Size of any start or end borders and padding.
  82. */
  83. private MinOptMax allocIPD = new MinOptMax(0);
  84. /**
  85. * Size of border and padding in BPD (ie, before and after).
  86. */
  87. private MinOptMax extraBPD;
  88. private InlineProps inlineProps = null;
  89. private BorderAndPadding borderProps = null;
  90. private BackgroundProps backgroundProps;
  91. private Area currentArea; // LineArea or InlineParent
  92. private BreakPoss prevBP;
  93. private LayoutContext childLC ;
  94. private LayoutManager lastChildLM = null; // Set when return last breakposs
  95. private boolean bAreaCreated = false;
  96. /** Used to store previous content IPD for each child LM. */
  97. private HashMap hmPrevIPD = new HashMap();
  98. /**
  99. * Create an inline stacking layout manager.
  100. * This is used for fo's that create areas that
  101. * contain inline areas.
  102. *
  103. * @param fobj the formatting object that creates the area
  104. * @param childLMiter the iterator for child areas
  105. */
  106. public InlineStackingLayoutManager() {
  107. }
  108. /**
  109. * Set the FO object for this layout manager
  110. *
  111. * @param fo the fo for this layout manager
  112. */
  113. public void setFObj(FObj fo) {
  114. this.fobj = fo;
  115. foID = fobj.getID();
  116. childLMiter = null;
  117. }
  118. /**
  119. * Set the iterator.
  120. *
  121. * @param iter the iterator for this LM
  122. */
  123. public void setLMiter(ListIterator iter) {
  124. childLMiter = iter;
  125. }
  126. /**
  127. * Check if this generates inline areas.
  128. * This creates inline areas that contain other inline areas.
  129. *
  130. * @return true
  131. */
  132. public boolean generatesInlineAreas() {
  133. return true;
  134. }
  135. /**
  136. * Initialize properties for this layout manager.
  137. *
  138. * @param propMgr the property manager from the fo that created this manager
  139. */
  140. protected void initProperties(PropertyManager propMgr) {
  141. // super.initProperties(propMgr);
  142. inlineProps = propMgr.getInlineProps();
  143. borderProps = propMgr.getBorderAndPadding();
  144. // Calculdate border and padding size in BPD
  145. int iPad = borderProps.getPadding(BorderAndPadding.BEFORE, false);
  146. iPad += borderProps.getBorderWidth(BorderAndPadding.BEFORE,
  147. false);
  148. iPad += borderProps.getPadding(BorderAndPadding.AFTER, false);
  149. iPad += borderProps.getBorderWidth(BorderAndPadding.AFTER, false);
  150. extraBPD = new MinOptMax(iPad);
  151. backgroundProps = propMgr.getBackgroundProps();
  152. }
  153. private MinOptMax getExtraIPD(boolean bNotFirst, boolean bNotLast) {
  154. int iBP = borderProps.getPadding(BorderAndPadding.START,
  155. bNotFirst);
  156. iBP += borderProps.getBorderWidth(BorderAndPadding.START,
  157. bNotFirst);
  158. iBP += borderProps.getPadding(BorderAndPadding.END, bNotLast);
  159. iBP += borderProps.getBorderWidth(BorderAndPadding.END, bNotLast);
  160. return new MinOptMax(iBP);
  161. }
  162. protected boolean hasLeadingFence(boolean bNotFirst) {
  163. int iBP = borderProps.getPadding(BorderAndPadding.START,
  164. bNotFirst);
  165. iBP += borderProps.getBorderWidth(BorderAndPadding.START,
  166. bNotFirst);
  167. return (iBP > 0);
  168. }
  169. protected boolean hasTrailingFence(boolean bNotLast) {
  170. int iBP = borderProps.getPadding(BorderAndPadding.END, bNotLast);
  171. iBP += borderProps.getBorderWidth(BorderAndPadding.END, bNotLast);
  172. return (iBP > 0);
  173. }
  174. /**
  175. * Reset position for returning next BreakPossibility.
  176. * @param prevPos a Position returned by this layout manager
  177. * representing a potential break decision.
  178. */
  179. public void resetPosition(Position prevPos) {
  180. if (prevPos != null) {
  181. // ASSERT (prevPos.getLM() == this)
  182. if (prevPos.getLM() != this) {
  183. //getLogger().error(
  184. // "InlineStackingLayoutManager.resetPosition: " +
  185. // "LM mismatch!!!");
  186. }
  187. // Back up the child LM Position
  188. Position childPos = prevPos.getPosition();
  189. reset(childPos);
  190. if (prevBP != null
  191. && prevBP.getLayoutManager() != childPos.getLM()) {
  192. childLC = null;
  193. }
  194. prevBP = new BreakPoss(childPos);
  195. } else {
  196. // Backup to start of first child layout manager
  197. prevBP = null;
  198. // super.resetPosition(prevPos);
  199. reset(prevPos);
  200. // If any areas created, we are restarting!
  201. bAreaCreated = false;
  202. }
  203. // Do we need to reset some context like pending or prevContent?
  204. // What about prevBP?
  205. }
  206. /**
  207. * Return value indicating whether the next area to be generated could
  208. * start a new line. This should only be called in the "START" condition
  209. * if a previous inline BP couldn't end the line.
  210. * Return true if any space-start, border-start or padding-start, else
  211. * propagate to first child LM
  212. */
  213. public boolean canBreakBefore(LayoutContext context) {
  214. if (inlineProps.spaceStart.getSpace().min > 0 || hasLeadingFence(false)) {
  215. return true;
  216. }
  217. LayoutProcessor lm = getChildLM();
  218. if (lm != null) {
  219. return lm.canBreakBefore(context);
  220. } else {
  221. return false; // ??? NO child LM?
  222. }
  223. }
  224. protected MinOptMax getPrevIPD(LayoutManager lm) {
  225. return (MinOptMax) hmPrevIPD.get(lm);
  226. }
  227. /**
  228. * Clear the previous IPD calculation.
  229. */
  230. protected void clearPrevIPD() {
  231. hmPrevIPD.clear();
  232. }
  233. /**
  234. * Get the next break position for this layout manager.
  235. * The next break position will be an position within the
  236. * areas return by the child inline layout managers.
  237. *
  238. * @param lc the layout context for finding breaks
  239. * @return the next break position
  240. */
  241. public BreakPoss getNextBreakPoss(LayoutContext lc) {
  242. // Get a break from currently active child LM
  243. BreakPoss bp = null;
  244. LayoutProcessor curLM;
  245. SpaceSpecifier leadingSpace = lc.getLeadingSpace();
  246. if (lc.startsNewArea()) {
  247. // First call to this LM in new parent "area", but this may
  248. // not be the first area created by this inline
  249. childLC = new LayoutContext(lc);
  250. lc.getLeadingSpace().addSpace(inlineProps.spaceStart);
  251. // Check for "fence"
  252. if (hasLeadingFence(!lc.isFirstArea())) {
  253. // Reset leading space sequence for child areas
  254. leadingSpace = new SpaceSpecifier(false);
  255. }
  256. // Reset state variables
  257. clearPrevIPD(); // Clear stored prev content dimensions
  258. }
  259. // We only do this loop more than once if a childLM returns
  260. // a null BreakPoss, meaning it has nothing (more) to layout.
  261. while ((curLM = getChildLM()) != null) {
  262. // ignore nested blocks for now
  263. if (!curLM.generatesInlineAreas()) {
  264. getLogger().warn("ignoring block inside inline fo");
  265. curLM.setFinished(true);
  266. continue;
  267. }
  268. /* If first break for this child LM, set START_AREA flag
  269. * and initialize pending space from previous LM sibling's
  270. * trailing space specifiers.
  271. */
  272. boolean bFirstChildBP = (prevBP == null
  273. || prevBP.getLayoutManager() != curLM);
  274. initChildLC(childLC, prevBP, lc.startsNewArea(),
  275. bFirstChildBP, leadingSpace);
  276. if (lc.tryHyphenate()) {
  277. childLC.setHyphContext(lc.getHyphContext());
  278. }
  279. if (((bp = curLM.getNextBreakPoss(childLC)) != null)
  280. || (lc.tryHyphenate()
  281. && !lc.getHyphContext().hasMoreHyphPoints())) {
  282. break;
  283. }
  284. // If LM has no content, should it generate any area? If not,
  285. // should trailing space from a previous area interact with
  286. // leading space from a following area?
  287. }
  288. if (bp == null) {
  289. setFinished(true);
  290. return null; // There was no childLM with anything to layout
  291. // Alternative is to return a BP with the isLast flag set
  292. } else {
  293. boolean bIsLast = false;
  294. if (getChildLM() == null) {
  295. bIsLast = true;
  296. setFinished(true);
  297. } else if (bp.couldEndLine()) {
  298. /* Child LM ends with suppressible spaces. See if it could
  299. * end this LM's area too. Child LM finish flag is NOT set!
  300. */
  301. bIsLast = !hasMoreLM(bp.getLayoutManager());
  302. }
  303. return makeBreakPoss(bp, lc, bIsLast);
  304. }
  305. }
  306. /** ATTENTION: ALSO USED BY LineLayoutManager! */
  307. protected void initChildLC(LayoutContext childLC, BreakPoss prevBP,
  308. boolean bStartParent, boolean bFirstChildBP,
  309. SpaceSpecifier leadingSpace) {
  310. childLC.setFlags(LayoutContext.NEW_AREA,
  311. (bFirstChildBP || bStartParent));
  312. if (bStartParent) {
  313. // Start of a new line area or inline parent area
  314. childLC.setFlags(LayoutContext.FIRST_AREA, bFirstChildBP);
  315. childLC.setLeadingSpace(leadingSpace);
  316. } else if (bFirstChildBP) {
  317. // Space-after sequence from previous "area"
  318. childLC.setFlags(LayoutContext.FIRST_AREA, true);
  319. childLC.setLeadingSpace(prevBP.getTrailingSpace());
  320. } else {
  321. childLC.setLeadingSpace(null);
  322. }
  323. }
  324. private BreakPoss makeBreakPoss(BreakPoss bp, LayoutContext lc,
  325. boolean bIsLast) {
  326. NonLeafPosition inlbp = new NonLeafPosition(this, bp.getPosition());
  327. BreakPoss myBP = new BreakPoss(inlbp, bp.getFlags());
  328. myBP.setFlag(BreakPoss.ISFIRST, lc.isFirstArea());
  329. myBP.setFlag(BreakPoss.ISLAST, bIsLast);
  330. if (bIsLast) {
  331. lastChildLM = bp.getLayoutManager();
  332. }
  333. // Update dimension information for our allocation area,
  334. // including child areas
  335. // generated by previous childLM which have completed layout
  336. // Update pending area measure
  337. // This includes all previous breakinfo
  338. MinOptMax bpDim = (MinOptMax) bp.getStackingSize().clone();
  339. MinOptMax prevIPD = updatePrevIPD(bp, prevBP, lc.startsNewArea(),
  340. lc.isFirstArea());
  341. if (lc.startsNewArea()) {
  342. myBP.setLeadingSpace(lc.getLeadingSpace());
  343. }
  344. // Add size of previous child areas which are finished
  345. bpDim.add(prevIPD);
  346. SpaceSpecifier trailingSpace = bp.getTrailingSpace();
  347. if (hasTrailingFence(!bIsLast)) {
  348. bpDim.add(bp.resolveTrailingSpace(false));
  349. trailingSpace = new SpaceSpecifier(false);
  350. } else {
  351. // Need this to avoid modifying pending space specifiers
  352. // on previous BP from child as we use these on the next
  353. // call in this LM
  354. trailingSpace = (SpaceSpecifier) trailingSpace.clone();
  355. }
  356. trailingSpace.addSpace(inlineProps.spaceEnd);
  357. myBP.setTrailingSpace(trailingSpace);
  358. // Add start and end borders and padding
  359. bpDim.add(getExtraIPD(!lc.isFirstArea(), !bIsLast));
  360. myBP.setStackingSize(bpDim);
  361. myBP.setNonStackingSize(
  362. MinOptMax.add(bp.getNonStackingSize(), extraBPD));
  363. prevBP = bp;
  364. // if (bIsLast) {
  365. // setFinished(true); // Our last area, so indicate done
  366. // }
  367. return myBP;
  368. }
  369. /** ATTENTION: ALSO USED BY LineLayoutManager! */
  370. protected MinOptMax updatePrevIPD(BreakPoss bp, BreakPoss prevBP,
  371. boolean bStartParent, boolean bFirstArea) {
  372. MinOptMax prevIPD = new MinOptMax(0);
  373. if (bStartParent) {
  374. if (hasLeadingFence(!bFirstArea)) {
  375. // Space-start before first child area placed
  376. prevIPD.add(bp.resolveLeadingSpace());
  377. }
  378. hmPrevIPD.put(bp.getLayoutManager(), prevIPD);
  379. } else {
  380. // In case of reset to a previous position, it may already
  381. // be calculated
  382. prevIPD = (MinOptMax) hmPrevIPD.get(bp.getLayoutManager());
  383. if (prevIPD == null) {
  384. // ASSERT(prevBP.getLayoutManager() != bp.getLayoutManager());
  385. /* This is first bp generated by child (in this parent area).
  386. * Calculate space-start on this area in combination with any
  387. * pending space-end with previous break.
  388. * Corresponds to Space between two child areas.
  389. */
  390. prevIPD = (MinOptMax) hmPrevIPD.get(
  391. prevBP.getLayoutManager());
  392. prevIPD = MinOptMax.add(prevIPD, bp.resolveLeadingSpace());
  393. prevIPD.add(prevBP.getStackingSize());
  394. hmPrevIPD.put(bp.getLayoutManager(), prevIPD);
  395. }
  396. }
  397. return prevIPD;
  398. }
  399. public void getWordChars(StringBuffer sbChars, Position bp1,
  400. Position bp2) {
  401. Position endPos = ((NonLeafPosition) bp2).getPosition();
  402. Position prevPos = null;
  403. if (bp1 != null) {
  404. prevPos = ((NonLeafPosition) bp1).getPosition();
  405. if (prevPos.getLM() != endPos.getLM()) {
  406. prevPos = null;
  407. }
  408. }
  409. endPos.getLM().getWordChars(sbChars, prevPos, endPos);
  410. }
  411. /******
  412. protected BreakableText getText(BreakPoss prevBP, BreakPoss lastBP) {
  413. }
  414. *****/
  415. protected InlineParent createArea() {
  416. return new InlineParent();
  417. }
  418. /**
  419. * Generate and add areas to parent area.
  420. * Set size of each area. This should only create and return one
  421. * inline area for any inline parent area.
  422. *
  423. * @param parentIter Iterator over Position information returned
  424. * by this LayoutManager.
  425. * @param dSpaceAdjust Factor controlling how much extra space to add
  426. * in order to justify the line.
  427. */
  428. public void addAreas(PositionIterator parentIter,
  429. LayoutContext context) {
  430. InlineParent parent = createArea();
  431. parent.setHeight(context.getLineHeight());
  432. parent.setOffset(0);
  433. setCurrentArea(parent);
  434. setChildContext(new LayoutContext(context)); // Store current value
  435. // If has fence, make a new leadingSS
  436. /* How to know if first area created by this LM? Keep a count and
  437. * reset it if getNextBreakPoss() is called again.
  438. */
  439. if (hasLeadingFence(bAreaCreated)) {
  440. getContext().setLeadingSpace(new SpaceSpecifier(false));
  441. getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE,
  442. true);
  443. } else {
  444. getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE,
  445. false);
  446. }
  447. context.getLeadingSpace().addSpace(inlineProps.spaceStart);
  448. // posIter iterates over positions returned by this LM
  449. StackingIter childPosIter = new StackingIter(parentIter);
  450. LayoutProcessor prevLM = null;
  451. LayoutProcessor childLM ;
  452. while ((childLM = childPosIter.getNextChildLM()) != null) {
  453. //getContext().setTrailingSpace(new SpaceSpecifier(false));
  454. childLM.addAreas(childPosIter, getContext());
  455. getContext().setLeadingSpace(getContext().getTrailingSpace());
  456. getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE,
  457. true);
  458. prevLM = childLM;
  459. }
  460. /* If has trailing fence, resolve trailing space specs from descendants.
  461. * Otherwise, propagate any trailing space specs to parent LM via
  462. * the context object.
  463. * If the last child LM called return ISLAST in the context object
  464. * and it is the last child LM for this LM, then this must be
  465. * the last area for the current LM also.
  466. */
  467. boolean bIsLast =
  468. (getContext().isLastArea() && prevLM == lastChildLM);
  469. if (hasTrailingFence(bIsLast)) {
  470. addSpace(getCurrentArea(),
  471. getContext().getTrailingSpace().resolve(false),
  472. getContext().getSpaceAdjust());
  473. context.setTrailingSpace(new SpaceSpecifier(false));
  474. } else {
  475. // Propagate trailing space-spec sequence to parent LM in context
  476. context.setTrailingSpace(getContext().getTrailingSpace());
  477. }
  478. // Add own trailing space to parent context (or set on area?)
  479. if (context.getTrailingSpace() != null) {
  480. context.getTrailingSpace().addSpace(inlineProps.spaceEnd);
  481. }
  482. // Add border and padding to current area and set flags (FIRST, LAST ...)
  483. TraitSetter.setBorderPaddingTraits(getCurrentArea(),
  484. borderProps, bAreaCreated, !bIsLast);
  485. if (borderProps != null) {
  486. TraitSetter.addBorders(getCurrentArea(), borderProps);
  487. }
  488. if (backgroundProps != null) {
  489. TraitSetter.addBackground(getCurrentArea(), backgroundProps);
  490. }
  491. parentLM.addChild(getCurrentArea());
  492. context.setFlags(LayoutContext.LAST_AREA, bIsLast);
  493. bAreaCreated = true;
  494. }
  495. protected Area getCurrentArea() {
  496. return currentArea;
  497. }
  498. protected void setCurrentArea(Area area) {
  499. currentArea = area;
  500. }
  501. public void addChild(Area childArea) {
  502. // Make sure childArea is inline area
  503. if (childArea instanceof InlineArea) {
  504. Area parent = getCurrentArea();
  505. if (getContext().resolveLeadingSpace()) {
  506. addSpace(parent,
  507. getContext().getLeadingSpace().resolve(false),
  508. getContext().getSpaceAdjust());
  509. }
  510. parent.addChild(childArea);
  511. }
  512. }
  513. protected void setChildContext(LayoutContext lc) {
  514. childLC = lc;
  515. }
  516. // Current child layout context
  517. protected LayoutContext getContext() {
  518. return childLC ;
  519. }
  520. protected void addSpace(Area parentArea, MinOptMax spaceRange,
  521. double dSpaceAdjust) {
  522. if (spaceRange != null) {
  523. int iAdjust = spaceRange.opt;
  524. if (dSpaceAdjust > 0.0) {
  525. // Stretch by factor
  526. iAdjust += (int)((double)(spaceRange.max
  527. - spaceRange.opt) * dSpaceAdjust);
  528. } else if (dSpaceAdjust < 0.0) {
  529. // Shrink by factor
  530. iAdjust += (int)((double)(spaceRange.opt
  531. - spaceRange.min) * dSpaceAdjust);
  532. }
  533. if (iAdjust != 0) {
  534. //getLogger().debug("Add leading space: " + iAdjust);
  535. Space ls = new Space();
  536. ls.setWidth(iAdjust);
  537. parentArea.addChild(ls);
  538. }
  539. }
  540. }
  541. }