/* * Created on Mar 7, 2010 11:10:45 AM * Copyright (C) 2010 Aelitis, All Rights Reserved. * * 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. * * AELITIS, SAS au capital de 46,603.30 euros * 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France. */ package com.aelitis.azureus.ui.swt.utils; import java.lang.reflect.Method; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.*; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.gudy.azureus2.core3.util.Debug; import org.gudy.azureus2.ui.swt.Utils; /** * @author TuxPaper * @created Mar 7, 2010 * */ public class FontUtils { private static Method mFontData_SetHeight; private static Method mFontData_GetHeightF; private static Font fontBold; static { try { mFontData_SetHeight = FontData.class.getDeclaredMethod("setHeight", new Class[] { float.class }); mFontData_SetHeight.setAccessible(true); } catch (Throwable e) { mFontData_SetHeight = null; } try { mFontData_GetHeightF = FontData.class.getDeclaredMethod("getHeightF", new Class[] { }); mFontData_GetHeightF.setAccessible(true); } catch (Throwable e) { mFontData_GetHeightF = null; } } /** * * @param baseFont * @param gc Can be null * @param heightInPixels * @return * * @since 3.0.0.7 */ public static float getFontHeightFromPX(Font baseFont, GC gc, int heightInPixels) { Font font = null; Device device = baseFont.getDevice(); // hack.. heightInPixels++; // This isn't accurate, but gets us close float[] size = { Utils.pixelsToPoint(heightInPixels, device.getDPI().y) + 1 }; if (size[0] <= 0) { return 0; } boolean bOurGC = gc == null || gc.isDisposed(); try { if (bOurGC) { gc = new GC(device); } FontData[] fontData = baseFont.getFontData(); font = findFont(gc, font, fontData, size, heightInPixels, SWT.DEFAULT); } finally { if (bOurGC) { gc.dispose(); } if (font != null && !font.isDisposed()) { font.dispose(); } } return size[0]; } public static float getFontHeightFromPX(Device device, FontData[] fontData, GC gc, int heightInPixels) { Font font = null; // hack.. heightInPixels++; // This isn't accurate, but gets us close float[] size = { Utils.pixelsToPoint(heightInPixels, device.getDPI().y) + 1 }; if (size[0] <= 0) { return 0; } boolean bOurGC = gc == null || gc.isDisposed(); try { if (bOurGC) { gc = new GC(device); } font = findFont(gc, font, fontData, size, heightInPixels, SWT.DEFAULT); } finally { if (bOurGC) { gc.dispose(); } if (font != null && !font.isDisposed()) { font.dispose(); } } return size[0]; } public static Font getFontWithHeight(Font baseFont, GC gc, int heightInPixels) { return getFontWithHeight(baseFont, gc, heightInPixels, SWT.DEFAULT); } public static Font getFontWithHeight(Font baseFont, GC gc, int heightInPixels, int style) { Font font = null; Device device = baseFont.getDevice(); // hack.. heightInPixels++; // This isn't accurate, but gets us close float[] size = { Utils.pixelsToPoint(heightInPixels, device.getDPI().y) + 1 }; if (size[0] <= 0) { size[0] = 2; } boolean bOurGC = gc == null || gc.isDisposed(); try { if (bOurGC) { gc = new GC(device); } FontData[] fontData = baseFont.getFontData(); font = findFont(gc, font, fontData, size, heightInPixels, style); } finally { if (bOurGC) { gc.dispose(); } } return font; } public static void setFontDataHeight(FontData[] fd, float fontSize) { if (mFontData_SetHeight != null) { try { mFontData_SetHeight.invoke(fd[0], fontSize); return; } catch (Throwable e) { } } fd[0].setHeight((int) fontSize); } private static Font findFont(GC gc, Font font, FontData[] fontData, float[] size, int heightInPixels, int style) { if (mFontData_SetHeight != null) { return findFontByFloat(gc, font, fontData, size, heightInPixels, style); } return findFontByInt(gc, font, fontData, size, heightInPixels, style); } public static Font findFontByInt(GC gc, Font font, FontData[] fontData, float[] returnSize, int heightInPixels, int style) { int size = (int) returnSize[0]; do { if (font != null) { size--; font.dispose(); } fontData[0].setHeight(size); if (style != SWT.DEFAULT) { fontData[0].setStyle(style); } font = new Font(gc.getDevice(), fontData); gc.setFont(font); } while (font != null && gc.textExtent(Utils.GOOD_STRING).y > heightInPixels && size > 1); returnSize[0] = size; return font; } public static Font findFontByFloat(GC gc, Font font, FontData[] fontData, float[] returnSize, int heightInPixels, int style) { float size = returnSize[0]; float delta = 2.0f; boolean fits; int numLoops = 0; do { numLoops++; if (font != null) { size -= delta; font.dispose(); } try { mFontData_SetHeight.invoke(fontData[0], size); } catch (Throwable e) { Debug.out(e); } if (style != SWT.DEFAULT) { fontData[0].setStyle(style); } font = new Font(gc.getDevice(), fontData); gc.setFont(font); //System.out.println("yay " + size + " = " // + gc.textExtent(Utils.GOOD_STRING).y + " (want " + heightInPixels // + ")"); fits = gc.textExtent(Utils.GOOD_STRING).y <= heightInPixels; if (fits && delta > .1) { size += delta; delta /= 2; fits = false; } } while (!fits && size > 1); returnSize[0] = size; return font; } public static int getFontHeightInPX(FontData[] fd) { Font font = new Font(Display.getDefault(), fd); try { return getFontHeightInPX(font); } finally { font.dispose(); } } public static int getFontHeightInPX(Font font) { GC gc = new GC(font.getDevice()); try { gc.setFont(font); return gc.textExtent(Utils.GOOD_STRING).y; } finally { gc.dispose(); } } /** * Change the height of the installed <code>Font</code> and takes care of disposing * the new font when the control is disposed * @param control * @param height * @param style one or both of SWT.BOLD, SWT.ITALIC, or SWT.NORMAL */ public static void setFontHeight(Control control, int height, int style) { FontData[] fDatas = control.getFont().getFontData(); for (int i = 0; i < fDatas.length; i++) { fDatas[i].height = height; fDatas[i].setStyle(style); } final Font newFont = new Font(control.getDisplay(), fDatas); control.setFont(newFont); control.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { if (null != newFont && false == newFont.isDisposed()) { newFont.dispose(); } } }); } public static float getHeight(FontData[] fd) { if (mFontData_GetHeightF != null) { try { return ((Number) mFontData_GetHeightF.invoke(fd[0], new Object[] {})).floatValue(); } catch (Throwable e) { } } return fd[0].getHeight(); } public static Font getFontPercentOf(Font baseFont, float pct) { FontData[] fontData = baseFont.getFontData(); float height = getHeight(fontData) * pct; setFontDataHeight(fontData, height); return new Font(baseFont.getDevice(), fontData); } public static Font getAnyFontBold(GC gc) { if (fontBold == null) { FontData[] fontData = gc.getFont().getFontData(); for (int i = 0; i < fontData.length; i++) { FontData fd = fontData[i]; fd.setStyle(SWT.BOLD); } fontBold = new Font(gc.getDevice(), fontData); } return fontBold; } }