History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/font/Font2D.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/font/Font2D.java+534−0
@@ -0,0 +1,534 @@
1/*
2 * Copyright (c) 2003, 2010, 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
26package sun.font;
27
28import java.awt.Font;
29import java.awt.font.FontRenderContext;
30import java.awt.geom.AffineTransform;
31import java.lang.ref.Reference;
32import java.lang.ref.SoftReference;
33import java.util.concurrent.ConcurrentHashMap;
34import java.util.Locale;
35
36public abstract class Font2D {
37
38 /* Note: JRE and FONT_CONFIG ranks are identical. I don't know of a reason
39 * to distingish these. Possibly if a user adds fonts to the JRE font
40 * directory that are the same font as the ones specified in the font
41 * configuration but that is more likely to be the legitimate intention
42 * than a problem. One reason why these should be the same is that on
43 * Linux the JRE fonts ARE the font configuration fonts, and although I
44 * believe all are assigned FONT_CONFIG rank, it is conceivable that if
45 * this were not so, that some JRE font would not be allowed to joint the
46 * family of its siblings which were assigned FONT_CONFIG rank. Giving
47 * them the same rank is the easy solution for now at least.
48 */
49 public static final int FONT_CONFIG_RANK = 2;
50 public static final int JRE_RANK = 2;
51 public static final int TTF_RANK = 3;
52 public static final int TYPE1_RANK = 4;
53 public static final int NATIVE_RANK = 5;
54 public static final int UNKNOWN_RANK = 6;
55 public static final int DEFAULT_RANK = 4;
56
57 private static final String[] boldNames = {
58 "bold", "demibold", "demi-bold", "demi bold", "negreta", "demi", };
59
60 private static final String[] italicNames = {
61 "italic", "cursiva", "oblique", "inclined", };
62
63 private static final String[] boldItalicNames = {
64 "bolditalic", "bold-italic", "bold italic",
65 "boldoblique", "bold-oblique", "bold oblique",
66 "demibold italic", "negreta cursiva","demi oblique", };
67
68 private static final FontRenderContext DEFAULT_FRC =
69 new FontRenderContext(null, false, false);
70
71 public Font2DHandle handle;
72 protected String familyName; /* Family font name (english) */
73 protected String fullName; /* Full font name (english) */
74 protected int style = Font.PLAIN;
75 protected FontFamily family;
76 protected int fontRank = DEFAULT_RANK;
77
78 /*
79 * A mapper can be independent of the strike.
80 * Perhaps the reference to the mapper ought to be held on the
81 * scaler, as it may be implemented via scaler functionality anyway
82 * and so the mapper would be useless if its native portion was
83 * freed when the scaler was GC'd.
84 */
85 protected CharToGlyphMapper mapper;
86
87 /*
88 * The strike cache is maintained per "Font2D" as that is the
89 * principal object by which you look up fonts.
90 * It means more Hashmaps, but look ups can be quicker because
91 * the map will have fewer entries, and there's no need to try to
92 * make the Font2D part of the key.
93 */
94 protected ConcurrentHashMap<FontStrikeDesc, Reference>
95 strikeCache = new ConcurrentHashMap<FontStrikeDesc, Reference>();
96
97 /* Store the last Strike in a Reference object.
98 * Similarly to the strike that was stored on a C++ font object,
99 * this is an optimisation which helps if multiple clients (ie
100 * typically SunGraphics2D instances) are using the same font, then
101 * as may be typical of many UIs, they are probably using it in the
102 * same style, so it can be a win to first quickly check if the last
103 * strike obtained from this Font2D satifies the needs of the next
104 * client too.
105 * This pre-supposes that a FontStrike is a shareable object, which
106 * it should.
107 */
108 protected Reference lastFontStrike = new SoftReference(null);
109
110 /*
111 * POSSIBLE OPTIMISATION:
112 * Array of length 1024 elements of 64 bits indicating if a font
113 * contains these. This kind of information can be shared between
114 * all point sizes.
115 * if corresponding bit in knownBitmaskMap is set then canDisplayBitmaskMap
116 * is valid. This is 16Kbytes of data per composite font style.
117 * What about UTF-32 and surrogates?
118 * REMIND: This is too much storage. Probably can only cache this
119 * information for latin range, although possibly OK to store all
120 * for just the "logical" fonts.
121 * Or instead store arrays of subranges of 1024 bits (128 bytes) in
122 * the range below surrogate pairs.
123 */
124// protected long[] knownBitmaskMap;
125// protected long[] canDisplayBitmaskMap;
126
127 /* Returns the "real" style of this Font2D. Eg the font face
128 * Lucida Sans Bold" has a real style of Font.BOLD, even though
129 * it may be able to used to simulate bold italic
130 */
131 public int getStyle() {
132 return style;
133 }
134 protected void setStyle() {
135
136 String fName = fullName.toLowerCase();
137
138 for (int i=0; i < boldItalicNames.length; i++) {
139 if (fName.indexOf(boldItalicNames[i]) != -1) {
140 style = Font.BOLD|Font.ITALIC;
141 return;
142 }
143 }
144
145 for (int i=0; i < italicNames.length; i++) {
146 if (fName.indexOf(italicNames[i]) != -1) {
147 style = Font.ITALIC;
148 return;
149 }
150 }
151
152 for (int i=0; i < boldNames.length; i++) {
153 if (fName.indexOf(boldNames[i]) != -1 ) {
154 style = Font.BOLD;
155 return;
156 }
157 }
158 }
159
160
161 int getRank() {
162 return fontRank;
163 }
164
165 void setRank(int rank) {
166 fontRank = rank;
167 }
168
169 abstract CharToGlyphMapper getMapper();
170
171
172
173 /* This isn't very efficient but its infrequently used.
174 * StandardGlyphVector uses it when the client assigns the glyph codes.
175 * These may not be valid. This validates them substituting the missing
176 * glyph elsewhere.
177 */
178 protected int getValidatedGlyphCode(int glyphCode) {
179 if (glyphCode < 0 || glyphCode >= getMapper().getNumGlyphs()) {
180 glyphCode = getMapper().getMissingGlyphCode();
181 }
182 return glyphCode;
183 }
184
185 /*
186 * Creates an appropriate strike for the Font2D subclass
187 */
188 abstract FontStrike createStrike(FontStrikeDesc desc);
189
190 /* this may be useful for APIs like canDisplay where the answer
191 * is dependent on the font and its scaler, but not the strike.
192 * If no strike has ever been returned, then create a one that matches
193 * this font with the default FRC. It will become the lastStrike and
194 * there's a good chance that the next call will be to get exactly that
195 * strike.
196 */
197 public FontStrike getStrike(Font font) {
198 FontStrike strike = (FontStrike)lastFontStrike.get();
199 if (strike != null) {
200 return strike;
201 } else {
202 return getStrike(font, DEFAULT_FRC);
203 }
204 }
205
206 /* SunGraphics2D has font, tx, aa and fm. From this info
207 * can get a Strike object from the cache, creating it if necessary.
208 * This code is designed for multi-threaded access.
209 * For that reason it creates a local FontStrikeDesc rather than filling
210 * in a shared one. Up to two AffineTransforms and one FontStrikeDesc will
211 * be created by every lookup. This appears to perform more than
212 * adequately. But it may make sense to expose FontStrikeDesc
213 * as a parameter so a caller can use its own.
214 * In such a case if a FontStrikeDesc is stored as a key then
215 * we would need to use a private copy.
216 *
217 * Note that this code doesn't prevent two threads from creating
218 * two different FontStrike instances and having one of the threads
219 * overwrite the other in the map. This is likely to be a rare
220 * occurrence and the only consequence is that these callers will have
221 * different instances of the strike, and there'd be some duplication of
222 * population of the strikes. However since users of these strikes are
223 * transient, then the one that was overwritten would soon be freed.
224 * If there is any problem then a small synchronized block would be
225 * required with its attendant consequences for MP scaleability.
226 */
227 public FontStrike getStrike(Font font, AffineTransform devTx,
228 int aa, int fm) {
229
230 /* Create the descriptor which is used to identify a strike
231 * in the strike cache/map. A strike is fully described by
232 * the attributes of this descriptor.
233 */
234 /* REMIND: generating garbage and doing computation here in order
235 * to include pt size in the tx just for a lookup! Figure out a
236 * better way.
237 */
238 double ptSize = font.getSize2D();
239 AffineTransform glyphTx = (AffineTransform)devTx.clone();
240 glyphTx.scale(ptSize, ptSize);
241 if (font.isTransformed()) {
242 glyphTx.concatenate(font.getTransform());
243 }
244 if (glyphTx.getTranslateX() != 0 || glyphTx.getTranslateY() != 0) {
245 glyphTx.setTransform(glyphTx.getScaleX(),
246 glyphTx.getShearY(),
247 glyphTx.getShearX(),
248 glyphTx.getScaleY(),
249 0.0, 0.0);
250 }
251 FontStrikeDesc desc = new FontStrikeDesc(devTx, glyphTx,
252 font.getStyle(), aa, fm);
253 return getStrike(desc, false);
254 }
255
256 public FontStrike getStrike(Font font, AffineTransform devTx,
257 AffineTransform glyphTx,
258 int aa, int fm) {
259
260 /* Create the descriptor which is used to identify a strike
261 * in the strike cache/map. A strike is fully described by
262 * the attributes of this descriptor.
263 */
264 FontStrikeDesc desc = new FontStrikeDesc(devTx, glyphTx,
265 font.getStyle(), aa, fm);
266 return getStrike(desc, false);
267 }
268
269 public FontStrike getStrike(Font font, FontRenderContext frc) {
270
271 AffineTransform at = frc.getTransform();
272 double ptSize = font.getSize2D();
273 at.scale(ptSize, ptSize);
274 if (font.isTransformed()) {
275 at.concatenate(font.getTransform());
276 if (at.getTranslateX() != 0 || at.getTranslateY() != 0) {
277 at.setTransform(at.getScaleX(),
278 at.getShearY(),
279 at.getShearX(),
280 at.getScaleY(),
281 0.0, 0.0);
282 }
283 }
284 int aa = FontStrikeDesc.getAAHintIntVal(this, font, frc);
285 int fm = FontStrikeDesc.getFMHintIntVal(frc.getFractionalMetricsHint());
286 FontStrikeDesc desc = new FontStrikeDesc(frc.getTransform(),
287 at, font.getStyle(),
288 aa, fm);
289 return getStrike(desc, false);
290 }
291
292 FontStrike getStrike(FontStrikeDesc desc) {
293 return getStrike(desc, true);
294 }
295
296 private FontStrike getStrike(FontStrikeDesc desc, boolean copy) {
297 /* Before looking in the map, see if the descriptor matches the
298 * last strike returned from this Font2D. This should often be a win
299 * since its common for the same font, in the same size to be
300 * used frequently, for example in many parts of a UI.
301 *
302 * If its not the same then we use the descriptor to locate a
303 * Reference to the strike. If it exists and points to a strike,
304 * then we update the last strike to refer to that and return it.
305 *
306 * If the key isn't in the map, or its reference object has been
307 * collected, then we create a new strike, put it in the map and
308 * set it to be the last strike.
309 */
310 FontStrike strike = (FontStrike)lastFontStrike.get();
311 if (strike != null && desc.equals(strike.desc)) {
312 //strike.lastlookupTime = System.currentTimeMillis();
313 return strike;
314 } else {
315 Reference strikeRef = strikeCache.get(desc);
316 if (strikeRef != null) {
317 strike = (FontStrike)strikeRef.get();
318 if (strike != null) {
319 //strike.lastlookupTime = System.currentTimeMillis();
320 lastFontStrike = new SoftReference(strike);
321 StrikeCache.refStrike(strike);
322 return strike;
323 }
324 }
325 /* When we create a new FontStrike instance, we *must*
326 * ask the StrikeCache for a reference. We must then ensure
327 * this reference remains reachable, by storing it in the
328 * Font2D's strikeCache map.
329 * So long as the Reference is there (reachable) then if the
330 * reference is cleared, it will be enqueued for disposal.
331 * If for some reason we explicitly remove this reference, it
332 * must only be done when holding a strong reference to the
333 * referent (the FontStrike), or if the reference is cleared,
334 * then we must explicitly "dispose" of the native resources.
335 * The only place this currently happens is in this same method,
336 * where we find a cleared reference and need to overwrite it
337 * here with a new reference.
338 * Clearing the whilst holding a strong reference, should only
339 * be done if the
340 */
341 if (copy) {
342 desc = new FontStrikeDesc(desc);
343 }
344 strike = createStrike(desc);
345 //StrikeCache.addStrike();
346 /* If we are creating many strikes on this font which
347 * involve non-quadrant rotations, or more general
348 * transforms which include shears, then force the use
349 * of weak references rather than soft references.
350 * This means that it won't live much beyond the next GC,
351 * which is what we want for what is likely a transient strike.
352 */
353 int txType = desc.glyphTx.getType();
354 if (txType == AffineTransform.TYPE_GENERAL_TRANSFORM ||
355 (txType & AffineTransform.TYPE_GENERAL_ROTATION) != 0 &&
356 strikeCache.size() > 10) {
357 strikeRef = StrikeCache.getStrikeRef(strike, true);
358 } else {
359 strikeRef = StrikeCache.getStrikeRef(strike);
360 }
361 strikeCache.put(desc, strikeRef);
362 //strike.lastlookupTime = System.currentTimeMillis();
363 lastFontStrike = new SoftReference(strike);
364 StrikeCache.refStrike(strike);
365 return strike;
366 }
367 }
368
369 void removeFromCache(FontStrikeDesc desc) {
370 Reference ref = strikeCache.get(desc);
371 if (ref != null) {
372 Object o = ref.get();
373 if (o == null) {
374 strikeCache.remove(desc);
375 }
376 }
377 }
378
379 /**
380 * The length of the metrics array must be >= 8. This method will
381 * store the following elements in that array before returning:
382 * metrics[0]: ascent
383 * metrics[1]: descent
384 * metrics[2]: leading
385 * metrics[3]: max advance
386 * metrics[4]: strikethrough offset
387 * metrics[5]: strikethrough thickness
388 * metrics[6]: underline offset
389 * metrics[7]: underline thickness
390 */
391 public void getFontMetrics(Font font, AffineTransform at,
392 Object aaHint, Object fmHint,
393 float metrics[]) {
394 /* This is called in just one place in Font with "at" == identity.
395 * Perhaps this can be eliminated.
396 */
397 int aa = FontStrikeDesc.getAAHintIntVal(aaHint, this, font.getSize());
398 int fm = FontStrikeDesc.getFMHintIntVal(fmHint);
399 FontStrike strike = getStrike(font, at, aa, fm);
400 StrikeMetrics strikeMetrics = strike.getFontMetrics();
401 metrics[0] = strikeMetrics.getAscent();
402 metrics[1] = strikeMetrics.getDescent();
403 metrics[2] = strikeMetrics.getLeading();
404 metrics[3] = strikeMetrics.getMaxAdvance();
405
406 getStyleMetrics(font.getSize2D(), metrics, 4);
407 }
408
409 /**
410 * The length of the metrics array must be >= offset+4, and offset must be
411 * >= 0. Typically offset is 4. This method will
412 * store the following elements in that array before returning:
413 * metrics[off+0]: strikethrough offset
414 * metrics[off+1]: strikethrough thickness
415 * metrics[off+2]: underline offset
416 * metrics[off+3]: underline thickness
417 *
418 * Note that this implementation simply returns default values;
419 * subclasses can override this method to provide more accurate values.
420 */
421 public void getStyleMetrics(float pointSize, float[] metrics, int offset) {
422 metrics[offset] = -metrics[0] / 2.5f;
423 metrics[offset+1] = pointSize / 12;
424 metrics[offset+2] = metrics[offset+1] / 1.5f;
425 metrics[offset+3] = metrics[offset+1];
426 }
427
428 /**
429 * The length of the metrics array must be >= 4. This method will
430 * store the following elements in that array before returning:
431 * metrics[0]: ascent
432 * metrics[1]: descent
433 * metrics[2]: leading
434 * metrics[3]: max advance
435 */
436 public void getFontMetrics(Font font, FontRenderContext frc,
437 float metrics[]) {
438 StrikeMetrics strikeMetrics = getStrike(font, frc).getFontMetrics();
439 metrics[0] = strikeMetrics.getAscent();
440 metrics[1] = strikeMetrics.getDescent();
441 metrics[2] = strikeMetrics.getLeading();
442 metrics[3] = strikeMetrics.getMaxAdvance();
443 }
444
445 /* Currently the layout code calls this. May be better for layout code
446 * to check the font class before attempting to run, rather than needing
447 * to promote this method up from TrueTypeFont
448 */
449 byte[] getTableBytes(int tag) {
450 return null;
451 }
452
453 /* for layout code */
454 protected long getUnitsPerEm() {
455 return 2048;
456 }
457
458 boolean supportsEncoding(String encoding) {
459 return false;
460 }
461
462 public boolean canDoStyle(int style) {
463 return (style == this.style);
464 }
465
466 /*
467 * All the important subclasses override this which is principally for
468 * the TrueType 'gasp' table.
469 */
470 public boolean useAAForPtSize(int ptsize) {
471 return true;
472 }
473
474 public boolean hasSupplementaryChars() {
475 return false;
476 }
477
478 /* The following methods implement public methods on java.awt.Font */
479 public String getPostscriptName() {
480 return fullName;
481 }
482
483 public String getFontName(Locale l) {
484 return fullName;
485 }
486
487 public String getFamilyName(Locale l) {
488 return familyName;
489 }
490
491 public int getNumGlyphs() {
492 return getMapper().getNumGlyphs();
493 }
494
495 public int charToGlyph(int wchar) {
496 return getMapper().charToGlyph(wchar);
497 }
498
499 public int getMissingGlyphCode() {
500 return getMapper().getMissingGlyphCode();
501 }
502
503 public boolean canDisplay(char c) {
504 return getMapper().canDisplay(c);
505 }
506
507 public boolean canDisplay(int cp) {
508 return getMapper().canDisplay(cp);
509 }
510
511 public byte getBaselineFor(char c) {
512 return Font.ROMAN_BASELINE;
513 }
514
515 public float getItalicAngle(Font font, AffineTransform at,
516 Object aaHint, Object fmHint) {
517 /* hardwire psz=12 as that's typical and AA vs non-AA for 'gasp' mode
518 * isn't important for the caret slope of this rarely used API.
519 */
520 int aa = FontStrikeDesc.getAAHintIntVal(aaHint, this, 12);
521 int fm = FontStrikeDesc.getFMHintIntVal(fmHint);
522 FontStrike strike = getStrike(font, at, aa, fm);
523 StrikeMetrics metrics = strike.getFontMetrics();
524 if (metrics.ascentY == 0 || metrics.ascentX == 0) {
525 return 0f;
526 } else {
527 /* ascent is "up" from the baseline so its typically
528 * a negative value, so we need to compensate
529 */
530 return metrics.ascentX/-metrics.ascentY;
531 }
532 }
533
534}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t