1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module org.eclipse.swt.graphics.PaletteData;
14 
15 import java.lang.all;
16 
17 
18 import org.eclipse.swt.SWT;
19 import org.eclipse.swt.graphics.RGB;
20 
21 /**
22  * Instances of this class describe the color data used by an image.
23  * <p>
24  * Depending on the depth of the image, the PaletteData can take one
25  * of two forms, indicated by the isDirect field:
26  * </p>
27  * <dl>
28  * <dt>
29  * <em>isDirect is false</em>
30  * </dt>
31  * <dd>
32  * If isDirect is <code>false</code>, this palette is an indexed
33  * palette which maps pixel values to RGBs. The actual RGB values
34  * may be retrieved by using the getRGBs() method.
35  * </dd>
36  * <dt>
37  * <em>isDirect is true</em>
38  * </dt>
39  * <dd>
40  * If isDirect is <code>true</code>, this palette is a direct color
41  * palette. Instead of containing RGB values, it contains red,
42  * green and blue mask and shift information which indicates how
43  * the color components may be extracted from a given pixel.
44  * This means that the RGB value is actually encoded in the pixel value.
45  * <p>
46  * In this case, the shift data is the number of bits required to shift
47  * the RGB value to the left in order to align the high bit of the
48  * corresponding mask with the high bit of the first byte. This number
49  * may be negative, so care must be taken when shifting. For example,
50  * with a red mask of 0xFF0000, the red shift would be -16. With a red
51  * mask of 0x1F, the red shift would be 3.
52  * </p>
53  * </dd>
54  * </dl>
55  *
56  * @see Image
57  * @see RGB
58  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
59  */
60 
61 public final class PaletteData {
62 
63     /**
64      * true if the receiver is a direct palette,
65      * and false otherwise
66      */
67     public bool isDirect;
68 
69     /**
70      * the RGB values for an indexed palette, where the
71      * indices of the array correspond to pixel values
72      */
73     public RGB[] colors;
74 
75     /**
76      * the red mask for a direct palette
77      */
78     public int redMask;
79 
80     /**
81      * the green mask for a direct palette
82      */
83     public int greenMask;
84 
85     /**
86      * the blue mask for a direct palette
87      */
88     public int blueMask;
89 
90     /**
91      * the red shift for a direct palette
92      */
93     public int redShift;
94 
95     /**
96      * the green shift for a direct palette
97      */
98     public int greenShift;
99 
100     /**
101      * the blue shift for a direct palette
102      */
103     public int blueShift;
104 
105 /**
106  * Constructs a new indexed palette given an array of RGB values.
107  *
108  * @param colors the array of <code>RGB</code>s for the palette
109  *
110  * @exception IllegalArgumentException <ul>
111  *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
112  * </ul>
113  */
114 public this(RGB[] colors) {
115     if (colors is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
116     this.colors = colors;
117     this.isDirect = false;
118 }
119 
120 /**
121  * Constructs a new direct palette given the red, green and blue masks.
122  *
123  * @param redMask the red mask
124  * @param greenMask the green mask
125  * @param blueMask the blue mask
126  */
127 public this(int redMask, int greenMask, int blueMask) {
128     this.redMask = redMask;
129     this.greenMask = greenMask;
130     this.blueMask = blueMask;
131     this.isDirect = true;
132     this.redShift = shiftForMask(redMask);
133     this.greenShift = shiftForMask(greenMask);
134     this.blueShift = shiftForMask(blueMask);
135 }
136 
137 /**
138  * Returns the pixel value corresponding to the given <code>RGB</code>.
139  *
140  * @param rgb the RGB to get the pixel value for
141  * @return the pixel value for the given RGB
142  *
143  * @exception IllegalArgumentException <ul>
144  *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
145  *    <li>ERROR_INVALID_ARGUMENT - if the RGB is not found in the palette</li>
146  * </ul>
147  */
148 public int getPixel(RGB rgb) {
149     if (rgb is null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
150     if (isDirect) {
151         int pixel = 0;
152         pixel |= (redShift < 0 ? rgb.red << -redShift : rgb.red >>> redShift) & redMask;
153         pixel |= (greenShift < 0 ? rgb.green << -greenShift : rgb.green >>> greenShift) & greenMask;
154         pixel |= (blueShift < 0 ? rgb.blue << -blueShift : rgb.blue >>> blueShift) & blueMask;
155         return pixel;
156     } else {
157         for (int i = 0; i < colors.length; i++) {
158             if (colors[i].opEquals(rgb) ) return i;
159         }
160         /* The RGB did not exist in the palette */
161         SWT.error(SWT.ERROR_INVALID_ARGUMENT);
162         return 0;
163     }
164 }
165 
166 /**
167  * Returns an <code>RGB</code> corresponding to the given pixel value.
168  *
169  * @param pixel the pixel to get the RGB value for
170  * @return the RGB value for the given pixel
171  *
172  * @exception IllegalArgumentException <ul>
173  *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
174  *    <li>ERROR_INVALID_ARGUMENT - if the pixel does not exist in the palette</li>
175  * </ul>
176  */
177 public RGB getRGB(int pixel) {
178     if (isDirect) {
179         int r = pixel & redMask;
180         r = (redShift < 0) ? r >>> -redShift : r << redShift;
181         int g = pixel & greenMask;
182         g = (greenShift < 0) ? g >>> -greenShift : g << greenShift;
183         int b = pixel & blueMask;
184         b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
185         return new RGB(r, g, b);
186     } else {
187         if (pixel < 0 || pixel >= colors.length) {
188             SWT.error(SWT.ERROR_INVALID_ARGUMENT);
189         }
190         return colors[pixel];
191     }
192 }
193 
194 /**
195  * Returns all the RGB values in the receiver if it is an
196  * indexed palette, or null if it is a direct palette.
197  *
198  * @return the <code>RGB</code>s for the receiver or null
199  */
200 public RGB[] getRGBs() {
201     return colors;
202 }
203 
204 /**
205  * Computes the shift value for a given mask.
206  *
207  * @param mask the mask to compute the shift for
208  * @return the shift amount
209  *
210  * @see PaletteData
211  */
212 int shiftForMask(int mask) {
213     for (int i = 31; i >= 0; i--) {
214         if (((mask >> i) & 0x1) !is 0) return 7 - i;
215     }
216     return 32;
217 }
218 
219 }