view dwt/graphics/PaletteData.d @ 156:969e7de37c3d default tip

Fixes to get dwt to work with dmd and ldc
author Jacob Carlborg <doob@me.com>
date Wed, 08 Jul 2009 21:56:44 +0200
parents d8635bb48c7c
children
line wrap: on
line source

/*******************************************************************************
 * Copyright (c) 2000, 2008 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
 *     
 * Port to the D programming language:
 *     Jacob Carlborg <doob@me.com>
 *******************************************************************************/
module dwt.graphics.PaletteData;


import dwt.DWT;

import dwt.dwthelper.utils;
import dwt.graphics.RGB;

/**
 * Instances of this class describe the color data used by an image.
 * <p>
 * Depending on the depth of the image, the PaletteData can take one
 * of two forms, indicated by the isDirect field:
 * </p>
 * <dl>
 * <dt>
 * <em>isDirect is false</em>
 * </dt>
 * <dd>
 * If isDirect is <code>false</code>, this palette is an indexed
 * palette which maps pixel values to RGBs. The actual RGB values
 * may be retrieved by using the getRGBs() method.
 * </dd>
 * <dt>
 * <em>isDirect is true</em>
 * </dt>
 * <dd>
 * If isDirect is <code>true</code>, this palette is a direct color
 * palette. Instead of containing RGB values, it contains red,
 * green and blue mask and shift information which indicates how
 * the color components may be extracted from a given pixel.
 * This means that the RGB value is actually encoded in the pixel value.
 * <p>
 * In this case, the shift data is the number of bits required to shift
 * the RGB value to the left in order to align the high bit of the
 * corresponding mask with the high bit of the first byte. This number
 * may be negative, so care must be taken when shifting. For example,
 * with a red mask of 0xFF0000, the red shift would be -16. With a red
 * mask of 0x1F, the red shift would be 3.
 * </p>
 * </dd>
 * </dl>
 *
 * @see Image
 * @see RGB
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 */
 
public final class PaletteData {
    
    /**
     * true if the receiver is a direct palette, 
     * and false otherwise
     */
    public bool isDirect;
    
    /**
     * the RGB values for an indexed palette, where the
     * indices of the array correspond to pixel values
     */
    public RGB[] colors;
    
    /**
     * the red mask for a direct palette
     */
    public int redMask;
    
    /**
     * the green mask for a direct palette
     */
    public int greenMask;
    
    /**
     * the blue mask for a direct palette
     */
    public int blueMask;
    
    /**
     * the red shift for a direct palette
     */
    public int redShift;
    
    /**
     * the green shift for a direct palette
     */
    public int greenShift;
    
    /**
     * the blue shift for a direct palette
     */
    public int blueShift;

/**
 * Constructs a new indexed palette given an array of RGB values.
 *
 * @param colors the array of <code>RGB</code>s for the palette
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
 * </ul>
 */
public this(RGB[] colors) {
    if (colors is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
    this.colors = colors;
    this.isDirect = false;
}

/**
 * Constructs a new direct palette given the red, green and blue masks.
 *
 * @param redMask the red mask
 * @param greenMask the green mask
 * @param blueMask the blue mask
 */
public this(int redMask, int greenMask, int blueMask) {
    this.redMask = redMask;
    this.greenMask = greenMask;
    this.blueMask = blueMask;
    this.isDirect = true;
    this.redShift = shiftForMask(redMask);
    this.greenShift = shiftForMask(greenMask);
    this.blueShift = shiftForMask(blueMask);
}

/**
 * Returns the pixel value corresponding to the given <code>RGB</code>.
 *
 * @param rgb the RGB to get the pixel value for
 * @return the pixel value for the given RGB
 * 
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the RGB is not found in the palette</li>
 * </ul>
 */
public int getPixel(RGB rgb) {
    if (rgb is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
    if (isDirect) {
        int pixel = 0;
        pixel |= (redShift < 0 ? rgb.red << -redShift : rgb.red >>> redShift) & redMask;
        pixel |= (greenShift < 0 ? rgb.green << -greenShift : rgb.green >>> greenShift) & greenMask;
        pixel |= (blueShift < 0 ? rgb.blue << -blueShift : rgb.blue >>> blueShift) & blueMask;
        return pixel;
    } else {
        for (int i = 0; i < colors.length; i++) {
            if (colors[i].equals(rgb)) return i;
        }
        /* The RGB did not exist in the palette */
        DWT.error(DWT.ERROR_INVALID_ARGUMENT);
        return 0;
    }
}

/**
 * Returns an <code>RGB</code> corresponding to the given pixel value.
 *
 * @param pixel the pixel to get the RGB value for
 * @return the RGB value for the given pixel
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the argument is null</li>
 *    <li>ERROR_INVALID_ARGUMENT - if the pixel does not exist in the palette</li>
 * </ul>
 */
public RGB getRGB(int pixel) {
    if (isDirect) {
        int r = pixel & redMask;
        r = (redShift < 0) ? r >>> -redShift : r << redShift;
        int g = pixel & greenMask;
        g = (greenShift < 0) ? g >>> -greenShift : g << greenShift;
        int b = pixel & blueMask;
        b = (blueShift < 0) ? b >>> -blueShift : b << blueShift;
        return new RGB(r, g, b);
    } else {
        if (pixel < 0 || pixel >= colors.length) {
            DWT.error(DWT.ERROR_INVALID_ARGUMENT);
        }
        return colors[pixel];
    }
}

/**
 * Returns all the RGB values in the receiver if it is an
 * indexed palette, or null if it is a direct palette.
 *
 * @return the <code>RGB</code>s for the receiver or null
 */
public RGB[] getRGBs() {
    return colors;
}

/**
 * Computes the shift value for a given mask.
 *
 * @param mask the mask to compute the shift for
 * @return the shift amount
 *
 * @see PaletteData
 */
int shiftForMask(int mask) {
    for (int i = 31; i >= 0; i--) { 
        if (((mask >> i) & 0x1) !is 0) return 7 - i;
    }
    return 32;
}

}