@@ -53,6 +53,25 @@ public class FontSelector {
53
53
54
54
protected List <FontInfo > fonts ;
55
55
56
+ private static final int EXPECTED_FONT_IS_BOLD_AWARD = 5 ;
57
+ private static final int EXPECTED_FONT_IS_NOT_BOLD_AWARD = 3 ;
58
+ private static final int EXPECTED_FONT_IS_ITALIC_AWARD = 5 ;
59
+ private static final int EXPECTED_FONT_IS_NOT_ITALIC_AWARD = 3 ;
60
+ private static final int EXPECTED_FONT_IS_MONOSPACED_AWARD = 5 ;
61
+ private static final int EXPECTED_FONT_IS_NOT_MONOSPACED_AWARD = 1 ;
62
+
63
+ private static final int FULL_NAME_EQUALS_AWARD = 11 ;
64
+ private static final int FONT_NAME_EQUALS_AWARD = 11 ;
65
+ private static final int ALIAS_EQUALS_AWARD = 11 ;
66
+
67
+ private static final int FULL_NAME_CONTAINS_AWARD = 7 ;
68
+ private static final int FONT_NAME_CONTAINS_AWARD = 7 ;
69
+ private static final int ALIAS_CONTAINS_AWARD = 7 ;
70
+
71
+ private static final int CONTAINS_ADDITIONAL_AWARD = 3 ;
72
+ private static final int EQUALS_ADDITIONAL_AWARD = 3 ;
73
+
74
+
56
75
/**
57
76
* Create new FontSelector instance.
58
77
* @param allFonts Unsorted set of all available fonts.
@@ -136,68 +155,100 @@ private static FontCharacteristics parseFontStyle(String fontFamily, FontCharact
136
155
return fc ;
137
156
}
138
157
158
+ /**
159
+ * This method is used to compare two fonts (the first is described by fontInfo,
160
+ * the second is described by fc and fontName) and measure their similarity.
161
+ * The more the fonts are similar the higher the score is.
162
+ *
163
+ * We check whether the fonts are both:
164
+ * a) bold
165
+ * b) italic
166
+ * c) monospaced
167
+ *
168
+ * We also check whether the font names are identical. There are two blocks of conditions:
169
+ * "equals" and "contains". They cannot be satisfied simultaneously.
170
+ * Some remarks about these checks:
171
+ * a) "contains" block checks are much easier to be satisfied so one can get award from this block
172
+ * higher than from "equals" block only if all "contains" conditions are satisfied.
173
+ * b) since ideally all conditions of a certain block are satisfied simultaneously, it may result
174
+ * in highly inflated score. So we decrease an award for other conditions of the block
175
+ * if one has been already satisfied.
176
+ */
139
177
private static int characteristicsSimilarity (String fontName , FontCharacteristics fc , FontInfo fontInfo ) {
140
178
boolean isFontBold = fontInfo .getDescriptor ().isBold () || fontInfo .getDescriptor ().getFontWeight () > 500 ;
141
179
boolean isFontItalic = fontInfo .getDescriptor ().isItalic () || fontInfo .getDescriptor ().getItalicAngle () < 0 ;
142
180
boolean isFontMonospace = fontInfo .getDescriptor ().isMonospace ();
143
181
int score = 0 ;
144
182
if (fc .isBold ()) {
145
183
if (isFontBold ) {
146
- score += 5 ;
184
+ score += EXPECTED_FONT_IS_BOLD_AWARD ;
147
185
} else {
148
- score -= 5 ;
186
+ score -= EXPECTED_FONT_IS_BOLD_AWARD ;
149
187
}
150
188
} else {
151
189
if (isFontBold ) {
152
- score -= 3 ;
190
+ score -= EXPECTED_FONT_IS_NOT_BOLD_AWARD ;
153
191
}
154
192
}
155
193
156
194
if (fc .isItalic ()) {
157
195
if (isFontItalic ) {
158
- score += 5 ;
196
+ score += EXPECTED_FONT_IS_ITALIC_AWARD ;
159
197
} else {
160
- score -= 5 ;
198
+ score -= EXPECTED_FONT_IS_ITALIC_AWARD ;
161
199
}
162
200
} else {
163
201
if (isFontItalic ) {
164
- score -= 3 ;
202
+ score -= EXPECTED_FONT_IS_NOT_ITALIC_AWARD ;
165
203
}
166
204
}
167
205
168
206
if (fc .isMonospace ()) {
169
207
if (isFontMonospace ) {
170
- score += 5 ;
208
+ score += EXPECTED_FONT_IS_MONOSPACED_AWARD ;
171
209
} else {
172
- score -= 5 ;
210
+ score -= EXPECTED_FONT_IS_MONOSPACED_AWARD ;
173
211
}
174
212
} else {
175
213
if (isFontMonospace ) {
176
- score -= 1 ;
214
+ score -= EXPECTED_FONT_IS_NOT_MONOSPACED_AWARD ;
177
215
}
178
216
}
179
217
180
218
FontProgramDescriptor descriptor = fontInfo .getDescriptor ();
181
219
// Note, aliases are custom behaviour, so in FontSelector will find only exact name,
182
220
// it should not be any 'contains' with aliases.
183
221
boolean checkContains = true ;
222
+
184
223
if (fontName .equals (descriptor .getFullNameLowerCase ())) {
185
- score += 4 ;
224
+ // the next condition can be simplified. it's been written that way to prevent mistakes if the condition is moved.
225
+ score += checkContains ? FULL_NAME_EQUALS_AWARD : EQUALS_ADDITIONAL_AWARD ;
186
226
checkContains = false ;
187
227
}
188
228
if (fontName .equals (descriptor .getFontNameLowerCase ())) {
189
- score += 4 ;
229
+ score += checkContains ? FONT_NAME_EQUALS_AWARD : EQUALS_ADDITIONAL_AWARD ;
190
230
checkContains = false ;
191
231
}
192
232
if (fontName .equals (fontInfo .getAlias ())) {
193
- score += 4 ;
233
+ score += checkContains ? ALIAS_EQUALS_AWARD : EQUALS_ADDITIONAL_AWARD ;
194
234
checkContains = false ;
195
235
}
196
236
197
237
if (checkContains ) {
198
- if (descriptor .getFullNameLowerCase ().contains (fontName )) score += 3 ;
199
- if (descriptor .getFontNameLowerCase ().contains (fontName )) score += 3 ;
200
- if (null != fontInfo .getAlias () && fontInfo .getAlias ().contains (fontName )) score += 3 ;
238
+ boolean conditionHasBeenSatisfied = false ;
239
+ if (descriptor .getFullNameLowerCase ().contains (fontName )) {
240
+ // the next condition can be simplified. it's been written that way to prevent mistakes if the condition is moved.
241
+ score += conditionHasBeenSatisfied ? FULL_NAME_CONTAINS_AWARD : CONTAINS_ADDITIONAL_AWARD ;
242
+ conditionHasBeenSatisfied = true ;
243
+ }
244
+ if (descriptor .getFontNameLowerCase ().contains (fontName )) {
245
+ score += conditionHasBeenSatisfied ? FONT_NAME_CONTAINS_AWARD : CONTAINS_ADDITIONAL_AWARD ;
246
+ conditionHasBeenSatisfied = true ;
247
+ }
248
+ if (null != fontInfo .getAlias () && fontInfo .getAlias ().contains (fontName )) {
249
+ score += conditionHasBeenSatisfied ? ALIAS_CONTAINS_AWARD : CONTAINS_ADDITIONAL_AWARD ;
250
+ conditionHasBeenSatisfied = true ; // this line is redundant. it's added to prevent mistakes if other condition is added.
251
+ }
201
252
}
202
253
203
254
return score ;
0 commit comments