1 /* 2 * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.awt; 27 28 import sun.awt.CustomCursor; 29 import java.awt.*; 30 import java.awt.image.*; 31 import sun.awt.image.ImageRepresentation; 32 33 /** 34 * A class to encapsulate a custom image-based cursor. 35 * 36 * @see Component#setCursor 37 * @author Thomas Ball 38 */ 39 public abstract class X11CustomCursor extends CustomCursor { 40 X11CustomCursor(Image cursor, Point hotSpot, String name)41 public X11CustomCursor(Image cursor, Point hotSpot, String name) 42 throws IndexOutOfBoundsException { 43 super(cursor, hotSpot, name); 44 } 45 createNativeCursor(Image im, int[] pixels, int width, int height, int xHotSpot, int yHotSpot)46 protected void createNativeCursor(Image im, int[] pixels, int width, int height, 47 int xHotSpot, int yHotSpot) { 48 49 class CCount implements Comparable { 50 int color; 51 int count; 52 53 public CCount(int cl, int ct) { 54 color = cl; 55 count = ct; 56 } 57 58 public int compareTo(Object cc) { 59 return ((CCount)cc).count - count; 60 } 61 } 62 63 int tmp[] = new int[pixels.length]; 64 for (int i=0; i<pixels.length; i++) { 65 if ((pixels[i] & 0xff000000) == 0) { 66 tmp[i] = -1; 67 } else { 68 tmp[i] = pixels[i] & 0x00ffffff; 69 } 70 } 71 java.util.Arrays.sort(tmp); 72 73 int fc = 0x000000; 74 int bc = 0xffffff; 75 CCount cols[] = new CCount[pixels.length]; 76 77 int is = 0; 78 int numColors = 0; 79 while ( is < pixels.length ) { 80 if (tmp[is] != -1) { 81 cols[numColors++] = new CCount(tmp[is], 1); 82 break; 83 } 84 is ++; 85 } 86 87 for (int i = is+1; i < pixels.length; i++) { 88 if (tmp[i] != cols[numColors-1].color) { 89 cols[numColors++] = new CCount(tmp[i], 1); 90 } else { 91 cols[numColors-1].count ++; 92 } 93 } 94 java.util.Arrays.sort(cols, 0, numColors); 95 96 if (numColors > 0) fc = cols[0].color; 97 int fcr = (fc >> 16) & 0x000000ff; 98 int fcg = (fc >> 8) & 0x000000ff; 99 int fcb = (fc >> 0) & 0x000000ff; 100 101 int rdis = 0; 102 int gdis = 0; 103 int bdis = 0; 104 for (int j = 1; j < numColors; j++) { 105 int rr = (cols[j].color >> 16) & 0x000000ff; 106 int gg = (cols[j].color >> 8) & 0x000000ff; 107 int bb = (cols[j].color >> 0) & 0x000000ff; 108 rdis = rdis + cols[j].count * rr; 109 gdis = gdis + cols[j].count * gg; 110 bdis = bdis + cols[j].count * bb; 111 } 112 int rest = pixels.length - ((numColors > 0) ? cols[0].count : 0); 113 // 4653170 Avoid divide / zero exception 114 if (rest > 0) { 115 rdis = rdis / rest - fcr; 116 gdis = gdis / rest - fcg; 117 bdis = bdis / rest - fcb; 118 } 119 rdis = (rdis*rdis + gdis*gdis + bdis*bdis) / 2; 120 // System.out.println(" rdis is "+ rdis); 121 122 for (int j = 1; j < numColors; j++) { 123 int rr = (cols[j].color >> 16) & 0x000000ff; 124 int gg = (cols[j].color >> 8) & 0x000000ff; 125 int bb = (cols[j].color >> 0) & 0x000000ff; 126 127 if ( (rr-fcr)*(rr-fcr) + (gg-fcg)*(gg-fcg) + (bb-fcb)*(bb-fcb) 128 >= rdis ) { 129 bc = cols[j].color; 130 break; 131 } 132 } 133 int bcr = (bc >> 16) & 0x000000ff; 134 int bcg = (bc >> 8) & 0x000000ff; 135 int bcb = (bc >> 0) & 0x000000ff; 136 137 138 // On Solaris 2.5.x, the above code for cursor of any size runs fine 139 // but on Solaris 2.6, the width of a cursor has to be 8 divisible, 140 // otherwise, the cursor could be displayed as garbaged. 141 // To work around the 2.6 problem, the following code pads any cursor 142 // with a transparent area to make a new cursor of width 8 multiples. 143 // --- Bug 4148455 144 int wNByte = (width + 7)/8; 145 int tNByte = wNByte * height; 146 byte[] xorMask = new byte[tNByte]; 147 byte[] andMask = new byte[tNByte]; 148 149 for (int i = 0; i < width; i++) { 150 int omask = 1 << (i % 8); 151 for (int j = 0; j < height; j++) { 152 int ip = j*width + i; 153 int ibyte = j*wNByte + i/8; 154 155 if ((pixels[ip] & 0xff000000) != 0) { 156 andMask[ibyte] |= omask; 157 } 158 159 int pr = (pixels[ip] >> 16) & 0x000000ff; 160 int pg = (pixels[ip] >> 8) & 0x000000ff; 161 int pb = (pixels[ip] >> 0) & 0x000000ff; 162 if ( (pr-fcr)*(pr-fcr) + (pg-fcg)*(pg-fcg) + (pb-fcb)*(pb-fcb) 163 <= (pr-bcr)*(pr-bcr) + (pg-bcg)*(pg-bcg) + (pb-bcb)*(pb-bcb) ) { 164 // show foreground color 165 xorMask[ibyte] |= omask; 166 } 167 } 168 } 169 170 createCursor(xorMask, andMask, 8*wNByte, height, fc, bc, xHotSpot, yHotSpot); 171 } 172 createCursor(byte[] xorMask, byte[] andMask, int width, int height, int fcolor, int bcolor, int xHotSpot, int yHotSpot)173 protected abstract void createCursor(byte[] xorMask, byte[] andMask, 174 int width, int height, 175 int fcolor, int bcolor, 176 int xHotSpot, int yHotSpot); 177 178 } 179