KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > render > AbstractRenderer


1 /*
2  * $Id: AbstractRenderer.java,v 1.4.2.10 2003/03/02 16:55:17 pietsch Exp $
3  * ============================================================================
4  * The Apache Software License, Version 1.1
5  * ============================================================================
6  *
7  * Copyright (C) 1999-2003 The Apache Software Foundation. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without modifica-
10  * tion, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice,
13  * this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  * this list of conditions and the following disclaimer in the documentation
17  * and/or other materials provided with the distribution.
18  *
19  * 3. The end-user documentation included with the redistribution, if any, must
20  * include the following acknowledgment: "This product includes software
21  * developed by the Apache Software Foundation (http://www.apache.org/)."
22  * Alternately, this acknowledgment may appear in the software itself, if
23  * and wherever such third-party acknowledgments normally appear.
24  *
25  * 4. The names "FOP" and "Apache Software Foundation" must not be used to
26  * endorse or promote products derived from this software without prior
27  * written permission. For written permission, please contact
28  * apache@apache.org.
29  *
30  * 5. Products derived from this software may not be called "Apache", nor may
31  * "Apache" appear in their name, without prior written permission of the
32  * Apache Software Foundation.
33  *
34  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
35  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
36  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
37  * APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
38  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
39  * DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
40  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
41  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
42  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44  * ============================================================================
45  *
46  * This software consists of voluntary contributions made by many individuals
47  * on behalf of the Apache Software Foundation and was originally created by
48  * James Tauber <jtauber@jtauber.com>. For more information on the Apache
49  * Software Foundation, please see <http://www.apache.org/>.
50  */

51 package org.apache.fop.render;
52
53 // FOP
54
import org.apache.fop.image.ImageArea;
55 import org.apache.fop.image.FopImage;
56 import org.apache.fop.image.FopImageException;
57 import org.apache.fop.fo.properties.*;
58 import org.apache.fop.layout.*;
59 import org.apache.fop.layout.inline.*;
60 import org.apache.fop.datatypes.*;
61
62 // Avalon
63
import org.apache.avalon.framework.logger.Logger;
64
65 // Java
66
import java.util.List JavaDoc;
67
68 /**
69  * Abstract base class for all renderers.
70  *
71  */

72 public abstract class AbstractRenderer implements Renderer {
73     protected Logger log;
74
75     /**
76      * the current vertical position in millipoints from bottom
77      */

78     protected int currentYPosition = 0;
79
80     /**
81      * the current horizontal position in millipoints from left
82      */

83     protected int currentXPosition = 0;
84
85     /**
86      * the horizontal position of the current area container
87      */

88     protected int currentAreaContainerXPosition = 0;
89
90     protected IDReferences idReferences;
91
92     public void setLogger(Logger logger) {
93         log = logger;
94     }
95
96     public void renderSpanArea(SpanArea area) {
97         List JavaDoc children = area.getChildren();
98         for (int i = 0; i < children.size(); i++) {
99             Box b = (Box)children.get(i);
100             b.render(this); // column areas
101
}
102
103     }
104
105     protected abstract void doFrame(Area area);
106
107     /**
108      * Renders an area's background.
109      * @param x the x position of the left edge in millipoints
110      * @param y the y position of top edge in millipoints
111      * @param w the width in millipoints
112      * @param h the height in millipoints
113      */

114     protected void doBackground(Area area, int x, int y, int w, int h) {
115         if (h == 0 || w == 0)
116             return;
117
118         BackgroundProps props = area.getBackground();
119         if (props == null)
120             return;
121
122         if (props.backColor.alpha() == 0) {
123             this.addFilledRect(x, y, w, -h, props.backColor);
124         }
125
126         // XXX: I'm ignoring area rotation here 8(
127
// is this taken care of for me elsewhere in the codebase?
128
if (props.backImage != null) {
129             int imgW;
130             int imgH;
131             try {
132             // XXX: do correct unit conversion here
133
imgW = props.backImage.getWidth() * 1000;
134             imgH = props.backImage.getHeight() * 1000;
135             }
136             catch (FopImageException fie) {
137             log.error("Error obtaining bg image width and height", fie);
138             return;
139             }
140
141             int dx = x;
142             int dy = y;
143             int endX = x + w;
144             int endY = y - h;
145             int clipW = w % imgW;
146             int clipH = h % imgH;
147
148             boolean repeatX = true;
149             boolean repeatY = true;
150             switch (props.backRepeat) {
151             case BackgroundRepeat.REPEAT:
152             break;
153
154             case BackgroundRepeat.REPEAT_X:
155             repeatY = false;
156             break;
157
158             case BackgroundRepeat.REPEAT_Y:
159             repeatX = false;
160             break;
161
162             case BackgroundRepeat.NO_REPEAT:
163             repeatX = false;
164             repeatY = false;
165             break;
166
167             case BackgroundRepeat.INHERIT:
168             // XXX: what to do here?
169
break;
170
171             default:
172             log.error("Ignoring invalid background-repeat property");
173             }
174
175             FontState fs = area.getFontState();
176
177             while (dy > endY) { // looping through rows
178
while (dx < endX) { // looping through cols
179
if (dx + imgW <= endX) {
180                 // no x clipping
181
if (dy - imgH >= endY) {
182                     // no x clipping, no y clipping
183
drawImageScaled(dx, dy, imgW, imgH,
184                             props.backImage, fs);
185                 }
186                 else {
187                     // no x clipping, y clipping
188
drawImageClipped(dx, dy,
189                              0, 0, imgW, clipH,
190                              props.backImage, fs);
191                 }
192                 }
193                 else {
194                 // x clipping
195
if (dy - imgH >= endY) {
196                     // x clipping, no y clipping
197
drawImageClipped(dx, dy,
198                              0, 0, clipW, imgH,
199                              props.backImage, fs);
200                 }
201
202                 else {
203                     // x clipping, y clipping
204
drawImageClipped(dx, dy,
205                              0, 0, clipW, clipH,
206                              props.backImage, fs);
207                 }
208                 }
209
210                 if (repeatX) {
211                 dx += imgW;
212                 }
213                 else {
214                 break;
215                 }
216             } // end looping through cols
217

218             dx = x;
219
220             if (repeatY) {
221                 dy -= imgH;
222             }
223             else {
224                 break;
225             }
226             } // end looping through rows
227
}
228     }
229
230     /**
231      * Add a filled rectangle to the current stream
232      * This default implementation calls addRect
233      * using the same color for fill and border.
234      *
235      * @param x the x position of left edge in millipoints
236      * @param y the y position of top edge in millipoints
237      * @param w the width in millipoints
238      * @param h the height in millipoints
239      * @param fill the fill color/gradient
240      */

241     protected abstract void addFilledRect(int x, int y, int w, int h,
242                                  ColorType col);
243
244     /**
245      * Renders an image, rendered at the image's intrinsic size.
246      * This by default calls drawImageScaled() with the image's
247      * intrinsic width and height, but implementations may
248      * override this method if it can provide a more efficient solution.
249      *
250      * @param x the x position of left edge in millipoints
251      * @param y the y position of top edge in millipoints
252      * @param image the image to be rendered
253      * @param fs the font state to use when rendering text
254      * in non-bitmapped images.
255      */

256     protected void drawImage(int x, int y, FopImage image, FontState fs) {
257         int w;
258         int h;
259         try {
260             // XXX: convert these units correctly
261
w = image.getWidth() * 1000;
262             h = image.getHeight() * 1000;
263         }
264         catch (FopImageException e) {
265             log.error("Failed to obtain the image width and height", e);
266             return;
267         }
268         drawImageScaled(x, y, w, h, image, fs);
269     }
270
271     /**
272      * Renders an image, scaling it to the given width and height.
273      * If the scaled width and height is the same intrinsic size
274      * of the image, the image is not scaled.
275      *
276      * @param x the x position of left edge in millipoints
277      * @param y the y position of top edge in millipoints
278      * @param w the width in millipoints
279      * @param h the height in millipoints
280      * @param image the image to be rendered
281      * @param fs the font state to use when rendering text
282      * in non-bitmapped images.
283      */

284     protected abstract void drawImageScaled(int x, int y, int w, int h,
285                         FopImage image,
286                         FontState fs);
287
288     /**
289      * Renders an image, clipping it as specified.
290      *
291      * @param x the x position of left edge in millipoints.
292      * @param y the y position of top edge in millipoints.
293      * @param clipX the left edge of the clip in millipoints
294      * @param clipY the top edge of the clip in millipoints
295      * @param clipW the clip width in millipoints
296      * @param clipH the clip height in millipoints
297      * @param fill the image to be rendered
298      * @param fs the font state to use when rendering text
299      * in non-bitmapped images.
300      */

301     protected abstract void drawImageClipped(int x, int y,
302                          int clipX, int clipY,
303                          int clipW, int clipH,
304                          FopImage image,
305                          FontState fs);
306
307     /**
308      * Render an image area.
309      *
310      * @param area the image area to render
311      */

312     public void renderImageArea(ImageArea area) {
313         // adapted from contribution by BoBoGi
314
int x = this.currentXPosition + area.getXOffset();
315         int y = this.currentYPosition;
316         int w = area.getContentWidth();
317         int h = area.getHeight();
318
319         this.currentYPosition -= h;
320
321         FopImage img = area.getImage();
322
323         if (img == null) {
324             log.error("Error while loading image: area.getImage() is null");
325         } else {
326             drawImageScaled(x, y, w, h, img, area.getFontState());
327         }
328
329         this.currentXPosition += w;
330     }
331
332     public void renderBodyAreaContainer(BodyAreaContainer area) {
333         int saveY = this.currentYPosition;
334         int saveX = this.currentAreaContainerXPosition;
335
336         if (area.getPosition() == Position.ABSOLUTE) {
337             // Y position is computed assuming positive Y axis, adjust for negative postscript one
338
this.currentYPosition = area.getYPosition();
339             this.currentAreaContainerXPosition = area.getXPosition();
340         } else if (area.getPosition() == Position.RELATIVE) {
341             this.currentYPosition -= area.getYPosition();
342             this.currentAreaContainerXPosition += area.getXPosition();
343         }
344
345         this.currentXPosition = this.currentAreaContainerXPosition;
346         int rx = this.currentAreaContainerXPosition;
347         int ry = this.currentYPosition;
348         // XXX: (mjg@recaldesign.com) I had to use getAllocationWidth()
349
// and getMaxHeight() as the content width and height are
350
// always 0. Is this supposed to be the case?
351
// IMHO, the bg should cover the entire area anyway, not
352
// just the parts with content, which makes this correct.
353
// Probably want to check this for the other region
354
// areas as well.
355
int w = area.getAllocationWidth();
356             int h = area.getMaxHeight();
357
358         doBackground(area, rx, ry, w, h);
359
360         // floats & footnotes stuff
361
renderAreaContainer(area.getBeforeFloatReferenceArea());
362         renderAreaContainer(area.getFootnoteReferenceArea());
363
364         // main reference area
365
List JavaDoc children = area.getMainReferenceArea().getChildren();
366         for (int i = 0; i < children.size(); i++) {
367             Box b = (Box)children.get(i);
368             b.render(this); // span areas
369
}
370
371         if (area.getPosition() != Position.STATIC) {
372             this.currentYPosition = saveY;
373             this.currentAreaContainerXPosition = saveX;
374         } else {
375             this.currentYPosition -= area.getHeight();
376         }
377     }
378
379     /**
380      * render region area container
381      *
382      * @param area the region area container to render
383      */

384     public void renderRegionAreaContainer(AreaContainer area) {
385         int saveY = this.currentYPosition;
386         int saveX = this.currentAreaContainerXPosition;
387
388         if (area.getPosition() == Position.ABSOLUTE) {
389             // Y position is computed assuming positive Y axis, adjust for negative postscript one
390
this.currentYPosition = area.getYPosition();
391             this.currentAreaContainerXPosition = area.getXPosition();
392         } else if (area.getPosition() == Position.RELATIVE) {
393             this.currentYPosition -= area.getYPosition();
394             this.currentAreaContainerXPosition += area.getXPosition();
395         }
396
397         this.currentXPosition = this.currentAreaContainerXPosition;
398         int rx = this.currentAreaContainerXPosition;
399         int ry = this.currentYPosition;
400         int w = area.getAllocationWidth();
401         int h = area.getMaxHeight();
402
403         doBackground(area, rx, ry, w, h);
404
405         List JavaDoc children = area.getChildren();
406         for (int i = 0; i < children.size(); i++) {
407             Box b = (Box)children.get(i);
408             b.render(this); // span areas
409
}
410
411         if (area.getPosition() != Position.STATIC) {
412             this.currentYPosition = saveY;
413             this.currentAreaContainerXPosition = saveX;
414         } else {
415             this.currentYPosition -= area.getHeight();
416         }
417     }
418
419     /**
420      * render area container
421      *
422      * @param area the area container to render
423      */

424     public void renderAreaContainer(AreaContainer area) {
425
426         int saveY = this.currentYPosition;
427         int saveX = this.currentAreaContainerXPosition;
428
429         if (area.getPosition() == Position.ABSOLUTE) {
430             // XPosition and YPosition give the content rectangle position
431
this.currentYPosition = area.getYPosition();
432             this.currentAreaContainerXPosition = area.getXPosition();
433         } else if (area.getPosition() == Position.RELATIVE) {
434             this.currentYPosition -= area.getYPosition();
435             this.currentAreaContainerXPosition += area.getXPosition();
436         } else if (area.getPosition() == Position.STATIC) {
437             this.currentYPosition -= area.getPaddingTop()
438                                      + area.getBorderTopWidth();
439             /*
440              * this.currentAreaContainerXPosition +=
441              * area.getPaddingLeft() + area.getBorderLeftWidth();
442              */

443         }
444
445         this.currentXPosition = this.currentAreaContainerXPosition;
446         doFrame(area);
447
448         List JavaDoc children = area.getChildren();
449         for (int i = 0; i < children.size(); i++) {
450             Box b = (Box)children.get(i);
451             b.render(this);
452         }
453         // Restore previous origin
454
this.currentYPosition = saveY;
455         this.currentAreaContainerXPosition = saveX;
456         if (area.getPosition() == Position.STATIC) {
457             this.currentYPosition -= area.getHeight();
458         }
459
460         /**
461          * **
462          * if (area.getPosition() != Position.STATIC) {
463          * this.currentYPosition = saveY;
464          * this.currentAreaContainerXPosition = saveX;
465          * } else
466          * this.currentYPosition -= area.getHeight();
467          * **
468          */

469     }
470
471     /**
472      * render block area
473      *
474      * @param area the block area to render
475      */

476     public void renderBlockArea(BlockArea area) {
477         // KLease: Temporary test to fix block positioning
478
// Offset ypos by padding and border widths
479
this.currentYPosition -= (area.getPaddingTop()
480                                   + area.getBorderTopWidth());
481         doFrame(area);
482         List JavaDoc children = area.getChildren();
483         for (int i = 0; i < children.size(); i++) {
484             Box b = (Box)children.get(i);
485             b.render(this);
486         }
487         this.currentYPosition -= (area.getPaddingBottom()
488                                   + area.getBorderBottomWidth());
489     }
490
491     /**
492      * render line area
493      *
494      * @param area area to render
495      */

496     public void renderLineArea(LineArea area) {
497         int rx = this.currentAreaContainerXPosition + area.getStartIndent();
498         int ry = this.currentYPosition;
499         int w = area.getContentWidth();
500         int h = area.getHeight();
501
502         this.currentYPosition -= area.getPlacementOffset();
503         this.currentXPosition = rx;
504
505         int bl = this.currentYPosition;
506
507         List JavaDoc children = area.getChildren();
508         for (int i = 0; i < children.size(); i++) {
509             Box b = (Box)children.get(i);
510             if (b instanceof InlineArea) {
511                 InlineArea ia = (InlineArea)b;
512                 this.currentYPosition = ry - ia.getYOffset();
513             } else {
514                 this.currentYPosition = ry - area.getPlacementOffset();
515             }
516             b.render(this);
517         }
518
519         this.currentYPosition = ry - h;
520         this.currentXPosition = rx;
521     }
522
523     /**
524      * render region areas
525      *
526      * @param page the page whose regions to render
527      */

528     public void renderRegions(Page page) {
529         page.getBody().render(this);
530         if (page.getBefore() != null)
531             page.getBefore().render(this);
532         if (page.getAfter() != null)
533             page.getAfter().render(this);
534         if (page.getStart() != null)
535             page.getStart().render(this);
536         if (page.getEnd() != null)
537             page.getEnd().render(this);
538     }
539
540     public IDReferences getIDReferences() {
541         return idReferences;
542     }
543 }
544
Popular Tags