# HG changeset patch # User Frank Benoit # Date 1201339378 -3600 # Node ID 437c596467314b9b836b96812dd434230efa8c87 # Parent eca0c8261b9f28ae3376f50dfb36ae034db4fc02 Color diff -r eca0c8261b9f -r 437c59646731 dwt/graphics/Color.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwt/graphics/Color.d Sat Jan 26 10:22:58 2008 +0100 @@ -0,0 +1,346 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +module dwt.graphics.Color; + + +import dwt.DWT; +import dwt.DWTException; +import dwt.internal.win32.OS; + +import dwt.graphics.Resource; +import dwt.graphics.RGB; +import dwt.graphics.Device; + +import tango.text.convert.Format; + +/** + * Instances of this class manage the operating system resources that + * implement DWT's RGB color model. To create a color you can either + * specify the individual color components as integers in the range + * 0 to 255 or provide an instance of an RGB. + *

+ * Application code must explicitly invoke the Color.dispose() + * method to release the operating system resources managed by each instance + * when those instances are no longer required. + *

+ * + * @see RGB + * @see Device#getSystemColor + */ + +public final class Color : Resource { + + /** + * the handle to the OS color resource + * (Warning: This field is platform dependent) + *

+ * IMPORTANT: This field is not part of the DWT + * public API. It is marked public only so that it can be shared + * within the packages provided by DWT. It is not available on all + * platforms and should never be accessed from application code. + *

+ */ + public COLORREF handle; + +/** + * Prevents uninitialized instances from being created outside the package. + */ +this() { +} + +/** + * Constructs a new instance of this class given a device and the + * desired red, green and blue values expressed as ints in the range + * 0 to 255 (where 0 is black and 255 is full brightness). On limited + * color devices, the color instance created by this call may not have + * the same RGB values as the ones specified by the arguments. The + * RGB values on the returned instance will be the color values of + * the operating system color. + *

+ * You must dispose the color when it is no longer required. + *

+ * + * @param device the device on which to allocate the color + * @param red the amount of red in the color + * @param green the amount of green in the color + * @param blue the amount of blue in the color + * + * @exception IllegalArgumentException + * + * @see #dispose + */ +public this (Device device, int red, int green, int blue) { + if (device is null) device = Device.getDevice(); + if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + init(device, red, green, blue); + if (device.tracking) device.new_Object(this); +} + +/** + * Constructs a new instance of this class given a device and an + * RGB describing the desired red, green and blue values. + * On limited color devices, the color instance created by this call + * may not have the same RGB values as the ones specified by the + * argument. The RGB values on the returned instance will be the color + * values of the operating system color. + *

+ * You must dispose the color when it is no longer required. + *

+ * + * @param device the device on which to allocate the color + * @param rgb the RGB values of the desired color + * + * @exception IllegalArgumentException + * + * @see #dispose + */ +public this (Device device, RGB rgb) { + if (device is null) device = Device.getDevice(); + if (device is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + if (rgb is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); + init(device, rgb.red, rgb.green, rgb.blue); + if (device.tracking) device.new_Object(this); +} + +/** + * Disposes of the operating system resources associated with + * the color. Applications must dispose of all colors which + * they allocate. + */ +public void dispose() { + if (handle is -1) return; + if (device.isDisposed()) return; + + /* + * If this is a palette-based device, + * Decrease the reference count for this color. + * If the reference count reaches 0, the slot may + * be reused when another color is allocated. + */ + auto hPal = device.hPalette; + if (hPal !is null) { + int index = OS.GetNearestPaletteIndex(hPal, handle); + int[] colorRefCount = device.colorRefCount; + if (colorRefCount[index] > 0) { + colorRefCount[index]--; + } + } + handle = -1; + if (device.tracking) device.dispose_Object(this); + device = null; +} + +/** + * Compares the argument to the receiver, and returns true + * if they represent the same object using a class + * specific comparison. + * + * @param object the object to compare with this object + * @return true if the object is the same as this object and false otherwise + * + * @see #hashCode + */ +public bool equals (Object object) { + if (object is this) return true; + if (!(cast(Color)object)) return false; + Color color = cast(Color) object; + return device is color.device && (handle & 0xFFFFFF) is (color.handle & 0xFFFFFF); +} + +/** + * Returns the amount of blue in the color, from 0 to 255. + * + * @return the blue component of the color + * + * @exception DWTException + */ +public int getBlue () { + if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); + return (handle & 0xFF0000) >> 16; +} + +/** + * Returns the amount of green in the color, from 0 to 255. + * + * @return the green component of the color + * + * @exception DWTException + */ +public int getGreen () { + if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); + return (handle & 0xFF00) >> 8 ; +} + +/** + * Returns the amount of red in the color, from 0 to 255. + * + * @return the red component of the color + * + * @exception DWTException + */ +public int getRed () { + if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); + return handle & 0xFF; +} + +/** + * Returns an RGB representing the receiver. + * + * @return the RGB for the color + * + * @exception DWTException + */ +public RGB getRGB () { + if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); + return new RGB(cast(int)handle & 0xFF,cast(int) (handle & 0xFF00) >> 8,cast(int) (handle & 0xFF0000) >> 16); +} + +/** + * Returns an integer hash code for the receiver. Any two + * objects that return true when passed to + * equals must return the same value for this + * method. + * + * @return the receiver's hash + * + * @see #equals + */ +public int hashCode () { + return handle; +} + +/** + * Allocates the operating system resources associated + * with the receiver. + * + * @param device the device on which to allocate the color + * @param red the amount of red in the color + * @param green the amount of green in the color + * @param blue the amount of blue in the color + * + * @exception IllegalArgumentException + * + * @see #dispose + */ +void init(Device device, int red, int green, int blue) { + if (red > 255 || red < 0 || green > 255 || green < 0 || blue > 255 || blue < 0) { + DWT.error(DWT.ERROR_INVALID_ARGUMENT); + } + this.device = device; + handle = (red & 0xFF) | ((green & 0xFF) << 8) | ((blue & 0xFF) << 16); + + /* If this is not a palette-based device, return */ + auto hPal = device.hPalette; + if (hPal is null) return; + + int[] colorRefCount = device.colorRefCount; + /* Add this color to the default palette now */ + /* First find out if the color already exists */ + int index = OS.GetNearestPaletteIndex(hPal, handle); + /* See if the nearest color actually is the color */ + PALETTEENTRY entry; + OS.GetPaletteEntries(hPal, index, 1, &entry); + if ((entry.peRed is cast(byte)red) && (entry.peGreen is cast(byte)green) && + (entry.peBlue is cast(byte)blue)) { + /* Found the color. Increment the ref count and return */ + colorRefCount[index]++; + return; + } + /* Didn't find the color, allocate it now. Find the first free entry */ + int i = 0; + while (i < colorRefCount.length) { + if (colorRefCount[i] is 0) { + index = i; + break; + } + i++; + } + if (i is colorRefCount.length) { + /* No free entries, use the closest one */ + /* Remake the handle from the actual rgbs */ + handle = (entry.peRed & 0xFF) | ((entry.peGreen & 0xFF) << 8) | + ((entry.peBlue & 0xFF) << 16); + } else { + /* Found a free entry */ + entry.peRed = cast(BYTE)(red & 0xFF); + entry.peGreen = cast(BYTE)(green & 0xFF); + entry.peBlue = cast(BYTE)(blue & 0xFF); + entry.peFlags = 0; + OS.SetPaletteEntries(hPal, index, 1, &entry); + } + colorRefCount[index]++; +} + +/** + * Returns true if the color has been disposed, + * and false otherwise. + *

+ * This method gets the dispose state for the color. + * When a color has been disposed, it is an error to + * invoke any other method using the color. + * + * @return true when the color is disposed and false otherwise + */ +public bool isDisposed() { + return handle is -1; +} + +/** + * Returns a string containing a concise, human-readable + * description of the receiver. + * + * @return a string representation of the receiver + */ +public char[] toString () { + if (isDisposed()) return "Color {*DISPOSED*}"; //$NON-NLS-1$ + return Format( "Color {{{}, {}, {}}", getRed(), getGreen(), getBlue()); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ +} + +/** + * Invokes platform specific functionality to allocate a new color. + *

+ * IMPORTANT: This method is not part of the public + * API for Color. It is marked public only so that it + * can be shared within the packages provided by DWT. It is not + * available on all platforms, and should never be called from + * application code. + *

+ * + * @param device the device on which to allocate the color + * @param handle the handle for the color + * @return a new color object containing the specified device and handle + */ +public static Color win32_new(Device device, int handle) { + if (device is null) device = Device.getDevice(); + Color color = new Color(); + color.handle = handle; + color.device = device; + return color; +} + +} diff -r eca0c8261b9f -r 437c59646731 dwt/graphics/Device.d --- a/dwt/graphics/Device.d Sat Jan 26 09:22:08 2008 +0100 +++ b/dwt/graphics/Device.d Sat Jan 26 10:22:58 2008 +0100 @@ -1,4 +1,4 @@ -/******************************************************************************* +/******************************************************************************* * Copyright (c) 2000, 2007 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 @@ -20,9 +20,12 @@ void dispose_Object (Object object) ; float computePoints(LOGFONT* logFont, HFONT hFont); int computePixels(float height) ; + public HPALETTE hPalette; + int [] colorRefCount; + } /+++ - + import dwt.DWT; import dwt.DWTException; import dwt.internal.Callback; @@ -44,16 +47,16 @@ * can be drawn on by sending messages to the associated GC. */ public abstract class Device implements Drawable { - + /* Debugging */ public static bool DEBUG; bool debug = DEBUG; bool tracking = DEBUG; Error [] errors; Object [] objects; - + /** - * Palette + * Palette * (Warning: This field is platform dependent) *

* IMPORTANT: This field is not part of the DWT @@ -64,7 +67,7 @@ */ public int hPalette = 0; int [] colorRefCount; - + /* System Font */ int systemFont; @@ -81,7 +84,7 @@ int [] gdipToken; bool disposed; - + final static Object CREATE_LOCK = new Object(); /* @@ -102,14 +105,14 @@ try { Class.forName ("org.eclipse.swt.widgets.Display"); //$NON-NLS-1$ } catch (Throwable e) {} - } + } /* * TEMPORARY CODE. */ static synchronized Device getDevice () { if (DeviceFinder !is null) DeviceFinder.run(); - Device device = CurrentDevice; + Device device = CurrentDevice; CurrentDevice = null; return device; } @@ -117,12 +120,12 @@ /** * Constructs a new instance of this class. *

- * You must dispose the device when it is no longer required. + * You must dispose the device when it is no longer required. *

* * @see #create * @see #init - * + * * @since 3.1 */ public Device() { @@ -132,7 +135,7 @@ /** * Constructs a new instance of this class. *

- * You must dispose the device when it is no longer required. + * You must dispose the device when it is no longer required. *

* * @param data the DeviceData which describes the receiver @@ -153,7 +156,7 @@ errors = new Error [128]; objects = new Object [128]; } - + /* Initialize the system font slot */ systemFont = getSystemFont().handle; } @@ -228,7 +231,7 @@ float computePoints(LOGFONT logFont, int hFont) { int hDC = internal_new_GC (null); int logPixelsY = OS.GetDeviceCaps(hDC, OS.LOGPIXELSY); - int pixels = 0; + int pixels = 0; if (logFont.lfHeight > 0) { /* * Feature in Windows. If the lfHeight of the LOGFONT structure @@ -391,7 +394,7 @@ /** * Returns a rectangle which describes the area of the * receiver which is capable of displaying data. - * + * * @return the client area * * @exception DWTException * * @see Font - * + * * @since 3.3 */ public bool loadFont (String path) {