001: /*
002: * Copyright 1997-2003 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt;
027:
028: import sun.awt.CustomCursor;
029: import java.awt.*;
030: import java.awt.image.*;
031: import sun.awt.image.ImageRepresentation;
032:
033: /**
034: * A class to encapsulate a custom image-based cursor.
035: *
036: * @see Component#setCursor
037: * @version 1.25 05/05/07
038: * @author Thomas Ball
039: */
040: public abstract class X11CustomCursor extends CustomCursor {
041:
042: public X11CustomCursor(Image cursor, Point hotSpot, String name)
043: throws IndexOutOfBoundsException {
044: super (cursor, hotSpot, name);
045: }
046:
047: protected void createNativeCursor(Image im, int[] pixels,
048: int width, int height, int xHotSpot, int yHotSpot) {
049:
050: class CCount implements Comparable {
051: int color;
052: int count;
053:
054: public CCount(int cl, int ct) {
055: color = cl;
056: count = ct;
057: }
058:
059: public int compareTo(Object cc) {
060: return ((CCount) cc).count - count;
061: }
062: }
063:
064: int tmp[] = new int[pixels.length];
065: for (int i = 0; i < pixels.length; i++) {
066: if ((pixels[i] & 0xff000000) == 0) {
067: tmp[i] = -1;
068: } else {
069: tmp[i] = pixels[i] & 0x00ffffff;
070: }
071: }
072: java.util.Arrays.sort(tmp);
073:
074: int fc = 0x000000;
075: int bc = 0xffffff;
076: CCount cols[] = new CCount[pixels.length];
077:
078: int is = 0;
079: int numColors = 0;
080: while (is < pixels.length) {
081: if (tmp[is] != -1) {
082: cols[numColors++] = new CCount(tmp[is], 1);
083: break;
084: }
085: is++;
086: }
087:
088: for (int i = is + 1; i < pixels.length; i++) {
089: if (tmp[i] != cols[numColors - 1].color) {
090: cols[numColors++] = new CCount(tmp[i], 1);
091: } else {
092: cols[numColors - 1].count++;
093: }
094: }
095: java.util.Arrays.sort(cols, 0, numColors);
096:
097: if (numColors > 0)
098: fc = cols[0].color;
099: int fcr = (fc >> 16) & 0x000000ff;
100: int fcg = (fc >> 8) & 0x000000ff;
101: int fcb = (fc >> 0) & 0x000000ff;
102:
103: int rdis = 0;
104: int gdis = 0;
105: int bdis = 0;
106: for (int j = 1; j < numColors; j++) {
107: int rr = (cols[j].color >> 16) & 0x000000ff;
108: int gg = (cols[j].color >> 8) & 0x000000ff;
109: int bb = (cols[j].color >> 0) & 0x000000ff;
110: rdis = rdis + cols[j].count * rr;
111: gdis = gdis + cols[j].count * gg;
112: bdis = bdis + cols[j].count * bb;
113: }
114: int rest = pixels.length
115: - ((numColors > 0) ? cols[0].count : 0);
116: // 4653170 Avoid divide / zero exception
117: if (rest > 0) {
118: rdis = rdis / rest - fcr;
119: gdis = gdis / rest - fcg;
120: bdis = bdis / rest - fcb;
121: }
122: rdis = (rdis * rdis + gdis * gdis + bdis * bdis) / 2;
123: // System.out.println(" rdis is "+ rdis);
124:
125: for (int j = 1; j < numColors; j++) {
126: int rr = (cols[j].color >> 16) & 0x000000ff;
127: int gg = (cols[j].color >> 8) & 0x000000ff;
128: int bb = (cols[j].color >> 0) & 0x000000ff;
129:
130: if ((rr - fcr) * (rr - fcr) + (gg - fcg) * (gg - fcg)
131: + (bb - fcb) * (bb - fcb) >= rdis) {
132: bc = cols[j].color;
133: break;
134: }
135: }
136: int bcr = (bc >> 16) & 0x000000ff;
137: int bcg = (bc >> 8) & 0x000000ff;
138: int bcb = (bc >> 0) & 0x000000ff;
139:
140: // On Solaris 2.5.x, the above code for cursor of any size runs fine
141: // but on Solaris 2.6, the width of a cursor has to be 8 divisible,
142: // otherwise, the cursor could be displayed as garbaged.
143: // To work around the 2.6 problem, the following code pads any cursor
144: // with a transparent area to make a new cursor of width 8 multiples.
145: // --- Bug 4148455
146: int wNByte = (width + 7) / 8;
147: int tNByte = wNByte * height;
148: byte[] xorMask = new byte[tNByte];
149: byte[] andMask = new byte[tNByte];
150:
151: for (int i = 0; i < width; i++) {
152: int omask = 1 << (i % 8);
153: for (int j = 0; j < height; j++) {
154: int ip = j * width + i;
155: int ibyte = j * wNByte + i / 8;
156:
157: if ((pixels[ip] & 0xff000000) != 0) {
158: andMask[ibyte] |= omask;
159: }
160:
161: int pr = (pixels[ip] >> 16) & 0x000000ff;
162: int pg = (pixels[ip] >> 8) & 0x000000ff;
163: int pb = (pixels[ip] >> 0) & 0x000000ff;
164: if ((pr - fcr) * (pr - fcr) + (pg - fcg) * (pg - fcg)
165: + (pb - fcb) * (pb - fcb) <= (pr - bcr)
166: * (pr - bcr) + (pg - bcg) * (pg - bcg)
167: + (pb - bcb) * (pb - bcb)) {
168: // show foreground color
169: xorMask[ibyte] |= omask;
170: }
171: }
172: }
173:
174: createCursor(xorMask, andMask, 8 * wNByte, height, fc, bc,
175: xHotSpot, yHotSpot);
176: }
177:
178: protected abstract void createCursor(byte[] xorMask,
179: byte[] andMask, int width, int height, int fcolor,
180: int bcolor, int xHotSpot, int yHotSpot);
181:
182: }
|