OSDN Git Service

ホワイトスペース修正
[jindolf/Jindolf.git] / src / main / java / jp / sfjp / jindolf / glyph / FontInfo.java
1 /*
2  * font information
3  *
4  * License : The MIT License
5  * Copyright(c) 2009 olyutorskii
6  */
7
8 package jp.sfjp.jindolf.glyph;
9
10 import java.awt.Font;
11 import java.awt.Rectangle;
12 import java.awt.font.FontRenderContext;
13 import java.awt.font.GlyphVector;
14 import java.awt.geom.AffineTransform;
15 import java.awt.geom.Rectangle2D;
16 import java.text.CharacterIterator;
17 import java.util.Locale;
18
19 /**
20  * フォント描画に関する各種設定。
21  */
22 public class FontInfo{
23
24     /** デフォルトのフォント環境。 */
25     public static final FontEnv DEFAULT_FONTENV;
26     /** デフォルトのフォント設定。 */
27     public static final FontInfo DEFAULT_FONTINFO;
28
29     /** デフォルトのポイントサイズ。 */
30     public static final int DEF_SIZE = 16;
31     /** デフォルトのフォントスタイル。 */
32     public static final int DEF_STYLE = 0x00 | Font.PLAIN;
33
34     /** {@link java.util.Locale#ROOT}代替品。 */
35     private static final Locale LOCALE_ROOT = new Locale("", "", "");
36     /** MSリコー系日本語ベクトルフォント下限ポイントサイズ。 */
37     private static final int MS_VEC_LIMIT = 24;
38     /** 二重引用符。 */
39     private static final char DQ = '"';
40
41
42     static{
43         DEFAULT_FONTENV = FontEnv.DEFAULT;
44         DEFAULT_FONTINFO = new FontInfo();
45     }
46
47
48     // いずれのフィールドもnull値はデフォルト値の遅延評価フラグ
49     private String familyName;
50     private Font font;
51     private FontRenderContext context;
52
53
54     /**
55      * コンストラクタ。
56      * デフォルトフォントとそれに適した描画属性が指定される。
57      */
58     public FontInfo(){
59         this((Font) null, (FontRenderContext) null);
60         return;
61     }
62
63     /**
64      * コンストラクタ。
65      * @param font フォント
66      * @param context 描画設定
67      */
68     public FontInfo(Font font, FontRenderContext context){
69         super();
70         this.familyName = null;
71         this.font = font;
72         this.context = context;
73         return;
74     }
75
76
77     /**
78      * マイクロソフト&リコー(リョービイマジクス)系
79      * 日本語ベクトルフォントか否か、ファミリ名で見当をつける。
80      *
81      * <p>日本語Windows同梱のMSゴシックやMS明朝などが対象。
82      *
83      * <p>メイリオは対象外。
84      *
85      * @param font フォント
86      * @return 見当が付けばtrue
87      */
88     protected static boolean isMsRicohJpFont(Font font){
89         String rootFamilyName = font.getFamily(LOCALE_ROOT);
90         if(rootFamilyName.startsWith("MS")){
91             if(rootFamilyName.contains("Gothic")) return true;
92             if(rootFamilyName.contains("Mincho")) return true;
93         }
94         return false;
95     }
96
97     /**
98      * ビットマップフォントか否か見当をつける。
99      *
100      * <p>判定基準はかなりアバウト。
101      * 実用上、小さめのMSPゴシックを補足できればそれでいい。
102      *
103      * <p>ビットマップフォントには
104      * アンチエイリアスやサブピクセルを使わないほうが
105      * 見栄えがいいような気がする。
106      *
107      * @param font 判定対象フォント
108      * @return ビットマップフォントらしかったらtrue
109      */
110     protected static boolean isBitmapFont(Font font){
111         if(font.getSize() >= MS_VEC_LIMIT) return false;
112         if(isMsRicohJpFont(font)) return true;
113         return false;
114     }
115
116     /**
117      * フォントに応じた最適な描画設定を生成する。
118      *
119      * <p>ビットマップフォントと推測されるときは
120      * アンチエイリアスやサブピクセル補完を無効にする。
121      *
122      * @param font フォント
123      * @return 描画設定
124      */
125     protected static FontRenderContext createBestContext(Font font){
126         boolean isAntiAliased;
127         boolean usesFractionalMetrics;
128
129         if(isBitmapFont(font)){
130             isAntiAliased         = false;
131             usesFractionalMetrics = false;
132         }else{
133             isAntiAliased         = true;
134             usesFractionalMetrics = true;
135         }
136
137         AffineTransform identity = ImtblAffineTx.IDENTITY;
138         FontRenderContext result;
139         result = new FontRenderContext(identity,
140                                        isAntiAliased,
141                                        usesFractionalMetrics );
142
143         return result;
144     }
145
146     /**
147      * ファミリ名を返す。
148      * @return ファミリ名
149      */
150     private String getFamilyName(){
151         if(this.familyName == null){
152             if(this.font == null){
153                 this.familyName = DEFAULT_FONTENV.selectFontFamily();
154             }else{
155                 // 再帰に注意
156                 this.familyName = getRootFamilyName();
157             }
158         }
159         return this.familyName;
160     }
161
162     /**
163      * フォントを返す。
164      * @return フォント
165      */
166     public Font getFont(){
167         if(this.font == null){
168             String name = getFamilyName();
169             this.font = new Font(name, DEF_STYLE, DEF_SIZE);
170         }
171         return this.font;
172     }
173
174     /**
175      * 描画属性を返す。
176      * @return 描画属性
177      */
178     public FontRenderContext getFontRenderContext(){
179         if(this.context == null){
180             Font thisFont = getFont();
181             this.context = createBestContext(thisFont);
182         }
183         return this.context;
184     }
185
186     /**
187      * アンチエイリアス機能を使うか判定する。
188      * @return アンチエイリアス機能を使うならtrue
189      */
190     public boolean isAntiAliased(){
191         FontRenderContext frc = getFontRenderContext();
192         boolean result = frc.isAntiAliased();
193         return result;
194     }
195
196     /**
197      * サブピクセル精度を使うか判定する。
198      * @return サブピクセル精度を使うならtrue
199      */
200     public boolean usesFractionalMetrics(){
201         FontRenderContext frc = getFontRenderContext();
202         boolean result = frc.usesFractionalMetrics();
203         return result;
204     }
205
206     /**
207      * フォントの最大寸法を返す。
208      * @return 最大寸法
209      * @see java.awt.Font#getMaxCharBounds(FontRenderContext)
210      */
211     public Rectangle getMaxCharBounds(){
212         Font thisFont = getFont();
213         FontRenderContext frc = getFontRenderContext();
214         Rectangle2D r2d = thisFont.getMaxCharBounds(frc);
215         Rectangle rect = r2d.getBounds();
216         return rect;
217     }
218
219     /**
220      * フォントのみ異なる設定を派生させる。
221      * @param newFont 新フォント
222      * @return 新設定
223      */
224     public FontInfo deriveFont(Font newFont){
225         FontInfo result = new FontInfo(newFont, this.context);
226         return result;
227     }
228
229     /**
230      * 描画属性のみ異なる設定を派生させる。
231      * @param newContext 新描画設定
232      * @return 新設定
233      */
234     public FontInfo deriveRenderContext(FontRenderContext newContext){
235         FontInfo result = new FontInfo(this.font, newContext);
236         return result;
237     }
238
239     /**
240      * 描画属性のみ異なる設定を派生させる。
241      * @param isAntiAliases アンチエイリアス設定
242      * @param useFractional サブピクセル精度設定
243      * @return 新設定
244      */
245     public FontInfo deriveRenderContext(boolean isAntiAliases,
246                                            boolean useFractional ){
247         AffineTransform tx;
248         if(this.context == null){
249             tx = ImtblAffineTx.IDENTITY;
250         }else{
251             tx = this.context.getTransform();
252         }
253         FontRenderContext newContext =
254                 new FontRenderContext(tx, isAntiAliases, useFractional);
255         return deriveRenderContext(newContext);
256     }
257
258     /**
259      * 文字列からグリフ集合を生成する。
260      * @param iterator 文字列
261      * @return グリフ集合
262      */
263     public GlyphVector createGlyphVector(CharacterIterator iterator){
264         Font thisFont = getFont();
265         FontRenderContext frc = getFontRenderContext();
266         GlyphVector glyph = thisFont.createGlyphVector(frc, iterator);
267         return glyph;
268     }
269
270     /**
271      * ロケール中立なフォントファミリ名を返す。
272      * JRE1.5対策
273      * @return ファミリ名
274      * @see Font#getFamily(Locale)
275      */
276     public String getRootFamilyName(){
277         Font thisFont = getFont();
278         String result = thisFont.getFamily(LOCALE_ROOT);
279         return result;
280     }
281
282     /**
283      * Font#decode()用の名前を返す。
284      * 空白が含まれる場合は二重引用符で囲まれる。
285      * @return {@link java.awt.Font#decode(String)}用の名前
286      * @see java.awt.Font#decode(String)
287      */
288     public String getFontDecodeName(){
289         StringBuilder result = new StringBuilder();
290
291         String name = getRootFamilyName();
292
293         Font thisFont = getFont();
294         StringBuilder style = new StringBuilder();
295         if(thisFont.isBold())   style.append("BOLD");
296         if(thisFont.isItalic()) style.append("ITALIC");
297         if(style.length() <= 0) style.append("PLAIN");
298
299         int fontSize = thisFont.getSize();
300
301         result.append(name)
302               .append('-').append(style)
303               .append('-').append(fontSize);
304
305         if(    result.indexOf("\u0020") >= 0
306             || result.indexOf("\u3000") >= 0 ){
307             result.insert(0, DQ).append(DQ);
308         }
309
310         return result.toString();
311     }
312
313     /**
314      * {@inheritDoc}
315      * @param obj {@inheritDoc}
316      * @return {@inheritDoc}
317      */
318     @Override
319     public boolean equals(Object obj){
320         if( ! (obj instanceof FontInfo) ) return false;
321         FontInfo target = (FontInfo) obj;
322
323         Font thisFont = getFont();
324         Font targetFont = target.getFont();
325         if( ! (thisFont.equals(targetFont)) ){
326             return false;
327         }
328
329         FontRenderContext thisContext = getFontRenderContext();
330         FontRenderContext targetContext = target.getFontRenderContext();
331         if( ! (thisContext.equals(targetContext)) ){
332             return false;
333         }
334
335         return true;
336     }
337
338     /**
339      * {@inheritDoc}
340      * @return {@inheritDoc}
341      */
342     @Override
343     public int hashCode(){
344         int hashFont = getFont().hashCode();
345         int hashContext = getFontRenderContext().hashCode();
346         return hashFont ^ hashContext;
347     }
348
349 }