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.

InlineLayoutManager.java 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. /* $Id$ */
  18. package org.apache.fop.layoutmgr.inline;
  19. import java.util.Iterator;
  20. import java.util.LinkedList;
  21. import java.util.List;
  22. import java.util.ListIterator;
  23. import org.apache.commons.logging.Log;
  24. import org.apache.commons.logging.LogFactory;
  25. import org.apache.fop.area.Area;
  26. import org.apache.fop.area.inline.InlineArea;
  27. import org.apache.fop.area.inline.InlineBlockParent;
  28. import org.apache.fop.area.inline.InlineParent;
  29. import org.apache.fop.datatypes.Length;
  30. import org.apache.fop.fo.flow.BasicLink;
  31. import org.apache.fop.fo.flow.Inline;
  32. import org.apache.fop.fo.flow.InlineLevel;
  33. import org.apache.fop.fo.flow.Leader;
  34. import org.apache.fop.fo.pagination.Title;
  35. import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  36. import org.apache.fop.fo.properties.CommonFont;
  37. import org.apache.fop.fo.properties.CommonMarginInline;
  38. import org.apache.fop.fo.properties.SpaceProperty;
  39. import org.apache.fop.fonts.Font;
  40. import org.apache.fop.fonts.FontInfo;
  41. import org.apache.fop.fonts.FontTriplet;
  42. import org.apache.fop.layoutmgr.BlockKnuthSequence;
  43. import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
  44. import org.apache.fop.layoutmgr.BreakElement;
  45. import org.apache.fop.layoutmgr.InlineKnuthSequence;
  46. import org.apache.fop.layoutmgr.KnuthBox;
  47. import org.apache.fop.layoutmgr.KnuthSequence;
  48. import org.apache.fop.layoutmgr.LayoutContext;
  49. import org.apache.fop.layoutmgr.LayoutManager;
  50. import org.apache.fop.layoutmgr.NonLeafPosition;
  51. import org.apache.fop.layoutmgr.Position;
  52. import org.apache.fop.layoutmgr.PositionIterator;
  53. import org.apache.fop.layoutmgr.SpaceSpecifier;
  54. import org.apache.fop.layoutmgr.TraitSetter;
  55. import org.apache.fop.traits.MinOptMax;
  56. import org.apache.fop.traits.SpaceVal;
  57. import org.apache.fop.util.ListUtil;
  58. /**
  59. * LayoutManager for objects which stack children in the inline direction,
  60. * such as Inline or Line
  61. */
  62. public class InlineLayoutManager extends InlineStackingLayoutManager {
  63. /**
  64. * logging instance
  65. */
  66. private static Log log = LogFactory.getLog(InlineLayoutManager.class);
  67. private CommonMarginInline inlineProps = null;
  68. private CommonBorderPaddingBackground borderProps = null;
  69. private boolean areaCreated = false;
  70. private LayoutManager lastChildLM = null; // Set when return last breakposs;
  71. private Font font;
  72. /** The alignment adjust property */
  73. protected Length alignmentAdjust;
  74. /** The alignment baseline property */
  75. protected int alignmentBaseline = EN_BASELINE;
  76. /** The baseline shift property */
  77. protected Length baselineShift;
  78. /** The dominant baseline property */
  79. protected int dominantBaseline;
  80. /** The line height property */
  81. protected SpaceProperty lineHeight;
  82. /** The keep-together property */
  83. //private KeepProperty keepTogether;
  84. private AlignmentContext alignmentContext = null;
  85. /**
  86. * Create an inline layout manager.
  87. * This is used for fo's that create areas that
  88. * contain inline areas.
  89. *
  90. * @param node the formatting object that creates the area
  91. */
  92. // The node should be FObjMixed
  93. public InlineLayoutManager(InlineLevel node) {
  94. super(node);
  95. }
  96. /** {@inheritDoc} */
  97. @Override
  98. public void initialize() {
  99. InlineLevel fobj = (InlineLevel) this.fobj;
  100. int padding = 0;
  101. FontInfo fi = fobj.getFOEventHandler().getFontInfo();
  102. CommonFont commonFont = fobj.getCommonFont();
  103. FontTriplet[] fontkeys = commonFont.getFontState(fi);
  104. font = fi.getFontInstance(fontkeys[0], commonFont.fontSize.getValue(this));
  105. lineHeight = fobj.getLineHeight();
  106. borderProps = fobj.getCommonBorderPaddingBackground();
  107. inlineProps = fobj.getCommonMarginInline();
  108. if (fobj instanceof Inline) {
  109. alignmentAdjust = ((Inline)fobj).getAlignmentAdjust();
  110. alignmentBaseline = ((Inline)fobj).getAlignmentBaseline();
  111. baselineShift = ((Inline)fobj).getBaselineShift();
  112. dominantBaseline = ((Inline)fobj).getDominantBaseline();
  113. } else if (fobj instanceof Leader) {
  114. alignmentAdjust = ((Leader)fobj).getAlignmentAdjust();
  115. alignmentBaseline = ((Leader)fobj).getAlignmentBaseline();
  116. baselineShift = ((Leader)fobj).getBaselineShift();
  117. dominantBaseline = ((Leader)fobj).getDominantBaseline();
  118. } else if (fobj instanceof BasicLink) {
  119. alignmentAdjust = ((BasicLink)fobj).getAlignmentAdjust();
  120. alignmentBaseline = ((BasicLink)fobj).getAlignmentBaseline();
  121. baselineShift = ((BasicLink)fobj).getBaselineShift();
  122. dominantBaseline = ((BasicLink)fobj).getDominantBaseline();
  123. }
  124. if (borderProps != null) {
  125. padding = borderProps.getPadding(CommonBorderPaddingBackground.BEFORE, false, this);
  126. padding += borderProps.getBorderWidth(CommonBorderPaddingBackground.BEFORE,
  127. false);
  128. padding += borderProps.getPadding(CommonBorderPaddingBackground.AFTER, false, this);
  129. padding += borderProps.getBorderWidth(CommonBorderPaddingBackground.AFTER, false);
  130. }
  131. extraBPD = MinOptMax.getInstance(padding);
  132. }
  133. /** {@inheritDoc} */
  134. @Override
  135. protected MinOptMax getExtraIPD(boolean isNotFirst, boolean isNotLast) {
  136. int borderAndPadding = 0;
  137. if (borderProps != null) {
  138. borderAndPadding
  139. = borderProps.getPadding(CommonBorderPaddingBackground.START, isNotFirst, this);
  140. borderAndPadding
  141. += borderProps.getBorderWidth(CommonBorderPaddingBackground.START, isNotFirst);
  142. borderAndPadding
  143. += borderProps.getPadding(CommonBorderPaddingBackground.END, isNotLast, this);
  144. borderAndPadding
  145. += borderProps.getBorderWidth(CommonBorderPaddingBackground.END, isNotLast);
  146. }
  147. return MinOptMax.getInstance(borderAndPadding);
  148. }
  149. /** {@inheritDoc} */
  150. @Override
  151. protected boolean hasLeadingFence(boolean isNotFirst) {
  152. return borderProps != null
  153. && (borderProps.getPadding(CommonBorderPaddingBackground.START, isNotFirst, this) > 0
  154. || borderProps.getBorderWidth(CommonBorderPaddingBackground.START, isNotFirst) > 0
  155. );
  156. }
  157. /** {@inheritDoc} */
  158. @Override
  159. protected boolean hasTrailingFence(boolean isNotLast) {
  160. return borderProps != null
  161. && (borderProps.getPadding(CommonBorderPaddingBackground.END, isNotLast, this) > 0
  162. || borderProps.getBorderWidth(CommonBorderPaddingBackground.END, isNotLast) > 0
  163. );
  164. }
  165. /** {@inheritDoc} */
  166. @Override
  167. protected SpaceProperty getSpaceStart() {
  168. return inlineProps != null ? inlineProps.spaceStart : null;
  169. }
  170. /** {@inheritDoc} */
  171. @Override
  172. protected SpaceProperty getSpaceEnd() {
  173. return inlineProps != null ? inlineProps.spaceEnd : null;
  174. }
  175. /**
  176. * Create and initialize an <code>InlineArea</code>
  177. *
  178. * @param isInline true if the parent is an inline
  179. * @return the area
  180. */
  181. protected InlineArea createArea(boolean isInline) {
  182. InlineArea area;
  183. if (isInline) {
  184. area = createInlineParent();
  185. area.setBlockProgressionOffset(0);
  186. } else {
  187. area = new InlineBlockParent();
  188. }
  189. if (fobj instanceof Inline || fobj instanceof BasicLink) {
  190. TraitSetter.setProducerID(area, fobj.getId());
  191. }
  192. return area;
  193. }
  194. /**
  195. * Creates the inline area that will contain the areas returned by the
  196. * children of this layout manager.
  197. *
  198. * @return a new inline area
  199. */
  200. protected InlineParent createInlineParent() {
  201. return new InlineParent();
  202. }
  203. /** {@inheritDoc} */
  204. @Override
  205. protected void setTraits(boolean isNotFirst, boolean isNotLast) {
  206. if (borderProps != null) {
  207. // Add border and padding to current area and set flags (FIRST, LAST ...)
  208. TraitSetter.setBorderPaddingTraits(getCurrentArea(),
  209. borderProps, isNotFirst, isNotLast, this);
  210. TraitSetter.addBackground(getCurrentArea(), borderProps, this);
  211. }
  212. }
  213. /**
  214. * @return true if this element must be kept together
  215. */
  216. public boolean mustKeepTogether() {
  217. return mustKeepTogether(this.getParent());
  218. }
  219. private boolean mustKeepTogether(LayoutManager lm) {
  220. if (lm instanceof BlockLevelLayoutManager) {
  221. return ((BlockLevelLayoutManager) lm).mustKeepTogether();
  222. } else if (lm instanceof InlineLayoutManager) {
  223. return ((InlineLayoutManager) lm).mustKeepTogether();
  224. } else {
  225. return mustKeepTogether(lm.getParent());
  226. }
  227. }
  228. /** {@inheritDoc} */
  229. @Override // CSOK: MethodLength
  230. public List getNextKnuthElements
  231. (LayoutContext context, int alignment) {
  232. LayoutManager curLM;
  233. // the list returned by child LM
  234. List<KnuthSequence> returnedList;
  235. // the list which will be returned to the parent LM
  236. List<KnuthSequence> returnList = new LinkedList<KnuthSequence>();
  237. KnuthSequence lastSequence = null;
  238. if (fobj instanceof Title) {
  239. alignmentContext = new AlignmentContext(font,
  240. lineHeight.getOptimum(this).getLength().getValue(this),
  241. context.getWritingMode());
  242. } else {
  243. alignmentContext = new AlignmentContext(font
  244. , lineHeight.getOptimum(this).getLength().getValue(this)
  245. , alignmentAdjust
  246. , alignmentBaseline
  247. , baselineShift
  248. , dominantBaseline
  249. , context.getAlignmentContext());
  250. }
  251. childLC = LayoutContext.copyOf(context);
  252. childLC.setAlignmentContext(alignmentContext);
  253. if (context.startsNewArea()) {
  254. // First call to this LM in new parent "area", but this may
  255. // not be the first area created by this inline
  256. if (getSpaceStart() != null) {
  257. context.getLeadingSpace().addSpace(new SpaceVal(getSpaceStart(), this));
  258. }
  259. }
  260. StringBuffer trace = new StringBuffer("InlineLM:");
  261. // We'll add the border to the first inline sequence created.
  262. // This flag makes sure we do it only once.
  263. boolean borderAdded = false;
  264. if (borderProps != null) {
  265. childLC.setLineStartBorderAndPaddingWidth(context.getLineStartBorderAndPaddingWidth()
  266. + borderProps.getPaddingStart(true, this)
  267. + borderProps.getBorderStartWidth(true)
  268. );
  269. childLC.setLineEndBorderAndPaddingWidth(context.getLineEndBorderAndPaddingWidth()
  270. + borderProps.getPaddingEnd(true, this)
  271. + borderProps.getBorderEndWidth(true)
  272. );
  273. }
  274. while ((curLM = getChildLM()) != null) {
  275. if (!(curLM instanceof InlineLevelLayoutManager)) {
  276. // A block LM
  277. // Leave room for start/end border and padding
  278. if (borderProps != null) {
  279. childLC.setRefIPD(childLC.getRefIPD()
  280. - borderProps.getPaddingStart(lastChildLM != null, this)
  281. - borderProps.getBorderStartWidth(lastChildLM != null)
  282. - borderProps.getPaddingEnd(hasNextChildLM(), this)
  283. - borderProps.getBorderEndWidth(hasNextChildLM()));
  284. }
  285. }
  286. // get KnuthElements from curLM
  287. returnedList = curLM.getNextKnuthElements(childLC, alignment);
  288. if (returnList.isEmpty() && childLC.isKeepWithPreviousPending()) {
  289. childLC.clearKeepWithPreviousPending();
  290. }
  291. if (returnedList == null
  292. || returnedList.isEmpty()) {
  293. // curLM returned null or an empty list, because it finished;
  294. // just iterate once more to see if there is another child
  295. continue;
  296. }
  297. if (curLM instanceof InlineLevelLayoutManager) {
  298. context.clearKeepWithNextPending();
  299. // "wrap" the Position stored in each element of returnedList
  300. ListIterator seqIter = returnedList.listIterator();
  301. while (seqIter.hasNext()) {
  302. KnuthSequence sequence = (KnuthSequence) seqIter.next();
  303. sequence.wrapPositions(this);
  304. }
  305. int insertionStartIndex = 0;
  306. if (lastSequence != null
  307. && lastSequence.appendSequenceOrClose(returnedList.get(0))) {
  308. insertionStartIndex = 1;
  309. }
  310. // add border and padding to the first complete sequence of this LM
  311. if (!borderAdded && !returnedList.isEmpty()) {
  312. addKnuthElementsForBorderPaddingStart(returnedList.get(0));
  313. borderAdded = true;
  314. }
  315. for (Iterator<KnuthSequence> iter = returnedList.listIterator(insertionStartIndex);
  316. iter.hasNext();) {
  317. returnList.add(iter.next());
  318. }
  319. } else { // A block LM
  320. BlockKnuthSequence sequence = new BlockKnuthSequence(returnedList);
  321. sequence.wrapPositions(this);
  322. boolean appended = false;
  323. if (lastSequence != null) {
  324. if (lastSequence.canAppendSequence(sequence)) {
  325. BreakElement bk = new BreakElement(new Position(this), 0, context);
  326. boolean keepTogether = (mustKeepTogether()
  327. || context.isKeepWithNextPending()
  328. || childLC.isKeepWithPreviousPending());
  329. appended = lastSequence.appendSequenceOrClose(sequence, keepTogether, bk);
  330. } else {
  331. lastSequence.endSequence();
  332. }
  333. }
  334. if (!appended) {
  335. // add border and padding to the first complete sequence of this LM
  336. if (!borderAdded) {
  337. addKnuthElementsForBorderPaddingStart(sequence);
  338. borderAdded = true;
  339. }
  340. returnList.add(sequence);
  341. }
  342. // propagate and clear
  343. context.updateKeepWithNextPending(childLC.getKeepWithNextPending());
  344. childLC.clearKeepsPending();
  345. }
  346. lastSequence = ListUtil.getLast(returnList);
  347. lastChildLM = curLM;
  348. // the context used to create this childLC above was applied a LayoutContext.SUPPRESS_BREAK_BEFORE
  349. // in the getNextChildElements() method of the parent BlockLayoutManger; as a consequence all
  350. // line breaks in blocks nested inside the inline associated with this ILM are being supressed;
  351. // here we revert that supression; we do not need to do that for the first element since that
  352. // is handled by the getBreakBefore() method of the wrapping BlockStackingLayoutManager.
  353. // Note: this fix seems to work but is far from being the ideal way to do this
  354. childLC.setFlags(LayoutContext.SUPPRESS_BREAK_BEFORE, false);
  355. }
  356. if (lastSequence != null) {
  357. addKnuthElementsForBorderPaddingEnd(lastSequence);
  358. }
  359. setFinished(true);
  360. log.trace(trace);
  361. if (returnList.isEmpty()) {
  362. /*
  363. * if the FO itself is empty, but has an id specified
  364. * or associated fo:markers, then we still need a dummy
  365. * sequence to register its position in the area tree
  366. */
  367. if (fobj.hasId() || fobj.hasMarkers()) {
  368. InlineKnuthSequence emptySeq = new InlineKnuthSequence();
  369. emptySeq.add(new KnuthInlineBox(
  370. 0,
  371. alignmentContext,
  372. notifyPos(getAuxiliaryPosition()),
  373. true));
  374. returnList.add(emptySeq);
  375. }
  376. }
  377. return returnList.isEmpty() ? null : returnList;
  378. }
  379. /**
  380. * Generate and add areas to parent area.
  381. * Set size of each area. This should only create and return one
  382. * inline area for any inline parent area.
  383. *
  384. * @param parentIter Iterator over Position information returned
  385. * by this LayoutManager.
  386. * @param context layout context.
  387. */
  388. @Override
  389. public void addAreas(PositionIterator parentIter,
  390. LayoutContext context) {
  391. addId();
  392. setChildContext(LayoutContext.copyOf(context)); // Store current value
  393. // "Unwrap" the NonLeafPositions stored in parentIter and put
  394. // them in a new list. Set lastLM to be the LayoutManager
  395. // which created the last Position: if the LAST_AREA flag is
  396. // set in the layout context, it must be also set in the
  397. // layout context given to lastLM, but must be cleared in the
  398. // layout context given to the other LMs.
  399. List<Position> positionList = new LinkedList<Position>();
  400. Position pos;
  401. LayoutManager lastLM = null; // last child LM in this iterator
  402. Position lastPos = null;
  403. while (parentIter.hasNext()) {
  404. pos = parentIter.next();
  405. if (pos != null && pos.getPosition() != null) {
  406. if (isFirst(pos)) {
  407. /*
  408. * If this element is a descendant of a table-header/footer,
  409. * its content may be repeated over pages, so the generation
  410. * of its areas may be restarted.
  411. */
  412. areaCreated = false;
  413. }
  414. positionList.add(pos.getPosition());
  415. lastLM = pos.getPosition().getLM();
  416. lastPos = pos;
  417. }
  418. }
  419. // If this LM has fence, make a new leading space specifier.
  420. if (hasLeadingFence(areaCreated)) {
  421. getContext().setLeadingSpace(new SpaceSpecifier(false));
  422. getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
  423. } else {
  424. getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE, false);
  425. }
  426. if (getSpaceStart() != null) {
  427. context.getLeadingSpace().addSpace(new SpaceVal(getSpaceStart(), this));
  428. }
  429. registerMarkers(
  430. true,
  431. !areaCreated,
  432. lastPos == null || isLast(lastPos));
  433. InlineArea parent = createArea(lastLM == null
  434. || lastLM instanceof InlineLevelLayoutManager);
  435. parent.setBPD(alignmentContext.getHeight());
  436. if (parent instanceof InlineParent) {
  437. parent.setBlockProgressionOffset(alignmentContext.getOffset());
  438. } else if (parent instanceof InlineBlockParent) {
  439. // All inline elements are positioned by the renderers relative to
  440. // the before edge of their content rectangle
  441. if (borderProps != null) {
  442. parent.setBlockProgressionOffset(borderProps.getPaddingBefore(false, this)
  443. + borderProps.getBorderBeforeWidth(false));
  444. }
  445. }
  446. setCurrentArea(parent);
  447. PositionIterator childPosIter
  448. = new PositionIterator(positionList.listIterator());
  449. LayoutManager prevLM = null;
  450. LayoutManager childLM;
  451. while ((childLM = childPosIter.getNextChildLM()) != null) {
  452. getContext().setFlags(LayoutContext.LAST_AREA,
  453. context.isLastArea() && childLM == lastLM);
  454. childLM.addAreas(childPosIter, getContext());
  455. getContext().setLeadingSpace(getContext().getTrailingSpace());
  456. getContext().setFlags(LayoutContext.RESOLVE_LEADING_SPACE, true);
  457. prevLM = childLM;
  458. }
  459. /* If this LM has a trailing fence, resolve trailing space
  460. * specs from descendants. Otherwise, propagate any trailing
  461. * space specs to the parent LM via the layout context. If
  462. * the last child LM called returns LAST_AREA in the layout
  463. * context and it is the last child LM for this LM, then this
  464. * must be the last area for the current LM too.
  465. */
  466. boolean isLast = (getContext().isLastArea() && prevLM == lastChildLM);
  467. if (hasTrailingFence(isLast)) {
  468. addSpace(getCurrentArea(), getContext().getTrailingSpace().resolve(false),
  469. getContext().getSpaceAdjust());
  470. context.setTrailingSpace(new SpaceSpecifier(false));
  471. } else {
  472. // Propagate trailing space-spec sequence to parent LM in context.
  473. context.setTrailingSpace(getContext().getTrailingSpace());
  474. }
  475. // Add own trailing space to parent context (or set on area?)
  476. if (context.getTrailingSpace() != null && getSpaceEnd() != null) {
  477. context.getTrailingSpace().addSpace(new SpaceVal(getSpaceEnd(), this));
  478. }
  479. // Not sure if lastPos can legally be null or if that masks a different problem.
  480. // But it seems to fix bug 38053.
  481. setTraits(areaCreated, lastPos == null || !isLast(lastPos));
  482. parentLayoutManager.addChildArea(getCurrentArea());
  483. registerMarkers(
  484. false,
  485. !areaCreated,
  486. lastPos == null || isLast(lastPos));
  487. context.setFlags(LayoutContext.LAST_AREA, isLast);
  488. areaCreated = true;
  489. checkEndOfLayout(lastPos);
  490. }
  491. /** {@inheritDoc} */
  492. @Override
  493. public void addChildArea(Area childArea) {
  494. Area parent = getCurrentArea();
  495. if (getContext().resolveLeadingSpace()) {
  496. addSpace(parent, getContext().getLeadingSpace().resolve(false),
  497. getContext().getSpaceAdjust());
  498. }
  499. parent.addChildArea(childArea);
  500. }
  501. /** {@inheritDoc} */
  502. @Override
  503. public List getChangedKnuthElements(List oldList, int alignment, int depth) {
  504. List returnedList = new LinkedList();
  505. addKnuthElementsForBorderPaddingStart(returnedList);
  506. returnedList.addAll(super.getChangedKnuthElements(oldList, alignment, depth));
  507. addKnuthElementsForBorderPaddingEnd(returnedList);
  508. return returnedList;
  509. }
  510. /**
  511. * Creates Knuth elements for start border padding and adds them to the return list.
  512. * @param returnList return list to add the additional elements to
  513. */
  514. protected void addKnuthElementsForBorderPaddingStart(List returnList) {
  515. //Border and Padding (start)
  516. /*
  517. * If the returnlist is a BlockKnuthSequence, the border and padding should be added
  518. * to the first paragraph inside it, but it is too late to do that now.
  519. * At least, avoid adding it to the bpd sequence.
  520. */
  521. if (returnList instanceof BlockKnuthSequence) {
  522. return;
  523. }
  524. CommonBorderPaddingBackground borderAndPadding
  525. = ((InlineLevel)fobj).getCommonBorderPaddingBackground();
  526. if (borderAndPadding != null) {
  527. int ipStart = borderAndPadding.getBorderStartWidth(false)
  528. + borderAndPadding.getPaddingStart(false, this);
  529. if (ipStart > 0) {
  530. returnList.add(0, new KnuthBox(ipStart, getAuxiliaryPosition(), true));
  531. }
  532. }
  533. }
  534. /**
  535. * Creates Knuth elements for end border padding and adds them to the return list.
  536. * @param returnList return list to add the additional elements to
  537. */
  538. protected void addKnuthElementsForBorderPaddingEnd(List returnList) {
  539. //Border and Padding (after)
  540. /*
  541. * If the returnlist is a BlockKnuthSequence, the border and padding should be added
  542. * to the last paragraph inside it, but it is too late to do that now.
  543. * At least, avoid adding it to the bpd sequence.
  544. */
  545. if (returnList instanceof BlockKnuthSequence) {
  546. return;
  547. }
  548. CommonBorderPaddingBackground borderAndPadding
  549. = ((InlineLevel)fobj).getCommonBorderPaddingBackground();
  550. if (borderAndPadding != null) {
  551. int ipEnd = borderAndPadding.getBorderEndWidth(false)
  552. + borderAndPadding.getPaddingEnd(false, this);
  553. if (ipEnd > 0) {
  554. returnList.add(new KnuthBox(ipEnd, getAuxiliaryPosition(), true));
  555. }
  556. }
  557. }
  558. /** @return an auxiliary {@link Position} instance used for things like spaces. */
  559. protected Position getAuxiliaryPosition() {
  560. return new NonLeafPosition(this, null);
  561. }
  562. }