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.

PageSequence.java 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684
  1. /*
  2. * $Id$
  3. * Copyright (C) 2001 The Apache Software Foundation. All rights reserved.
  4. * For details on use and redistribution please refer to the
  5. * LICENSE file included with these sources.
  6. */
  7. /*
  8. Modified by Mark Lillywhite mark-fop@inomial.com. Does not add
  9. itself to the root any more. Does not hang onto currentPage
  10. pointer, which caused GC issues.
  11. */
  12. package org.apache.fop.fo.pagination;
  13. // FOP
  14. import org.apache.fop.fo.*;
  15. import org.apache.fop.fo.properties.*;
  16. import org.apache.fop.fo.flow.Flow;
  17. import org.apache.fop.fo.flow.StaticContent;
  18. import org.apache.fop.layout.Area;
  19. import org.apache.fop.layout.AreaContainer;
  20. import org.apache.fop.layout.BodyAreaContainer;
  21. import org.apache.fop.layout.AreaTree;
  22. import org.apache.fop.layout.Page;
  23. import org.apache.fop.layout.PageMaster;
  24. import org.apache.fop.apps.FOPException;
  25. // Java
  26. import java.util.*;
  27. /**
  28. * This provides pagination of flows onto pages. Much of the
  29. * logic for paginating flows is contained in this class.
  30. * The main entry point is the format method.
  31. */
  32. public class PageSequence extends FObj {
  33. //
  34. // Factory methods
  35. //
  36. public static class Maker extends FObj.Maker {
  37. public FObj make(FObj parent,
  38. PropertyList propertyList) throws FOPException {
  39. return new PageSequence(parent, propertyList);
  40. }
  41. }
  42. public static FObj.Maker maker() {
  43. return new PageSequence.Maker();
  44. }
  45. //
  46. // intial-page-number types
  47. //
  48. private static final int EXPLICIT = 0;
  49. private static final int AUTO = 1;
  50. private static final int AUTO_EVEN = 2;
  51. private static final int AUTO_ODD = 3;
  52. //
  53. // associations
  54. //
  55. /**
  56. * The parent root object
  57. */
  58. private Root root;
  59. /**
  60. * the set of layout masters (provided by the root object)
  61. */
  62. private LayoutMasterSet layoutMasterSet;
  63. // There doesn't seem to be anything in the spec requiring flows
  64. // to be in the order given, only that they map to the regions
  65. // defined in the page sequence, so all we need is this one hashtable
  66. // the set of flows includes StaticContent flows also
  67. /**
  68. * Map of flows to their flow name (flow-name, Flow)
  69. */
  70. private Hashtable _flowMap;
  71. /**
  72. * the "master-name" attribute
  73. */
  74. private String masterName;
  75. // according to communication from Paul Grosso (XSL-List,
  76. // 001228, Number 406), confusion in spec section 6.4.5 about
  77. // multiplicity of fo:flow in XSL 1.0 is cleared up - one (1)
  78. // fo:flow per fo:page-sequence only.
  79. private boolean isFlowSet = false;
  80. //
  81. // state attributes used during layout
  82. //
  83. private Page currentPage;
  84. // page number and related formatting variables
  85. private String ipnValue;
  86. private int currentPageNumber = 0;
  87. private PageNumberGenerator pageNumberGenerator;
  88. private int forcePageCount = 0;
  89. private int pageCount = 0;
  90. private boolean isForcing = false;
  91. /**
  92. * specifies page numbering type (auto|auto-even|auto-odd|explicit)
  93. */
  94. private int pageNumberType;
  95. /**
  96. * used to determine whether to calculate auto, auto-even, auto-odd
  97. */
  98. private boolean thisIsFirstPage;
  99. /**
  100. * the current subsequence while formatting a given page sequence
  101. */
  102. private SubSequenceSpecifier currentSubsequence;
  103. /**
  104. * the current index in the subsequence list
  105. */
  106. private int currentSubsequenceNumber =
  107. -1; // starting case is -1 so that first getNext increments to 0
  108. /**
  109. * the name of the current page master
  110. */
  111. private String currentPageMasterName;
  112. protected PageSequence(FObj parent,
  113. PropertyList propertyList) throws FOPException {
  114. super(parent, propertyList);
  115. this.name = "fo:page-sequence";
  116. if (parent.getName().equals("fo:root")) {
  117. this.root = (Root)parent;
  118. // this.root.addPageSequence(this);
  119. }
  120. else {
  121. throw new FOPException("page-sequence must be child of root, not "
  122. + parent.getName());
  123. }
  124. layoutMasterSet = root.getLayoutMasterSet();
  125. // best time to run some checks on LayoutMasterSet
  126. layoutMasterSet.checkRegionNames();
  127. _flowMap = new Hashtable();
  128. thisIsFirstPage =
  129. true; // we are now on the first page of the page sequence
  130. ipnValue = this.properties.get("initial-page-number").getString();
  131. if (ipnValue.equals("auto")) {
  132. pageNumberType = AUTO;
  133. } else if (ipnValue.equals("auto-even")) {
  134. pageNumberType = AUTO_EVEN;
  135. } else if (ipnValue.equals("auto-odd")) {
  136. pageNumberType = AUTO_ODD;
  137. } else {
  138. pageNumberType = EXPLICIT;
  139. try {
  140. int pageStart = new Integer(ipnValue).intValue();
  141. this.currentPageNumber = (pageStart > 0) ? pageStart - 1 : 0;
  142. } catch (NumberFormatException nfe) {
  143. throw new FOPException("\"" + ipnValue
  144. + "\" is not a valid value for initial-page-number");
  145. }
  146. }
  147. masterName = this.properties.get("master-name").getString();
  148. // get the 'format' properties
  149. this.pageNumberGenerator =
  150. new PageNumberGenerator(this.properties.get("format").getString(),
  151. this.properties.get("grouping-separator").getCharacter(),
  152. this.properties.get("grouping-size").getNumber().intValue(),
  153. this.properties.get("letter-value").getEnum());
  154. this.forcePageCount =
  155. this.properties.get("force-page-count").getEnum();
  156. // this.properties.get("country");
  157. // this.properties.get("language");
  158. // this.properties.get("id");
  159. }
  160. public void addFlow(Flow flow) throws FOPException {
  161. if (_flowMap.containsKey(flow.getFlowName())) {
  162. throw new FOPException("flow-names must be unique within an fo:page-sequence");
  163. }
  164. if (!this.layoutMasterSet.regionNameExists(flow.getFlowName())) {
  165. log.error("region-name '"
  166. + flow.getFlowName()
  167. + "' doesn't exist in the layout-master-set.");
  168. }
  169. _flowMap.put(flow.getFlowName(), flow);
  170. setIsFlowSet(true);
  171. }
  172. /**
  173. * Runs the formatting of this page sequence into the given area tree
  174. */
  175. public void format(AreaTree areaTree) throws FOPException {
  176. Status status = new Status(Status.OK);
  177. this.layoutMasterSet.resetPageMasters();
  178. int firstAvailPageNumber = 0;
  179. do {
  180. // makePage() moved to after the page-number computations,
  181. // but store the page-number at this point for that method,
  182. // since we want the 'current' current page-number...
  183. firstAvailPageNumber = this.root.getRunningPageNumberCounter();
  184. boolean tempIsFirstPage = false;
  185. if (thisIsFirstPage) {
  186. tempIsFirstPage = thisIsFirstPage;
  187. if (pageNumberType == AUTO) {
  188. this.currentPageNumber =
  189. this.root.getRunningPageNumberCounter();
  190. } else if (pageNumberType == AUTO_ODD) {
  191. this.currentPageNumber =
  192. this.root.getRunningPageNumberCounter();
  193. if (this.currentPageNumber % 2 == 1) {
  194. this.currentPageNumber++;
  195. }
  196. } else if (pageNumberType == AUTO_EVEN) {
  197. this.currentPageNumber =
  198. this.root.getRunningPageNumberCounter();
  199. if (this.currentPageNumber % 2 == 0) {
  200. this.currentPageNumber++;
  201. }
  202. }
  203. thisIsFirstPage = false;
  204. }
  205. this.currentPageNumber++;
  206. // deliberately moved down here so page-number calculations
  207. // are complete;
  208. // compute flag for 'blank-or-not-blank'
  209. boolean isEmptyPage = false;
  210. if ((status.getCode() == Status.FORCE_PAGE_BREAK_EVEN)
  211. && ((currentPageNumber % 2) == 1)) {
  212. isEmptyPage = true;
  213. } else if ((status.getCode() == Status.FORCE_PAGE_BREAK_ODD)
  214. && ((currentPageNumber % 2) == 0)) {
  215. isEmptyPage = true;
  216. } else {
  217. isEmptyPage = false;
  218. }
  219. currentPage = makePage(areaTree, firstAvailPageNumber,
  220. tempIsFirstPage, isEmptyPage);
  221. currentPage.setNumber(this.currentPageNumber);
  222. String formattedPageNumber =
  223. pageNumberGenerator.makeFormattedPageNumber(this.currentPageNumber);
  224. currentPage.setFormattedNumber(formattedPageNumber);
  225. this.root.setRunningPageNumberCounter(this.currentPageNumber);
  226. log.info("[" + currentPageNumber + "]");
  227. if ((status.getCode() == Status.FORCE_PAGE_BREAK_EVEN)
  228. && ((currentPageNumber % 2) == 1)) {}
  229. else if ((status.getCode() == Status.FORCE_PAGE_BREAK_ODD)
  230. && ((currentPageNumber % 2) == 0)) {}
  231. else {
  232. BodyAreaContainer bodyArea = currentPage.getBody();
  233. bodyArea.setIDReferences(areaTree.getIDReferences());
  234. Flow flow = getCurrentFlow(RegionBody.REGION_CLASS);
  235. if (null == flow) {
  236. log.error("No flow found for region-body "
  237. + "in page-master '"
  238. + currentPageMasterName + "'");
  239. break;
  240. } else {
  241. status = flow.layout(bodyArea);
  242. }
  243. }
  244. // because of markers, do after fo:flow (likely also
  245. // justifiable because of spec)
  246. currentPage.setPageSequence(this);
  247. formatStaticContent(areaTree);
  248. //log.info("]");
  249. areaTree.addPage(currentPage);
  250. this.pageCount++; // used for 'force-page-count' calculations
  251. }
  252. while (flowsAreIncomplete());
  253. // handle the 'force-page-count'
  254. forcePage(areaTree, firstAvailPageNumber);
  255. currentPage = null;
  256. }
  257. /**
  258. * Creates a new page area for the given parameters
  259. * @param areaTree the area tree the page should be contained in
  260. * @param firstAvailPageNumber the page number for this page
  261. * @param isFirstPage true when this is the first page in the sequence
  262. * @param isEmptyPage true if this page will be empty (e.g. forced even or odd break)
  263. * @return a Page layout object based on the page master selected from the params
  264. */
  265. private Page makePage(AreaTree areaTree, int firstAvailPageNumber,
  266. boolean isFirstPage,
  267. boolean isEmptyPage) throws FOPException {
  268. // layout this page sequence
  269. // while there is still stuff in the flow, ask the
  270. // layoutMasterSet for a new page
  271. // page number is 0-indexed
  272. PageMaster pageMaster = getNextPageMaster(masterName,
  273. firstAvailPageNumber,
  274. isFirstPage, isEmptyPage);
  275. // a legal alternative is to use the last sub-sequence
  276. // specification which should be handled in getNextSubsequence. That's not done here.
  277. if (pageMaster == null) {
  278. throw new FOPException("page masters exhausted. Cannot recover.");
  279. }
  280. Page p = pageMaster.makePage(areaTree);
  281. if (currentPage != null) {
  282. Vector foots = currentPage.getPendingFootnotes();
  283. p.setPendingFootnotes(foots);
  284. }
  285. return p;
  286. }
  287. /**
  288. * Formats the static content of the current page
  289. */
  290. private void formatStaticContent(AreaTree areaTree) throws FOPException {
  291. SimplePageMaster simpleMaster = getCurrentSimplePageMaster();
  292. if (simpleMaster.getRegion(RegionBefore.REGION_CLASS) != null
  293. && (currentPage.getBefore() != null)) {
  294. Flow staticFlow =
  295. (Flow)_flowMap.get(simpleMaster.getRegion(RegionBefore.REGION_CLASS).getRegionName());
  296. if (staticFlow != null) {
  297. AreaContainer beforeArea = currentPage.getBefore();
  298. beforeArea.setIDReferences(areaTree.getIDReferences());
  299. layoutStaticContent(staticFlow,
  300. simpleMaster.getRegion(RegionBefore.REGION_CLASS),
  301. beforeArea);
  302. }
  303. }
  304. if (simpleMaster.getRegion(RegionAfter.REGION_CLASS) != null
  305. && (currentPage.getAfter() != null)) {
  306. Flow staticFlow =
  307. (Flow)_flowMap.get(simpleMaster.getRegion(RegionAfter.REGION_CLASS).getRegionName());
  308. if (staticFlow != null) {
  309. AreaContainer afterArea = currentPage.getAfter();
  310. afterArea.setIDReferences(areaTree.getIDReferences());
  311. layoutStaticContent(staticFlow,
  312. simpleMaster.getRegion(RegionAfter.REGION_CLASS),
  313. afterArea);
  314. }
  315. }
  316. if (simpleMaster.getRegion(RegionStart.REGION_CLASS) != null
  317. && (currentPage.getStart() != null)) {
  318. Flow staticFlow =
  319. (Flow)_flowMap.get(simpleMaster.getRegion(RegionStart.REGION_CLASS).getRegionName());
  320. if (staticFlow != null) {
  321. AreaContainer startArea = currentPage.getStart();
  322. startArea.setIDReferences(areaTree.getIDReferences());
  323. layoutStaticContent(staticFlow,
  324. simpleMaster.getRegion(RegionStart.REGION_CLASS),
  325. startArea);
  326. }
  327. }
  328. if (simpleMaster.getRegion(RegionEnd.REGION_CLASS) != null
  329. && (currentPage.getEnd() != null)) {
  330. Flow staticFlow =
  331. (Flow)_flowMap.get(simpleMaster.getRegion(RegionEnd.REGION_CLASS).getRegionName());
  332. if (staticFlow != null) {
  333. AreaContainer endArea = currentPage.getEnd();
  334. endArea.setIDReferences(areaTree.getIDReferences());
  335. layoutStaticContent(staticFlow,
  336. simpleMaster.getRegion(RegionEnd.REGION_CLASS),
  337. endArea);
  338. }
  339. }
  340. }
  341. private void layoutStaticContent(Flow flow, Region region,
  342. AreaContainer area) throws FOPException {
  343. if (flow instanceof StaticContent) {
  344. AreaContainer beforeArea = currentPage.getBefore();
  345. ((StaticContent)flow).layout(area, region);
  346. } else {
  347. log.error("" + region.getName()
  348. + " only supports static-content flows currently. Cannot use flow named '"
  349. + flow.getFlowName() + "'");
  350. }
  351. }
  352. /**
  353. * Returns the next SubSequenceSpecifier for the given page sequence master. The result
  354. * is bassed on the current state of this page sequence.
  355. */
  356. // refactored from PageSequenceMaster
  357. private SubSequenceSpecifier getNextSubsequence(PageSequenceMaster master) {
  358. if (master.getSubSequenceSpecifierCount()
  359. > currentSubsequenceNumber + 1) {
  360. currentSubsequence =
  361. master.getSubSequenceSpecifier(currentSubsequenceNumber + 1);
  362. currentSubsequenceNumber++;
  363. return currentSubsequence;
  364. } else {
  365. return null;
  366. }
  367. }
  368. /**
  369. * Returns the next simple page master for the given sequence master, page number and
  370. * other state information
  371. */
  372. private SimplePageMaster getNextSimplePageMaster(PageSequenceMaster sequenceMaster,
  373. int currentPageNumber, boolean thisIsFirstPage,
  374. boolean isEmptyPage) {
  375. // handle forcing
  376. if (isForcing) {
  377. String nextPageMaster = getNextPageMasterName(sequenceMaster,
  378. currentPageNumber, false, true);
  379. return this.layoutMasterSet.getSimplePageMaster(nextPageMaster);
  380. }
  381. String nextPageMaster = getNextPageMasterName(sequenceMaster,
  382. currentPageNumber, thisIsFirstPage, isEmptyPage);
  383. return this.layoutMasterSet.getSimplePageMaster(nextPageMaster);
  384. }
  385. private String getNextPageMasterName(PageSequenceMaster sequenceMaster,
  386. int currentPageNumber,
  387. boolean thisIsFirstPage,
  388. boolean isEmptyPage) {
  389. if (null == currentSubsequence) {
  390. currentSubsequence = getNextSubsequence(sequenceMaster);
  391. }
  392. String nextPageMaster =
  393. currentSubsequence.getNextPageMaster(currentPageNumber,
  394. thisIsFirstPage,
  395. isEmptyPage);
  396. if (null == nextPageMaster
  397. || isFlowForMasterNameDone(currentPageMasterName)) {
  398. SubSequenceSpecifier nextSubsequence =
  399. getNextSubsequence(sequenceMaster);
  400. if (nextSubsequence == null) {
  401. log.error("Page subsequences exhausted. Using previous subsequence.");
  402. thisIsFirstPage =
  403. true; // this becomes the first page in the new (old really) page master
  404. currentSubsequence.reset();
  405. // we leave currentSubsequence alone
  406. }
  407. else {
  408. currentSubsequence = nextSubsequence;
  409. }
  410. nextPageMaster =
  411. currentSubsequence.getNextPageMaster(currentPageNumber,
  412. thisIsFirstPage,
  413. isEmptyPage);
  414. }
  415. currentPageMasterName = nextPageMaster;
  416. return nextPageMaster;
  417. }
  418. private SimplePageMaster getCurrentSimplePageMaster() {
  419. return this.layoutMasterSet.getSimplePageMaster(currentPageMasterName);
  420. }
  421. private String getCurrentPageMasterName() {
  422. return currentPageMasterName;
  423. }
  424. // refactored from LayoutMasterSet
  425. private PageMaster getNextPageMaster(String pageSequenceName,
  426. int currentPageNumber,
  427. boolean thisIsFirstPage,
  428. boolean isEmptyPage) throws FOPException {
  429. PageMaster pageMaster = null;
  430. // see if there is a page master sequence for this master name
  431. PageSequenceMaster sequenceMaster =
  432. this.layoutMasterSet.getPageSequenceMaster(pageSequenceName);
  433. if (sequenceMaster != null) {
  434. pageMaster = getNextSimplePageMaster(sequenceMaster,
  435. currentPageNumber,
  436. thisIsFirstPage,
  437. isEmptyPage).getPageMaster();
  438. } else { // otherwise see if there's a simple master by the given name
  439. SimplePageMaster simpleMaster =
  440. this.layoutMasterSet.getSimplePageMaster(pageSequenceName);
  441. if (simpleMaster == null) {
  442. throw new FOPException("'master-name' for 'fo:page-sequence'"
  443. + "matches no 'simple-page-master' or 'page-sequence-master'");
  444. }
  445. currentPageMasterName = pageSequenceName;
  446. pageMaster = simpleMaster.getNextPageMaster();
  447. }
  448. return pageMaster;
  449. }
  450. /**
  451. * Returns true when there is more flow elements left to lay out.
  452. */
  453. private boolean flowsAreIncomplete() {
  454. boolean isIncomplete = false;
  455. for (Enumeration e = _flowMap.elements(); e.hasMoreElements(); ) {
  456. Flow flow = (Flow)e.nextElement();
  457. if (flow instanceof StaticContent) {
  458. continue;
  459. }
  460. Status status = flow.getStatus();
  461. isIncomplete |= status.isIncomplete();
  462. }
  463. return isIncomplete;
  464. }
  465. /**
  466. * Returns the flow that maps to the given region class for the current
  467. * page master.
  468. */
  469. private Flow getCurrentFlow(String regionClass) {
  470. Region region = getCurrentSimplePageMaster().getRegion(regionClass);
  471. if (region != null) {
  472. Flow flow = (Flow)_flowMap.get(region.getRegionName());
  473. return flow;
  474. } else {
  475. System.out.println("flow is null. regionClass = '" + regionClass
  476. + "' currentSPM = "
  477. + getCurrentSimplePageMaster());
  478. return null;
  479. }
  480. }
  481. private boolean isFlowForMasterNameDone(String masterName) {
  482. // parameter is master-name of PMR; we need to locate PM
  483. // referenced by this, and determine whether flow(s) are OK
  484. if (isForcing)
  485. return false;
  486. if (masterName != null) {
  487. SimplePageMaster spm =
  488. this.layoutMasterSet.getSimplePageMaster(masterName);
  489. Region region = spm.getRegion(RegionBody.REGION_CLASS);
  490. Flow flow = (Flow)_flowMap.get(region.getRegionName());
  491. if ((null == flow) || flow.getStatus().isIncomplete())
  492. return false;
  493. else
  494. return true;
  495. }
  496. return false;
  497. }
  498. public boolean isFlowSet() {
  499. return isFlowSet;
  500. }
  501. public void setIsFlowSet(boolean isFlowSet) {
  502. this.isFlowSet = isFlowSet;
  503. }
  504. public String getIpnValue() {
  505. return ipnValue;
  506. }
  507. public int getCurrentPageNumber() {
  508. return currentPageNumber;
  509. }
  510. private void forcePage(AreaTree areaTree, int firstAvailPageNumber) {
  511. boolean makePage = false;
  512. if (this.forcePageCount == ForcePageCount.AUTO) {
  513. PageSequence nextSequence =
  514. this.root.getSucceedingPageSequence(this);
  515. if (nextSequence != null) {
  516. if (nextSequence.getIpnValue().equals("auto")) {
  517. // do nothing special
  518. }
  519. else if (nextSequence.getIpnValue().equals("auto-odd")) {
  520. if (firstAvailPageNumber % 2 == 0) {
  521. makePage = true;
  522. }
  523. } else if (nextSequence.getIpnValue().equals("auto-even")) {
  524. if (firstAvailPageNumber % 2 != 0) {
  525. makePage = true;
  526. }
  527. } else {
  528. int nextSequenceStartPageNumber =
  529. nextSequence.getCurrentPageNumber();
  530. if ((nextSequenceStartPageNumber % 2 == 0)
  531. && (firstAvailPageNumber % 2 == 0)) {
  532. makePage = true;
  533. } else if ((nextSequenceStartPageNumber % 2 != 0)
  534. && (firstAvailPageNumber % 2 != 0)) {
  535. makePage = true;
  536. }
  537. }
  538. }
  539. } else if ((this.forcePageCount == ForcePageCount.EVEN)
  540. && (this.pageCount % 2 != 0)) {
  541. makePage = true;
  542. } else if ((this.forcePageCount == ForcePageCount.ODD)
  543. && (this.pageCount % 2 == 0)) {
  544. makePage = true;
  545. } else if ((this.forcePageCount == ForcePageCount.END_ON_EVEN)
  546. && (firstAvailPageNumber % 2 == 0)) {
  547. makePage = true;
  548. } else if ((this.forcePageCount == ForcePageCount.END_ON_ODD)
  549. && (firstAvailPageNumber % 2 != 0)) {
  550. makePage = true;
  551. } else if (this.forcePageCount == ForcePageCount.NO_FORCE) {
  552. // do nothing
  553. }
  554. if (makePage) {
  555. try {
  556. this.isForcing = true;
  557. this.currentPageNumber++;
  558. firstAvailPageNumber = this.currentPageNumber;
  559. currentPage = makePage(areaTree, firstAvailPageNumber, false,
  560. true);
  561. String formattedPageNumber =
  562. pageNumberGenerator.makeFormattedPageNumber(this.currentPageNumber);
  563. currentPage.setFormattedNumber(formattedPageNumber);
  564. currentPage.setPageSequence(this);
  565. formatStaticContent(areaTree);
  566. log.debug("[forced-" + firstAvailPageNumber + "]");
  567. areaTree.addPage(currentPage);
  568. this.root.setRunningPageNumberCounter(this.currentPageNumber);
  569. this.isForcing = false;
  570. } catch (FOPException fopex) {
  571. log.debug("'force-page-count' failure");
  572. }
  573. }
  574. }
  575. }