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

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