📄 iconholder.java
字号:
/*
* LumaQQ - Java QQ Client
*
* Copyright (C) 2004 luma <stubma@163.com>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.tsinghua.lumaqq;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.PaletteData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import edu.tsinghua.lumaqq.qq.Util;
/**
* 管理图像资源,程序协议切换到2004,使用2004头像的选项不再使用,注释掉
*/
public class IconHolder {
// Log
private static Log log = LogFactory.getLog(IconHolder.class);
// resource id
public static final int
icoOnline = 0,
icoAway = 1,
icoHidden = 2,
icoOffline = 3,
icoQQ = 4,
icoAbout = 5,
icoExit = 6,
icoSysMsg = 7,
icoSysOpt = 8,
icoChangeUser = 9,
icoBackground = 10,
icoPersonInfo = 11,
bmpLogin = 12,
icoReply = 13,
icoNoReply = 14,
icoCustomReply = 15,
icoMessage = 16,
icoSearch = 17,
icoLargeFace = 18,
icoSmallFace = 19,
icoAddGroup = 20,
icoDelGroup = 21,
icoAddFriend = 22,
icoShowOnlineOnly = 23,
icoShowBlackList = 24,
icoRename = 25,
icoSortFriend = 26,
icoDisplayName = 27,
icoHideBlackList = 28,
icoChecked = 29,
icoFriendInfoManage = 30,
icoDelFriend = 31,
icoSendReceiveMessage = 32,
icoFont = 33,
icoSmiley = 34,
icoQuickReply = 35,
icoBlank = 36,
icoArrow = 37,
bmpSearch = 38,
icoSendFile = 39,
icoGroup = 40,
icoUploadGroup = 41,
icoDownloadGroup = 42,
icoMe = 43,
bmpTipBackground = 44,
bmpDefaultQQShow = 45,
bmpDownloading = 46,
icoMessageManage = 47,
icoTxtFile = 48,
icoCopy = 49,
icoCluster = 50,
icoSearchCluster = 51,
icoAddCluster = 52,
icoFolder = 53,
icoRightArrow = 54,
icoLeftArrow = 55,
bmpOnlineTipBackground = 56,
icoNotFound = 57,
icoYes = 58,
icoNo = 59,
icoFriend = 60,
icoApply = 61,
icoDownloadRemark = 62,
icoBack = 63,
icoForward = 64,
icoRefresh = 65,
icoStop = 66,
icoUpdate = 67,
icoFirefox = 68,
bmpCheckUpdate = 69,
icoSearchIp = 70,
icoNA = 71,
icoColor = 72,
icoIn = 73,
icoOut = 74,
icoFragment = 75,
icoDebug = 76,
icoMobile = 77,
icoSMSBlink = 78,
icoPalm = 79,
icoPalms = 80,
icoMachine = 81,
icoChatroom = 82,
icoRefreshFriend = 83,
icoAddAlbum = 84,
icoMobileFriend = 85,
icoFriendView = 86,
icoSysOpt24 = 87,
icoModifyPersonInfo24 = 88,
icoChangeQQShow = 89,
icoQQHome = 90,
icoQQShowMall = 91,
icoQQGame = 92,
icoViewPersonInfo24 = 93,
icoAboutTitleImage = 94,
icoSearchWizard = 95,
icoNext = 96,
icoPrevious = 97,
icoWarning = 98,
icoDebugBytes = 99,
icoDebugInput = 100,
icoDebugPacket = 101,
icoDebugFormat = 102,
icoDebugSend = 103,
icoLeaf = 104,
icoClusterWizard = 105,
bmpSmth = 106,
icoCam32 = 107,
icoSendFile32 = 108,
icoMobile32 = 109,
icoExport24 = 110,
icoImport24 = 111,
icoAddFaceGroup24 = 112,
icoModifyFaceGroup24 = 113,
icoDeleteFaceGroup24 = 114,
bmpLogin2 = 115;
// resource location
public static final String[] resourceLocations = {
"/edu/tsinghua/lumaqq/icons/online.gif",
"/edu/tsinghua/lumaqq/icons/away.gif",
"/edu/tsinghua/lumaqq/icons/hidden.gif",
"/edu/tsinghua/lumaqq/icons/offline.gif",
"/edu/tsinghua/lumaqq/icons/qq.gif",
"/edu/tsinghua/lumaqq/icons/about.gif",
"/edu/tsinghua/lumaqq/icons/exit.gif",
"/edu/tsinghua/lumaqq/icons/sysmsg.gif",
"/edu/tsinghua/lumaqq/icons/sysoption.gif",
"/edu/tsinghua/lumaqq/icons/changeuser.gif",
"/edu/tsinghua/lumaqq/icons/bg.gif",
"/edu/tsinghua/lumaqq/icons/personinfo.gif",
"/edu/tsinghua/lumaqq/bitmaps/login.gif",
"/edu/tsinghua/lumaqq/icons/reply.gif",
"/edu/tsinghua/lumaqq/icons/noreply.gif",
"/edu/tsinghua/lumaqq/icons/customreply.gif",
"/edu/tsinghua/lumaqq/icons/message.gif",
"/edu/tsinghua/lumaqq/icons/search.gif",
"/edu/tsinghua/lumaqq/icons/largeface.gif",
"/edu/tsinghua/lumaqq/icons/smallface.gif",
"/edu/tsinghua/lumaqq/icons/addgroup.gif",
"/edu/tsinghua/lumaqq/icons/delgroup.gif",
"/edu/tsinghua/lumaqq/icons/addfriend.gif",
"/edu/tsinghua/lumaqq/icons/showonlineonly.gif",
"/edu/tsinghua/lumaqq/icons/showblacklist.gif",
"/edu/tsinghua/lumaqq/icons/rename.gif",
"/edu/tsinghua/lumaqq/icons/sortfriend.gif",
"/edu/tsinghua/lumaqq/icons/displayname.gif",
"/edu/tsinghua/lumaqq/icons/hideblacklist.gif",
"/edu/tsinghua/lumaqq/icons/checked.gif",
"/edu/tsinghua/lumaqq/icons/friendinfomanage.gif",
"/edu/tsinghua/lumaqq/icons/delfriend.gif",
"/edu/tsinghua/lumaqq/icons/sendreceivemessage.gif",
"/edu/tsinghua/lumaqq/icons/font.gif",
"/edu/tsinghua/lumaqq/icons/smiley.gif",
"/edu/tsinghua/lumaqq/icons/quickreply.gif",
"/edu/tsinghua/lumaqq/icons/blank.gif",
"/edu/tsinghua/lumaqq/icons/arrow.gif",
"/edu/tsinghua/lumaqq/bitmaps/search.gif",
"/edu/tsinghua/lumaqq/icons/sendfile.gif",
"/edu/tsinghua/lumaqq/icons/group.gif",
"/edu/tsinghua/lumaqq/icons/uploadgroup.gif",
"/edu/tsinghua/lumaqq/icons/downloadgroup.gif",
"/edu/tsinghua/lumaqq/icons/me.gif",
"/edu/tsinghua/lumaqq/bitmaps/tipbackground.gif",
"/edu/tsinghua/lumaqq/bitmaps/defaultqqshow.gif",
"/edu/tsinghua/lumaqq/bitmaps/downloading.gif",
"/edu/tsinghua/lumaqq/icons/messagemanage.gif",
"/edu/tsinghua/lumaqq/icons/txtfile.gif",
"/edu/tsinghua/lumaqq/icons/copy.gif",
"/edu/tsinghua/lumaqq/icons/cluster.gif",
"/edu/tsinghua/lumaqq/icons/searchcluster.gif",
"/edu/tsinghua/lumaqq/icons/addcluster.gif",
"/edu/tsinghua/lumaqq/icons/folder.gif",
"/edu/tsinghua/lumaqq/icons/rightarrow.gif",
"/edu/tsinghua/lumaqq/icons/leftarrow.gif",
"/edu/tsinghua/lumaqq/bitmaps/onlinetipbackground.gif",
"/edu/tsinghua/lumaqq/icons/notfound.gif",
"/edu/tsinghua/lumaqq/icons/yes.gif",
"/edu/tsinghua/lumaqq/icons/no.gif",
"/edu/tsinghua/lumaqq/icons/friend.gif",
"/edu/tsinghua/lumaqq/icons/apply.gif",
"/edu/tsinghua/lumaqq/icons/downloadremark.gif",
"/edu/tsinghua/lumaqq/icons/back.gif",
"/edu/tsinghua/lumaqq/icons/forward.gif",
"/edu/tsinghua/lumaqq/icons/refresh.gif",
"/edu/tsinghua/lumaqq/icons/stop.gif",
"/edu/tsinghua/lumaqq/icons/update.gif",
"/edu/tsinghua/lumaqq/icons/firefox.gif",
"/edu/tsinghua/lumaqq/bitmaps/checkupdate.gif",
"/edu/tsinghua/lumaqq/icons/searchip.gif",
"/edu/tsinghua/lumaqq/icons/na.gif",
"/edu/tsinghua/lumaqq/icons/colorsetting.gif",
"/edu/tsinghua/lumaqq/icons/in.gif",
"/edu/tsinghua/lumaqq/icons/out.gif",
"/edu/tsinghua/lumaqq/icons/frag.gif",
"/edu/tsinghua/lumaqq/icons/debug.gif",
"/edu/tsinghua/lumaqq/icons/mobile.gif",
"/edu/tsinghua/lumaqq/icons/smsblink.gif",
"/edu/tsinghua/lumaqq/icons/palm.gif",
"/edu/tsinghua/lumaqq/icons/palms.gif",
"/edu/tsinghua/lumaqq/icons/machine.gif",
"/edu/tsinghua/lumaqq/icons/chatroom.gif",
"/edu/tsinghua/lumaqq/icons/refreshfriend.gif",
"/edu/tsinghua/lumaqq/icons/addalbum.gif",
"/edu/tsinghua/lumaqq/icons/mobilefriend.gif",
"/edu/tsinghua/lumaqq/icons/friendview.gif",
"/edu/tsinghua/lumaqq/icons/sysoption_24.gif",
"/edu/tsinghua/lumaqq/icons/modifypersoninfo_24.gif",
"/edu/tsinghua/lumaqq/icons/changeqqshow.gif",
"/edu/tsinghua/lumaqq/icons/qqhome.gif",
"/edu/tsinghua/lumaqq/icons/qqshowmall.gif",
"/edu/tsinghua/lumaqq/icons/qqgame.gif",
"/edu/tsinghua/lumaqq/icons/viewpersoninfo_24.gif",
"/edu/tsinghua/lumaqq/icons/abouttitleimage.gif",
"/edu/tsinghua/lumaqq/icons/searchwizard.gif",
"/edu/tsinghua/lumaqq/icons/next.gif",
"/edu/tsinghua/lumaqq/icons/previous.gif",
"/edu/tsinghua/lumaqq/icons/warning.gif",
"/edu/tsinghua/lumaqq/icons/debug_bytes.gif",
"/edu/tsinghua/lumaqq/icons/debug_input.gif",
"/edu/tsinghua/lumaqq/icons/debug_packet.gif",
"/edu/tsinghua/lumaqq/icons/debug_format.gif",
"/edu/tsinghua/lumaqq/icons/debug_send.gif",
"/edu/tsinghua/lumaqq/icons/leaf.gif",
"/edu/tsinghua/lumaqq/icons/clusterwizard.gif",
"/edu/tsinghua/lumaqq/bitmaps/smth.gif",
"/edu/tsinghua/lumaqq/icons/cam_32.gif",
"/edu/tsinghua/lumaqq/icons/sendfile_32.gif",
"/edu/tsinghua/lumaqq/icons/mobile_32.gif",
"/edu/tsinghua/lumaqq/icons/export_24.gif",
"/edu/tsinghua/lumaqq/icons/import_24.gif",
"/edu/tsinghua/lumaqq/icons/addfacegroup_24.gif",
"/edu/tsinghua/lumaqq/icons/modifyfacegroup_24.gif",
"/edu/tsinghua/lumaqq/icons/deletefacegroup_24.gif",
"/edu/tsinghua/lumaqq/bitmaps/login2.gif"
};
// 表情顺序号和代码数组,索引0存放的是顺序号,索引1存放的是code
private int[][] smileySeqCode;
// 表情代码和顺序号数组,索引0是code,索引1是顺序号
// 顺序号的范围在0-95之间,code的范围在65-160之间,所以需要把code减去65得到数组索引
private int[][] smileyCodeSeq;
// 离开图标和隐身图标的数据
private RGB[] naRGB;
private int[][] naPixel;
private RGB[] leafRGB;
private int[][] leafPixel;
// 单一实例
private static IconHolder holder = new IconHolder();
// 2004头像最大索引
public static final int QQ_2004_FACE_MAX_INDEX = 303;
// 一些路径常量
private static final String HEAD_PATH_PREFIX = "/edu/tsinghua/lumaqq/head/";
private static final String SMALL_HEAD_PATH_PREFIX = "/edu/tsinghua/lumaqq/smallhead/";
private static final String CLUSTER_HEAD_PATH_PREFIX = "/edu/tsinghua/lumaqq/clusterhead/";
private static final String FACE_PATH_PREFIX = "/edu/tsinghua/lumaqq/face/";
// 注册表
private ImageRegistry registry;
/**
* 私有构造,singleton模式
*/
private IconHolder() {
// 创建图像注册表
registry = new ImageRegistry(Display.getCurrent());
// 读取缺省表情映射文件
Properties p = new Properties();
try {
p.load(this.getClass().getResourceAsStream("/face.properties"));
int size = p.size();
smileySeqCode = new int[size][2];
smileyCodeSeq = new int[size][2];
for(int i = 0; i < size; i++) {
int code = Util.getInt(p.getProperty(String.valueOf(i)), 65);
smileySeqCode[i][0] = i;
smileySeqCode[i][1] = code;
smileyCodeSeq[code - 65][0] = code;
smileyCodeSeq[code - 65][1] = i;
}
} catch (IOException e) {
log.error(e.getMessage());
}
}
/**
* @return 实例
*/
public static IconHolder getInstance() {
return holder;
}
/**
* @param imageId 图标id
* @return 图标
*/
public Image getImage(int resId) {
if(resId < 0 || resId >= resourceLocations.length) return null;
return getImage(resourceLocations[resId]);
}
/**
* 得到程序图标
* @param s 资源路径
* @return Image
*/
private Image getImage(String s) {
Image ret = registry.get(s);
if(ret == null) {
ret = createImageFromJar(s);
if(ret != null)
registry.put(s, ret);
return ret;
} else
return ret;
}
/**
* 得到图像描述符
*
* @param resId
* 资源ID
* @return
* ImageDescriptor
*/
public ImageDescriptor getImageDescriptor(int resId) {
ImageDescriptor ret = registry.getDescriptor(resourceLocations[resId]);
if(ret == null) {
ret = ImageDescriptor.createFromFile(LumaQQ.class, resourceLocations[resId]);
if(ret != null)
registry.put(resourceLocations[resId], ret);
return ret;
} else
return ret;
}
/**
* 得到隐身头像
*
* @param faceId
* 头像序号
* @return
* 隐身头像
*/
public Image getHiddenHead(int faceId) {
if(faceId < 0) faceId = 0;
if(faceId >= QQ_2004_FACE_MAX_INDEX)
faceId = QQ_2004_FACE_MAX_INDEX - 3;
int major = faceId / 3 + 1;
String face = HEAD_PATH_PREFIX + major + ".gif";
// 检查cache中是否有隐身头像
String faceHidden = face + ".hidden";
Image image = registry.get(faceHidden);
if(image == null) {
// 构建2004风格离开头像
image = createHiddenImage(face);
registry.put(faceHidden, image);
}
return image;
}
/**
* @param face
* @return
*/
private Image createHiddenImage(String path) {
// 载入原始图像
Display dispay = Display.getCurrent();
Image face = new Image(dispay, getClass().getResourceAsStream(path));
Image faceHidden = null;
// 载入离开标志
Image leaf = getImage(icoLeaf);
// 得到图像数据和调色板和图像尺寸
ImageData faceData = face.getImageData();
ImageData leafData = leaf.getImageData();
PaletteData facePalette = faceData.palette;
PaletteData leafPalette = leafData.palette;
Rectangle faceBound = face.getBounds();
Rectangle leafBound = leaf.getBounds();
// 得到替换的起始坐标
int startX = faceBound.width - leafBound.width;
int startY = faceBound.height - leafBound.height;
if(facePalette.isDirect == leafPalette.isDirect) {
if(facePalette.isDirect) {
// 替换
for(int x = startX, leafX = 0; x < faceBound.width; x++, leafX++) {
for(int y = startY, leafY = 0; y < faceBound.height; y++, leafY++) {
if(leafData.getPixel(leafX, leafY) != 0)
faceData.setPixel(x, y, leafData.getPixel(leafX, leafY));
}
}
} else {
// 提取叶子图标数据
extractLeafRgb();
// 拷贝N/A图标的RGB数据到原始图像的调色板中
int delta = facePalette.colors.length - leafRGB.length;
System.arraycopy(leafRGB, 0, facePalette.colors, delta, leafRGB.length);
// 替换
for(int x = startX, leafX = 0; x < faceBound.width; x++, leafX++) {
for(int y = startY, leafY = 0; y < faceBound.height; y++, leafY++) {
if(leafPixel[leafX][leafY] != 0)
faceData.setPixel(x, y, leafPixel[leafX][leafY] + delta);
}
}
}
faceHidden = new Image(dispay, faceData);
face.dispose();
return faceHidden;
} else if(facePalette.isDirect) {
simpleAreaCopy(face, leaf);
return face;
} else {
// 提取叶子图标数据
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -