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.

PageBreaker.java 23KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  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;
  19. import java.util.LinkedList;
  20. import java.util.List;
  21. import java.util.ListIterator;
  22. import org.apache.fop.area.Block;
  23. import org.apache.fop.area.Footnote;
  24. import org.apache.fop.area.PageViewport;
  25. import org.apache.fop.fo.Constants;
  26. import org.apache.fop.fo.FObj;
  27. import org.apache.fop.fo.pagination.PageSequence;
  28. import org.apache.fop.fo.pagination.Region;
  29. import org.apache.fop.fo.pagination.RegionBody;
  30. import org.apache.fop.fo.pagination.StaticContent;
  31. import org.apache.fop.layoutmgr.PageBreakingAlgorithm.PageBreakingLayoutListener;
  32. import org.apache.fop.traits.MinOptMax;
  33. /**
  34. * Handles the breaking of pages in an fo:flow
  35. */
  36. public class PageBreaker extends AbstractBreaker {
  37. private PageSequenceLayoutManager pslm;
  38. private boolean firstPart = true;
  39. private boolean pageBreakHandled;
  40. private boolean needColumnBalancing;
  41. private PageProvider pageProvider;
  42. private Block separatorArea;
  43. /**
  44. * The FlowLayoutManager object, which processes
  45. * the single fo:flow of the fo:page-sequence
  46. */
  47. private FlowLayoutManager childFLM = null;
  48. private StaticContentLayoutManager footnoteSeparatorLM = null;
  49. public PageBreaker(PageSequenceLayoutManager pslm) {
  50. this.pslm = pslm;
  51. this.pageProvider = pslm.getPageProvider();
  52. this.childFLM = pslm.getLayoutManagerMaker().makeFlowLayoutManager(
  53. pslm, pslm.getPageSequence().getMainFlow());
  54. }
  55. /** {@inheritDoc} */
  56. protected void updateLayoutContext(LayoutContext context) {
  57. int flowIPD = pslm.getCurrentPV().getCurrentSpan().getColumnWidth();
  58. context.setRefIPD(flowIPD);
  59. }
  60. /** {@inheritDoc} */
  61. protected LayoutManager getTopLevelLM() {
  62. return pslm;
  63. }
  64. /** {@inheritDoc} */
  65. protected PageProvider getPageProvider() {
  66. return pslm.getPageProvider();
  67. }
  68. /** {@inheritDoc} */
  69. protected PageBreakingLayoutListener createLayoutListener() {
  70. return new PageBreakingLayoutListener() {
  71. public void notifyOverflow(int part, int amount, FObj obj) {
  72. Page p = pageProvider.getPage(
  73. false, part, PageProvider.RELTO_CURRENT_ELEMENT_LIST);
  74. RegionBody body = (RegionBody)p.getSimplePageMaster().getRegion(
  75. Region.FO_REGION_BODY);
  76. BlockLevelEventProducer eventProducer = BlockLevelEventProducer.Factory.create(
  77. body.getUserAgent().getEventBroadcaster());
  78. boolean canRecover = (body.getOverflow() != Constants.EN_ERROR_IF_OVERFLOW);
  79. boolean needClip = (body.getOverflow() == Constants.EN_HIDDEN
  80. || body.getOverflow() == Constants.EN_ERROR_IF_OVERFLOW);
  81. eventProducer.regionOverflow(this, body.getName(),
  82. p.getPageViewport().getPageNumberString(),
  83. amount, needClip, canRecover,
  84. body.getLocator());
  85. }
  86. };
  87. }
  88. /** {@inheritDoc} */
  89. protected int handleSpanChange(LayoutContext childLC, int nextSequenceStartsOn) {
  90. needColumnBalancing = false;
  91. if (childLC.getNextSpan() != Constants.NOT_SET) {
  92. //Next block list will have a different span.
  93. nextSequenceStartsOn = childLC.getNextSpan();
  94. needColumnBalancing = (childLC.getNextSpan() == Constants.EN_ALL);
  95. }
  96. if (needColumnBalancing) {
  97. AbstractBreaker.log.debug(
  98. "Column balancing necessary for the next element list!!!");
  99. }
  100. return nextSequenceStartsOn;
  101. }
  102. /** {@inheritDoc} */
  103. protected int getNextBlockList(LayoutContext childLC,
  104. int nextSequenceStartsOn) {
  105. if (!firstPart) {
  106. // if this is the first page that will be created by
  107. // the current BlockSequence, it could have a break
  108. // condition that must be satisfied;
  109. // otherwise, we may simply need a new page
  110. handleBreakTrait(nextSequenceStartsOn);
  111. }
  112. firstPart = false;
  113. pageBreakHandled = true;
  114. pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(),
  115. pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
  116. return super.getNextBlockList(childLC, nextSequenceStartsOn);
  117. }
  118. /** {@inheritDoc} */
  119. protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) {
  120. LinkedList contentList = null;
  121. while (!childFLM.isFinished() && contentList == null) {
  122. contentList = childFLM.getNextKnuthElements(context, alignment);
  123. }
  124. // scan contentList, searching for footnotes
  125. boolean bFootnotesPresent = false;
  126. if (contentList != null) {
  127. ListIterator contentListIterator = contentList.listIterator();
  128. while (contentListIterator.hasNext()) {
  129. ListElement element = (ListElement) contentListIterator.next();
  130. if (element instanceof KnuthBlockBox
  131. && ((KnuthBlockBox) element).hasAnchors()) {
  132. // element represents a line with footnote citations
  133. bFootnotesPresent = true;
  134. LayoutContext footnoteContext = new LayoutContext(context);
  135. footnoteContext.setStackLimitBP(context.getStackLimitBP());
  136. footnoteContext.setRefIPD(pslm.getCurrentPV()
  137. .getRegionReference(Constants.FO_REGION_BODY).getIPD());
  138. LinkedList footnoteBodyLMs = ((KnuthBlockBox) element).getFootnoteBodyLMs();
  139. ListIterator footnoteBodyIterator = footnoteBodyLMs.listIterator();
  140. // store the lists of elements representing the footnote bodies
  141. // in the box representing the line containing their references
  142. while (footnoteBodyIterator.hasNext()) {
  143. FootnoteBodyLayoutManager fblm
  144. = (FootnoteBodyLayoutManager) footnoteBodyIterator.next();
  145. fblm.setParent(childFLM);
  146. fblm.initialize();
  147. ((KnuthBlockBox) element).addElementList(
  148. fblm.getNextKnuthElements(footnoteContext, alignment));
  149. }
  150. }
  151. }
  152. }
  153. if (bFootnotesPresent) {
  154. // handle the footnote separator
  155. StaticContent footnoteSeparator;
  156. footnoteSeparator = pslm.getPageSequence().getStaticContent("xsl-footnote-separator");
  157. if (footnoteSeparator != null) {
  158. // the footnote separator can contain page-dependent content such as
  159. // page numbers or retrieve markers, so its areas cannot simply be
  160. // obtained now and repeated in each page;
  161. // we need to know in advance the separator bpd: the actual separator
  162. // could be different from page to page, but its bpd would likely be
  163. // always the same
  164. // create a Block area that will contain the separator areas
  165. separatorArea = new Block();
  166. separatorArea.setIPD(pslm.getCurrentPV()
  167. .getRegionReference(Constants.FO_REGION_BODY).getIPD());
  168. // create a StaticContentLM for the footnote separator
  169. footnoteSeparatorLM = (StaticContentLayoutManager)
  170. pslm.getLayoutManagerMaker().makeStaticContentLayoutManager(
  171. pslm, footnoteSeparator, separatorArea);
  172. footnoteSeparatorLM.doLayout();
  173. footnoteSeparatorLength = new MinOptMax(separatorArea.getBPD());
  174. }
  175. }
  176. return contentList;
  177. }
  178. /**
  179. * @return current display alignment
  180. */
  181. protected int getCurrentDisplayAlign() {
  182. return pslm.getCurrentPage().getSimplePageMaster().getRegion(
  183. Constants.FO_REGION_BODY).getDisplayAlign();
  184. }
  185. /**
  186. * @return whether or not this flow has more page break opportunities
  187. */
  188. protected boolean hasMoreContent() {
  189. return !childFLM.isFinished();
  190. }
  191. /**
  192. * Adds an area to the flow layout manager
  193. * @param posIter the position iterator
  194. * @param context the layout context
  195. */
  196. protected void addAreas(PositionIterator posIter, LayoutContext context) {
  197. if (footnoteSeparatorLM != null) {
  198. StaticContent footnoteSeparator = pslm.getPageSequence().getStaticContent(
  199. "xsl-footnote-separator");
  200. // create a Block area that will contain the separator areas
  201. separatorArea = new Block();
  202. separatorArea.setIPD(
  203. pslm.getCurrentPV().getRegionReference(Constants.FO_REGION_BODY).getIPD());
  204. // create a StaticContentLM for the footnote separator
  205. footnoteSeparatorLM = (StaticContentLayoutManager)
  206. pslm.getLayoutManagerMaker().makeStaticContentLayoutManager(
  207. pslm, footnoteSeparator, separatorArea);
  208. footnoteSeparatorLM.doLayout();
  209. }
  210. childFLM.addAreas(posIter, context);
  211. }
  212. /**
  213. * Performs phase 3 operation
  214. *
  215. * @param alg page breaking algorithm
  216. * @param partCount part count
  217. * @param originalList the block sequence original list
  218. * @param effectiveList the block sequence effective list
  219. */
  220. protected void doPhase3(PageBreakingAlgorithm alg, int partCount,
  221. BlockSequence originalList, BlockSequence effectiveList) {
  222. if (needColumnBalancing) {
  223. doPhase3WithColumnBalancing(alg, partCount, originalList, effectiveList);
  224. } else {
  225. if (!hasMoreContent() && pslm.getPageSequence().hasPagePositionLast()) {
  226. //last part is reached and we have a "last page" condition
  227. doPhase3WithLastPage(alg, partCount, originalList, effectiveList);
  228. } else {
  229. //Directly add areas after finding the breaks
  230. addAreas(alg, partCount, originalList, effectiveList);
  231. }
  232. }
  233. }
  234. private void doPhase3WithLastPage(PageBreakingAlgorithm alg, int partCount,
  235. BlockSequence originalList, BlockSequence effectiveList) {
  236. int newStartPos;
  237. int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
  238. if (restartPoint > 0) {
  239. //Add definitive areas before last page
  240. addAreas(alg, restartPoint, originalList, effectiveList);
  241. //Get page break from which we restart
  242. PageBreakPosition pbp = (PageBreakPosition)
  243. alg.getPageBreaks().get(restartPoint - 1);
  244. newStartPos = pbp.getLeafPos();
  245. //Handle page break right here to avoid any side-effects
  246. if (newStartPos > 0) {
  247. handleBreakTrait(Constants.EN_PAGE);
  248. }
  249. } else {
  250. newStartPos = 0;
  251. }
  252. AbstractBreaker.log.debug("Last page handling now!!!");
  253. AbstractBreaker.log.debug("===================================================");
  254. AbstractBreaker.log.debug("Restarting at " + restartPoint
  255. + ", new start position: " + newStartPos);
  256. pageBreakHandled = true;
  257. //Update so the available BPD is reported correctly
  258. int currentPageNum = pslm.getCurrentPageNum();
  259. pageProvider.setStartOfNextElementList(currentPageNum,
  260. pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
  261. pageProvider.setLastPageIndex(currentPageNum);
  262. //Restart last page
  263. PageBreakingAlgorithm algRestart = new PageBreakingAlgorithm(
  264. getTopLevelLM(),
  265. getPageProvider(), createLayoutListener(),
  266. alg.getAlignment(), alg.getAlignmentLast(),
  267. footnoteSeparatorLength,
  268. isPartOverflowRecoveryActivated(), false, false);
  269. //alg.setConstantLineWidth(flowBPD);
  270. int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
  271. newStartPos,
  272. 1, true, BreakingAlgorithm.ALL_BREAKS);
  273. AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
  274. + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
  275. boolean replaceLastPage
  276. = iOptPageCount <= pslm.getCurrentPV().getBodyRegion().getColumnCount();
  277. if (replaceLastPage) {
  278. //Replace last page
  279. pslm.setCurrentPage(pageProvider.getPage(false, currentPageNum));
  280. //Make sure we only add the areas we haven't added already
  281. effectiveList.ignoreAtStart = newStartPos;
  282. addAreas(algRestart, iOptPageCount, originalList, effectiveList);
  283. } else {
  284. effectiveList.ignoreAtStart = newStartPos;
  285. addAreas(alg, restartPoint, partCount - restartPoint, originalList, effectiveList);
  286. //Add blank last page
  287. pageProvider.setLastPageIndex(currentPageNum + 1);
  288. pslm.setCurrentPage(pslm.makeNewPage(true, true));
  289. }
  290. AbstractBreaker.log.debug("===================================================");
  291. }
  292. private void doPhase3WithColumnBalancing(PageBreakingAlgorithm alg, int partCount,
  293. BlockSequence originalList, BlockSequence effectiveList) {
  294. AbstractBreaker.log.debug("Column balancing now!!!");
  295. AbstractBreaker.log.debug("===================================================");
  296. int newStartPos;
  297. int restartPoint = pageProvider.getStartingPartIndexForLastPage(partCount);
  298. if (restartPoint > 0) {
  299. //Add definitive areas
  300. addAreas(alg, restartPoint, originalList, effectiveList);
  301. //Get page break from which we restart
  302. PageBreakPosition pbp = (PageBreakPosition)
  303. alg.getPageBreaks().get(restartPoint - 1);
  304. newStartPos = pbp.getLeafPos();
  305. //Handle page break right here to avoid any side-effects
  306. if (newStartPos > 0) {
  307. handleBreakTrait(Constants.EN_PAGE);
  308. }
  309. } else {
  310. newStartPos = 0;
  311. }
  312. AbstractBreaker.log.debug("Restarting at " + restartPoint
  313. + ", new start position: " + newStartPos);
  314. pageBreakHandled = true;
  315. //Update so the available BPD is reported correctly
  316. pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(),
  317. pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
  318. //Restart last page
  319. PageBreakingAlgorithm algRestart = new BalancingColumnBreakingAlgorithm(
  320. getTopLevelLM(),
  321. getPageProvider(), createLayoutListener(),
  322. alignment, Constants.EN_START, footnoteSeparatorLength,
  323. isPartOverflowRecoveryActivated(),
  324. pslm.getCurrentPV().getBodyRegion().getColumnCount());
  325. //alg.setConstantLineWidth(flowBPD);
  326. int iOptPageCount = algRestart.findBreakingPoints(effectiveList,
  327. newStartPos,
  328. 1, true, BreakingAlgorithm.ALL_BREAKS);
  329. AbstractBreaker.log.debug("restart: iOptPageCount= " + iOptPageCount
  330. + " pageBreaks.size()= " + algRestart.getPageBreaks().size());
  331. if (iOptPageCount > pslm.getCurrentPV().getBodyRegion().getColumnCount()) {
  332. AbstractBreaker.log.warn(
  333. "Breaking algorithm produced more columns than are available.");
  334. /* reenable when everything works
  335. throw new IllegalStateException(
  336. "Breaking algorithm must not produce more columns than available.");
  337. */
  338. }
  339. //Make sure we only add the areas we haven't added already
  340. effectiveList.ignoreAtStart = newStartPos;
  341. addAreas(algRestart, iOptPageCount, originalList, effectiveList);
  342. AbstractBreaker.log.debug("===================================================");
  343. }
  344. protected void startPart(BlockSequence list, int breakClass) {
  345. AbstractBreaker.log.debug("startPart() breakClass=" + breakClass);
  346. if (pslm.getCurrentPage() == null) {
  347. throw new IllegalStateException("curPage must not be null");
  348. }
  349. if (!pageBreakHandled) {
  350. //firstPart is necessary because we need the first page before we start the
  351. //algorithm so we have a BPD and IPD. This may subject to change later when we
  352. //start handling more complex cases.
  353. if (!firstPart) {
  354. // if this is the first page that will be created by
  355. // the current BlockSequence, it could have a break
  356. // condition that must be satisfied;
  357. // otherwise, we may simply need a new page
  358. handleBreakTrait(breakClass);
  359. }
  360. pageProvider.setStartOfNextElementList(pslm.getCurrentPageNum(),
  361. pslm.getCurrentPV().getCurrentSpan().getCurrentFlowIndex());
  362. }
  363. pageBreakHandled = false;
  364. // add static areas and resolve any new id areas
  365. // finish page and add to area tree
  366. firstPart = false;
  367. }
  368. /** {@inheritDoc} */
  369. protected void handleEmptyContent() {
  370. pslm.getCurrentPV().getPage().fakeNonEmpty();
  371. }
  372. protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) {
  373. // add footnote areas
  374. if (pbp.footnoteFirstListIndex < pbp.footnoteLastListIndex
  375. || pbp.footnoteFirstElementIndex <= pbp.footnoteLastElementIndex) {
  376. // call addAreas() for each FootnoteBodyLM
  377. for (int i = pbp.footnoteFirstListIndex; i <= pbp.footnoteLastListIndex; i++) {
  378. LinkedList elementList = alg.getFootnoteList(i);
  379. int firstIndex = (i == pbp.footnoteFirstListIndex
  380. ? pbp.footnoteFirstElementIndex : 0);
  381. int lastIndex = (i == pbp.footnoteLastListIndex
  382. ? pbp.footnoteLastElementIndex : elementList.size() - 1);
  383. SpaceResolver.performConditionalsNotification(elementList,
  384. firstIndex, lastIndex, -1);
  385. LayoutContext childLC = new LayoutContext(0);
  386. AreaAdditionUtil.addAreas(null,
  387. new KnuthPossPosIter(elementList, firstIndex, lastIndex + 1),
  388. childLC);
  389. }
  390. // set the offset from the top margin
  391. Footnote parentArea = (Footnote) pslm.getCurrentPV().getBodyRegion().getFootnote();
  392. int topOffset = (int) pslm.getCurrentPV().getBodyRegion().getBPD() - parentArea.getBPD();
  393. if (separatorArea != null) {
  394. topOffset -= separatorArea.getBPD();
  395. }
  396. parentArea.setTop(topOffset);
  397. parentArea.setSeparator(separatorArea);
  398. }
  399. pslm.getCurrentPV().getCurrentSpan().notifyFlowsFinished();
  400. }
  401. /**
  402. * @return the current child flow layout manager
  403. */
  404. protected LayoutManager getCurrentChildLM() {
  405. return childFLM;
  406. }
  407. /** {@inheritDoc} */
  408. protected void observeElementList(List elementList) {
  409. ElementListObserver.observe(elementList, "breaker",
  410. ((PageSequence)pslm.getFObj()).getId());
  411. }
  412. /**
  413. * Depending on the kind of break condition, move to next column
  414. * or page. May need to make an empty page if next page would
  415. * not have the desired "handedness".
  416. * @param breakVal - value of break-before or break-after trait.
  417. */
  418. private void handleBreakTrait(int breakVal) {
  419. Page curPage = pslm.getCurrentPage();
  420. if (breakVal == Constants.EN_ALL) {
  421. //break due to span change in multi-column layout
  422. curPage.getPageViewport().createSpan(true);
  423. return;
  424. } else if (breakVal == Constants.EN_NONE) {
  425. curPage.getPageViewport().createSpan(false);
  426. return;
  427. } else if (breakVal == Constants.EN_COLUMN
  428. || breakVal <= 0
  429. || breakVal == Constants.EN_AUTO) {
  430. PageViewport pv = curPage.getPageViewport();
  431. //Check if previous page was spanned
  432. boolean forceNewPageWithSpan = false;
  433. RegionBody rb = (RegionBody)curPage.getSimplePageMaster().getRegion(
  434. Constants.FO_REGION_BODY);
  435. if (breakVal < 0
  436. && rb.getColumnCount() > 1
  437. && pv.getCurrentSpan().getColumnCount() == 1) {
  438. forceNewPageWithSpan = true;
  439. }
  440. if (forceNewPageWithSpan) {
  441. curPage = pslm.makeNewPage(false, false);
  442. curPage.getPageViewport().createSpan(true);
  443. } else if (pv.getCurrentSpan().hasMoreFlows()) {
  444. pv.getCurrentSpan().moveToNextFlow();
  445. } else {
  446. curPage = pslm.makeNewPage(false, false);
  447. }
  448. return;
  449. }
  450. log.debug("handling break-before after page " + pslm.getCurrentPageNum()
  451. + " breakVal=" + breakVal);
  452. if (needBlankPageBeforeNew(breakVal)) {
  453. curPage = pslm.makeNewPage(true, false);
  454. }
  455. if (needNewPage(breakVal)) {
  456. curPage = pslm.makeNewPage(false, false);
  457. }
  458. }
  459. /**
  460. * Check if a blank page is needed to accomodate
  461. * desired even or odd page number.
  462. * @param breakVal - value of break-before or break-after trait.
  463. */
  464. private boolean needBlankPageBeforeNew(int breakVal) {
  465. if (breakVal == Constants.EN_PAGE || (pslm.getCurrentPage().getPageViewport().getPage().isEmpty())) {
  466. // any page is OK or we already have an empty page
  467. return false;
  468. } else {
  469. /* IF we are on the kind of page we need, we'll need a new page. */
  470. if (pslm.getCurrentPageNum() % 2 == 0) { // even page
  471. return (breakVal == Constants.EN_EVEN_PAGE);
  472. } else { // odd page
  473. return (breakVal == Constants.EN_ODD_PAGE);
  474. }
  475. }
  476. }
  477. /**
  478. * See if need to generate a new page
  479. * @param breakVal - value of break-before or break-after trait.
  480. */
  481. private boolean needNewPage(int breakVal) {
  482. if (pslm.getCurrentPage().getPageViewport().getPage().isEmpty()) {
  483. if (breakVal == Constants.EN_PAGE) {
  484. return false;
  485. } else if (pslm.getCurrentPageNum() % 2 == 0) { // even page
  486. return (breakVal == Constants.EN_ODD_PAGE);
  487. } else { // odd page
  488. return (breakVal == Constants.EN_EVEN_PAGE);
  489. }
  490. } else {
  491. return true;
  492. }
  493. }
  494. }