OpenCores
URL https://opencores.org/ocsvn/scarts/scarts/trunk

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [classpath/] [gnu/] [java/] [awt/] [peer/] [gtk/] [GtkImage.java] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
/* GtkImage.java
2
   Copyright (C) 2005 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package gnu.java.awt.peer.gtk;
40
 
41
import java.awt.Graphics;
42
import java.awt.Color;
43
import java.awt.Image;
44
import java.awt.image.ColorModel;
45
import java.awt.image.DirectColorModel;
46
import java.awt.image.MemoryImageSource;
47
import java.awt.image.ImageConsumer;
48
import java.awt.image.ImageObserver;
49
import java.awt.image.ImageProducer;
50
import java.io.File;
51
import java.io.IOException;
52
import java.util.Hashtable;
53
import java.util.Vector;
54
import java.io.ByteArrayOutputStream;
55
import java.io.BufferedInputStream;
56
import java.net.URL;
57
import gnu.classpath.Pointer;
58
 
59
/**
60
 * GtkImage - wraps a GdkPixbuf or GdkPixmap.
61
 *
62
 * The constructor GtkImage(int, int) creates an 'off-screen' GdkPixmap,
63
 * this can be drawn to (it's a GdkDrawable), and correspondingly, you can
64
 * create a GdkGraphics object for it.
65
 *
66
 * This corresponds to the Image implementation returned by
67
 * Component.createImage(int, int).
68
 *
69
 * A GdkPixbuf is 'on-screen' and the gdk cannot draw to it,
70
 * this is used for the other constructors (and other createImage methods), and
71
 * corresponds to the Image implementations returned by the Toolkit.createImage
72
 * methods, and is basically immutable.
73
 *
74
 * @author Sven de Marothy
75
 */
76
public class GtkImage extends Image
77
{
78
  int width = -1, height = -1;
79
 
80
  /**
81
   * Properties.
82
   */
83
  Hashtable props;
84
 
85
  /**
86
   * Loaded or not flag, for asynchronous compatibility.
87
   */
88
  boolean isLoaded;
89
 
90
  /**
91
   * Pointer to the GdkPixbuf
92
   */
93
  Pointer pixmap;
94
 
95
  /**
96
   * Observer queue.
97
   */
98
  Vector observers;
99
 
100
  /**
101
   * If offScreen is set, a GdkBitmap is wrapped and not a Pixbuf.
102
   */
103
  boolean offScreen;
104
 
105
  /**
106
   * Error flag for loading.
107
   */
108
  boolean errorLoading;
109
 
110
  /**
111
   * Original source, if created from an ImageProducer.
112
   */
113
  ImageProducer source;
114
 
115
  /*
116
   * The 32-bit AABBGGRR format the GDK uses.
117
   */
118
  static ColorModel nativeModel = new DirectColorModel(32,
119
                                                       0x000000FF,
120
                                                       0x0000FF00,
121
                                                       0x00FF0000,
122
                                                       0xFF000000);
123
 
124
  /**
125
   * Returns a copy of the pixel data as a java array.
126
   */
127
  private native int[] getPixels();
128
 
129
  /**
130
   * Sets the pixel data from a java array.
131
   */
132
  private native void setPixels(int[] pixels);
133
 
134
  /**
135
   * Loads an image using gdk-pixbuf from a file.
136
   */
137
  private native boolean loadPixbuf(String name);
138
 
139
  /**
140
   * Loads an image using gdk-pixbuf from data.
141
   */
142
  private native boolean loadImageFromData(byte[] data);
143
 
144
  /**
145
   * Allocates a Gtk Pixbuf or pixmap
146
   */
147
  private native void createPixmap();
148
 
149
  /**
150
   * Frees the above.
151
   */
152
  private native void freePixmap();
153
 
154
  /**
155
   * Sets the pixmap to scaled copy of src image. hints are rendering hints.
156
   */
157
  private native void createScaledPixmap(GtkImage src, int hints);
158
 
159
  /**
160
   * Draws the image, optionally scaled and composited.
161
   */
162
  private native void drawPixelsScaled (GdkGraphics gc,
163
                                        int bg_red, int bg_green, int bg_blue,
164
                                        int x, int y, int width, int height,
165
                                        boolean composite);
166
 
167
  /**
168
   * Draws the image, optionally scaled flipped and composited.
169
   */
170
  private native void drawPixelsScaledFlipped (GdkGraphics gc,
171
                                               int bg_red, int bg_green,
172
                                               int bg_blue,
173
                                               boolean flipX, boolean flipY,
174
                                               int srcX, int srcY,
175
                                               int srcWidth, int srcHeight,
176
                                               int dstX, int dstY,
177
                                               int dstWidth, int dstHeight,
178
                                               boolean composite);
179
 
180
  /**
181
   * Constructs a GtkImage from an ImageProducer. Asynchronity is handled in
182
   * the following manner:
183
   * A GtkImageConsumer gets the image data, and calls setImage() when
184
   * completely finished. The GtkImage is not considered loaded until the
185
   * GtkImageConsumer is completely finished. We go for all "all or nothing".
186
   */
187
  public GtkImage (ImageProducer producer)
188
  {
189
    isLoaded = false;
190
    observers = new Vector();
191
    source = producer;
192
    errorLoading = false;
193
    source.startProduction(new GtkImageConsumer(this, source));
194
    offScreen = false;
195
  }
196
 
197
  /**
198
   * Constructs a blank GtkImage.  This is called when
199
   * GtkToolkit.createImage (String) is called with an empty string
200
   * argument ("").  A blank image is loaded immediately upon
201
   * construction and has width -1 and height -1.
202
   */
203
  public GtkImage ()
204
  {
205
    isLoaded = true;
206
    observers = null;
207
    offScreen = false;
208
    props = new Hashtable();
209
    errorLoading = false;
210
  }
211
 
212
  /**
213
   * Constructs a GtkImage by loading a given file.
214
   *
215
   * @throws IllegalArgumentException if the image could not be loaded.
216
   */
217
  public GtkImage (String filename)
218
  {
219
    File f = new File(filename);
220
    try
221
      {
222
        if (loadPixbuf(f.getCanonicalPath()) != true)
223
          throw new IllegalArgumentException("Couldn't load image: "+filename);
224
      }
225
    catch(IOException e)
226
      {
227
          throw new IllegalArgumentException("Couldn't load image: "+filename);
228
      }
229
 
230
    isLoaded = true;
231
    observers = null;
232
    offScreen = false;
233
    props = new Hashtable();
234
  }
235
 
236
  /**
237
   * Constructs a GtkImage from a byte array of an image file.
238
   *
239
   * @throws IllegalArgumentException if the image could not be
240
   * loaded.
241
   */
242
  public GtkImage (byte[] data)
243
  {
244
    if (loadImageFromData (data) != true)
245
      throw new IllegalArgumentException ("Couldn't load image.");
246
 
247
    isLoaded = true;
248
    observers = null;
249
    offScreen = false;
250
    props = new Hashtable();
251
    errorLoading = false;
252
  }
253
 
254
  /**
255
   * Constructs a GtkImage from a URL. May result in an error image.
256
   */
257
  public GtkImage (URL url)
258
  {
259
    isLoaded = false;
260
    observers = new Vector();
261
    errorLoading = false;
262
    if( url == null)
263
      return;
264
    ByteArrayOutputStream baos = new ByteArrayOutputStream (5000);
265
    try
266
      {
267
        BufferedInputStream bis = new BufferedInputStream (url.openStream());
268
 
269
        byte[] buf = new byte[5000];
270
        int n = 0;
271
 
272
        while ((n = bis.read(buf)) != -1)
273
          baos.write(buf, 0, n);
274
        bis.close();
275
      }
276
    catch(IOException e)
277
      {
278
        throw new IllegalArgumentException ("Couldn't load image.");
279
      }
280
    if (loadImageFromData (baos.toByteArray()) != true)
281
      throw new IllegalArgumentException ("Couldn't load image.");
282
 
283
    isLoaded = true;
284
    observers = null;
285
    props = new Hashtable();
286
  }
287
 
288
  /**
289
   * Constructs an empty GtkImage.
290
   */
291
  public GtkImage (int width, int height)
292
  {
293
    this.width = width;
294
    this.height = height;
295
    props = new Hashtable();
296
    isLoaded = true;
297
    observers = null;
298
    offScreen = true;
299
    createPixmap();
300
  }
301
 
302
  /**
303
   * Constructs a scaled version of the src bitmap, using the GDK.
304
   */
305
  private GtkImage (GtkImage src, int width, int height, int hints)
306
  {
307
    this.width = width;
308
    this.height = height;
309
    props = new Hashtable();
310
    isLoaded = true;
311
    observers = null;
312
    offScreen = false;
313
 
314
    // Use the GDK scaling method.
315
    createScaledPixmap(src, hints);
316
  }
317
 
318
  /**
319
   * Package private constructor to create a GtkImage from a given
320
   * PixBuf pointer.
321
   */
322
  GtkImage (Pointer pixbuf)
323
  {
324
    pixmap = pixbuf;
325
    createFromPixbuf();
326
    isLoaded = true;
327
    observers = null;
328
    offScreen = false;
329
    props = new Hashtable();
330
  }
331
 
332
  /**
333
   * Native helper function for constructor that takes a pixbuf Pointer.
334
   */
335
  private native void createFromPixbuf();
336
 
337
  /**
338
   * Callback from the image consumer.
339
   */
340
  public void setImage(int width, int height,
341
                       int[] pixels, Hashtable properties)
342
  {
343
    this.width = width;
344
    this.height = height;
345
    props = (properties != null) ? properties : new Hashtable();
346
 
347
    if (width <= 0 || height <= 0 || pixels == null)
348
      {
349
        errorLoading = true;
350
        return;
351
      }
352
 
353
    isLoaded = true;
354
    deliver();
355
    createPixmap();
356
    setPixels(pixels);
357
  }
358
 
359
  // java.awt.Image methods ////////////////////////////////////////////////
360
 
361
  public synchronized int getWidth (ImageObserver observer)
362
  {
363
    if (addObserver(observer))
364
      return -1;
365
 
366
    return width;
367
  }
368
 
369
  public synchronized int getHeight (ImageObserver observer)
370
  {
371
    if (addObserver(observer))
372
      return -1;
373
 
374
    return height;
375
  }
376
 
377
  public synchronized Object getProperty (String name, ImageObserver observer)
378
  {
379
    if (addObserver(observer))
380
      return UndefinedProperty;
381
 
382
    Object value = props.get (name);
383
    return (value == null) ? UndefinedProperty : value;
384
  }
385
 
386
  /**
387
   * Returns the source of this image.
388
   */
389
  public ImageProducer getSource ()
390
  {
391
    if (!isLoaded)
392
      return null;
393
    return new MemoryImageSource(width, height, nativeModel, getPixels(),
394
                                 0, width);
395
  }
396
 
397
  /**
398
   * Creates a GdkGraphics context for this pixmap.
399
   */
400
  public Graphics getGraphics ()
401
  {
402
    if (!isLoaded)
403
      return null;
404
    if (offScreen)
405
      return new GdkGraphics(this);
406
    else
407
      throw new IllegalAccessError("This method only works for off-screen"
408
                                   +" Images.");
409
  }
410
 
411
  /**
412
   * Returns a scaled instance of this pixmap.
413
   */
414
  public Image getScaledInstance(int width,
415
                                 int height,
416
                                 int hints)
417
  {
418
    if (width <= 0 || height <= 0)
419
      throw new IllegalArgumentException("Width and height of scaled bitmap"+
420
                                         "must be >= 0");
421
 
422
    return new GtkImage(this, width, height, hints);
423
  }
424
 
425
  /**
426
   * If the image is loaded and comes from an ImageProducer,
427
   * regenerate the image from there.
428
   *
429
   * I have no idea if this is ever actually used. Since GtkImage can't be
430
   * instantiated directly, how is the user to know if it was created from
431
   * an ImageProducer or not?
432
   */
433
  public synchronized void flush ()
434
  {
435
    if (isLoaded && source != null)
436
      {
437
        observers = new Vector();
438
        isLoaded = false;
439
        freePixmap();
440
        source.startProduction(new GtkImageConsumer(this, source));
441
      }
442
  }
443
 
444
  public void finalize()
445
  {
446
    if (isLoaded)
447
      freePixmap();
448
  }
449
 
450
  /**
451
   * Returns the image status, used by GtkToolkit
452
   */
453
  public int checkImage (ImageObserver observer)
454
  {
455
    if (addObserver(observer))
456
      {
457
        if (errorLoading == true)
458
          return ImageObserver.ERROR;
459
        else
460
          return 0;
461
      }
462
 
463
    return ImageObserver.ALLBITS | ImageObserver.WIDTH | ImageObserver.HEIGHT;
464
  }
465
 
466
  // Drawing methods ////////////////////////////////////////////////
467
 
468
  /**
469
   * Draws an image with eventual scaling/transforming.
470
   */
471
  public boolean drawImage (GdkGraphics g, int dx1, int dy1, int dx2, int dy2,
472
                            int sx1, int sy1, int sx2, int sy2,
473
                            Color bgcolor, ImageObserver observer)
474
  {
475
    if (addObserver(observer))
476
      return false;
477
 
478
    boolean flipX = (dx1 > dx2)^(sx1 > sx2);
479
    boolean flipY = (dy1 > dy2)^(sy1 > sy2);
480
    int dstWidth = Math.abs (dx2 - dx1);
481
    int dstHeight = Math.abs (dy2 - dy1);
482
    int srcWidth = Math.abs (sx2 - sx1);
483
    int srcHeight = Math.abs (sy2 - sy1);
484
    int srcX = (sx1 < sx2) ? sx1 : sx2;
485
    int srcY = (sy1 < sy2) ? sy1 : sy2;
486
    int dstX = (dx1 < dx2) ? dx1 : dx2;
487
    int dstY = (dy1 < dy2) ? dy1 : dy2;
488
 
489
    // Clipping. This requires the dst to be scaled as well, 
490
    if (srcWidth > width)
491
      {
492
        dstWidth = (int)((double)dstWidth*((double)width/(double)srcWidth));
493
        srcWidth = width - srcX;
494
      }
495
 
496
    if (srcHeight > height)
497
      {
498
        dstHeight = (int)((double)dstHeight*((double)height/(double)srcHeight));
499
        srcHeight = height - srcY;
500
      }
501
 
502
    if (srcWidth + srcX > width)
503
      {
504
        dstWidth = (int)((double)dstWidth * (double)(width - srcX)/(double)srcWidth);
505
        srcWidth = width - srcX;
506
      }
507
 
508
    if (srcHeight + srcY > height)
509
      {
510
        dstHeight = (int)((double)dstHeight * (double)(width - srcY)/(double)srcHeight);
511
        srcHeight = height - srcY;
512
      }
513
 
514
    if ( srcWidth <= 0 || srcHeight <= 0 || dstWidth <= 0 || dstHeight <= 0)
515
      return true;
516
 
517
    if(bgcolor != null)
518
      drawPixelsScaledFlipped (g, bgcolor.getRed (), bgcolor.getGreen (),
519
                               bgcolor.getBlue (),
520
                               flipX, flipY,
521
                               srcX, srcY,
522
                               srcWidth, srcHeight,
523
                               dstX,  dstY,
524
                               dstWidth, dstHeight,
525
                               true);
526
    else
527
      drawPixelsScaledFlipped (g, 0, 0, 0, flipX, flipY,
528
                               srcX, srcY, srcWidth, srcHeight,
529
                               dstX,  dstY, dstWidth, dstHeight,
530
                               false);
531
    return true;
532
  }
533
 
534
  /**
535
   * Draws an image to the GdkGraphics context, at (x,y) scaled to
536
   * width and height, with optional compositing with a background color.
537
   */
538
  public boolean drawImage (GdkGraphics g, int x, int y, int width, int height,
539
                            Color bgcolor, ImageObserver observer)
540
  {
541
    if (addObserver(observer))
542
      return false;
543
 
544
    if(bgcolor != null)
545
      drawPixelsScaled(g, bgcolor.getRed (), bgcolor.getGreen (),
546
                       bgcolor.getBlue (), x, y, width, height, true);
547
    else
548
      drawPixelsScaled(g, 0, 0, 0, x, y, width, height, false);
549
 
550
    return true;
551
  }
552
 
553
  // Private methods ////////////////////////////////////////////////
554
 
555
  /**
556
   * Delivers notifications to all queued observers.
557
   */
558
  private void deliver()
559
  {
560
    int flags = ImageObserver.HEIGHT |
561
      ImageObserver.WIDTH |
562
      ImageObserver.PROPERTIES |
563
      ImageObserver.ALLBITS;
564
 
565
    if (observers != null)
566
      for(int i=0; i < observers.size(); i++)
567
        ((ImageObserver)observers.elementAt(i)).
568
          imageUpdate(this, flags, 0, 0, width, height);
569
 
570
    observers = null;
571
  }
572
 
573
  /**
574
   * Adds an observer, if we need to.
575
   * @return true if an observer was added.
576
   */
577
  private boolean addObserver(ImageObserver observer)
578
  {
579
    if (!isLoaded)
580
      {
581
        if(observer != null)
582
          if (!observers.contains (observer))
583
            observers.addElement (observer);
584
        return true;
585
      }
586
    return false;
587
  }
588
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.