/* * This file is a part of the Jop-UI * Copyright (C) 2009, Stefan Resch (e0425306@student.tuwien.ac.at) * Stefan Rottensteiner (e0425058@student.tuwien.ac.at) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package com.jopdesign.jopui.core; import com.jopdesign.jopui.helper.Color8Bit; /** * For drawing to images. Can draw images, fonts, primitives. */ public class Graphics { /** * State value for enable/disable color key. <p> * Constant has the value 0x1 */ public static final int COLOR_KEY = 0x1; /** * Status of a state <p> * Constant has the value 0x0 */ public static final int DISABLE = 0x0; /** * Status of a state <p> * Constant has the value 0x1 */ public static final int ENABLE = 0x1; /** * Informs, that an unknown state is enabled/disabled <p> * Constant has the value 0x2 */ public static final int UNKNOWN_STATE = 0x2; private Image destImage; private int curColor; private Bounds curClip; private Font curFont; private int colorKey; private static int stateColorKey; Graphics(Image image) { destImage = image; curClip = new Bounds(0,0,image.getWidth(),image.getHeight()); curFont = JopFont.getInstance(); curColor = Color8Bit.convert(0xFF); colorKey = image.colorKey; } /** * <p>Draws an ellipse or circle </p> * <p>If xRadius equals yRadius a circle will be drawn. Only pixel inside the clipping window will be drawn </p> * <pre> * Used Algorithm: * A Fast Bresenham Type Algorithm. For Drawing Circles * John Kennedy. Mathematics Department. Santa Monica College. 1900 Pico Blvd. Santa Monica, CA 90405 * </pre> * @param cx x-coordinate of the center * @param cy y-coordinate of the center * @param xRadius pixel width in x direction * @param yRadius pixel width in y direction */ public void drawArc(int cx, int cy, int xRadius, int yRadius) { int x, y; int xChange, yChange; int ellipseError; int twoASquare, twoBSquare; int xStopping, yStopping; int xSquare = xRadius*xRadius; int ySquare = yRadius*yRadius; twoASquare = 2*xSquare; twoBSquare = 2*ySquare; x = xRadius; y = 0; xChange = ySquare*(1-2*xRadius); yChange = xSquare; ellipseError = 0; xStopping = twoBSquare * xRadius; yStopping = 0; while(xStopping >= yStopping) { ellipseSetPixel(cx,cy,x,y); y++; yStopping += twoASquare; ellipseError += yChange; yChange += twoASquare; if((2*ellipseError + xChange) > 0) { x--; xStopping -= twoBSquare; ellipseError += xChange; xChange += twoBSquare; } } x = 0; y = yRadius; xChange = ySquare; yChange = xSquare*(1-2*yRadius); ellipseError = 0; xStopping = 0; yStopping = twoASquare*yRadius; while(xStopping <= yStopping) { ellipseSetPixel(cx,cy,x,y); x++; xStopping += twoBSquare; ellipseError += xChange; xChange += twoBSquare; if((2*ellipseError + yChange) > 0) { y--; yStopping -= twoASquare; ellipseError += yChange; yChange += twoASquare; } } } private void ellipseSetPixel(int cx, int cy, int x, int y) { int adr; int absolute_adr; int adroffset; int xpos, ypos; int clipXmin = curClip.x; int clipXmax = curClip.x + curClip.width - 1; int clipYmin = curClip.y; int clipYmax = curClip.y + curClip.height - 1; for(int i=0; i<4; ++i) { switch(i) { case 0: xpos = cx + x; ypos = cy + y; break; case 1: xpos = cx + x; ypos = cy - y; break; case 2: xpos = cx - x; ypos = cy + y; break; case 3: xpos = cx - x; ypos = cy - y; break; default: continue; } if(xpos >= clipXmin && xpos <= clipXmax && ypos >= clipYmin && ypos <= clipYmax) { adr = xpos + ypos*destImage.width; absolute_adr = adr>>2; adroffset = 8*(adr & 0x03); destImage.data[absolute_adr] &= ~(0xFF << adroffset); destImage.data[absolute_adr] |= curColor << adroffset; } } } /** * <p>Reads the colorvalue of a given pixel </p> * <pre> * Conditions: * clipping window x <= x < clipping window x + clipping window width * clipping window y <= y < clipping window y + clipping window height * </pre> * @param x x-coordinate of the pixel * @param y y-coordinate of the pixel * @return if P(x,y) is inside the clipping window an 8 bit colorvalue will be returned otherwise 0x100 */ public int getPixel(int x, int y) { int clipXmin = curClip.x; int clipXmax = curClip.x + curClip.width - 1; int clipYmin = curClip.y; int clipYmax = curClip.y + curClip.height - 1; if(x >= clipXmin && x <= clipXmax && y >= clipYmin && y <= clipYmax) { int adr = (x+y*destImage.width); int absolute_adr = adr>>2; int adroffset = 8*(adr & 0x03); return (0xFF & (destImage.data[absolute_adr] >> adroffset)); } return (0x100); } /** * <p>Set the given pixel to the current color </p> * <pre> * Conditions: * clipping window x <= x < clipping window x + clipping window width * clipping window y <= y < clipping window y + clipping window height * If pixel is outside the clipping window, no pixel will be drawn * </pre> * @param x x-coordinate of the pixel * @param y y-coordinate of the pixel * @param x x-coordinate of the pixel * @param y y-coordinate of the pixel */ public void setPixel(int x, int y) { int clipXmin = curClip.x; int clipXmax = curClip.x + curClip.width - 1; int clipYmin = curClip.y; int clipYmax = curClip.y + curClip.height - 1; if(x >= clipXmin && x <= clipXmax && y >= clipYmin && y <= clipYmax) { int adr = (x+y*destImage.width); //position in the one-dimensional pixelarray int absolute_adr = adr>>2; //because 4 pixel are stored per int int adroffset = 8*(adr & 0x03); //which of the 4 pixel destImage.data[absolute_adr] &= ~(0xFF << adroffset); //read int destImage.data[absolute_adr] |= curColor << adroffset; //write color to the right pos } } /** * <p>Draws a ascii character at the specific location </p> * <p>Every character is drawn on a 8*10 pixel grid.</p> * <pre> * Conditions: * if character is unknown, no character is drawn * Only pixel inside the clipping area will be drawn * </pre> * @param character character to be drawn. * @param x x-coordinate of the upper left corner of the 8*10 grid * @param y y-coordinate of the upper left corner of the 8*10 grid */ public void drawChar(char character, int x, int y) { if((stateColorKey == ENABLE) && (curColor == colorKey)) { return; } int [] ch = curFont.getChar(character); if(ch == null) return; int c1 = 0x0; int c2 = 0x0; int c3 = 0x0; /* * characters are stored in int arrays with length 3. * for some, length of 2 or 1 is enough. */ switch(ch.length) { case 1: c1 = ch[0]; break; case 2: c1 = ch[0]; c2 = ch[1]; break; case 3: c1 = ch[0]; c2 = ch[1]; c3 = ch[2]; break; default: return; } int w = curFont.getWidth(); //8 int h = curFont.getHeight(); //10 int clipXmin = curClip.x; int clipXmax = curClip.x + curClip.width - 1; int clipYmin = curClip.y; int clipYmax = curClip.y + curClip.height -1; int cx=0, cy = 0; for(int addr = 0; addr < w*h; addr++) { int buf; if(cx == w) { cx = 0; cy++; } switch(addr >> 5) { case 0: buf = c1; break; case 1: buf = c2; break; case 2: buf = c3; break; default: buf = 0; } if((buf & (1<<(addr & 63))) != 0) { int nx = cx + x; int ny = cy + y; if(nx >= clipXmin && nx <= clipXmax && ny >= clipYmin && ny <= clipYmax) { int adr = (nx+ny*destImage.width); int absolute_adr = adr>>2; int adroffset = 8*(adr & 0x03); destImage.data[absolute_adr] &= ~(0xFF << adroffset); destImage.data[absolute_adr] |= curColor << adroffset; } } cx++; } } /** * <p>Draws a sequence of ascii characters</p> * <pre> * Conditions: * if data == null no character will be drawn * if offset < 0 or length < 0 no character will be drawn * if offset + length > the length of the data array no character will be drawn * Only pixel inside the clipping area will be drawn * </pre> * @param data array holding the string * @param offset start index for the array * @param length number of chars to be drawn * @param x x-coordinate of the upper left corner of the 8*10 grid * @param y y-coordinate of the upper left corner of the 8*10 grid */ public void drawChars(char[] data, int offset, int length, int x, int y) { if((stateColorKey == ENABLE) && (curColor == colorKey)) { return; } if(data == null) return; if(offset < 0 || length < 0) return; if((offset + length) > data.length) return; int w = curFont.getWidth(); for(int i=0; i<length; ++i) { char c = data[offset + i]; int nx = x + i*w; drawChar(c, nx, y); } } /** * <p>Draws an image to the specific location</p> * <p>Image will be clipped with the current clipping window</p> * <pre> * Conditions: * if img is null no image will be drawn * Only pixel inside the clipping window will be drawn * </pre> * @param img image to be drawn * @param x x-coordinate of the upper left corner of the image * @param y x-coordinate of the upper left corner of the image */ public void drawImage(Image img, int x, int y) { if(img == null) return; Bounds srcRect = new Bounds(0,0,img.getWidth(),img.getHeight()); int srcWidth = img.getWidth(); int srcHeight = img.getHeight(); /* calculate drawable area, so no clipping check is needed per pixelset later */ if(srcRect.x < 0) { srcRect.width += srcRect.x; srcRect.x = 0; } if(srcRect.y < 0) { srcRect.height += srcRect.y; srcRect.y = 0; } if(srcRect.width > srcWidth) { srcRect.width = srcWidth; } if(srcRect.height > srcHeight) { srcRect.height = srcWidth; } Bounds drawable = new Bounds(x, y, srcRect.width, srcRect.height); int x1 = 0; int y1 = 0; int w = 0; int h = 0; if( (drawable.x > curClip.x+curClip.width-1) || (drawable.x+drawable.width-1 < curClip.x) || (drawable.y > curClip.y+curClip.height-1) || (drawable.y+drawable.height-1 < curClip.y)) { return; } if(drawable.x < curClip.x) x1 = curClip.x; else x1 = drawable.x; if(drawable.y < curClip.y) y1 = curClip.y; else y1 = drawable.y; if(drawable.x+drawable.width < curClip.x+curClip.width) w = drawable.x+drawable.width - x1; else w = curClip.x+curClip.width - x1; if(drawable.y+drawable.height < curClip.y+curClip.height) h = drawable.y+drawable.height - y1; else h = curClip.y+curClip.height - y1; drawable.set(x1, y1, w, h); int xn, yn, wn, hn; xn = srcRect.x + srcRect.width - drawable.width; yn = srcRect.y + srcRect.height - drawable.height; wn = drawable.width; hn = drawable.height; // read pixel for pixel for(int i=yn; i<hn+yn; ++i) { for(int j=xn; j<wn+xn; ++j) { // read pixel from source image int adr = (j+i*img.width); int absolute_adr = adr>>2; int adroffset = 8*(adr & 0x03); int c = 0xFF & (img.data[absolute_adr] >> adroffset); // only draw visible pixel if((stateColorKey == ENABLE) && (c == colorKey)) { continue; } // write pixel to destination image adr = ((drawable.x+j)+(drawable.y+i)*destImage.width); absolute_adr = adr>>2; adroffset = 8*(adr & 0x03); destImage.data[absolute_adr] &= ~(0xFF << adroffset); destImage.data[absolute_adr] |= c << adroffset; } } } /** * <p>Draws a line between to points</p> * <pre> * Conditions: * Only pixel inside the clipping window will be drawn * </pre> * @param x1 x-coordinate of the first point * @param y1 y-coordinate of the first point * @param x2 x-coordinate of the second point * @param y2 y-coordinate of the second point */ public void drawLine(int x1, int y1, int x2, int y2) { if((stateColorKey == ENABLE) && (curColor == colorKey)) { return; } int x,y,xEnd,yEnd; int xInc=1,yInc=1; int dx,dy; int clipXmin = curClip.x; int clipXmax = curClip.x + curClip.width - 1; int clipYmin = curClip.y; int clipYmax = curClip.y + curClip.height -1; int twody,TwoDymTwoDx,p; /* * |dx|<|dy|...|m|>1...bCheck=true * |dx|>|dy|...|m|<1...bCheck=false * |dx|=|dy|...|m|=1...bCheck=false */ boolean bCheck=Math.abs(x2-x1)<Math.abs(y2-y1); if(bCheck) { x=y1; y=x1; xEnd=y2; yEnd=x2; } else { x=x1; y=y1; xEnd=x2; yEnd=y2; } // always draw from left endpoint to right endpoint if(x>xEnd) { //swap x,xEnd x = x ^ xEnd; xEnd = xEnd ^x; x = x ^ xEnd; //swap y,yEnd y = y ^ yEnd; yEnd = yEnd ^ y; y = y ^ yEnd; } // decrease the y-coordinate for a neg. slope if(yEnd<y) yInc=-1; dx = Math.abs(xEnd-x); dy = Math.abs(yEnd-y); twody = 2*dy; TwoDymTwoDx = 2*(dy-dx); p = twody-dx; // if |m|>1 change roles of x and y calculations // clip & draw current Pixel and calculate next one if(bCheck) { while(x<=xEnd) { if(y >= clipXmin && y <= clipXmax && x >= clipYmin && x <= clipYmax) { int adr = (y+x*destImage.width); int absolute_adr = adr>>2; int offset = 8*(adr & 0x03); destImage.data[absolute_adr] &= ~(0xFF << offset); destImage.data[absolute_adr] |= curColor << offset; } if(p<0) { p+=twody; } else { p+=TwoDymTwoDx; y+=yInc; } x+=xInc; } } else { while(x<=xEnd) { if(x >= clipXmin && x <= clipXmax && y >= clipYmin && y <= clipYmax) { int adr = (x+y*destImage.width); int absolute_adr = adr>>2; int offset = 8*(adr & 0x03); destImage.data[absolute_adr] &= ~(0xFF << offset); destImage.data[absolute_adr] |= curColor << offset; } if(p<0) { p+=twody; } else { p+=TwoDymTwoDx; y+=yInc; } x+=xInc; } } } /** * <p>Draws a rectangle</p> * <pre> * Conditions: * if width or height <= 0 no rectangle will be drawn * Only pixel inside the clipping window will be drawn * </pre> * @param x x-coordinate of the upper left corner * @param y y-coordinate of the upper left corner * @param width width of the rectangle * @param height height of the rectangle */ public void drawRect(int x, int y, int width, int height) { if((stateColorKey == ENABLE) && (curColor == colorKey)) { return; } if(width <= 0 || height <= 0) return; drawLine(x,y,x+width-1,y); drawLine(x+width-1,y,x+width-1,y+height-1); drawLine(x+width-1,y+height-1,x,y+height-1); drawLine(x,y+height-1,x,y); } /** * <p>Draws a region of a source image to the destination image</p> * <pre> * Conditions: * if src == null no action is performed * if width or height <= 0 no action is performed * if width > destination image no action is performed * if height > destination image no action is performed * Only pixel inside the clipping window will be drawn * </pre> * @param src source image * @param x_src x-coordinate of the upper left corner of the region * @param y_src y-coordinate of the upper left corner of the region * @param width width of the region * @param height height of the region * @param transform transformation to be used for the region * @param x_dest x-coordinate for the destination upper left corner * @param y_dest y-coordinate for the destination upper left corner */ public void drawRegion(Image src, int x_src, int y_src, int width, int height, int transform, int x_dest, int y_dest) { if(src == null) return; if(width <= 0 || height <= 0) return; if(width > src.getWidth() || height > src.getHeight()) return; Image tmp = null; tmp = Image.createImage(src,x_src,y_src,width,height,transform); if(tmp == null) return; Bounds srcRect = new Bounds(0,0,tmp.getWidth(),tmp.getHeight()); int srcWidth = tmp.getWidth(); int srcHeight = tmp.getHeight(); if(srcRect.x < 0) { srcRect.width += srcRect.x; srcRect.x = 0; } if(srcRect.y < 0) { srcRect.height += srcRect.y; srcRect.y = 0; } if(srcRect.width > srcWidth) { srcRect.width = srcWidth; } if(srcRect.height > srcHeight) { srcRect.height = srcWidth; } Bounds drawable = new Bounds(x_dest, y_dest, srcRect.width, srcRect.height); int x1 = 0; int y1 = 0; int w = 0; int h = 0; if( (drawable.x > curClip.x+curClip.width-1) || (drawable.x+drawable.width-1 < curClip.x) || (drawable.y > curClip.y+curClip.height-1) || (drawable.y+drawable.height-1 < curClip.y)) { return; } if(drawable.x < curClip.x) x1 = curClip.x; else x1 = drawable.x; if(drawable.y < curClip.y) y1 = curClip.y; else y1 = drawable.y; if(drawable.x+drawable.width < curClip.x+curClip.width) w = drawable.x+drawable.width - x1; else w = curClip.x+curClip.width - x1; if(drawable.y+drawable.height < curClip.y+curClip.height) h = drawable.y+drawable.height - y1; else h = curClip.y+curClip.height - y1; drawable.set(x1, y1, w, h); int xn, yn, wn, hn; xn = srcRect.x + srcRect.width - drawable.width; yn = srcRect.y + srcRect.height - drawable.height; wn = drawable.width; hn = drawable.height; for(int i=yn; i<hn+yn; ++i) { for(int j=xn; j<wn+xn; ++j) { int adr = (j+i*tmp.width); int absolute_adr = adr>>2; int adroffset = 8*(adr & 0x03); int c = 0xFF & (tmp.data[absolute_adr] >> adroffset); if((stateColorKey == ENABLE) && (c == colorKey)) { continue; } adr = ((drawable.x+j)+(drawable.y+i)*destImage.width); absolute_adr = adr>>2; adroffset = 8*(adr & 0x03); destImage.data[absolute_adr] &= ~(0xFF << adroffset); destImage.data[absolute_adr] |= c << adroffset; } } } /** * <p>Draws an image with the given rgb data</p> * <pre> * Conditions: * if rgbData == null no action is performed * if x of y or offset < 0 no action is performed * if width or height <= 0 no action is performed * if scanlength < width no action is performed * if x + width > destination image width no action is performed * if y + height > destination image height no action is performed * if width * height + offset > the length of rgbData no action is performed * Only pixel inside the clipping window will be drawn * </pre> * @param rgbData image data * @param offset offset in the image data array * @param scanlength length of one scanline in the image data array * @param x x-coordinate of the upper left corner of the destination * @param y y-coordinate of the upper left corner of the destination * @param width width of the image * @param height height of the image */ public void drawRGB(int[] rgbData, int offset, int scanlength, int x, int y, int width, int height) { if(rgbData == null) return; if(x < 0 || y < 0 || width <= 0 || height <= 0 || offset < 0 || scanlength < width) return; int imgWidth = destImage.getWidth(); if((x + width > imgWidth) || (y + height > destImage.getHeight())) return; if((width*height + offset) > rgbData.length) return; int [] data = destImage.getData(); int adr; int absolute_adr; int adroffset; for(int j=y; j<height; ++j) { for(int i=x; i<width; ++i) { adr = (i+j*imgWidth); absolute_adr = adr>>2; adroffset = 8*(adr & 0x03); data[absolute_adr] &= ~(0xFF << adroffset); data[absolute_adr] |= rgbData[offset + (i-x) + (j-y)*scanlength] << adroffset; } } } /** * <p>Draws a string to the specific location</p> * <pre> * Conditions: * if str == null no action is performed * if str is an empty string no action is performed * Only pixel inside the clipping window will be drawn * </pre> * @param str string to be drawn * @param x x-coordinate of the upper left corner of the character grid * @param y x-coordinate of the upper left corner of the character grid */ public void drawString(String str, int x, int y) { if((stateColorKey == ENABLE) && (curColor == colorKey)) { return; } if(str == null) return; int length = str.length(); if(length == 0) return; char [] dest = new char[length]; str.getChars(0, length, dest, 0); drawChars(dest,0,length,x,y); } /** * <p>Draws a string to the specific location</p> * <pre> * Conditions: * if str == null no action is performed * if str is an empty string no action is performed * if offset + len > length no action is performed * Only pixel inside the clipping window will be drawn * </pre> * @param str string to be drawn * @param offset start index in the string * @param len number of chars to be drawn * @param x x-coordinate of the upper left corner of the character grid * @param y y-coordinate of the upper left corner of the character grid */ public void drawSubstring(String str, int offset, int len, int x, int y) { if((stateColorKey == ENABLE) && (curColor == colorKey)) { return; } if(str == null) return; int length = str.length(); if(length == 0) return; if((offset + len)> length) return; String sub = str.substring(offset, offset+len); drawString(sub,x,y); } /** * <p>Fill a circle/ellipse with the current color</p> * <pre> * Used Algorithm: * A Fast Bresenham Type Algorithm. For Drawing Circles * John Kennedy. Mathematics Department. Santa Monica College. 1900 Pico Blvd. Santa Monica, CA 90405 * </pre> * @param cx x-coordinate of the center * @param cy y-coordinate of the center * @param xRadius pixel width in x diBoundson * @param yRadius pixel width in y diBoundson */ public void fillArc(int cx, int cy, int xRadius, int yRadius) { int x, y; int xChange, yChange; int ellipseError; int twoASquare, twoBSquare; int xStopping, yStopping; int xSquare = xRadius*xRadius; int ySquare = yRadius*yRadius; twoASquare = 2*xSquare; twoBSquare = 2*ySquare; x = xRadius; y = 0; xChange = ySquare*(1-2*xRadius); yChange = xSquare; ellipseError = 0; xStopping = twoBSquare * xRadius; yStopping = 0; while(xStopping >= yStopping) { drawLine(cx-x,cy+y,cx+x,cy+y); drawLine(cx-x,cy-y,cx+x,cy-y); y++; yStopping += twoASquare; ellipseError += yChange; yChange += twoASquare; if((2*ellipseError + xChange) > 0) { x--; xStopping -= twoBSquare; ellipseError += xChange; xChange += twoBSquare; } } x = 0; y = yRadius; xChange = ySquare; yChange = xSquare*(1-2*yRadius); ellipseError = 0; xStopping = 0; yStopping = twoASquare*yRadius; while(xStopping <= yStopping) { drawLine(cx-x,cy+y,cx+x,cy+y); drawLine(cx-x,cy-y,cx+x,cy-y); x++; xStopping += twoBSquare; ellipseError += xChange; xChange += twoBSquare; if((2*ellipseError + yChange) > 0) { y--; yStopping -= twoASquare; ellipseError += yChange; yChange += twoASquare; } } } /** * <p>Fills a recangle with the current color</p> * <p>Only pixel inside the clipping window will be drawn</p> * * @param x x-coordinate for the upper left corner * @param y y-coordinate for the upper left corner * @param width width of the rectangle * @param height height of the rectangle */ public void fillRect(int x, int y, int width, int height) { if((stateColorKey == ENABLE) && (curColor == colorKey)) { return; } int clipXmin = curClip.x; int clipXmax = curClip.x + curClip.width - 1; int clipYmin = curClip.y; int clipYmax = curClip.y + curClip.height -1; if(x == 0 && y == 0 && width == destImage.width && height == destImage.height) { int c = (curColor<<24) | (curColor<<16) | (curColor<<8) | curColor; for(int i=0; i<destImage.data.length; ++i) { destImage.data[i] = c; } return; } int xStart = x; int xStop = x + width - 1; int yStart = y; int yStop = y + height - 1; int adr; int absolute_adr; int adroffset; if(x > clipXmax || y > clipYmax) return; if((x + width) < clipXmin || (y + height) < clipYmin) return; if(x < clipXmin) xStart = clipXmin; if(y < clipYmin) yStart = clipYmin; if(x+width > clipXmax) xStop = clipXmax; if(y+height > clipYmax) yStop = clipYmax; // fill rectangle pixel per pixel for(int i=yStart; i<=yStop; ++i) { for(int j=xStart; j<=xStop; ++j) { adr = (j+i*destImage.width); absolute_adr = adr>>2; adroffset = 8*(adr & 0x03); destImage.data[absolute_adr] &= ~(0xFF << adroffset); destImage.data[absolute_adr] |= curColor << adroffset; } } } /** * <p>Set the clipping window</p> * <pre> * Conditions: * if x or y < 0 no action is performed * if width or height >= 0 no action is performed * if x+width > destination image width no action is performed * if y+height > destination image height no action is performed * </pre> * @param x x-coordinate of the upper left corner of the clipping window in pixel * @param y y-coordinate of the upper left corner of the clipping window in pixel * @param width width of the clipping window in pixel * @param height height of the clipping window in pixel */ public void setClip(int x, int y, int width, int height) { if(x < 0 || y < 0 || width <= 0 || height <= 0) return; if(x+width > destImage.getWidth() || y+height > destImage.getHeight()) return; curClip.set(x, y, width, height); } /** * Set the current color * * @param RGB an 8 bit value */ public void setColor(int RGB) { curColor = Color8Bit.convert(RGB); } /** * <p>Set the current color</p> * Greater values as given bits will be truncated * @param red 3 bit value * @param green 2 bit value * @param blue 2 bit value */ public void setColor(int red, int green, int blue) { curColor = Color8Bit.convert(red, green, blue); } /** * Set current font * * @param font font to be used */ public void setFont(Font font) { curFont = font; } /** * Get the red value of the current color * @return red color value */ public int getRedComponent() { return Color8Bit.getRed(curColor); } /** * Get the green value of the current color * @return green color value */ public int getGreenComponent() { return Color8Bit.getGreen(curColor); } /** * Get the blue value of the current color * @return blue color value */ public int getBlueComponent() { return Color8Bit.getBlue(curColor); } /** * Get the current color * @return current color value */ public int getColor() { return curColor; } /** * Get the current font * @return current font */ public Font getFont() { return curFont; } /** * Get the x-coordinate of the clipping window * * @return x-coordinate of clipping window */ public int getClipX() { return curClip.x; } /** * Get the y-coordinate of the clipping window * * @return y-coordinate of clipping window */ public int getClipY() { return curClip.y; } /** * Get the width of the clipping window * * @return width of clipping window */ public int getClipWidth() { return curClip.width; } /** * Get the height of the clipping window * * @return height of clipping window */ public int getClipHeight() { return curClip.height; } /** * <p>Enable states for drawing</p> * <pre> * State: * COLOR_KEY * </pre> * @param state state to be enabled */ public static void enable(int state) { switch(state) { case COLOR_KEY: stateColorKey = ENABLE; break; default: } } /** * <p>Disable states for drawing</p> * <pre> * State: * COLOR_KEY * </pre> * @param state state to be disabled */ public static void disable(int state) { switch(state) { case COLOR_KEY: stateColorKey = DISABLE; break; default: } } /** * <p>Test if a state is enabled/disabled</p> * <pre> * State: * COLOR_KEY * </pre> * @param state state to be tested * @return state value or UNKNOWN_STATE if state is currently not implemented */ public static int isEnabled(int state) { switch(state) { case COLOR_KEY: return stateColorKey; default: return UNKNOWN_STATE; } } }