1 17 18 19 20 package org.apache.fop.layoutmgr; 21 22 import java.util.LinkedList ; 23 import java.util.List ; 24 import java.util.ListIterator ; 25 import java.awt.Point ; 26 import java.awt.geom.Rectangle2D ; 27 28 import org.apache.commons.logging.Log; 29 import org.apache.commons.logging.LogFactory; 30 import org.apache.fop.area.Area; 31 import org.apache.fop.area.BlockViewport; 32 import org.apache.fop.area.Block; 33 import org.apache.fop.area.Trait; 34 import org.apache.fop.fo.FONode; 35 import org.apache.fop.fo.flow.BlockContainer; 36 import org.apache.fop.fo.properties.CommonAbsolutePosition; 37 import org.apache.fop.area.CTM; 38 import org.apache.fop.datatypes.FODimension; 39 import org.apache.fop.datatypes.Length; 40 import org.apache.fop.traits.MinOptMax; 41 import org.apache.fop.traits.SpaceVal; 42 43 46 public class BlockContainerLayoutManager extends BlockStackingLayoutManager 47 implements ConditionalElementListener { 48 49 52 private static Log log = LogFactory.getLog(BlockContainerLayoutManager.class); 53 54 private BlockViewport viewportBlockArea; 55 private Block referenceArea; 56 57 private CommonAbsolutePosition abProps; 58 private FODimension relDims; 59 private CTM absoluteCTM; 60 private Length width; 61 private Length height; 62 private int vpContentBPD; 64 65 private boolean autoHeight = true; 67 68 76 private MinOptMax foBlockSpaceBefore; 78 private MinOptMax foBlockSpaceAfter; 79 80 private boolean discardBorderBefore; 81 private boolean discardBorderAfter; 82 private boolean discardPaddingBefore; 83 private boolean discardPaddingAfter; 84 private MinOptMax effSpaceBefore; 85 private MinOptMax effSpaceAfter; 86 87 88 92 public BlockContainerLayoutManager(BlockContainer node) { 93 super(node); 94 } 95 96 97 public void initialize() { 98 abProps = getBlockContainerFO().getCommonAbsolutePosition(); 99 foBlockSpaceBefore = new SpaceVal(getBlockContainerFO().getCommonMarginBlock() 100 .spaceBefore, this).getSpace(); 101 foBlockSpaceAfter = new SpaceVal(getBlockContainerFO().getCommonMarginBlock() 102 .spaceAfter, this).getSpace(); 103 startIndent = getBlockContainerFO().getCommonMarginBlock().startIndent.getValue(this); 104 endIndent = getBlockContainerFO().getCommonMarginBlock().endIndent.getValue(this); 105 106 boolean rotated = (getBlockContainerFO().getReferenceOrientation() % 180 != 0); 107 if (rotated) { 108 height = getBlockContainerFO().getInlineProgressionDimension() 109 .getOptimum(this).getLength(); 110 width = getBlockContainerFO().getBlockProgressionDimension() 111 .getOptimum(this).getLength(); 112 } else { 113 height = getBlockContainerFO().getBlockProgressionDimension() 114 .getOptimum(this).getLength(); 115 width = getBlockContainerFO().getInlineProgressionDimension() 116 .getOptimum(this).getLength(); 117 } 118 119 bpUnit = 0; if (bpUnit == 0) { 121 adjustedSpaceBefore = getBlockContainerFO().getCommonMarginBlock() 123 .spaceBefore.getSpace().getOptimum(this).getLength().getValue(this); 124 adjustedSpaceAfter = getBlockContainerFO().getCommonMarginBlock() 125 .spaceAfter.getSpace().getOptimum(this).getLength().getValue(this); 126 } else { 127 adjustedSpaceBefore = getBlockContainerFO().getCommonMarginBlock() 129 .spaceBefore.getSpace().getMinimum(this).getLength().getValue(this); 130 adjustedSpaceAfter = getBlockContainerFO().getCommonMarginBlock() 131 .spaceAfter.getSpace().getMinimum(this).getLength().getValue(this); 132 } 133 } 134 135 private void resetSpaces() { 136 this.discardBorderBefore = false; 137 this.discardBorderAfter = false; 138 this.discardPaddingBefore = false; 139 this.discardPaddingAfter = false; 140 this.effSpaceBefore = null; 141 this.effSpaceAfter = null; 142 } 143 144 145 protected int getRotatedIPD() { 146 return getBlockContainerFO().getInlineProgressionDimension() 147 .getOptimum(this).getLength().getValue(this); 148 } 149 150 private boolean needClip() { 151 int overflow = getBlockContainerFO().getOverflow(); 152 return (overflow == EN_HIDDEN || overflow == EN_ERROR_IF_OVERFLOW); 153 } 154 155 private int getSpaceBefore() { 156 return foBlockSpaceBefore.opt; 157 } 158 159 private int getBPIndents() { 160 int indents = 0; 161 167 indents += getBlockContainerFO().getCommonBorderPaddingBackground() 168 .getBPPaddingAndBorder(false, this); 169 return indents; 170 } 171 172 private boolean isAbsoluteOrFixed() { 173 return (abProps.absolutePosition == EN_ABSOLUTE) 174 || (abProps.absolutePosition == EN_FIXED); 175 } 176 177 private boolean isFixed() { 178 return (abProps.absolutePosition == EN_FIXED); 179 } 180 181 182 public int getContentAreaBPD() { 183 if (autoHeight) { 184 return -1; 185 } else { 186 return this.vpContentBPD; 187 } 188 } 189 190 191 public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { 192 resetSpaces(); 193 if (isAbsoluteOrFixed()) { 194 return getNextKnuthElementsAbsolute(context, alignment); 195 } 196 197 autoHeight = false; 198 int maxbpd = context.getStackLimit().opt; 200 int allocBPD; 201 if (height.getEnum() == EN_AUTO 202 || (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) { 203 allocBPD = maxbpd; 206 autoHeight = true; 207 } else { 208 allocBPD = height.getValue(this); allocBPD += getBPIndents(); 210 } 211 vpContentBPD = allocBPD - getBPIndents(); 212 213 referenceIPD = context.getRefIPD(); 214 if (width.getEnum() == EN_AUTO) { 215 updateContentAreaIPDwithOverconstrainedAdjust(); 216 } else { 217 int contentWidth = width.getValue(this); 218 updateContentAreaIPDwithOverconstrainedAdjust(contentWidth); 219 } 220 221 double contentRectOffsetX = 0; 222 contentRectOffsetX += getBlockContainerFO() 223 .getCommonMarginBlock().startIndent.getValue(this); 224 double contentRectOffsetY = 0; 225 contentRectOffsetY += getBlockContainerFO() 226 .getCommonBorderPaddingBackground().getBorderBeforeWidth(false); 227 contentRectOffsetY += getBlockContainerFO() 228 .getCommonBorderPaddingBackground().getPaddingBefore(false, this); 229 230 Rectangle2D rect = new Rectangle2D.Double ( 231 contentRectOffsetX, contentRectOffsetY, 232 getContentAreaIPD(), getContentAreaBPD()); 233 relDims = new FODimension(0, 0); 234 absoluteCTM = CTM.getCTMandRelDims(getBlockContainerFO().getReferenceOrientation(), 235 getBlockContainerFO().getWritingMode(), rect, relDims); 236 237 int availableIPD = referenceIPD - getIPIndents(); 238 if (rect.getWidth() > availableIPD) { 239 log.warn(FONode.decorateWithContextInfo( 240 "The extent in inline-progression-direction (width) of a block-container is" 241 + " bigger than the available space (" 242 + rect.getWidth() + "mpt > " + context.getRefIPD() + "mpt)", 243 getBlockContainerFO())); 244 } 245 246 MinOptMax stackLimit = new MinOptMax(relDims.bpd); 247 248 LinkedList returnedList = null; 249 LinkedList contentList = new LinkedList (); 250 LinkedList returnList = new LinkedList (); 251 252 if (!breakBeforeServed) { 253 try { 254 if (addKnuthElementsForBreakBefore(returnList, context)) { 255 return returnList; 256 } 257 } finally { 258 breakBeforeServed = true; 259 } 260 } 261 262 if (!firstVisibleMarkServed) { 263 addKnuthElementsForSpaceBefore(returnList, alignment); 264 } 265 266 addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); 267 firstVisibleMarkServed = true; 268 269 if (autoHeight) { 270 addPendingMarks(context); 272 273 BlockLevelLayoutManager curLM; BlockLevelLayoutManager prevLM = null; while ((curLM = (BlockLevelLayoutManager) getChildLM()) != null) { 276 LayoutContext childLC = new LayoutContext(0); 277 childLC.copyPendingMarksFrom(context); 278 childLC.setStackLimit(MinOptMax.subtract(context 280 .getStackLimit(), stackLimit)); 281 childLC.setRefIPD(relDims.ipd); 282 childLC.setWritingMode(getBlockContainerFO().getWritingMode()); 283 284 returnedList = curLM.getNextKnuthElements(childLC, alignment); 286 if (returnedList.size() == 1 287 && ((ListElement)returnedList.getFirst()).isForcedBreak()) { 288 298 contentList.addAll(returnedList); 299 300 returnedList = new LinkedList (); 303 wrapPositionElements(contentList, returnList); 304 305 return returnList; 306 } else { 307 if (prevLM != null) { 308 if (mustKeepTogether() 311 || prevLM.mustKeepWithNext() 312 || curLM.mustKeepWithPrevious()) { 313 contentList.add(new BreakElement( 316 new Position(this), KnuthElement.INFINITE, context)); 317 } else if (!((ListElement) contentList.getLast()).isGlue()) { 318 contentList.add(new BreakElement( 320 new Position(this), 0, context)); 321 } else { 322 } 326 } 327 contentList.addAll(returnedList); 328 if (returnedList.size() == 0) { 329 continue; 331 } 332 if (((ListElement)returnedList.getLast()).isForcedBreak()) { 333 if (curLM.isFinished()) { 335 setFinished(true); 338 } 339 340 returnedList = new LinkedList (); 341 wrapPositionElements(contentList, returnList); 342 343 return returnList; 344 } 345 } 346 prevLM = curLM; 347 } 348 349 returnedList = new LinkedList (); 350 wrapPositionElements(contentList, returnList); 351 352 } else { 353 MinOptMax range = new MinOptMax(relDims.ipd); 354 BlockContainerBreaker breaker = new BlockContainerBreaker(this, range); 355 breaker.doLayout(relDims.bpd, autoHeight); 356 boolean contentOverflows = false; 357 if (!breaker.isEmpty()) { 358 contentOverflows = (breaker.deferredAlg.getPageBreaks().size() > 1); 359 } 360 361 Position bcPosition = new BlockContainerPosition(this, breaker); 362 returnList.add(new KnuthBox(vpContentBPD, notifyPos(bcPosition), false)); 363 370 371 if (contentOverflows) { 372 log.warn("Contents overflow block-container viewport: clipping"); 373 if (getBlockContainerFO().getOverflow() == EN_ERROR_IF_OVERFLOW) { 374 } 376 } 377 } 378 addKnuthElementsForBorderPaddingAfter(returnList, true); 379 addKnuthElementsForSpaceAfter(returnList, alignment); 380 addKnuthElementsForBreakAfter(returnList, context); 381 382 setFinished(true); 383 return returnList; 384 } 385 386 private LinkedList getNextKnuthElementsAbsolute(LayoutContext context, int alignment) { 387 autoHeight = false; 388 389 Point offset = getAbsOffset(); 390 int allocBPD, allocIPD; 391 if (height.getEnum() == EN_AUTO 392 || (!height.isAbsolute() && getAncestorBlockAreaBPD() <= 0)) { 393 allocBPD = 0; 396 if (abProps.bottom.getEnum() != EN_AUTO) { 397 int availHeight; 398 if (isFixed()) { 399 availHeight = (int)getCurrentPV().getViewArea().getHeight(); 400 } else { 401 availHeight = context.getStackLimit().opt; 402 } 403 allocBPD = availHeight; 404 allocBPD -= offset.y; 405 if (abProps.bottom.getEnum() != EN_AUTO) { 406 allocBPD -= abProps.bottom.getValue(this); 407 if (allocBPD < 0) { 408 418 allocBPD = 0; 419 } 420 } else { 421 if (allocBPD < 0) { 422 430 allocBPD = 0; 431 } 432 } 433 } else { 434 autoHeight = true; 435 } 436 } else { 437 allocBPD = height.getValue(this); allocBPD += getBPIndents(); 439 } 440 if (width.getEnum() == EN_AUTO) { 441 int availWidth; 442 if (isFixed()) { 443 availWidth = (int)getCurrentPV().getViewArea().getWidth(); 444 } else { 445 availWidth = context.getRefIPD(); 446 } 447 allocIPD = availWidth; 448 if (abProps.left.getEnum() != EN_AUTO) { 449 allocIPD -= abProps.left.getValue(this); 450 } 451 if (abProps.right.getEnum() != EN_AUTO) { 452 allocIPD -= abProps.right.getValue(this); 453 if (allocIPD < 0) { 454 462 allocIPD = 0; 463 } 464 } else { 465 if (allocIPD < 0) { 466 474 allocIPD = 0; 475 } 476 } 477 } else { 478 allocIPD = width.getValue(this); allocIPD += getIPIndents(); 480 } 481 482 vpContentBPD = allocBPD - getBPIndents(); 483 setContentAreaIPD(allocIPD - getIPIndents()); 484 485 double contentRectOffsetX = offset.getX(); 486 contentRectOffsetX += getBlockContainerFO() 487 .getCommonMarginBlock().startIndent.getValue(this); 488 double contentRectOffsetY = offset.getY(); 489 contentRectOffsetY += getSpaceBefore(); contentRectOffsetY += getBlockContainerFO() 491 .getCommonBorderPaddingBackground().getBorderBeforeWidth(false); 492 contentRectOffsetY += getBlockContainerFO() 493 .getCommonBorderPaddingBackground().getPaddingBefore(false, this); 494 495 Rectangle2D rect = new Rectangle2D.Double ( 496 contentRectOffsetX, contentRectOffsetY, 497 getContentAreaIPD(), vpContentBPD); 498 relDims = new FODimension(0, 0); 499 absoluteCTM = CTM.getCTMandRelDims( 500 getBlockContainerFO().getReferenceOrientation(), 501 getBlockContainerFO().getWritingMode(), 502 rect, relDims); 503 504 MinOptMax range = new MinOptMax(relDims.ipd); 505 BlockContainerBreaker breaker = new BlockContainerBreaker(this, range); 506 breaker.doLayout(relDims.bpd, autoHeight); 507 boolean contentOverflows = breaker.isOverflow(); 508 LinkedList returnList = new LinkedList (); 509 if (!breaker.isEmpty()) { 510 Position bcPosition = new BlockContainerPosition(this, breaker); 511 returnList.add(new KnuthBox(0, notifyPos(bcPosition), false)); 512 513 if (!autoHeight & (contentOverflows)) { 515 log.warn("Contents overflow block-container viewport: clipping"); 516 if (getBlockContainerFO().getOverflow() == EN_ERROR_IF_OVERFLOW) { 517 } 519 } 520 } 521 522 setFinished(true); 523 return returnList; 524 } 525 526 private class BlockContainerPosition extends NonLeafPosition { 527 528 private BlockContainerBreaker breaker; 529 530 public BlockContainerPosition(LayoutManager lm, BlockContainerBreaker breaker) { 531 super(lm, null); 532 this.breaker = breaker; 533 } 534 535 public BlockContainerBreaker getBreaker() { 536 return this.breaker; 537 } 538 539 } 540 541 private class BlockContainerBreaker extends AbstractBreaker { 542 543 private BlockContainerLayoutManager bclm; 544 private MinOptMax ipd; 545 546 private PageBreakingAlgorithm deferredAlg; 548 private BlockSequence deferredOriginalList; 549 private BlockSequence deferredEffectiveList; 550 551 public BlockContainerBreaker(BlockContainerLayoutManager bclm, MinOptMax ipd) { 552 this.bclm = bclm; 553 this.ipd = ipd; 554 } 555 556 557 protected void observeElementList(List elementList) { 558 ElementListObserver.observe(elementList, "block-container", 559 bclm.getBlockContainerFO().getId()); 560 } 561 562 563 protected boolean isPartOverflowRecoveryActivated() { 564 return false; 566 } 567 568 569 protected boolean isSinglePartFavored() { 570 return true; 571 } 572 573 public int getDifferenceOfFirstPart() { 574 PageBreakPosition pbp = (PageBreakPosition)this.deferredAlg.getPageBreaks().getFirst(); 575 return pbp.difference; 576 } 577 578 public boolean isOverflow() { 579 if (isEmpty()) { 580 return false; 581 } else { 582 return (deferredAlg.getPageBreaks().size() > 1); 583 } 584 } 585 586 protected LayoutManager getTopLevelLM() { 587 return bclm; 588 } 589 590 protected LayoutContext createLayoutContext() { 591 LayoutContext lc = super.createLayoutContext(); 592 lc.setRefIPD(ipd.opt); 593 lc.setWritingMode(getBlockContainerFO().getWritingMode()); 594 return lc; 595 } 596 597 protected LinkedList getNextKnuthElements(LayoutContext context, int alignment) { 598 LayoutManager curLM; LinkedList returnList = new LinkedList (); 600 601 while ((curLM = getChildLM()) != null) { 602 LayoutContext childLC = new LayoutContext(0); 603 childLC.setStackLimit(context.getStackLimit()); 604 childLC.setRefIPD(context.getRefIPD()); 605 childLC.setWritingMode(getBlockContainerFO().getWritingMode()); 606 607 LinkedList returnedList = null; 608 if (!curLM.isFinished()) { 609 returnedList = curLM.getNextKnuthElements(childLC, alignment); 610 } 611 if (returnedList != null) { 612 bclm.wrapPositionElements(returnedList, returnList); 613 } 614 } 615 SpaceResolver.resolveElementList(returnList); 616 setFinished(true); 617 return returnList; 618 } 619 620 protected int getCurrentDisplayAlign() { 621 return getBlockContainerFO().getDisplayAlign(); 622 } 623 624 protected boolean hasMoreContent() { 625 return !isFinished(); 626 } 627 628 protected void addAreas(PositionIterator posIter, LayoutContext context) { 629 AreaAdditionUtil.addAreas(bclm, posIter, context); 630 } 631 632 protected void doPhase3(PageBreakingAlgorithm alg, int partCount, 633 BlockSequence originalList, BlockSequence effectiveList) { 634 this.deferredAlg = alg; 636 this.deferredOriginalList = originalList; 637 this.deferredEffectiveList = effectiveList; 638 } 639 640 protected void finishPart(PageBreakingAlgorithm alg, PageBreakPosition pbp) { 641 } 643 644 protected LayoutManager getCurrentChildLM() { 645 return curChildLM; 646 } 647 648 public void addContainedAreas() { 649 if (isEmpty()) { 650 return; 651 } 652 this.addAreas(this.deferredAlg, 656 this.deferredAlg.getPageBreaks().size(), 657 this.deferredOriginalList, this.deferredEffectiveList); 658 } 659 660 } 661 662 private Point getAbsOffset() { 663 int x = 0; 664 int y = 0; 665 if (abProps.left.getEnum() != EN_AUTO) { 666 x = abProps.left.getValue(this); 667 } 668 if (abProps.top.getEnum() != EN_AUTO) { 669 y = abProps.top.getValue(this); 670 } 671 return new Point (x, y); 672 } 673 674 675 public void addAreas(PositionIterator parentIter, 676 LayoutContext layoutContext) { 677 getParentArea(null); 678 679 if (layoutContext.getSpaceBefore() > 0) { 682 addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); 683 } 684 685 LayoutManager childLM = null; 686 LayoutManager lastLM = null; 687 LayoutContext lc = new LayoutContext(0); 688 lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); 689 if (layoutContext.getSpaceAfter() > 0) { 691 lc.setSpaceAfter(layoutContext.getSpaceAfter()); 692 } 693 BlockContainerPosition bcpos = null; 694 PositionIterator childPosIter; 695 696 LinkedList positionList = new LinkedList (); 699 Position pos; 700 boolean bSpaceBefore = false; 701 boolean bSpaceAfter = false; 702 Position firstPos = null; 703 Position lastPos = null; 704 while (parentIter.hasNext()) { 705 pos = (Position) parentIter.next(); 706 if (pos.getIndex() >= 0) { 707 if (firstPos == null) { 708 firstPos = pos; 709 } 710 lastPos = pos; 711 } 712 Position innerPosition = pos; 713 if (pos instanceof NonLeafPosition) { 714 innerPosition = ((NonLeafPosition)pos).getPosition(); 715 } 716 if (pos instanceof BlockContainerPosition) { 717 if (bcpos != null) { 718 throw new IllegalStateException ("Only one BlockContainerPosition allowed"); 719 } 720 bcpos = (BlockContainerPosition)pos; 721 } else if (innerPosition == null) { 724 if (pos instanceof NonLeafPosition) { 725 if (positionList.size() == 0 && bcpos == null) { 729 bSpaceBefore = true; 731 } else { 732 bSpaceAfter = true; 734 } 735 } else { 736 } 738 } else if (innerPosition.getLM() == this 739 && !(innerPosition instanceof MappingPosition)) { 740 } else { 744 positionList.add(innerPosition); 746 lastLM = innerPosition.getLM(); 747 } 748 } 749 750 getPSLM().addIDToPage(getBlockContainerFO().getId()); 751 if (markers != null) { 752 getCurrentPV().addMarkers(markers, true, isFirst(firstPos), isLast(lastPos)); 753 } 754 755 if (bcpos == null) { 756 if (bpUnit == 0) { 757 childPosIter = new StackingIter(positionList.listIterator()); 760 } else { 761 LinkedList splitList = new LinkedList (); 775 int splitLength = 0; 776 int iFirst = ((MappingPosition) positionList.getFirst()).getFirstIndex(); 777 int iLast = ((MappingPosition) positionList.getLast()).getLastIndex(); 778 ListIterator storedListIterator = storedList.listIterator(iFirst); 781 while (storedListIterator.nextIndex() <= iLast) { 782 KnuthElement element = (KnuthElement) storedListIterator 783 .next(); 784 if (element.getLayoutManager() != this) { 787 splitList.add(element); 788 splitLength += element.getW(); 789 lastLM = element.getLayoutManager(); 790 } 791 } 792 if (bSpaceBefore && bSpaceAfter) { 800 foBlockSpaceBefore = new SpaceVal(getBlockContainerFO() 801 .getCommonMarginBlock().spaceBefore, this).getSpace(); 802 foBlockSpaceAfter = new SpaceVal(getBlockContainerFO() 803 .getCommonMarginBlock().spaceAfter, this).getSpace(); 804 adjustedSpaceBefore = (neededUnits(splitLength 805 + foBlockSpaceBefore.min 806 + foBlockSpaceAfter.min) 807 * bpUnit - splitLength) / 2; 808 adjustedSpaceAfter = neededUnits(splitLength 809 + foBlockSpaceBefore.min 810 + foBlockSpaceAfter.min) 811 * bpUnit - splitLength - adjustedSpaceBefore; 812 } else if (bSpaceBefore) { 813 adjustedSpaceBefore = neededUnits(splitLength 814 + foBlockSpaceBefore.min) 815 * bpUnit - splitLength; 816 } else { 817 adjustedSpaceAfter = neededUnits(splitLength 818 + foBlockSpaceAfter.min) 819 * bpUnit - splitLength; 820 } 821 childPosIter = new KnuthPossPosIter(splitList, 0, splitList 825 .size()); 826 } 828 829 while ((childLM = childPosIter.getNextChildLM()) != null) { 830 lc.setFlags(LayoutContext.LAST_AREA, 832 (layoutContext.isLastArea() && childLM == lastLM)); 833 lc.setStackLimit(layoutContext.getStackLimit()); 834 childLM.addAreas(childPosIter, lc); 836 } 837 } else { 838 bcpos.getBreaker().addContainedAreas(); 840 } 841 842 if (markers != null) { 843 getCurrentPV().addMarkers(markers, false, isFirst(firstPos), isLast(lastPos)); 844 } 845 846 TraitSetter.addSpaceBeforeAfter(viewportBlockArea, layoutContext.getSpaceAdjust(), 847 effSpaceBefore, effSpaceAfter); 848 flush(); 849 850 viewportBlockArea = null; 851 referenceArea = null; 852 resetSpaces(); 853 854 getPSLM().notifyEndOfLayout(((BlockContainer)getFObj()).getId()); 855 } 856 857 864 public Area getParentArea(Area childArea) { 865 if (referenceArea == null) { 866 viewportBlockArea = new BlockViewport(); 867 viewportBlockArea.addTrait(Trait.IS_VIEWPORT_AREA, Boolean.TRUE); 868 viewportBlockArea.setIPD(getContentAreaIPD()); 869 if (autoHeight) { 870 viewportBlockArea.setBPD(0); 871 } else { 872 viewportBlockArea.setBPD(getContentAreaBPD()); 873 } 874 875 TraitSetter.setProducerID(viewportBlockArea, getBlockContainerFO().getId()); 876 TraitSetter.addBorders(viewportBlockArea, 877 getBlockContainerFO().getCommonBorderPaddingBackground(), 878 discardBorderBefore, discardBorderAfter, false, false, this); 879 TraitSetter.addPadding(viewportBlockArea, 880 getBlockContainerFO().getCommonBorderPaddingBackground(), 881 discardPaddingBefore, discardPaddingAfter, false, false, this); 882 TraitSetter.addMargins(viewportBlockArea, 886 getBlockContainerFO().getCommonBorderPaddingBackground(), 887 startIndent, endIndent, 888 this); 889 890 viewportBlockArea.setCTM(absoluteCTM); 891 viewportBlockArea.setClip(needClip()); 892 899 900 if (abProps.absolutePosition == EN_ABSOLUTE 901 || abProps.absolutePosition == EN_FIXED) { 902 Point offset = getAbsOffset(); 903 viewportBlockArea.setXOffset(offset.x); 904 viewportBlockArea.setYOffset(offset.y); 905 } else { 906 } 908 909 referenceArea = new Block(); 910 referenceArea.addTrait(Trait.IS_REFERENCE_AREA, Boolean.TRUE); 911 TraitSetter.setProducerID(referenceArea, getBlockContainerFO().getId()); 912 913 if (abProps.absolutePosition == EN_ABSOLUTE) { 914 viewportBlockArea.setPositioning(Block.ABSOLUTE); 915 } else if (abProps.absolutePosition == EN_FIXED) { 916 viewportBlockArea.setPositioning(Block.FIXED); 917 } 918 919 parentLM.getParentArea(referenceArea); 922 referenceArea.setIPD(relDims.ipd); 924 setCurrentArea(viewportBlockArea); } 927 return referenceArea; 928 } 929 930 935 public void addChildArea(Area childArea) { 936 if (referenceArea != null) { 937 referenceArea.addBlock((Block) childArea); 938 } 939 } 940 941 944 public void resetPosition(Position resetPos) { 945 if (resetPos == null) { 946 reset(null); 947 } 948 } 949 950 954 protected void flush() { 955 viewportBlockArea.addBlock(referenceArea, autoHeight); 956 957 TraitSetter.addBackground(viewportBlockArea, 958 getBlockContainerFO().getCommonBorderPaddingBackground(), 959 this); 960 961 int saveBPD = viewportBlockArea.getBPD(); 963 if (viewportBlockArea.getPositioning() == Block.ABSOLUTE) { 964 viewportBlockArea.setBPD(0); 965 } 966 super.flush(); 967 if (viewportBlockArea.getPositioning() == Block.ABSOLUTE) { 969 viewportBlockArea.setBPD(saveBPD); 970 } 971 } 972 973 974 public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) { 975 return 0; 977 } 978 979 980 public void discardSpace(KnuthGlue spaceGlue) { 981 983 } 984 985 988 public boolean mustKeepTogether() { 989 return ((BlockLevelLayoutManager)getParent()).mustKeepTogether() 991 || !getBlockContainerFO().getKeepTogether().getWithinPage().isAuto() 992 || !getBlockContainerFO().getKeepTogether().getWithinColumn().isAuto(); 993 } 994 995 998 public boolean mustKeepWithPrevious() { 999 return !getBlockContainerFO().getKeepWithPrevious().getWithinPage().isAuto() 1000 || !getBlockContainerFO().getKeepWithPrevious().getWithinColumn().isAuto(); 1001 } 1002 1003 1006 public boolean mustKeepWithNext() { 1007 return !getBlockContainerFO().getKeepWithNext().getWithinPage().isAuto() 1008 || !getBlockContainerFO().getKeepWithNext().getWithinColumn().isAuto(); 1009 } 1010 1011 1014 protected BlockContainer getBlockContainerFO() { 1015 return (BlockContainer) fobj; 1016 } 1017 1018 1020 1023 public boolean getGeneratesReferenceArea() { 1024 return true; 1025 } 1026 1027 1030 public boolean getGeneratesBlockArea() { 1031 return true; 1032 } 1033 1034 1035 public void notifySpace(RelSide side, MinOptMax effectiveLength) { 1036 if (RelSide.BEFORE == side) { 1037 if (log.isDebugEnabled()) { 1038 log.debug(this + ": Space " + side + ", " 1039 + this.effSpaceBefore + "-> " + effectiveLength); 1040 } 1041 this.effSpaceBefore = effectiveLength; 1042 } else { 1043 if (log.isDebugEnabled()) { 1044 log.debug(this + ": Space " + side + ", " 1045 + this.effSpaceAfter + "-> " + effectiveLength); 1046 } 1047 this.effSpaceAfter = effectiveLength; 1048 } 1049 } 1050 1051 1052 public void notifyBorder(RelSide side, MinOptMax effectiveLength) { 1053 if (effectiveLength == null) { 1054 if (RelSide.BEFORE == side) { 1055 this.discardBorderBefore = true; 1056 } else { 1057 this.discardBorderAfter = true; 1058 } 1059 } 1060 if (log.isDebugEnabled()) { 1061 log.debug(this + ": Border " + side + " -> " + effectiveLength); 1062 } 1063 } 1064 1065 1066 public void notifyPadding(RelSide side, MinOptMax effectiveLength) { 1067 if (effectiveLength == null) { 1068 if (RelSide.BEFORE == side) { 1069 this.discardPaddingBefore = true; 1070 } else { 1071 this.discardPaddingAfter = true; 1072 } 1073 } 1074 if (log.isDebugEnabled()) { 1075 log.debug(this + ": Padding " + side + " -> " + effectiveLength); 1076 } 1077 } 1078 1079} 1080 1081 | Popular Tags |