1 17 18 19 20 package org.apache.fop.render.txt; 21 22 import java.io.OutputStream ; 23 import java.util.Arrays ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 27 import org.apache.fop.apps.FOPException; 28 import org.apache.fop.apps.FOUserAgent; 29 import org.apache.fop.apps.MimeConstants; 30 import org.apache.fop.area.AreaTreeHandler; 31 import org.apache.fop.datatypes.CompoundDatatype; 32 import org.apache.fop.datatypes.Length; 33 import org.apache.fop.datatypes.PercentBaseContext; 34 import org.apache.fop.fo.Constants; 35 import org.apache.fop.fo.FONode; 36 import org.apache.fop.fo.FOText; 37 import org.apache.fop.fo.expr.NumericProperty; 38 import org.apache.fop.fo.expr.RelativeNumericProperty; 39 import org.apache.fop.fo.flow.Block; 40 import org.apache.fop.fo.flow.BlockContainer; 41 import org.apache.fop.fo.flow.ExternalGraphic; 42 import org.apache.fop.fo.flow.Inline; 43 import org.apache.fop.fo.flow.ListBlock; 44 import org.apache.fop.fo.flow.ListItem; 45 import org.apache.fop.fo.flow.PageNumber; 46 import org.apache.fop.fo.flow.Table; 47 import org.apache.fop.fo.flow.TableCell; 48 import org.apache.fop.fo.flow.TableColumn; 49 import org.apache.fop.fo.pagination.PageSequence; 50 import org.apache.fop.fo.properties.CommonAbsolutePosition; 51 import org.apache.fop.fo.properties.CommonBorderPaddingBackground; 52 import org.apache.fop.fo.properties.CommonFont; 53 import org.apache.fop.fo.properties.CommonMarginBlock; 54 import org.apache.fop.fo.properties.FixedLength; 55 import org.apache.fop.fo.properties.Property; 56 import org.apache.fop.fo.properties.SpaceProperty; 57 import org.apache.fop.layoutmgr.BlockLayoutManager; 58 59 67 public class TXTHandler extends AreaTreeHandler { 68 69 70 private static final PercentBaseContext CONTEXT 71 = new BlockLayoutManager(new Block(null)); 72 73 74 private static final int MODIFIED_FONT_SIZE = 10000; 75 76 77 private final int[] quantum = {TXTRenderer.CHAR_HEIGHT, 78 TXTRenderer.CHAR_HEIGHT, TXTRenderer.CHAR_WIDTH, 79 TXTRenderer.CHAR_WIDTH}; 80 81 82 private int[] overPatching = new int[4]; 83 84 88 private int[] lastOverPatching = new int[4]; 89 90 97 public TXTHandler(FOUserAgent userAgent, OutputStream stream) 98 throws FOPException { 99 super(userAgent, MimeConstants.MIME_PLAIN_TEXT, stream); 100 } 101 102 109 private static void setLength(CompoundDatatype cd, int value) { 110 cd.setComponent(Constants.CP_LENGTH, new FixedLength(value), true); 111 } 112 113 120 private static void setMinOptMax(CompoundDatatype cd, Property p) { 121 cd.setComponent(Constants.CP_MINIMUM, p, true); 122 cd.setComponent(Constants.CP_OPTIMUM, p, true); 123 cd.setComponent(Constants.CP_MAXIMUM, p, true); 124 } 125 126 136 private void modifyBorder(int side, CommonBorderPaddingBackground bpb) { 137 CommonBorderPaddingBackground.BorderInfo bi = bpb.getBorderInfo(side); 138 139 if (bi != null) { 140 int width = bpb.getBorderWidth(side, false); 141 setLength(bi.getWidth(), quantum[side] / 2); 142 lastOverPatching[side] += bpb.getBorderWidth(side, false) - width; 143 } 144 } 145 146 158 private void modifyPadding(int side, CommonBorderPaddingBackground bpb) { 159 int oldPadding = bpb.getPadding(side, false, null); 160 int newPadding = Helper.round(oldPadding, quantum[side]); 161 if (bpb.getBorderInfo(side) != null) { 162 newPadding = Math.max(newPadding, quantum[side]) 163 - bpb.getBorderWidth(side, false); 164 } 165 166 setLength(bpb.getPaddingLengthProperty(side), newPadding); 167 lastOverPatching[side] += newPadding - oldPadding; 168 } 169 170 175 private void modifyBPB(CommonBorderPaddingBackground bpb) { 176 modifyBorder(CommonBorderPaddingBackground.BEFORE, bpb); 177 modifyBorder(CommonBorderPaddingBackground.AFTER, bpb); 178 modifyBorder(CommonBorderPaddingBackground.START, bpb); 179 modifyBorder(CommonBorderPaddingBackground.END, bpb); 180 181 modifyPadding(CommonBorderPaddingBackground.BEFORE, bpb); 182 modifyPadding(CommonBorderPaddingBackground.AFTER, bpb); 183 modifyPadding(CommonBorderPaddingBackground.START, bpb); 184 modifyPadding(CommonBorderPaddingBackground.END, bpb); 185 } 186 187 194 private void modifySpace(SpaceProperty space, int q) { 195 int value = space.getOptimum(null).getLength().getValue(); 196 setMinOptMax(space, new FixedLength(Helper.round(value, q))); 197 } 198 199 205 private Length roundLength(Length length, int q) { 206 int x = Helper.round(length.getValue(), q); 207 return new FixedLength(x); 208 } 209 210 216 private Length ceilLength(Length length, int q) { 217 int x = Helper.ceil(length.getValue(), q); 218 return new FixedLength(x); 219 } 220 221 230 private Length modifyIndent(Length indent, int side) { 231 if (indent instanceof NumericProperty) { 232 overPatching[side] += lastOverPatching[side]; 233 } 234 int newValue = indent.getValue() + overPatching[side]; 235 newValue = Helper.round(newValue, quantum[side]); 236 return new FixedLength(newValue); 237 } 238 239 249 private void modifyCommonMarginBlock(CommonMarginBlock cmb) { 250 cmb.marginTop = roundLength(cmb.marginTop, TXTRenderer.CHAR_HEIGHT); 251 cmb.marginBottom = roundLength(cmb.marginBottom, 252 TXTRenderer.CHAR_HEIGHT); 253 cmb.marginLeft = roundLength(cmb.marginLeft, TXTRenderer.CHAR_WIDTH); 254 cmb.marginRight = roundLength(cmb.marginRight, TXTRenderer.CHAR_WIDTH); 255 256 modifySpace(cmb.spaceBefore, TXTRenderer.CHAR_HEIGHT); 257 modifySpace(cmb.spaceAfter, TXTRenderer.CHAR_HEIGHT); 258 259 if (!(cmb.startIndent instanceof RelativeNumericProperty)) { 260 cmb.startIndent = modifyIndent(cmb.startIndent, 261 CommonBorderPaddingBackground.START); 262 } 263 if (!(cmb.endIndent instanceof RelativeNumericProperty)) { 264 cmb.endIndent = modifyIndent(cmb.endIndent, 265 CommonBorderPaddingBackground.END); 266 } 267 } 268 269 279 private void modifyTable(Table table) { 280 CommonMarginBlock cmb = table.getCommonMarginBlock(); 281 if (table.getBorderCollapse() == Constants.EN_COLLAPSE) { 282 int value = cmb.spaceAfter.getOptimum(null).getLength().getValue(); 285 value += TXTRenderer.CHAR_HEIGHT; 286 setMinOptMax(cmb.spaceAfter, new FixedLength(value)); 287 } 288 modifyCommonMarginBlock(cmb); 289 290 modifyBPB(table.getCommonBorderPaddingBackground()); 291 292 List columnList = table.getColumns(); 294 Iterator iter = columnList.iterator(); 295 while (iter.hasNext()) { 296 modifyTableColumn((TableColumn) iter.next()); 297 } 298 } 299 300 308 private void modifyTableColumn(TableColumn column) { 309 column.setColumnWidth(ceilLength(column.getColumnWidth(), 310 TXTRenderer.CHAR_WIDTH)); 311 } 312 313 319 private void modifyCellPadding(int side, CommonBorderPaddingBackground bpb) { 320 if (bpb.getBorderInfo(side) == null) { 321 int oldPadding = bpb.getPadding(side, false, null); 322 int newPadding = oldPadding + quantum[side] / 2; 323 setLength(bpb.getPaddingLengthProperty(side), newPadding); 324 } 325 } 326 327 335 private void modifyTableCell(TableCell c) { 336 CommonBorderPaddingBackground bpb = c 337 .getCommonBorderPaddingBackground(); 338 modifyBPB(bpb); 339 modifyCellPadding(CommonBorderPaddingBackground.BEFORE, bpb); 340 modifyCellPadding(CommonBorderPaddingBackground.AFTER, bpb); 341 modifyCellPadding(CommonBorderPaddingBackground.START, bpb); 342 modifyCellPadding(CommonBorderPaddingBackground.END, bpb); 343 } 344 345 354 private void modifyCommonAbsolutePosition(CommonAbsolutePosition cap) { 355 if (cap.absolutePosition == Constants.EN_ABSOLUTE) { 356 cap.left = roundLength(cap.left, TXTRenderer.CHAR_WIDTH); 357 cap.top = roundLength(cap.top, TXTRenderer.CHAR_HEIGHT); 358 } 359 } 360 361 367 private void modifyLineHeight(SpaceProperty lineHeight) { 368 Property p = lineHeight.getOptimum(null); 369 int value = p.getLength().getValue(CONTEXT); 370 371 int height = TXTRenderer.CHAR_HEIGHT; 372 int newValue = Math.max(Helper.floor(value, height), height); 373 setMinOptMax(lineHeight, new FixedLength(newValue)); 374 } 375 376 387 private void modifyCommonFont(CommonFont cf) { 388 if (cf != null) { 389 cf.overrideFontFamily("Courier"); 390 cf.fontSize = new FixedLength(MODIFIED_FONT_SIZE); 391 cf.fontStretch = Constants.EN_NORMAL; 392 cf.fontWeight = Constants.EN_NORMAL; 393 } 394 } 395 396 407 private void modifyBlock(Block block) { 408 modifyBPB(block.getCommonBorderPaddingBackground()); 409 modifyCommonMarginBlock(block.getCommonMarginBlock()); 410 modifyCommonFont(block.getCommonFont()); 411 modifyLineHeight(block.getLineHeight()); 412 } 413 414 424 private void modifyBlockContainer(BlockContainer bc) { 425 modifyBPB(bc.getCommonBorderPaddingBackground()); 426 modifyCommonMarginBlock(bc.getCommonMarginBlock()); 427 modifyCommonAbsolutePosition(bc.getCommonAbsolutePosition()); 428 } 429 430 438 private void modifyInline(Inline inline) { 439 modifyCommonFont(inline.getCommonFont()); 440 } 441 442 450 private void modifyFOText(FOText text) { 451 modifyCommonFont(text.getCommonFont()); 452 } 453 454 463 private void modifyExternalGraphic(ExternalGraphic eg) { 464 modifyBPB(eg.getCommonBorderPaddingBackground()); 465 modifyLineHeight(eg.getLineHeight()); 466 } 467 468 477 private void modifyListBlock(ListBlock lb) { 478 modifyBPB(lb.getCommonBorderPaddingBackground()); 479 modifyCommonMarginBlock(lb.getCommonMarginBlock()); 480 } 481 482 493 private void modifyListItem(ListItem li) { 494 modifyBPB(li.getCommonBorderPaddingBackground()); 495 modifyCommonMarginBlock(li.getCommonMarginBlock()); 496 refinement(li.getLabel()); 497 refinement(li.getBody()); 498 } 499 500 506 private void refinement(FONode node) { 507 int[] saveOverPatching = (int[]) overPatching.clone(); 508 Arrays.fill(lastOverPatching, 0); 509 510 if (node instanceof Block) { 511 modifyBlock((Block) node); 512 } else if (node instanceof BlockContainer) { 513 modifyBlockContainer((BlockContainer) node); 514 } else if (node instanceof Inline) { 515 modifyInline((Inline) node); 516 } else if (node instanceof FOText) { 517 modifyFOText((FOText) node); 518 } else if (node instanceof Table) { 519 modifyTable((Table) node); 520 Arrays.fill(overPatching, 0); 521 } else if (node instanceof TableCell) { 522 modifyTableCell((TableCell) node); 523 } else if (node instanceof ExternalGraphic) { 524 modifyExternalGraphic((ExternalGraphic) node); 525 } else if (node instanceof ListBlock) { 526 modifyListBlock((ListBlock) node); 527 } else if (node instanceof ListItem) { 528 modifyListItem((ListItem) node); 529 } else if (node instanceof PageNumber) { 530 modifyCommonFont(((PageNumber) node).getCommonFont()); 531 } 532 533 Iterator it = node.getChildNodes(); 534 if (it != null) { 535 while (it.hasNext()) { 536 refinement((FONode) it.next()); 537 } 538 } 539 overPatching = saveOverPatching; 540 } 541 542 552 public void endPageSequence(PageSequence pageSequence) { 553 Arrays.fill(overPatching, 0); 554 555 refinement(pageSequence.getMainFlow()); 556 557 if (pageSequence.getStaticContent("xsl-region-before") != null) { 558 refinement(pageSequence.getStaticContent("xsl-region-before")); 559 } 560 if (pageSequence.getStaticContent("xsl-region-after") != null) { 561 refinement(pageSequence.getStaticContent("xsl-region-after")); 562 } 563 if (pageSequence.getStaticContent("xsl-region-start") != null) { 564 refinement(pageSequence.getStaticContent("xsl-region-start")); 565 } 566 if (pageSequence.getStaticContent("xsl-region-end") != null) { 567 refinement(pageSequence.getStaticContent("xsl-region-end")); 568 } 569 570 super.endPageSequence(pageSequence); 571 } 572 } 573
| Popular Tags
|