Path: blob/master/src/java.desktop/unix/classes/sun/awt/X11CustomCursor.java
41152 views
/*1* Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.awt;2627import sun.awt.CustomCursor;28import java.awt.*;29import java.awt.image.*;30import sun.awt.image.ImageRepresentation;3132/**33* A class to encapsulate a custom image-based cursor.34*35* @see Component#setCursor36* @author Thomas Ball37*/38@SuppressWarnings("serial") // JDK-implementation class39public abstract class X11CustomCursor extends CustomCursor {4041public X11CustomCursor(Image cursor, Point hotSpot, String name)42throws IndexOutOfBoundsException {43super(cursor, hotSpot, name);44}4546protected void createNativeCursor(Image im, int[] pixels, int width, int height,47int xHotSpot, int yHotSpot) {4849class CCount implements Comparable<CCount> {50int color;51int count;5253public CCount(int cl, int ct) {54color = cl;55count = ct;56}5758public int compareTo(CCount cc) {59return cc.count - count;60}61}6263int[] tmp = new int[pixels.length];64for (int i=0; i<pixels.length; i++) {65if ((pixels[i] & 0xff000000) == 0) {66tmp[i] = -1;67} else {68tmp[i] = pixels[i] & 0x00ffffff;69}70}71java.util.Arrays.sort(tmp);7273int fc = 0x000000;74int bc = 0xffffff;75CCount[] cols = new CCount[pixels.length];7677int is = 0;78int numColors = 0;79while ( is < pixels.length ) {80if (tmp[is] != -1) {81cols[numColors++] = new CCount(tmp[is], 1);82break;83}84is ++;85}8687for (int i = is+1; i < pixels.length; i++) {88if (tmp[i] != cols[numColors-1].color) {89cols[numColors++] = new CCount(tmp[i], 1);90} else {91cols[numColors-1].count ++;92}93}94java.util.Arrays.sort(cols, 0, numColors);9596if (numColors > 0) fc = cols[0].color;97int fcr = (fc >> 16) & 0x000000ff;98int fcg = (fc >> 8) & 0x000000ff;99int fcb = (fc >> 0) & 0x000000ff;100101int rdis = 0;102int gdis = 0;103int bdis = 0;104for (int j = 1; j < numColors; j++) {105int rr = (cols[j].color >> 16) & 0x000000ff;106int gg = (cols[j].color >> 8) & 0x000000ff;107int bb = (cols[j].color >> 0) & 0x000000ff;108rdis = rdis + cols[j].count * rr;109gdis = gdis + cols[j].count * gg;110bdis = bdis + cols[j].count * bb;111}112int rest = pixels.length - ((numColors > 0) ? cols[0].count : 0);113// 4653170 Avoid divide / zero exception114if (rest > 0) {115rdis = rdis / rest - fcr;116gdis = gdis / rest - fcg;117bdis = bdis / rest - fcb;118}119rdis = (rdis*rdis + gdis*gdis + bdis*bdis) / 2;120// System.out.println(" rdis is "+ rdis);121122for (int j = 1; j < numColors; j++) {123int rr = (cols[j].color >> 16) & 0x000000ff;124int gg = (cols[j].color >> 8) & 0x000000ff;125int bb = (cols[j].color >> 0) & 0x000000ff;126127if ( (rr-fcr)*(rr-fcr) + (gg-fcg)*(gg-fcg) + (bb-fcb)*(bb-fcb)128>= rdis ) {129bc = cols[j].color;130break;131}132}133int bcr = (bc >> 16) & 0x000000ff;134int bcg = (bc >> 8) & 0x000000ff;135int bcb = (bc >> 0) & 0x000000ff;136137138// On Solaris 2.5.x, the above code for cursor of any size runs fine139// 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 cursor142// with a transparent area to make a new cursor of width 8 multiples.143// --- Bug 4148455144int wNByte = (width + 7)/8;145int tNByte = wNByte * height;146byte[] xorMask = new byte[tNByte];147byte[] andMask = new byte[tNByte];148149for (int i = 0; i < width; i++) {150int omask = 1 << (i % 8);151for (int j = 0; j < height; j++) {152int ip = j*width + i;153int ibyte = j*wNByte + i/8;154155if ((pixels[ip] & 0xff000000) != 0) {156andMask[ibyte] |= omask;157}158159int pr = (pixels[ip] >> 16) & 0x000000ff;160int pg = (pixels[ip] >> 8) & 0x000000ff;161int pb = (pixels[ip] >> 0) & 0x000000ff;162if ( (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 color165xorMask[ibyte] |= omask;166}167}168}169170createCursor(xorMask, andMask, 8*wNByte, height, fc, bc, xHotSpot, yHotSpot);171}172173protected abstract void createCursor(byte[] xorMask, byte[] andMask,174int width, int height,175int fcolor, int bcolor,176int xHotSpot, int yHotSpot);177178}179180181