1 51 package org.apache.fop.fo.pagination; 52 53 import org.apache.fop.fo.*; 55 import org.apache.fop.fo.properties.*; 56 import org.apache.fop.fo.flow.Flow; 57 import org.apache.fop.fo.flow.StaticContent; 58 import org.apache.fop.layout.AreaContainer; 59 import org.apache.fop.layout.BodyAreaContainer; 60 import org.apache.fop.layout.AreaTree; 61 import org.apache.fop.layout.Page; 62 import org.apache.fop.apps.FOPException; 63 64 import java.util.HashMap ; 66 import java.util.ArrayList ; 67 68 76 public class PageSequence extends FObj { 77 public static class Maker extends FObj.Maker { 81 public FObj make(FObj parent, PropertyList propertyList, 82 String systemId, int line, int column) 83 throws FOPException { 84 return new PageSequence(parent, propertyList, 85 systemId, line, column); 86 } 87 88 } 89 90 public static FObj.Maker maker() { 91 return new PageSequence.Maker(); 92 } 93 94 private static final int EXPLICIT = 0; 98 private static final int AUTO = 1; 99 private static final int AUTO_EVEN = 2; 100 private static final int AUTO_ODD = 3; 101 102 105 private Root root; 106 107 110 private LayoutMasterSet layoutMasterSet; 111 112 117 121 private HashMap flowMap; 122 123 private Flow flow = null; 128 129 134 private String masterName; 135 136 private int firstPageNumber = 0; 138 private PageNumberGenerator pageNumberGenerator; 139 140 141 private int pageCount = 0; 142 private int currentPageNumber; 143 144 147 private int pageNumberType; 148 149 private int forcePageCountType; 150 151 154 private SimplePageMaster currentSimplePageMaster; 155 private PageSequenceMaster pageSequenceMaster; 156 157 protected PageSequence(FObj parent, PropertyList propertyList, 158 String systemId, int line, int column) 159 throws FOPException { 160 super(parent, propertyList, systemId, line, column); 161 162 if (parent.getName().equals("fo:root")) { 163 this.root = (Root)parent; 164 } 165 else { 166 throw new FOPException("page-sequence must be child of root, not " 167 + parent.getName(), systemId, line, column); 168 } 169 170 layoutMasterSet = root.getLayoutMasterSet(); 171 172 layoutMasterSet.checkRegionNames(); 174 175 flowMap = new HashMap (); 176 177 String ipnValue = this.properties.get("initial-page-number").getString(); 178 179 if (ipnValue.equals("auto")) { 180 pageNumberType = AUTO; 181 this.firstPageNumber = 1; 182 } else if (ipnValue.equals("auto-even")) { 183 pageNumberType = AUTO_EVEN; 184 this.firstPageNumber = 2; 185 } else if (ipnValue.equals("auto-odd")) { 186 pageNumberType = AUTO_ODD; 187 this.firstPageNumber = 1; 188 } else { 189 pageNumberType = EXPLICIT; 190 try { 191 int pageStart = Integer.parseInt(ipnValue); 192 this.firstPageNumber = (pageStart > 0) ? pageStart : 1; 193 } catch (NumberFormatException nfe) { 194 throw new FOPException("The value '" + ipnValue 195 + "' is not valid for initial-page-number", systemId, line, column); 196 } 197 } 198 199 masterName = this.properties.get("master-reference").getString(); 200 201 this.pageNumberGenerator = 203 new PageNumberGenerator(this.properties.get("format").getString(), 204 this.properties.get("grouping-separator").getCharacter(), 205 this.properties.get("grouping-size").getNumber().intValue(), 206 this.properties.get("letter-value").getEnum()); 207 208 this.forcePageCountType = 209 this.properties.get("force-page-count").getEnum(); 210 211 } 215 216 public String getName() { 217 return "fo:page-sequence"; 218 } 219 220 public void addFlow(Flow flow) throws FOPException { 221 if (this.flow!=null) { 222 throw new FOPException("Only a single fo:flow permitted per fo:page-sequence", systemId, line, column); 223 } 224 if (flowMap.containsKey(flow.getFlowName())) { 225 throw new FOPException("flow-names must be unique within an fo:page-sequence", systemId, line, column); 226 } 227 this.flow = flow; 228 } 229 230 231 public void addStaticContent(StaticContent staticContent) throws FOPException { 232 if (this.flow!=null) { 233 throw new FOPException("Static content ('" 234 + staticContent.getFlowName() 235 + "') is not allowed after fo:flow", 236 systemId, line, column); 237 } 238 if (flowMap.containsKey(staticContent.getFlowName())) { 239 throw new FOPException("flow-names must be unique within an fo:page-sequence", systemId, line, column); 240 } 241 String flowName = staticContent.getFlowName(); 242 if (!this.layoutMasterSet.regionNameExists(flowName) 243 && !flowName.equals("xsl-before-float-separator") 244 && !flowName.equals("xsl-footnote-separator")) { 245 log.error("region-name '" 246 + staticContent.getFlowName() 247 + "' doesn't exist in the layout-master-set."); 248 } 249 flowMap.put(staticContent.getFlowName(), staticContent); 250 } 251 252 253 256 public void format(AreaTree areaTree) throws FOPException { 257 if (flow == null) { 258 throw new FOPException("No flow in page-sequence", systemId, line, column); 259 } 260 PageSequence previousPageSequence=this.root.getPageSequence(); 261 if( previousPageSequence!=null ) { 262 if (previousPageSequence.forcePageCountType == ForcePageCount.AUTO) { 263 if (pageNumberType == AUTO_ODD) { 264 if (previousPageSequence.currentPageNumber % 2 == 0) { 265 previousPageSequence.makePage(areaTree,true,null); 266 } 267 currentPageNumber = previousPageSequence.currentPageNumber; 268 } else if (pageNumberType == AUTO_EVEN) { 269 if (previousPageSequence.currentPageNumber % 2 == 1) { 270 previousPageSequence.makePage(areaTree,true,null); 271 } 272 currentPageNumber = previousPageSequence.currentPageNumber; 273 } else if (pageNumberType == EXPLICIT){ 274 if ((previousPageSequence.currentPageNumber % 2) 275 != (firstPageNumber % 2)) { 276 previousPageSequence.makePage(areaTree,true,null); 277 } 278 currentPageNumber = firstPageNumber; 279 } else { 280 currentPageNumber = previousPageSequence.currentPageNumber; 281 } 282 } else { 283 currentPageNumber = previousPageSequence.currentPageNumber; 284 if (pageNumberType == AUTO_ODD) { 285 if (currentPageNumber % 2 == 0) { 286 currentPageNumber++; 287 } 288 } else if (pageNumberType == AUTO_EVEN) { 289 if (currentPageNumber % 2 == 1) { 290 currentPageNumber++; 291 } 292 } else if (pageNumberType == EXPLICIT){ 293 currentPageNumber = firstPageNumber; 294 } 295 } 296 } else { 297 currentPageNumber = firstPageNumber; 298 } 299 previousPageSequence = null; 300 this.root.setPageSequence(this); 301 this.currentSimplePageMaster = 302 this.layoutMasterSet.getSimplePageMaster(masterName); 303 if (this.currentSimplePageMaster==null) { 304 this.pageSequenceMaster = 305 this.layoutMasterSet.getPageSequenceMaster(masterName); 306 if (this.pageSequenceMaster==null) { 307 throw new FOPException("master-reference '" + masterName 308 + "' for fo:page-sequence matches no simple-page-master or page-sequence-master", systemId, line, column); 309 } 310 pageSequenceMaster.reset(); 311 } else { 312 Region region = currentSimplePageMaster 313 .getRegion(RegionBody.REGION_CLASS); 314 if (!flow.getFlowName().equals(region.getRegionName())) { 315 throw new FOPException("Flow '" + flow.getFlowName() 316 + "' does not map to the region-body in page-master '" 317 + currentSimplePageMaster.getMasterName() + "'", systemId, line, column); 318 } 319 } 320 321 int status = Status.OK; 323 Page currentPage = null; 324 do { 325 boolean isBlankPage = false; 326 327 if (status == Status.FORCE_PAGE_BREAK_EVEN) { 330 if ((currentPageNumber % 2) == 1) { 331 isBlankPage = true; 332 } 333 } else if (status == Status.FORCE_PAGE_BREAK_ODD) { 334 if ((currentPageNumber % 2) == 0) { 335 isBlankPage = true; 336 } 337 } 338 currentPage = makePage(areaTree, isBlankPage, currentPage); 339 status = flow.getStatus(); 340 } while (Status.isIncomplete(status)); 341 342 if (this.forcePageCountType == ForcePageCount.EVEN) { 345 if (this.pageCount % 2 != 0) { 346 makePage(areaTree,true, null); 347 } 348 } else if (this.forcePageCountType == ForcePageCount.ODD) { 349 if (this.pageCount % 2 != 1) { 350 makePage(areaTree,true, null); 351 } 352 } else if (this.forcePageCountType == ForcePageCount.END_ON_EVEN) { 353 if (this.currentPageNumber % 2 == 0) { 354 makePage(areaTree,true, null); 355 } 356 } else if (this.forcePageCountType == ForcePageCount.END_ON_ODD) { 357 if (this.currentPageNumber % 2 == 1) { 358 makePage(areaTree,true, null); 359 } 360 } 361 } 362 363 369 private Page makePage(AreaTree areaTree, 370 boolean isBlankPage, 371 Page currentPage) 372 throws FOPException { 373 if (this.pageSequenceMaster!=null) { 374 this.currentSimplePageMaster = this.pageSequenceMaster 375 .getNextSimplePageMaster(((this.currentPageNumber % 2)==1), 376 isBlankPage); 377 Region region = currentSimplePageMaster 378 .getRegion(RegionBody.REGION_CLASS); 379 if (!flow.getFlowName().equals(region.getRegionName())) { 380 throw new FOPException("Flow '" + flow.getFlowName() 381 + "' does not map to the region-body in page-master '" 382 + currentSimplePageMaster.getMasterName() + "'", systemId, line, column); 383 } 384 } 385 Page newPage = this.currentSimplePageMaster.getPageMaster() 386 .makePage(areaTree); 387 newPage.setNumber(this.currentPageNumber); 388 String formattedPageNumber = 389 pageNumberGenerator.makeFormattedPageNumber(this.currentPageNumber); 390 newPage.setFormattedNumber(formattedPageNumber); 391 newPage.setPageSequence(this); 392 if (!isBlankPage) { 393 log.info("[" + currentPageNumber + "]"); 394 BodyAreaContainer bodyArea = newPage.getBody(); 395 bodyArea.setIDReferences(areaTree.getIDReferences()); 396 if (currentPage != null) { 397 ArrayList foots = currentPage.getPendingFootnotes(); 398 newPage.setPendingFootnotes(foots); 399 } 400 flow.layout(bodyArea); 401 } else { 402 log.info("[" + currentPageNumber + "] (blank)"); 403 if (currentPage != null) { 404 ArrayList foots = currentPage.getPendingFootnotes(); 405 if (foots != null) { 406 BodyAreaContainer bodyArea = newPage.getBody(); 407 bodyArea.setIDReferences(areaTree.getIDReferences()); 408 newPage.setPendingFootnotes(foots); 409 } 410 } 411 } 412 formatStaticContent(areaTree, newPage); 415 areaTree.addPage(newPage); 416 this.currentPageNumber++; 417 this.pageCount++; 418 return newPage; 419 } 420 421 424 private void formatStaticContent(AreaTree areaTree, Page page) 425 throws FOPException { 426 SimplePageMaster simpleMaster = currentSimplePageMaster; 427 428 if (simpleMaster.getRegion(RegionBefore.REGION_CLASS) != null 429 && (page.getBefore() != null)) { 430 StaticContent staticFlow = 431 (StaticContent)flowMap.get(simpleMaster.getRegion(RegionBefore.REGION_CLASS).getRegionName()); 432 if (staticFlow != null) { 433 AreaContainer beforeArea = page.getBefore(); 434 beforeArea.setIDReferences(areaTree.getIDReferences()); 435 layoutStaticContent(staticFlow, 436 simpleMaster.getRegion(RegionBefore.REGION_CLASS), 437 beforeArea); 438 } 439 } 440 441 if (simpleMaster.getRegion(RegionAfter.REGION_CLASS) != null 442 && (page.getAfter() != null)) { 443 StaticContent staticFlow = 444 (StaticContent)flowMap.get(simpleMaster.getRegion(RegionAfter.REGION_CLASS).getRegionName()); 445 if (staticFlow != null) { 446 AreaContainer afterArea = page.getAfter(); 447 afterArea.setIDReferences(areaTree.getIDReferences()); 448 layoutStaticContent(staticFlow, 449 simpleMaster.getRegion(RegionAfter.REGION_CLASS), 450 afterArea); 451 } 452 } 453 454 if (simpleMaster.getRegion(RegionStart.REGION_CLASS) != null 455 && (page.getStart() != null)) { 456 StaticContent staticFlow = 457 (StaticContent)flowMap.get(simpleMaster.getRegion(RegionStart.REGION_CLASS).getRegionName()); 458 if (staticFlow != null) { 459 AreaContainer startArea = page.getStart(); 460 startArea.setIDReferences(areaTree.getIDReferences()); 461 layoutStaticContent(staticFlow, 462 simpleMaster.getRegion(RegionStart.REGION_CLASS), 463 startArea); 464 } 465 } 466 467 if (simpleMaster.getRegion(RegionEnd.REGION_CLASS) != null 468 && (page.getEnd() != null)) { 469 StaticContent staticFlow = 470 (StaticContent)flowMap.get(simpleMaster.getRegion(RegionEnd.REGION_CLASS).getRegionName()); 471 if (staticFlow != null) { 472 AreaContainer endArea = page.getEnd(); 473 endArea.setIDReferences(areaTree.getIDReferences()); 474 layoutStaticContent(staticFlow, 475 simpleMaster.getRegion(RegionEnd.REGION_CLASS), 476 endArea); 477 } 478 } 479 480 } 481 482 private void layoutStaticContent(StaticContent flow, Region region, 483 AreaContainer area) throws FOPException { 484 flow.layout(area, region); 485 } 489 490 public StaticContent getStaticContent(String regionName) { 491 return (StaticContent)flowMap.get(regionName); 492 } 493 494 public int getCurrentPageNumber() { 495 return currentPageNumber; 496 } 497 498 public int getPageCount() { 499 return pageCount; 500 } 501 502 } 503 | Popular Tags |