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+
26+package sun.font;
27+
28+import java.awt.Font;
29+import java.awt.font.FontRenderContext;
30+import java.awt.geom.AffineTransform;
31+import java.lang.ref.Reference;
32+import java.lang.ref.SoftReference;
33+import java.util.concurrent.ConcurrentHashMap;
34+import java.util.Locale;
35+
36+public 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