/// <summary> /// Function to retrieve the built in kerning pairs and advancement information for the font. /// </summary> /// <param name="graphics">The GDI graphics interface.</param> /// <param name="font">The GDI font.</param> /// <param name="allowedCharacters">The list of characters available to the font.</param> private Dictionary <char, ABC> GetKerningInformation(System.Drawing.Graphics graphics, Font font, IList <char> allowedCharacters) { Dictionary <char, ABC> advancementInfo; KerningPairs.Clear(); IntPtr prevGdiHandle = Win32API.SetActiveFont(graphics, font); try { advancementInfo = Win32API.GetCharABCWidths(allowedCharacters[0], allowedCharacters[allowedCharacters.Count - 1]); if (!Info.UseKerningPairs) { return(advancementInfo); } IList <KERNINGPAIR> kerningPairs = Win32API.GetKerningPairs(); foreach (KERNINGPAIR pair in kerningPairs.Where(item => item.KernAmount != 0)) { var newPair = new GorgonKerningPair(Convert.ToChar(pair.First), Convert.ToChar(pair.Second)); if ((!allowedCharacters.Contains(newPair.LeftCharacter)) || (!allowedCharacters.Contains(newPair.RightCharacter))) { continue; } KerningPairs[newPair] = pair.KernAmount; } } finally { Win32API.RestoreActiveObject(prevGdiHandle); } return(advancementInfo); }
/// <summary> /// Function to measure the width of an individual line of text. /// </summary> /// <param name="line">The line to measure.</param> /// <param name="useOutline"><b>true</b> to use the font outline, <b>false</b> to disregard it.</param> /// <returns>The width of the line.</returns> private float GetLineWidth(string line, bool useOutline) { float size = 0; bool firstChar = true; if (!Glyphs.TryGetValue(Info.DefaultCharacter, out GorgonGlyph defaultGlyph)) { throw new GorgonException(GorgonResult.CannotEnumerate, string.Format(Resources.GORGFX_ERR_FONT_DEFAULT_CHAR_NOT_VALID, Info.DefaultCharacter)); } for (int i = 0; i < line.Length; i++) { char character = line[i]; if (!Glyphs.TryGetValue(character, out GorgonGlyph glyph)) { glyph = defaultGlyph; } // Skip out on carriage returns and newlines. if ((character == '\r') || (character == '\n')) { continue; } // Whitespace will use the glyph width. if (char.IsWhiteSpace(character)) { size += glyph.Advance; continue; } // Include the initial offset. if (firstChar) { size += (useOutline && glyph.OutlineCoordinates.Width > 0) ? glyph.OutlineOffset.X : glyph.Offset.X; firstChar = false; } size += glyph.Advance; if (!Info.UseKerningPairs) { continue; } if ((i == line.Length - 1) || (KerningPairs.Count == 0)) { continue; } var kerning = new GorgonKerningPair(character, line[i + 1]); if (KerningPairs.TryGetValue(kerning, out int kernAmount)) { size += kernAmount; } } return(size); }