001: /*
002: * uDig - User Friendly Desktop Internet GIS client http://udig.refractions.net (C) 2004,
003: * Refractions Research Inc. This library is free software; you can redistribute it and/or modify it
004: * under the terms of the GNU Lesser General Public License as published by the Free Software
005: * Foundation; version 2.1 of the License. This library is distributed in the hope that it will be
006: * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
007: * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
008: */
009: package net.refractions.udig.ui.graphics;
010:
011: import java.awt.Dimension;
012: import java.awt.Point;
013: import java.awt.Shape;
014: import java.awt.geom.AffineTransform;
015: import java.awt.geom.PathIterator;
016: import java.awt.geom.Rectangle2D;
017: import java.awt.image.BufferedImage;
018: import java.awt.image.Raster;
019: import java.awt.image.RenderedImage;
020: import java.util.ArrayList;
021:
022: import org.eclipse.jface.resource.ImageDescriptor;
023: import org.eclipse.swt.SWT;
024: import org.eclipse.swt.graphics.Color;
025: import org.eclipse.swt.graphics.GC;
026: import org.eclipse.swt.graphics.Image;
027: import org.eclipse.swt.graphics.ImageData;
028: import org.eclipse.swt.graphics.PaletteData;
029: import org.eclipse.swt.graphics.Rectangle;
030: import org.eclipse.swt.graphics.Transform;
031: import org.eclipse.swt.widgets.Display;
032:
033: /**
034: * A Graphics object that wraps SWT's GC object
035: *
036: * @author jeichar
037: * @since 0.3
038: */
039: public class SWTGraphics implements ViewportGraphics {
040: /** The <code>TRANSPARENT</code> color */
041: public final static int TRANSPARENT = 0x220000 | 0x2200 | 0x22;
042:
043: private static final AffineTransform IDENTITY = new AffineTransform();
044:
045: private GC gc = null;
046:
047: private double[] current = new double[2];
048:
049: private double[] last = new double[2];
050:
051: private double[] move_to = new double[2];
052:
053: private Color fore = null;
054:
055: private Color back = null;
056:
057: private Display display;
058:
059: private Dimension displaySize;
060:
061: /**
062: * Construct <code>SWTGraphics</code>.
063: *
064: * @param Image
065: * image
066: * @param display
067: * The display object
068: */
069: public SWTGraphics(Image image, Display display) {
070: this (new GC(image), display,
071: new Dimension(image.getImageData().width, image
072: .getImageData().height));
073: }
074:
075: /**
076: * Construct <code>SWTGraphics</code>.
077: *
078: * @param gc
079: * The GC object
080: * @param display
081: * The display object
082: */
083: public SWTGraphics(GC gc, Display display, Dimension displaySize) {
084: setGraphics(gc, display);
085: this .displaySize = displaySize;
086: }
087:
088: void setGraphics(GC gc, Display display) {
089: this .gc = gc;
090: // this.display=display;
091: if (back != null)
092: back.dispose();
093: back = new Color(display, 255, 255, 255);
094: gc.setBackground(back);
095: }
096:
097: public void dispose() {
098: if (fore != null)
099: fore.dispose();
100: if (back != null)
101: back.dispose();
102: }
103:
104: /**
105: * @see net.refractions.udig.project.render.ViewportGraphics#draw(java.awt.Shape)
106: */
107: public void draw(Shape s) {
108: PathIterator p = s.getPathIterator(IDENTITY);
109: boolean singlePoint = true;
110: p.currentSegment(current);
111: move_to = current.clone();
112: p.next();
113: while (!p.isDone()) {
114: singlePoint = false;
115: last = current.clone();
116: switch (p.currentSegment(current)) {
117: case PathIterator.SEG_CLOSE:
118: gc.drawLine((int) current[0], (int) current[1],
119: (int) move_to[0], (int) move_to[1]);
120: break;
121: case PathIterator.SEG_LINETO:
122: gc.drawLine((int) last[0], (int) last[1],
123: (int) current[0], (int) current[1]);
124: break;
125: case PathIterator.SEG_MOVETO:
126: move_to = current;
127: break;
128: case PathIterator.SEG_QUADTO:
129: case PathIterator.SEG_CUBICTO:
130: default:
131: }
132: p.next();
133: }
134: if (singlePoint == true) {
135: gc.drawPoint((int) current[0], (int) current[1]);
136: }
137: }
138:
139: // public void drawPoint( Shape shape, Feature feature, PointSymbolizer
140: // pointSymbolizer ) {
141: // /** Factory that will resolve symbolizers into rendered styles */
142: // SLDStyleFactory styleFactory = new SLDStyleFactory();
143: // /** The painter class we use to depict shapes onto the screen */
144: // StyledShapePainter painter = new StyledShapePainter(null);
145: //
146: // Style2D style = styleFactory.createStyle(feature, pointSymbolizer, null);
147: //
148: // //Graphics2D graphics = getContext().getImage().createGraphics();
149: // painter.paint(this, shape, style, 1.0);
150: // }
151:
152: /**
153: * @see net.refractions.udig.project.render.ViewportGraphics#draw(java.awt.Shape)
154: */
155: public void fill(Shape s) {
156: gc.setBackground(fore);
157: PathIterator p = s.getPathIterator(IDENTITY);
158: ArrayList<Integer> pts = new ArrayList<Integer>();
159:
160: p.currentSegment(current);
161: for (double ord : current)
162: pts.add((int) ord); // "move_to"
163:
164: p.next();
165: while (!p.isDone()) {
166: switch (p.currentSegment(current)) {
167:
168: case PathIterator.SEG_LINETO:
169: p.currentSegment(current);
170: for (double ord : current)
171: pts.add((int) ord); // "line_to"
172: break;
173:
174: case PathIterator.SEG_MOVETO:
175: case PathIterator.SEG_CLOSE: {
176: for (double ord : current)
177: pts.add((int) ord); // "close"
178: final int SIZE = pts.size();
179: int polygon[] = new int[SIZE];
180: for (int i = 0; i < SIZE; i++)
181: polygon[i] = pts.get(i);
182: gc.fillPolygon(polygon);
183:
184: pts.clear(); // closed we can start again now
185: }
186: break;
187:
188: case PathIterator.SEG_QUADTO:
189: case PathIterator.SEG_CUBICTO:
190: default:
191:
192: }
193: p.next();
194: }
195: gc.setBackground(fore);
196: }
197:
198: /**
199: * @see net.refractions.udig.project.render.ViewportGraphics#fillRect(int,
200: * int, int, int)
201: */
202: public void fillRect(int x, int y, int width, int height) {
203:
204: gc.fillRectangle(new Rectangle(x, y, width, height));
205: }
206:
207: /**
208: * @see net.refractions.udig.project.render.ViewportGraphics#setColor(java.awt.Color)
209: */
210: public void setColor(java.awt.Color c) {
211: Color color = new Color(display, c.getRed(), c.getGreen(), c
212: .getBlue());
213: gc.setForeground(color);
214: if (fore != null)
215: fore.dispose();
216: fore = color;
217: }
218:
219: /**
220: * This is hard because - background doesn't mean what we think it means.
221: *
222: * @see net.refractions.udig.project.render.ViewportGraphics#setBackground(java.awt.Color)
223: */
224: public void setBackground(java.awt.Color c) {
225: Color color = new Color(display, c.getRed(), c.getGreen(), c
226: .getBlue());
227: gc.setBackground(color);
228: if (back != null)
229: back.dispose();
230: back = color;
231: }
232:
233: /**
234: * @see net.refractions.udig.project.render.ViewportGraphics#setStroke(int,
235: * int)
236: */
237: public void setStroke(int style, int width) {
238: switch (style) {
239: case LINE_DASH: {
240: gc.setLineStyle(SWT.LINE_DASH);
241: }
242: case LINE_DASHDOT: {
243: gc.setLineStyle(SWT.LINE_DASHDOT);
244: }
245: case LINE_DASHDOTDOT: {
246: gc.setLineStyle(SWT.LINE_DASHDOTDOT);
247: }
248: case LINE_DOT: {
249: gc.setLineStyle(SWT.LINE_DOT);
250: }
251: case LINE_SOLID: {
252: gc.setLineStyle(SWT.LINE_SOLID);
253: }
254: }
255: gc.setLineWidth(width);
256: }
257:
258: /**
259: * @see net.refractions.udig.project.render.ViewportGraphics#setClip(java.awt.Rectangle)
260: */
261: public void setClip(java.awt.Rectangle r) {
262: gc.setClipping(r.x, r.y, r.width, r.height);
263: }
264:
265: /**
266: * @see net.refractions.udig.project.render.ViewportGraphics#translate(java.awt.Point)
267: */
268: public void translate(Point offset) {
269: Transform transform = new Transform(display);
270: gc.getTransform(transform);
271: transform.translate(offset.x, offset.y);
272: gc.setTransform(transform);
273: }
274:
275: /**
276: * @see net.refractions.udig.project.render.ViewportGraphics#clearRect(int,
277: * int, int, int)
278: */
279: public void clearRect(int x, int y, int width, int height) {
280: Color c = gc.getForeground();
281: gc.setForeground(gc.getBackground());
282: gc.fillRectangle(x, y, width, height);
283: gc.setForeground(c);
284: }
285:
286: /**
287: * @see net.refractions.udig.project.render.ViewportGraphics#drawImage(javax.media.jai.PlanarImage,
288: * int, int)
289: */
290: public void drawImage(RenderedImage rimage, int x, int y) {
291: drawImage(rimage, 0, 0, rimage.getWidth(), rimage.getWidth(),
292: x, y, x + rimage.getWidth(), y + rimage.getWidth());
293: }
294:
295: public static Image createDefaultImage(Display display, int width,
296: int height) {
297: ImageData swtdata = null;
298: PaletteData palette;
299: int depth;
300:
301: depth = 24;
302: palette = new PaletteData(0xFF0000, 0xFF00, 0xFF);
303: swtdata = new ImageData(width, height, depth, palette);
304: swtdata.transparentPixel = -1;
305: swtdata.alpha = -1;
306: swtdata.alphaData = new byte[swtdata.data.length];
307: for (int i = 0; i < swtdata.alphaData.length; i++) {
308: swtdata.alphaData[i] = (byte) i;
309: }
310: return new Image(display, swtdata);
311:
312: }
313:
314: private ImageData awtImageToSWT(Raster raster, Rectangle size) {
315: ImageData swtdata = null;
316: int width = size.width;
317: int height = size.height;
318: PaletteData palette;
319: int depth;
320:
321: depth = 24;
322: palette = new PaletteData(0xFF0000, 0xFF00, 0xFF);
323: swtdata = new ImageData(width, height, depth, palette);
324: swtdata.transparentPixel = TRANSPARENT;
325:
326: byte blueT = (byte) ((TRANSPARENT) & 0xFF);
327: byte greenT = (byte) ((TRANSPARENT >> 8) & 0xFF);
328: byte redT = (byte) ((TRANSPARENT >> 16) & 0xFF);
329: // System.out.println("red="+redT+"blue"+blueT+"green"+greenT);
330: // System.out.println("Transparent"+TRANSPARENT);
331:
332: // awtImage2.getRGB();
333: int[] awtdata = raster.getPixels(0, 0, width, height,
334: new int[width * height * raster.getNumBands()]);
335: int step = swtdata.depth / 8;
336:
337: byte[] data = swtdata.data;
338: int baseindex = 0;
339: for (int y = 0; y < height; y++) {
340: int idx = ((0 + y) * swtdata.bytesPerLine) + (0 * step);
341:
342: for (int x = 0; x < width; x++) {
343: baseindex = (x + (y * width)) * 4;
344:
345: if (awtdata[baseindex + 3] == 0) {
346: data[idx++] = blueT;
347: data[idx++] = greenT;
348: data[idx++] = redT;
349: } else {
350: data[idx++] = (byte) awtdata[baseindex];
351: data[idx++] = (byte) awtdata[baseindex + 1];
352: data[idx++] = (byte) awtdata[baseindex + 2];
353: }
354: }
355: }
356:
357: return swtdata;
358: }
359:
360: public static ImageDescriptor createImageDescriptor(
361: final RenderedImage image, final boolean transparent) {
362: return new ImageDescriptor() {
363: public ImageData getImageData() {
364: return createImageData(image, transparent);
365: }
366: };
367: }
368:
369: /** Create a buffered image that can be be coverted to SWTland later */
370: public static BufferedImage createBufferedImage(int w, int h) {
371: return new BufferedImage(w, h,
372: BufferedImage.TYPE_4BYTE_ABGR_PRE);
373: }
374:
375: public static Image createSWTImage(RenderedImage image,
376: boolean transparent) {
377: ImageData data = createImageData(image, transparent);
378:
379: return new org.eclipse.swt.graphics.Image(Display.getDefault(),
380: data);
381: }
382:
383: // optimized version that works if the image is rgb with a byte data buffer
384: public static ImageData createImageDataFromBytes(RenderedImage image) {
385: ImageData swtdata = null;
386: int width = image.getWidth();
387: int height = image.getHeight();
388: PaletteData palette;
389: int depth;
390: depth = 24;
391: palette = new PaletteData(0xFF0000, 0xFF00, 0xFF);
392: swtdata = new ImageData(width, height, depth, palette);
393:
394: Raster raster = image.getData();
395: raster.getDataElements(0, 0, width, height, swtdata.data);
396:
397: return swtdata;
398: }
399:
400: public static ImageData createImageData(RenderedImage image,
401: boolean transparent) {
402:
403: // if( image.getData().getDataBuffer().getDataType()==DataBuffer.TYPE_BYTE
404: // && !image.getColorModel().hasAlpha() )
405: // return createImageDataFromBytes(image);
406: ImageData swtdata = null;
407: int width = image.getWidth();
408: int height = image.getHeight();
409: PaletteData palette;
410: int depth;
411:
412: depth = 24;
413: palette = new PaletteData(0xFF0000, 0xFF00, 0xFF);
414: swtdata = new ImageData(width, height, depth, palette);
415: byte blueT = (byte) 255;
416: byte greenT = (byte) 255;
417: byte redT = (byte) 255;
418: if (transparent) {
419: swtdata.transparentPixel = TRANSPARENT;
420:
421: blueT = (byte) ((TRANSPARENT) & 0xFF);
422: greenT = (byte) ((TRANSPARENT >> 8) & 0xFF);
423: redT = (byte) ((TRANSPARENT >> 16) & 0xFF);
424: }
425: Raster raster = image.getData();
426: int numbands = raster.getNumBands();
427: int[] awtdata = raster.getPixels(0, 0, width, height,
428: new int[width * height * numbands]);
429: int step = swtdata.depth / 8;
430:
431: byte[] data = swtdata.data;
432: int baseindex = 0;
433: for (int y = 0; y < height; y++) {
434: int idx = ((0 + y) * swtdata.bytesPerLine) + (0 * step);
435:
436: for (int x = 0; x < width; x++) {
437: baseindex = (x + (y * width)) * numbands;
438:
439: if (numbands == 4 && awtdata[baseindex + 3] == 0) {
440: data[idx++] = blueT;
441: data[idx++] = greenT;
442: data[idx++] = redT;
443: } else {
444: data[idx++] = (byte) awtdata[baseindex];
445: data[idx++] = (byte) awtdata[baseindex + 1];
446: data[idx++] = (byte) awtdata[baseindex + 2];
447: }
448: }
449: }
450: return swtdata;
451: }
452:
453: /**
454: * @see net.refractions.udig.ui.graphics.ViewportGraphics#drawString(String,
455: * int, int)
456: */
457: public void drawString(String string, int x, int y, int alignx,
458: int aligny) {
459: // FIXME do the alignment.
460: gc.drawString(string, x, y);
461: }
462:
463: /**
464: * @see net.refractions.udig.project.render.ViewportGraphics#setTransform(java.awt.geom.AffineTransform)
465: */
466: public void setTransform(AffineTransform transform) {
467: double[] matrix = new double[6];
468: transform.getMatrix(matrix);
469: gc
470: .setTransform(new Transform(display, (float) matrix[0],
471: (float) matrix[1], (float) matrix[2],
472: (float) matrix[3], (float) matrix[4],
473: (float) matrix[5]));
474: }
475:
476: /**
477: * @see net.refractions.udig.ui.graphics.ViewportGraphics#drawImage(java.awt.Image,
478: * int, int)
479: *
480: * Current version can only draw Image if the image is an RenderedImage
481: */
482: public void drawImage(java.awt.Image image, int x, int y) {
483: RenderedImage rimage = (RenderedImage) image;
484: drawImage(rimage, x, y);
485: }
486:
487: /**
488: * @see net.refractions.udig.ui.graphics.ViewportGraphics#drawImage(java.awt.Image,
489: * int, int, int, int, int, int, int, int)
490: */
491: public void drawImage(java.awt.Image image, int dx1, int dy1,
492: int dx2, int dy2, int sx1, int sy1, int sx2, int sy2) {
493: RenderedImage rimage = (RenderedImage) image;
494: drawImage(rimage, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2);
495: }
496:
497: public void drawImage(RenderedImage rimage, int dx1, int dy1,
498: int dx2, int dy2, int sx1, int sy1, int sx2, int sy2) {
499: assert rimage != null;
500: Image swtImage = null;
501: try {
502: swtImage = createSWTImage(rimage, true);
503: if (swtImage != null) {
504: gc.drawImage(swtImage, sx1, sy1, sx2 - sx1, sy2 - sy1,
505: dx1, dy1, dx2 - dx1, dy2 - dy1);
506: swtImage.dispose();
507: }
508: } finally {
509: if (swtImage != null)
510: swtImage.dispose();
511: }
512:
513: }
514:
515: public int getFontHeight() {
516: return gc.getFontMetrics().getHeight();
517: }
518:
519: public int stringWidth(String str) {
520: return -1;
521: }
522:
523: public int getFontAscent() {
524: return gc.getFontMetrics().getAscent();
525: }
526:
527: public Rectangle2D getStringBounds(String str) {
528: return null;
529: }
530:
531: public void drawLine(int x1, int y1, int x2, int y2) {
532: gc.drawLine(x1, y1, x2, y2);
533: }
534:
535: public void drawImage(Image image, int dx1, int dy1, int dx2,
536: int dy2, int sx1, int sy1, int sx2, int sy2) {
537: gc.drawImage(image, sx1, sy1, sx2 - sx1, sy2 - sy1, dx1, dy1,
538: dx2 - dx1, dy2 - dy1);
539: }
540: }
|