/// <summary>Gets or synthesises a glyph for the given style settings which include weight and italic. Style code 400 means regular.</summary> public Glyph GetGlyph(int charcode, FontFaceFlags style) { // Try getting the face: FontFace face = null; if (FontFaces.TryGetValue(style, out face)) { // Great! Raster using that font face: return(face.GetGlyph(charcode)); } // Get the code as an int: int styleCode = (int)style; // Italic? bool italic = ((styleCode & 1) == 1); // Get the font weight: int weight = (styleCode & ~1); if (weight == 0) { // Regular: weight = 400; } int match = 0; if (italic) { // Find one with the closest weight match. face = BestWeight(Italics, weight, out match); } else if (weight == 400) { // Regular. Note that regular must be set - the family wouldn't exist otherwise. return(Regular.GetGlyph(charcode)); } else { // Find best weight match. Must also be not italic (this is why the bold set doesn't contain italic ones). face = BestWeight(Bold, weight, out match); } if (face == null || match != 0) { // We're synthesizing! if (face == null) { face = Regular; } // Derive from face. face = face.CreateSynthetic(italic, weight); } return(face.GetGlyph(charcode)); }
/// <summary>Gets or creates the most suitable font face for the given style.</summary> public FontFace GetFace(int styleCode, int synthFlags) { // Style (italic, oblique etc): int style = (styleCode & FontFaceFlags.StyleMask); // Get the font weight: int weight = (styleCode & FontFaceFlags.WeightMask) >> 3; if (weight == 0) { // Regular: weight = 4; } // And the stretch mode: int stretch = (styleCode & FontFaceFlags.StretchMask) >> 7; if (stretch == 0) { // Medium stretch stretch = 5; } // Try getting the face: FontFace bestFace = Regular; // A linear search is actually optimal for most cases. // This is because the set is typically very small. // [Condensed][Weight][Italic] int bestMatch = 0; for (int i = 0; i < FontFaces.Count; i++) { // Current face: FontFace face = FontFaces[i]; // We'll now figure out a match weighting. int matchWeight = 0; // First, we match by condensed: if (face.Stretch == stretch) { // Direct match. 8 points awarded. matchWeight = 8; } else { // How close is it? int stretchDiff = face.Stretch - stretch; if (stretchDiff < 0) { stretchDiff = -stretchDiff; } // StretchDiff maxes out at 8. Award at most 8 points. matchWeight = 8 - stretchDiff; } // Weight next. if (face.Weight == weight) { // Direct match. 8 points awarded. matchWeight += 8; } else { // How close is it? int weightDiff = face.Weight - weight; if (weightDiff < 0) { weightDiff = -weightDiff; } // weightDiff maxes out at 8. Award at most 8 points. matchWeight += 8 - weightDiff; } // Style. if (face.Style == style) { // Direct match! 2 points awarded. matchWeight += 2; } else { // If it's the other of oblique/italic, award 1 point. if (style != 0 && face.Style != 0) { matchWeight += 1; } } if (matchWeight > bestMatch) { // Got a new best! bestMatch = matchWeight; bestFace = face; } if (matchWeight == 18) { // Perfect match! break; } } if (bestMatch != 18 && synthFlags != 0) { // Synthesize a face, deriving it from our best match. bestFace = bestFace.CreateSynthetic(style, weight, stretch); // Add it: Add(bestFace); } return(bestFace); }