@@ -53,6 +53,25 @@ public class FontSelector {
5353
5454 protected List <FontInfo > fonts ;
5555
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+
5675 /**
5776 * Create new FontSelector instance.
5877 * @param allFonts Unsorted set of all available fonts.
@@ -136,68 +155,100 @@ private static FontCharacteristics parseFontStyle(String fontFamily, FontCharact
136155 return fc ;
137156 }
138157
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+ */
139177 private static int characteristicsSimilarity (String fontName , FontCharacteristics fc , FontInfo fontInfo ) {
140178 boolean isFontBold = fontInfo .getDescriptor ().isBold () || fontInfo .getDescriptor ().getFontWeight () > 500 ;
141179 boolean isFontItalic = fontInfo .getDescriptor ().isItalic () || fontInfo .getDescriptor ().getItalicAngle () < 0 ;
142180 boolean isFontMonospace = fontInfo .getDescriptor ().isMonospace ();
143181 int score = 0 ;
144182 if (fc .isBold ()) {
145183 if (isFontBold ) {
146- score += 5 ;
184+ score += EXPECTED_FONT_IS_BOLD_AWARD ;
147185 } else {
148- score -= 5 ;
186+ score -= EXPECTED_FONT_IS_BOLD_AWARD ;
149187 }
150188 } else {
151189 if (isFontBold ) {
152- score -= 3 ;
190+ score -= EXPECTED_FONT_IS_NOT_BOLD_AWARD ;
153191 }
154192 }
155193
156194 if (fc .isItalic ()) {
157195 if (isFontItalic ) {
158- score += 5 ;
196+ score += EXPECTED_FONT_IS_ITALIC_AWARD ;
159197 } else {
160- score -= 5 ;
198+ score -= EXPECTED_FONT_IS_ITALIC_AWARD ;
161199 }
162200 } else {
163201 if (isFontItalic ) {
164- score -= 3 ;
202+ score -= EXPECTED_FONT_IS_NOT_ITALIC_AWARD ;
165203 }
166204 }
167205
168206 if (fc .isMonospace ()) {
169207 if (isFontMonospace ) {
170- score += 5 ;
208+ score += EXPECTED_FONT_IS_MONOSPACED_AWARD ;
171209 } else {
172- score -= 5 ;
210+ score -= EXPECTED_FONT_IS_MONOSPACED_AWARD ;
173211 }
174212 } else {
175213 if (isFontMonospace ) {
176- score -= 1 ;
214+ score -= EXPECTED_FONT_IS_NOT_MONOSPACED_AWARD ;
177215 }
178216 }
179217
180218 FontProgramDescriptor descriptor = fontInfo .getDescriptor ();
181219 // Note, aliases are custom behaviour, so in FontSelector will find only exact name,
182220 // it should not be any 'contains' with aliases.
183221 boolean checkContains = true ;
222+
184223 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 ;
186226 checkContains = false ;
187227 }
188228 if (fontName .equals (descriptor .getFontNameLowerCase ())) {
189- score += 4 ;
229+ score += checkContains ? FONT_NAME_EQUALS_AWARD : EQUALS_ADDITIONAL_AWARD ;
190230 checkContains = false ;
191231 }
192232 if (fontName .equals (fontInfo .getAlias ())) {
193- score += 4 ;
233+ score += checkContains ? ALIAS_EQUALS_AWARD : EQUALS_ADDITIONAL_AWARD ;
194234 checkContains = false ;
195235 }
196236
197237 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+ }
201252 }
202253
203254 return score ;
0 commit comments