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 26 import org.apache.commons.logging.Log; 27 import org.apache.commons.logging.LogFactory; 28 import org.apache.fop.area.Area; 29 import org.apache.fop.area.Block; 30 import org.apache.fop.area.LineArea; 31 import org.apache.fop.datatypes.Length; 32 import org.apache.fop.fonts.Font; 33 import org.apache.fop.layoutmgr.inline.InlineLayoutManager; 34 import org.apache.fop.layoutmgr.inline.InlineLevelLayoutManager; 35 import org.apache.fop.layoutmgr.inline.LineLayoutManager; 36 import org.apache.fop.traits.MinOptMax; 37 import org.apache.fop.traits.SpaceVal; 38 39 42 public class BlockLayoutManager extends BlockStackingLayoutManager 43 implements ConditionalElementListener { 44 45 48 private static Log log = LogFactory.getLog(BlockLayoutManager.class); 49 50 private Block curBlockArea; 51 52 53 protected ListIterator proxyLMiter; 54 55 private int lead = 12000; 56 private Length lineHeight; 57 private int follow = 2000; 58 private int middleShift = 0; 59 60 private boolean discardBorderBefore; 61 private boolean discardBorderAfter; 62 private boolean discardPaddingBefore; 63 private boolean discardPaddingAfter; 64 private MinOptMax effSpaceBefore; 65 private MinOptMax effSpaceAfter; 66 67 68 protected List childBreaks = new java.util.ArrayList (); 69 70 74 public BlockLayoutManager(org.apache.fop.fo.flow.Block inBlock) { 75 super(inBlock); 76 proxyLMiter = new ProxyLMiter(); 77 } 78 79 public void initialize() { 80 super.initialize(); 81 Font fs = getBlockFO().getCommonFont().getFontState( 82 getBlockFO().getFOEventHandler().getFontInfo(), this); 83 84 lead = fs.getAscender(); 85 follow = -fs.getDescender(); 86 middleShift = -fs.getXHeight() / 2; 87 lineHeight = getBlockFO().getLineHeight().getOptimum(this).getLength(); 88 startIndent = getBlockFO().getCommonMarginBlock().startIndent.getValue(this); 89 endIndent = getBlockFO().getCommonMarginBlock().endIndent.getValue(this); 90 foSpaceBefore = new SpaceVal(getBlockFO().getCommonMarginBlock().spaceBefore, this) 91 .getSpace(); 92 foSpaceAfter = new SpaceVal(getBlockFO().getCommonMarginBlock().spaceAfter, this) 93 .getSpace(); 94 bpUnit = 0; if (bpUnit == 0) { 96 adjustedSpaceBefore = getBlockFO().getCommonMarginBlock().spaceBefore.getSpace() 98 .getOptimum(this).getLength().getValue(this); 99 adjustedSpaceAfter = getBlockFO().getCommonMarginBlock().spaceAfter.getSpace() 100 .getOptimum(this).getLength().getValue(this); 101 } else { 102 adjustedSpaceBefore = getBlockFO().getCommonMarginBlock().spaceBefore.getSpace() 104 .getMinimum(this).getLength().getValue(this); 105 adjustedSpaceAfter = getBlockFO().getCommonMarginBlock().spaceAfter.getSpace() 106 .getMinimum(this).getLength().getValue(this); 107 } 108 } 109 110 111 public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { 112 resetSpaces(); 113 return super.getNextKnuthElements(context, alignment); 114 } 115 116 private void resetSpaces() { 117 this.discardBorderBefore = false; 118 this.discardBorderAfter = false; 119 this.discardPaddingBefore = false; 120 this.discardPaddingAfter = false; 121 this.effSpaceBefore = null; 122 this.effSpaceAfter = null; 123 } 124 125 133 protected class ProxyLMiter extends LMiter { 134 135 138 public ProxyLMiter() { 139 super(BlockLayoutManager.this); 140 listLMs = new java.util.ArrayList (10); 141 } 142 143 146 public boolean hasNext() { 147 return (curPos < listLMs.size()) ? true : createNextChildLMs(curPos); 148 } 149 150 153 protected boolean createNextChildLMs(int pos) { 154 List newLMs = createChildLMs(pos + 1 - listLMs.size()); 155 if (newLMs != null) { 156 listLMs.addAll(newLMs); 157 } 158 return pos < listLMs.size(); 159 } 160 } 161 162 165 public boolean createNextChildLMs(int pos) { 166 167 while (proxyLMiter.hasNext()) { 168 LayoutManager lm = (LayoutManager) proxyLMiter.next(); 169 if (lm instanceof InlineLevelLayoutManager) { 170 LineLayoutManager lineLM = createLineManager(lm); 171 addChildLM(lineLM); 172 } else { 173 addChildLM(lm); 174 } 175 if (pos < childLMs.size()) { 176 return true; 177 } 178 } 179 return false; 180 } 181 182 188 private LineLayoutManager createLineManager(LayoutManager firstlm) { 189 LineLayoutManager llm; 190 llm = new LineLayoutManager(getBlockFO(), lineHeight, lead, follow); 191 List inlines = new java.util.ArrayList (); 192 inlines.add(firstlm); 193 while (proxyLMiter.hasNext()) { 194 LayoutManager lm = (LayoutManager) proxyLMiter.next(); 195 if (lm instanceof InlineLevelLayoutManager) { 196 inlines.add(lm); 197 } else { 198 proxyLMiter.previous(); 199 break; 200 } 201 } 202 llm.addChildLMs(inlines); 203 return llm; 204 } 205 206 209 public boolean mustKeepTogether() { 210 return (!getBlockFO().getKeepTogether().getWithinPage().isAuto() 214 || !getBlockFO().getKeepTogether().getWithinColumn().isAuto() 215 || (getParent() instanceof BlockLevelLayoutManager 216 && ((BlockLevelLayoutManager) getParent()).mustKeepTogether()) 217 || (getParent() instanceof InlineLayoutManager 218 && ((InlineLayoutManager) getParent()).mustKeepTogether())); 219 } 220 221 224 public boolean mustKeepWithPrevious() { 225 return !getBlockFO().getKeepWithPrevious().getWithinPage().isAuto() 226 || !getBlockFO().getKeepWithPrevious().getWithinColumn().isAuto(); 227 } 228 229 232 public boolean mustKeepWithNext() { 233 return !getBlockFO().getKeepWithNext().getWithinPage().isAuto() 234 || !getBlockFO().getKeepWithNext().getWithinColumn().isAuto(); 235 } 236 237 240 public void addAreas(PositionIterator parentIter, 241 LayoutContext layoutContext) { 242 getParentArea(null); 243 244 if (layoutContext.getSpaceBefore() > 0) { 247 addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); 248 } 249 250 LayoutManager childLM = null; 251 LayoutManager lastLM = null; 252 LayoutContext lc = new LayoutContext(0); 253 lc.setSpaceAdjust(layoutContext.getSpaceAdjust()); 254 if (layoutContext.getSpaceAfter() > 0) { 256 lc.setSpaceAfter(layoutContext.getSpaceAfter()); 257 } 258 PositionIterator childPosIter; 259 260 LinkedList positionList = new LinkedList (); 263 Position pos; 264 boolean bSpaceBefore = false; 265 boolean bSpaceAfter = false; 266 Position firstPos = null; 267 Position lastPos = null; 268 while (parentIter.hasNext()) { 269 pos = (Position) parentIter.next(); 270 if (pos.getIndex() >= 0) { 272 if (firstPos == null) { 273 firstPos = pos; 274 } 275 lastPos = pos; 276 } 277 Position innerPosition = pos; 278 if (pos instanceof NonLeafPosition) { 279 innerPosition = ((NonLeafPosition) pos).getPosition(); 281 } 282 if (innerPosition == null) { 283 if (positionList.size() == 0) { 287 bSpaceBefore = true; 289 } else { 291 bSpaceAfter = true; 293 } 295 } else if (innerPosition.getLM() == this 296 && !(innerPosition instanceof MappingPosition)) { 297 } else { 302 positionList.add(innerPosition); 304 lastLM = innerPosition.getLM(); 305 } 307 } 308 309 getPSLM().addIDToPage(getBlockFO().getId()); 310 if (markers != null) { 311 getCurrentPV().addMarkers(markers, true, isFirst(firstPos), isLast(lastPos)); 312 } 313 314 if (bpUnit == 0) { 315 childPosIter = new StackingIter(positionList.listIterator()); 318 } else { 319 LinkedList splitList = new LinkedList (); 333 int splitLength = 0; 334 int iFirst = ((MappingPosition) positionList.getFirst()).getFirstIndex(); 335 int iLast = ((MappingPosition) positionList.getLast()).getLastIndex(); 336 ListIterator storedListIterator = storedList.listIterator(iFirst); 339 while (storedListIterator.nextIndex() <= iLast) { 340 KnuthElement element = (KnuthElement) storedListIterator 341 .next(); 342 if (element.getLayoutManager() != this) { 345 splitList.add(element); 346 splitLength += element.getW(); 347 lastLM = element.getLayoutManager(); 348 } 349 } 350 if (bSpaceBefore && bSpaceAfter) { 358 foSpaceBefore = new SpaceVal(getBlockFO() 359 .getCommonMarginBlock().spaceBefore, this).getSpace(); 360 foSpaceAfter = new SpaceVal(getBlockFO() 361 .getCommonMarginBlock().spaceAfter, this).getSpace(); 362 adjustedSpaceBefore = (neededUnits(splitLength 363 + foSpaceBefore.min 364 + foSpaceAfter.min) 365 * bpUnit - splitLength) / 2; 366 adjustedSpaceAfter = neededUnits(splitLength 367 + foSpaceBefore.min 368 + foSpaceAfter.min) 369 * bpUnit - splitLength - adjustedSpaceBefore; 370 } else if (bSpaceBefore) { 371 adjustedSpaceBefore = neededUnits(splitLength 372 + foSpaceBefore.min) 373 * bpUnit - splitLength; 374 } else { 375 adjustedSpaceAfter = neededUnits(splitLength 376 + foSpaceAfter.min) 377 * bpUnit - splitLength; 378 } 379 childPosIter = new KnuthPossPosIter(splitList, 0, splitList 383 .size()); 384 } 386 387 while ((childLM = childPosIter.getNextChildLM()) != null) { 388 lc.setFlags(LayoutContext.LAST_AREA, 390 (layoutContext.isLastArea() && childLM == lastLM)); 391 lc.setStackLimit(layoutContext.getStackLimit()); 392 childLM.addAreas(childPosIter, lc); 394 } 395 396 if (markers != null) { 397 getCurrentPV().addMarkers(markers, false, isFirst(firstPos), isLast(lastPos)); 398 } 399 400 TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(), 401 effSpaceBefore, effSpaceAfter); 402 flush(); 403 404 curBlockArea = null; 405 resetSpaces(); 406 407 getPSLM().notifyEndOfLayout(getBlockFO().getId()); 409 } 410 411 423 public Area getParentArea(Area childArea) { 424 if (curBlockArea == null) { 425 curBlockArea = new Block(); 426 427 curBlockArea.setIPD(super.getContentAreaIPD()); 428 429 TraitSetter.addBreaks(curBlockArea, 430 getBlockFO().getBreakBefore(), getBlockFO().getBreakAfter()); 431 432 parentLM.getParentArea(curBlockArea); 435 436 TraitSetter.setProducerID(curBlockArea, getBlockFO().getId()); 438 TraitSetter.addBorders(curBlockArea, 439 getBlockFO().getCommonBorderPaddingBackground(), 440 discardBorderBefore, discardBorderAfter, false, false, this); 441 TraitSetter.addPadding(curBlockArea, 442 getBlockFO().getCommonBorderPaddingBackground(), 443 discardPaddingBefore, discardPaddingAfter, false, false, this); 444 TraitSetter.addMargins(curBlockArea, 445 getBlockFO().getCommonBorderPaddingBackground(), 446 startIndent, endIndent, 447 this); 448 449 setCurrentArea(curBlockArea); } 451 return curBlockArea; 452 } 453 454 457 public void addChildArea(Area childArea) { 458 if (curBlockArea != null) { 459 if (childArea instanceof LineArea) { 460 curBlockArea.addLineArea((LineArea) childArea); 461 } else { 462 curBlockArea.addBlock((Block) childArea); 463 } 464 } 465 } 466 467 471 protected void flush() { 472 if (curBlockArea != null) { 473 TraitSetter.addBackground(curBlockArea, 474 getBlockFO().getCommonBorderPaddingBackground(), 475 this); 476 super.flush(); 477 } 478 } 479 480 483 public void resetPosition(Position resetPos) { 484 if (resetPos == null) { 485 reset(null); 486 childBreaks.clear(); 487 } else { 488 LayoutManager lm = resetPos.getLM(); 490 } 491 } 492 493 497 protected org.apache.fop.fo.flow.Block getBlockFO() { 498 return (org.apache.fop.fo.flow.Block) fobj; 499 } 500 501 503 507 public int getContentAreaIPD() { 508 if (curBlockArea != null) { 509 return curBlockArea.getIPD(); 510 } 511 return super.getContentAreaIPD(); 512 } 513 514 515 519 public int getContentAreaBPD() { 520 if (curBlockArea != null) { 521 return curBlockArea.getBPD(); 522 } 523 return -1; 524 } 525 526 529 public boolean getGeneratesBlockArea() { 530 return true; 531 } 532 533 534 public void notifySpace(RelSide side, MinOptMax effectiveLength) { 535 if (RelSide.BEFORE == side) { 536 if (log.isDebugEnabled()) { 537 log.debug(this + ": Space " + side + ", " 538 + this.effSpaceBefore + "-> " + effectiveLength); 539 } 540 this.effSpaceBefore = effectiveLength; 541 } else { 542 if (log.isDebugEnabled()) { 543 log.debug(this + ": Space " + side + ", " 544 + this.effSpaceAfter + "-> " + effectiveLength); 545 } 546 this.effSpaceAfter = effectiveLength; 547 } 548 } 549 550 551 public void notifyBorder(RelSide side, MinOptMax effectiveLength) { 552 if (effectiveLength == null) { 553 if (RelSide.BEFORE == side) { 554 this.discardBorderBefore = true; 555 } else { 556 this.discardBorderAfter = true; 557 } 558 } 559 if (log.isDebugEnabled()) { 560 log.debug(this + ": Border " + side + " -> " + effectiveLength); 561 } 562 } 563 564 565 public void notifyPadding(RelSide side, MinOptMax effectiveLength) { 566 if (effectiveLength == null) { 567 if (RelSide.BEFORE == side) { 568 this.discardPaddingBefore = true; 569 } else { 570 this.discardPaddingAfter = true; 571 } 572 } 573 if (log.isDebugEnabled()) { 574 log.debug(this + ": Padding " + side + " -> " + effectiveLength); 575 } 576 } 577 578 } 579 580 | Popular Tags |