您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

InlineLayoutManager.java 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  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 org.apache.commons.logging.Log;
  23. import org.apache.commons.logging.LogFactory;
  24. import org.apache.fop.area.Area;
  25. import org.apache.fop.area.inline.InlineArea;
  26. import org.apache.fop.area.inline.InlineBlockParent;
  27. import org.apache.fop.area.inline.InlineParent;
  28. import org.apache.fop.datatypes.Length;
  29. import org.apache.fop.fo.flow.BasicLink;
  30. import org.apache.fop.fo.flow.Inline;
  31. import org.apache.fop.fo.flow.InlineLevel;
  32. import org.apache.fop.fo.flow.Leader;
  33. import org.apache.fop.fo.pagination.Title;
  34. import org.apache.fop.fo.properties.CommonBorderPaddingBackground;
  35. import org.apache.fop.fo.properties.CommonFont;
  36. import org.apache.fop.fo.properties.CommonMarginInline;
  37. import org.apache.fop.fo.properties.SpaceProperty;
  38. import org.apache.fop.fonts.Font;
  39. import org.apache.fop.fonts.FontInfo;
  40. import org.apache.fop.fonts.FontTriplet;
  41. import org.apache.fop.layoutmgr.BlockKnuthSequence;
  42. import org.apache.fop.layoutmgr.BlockLevelLayoutManager;
  43. import org.apache.fop.layoutmgr.BreakElement;
  44. import org.apache.fop.layoutmgr.InlineKnuthSequence;
  45. import org.apache.fop.layoutmgr.KnuthBox;
  46. import org.apache.fop.layoutmgr.KnuthSequence;
  47. import org.apache.fop.layoutmgr.LayoutContext;
  48. import org.apache.fop.layoutmgr.LayoutManager;
  49. import org.apache.fop.layoutmgr.NonLeafPosition;
  50. import org.apache.fop.layoutmgr.Position;
  51. import org.apache.fop.layoutmgr.PositionIterator;
  52. import org.apache.fop.layoutmgr.SpaceSpecifier;
  53. import org.apache.fop.layoutmgr.TraitSetter;
  54. import org.apache.fop.traits.MinOptMax;
  55. import org.apache.fop.traits.SpaceVal;
  56. import org.apache.fop.util.ListUtil;
  57. /**
  58. * LayoutManager for objects which stack children in the inline direction,
  59. * such as Inline or Line
  60. */
  61. public class InlineLayoutManager extends InlineStackingLayoutManager {
  62. /**
  63. * logging instance
  64. */
  65. private static Log log = LogFactory.getLog(InlineLayoutManager.class);
  66. private CommonMarginInline inlineProps;
  67. private CommonBorderPaddingBackground borderProps;
  68. private boolean areaCreated;
  69. private LayoutManager lastChildLM; // Set when return last breakposs;
  70. private Font font;
  71. /** The alignment adjust property */
  72. protected Length alignmentAdjust;
  73. /** The alignment baseline property */
  74. protected int alignmentBaseline = EN_BASELINE;
  75. /** The baseline shift property */
  76. protected Length baselineShift;
  77. /** The dominant baseline property */
  78. protected int dominantBaseline;
  79. /** The line height property */
  80. protected SpaceProperty lineHeight;
  81. /** The keep-together property */
  82. //private KeepProperty keepTogether;
  83. private AlignmentContext alignmentContext;
  84. /**
  85. * Create an inline layout manager.
  86. * This is used for fo's that create areas that
  87. * contain inline areas.
  88. *
  89. * @param node the formatting object that creates the area
  90. */
  91. // The node should be FObjMixed
  92. public InlineLayoutManager(InlineLevel node) {
  93. super(node);
  94. }
  95. /** {@inheritDoc} */
  96. @Override
  97. public void initialize() {
  98. InlineLevel fobj = (InlineLevel) this.fobj;
  99. int padding = 0;
  100. FontInfo fi = fobj.getFOEventHandler().getFontInfo();
  101. CommonFont commonFont = fobj.getCommonFont();
  102. FontTriplet[] fontkeys = commonFont.getFontState(fi);
  103. font = fi.getFontInstance(fontkeys[0], commonFont.fontSize.getValue(this));
  104. lineHeight = fobj.getLineHeight();
  105. borderProps = fobj.getCommonBorderPaddingBackground();
  106. inlineProps = fobj.getCommonMarginInline();
  107. if (fobj instanceof Inline) {
  108. alignmentAdjust = ((Inline)fobj).getAlignmentAdjust();
  109. alignmentBaseline = ((Inline)fobj).getAlignmentBaseline();
  110. baselineShift = ((Inline)fobj).getBaselineShift();
  111. dominantBaseline = ((Inline)fobj).getDominantBaseline();
  112. } else if (fobj instanceof Leader) {
  113. alignmentAdjust = ((Leader)fobj).getAlignmentAdjust();
  114. alignmentBaseline = ((Leader)fobj).getAlignmentBaseline();
  115. baselineShift = ((Leader)fobj).getBaselineShift();
  116. dominantBaseline = ((Leader)fobj).getDominantBaseline();
  117. } else if (fobj instanceof BasicLink) {
  118. alignmentAdjust = ((BasicLink)fobj).getAlignmentAdjust();
  119. alignmentBaseline = ((BasicLink)fobj).getAlignmentBaseline();
  120. baselineShift = ((BasicLink)fobj).getBaselineShift();
  121. dominantBaseline = ((BasicLink)fobj).getDominantBaseline();
  122. }
  123. if (borderProps != null) {
  124. padding = borderProps.getPadding(CommonBorderPaddingBackground.BEFORE, false, this);
  125. padding += borderProps.getBorderWidth(CommonBorderPaddingBackground.BEFORE,
  126. false);
  127. padding += borderProps.getPadding(CommonBorderPaddingBackground.AFTER, false, this);
  128. padding += borderProps.getBorderWidth(CommonBorderPaddingBackground.AFTER, false);
  129. }
  130. extraBPD = MinOptMax.getInstance(padding);
  131. }
  132. /** {@inheritDoc} */
  133. @Override
  134. protected MinOptMax getExtraIPD(boolean isNotFirst, boolean isNotLast) {
  135. int borderAndPadding = 0;
  136. if (borderProps != null) {
  137. borderAndPadding
  138. = borderProps.getPadding(CommonBorderPaddingBackground.START, isNotFirst, this);
  139. borderAndPadding
  140. += borderProps.getBorderWidth(CommonBorderPaddingBackground.START, isNotFirst);
  141. borderAndPadding
  142. += borderProps.getPadding(CommonBorderPaddingBackground.END, isNotLast, this);
  143. borderAndPadding
  144. += borderProps.getBorderWidth(CommonBorderPaddingBackground.END, isNotLast);
  145. }
  146. return MinOptMax.getInstance(borderAndPadding);
  147. }
  148. /** {@inheritDoc} */
  149. @Override
  150. protected boolean hasLeadingFence(boolean isNotFirst) {
  151. return borderProps != null
  152. && (borderProps.getPadding(CommonBorderPaddingBackground.START, isNotFirst, this) > 0
  153. || borderProps.getBorderWidth(CommonBorderPaddingBackground.START, isNotFirst) > 0
  154. );
  155. }
  156. /** {@inheritDoc} */
  157. @Override
  158. protected boolean hasTrailingFence(boolean isNotLast) {
  159. return borderProps != null
  160. && (borderProps.getPadding(CommonBorderPaddingBackground.END, isNotLast, this) > 0
  161. || borderProps.getBorderWidth(CommonBorderPaddingBackground.END, isNotLast) > 0
  162. );
  163. }
  164. /** {@inheritDoc} */
  165. @Override
  166. protected SpaceProperty getSpaceStart() {
  167. return inlineProps != null ? inlineProps.spaceStart : null;
  168. }
  169. /** {@inheritDoc} */
  170. @Override
  171. protected SpaceProperty getSpaceEnd() {
  172. return inlineProps != null ? inlineProps.spaceEnd : null;
  173. }
  174. /**
  175. * Create and initialize an <code>InlineArea</code>
  176. *
  177. * @param isInline true if the parent is an inline
  178. * @return the area
  179. */
  180. protected InlineArea createArea(boolean isInline) {
  181. InlineArea area;
  182. if (isInline) {
  183. area = createInlineParent();
  184. area.setChangeBarList(getChangeBarList());
  185. area.setBlockProgressionOffset(0);
  186. } else {
  187. area = new InlineBlockParent();
  188. area.setChangeBarList(getChangeBarList());
  189. }
  190. if (fobj instanceof Inline || fobj instanceof BasicLink) {
  191. TraitSetter.setProducerID(area, fobj.getId());
  192. TraitSetter.setLayer(area, fobj.getLayer());
  193. }
  194. return area;
  195. }
  196. /**
  197. * Creates the inline area that will contain the areas returned by the
  198. * children of this layout manager.
  199. *
  200. * @return a new inline area
  201. */
  202. protected InlineParent createInlineParent() {
  203. return new InlineParent();
  204. }
  205. /** {@inheritDoc} */
  206. @Override
  207. protected void setTraits(boolean isNotFirst, boolean isNotLast) {
  208. if (borderProps != null) {
  209. // Add border and padding to current area and set flags (FIRST, LAST ...)
  210. TraitSetter.setBorderPaddingTraits(getCurrentArea(),
  211. borderProps, isNotFirst, isNotLast, this);
  212. TraitSetter.addBackground(getCurrentArea(), borderProps, this);
  213. }
  214. }
  215. /**
  216. * @return true if this element must be kept together
  217. */
  218. public boolean mustKeepTogether() {
  219. return mustKeepTogether(this.getParent());
  220. }
  221. private boolean mustKeepTogether(LayoutManager lm) {
  222. if (lm instanceof BlockLevelLayoutManager) {
  223. return ((BlockLevelLayoutManager) lm).mustKeepTogether();
  224. } else if (lm instanceof InlineLayoutManager) {
  225. return ((InlineLayoutManager) lm).mustKeepTogether();
  226. } else {
  227. return mustKeepTogether(lm.getParent());
  228. }
  229. }
  230. /** {@inheritDoc} */
  231. @Override
  232. public List getNextKnuthElements(
  233. LayoutContext context, int alignment) {
  234. LayoutManager curLM;
  235. // the list returned by child LM
  236. List<KnuthSequence> returnedList;
  237. // the list which will be returned to the parent LM
  238. List<KnuthSequence> returnList = new LinkedList<KnuthSequence>();
  239. KnuthSequence lastSequence = null;
  240. if (fobj instanceof Title) {
  241. alignmentContext = new AlignmentContext(font,
  242. lineHeight.getOptimum(this).getLength().getValue(this),
  243. context.getWritingMode());
  244. } else {
  245. alignmentContext = new AlignmentContext(font
  246. , lineHeight.getOptimum(this).getLength().getValue(this)
  247. , alignmentAdjust
  248. , alignmentBaseline
  249. , baselineShift
  250. , dominantBaseline
  251. , context.getAlignmentContext());
  252. }
  253. childLC = LayoutContext.copyOf(context);
  254. childLC.setAlignmentContext(alignmentContext);
  255. if (context.startsNewArea()) {
  256. // First call to this LM in new parent "area", but this may
  257. // not be the first area created by this inline
  258. if (getSpaceStart() != null) {
  259. context.getLeadingSpace().addSpace(new SpaceVal(getSpaceStart(), this));
  260. }
  261. }
  262. StringBuffer trace = new StringBuffer("InlineLM:");
  263. // We'll add the border to the first inline sequence created.
  264. // This flag makes sure we do it only once.
  265. boolean borderAdded = false;
  266. if (borderProps != null) {
  267. childLC.setLineStartBorderAndPaddingWidth(context.getLineStartBorderAndPaddingWidth()
  268. + borderProps.getPaddingStart(true, this)
  269. + borderProps.getBorderStartWidth(true)
  270. );
  271. childLC.setLineEndBorderAndPaddingWidth(context.getLineEndBorderAndPaddingWidth()
  272. + borderProps.getPaddingEnd(true, this)
  273. + borderProps.getBorderEndWidth(true)
  274. );
  275. }
  276. while ((curLM = getChildLM()) != null) {
  277. if (!(curLM instanceof InlineLevelLayoutManager)) {
  278. // A block LM
  279. // Leave room for start/end border and padding
  280. if (borderProps != null) {
  281. childLC.setRefIPD(childLC.getRefIPD()
  282. - borderProps.getPaddingStart(lastChildLM != null, this)
  283. - borderProps.getBorderStartWidth(lastChildLM != null)
  284. - borderProps.getPaddingEnd(hasNextChildLM(), this)
  285. - borderProps.getBorderEndWidth(hasNextChildLM()));
  286. }
  287. }
  288. // get KnuthElements from curLM
  289. returnedList = curLM.getNextKnuthElements(childLC, alignment);
  290. if (returnList.isEmpty() && childLC.isKeepWithPreviousPending()) {
  291. childLC.clearKeepWithPreviousPending();
  292. }
  293. if (returnedList == null
  294. || returnedList.isEmpty()) {
  295. // curLM returned null or an empty list, because it finished;
  296. // just iterate once more to see if there is another child
  297. continue;
  298. }
  299. if (curLM instanceof InlineLevelLayoutManager) {
  300. context.clearKeepWithNextPending();
  301. // "wrap" the Position stored in each element of returnedList
  302. for (KnuthSequence sequence : returnedList) {
  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. getCurrentArea().setFromFootnote(isFromFootnote());
  483. parentLayoutManager.addChildArea(getCurrentArea());
  484. registerMarkers(
  485. false,
  486. !areaCreated,
  487. lastPos == null || isLast(lastPos));
  488. context.setFlags(LayoutContext.LAST_AREA, isLast);
  489. areaCreated = true;
  490. checkEndOfLayout(lastPos);
  491. }
  492. /** {@inheritDoc} */
  493. @Override
  494. public void addChildArea(Area childArea) {
  495. Area parent = getCurrentArea();
  496. if (getContext().resolveLeadingSpace()) {
  497. addSpace(parent, getContext().getLeadingSpace().resolve(false),
  498. getContext().getSpaceAdjust());
  499. }
  500. parent.addChildArea(childArea);
  501. }
  502. /** {@inheritDoc} */
  503. @Override
  504. public List getChangedKnuthElements(List oldList, int alignment, int depth) {
  505. List returnedList = new LinkedList();
  506. addKnuthElementsForBorderPaddingStart(returnedList);
  507. returnedList.addAll(super.getChangedKnuthElements(oldList, alignment, depth));
  508. addKnuthElementsForBorderPaddingEnd(returnedList);
  509. return returnedList;
  510. }
  511. /**
  512. * Creates Knuth elements for start border padding and adds them to the return list.
  513. * @param returnList return list to add the additional elements to
  514. */
  515. protected void addKnuthElementsForBorderPaddingStart(List returnList) {
  516. //Border and Padding (start)
  517. /*
  518. * If the returnlist is a BlockKnuthSequence, the border and padding should be added
  519. * to the first paragraph inside it, but it is too late to do that now.
  520. * At least, avoid adding it to the bpd sequence.
  521. */
  522. if (returnList instanceof BlockKnuthSequence) {
  523. return;
  524. }
  525. CommonBorderPaddingBackground borderAndPadding
  526. = ((InlineLevel)fobj).getCommonBorderPaddingBackground();
  527. if (borderAndPadding != null) {
  528. int ipStart = borderAndPadding.getBorderStartWidth(false)
  529. + borderAndPadding.getPaddingStart(false, this);
  530. if (ipStart > 0) {
  531. returnList.add(0, new KnuthBox(ipStart, getAuxiliaryPosition(), true));
  532. }
  533. }
  534. }
  535. /**
  536. * Creates Knuth elements for end border padding and adds them to the return list.
  537. * @param returnList return list to add the additional elements to
  538. */
  539. protected void addKnuthElementsForBorderPaddingEnd(List returnList) {
  540. //Border and Padding (after)
  541. /*
  542. * If the returnlist is a BlockKnuthSequence, the border and padding should be added
  543. * to the last paragraph inside it, but it is too late to do that now.
  544. * At least, avoid adding it to the bpd sequence.
  545. */
  546. if (returnList instanceof BlockKnuthSequence) {
  547. return;
  548. }
  549. CommonBorderPaddingBackground borderAndPadding
  550. = ((InlineLevel)fobj).getCommonBorderPaddingBackground();
  551. if (borderAndPadding != null) {
  552. int ipEnd = borderAndPadding.getBorderEndWidth(false)
  553. + borderAndPadding.getPaddingEnd(false, this);
  554. if (ipEnd > 0) {
  555. returnList.add(new KnuthBox(ipEnd, getAuxiliaryPosition(), true));
  556. }
  557. }
  558. }
  559. /** @return an auxiliary {@link Position} instance used for things like spaces. */
  560. protected Position getAuxiliaryPosition() {
  561. return new NonLeafPosition(this, null);
  562. }
  563. }