1 /*******************************************************************************
2  * Copyright (c) 2004, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jface.resource;
15 
16 import org.eclipse.swt.graphics.Device;
17 import org.eclipse.swt.graphics.Font;
18 import org.eclipse.swt.graphics.FontData;
19 import org.eclipse.swt.widgets.Display;
20 
21 /**
22  * Lightweight descriptor for a font. Creates the described font on demand.
23  * Subclasses can implement different ways of describing a font. These objects
24  * will be compared, so hashCode(...) and equals(...) must return something
25  * meaningful.
26  *
27  * @since 3.1
28  */
29 public abstract class FontDescriptor extends DeviceResourceDescriptor {
30 
31 	/**
32 	 * Creates a FontDescriptor that describes an existing font. The resulting
33 	 * descriptor depends on the Font. Disposing the Font while the descriptor
34 	 * is still in use may throw a graphic disposed exception.
35 	 *
36 	 * @since 3.1
37 	 *
38 	 * @deprecated use {@link FontDescriptor#createFrom(Font)}
39 	 *
40 	 * @param font a font to describe
41 	 * @param originalDevice must be the same Device that was passed into
42 	 * the font's constructor when it was first created.
43 	 * @return a newly created FontDescriptor.
44 	 */
45 	@Deprecated
createFrom(Font font, Device originalDevice)46 	public static FontDescriptor createFrom(Font font, Device originalDevice) {
47 		return new ArrayFontDescriptor(font);
48 	}
49 
50 	/**
51 	 * Creates a FontDescriptor that describes an existing font. The resulting
52 	 * descriptor depends on the original Font, and disposing the original Font
53 	 * while the descriptor is still in use may cause SWT to throw a graphic
54 	 * disposed exception.
55 	 *
56 	 * @since 3.1
57 	 *
58 	 * @param font font to create
59 	 * @return a newly created FontDescriptor that describes the given font
60 	 */
createFrom(Font font)61 	public static FontDescriptor createFrom(Font font) {
62 		return new ArrayFontDescriptor(font);
63 	}
64 
65 	/**
66 	 * Creates a new FontDescriptor given the an array of FontData that describes
67 	 * the font.
68 	 *
69 	 * @since 3.1
70 	 *
71 	 * @param data an array of FontData that describes the font (will be passed into
72 	 * the Font's constructor)
73 	 * @return a FontDescriptor that describes the given font
74 	 */
createFrom(FontData[] data)75 	public static FontDescriptor createFrom(FontData[] data) {
76 		return new ArrayFontDescriptor(data);
77 	}
78 
79 	/**
80 	 * Creates a new FontDescriptor given the associated FontData
81 	 *
82 	 * @param data FontData describing the font to create
83 	 * @return a newly created FontDescriptor
84 	 */
createFrom(FontData data)85 	public static FontDescriptor createFrom(FontData data) {
86 		return new ArrayFontDescriptor(new FontData[]{data});
87 	}
88 
89 	/**
90 	 * Creates a new FontDescriptor given an OS-specific font name, height, and style.
91 	 *
92 	 * @see Font#Font(org.eclipse.swt.graphics.Device, java.lang.String, int, int)
93 	 *
94 	 * @param name os-specific font name
95 	 * @param height height (pixels)
96 	 * @param style a bitwise combination of NORMAL, BOLD, ITALIC
97 	 * @return a new FontDescriptor
98 	 */
createFrom(String name, int height, int style)99 	public static FontDescriptor createFrom(String name, int height, int style) {
100 		return createFrom(new FontData(name, height, style));
101 	}
102 
103 	/**
104 	 * Returns the set of FontData associated with this font. Modifying the elements
105 	 * in the returned array has no effect on the original FontDescriptor.
106 	 *
107 	 * @return the set of FontData associated with this font
108 	 * @since 3.3
109 	 */
getFontData()110 	public FontData[] getFontData() {
111 		Font tempFont = createFont(Display.getCurrent());
112 		FontData[] result = tempFont.getFontData();
113 		destroyFont(tempFont);
114 		return result;
115 	}
116 
117 	/**
118 	 * Returns an array of FontData containing copies of the FontData
119 	 * from the original.
120 	 *
121 	 * @param original array to copy
122 	 * @return a deep copy of the original array
123 	 * @since 3.3
124 	 */
copy(FontData[] original)125 	public static FontData[] copy(FontData[] original) {
126 		FontData[] result = new FontData[original.length];
127 		for (int i = 0; i < original.length; i++) {
128 			FontData next = original[i];
129 
130 			result[i] = copy(next);
131 		}
132 
133 		return result;
134 	}
135 
136 	/**
137 	 * Returns a copy of the original FontData
138 	 *
139 	 * @param next FontData to copy
140 	 * @return a copy of the given FontData
141 	 * @since 3.3
142 	 */
copy(FontData next)143 	public static FontData copy(FontData next) {
144 		FontData result = new FontData(next.getName(), next.getHeight(), next.getStyle());
145 		result.setLocale(next.getLocale());
146 		return result;
147 	}
148 
149 	/**
150 	 * Returns a FontDescriptor that is equivalent to the receiver, but uses
151 	 * the given style bits.
152 	 *
153 	 * <p>Does not modify the receiver.</p>
154 	 *
155 	 * @param style a bitwise combination of SWT.NORMAL, SWT.ITALIC and SWT.BOLD
156 	 * @return a new FontDescriptor with the given style
157 	 *
158 	 * @since 3.3
159 	 */
setStyle(int style)160 	public final FontDescriptor setStyle(int style) {
161 		FontData[] data = getFontData();
162 
163 		for (FontData next : data) {
164 			next.setStyle(style);
165 		}
166 
167 		// Optimization: avoid holding onto extra instances by returning the receiver if
168 		// if it is exactly the same as the result
169 		FontDescriptor result = new ArrayFontDescriptor(data);
170 		if (result.equals(this)) {
171 			return this;
172 		}
173 
174 		return result;
175 	}
176 
177 	/**
178 	 * <p>Returns a FontDescriptor that is equivalent to the receiver, but
179 	 * has the given style bits, in addition to any styles the receiver already has.</p>
180 	 *
181 	 * <p>Does not modify the receiver.</p>
182 	 *
183 	 * @param style a bitwise combination of SWT.NORMAL, SWT.ITALIC and SWT.BOLD
184 	 * @return a new FontDescriptor with the given additional style bits
185 	 * @since 3.3
186 	 */
withStyle(int style)187 	public final FontDescriptor withStyle(int style) {
188 		FontData[] data = getFontData();
189 
190 		for (FontData next : data) {
191 			next.setStyle(next.getStyle() | style);
192 		}
193 
194 		// Optimization: avoid allocating extra instances by returning the receiver if
195 		// if it is exactly the same as the result
196 		FontDescriptor result = new ArrayFontDescriptor(data);
197 		if (result.equals(this)) {
198 			return this;
199 		}
200 
201 		return result;
202 	}
203 
204 	/**
205 	 * <p>Returns a new FontDescriptor that is equivalent to the receiver, but
206 	 * has the given height.</p>
207 	 *
208 	 * <p>Does not modify the receiver.</p>
209 	 *
210 	 * @param height a height, in points
211 	 * @return a new FontDescriptor with the height, in points
212 	 * @since 3.3
213 	 */
setHeight(int height)214 	public final FontDescriptor setHeight(int height) {
215 		FontData[] data = getFontData();
216 
217 		for (FontData next : data) {
218 			next.setHeight(height);
219 		}
220 
221 		// Optimization: avoid holding onto extra instances by returning the receiver if
222 		// if it is exactly the same as the result
223 		FontDescriptor result = new ArrayFontDescriptor(data);
224 		if (result.equals(this)) {
225 			return this;
226 		}
227 
228 		return result;
229 	}
230 
231 	/**
232 	 * <p>Returns a FontDescriptor that is equivalent to the receiver, but whose height
233 	 * is larger by the given number of points.</p>
234 	 *
235 	 * <p>Does not modify the receiver.</p>
236 	 *
237 	 * @param heightDelta a change in height, in points. Negative values will return smaller
238 	 * fonts.
239 	 * @return a FontDescriptor whose height differs from the receiver by the given number
240 	 * of points.
241 	 * @since 3.3
242 	 */
increaseHeight(int heightDelta)243 	public final FontDescriptor increaseHeight(int heightDelta) {
244 		if (heightDelta == 0) {
245 			return this;
246 		}
247 		FontData[] data = getFontData();
248 
249 		for (FontData next : data) {
250 			next.setHeight(next.getHeight() + heightDelta);
251 		}
252 
253 		return new ArrayFontDescriptor(data);
254 	}
255 
256 	/**
257 	 * Creates the Font described by this descriptor.
258 	 *
259 	 * @since 3.1
260 	 *
261 	 * @param device device on which to allocate the font
262 	 * @return a newly allocated Font (never null)
263 	 * @throws DeviceResourceException if unable to allocate the Font
264 	 */
createFont(Device device)265 	public abstract Font createFont(Device device) throws DeviceResourceException;
266 
267 	/**
268 	 * Deallocates anything that was allocated by createFont, given a font
269 	 * that was allocated by an equal FontDescriptor.
270 	 *
271 	 * @since 3.1
272 	 *
273 	 * @param previouslyCreatedFont previously allocated font
274 	 */
destroyFont(Font previouslyCreatedFont)275 	public abstract void destroyFont(Font previouslyCreatedFont);
276 
277 	@Override
createResource(Device device)278 	public final Object createResource(Device device) throws DeviceResourceException {
279 		return createFont(device);
280 	}
281 
282 	@Override
destroyResource(Object previouslyCreatedObject)283 	public final void destroyResource(Object previouslyCreatedObject) {
284 		destroyFont((Font)previouslyCreatedObject);
285 	}
286 }
287