/// <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));
        }
示例#2
0
        /// <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);
        }