1 17 18 19 20 package org.apache.fop.render; 21 22 import java.awt.Color ; 23 import java.awt.Rectangle ; 24 import java.awt.geom.Rectangle2D ; 25 import java.util.List ; 26 import java.util.Map ; 27 28 import org.apache.fop.area.Area; 29 import org.apache.fop.area.Block; 30 import org.apache.fop.area.BlockViewport; 31 import org.apache.fop.area.CTM; 32 import org.apache.fop.area.RegionViewport; 33 import org.apache.fop.area.Trait; 34 import org.apache.fop.area.inline.ForeignObject; 35 import org.apache.fop.area.inline.InlineArea; 36 import org.apache.fop.area.inline.Viewport; 37 import org.apache.fop.fo.Constants; 38 import org.apache.fop.fonts.FontMetrics; 39 import org.apache.fop.image.FopImage; 40 import org.apache.fop.traits.BorderProps; 41 import org.w3c.dom.Document ; 42 43 47 public abstract class AbstractPathOrientedRenderer extends PrintRenderer { 48 49 57 protected void handleBlockTraits(Block block) { 58 int borderPaddingStart = block.getBorderAndPaddingWidthStart(); 59 int borderPaddingBefore = block.getBorderAndPaddingWidthBefore(); 60 61 float startx = currentIPPosition / 1000f; 62 float starty = currentBPPosition / 1000f; 63 float width = block.getIPD() / 1000f; 64 float height = block.getBPD() / 1000f; 65 66 71 startx += block.getStartIndent() / 1000f; 72 startx -= block.getBorderAndPaddingWidthStart() / 1000f; 73 74 width += borderPaddingStart / 1000f; 75 width += block.getBorderAndPaddingWidthEnd() / 1000f; 76 height += borderPaddingBefore / 1000f; 77 height += block.getBorderAndPaddingWidthAfter() / 1000f; 78 79 drawBackAndBorders(block, startx, starty, 80 width, height); 81 } 82 83 89 protected void handleRegionTraits(RegionViewport region) { 90 Rectangle2D viewArea = region.getViewArea(); 91 float startx = (float)(viewArea.getX() / 1000f); 92 float starty = (float)(viewArea.getY() / 1000f); 93 float width = (float)(viewArea.getWidth() / 1000f); 94 float height = (float)(viewArea.getHeight() / 1000f); 95 96 if (region.getRegionReference().getRegionClass() == FO_REGION_BODY) { 97 currentBPPosition = region.getBorderAndPaddingWidthBefore(); 98 currentIPPosition = region.getBorderAndPaddingWidthStart(); 99 } 100 drawBackAndBorders(region, startx, starty, width, height); 101 } 102 103 104 115 protected void drawBackAndBorders(Area area, 116 float startx, float starty, 117 float width, float height) { 118 120 BorderProps bpsBefore = (BorderProps)area.getTrait(Trait.BORDER_BEFORE); 121 BorderProps bpsAfter = (BorderProps)area.getTrait(Trait.BORDER_AFTER); 122 BorderProps bpsStart = (BorderProps)area.getTrait(Trait.BORDER_START); 123 BorderProps bpsEnd = (BorderProps)area.getTrait(Trait.BORDER_END); 124 125 Trait.Background back; 126 back = (Trait.Background)area.getTrait(Trait.BACKGROUND); 127 if (back != null) { 128 endTextObject(); 129 130 float sx = startx; 132 float sy = starty; 133 float paddRectWidth = width; 134 float paddRectHeight = height; 135 if (bpsStart != null) { 136 sx += bpsStart.width / 1000f; 137 paddRectWidth -= bpsStart.width / 1000f; 138 } 139 if (bpsBefore != null) { 140 sy += bpsBefore.width / 1000f; 141 paddRectHeight -= bpsBefore.width / 1000f; 142 } 143 if (bpsEnd != null) { 144 paddRectWidth -= bpsEnd.width / 1000f; 145 } 146 if (bpsAfter != null) { 147 paddRectHeight -= bpsAfter.width / 1000f; 148 } 149 150 if (back.getColor() != null) { 151 updateColor(back.getColor(), true); 152 fillRect(sx, sy, paddRectWidth, paddRectHeight); 153 } 154 if (back.getFopImage() != null) { 155 FopImage fopimage = back.getFopImage(); 156 if (fopimage != null && fopimage.load(FopImage.DIMENSIONS)) { 157 saveGraphicsState(); 158 clipRect(sx, sy, paddRectWidth, paddRectHeight); 159 int horzCount = (int)((paddRectWidth 160 * 1000 / fopimage.getIntrinsicWidth()) + 1.0f); 161 int vertCount = (int)((paddRectHeight 162 * 1000 / fopimage.getIntrinsicHeight()) + 1.0f); 163 if (back.getRepeat() == EN_NOREPEAT) { 164 horzCount = 1; 165 vertCount = 1; 166 } else if (back.getRepeat() == EN_REPEATX) { 167 vertCount = 1; 168 } else if (back.getRepeat() == EN_REPEATY) { 169 horzCount = 1; 170 } 171 sx *= 1000; 173 sy *= 1000; 174 if (horzCount == 1) { 175 sx += back.getHoriz(); 176 } 177 if (vertCount == 1) { 178 sy += back.getVertical(); 179 } 180 for (int x = 0; x < horzCount; x++) { 181 for (int y = 0; y < vertCount; y++) { 182 Rectangle2D pos; 184 pos = new Rectangle2D.Float (sx - currentIPPosition 186 + (x * fopimage.getIntrinsicWidth()), 187 sy - currentBPPosition 188 + (y * fopimage.getIntrinsicHeight()), 189 fopimage.getIntrinsicWidth(), 190 fopimage.getIntrinsicHeight()); 191 drawImage(back.getURL(), pos); 192 } 193 } 194 195 restoreGraphicsState(); 196 } else { 197 log.warn("Can't find background image: " + back.getURL()); 198 } 199 } 200 } 201 202 Rectangle2D.Float borderRect = new Rectangle2D.Float (startx, starty, width, height); 203 drawBorders(borderRect, bpsBefore, bpsAfter, bpsStart, bpsEnd); 204 } 205 206 214 protected void drawBorders(Rectangle2D.Float borderRect, 215 BorderProps bpsBefore, BorderProps bpsAfter, BorderProps bpsStart, BorderProps bpsEnd) { 216 float startx = borderRect.x; 217 float starty = borderRect.y; 218 float width = borderRect.width; 219 float height = borderRect.height; 220 boolean[] b = new boolean[] { 221 (bpsBefore != null), (bpsEnd != null), 222 (bpsAfter != null), (bpsStart != null)}; 223 if (!b[0] && !b[1] && !b[2] && !b[3]) { 224 return; 225 } 226 float[] bw = new float[] { 227 (b[0] ? bpsBefore.width / 1000f : 0.0f), 228 (b[1] ? bpsEnd.width / 1000f : 0.0f), 229 (b[2] ? bpsAfter.width / 1000f : 0.0f), 230 (b[3] ? bpsStart.width / 1000f : 0.0f)}; 231 float[] clipw = new float[] { 232 BorderProps.getClippedWidth(bpsBefore) / 1000f, 233 BorderProps.getClippedWidth(bpsEnd) / 1000f, 234 BorderProps.getClippedWidth(bpsAfter) / 1000f, 235 BorderProps.getClippedWidth(bpsStart) / 1000f}; 236 starty += clipw[0]; 237 height -= clipw[0]; 238 height -= clipw[2]; 239 startx += clipw[3]; 240 width -= clipw[3]; 241 width -= clipw[1]; 242 243 boolean[] slant = new boolean[] { 244 (b[3] && b[0]), (b[0] && b[1]), (b[1] && b[2]), (b[2] && b[3])}; 245 if (bpsBefore != null) { 246 endTextObject(); 247 248 float sx1 = startx; 249 float sx2 = (slant[0] ? sx1 + bw[3] - clipw[3] : sx1); 250 float ex1 = startx + width; 251 float ex2 = (slant[1] ? ex1 - bw[1] + clipw[1] : ex1); 252 float outery = starty - clipw[0]; 253 float clipy = outery + clipw[0]; 254 float innery = outery + bw[0]; 255 256 saveGraphicsState(); 257 moveTo(sx1, clipy); 258 float sx1a = sx1; 259 float ex1a = ex1; 260 if (bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { 261 if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) { 262 sx1a -= clipw[3]; 263 } 264 if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { 265 ex1a += clipw[1]; 266 } 267 lineTo(sx1a, outery); 268 lineTo(ex1a, outery); 269 } 270 lineTo(ex1, clipy); 271 lineTo(ex2, innery); 272 lineTo(sx2, innery); 273 closePath(); 274 clip(); 275 drawBorderLine(sx1a, outery, ex1a, innery, true, true, 276 bpsBefore.style, bpsBefore.color); 277 restoreGraphicsState(); 278 } 279 if (bpsEnd != null) { 280 endTextObject(); 281 282 float sy1 = starty; 283 float sy2 = (slant[1] ? sy1 + bw[0] - clipw[0] : sy1); 284 float ey1 = starty + height; 285 float ey2 = (slant[2] ? ey1 - bw[2] + clipw[2] : ey1); 286 float outerx = startx + width + clipw[1]; 287 float clipx = outerx - clipw[1]; 288 float innerx = outerx - bw[1]; 289 290 saveGraphicsState(); 291 moveTo(clipx, sy1); 292 float sy1a = sy1; 293 float ey1a = ey1; 294 if (bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { 295 if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { 296 sy1a -= clipw[0]; 297 } 298 if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { 299 ey1a += clipw[2]; 300 } 301 lineTo(outerx, sy1a); 302 lineTo(outerx, ey1a); 303 } 304 lineTo(clipx, ey1); 305 lineTo(innerx, ey2); 306 lineTo(innerx, sy2); 307 closePath(); 308 clip(); 309 drawBorderLine(innerx, sy1a, outerx, ey1a, false, false, bpsEnd.style, bpsEnd.color); 310 restoreGraphicsState(); 311 } 312 if (bpsAfter != null) { 313 endTextObject(); 314 315 float sx1 = startx; 316 float sx2 = (slant[3] ? sx1 + bw[3] - clipw[3] : sx1); 317 float ex1 = startx + width; 318 float ex2 = (slant[2] ? ex1 - bw[1] + clipw[1] : ex1); 319 float outery = starty + height + clipw[2]; 320 float clipy = outery - clipw[2]; 321 float innery = outery - bw[2]; 322 323 saveGraphicsState(); 324 moveTo(ex1, clipy); 325 float sx1a = sx1; 326 float ex1a = ex1; 327 if (bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { 328 if (bpsStart != null && bpsStart.mode == BorderProps.COLLAPSE_OUTER) { 329 sx1a -= clipw[3]; 330 } 331 if (bpsEnd != null && bpsEnd.mode == BorderProps.COLLAPSE_OUTER) { 332 ex1a += clipw[1]; 333 } 334 lineTo(ex1a, outery); 335 lineTo(sx1a, outery); 336 } 337 lineTo(sx1, clipy); 338 lineTo(sx2, innery); 339 lineTo(ex2, innery); 340 closePath(); 341 clip(); 342 drawBorderLine(sx1a, innery, ex1a, outery, true, false, bpsAfter.style, bpsAfter.color); 343 restoreGraphicsState(); 344 } 345 if (bpsStart != null) { 346 endTextObject(); 347 348 float sy1 = starty; 349 float sy2 = (slant[0] ? sy1 + bw[0] - clipw[0] : sy1); 350 float ey1 = sy1 + height; 351 float ey2 = (slant[3] ? ey1 - bw[2] + clipw[2] : ey1); 352 float outerx = startx - clipw[3]; 353 float clipx = outerx + clipw[3]; 354 float innerx = outerx + bw[3]; 355 356 saveGraphicsState(); 357 moveTo(clipx, ey1); 358 float sy1a = sy1; 359 float ey1a = ey1; 360 if (bpsStart.mode == BorderProps.COLLAPSE_OUTER) { 361 if (bpsBefore != null && bpsBefore.mode == BorderProps.COLLAPSE_OUTER) { 362 sy1a -= clipw[0]; 363 } 364 if (bpsAfter != null && bpsAfter.mode == BorderProps.COLLAPSE_OUTER) { 365 ey1a += clipw[2]; 366 } 367 lineTo(outerx, ey1a); 368 lineTo(outerx, sy1a); 369 } 370 lineTo(clipx, sy1); 371 lineTo(innerx, sy2); 372 lineTo(innerx, ey2); 373 closePath(); 374 clip(); 375 drawBorderLine(outerx, sy1a, innerx, ey1a, false, true, bpsStart.style, bpsStart.color); 376 restoreGraphicsState(); 377 } 378 } 379 380 386 protected void renderInlineAreaBackAndBorders(InlineArea area) { 387 float x = currentIPPosition / 1000f; 388 float y = (currentBPPosition + area.getOffset()) / 1000f; 389 float width = area.getIPD() / 1000f; 390 float height = area.getBPD() / 1000f; 391 float borderPaddingStart = area.getBorderAndPaddingWidthStart() / 1000f; 392 float borderPaddingBefore = area.getBorderAndPaddingWidthBefore() / 1000f; 393 float bpwidth = borderPaddingStart 394 + (area.getBorderAndPaddingWidthEnd() / 1000f); 395 float bpheight = borderPaddingBefore 396 + (area.getBorderAndPaddingWidthAfter() / 1000f); 397 398 if (height != 0.0f || bpheight != 0.0f && bpwidth != 0.0f) { 399 drawBackAndBorders(area, x, y - borderPaddingBefore 400 , width + bpwidth 401 , height + bpheight); 402 } 403 404 } 405 406 409 protected void renderBlockViewport(BlockViewport bv, List children) { 410 412 int saveIP = currentIPPosition; 414 int saveBP = currentBPPosition; 415 417 CTM ctm = bv.getCTM(); 418 int borderPaddingStart = bv.getBorderAndPaddingWidthStart(); 419 int borderPaddingBefore = bv.getBorderAndPaddingWidthBefore(); 420 float x, y; 421 x = (float)(bv.getXOffset() + containingIPPosition) / 1000f; 422 y = (float)(bv.getYOffset() + containingBPPosition) / 1000f; 423 float width = (float)bv.getIPD() / 1000f; 425 float height = (float)bv.getBPD() / 1000f; 426 427 428 if (bv.getPositioning() == Block.ABSOLUTE 429 || bv.getPositioning() == Block.FIXED) { 430 431 currentIPPosition = bv.getXOffset(); 432 currentBPPosition = bv.getYOffset(); 433 434 List breakOutList = null; 438 if (bv.getPositioning() == Block.FIXED) { 439 breakOutList = breakOutOfStateStack(); 440 } 441 442 CTM tempctm = new CTM(containingIPPosition, containingBPPosition); 443 ctm = tempctm.multiply(ctm); 444 445 x += bv.getSpaceStart() / 1000f; 447 currentIPPosition += bv.getSpaceStart(); 448 449 y += bv.getSpaceBefore() / 1000f; 450 currentBPPosition += bv.getSpaceBefore(); 451 452 float bpwidth = (borderPaddingStart + bv.getBorderAndPaddingWidthEnd()) / 1000f; 453 float bpheight = (borderPaddingBefore + bv.getBorderAndPaddingWidthAfter()) / 1000f; 454 455 drawBackAndBorders(bv, x, y, width + bpwidth, height + bpheight); 456 457 currentIPPosition += borderPaddingStart; 459 currentBPPosition += borderPaddingBefore; 460 461 Rectangle2D clippingRect = null; 462 if (bv.getClip()) { 463 clippingRect = new Rectangle (currentIPPosition, currentBPPosition, 464 bv.getIPD(), bv.getBPD()); 465 } 466 467 startVParea(ctm, clippingRect); 468 currentIPPosition = 0; 469 currentBPPosition = 0; 470 renderBlocks(bv, children); 471 endVParea(); 472 473 if (breakOutList != null) { 474 restoreStateStackAfterBreakOut(breakOutList); 475 } 476 477 currentIPPosition = saveIP; 478 currentBPPosition = saveBP; 479 } else { 480 481 currentBPPosition += bv.getSpaceBefore(); 482 483 handleBlockTraits(bv); 485 486 currentIPPosition += bv.getStartIndent(); 488 489 CTM tempctm = new CTM(containingIPPosition, currentBPPosition); 490 ctm = tempctm.multiply(ctm); 491 492 currentBPPosition += borderPaddingBefore; 494 495 Rectangle2D clippingRect = null; 496 if (bv.getClip()) { 497 clippingRect = new Rectangle (currentIPPosition, currentBPPosition, 498 bv.getIPD(), bv.getBPD()); 499 } 500 501 startVParea(ctm, clippingRect); 502 currentIPPosition = 0; 503 currentBPPosition = 0; 504 renderBlocks(bv, children); 505 endVParea(); 506 507 currentIPPosition = saveIP; 508 currentBPPosition = saveBP; 509 510 currentBPPosition += (int)(bv.getAllocBPD()); 511 } 512 } 514 515 520 public void renderViewport(Viewport viewport) { 521 522 float x = currentIPPosition / 1000f; 523 float y = (currentBPPosition + viewport.getOffset()) / 1000f; 524 float width = viewport.getIPD() / 1000f; 525 float height = viewport.getBPD() / 1000f; 526 float borderPaddingStart = viewport.getBorderAndPaddingWidthStart() / 1000f; 528 float borderPaddingBefore = viewport.getBorderAndPaddingWidthBefore() / 1000f; 529 float bpwidth = borderPaddingStart 530 + (viewport.getBorderAndPaddingWidthEnd() / 1000f); 531 float bpheight = borderPaddingBefore 532 + (viewport.getBorderAndPaddingWidthAfter() / 1000f); 533 534 drawBackAndBorders(viewport, x, y, width + bpwidth, height + bpheight); 535 536 if (viewport.getClip()) { 537 saveGraphicsState(); 538 539 clipRect(x + borderPaddingStart, y + borderPaddingBefore, width, height); 540 } 541 super.renderViewport(viewport); 542 543 if (viewport.getClip()) { 544 restoreGraphicsState(); 545 } 546 } 547 548 552 protected abstract void restoreStateStackAfterBreakOut(List breakOutList); 553 554 558 protected abstract List breakOutOfStateStack(); 559 560 561 protected abstract void saveGraphicsState(); 562 563 564 protected abstract void restoreGraphicsState(); 565 566 567 protected abstract void beginTextObject(); 568 569 570 protected abstract void endTextObject(); 571 572 580 protected void renderTextDecoration(FontMetrics fm, int fontsize, InlineArea inline, 581 int baseline, int startx) { 582 boolean hasTextDeco = inline.hasUnderline() 583 || inline.hasOverline() 584 || inline.hasLineThrough(); 585 if (hasTextDeco) { 586 endTextObject(); 587 float descender = fm.getDescender(fontsize) / 1000f; 588 float capHeight = fm.getCapHeight(fontsize) / 1000f; 589 float halfLineWidth = (descender / -8f) / 2f; 590 float endx = (startx + inline.getIPD()) / 1000f; 591 if (inline.hasUnderline()) { 592 Color ct = (Color ) inline.getTrait(Trait.UNDERLINE_COLOR); 593 float y = baseline - descender / 2f; 594 drawBorderLine(startx / 1000f, (y - halfLineWidth) / 1000f, 595 endx, (y + halfLineWidth) / 1000f, 596 true, true, Constants.EN_SOLID, ct); 597 } 598 if (inline.hasOverline()) { 599 Color ct = (Color ) inline.getTrait(Trait.OVERLINE_COLOR); 600 float y = (float)(baseline - (1.1 * capHeight)); 601 drawBorderLine(startx / 1000f, (y - halfLineWidth) / 1000f, 602 endx, (y + halfLineWidth) / 1000f, 603 true, true, Constants.EN_SOLID, ct); 604 } 605 if (inline.hasLineThrough()) { 606 Color ct = (Color ) inline.getTrait(Trait.LINETHROUGH_COLOR); 607 float y = (float)(baseline - (0.45 * capHeight)); 608 drawBorderLine(startx / 1000f, (y - halfLineWidth) / 1000f, 609 endx, (y + halfLineWidth) / 1000f, 610 true, true, Constants.EN_SOLID, ct); 611 } 612 } 613 } 614 615 616 protected abstract void clip(); 617 618 625 protected abstract void clipRect(float x, float y, float width, float height); 626 627 632 protected abstract void moveTo(float x, float y); 633 634 640 protected abstract void lineTo(float x, float y); 641 642 646 protected abstract void closePath(); 647 648 655 protected abstract void fillRect(float x, float y, float width, float height); 656 657 662 protected abstract void updateColor(Color col, boolean fill); 663 664 670 protected abstract void drawImage(String url, Rectangle2D pos, Map foreignAttributes); 671 672 677 protected final void drawImage(String url, Rectangle2D pos) { 678 drawImage(url, pos, null); 679 } 680 681 693 protected abstract void drawBorderLine(float x1, float y1, float x2, float y2, 694 boolean horz, boolean startOrBefore, int style, Color col); 695 696 699 public void renderForeignObject(ForeignObject fo, Rectangle2D pos) { 700 endTextObject(); 701 Document doc = fo.getDocument(); 702 String ns = fo.getNameSpace(); 703 renderDocument(doc, ns, pos, fo.getForeignAttributes()); 704 } 705 706 } 707 | Popular Tags |