KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > java > swing > plaf > gtk > PixmapEngine


1 /*
2  * @(#)PixmapEngine.java 1.14 03/12/19
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7 package com.sun.java.swing.plaf.gtk;
8
9 import javax.swing.plaf.synth.*;
10
11 import java.awt.*;
12 import java.security.AccessController JavaDoc;
13 import java.util.*;
14 import javax.swing.*;
15 import sun.security.action.GetPropertyAction;
16
17 /**
18  * GTKEngine implementation that renders using images. The images to render
19  * are dictated by the <code>PixmapStyle.Info</code>.
20  *
21  * @version 1.14, 12/19/03
22  * @author Scott Violet
23  */

24 class PixmapEngine extends GTKEngine implements GTKConstants {
25     /**
26      * By default we don't use smooth scaling as it is currently not optimized.
27      */

28     private static final Object JavaDoc RENDERING_HINT;
29
30     private int _clipX1;
31     private int _clipX2;
32     private int _clipY1;
33     private int _clipY2;
34
35     static {
36         if ("true".equals((String JavaDoc)AccessController.doPrivileged(
37                    new GetPropertyAction("swing.pixmap.smoothScaling")))) {
38             RENDERING_HINT = RenderingHints.VALUE_INTERPOLATION_BILINEAR;
39         }
40         else {
41             RENDERING_HINT = null;
42         }
43     }
44
45     public void paintSlider(SynthContext context, Graphics g, int state,
46                            int shadowType, String JavaDoc info,
47                            int x, int y, int w, int h, int orientation) {
48         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
49                          getInfo("SLIDER", info,state, shadowType, orientation,
50                                  UNDEFINED, UNDEFINED), true)) {
51             super.paintSlider(context, g, state, shadowType, info,
52                               x, y, w, h, orientation);
53         }
54     }
55
56     public void paintHline(SynthContext context, Graphics g, int state,
57                            String JavaDoc info, int x, int y, int w, int h) {
58         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
59                          getInfo("HLINE", info, state, UNDEFINED, UNDEFINED,
60                          UNDEFINED, UNDEFINED), true)) {
61             super.paintHline(context, g, state, info, x, y, w, h);
62         }
63     }
64
65     public void paintVline(SynthContext context, Graphics g, int state,
66                            String JavaDoc info, int x, int y, int w, int h) {
67         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
68                          getInfo("VLINE", info, state, UNDEFINED, UNDEFINED,
69                                  UNDEFINED, UNDEFINED), true)) {
70             super.paintVline(context, g, state, info, x, y, w, h);
71         }
72     }
73
74     public void paintArrow(SynthContext context, Graphics g, int state,
75                            int shadowType, int direction, String JavaDoc info,
76                            int x, int y, int w, int h) {
77         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
78                          getInfo("ARROW", info, state, shadowType, UNDEFINED,
79                          UNDEFINED, direction), true)) {
80             super.paintArrow(context, g, state, shadowType, direction, info,
81                              x, y, w, h);
82         }
83     }
84
85     public void paintBox(SynthContext context, Graphics g, int state,
86                          int shadowType, String JavaDoc info, int x, int y,
87                          int w, int h) {
88         int orientation;
89         Region id = context.getRegion();
90         if (id == Region.SCROLL_BAR) {
91             if (((JScrollBar)context.getComponent()).getOrientation() ==
92                                      SwingConstants.HORIZONTAL) {
93                 orientation = GTKConstants.HORIZONTAL;
94             }
95             else {
96                 orientation = GTKConstants.VERTICAL;
97             }
98         }
99         else if (id == Region.SLIDER_TRACK) {
100             if (((JSlider)context.getComponent()).getOrientation() ==
101                                      SwingConstants.HORIZONTAL) {
102                 orientation = GTKConstants.HORIZONTAL;
103             }
104             else {
105                 orientation = GTKConstants.VERTICAL;
106             }
107         }
108         else {
109             orientation = UNDEFINED;
110         }
111         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
112                          getInfo("BOX", info, state, shadowType, orientation,
113                                  UNDEFINED, UNDEFINED), true)) {
114             super.paintBox(context, g, state, shadowType, info, x, y, w, h);
115         }
116     }
117
118     public void paintBoxGap(SynthContext context, Graphics g, int state,
119                             int shadow, String JavaDoc key, int x, int y,
120                             int w, int h, int gapSide, int gapStart,
121                             int gapSize) {
122         PixmapStyle.Info info = ((PixmapStyle)context.getStyle()).getInfo(
123               "BOX_GAP", key, state, shadow, UNDEFINED, gapSide, UNDEFINED);
124
125         if (info != null) {
126             // Yes, this appears to paint before the gap does.
127
paintPixmap(g, x, y, w, h, info, true);
128
129             // Determine the size of the opposite axis of the gap.
130
int size = 0;
131             Image startImage = info.getGapStartImage();
132             Image image = info.getGapImage();
133             Image endImage = info.getGapEndImage();
134             if (gapSide == LEFT || gapSide == RIGHT) {
135                 if (startImage != null) {
136                     size = startImage.getWidth(null);
137                 }
138                 else if (image != null) {
139                     size = image.getWidth(null);
140                 }
141                 else if (endImage != null) {
142                     size = endImage.getWidth(null);
143                 }
144             }
145             else {
146                 if (startImage != null) {
147                     size = startImage.getHeight(null);
148                 }
149                 else if (image != null) {
150                     size = image.getHeight(null);
151                 }
152                 else if (endImage != null) {
153                     size = endImage.getHeight(null);
154                 }
155             }
156             if (size <= 0) {
157                 // No matching images.
158
return;
159             }
160             paintGapImage(g, x, y, w, h, startImage, info.getGapStartInsets(),
161                           gapSide, size, 0, gapStart);
162             paintGapImage(g, x, y, w, h, image, info.getGapInsets(), gapSide,
163                           size, gapStart, gapSize);
164             paintGapImage(g, x, y, w, h, endImage, info.getGapEndInsets(),
165                           gapSide, size, gapStart + gapSize,
166                           Integer.MAX_VALUE);
167         }
168         else {
169             super.paintBoxGap(context, g, state, shadow, key, x, y, w, h,
170                               gapSide, gapStart,gapSize);
171         }
172     }
173
174     public void paintHandle(SynthContext context, Graphics g, int paintState,
175                             int shadowType, String JavaDoc info, int x, int y,
176                             int w, int h, int orientation) {
177         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
178                          getInfo("HANDLE", info, paintState, shadowType,
179                                  orientation, UNDEFINED, UNDEFINED), true)) {
180             super.paintHandle(context, g, paintState, shadowType, info, x, y,
181                               w, h, orientation);
182         }
183     }
184
185     public void paintOption(SynthContext context, Graphics g, int paintState,
186                             int shadowType, String JavaDoc info, int x, int y,
187                             int w, int h) {
188         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
189                          getInfo("OPTION", info, paintState, shadowType,
190                                  UNDEFINED, UNDEFINED, UNDEFINED), true)) {
191             super.paintOption(context, g, paintState, shadowType, info, x, y,
192                               w, h);
193         }
194     }
195
196     public void paintFocus(SynthContext context, Graphics g, int state,
197                            String JavaDoc key, int x, int y, int w, int h) {
198         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
199                          getInfo( "FOCUS", key, state, UNDEFINED, UNDEFINED,
200                          UNDEFINED, UNDEFINED), true)) {
201             super.paintFocus(context, g, state, key, x, y, w, h);
202         }
203     }
204
205     public void paintShadow(SynthContext context, Graphics g, int state,
206                             int shadowType, String JavaDoc info, int x, int y,
207                             int w, int h) {
208         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
209                          getInfo("SHADOW", info, state, shadowType, UNDEFINED,
210                                  UNDEFINED, UNDEFINED), false)) {
211             super.paintShadow(context, g, state, shadowType, info, x, y, w, h);
212         }
213     }
214
215     public void paintExpander(SynthContext context, Graphics g, int state,
216                               int expanderStyle, String JavaDoc info, int x,
217                               int y, int w, int h) {
218         // It does not appear that there is a way to override this.
219
super.paintExpander(context, g, state, expanderStyle, info, x, y, w,h);
220     }
221
222     public void paintCheck(SynthContext context, Graphics g, int state,
223                            int shadowType, String JavaDoc info, int x, int y,
224                            int w, int h) {
225         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
226                         getInfo("CHECK", info, state, shadowType, UNDEFINED,
227                                 UNDEFINED, UNDEFINED), true)) {
228             super.paintCheck(context, g, state, shadowType, info, x, y, w, h);
229         }
230     }
231
232     public void paintExtension(SynthContext context, Graphics g, int state,
233                                int shadowType, String JavaDoc info, int x, int y,
234                                int w, int h, int placement, int tabIndex) {
235         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
236                          getInfo("EXTENSION", info, state, shadowType,
237                                  UNDEFINED, placement, UNDEFINED), true)) {
238             super.paintExtension(context, g, state, shadowType, info, x, y,
239                                  w, h, placement, tabIndex);
240         }
241     }
242
243     public void paintFlatBox(SynthContext context, Graphics g, int state,
244                              String JavaDoc key, int x, int y, int w, int h) {
245         if (!paintPixmap(g, x, y, w, h, ((PixmapStyle)context.getStyle()).
246                          getInfo("FLAT_BOX", key, state, UNDEFINED, UNDEFINED,
247                                  UNDEFINED, UNDEFINED), true)) {
248             super.paintFlatBox(context, g, state, key, x, y, w, h);
249         }
250     }
251
252
253     /**
254      * Paints a gap image. This renders the image into a portion of
255      * the passed in region that is dictated
256      * by the <code>gapSide</code> and <code>size</code> arguments. For
257      * example, if <code>gapSide</code> is <code>GTKConstants.TOP</code>,
258      * this will render the image into the space:
259      * <table>
260      * <tr><td>x origin<td> <code>x</code> + <code>gapStart</code>
261      * <tr><td>y origin<td> <code>y</code>
262      * <tr><td>width<td> <code>gapSize</code>
263      * <tr><td>height<td> <code>size</code>
264      * </table>
265      *
266      * @param g Graphics object to paint to
267      * @param x X origin
268      * @param y Y origin
269      * @param w Width to draw to
270      * @param h Height to draw to
271      * @param image Image to paint
272      * @param insets Insets dicatating fixed portion and scaled portion of
273      * the image.
274      * @param gapSide Side the gap is on, one of GTKConstants.LEFT,
275      * GTKConstants.RIGHT, GTKConstants.TOP or GTKConstants.BOTTOM
276      * @param size Size of the gap, either width or height, dependant upon
277      * gapSide
278      * @param gapStart Starting location of the gap. The axis the gap is
279      * on is dictated by the gapSide
280      * @param gapSize size of the gap
281      */

282     private void paintGapImage(Graphics g, int x, int y, int w, int h,
283                                Image image, Insets insets, int gapSide,
284                                int size, int gapStart, int gapSize) {
285         if (image != null && gapSize > 0) {
286             switch(gapSide) {
287             case LEFT:
288                 paintImage(g, x, y + gapStart, Math.min(w, size),
289                       Math.min(h - y - gapStart, gapSize), image,insets, true,
290                            false, true);
291                 break;
292             case RIGHT:
293                 paintImage(g, x + w - Math.min(w, size),
294                            y + gapStart, Math.min(w, size),
295                            Math.min(h - y - gapStart, gapSize), image,
296                            insets, true, false, true);
297                 break;
298             case TOP:
299                 paintImage(g, x + gapStart, y, Math.min(w - x - gapStart,
300                            gapSize), Math.min(h, size), image, insets, true,
301                            false, true);
302                 break;
303             case BOTTOM:
304                 paintImage(g, x + gapStart, y + h - Math.min(h, size),
305                            Math.min(w - x - gapStart, gapSize),
306                            Math.min(h, size), image, insets, true, false,true);
307                 break;
308             }
309          }
310     }
311
312     /**
313      * Paints the image and overlay image from the passed in style.
314      *
315      * @param g Graphics object to paint to
316      * @param x X origin
317      * @param y Y origin
318      * @param w Width to draw to
319      * @param h Height to draw to
320      * @param info Used to fetch image, insets and overlay image from
321      */

322     private boolean paintPixmap(Graphics g, int x, int y, int w, int h,
323                                 PixmapStyle.Info info, boolean drawCenter) {
324         if (info != null) {
325             Rectangle clip = g.getClipBounds();
326             _clipX1 = clip.x;
327             _clipY1 = clip.y;
328             _clipX2 = _clipX1 + clip.width;
329             _clipY2 = _clipY1 + clip.height;
330             paintImage(g, x, y, w, h, info.getImage(), info.getImageInsets(),
331                        info.getStretch(), false, drawCenter);
332             paintImage(g, x, y, w, h, info.getOverlayImage(),
333                        info.getOverlayInsets(), info.getOverlayStretch(),
334                        true, drawCenter);
335             return true;
336          }
337         return false;
338     }
339
340     /**
341      * Paints the image in the specified region.
342      *
343      * @param g Graphics object to paint to
344      * @param x X origin
345      * @param y Y origin
346      * @param w Width to draw to
347      * @param h Height to draw to
348      * @param image Image to render
349      * @param insets Insets used to determine portion of image that is fixed.
350      */

351     private void paintImage(Graphics g, int x, int y, int w, int h,
352                             Image image, Insets insets, boolean stretch,
353                             boolean overlay, boolean drawCenter) {
354         if (image == null) {
355             return;
356         }
357         if (insets == null) {
358             insets = GTKPainter.EMPTY_INSETS;
359         }
360         int iw = image.getWidth(null);
361         int ih = image.getHeight(null);
362
363         if (iw <= 0 || ih <= 0) {
364             return;
365         }
366         Object JavaDoc lastHint;
367         Object JavaDoc renderingHint = RENDERING_HINT;
368
369         if (renderingHint != null && stretch) {
370             Graphics2D g2 = (Graphics2D)g;
371
372             lastHint = g2.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
373             if (lastHint == null) {
374                 lastHint = RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
375             }
376             g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
377                                 renderingHint);
378         }
379         else {
380             lastHint = null;
381         }
382
383         if (!stretch) {
384             if (overlay) {
385                 g.drawImage(image, x + w / 2 - iw / 2, y + h / 2 - ih / 2,
386                             null);
387             }
388             else {
389                 int lastIY = 0;
390                 for (int yCounter = y, maxY = y + h; yCounter < maxY;
391                          yCounter += (ih - lastIY), lastIY = 0) {
392                     int lastIX = 0;
393                     for (int xCounter = x, maxX = x + w; xCounter < maxX;
394                              xCounter += (iw - lastIX), lastIX = 0) {
395                         int dx2 = Math.min(maxX, xCounter + iw - lastIX);
396                         int dy2 = Math.min(maxY, yCounter + ih - lastIY);
397                         if (intersectsClip(xCounter, yCounter, dx2, dy2)) {
398                             g.drawImage(image, xCounter, yCounter, dx2, dy2,
399                                         lastIX, lastIY, lastIX + dx2 -xCounter,
400                                         lastIY + dy2 - yCounter, null);
401                         }
402                     }
403                 }
404             }
405         }
406         else {
407             int it = insets.top;
408             int il = insets.left;
409             int ib = insets.bottom;
410             int ir = insets.right;
411
412             // Constrain the insets to the size of the image
413
if (it + ib >= ih) {
414                 ib = it = Math.max(0, ih / 2 - 1);
415             }
416             if (il + ir >= iw) {
417                 il = ir = Math.max(0, iw / 2 - 1);
418             }
419             // Constrain the insets to the size of the region we're painting
420
// in.
421
if (it + ib > h) {
422                 it = ib = Math.max(2, h / 2 - 1);
423             }
424             if (il + ir > w) {
425                 il = ir = Math.max(2, w / 2 - 1);
426             }
427             // left
428
if (il > 0 && it + ib < ih) {
429                 drawChunk(image, g, stretch, x, y + it, x + il, y + h - ib, 0,
430                           it, il, ih - ib, false);
431             }
432             // top left
433
if (il > 0 && it > 0) {
434                 g.drawImage(image, x, y, x + il, y + it, 0, 0, il, it, null);
435             }
436             // top
437
if (it > 0 && il + ir < iw) {
438                 drawChunk(image, g, stretch, x + il, y, x + w - ir, y + it,
439                           il, 0, iw - ir, it, true);
440             }
441             // top right
442
if (ir < iw && it > 0) {
443                 g.drawImage(image, x + w - ir, y, x + w, y + it, iw - ir, 0,
444                             iw, it, null);
445             }
446             // right
447
if (ir < iw && it + ib < ih) {
448                 drawChunk(image, g, stretch, x + w - ir, y + it, x + w,
449                           y + h - ib, iw - ir, it, iw, ih - ib, false);
450             }
451             // bottom right
452
if (ir < iw && ib < ih) {
453                 g.drawImage(image, x + w - ir, y + h - ib, x + w, y + h,
454                             iw - ir, ih - ib, iw, ih, null);
455             }
456             // bottom
457
if (il + ir < iw && ib > 0) {
458                 drawChunk(image, g, stretch, x + il, y + h - ib, x + w - ir,
459                           y + h, il, ih - ib, iw - ir, ih, true);
460             }
461             // bottom left
462
if (il > 0 && ib > 0) {
463                 g.drawImage(image, x, y + h - ib, x + il,
464                             y + h, 0, ih - ib, il, ih, null);
465             }
466             // center
467
if (drawCenter && il + ir < iw && it + ib < ih) {
468                 g.drawImage(image, x + il, y + it, x + w - ir, y + h - ib,
469                             il, it, iw - ir, ih - ib, null);
470             }
471         }
472
473         if (lastHint != null) {
474             ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_INTERPOLATION,
475                                              lastHint);
476         }
477     }
478
479     /**
480      * Draws a portion of an image, stretched or tiled.
481      *
482      * @param image Image to render.
483      * @param g Graphics to render to
484      * @param stretch Whether the image should be stretched or timed in the
485      * provided space.
486      * @param dx1 X origin to draw to
487      * @param dy1 Y origin to draw to
488      * @param dx2 End x location to draw to
489      * @param dy2 End y location to draw to
490      * @param sx1 X origin to draw from
491      * @param sy1 Y origin to draw from
492      * @param sx2 Max x location to draw from
493      * @param sy2 Max y location to draw from
494      * @param xDirection Used if the image is not stretched. If true it
495      * indicates the image should be tiled along the x axis.
496      */

497     private void drawChunk(Image image, Graphics g, boolean stretch,
498                            int dx1, int dy1, int dx2, int dy2, int sx1,
499                            int sy1, int sx2, int sy2,
500                            boolean xDirection) {
501         if (dx2 - dx1 <= 0 || dy2 - dy1 <= 0 ||
502                               !intersectsClip(dx1, dy1, dx2, dy2)) {
503             // Bogus location, nothing to paint
504
return;
505         }
506         if (stretch) {
507             g.drawImage(image, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, null);
508         }
509         else {
510             int xSize = sx2 - sx1;
511             int ySize = sy2 - sy1;
512             int deltaX;
513             int deltaY;
514
515             if (xDirection) {
516                 deltaX = xSize;
517                 deltaY = 0;
518             }
519             else {
520                 deltaX = 0;
521                 deltaY = ySize;
522             }
523             while (dx1 < dx2 && dy1 < dy2) {
524                 int newDX2 = Math.min(dx2, dx1 + xSize);
525                 int newDY2 = Math.min(dy2, dy1 + ySize);
526
527                 if (intersectsClip(dx1, dy1, newDX2, newDY2)) {
528                     g.drawImage(image, dx1, dy1, newDX2, newDY2,
529                                 sx1, sy1, sx1 + newDX2 - dx1,
530                                 sy1 + newDY2 - dy1, null);
531                 }
532                 dx1 += deltaX;
533                 dy1 += deltaY;
534             }
535         }
536     }
537
538     /**
539      * Returns true if the passed in region intersects the clip.
540      */

541     private boolean intersectsClip(int x1, int y1, int x2, int y2) {
542         return ((x2 < x1 || x2 > _clipX1) &&
543                 (y2 < y1 || y2 > _clipY1) &&
544                 (_clipX2 < _clipX1 || _clipX2 > x1) &&
545                 (_clipY2 < _clipY1 || _clipY2 > y1));
546     }
547 }
548
Popular Tags