2016-04-14 12 views
1

TextRenderer sınıfını kullanarak belirli bir yazı tipi verilen bir dizenin boyutunu ölçmeye çalışıyorum. 3 farklı yaklaşımla ölçtüğüm gerçeğine rağmen (Graphics.MeasureCharacterRanges, Graphics.MeasureString, TextRenderer.MeasureText) ve hepsi bana doğru sonuçlar vermeden farklı sonuçlar veriyor, başka bir şeye rastladım. Aynı yazı tipiyle START aynı fontla 7 ve 8 yazı tipi boyutu kullanılarak, font boyutlu 7 ölçümü fontsize 8 ölçümünden daha geniş bir görünüme sahiptir.C# Textrenderer - Daha küçük font boyutlu sonuçlar ölçmek daha büyük boyutta sonuçlar verir

Font f1 = new Font("Arial", 7, FontStyle.Regular); 
Font f2 = new Font("Arial", 8, FontStyle.Regular); 
Size s1 = TextRenderer.MeasureText("START", f1); 
Size s2 = TextRenderer.MeasureText("START", f2); 

sonuç s1 bir width 41 sahip olan ve bir width 14.

neden olur ve height 40 ve sahip olan s2 ise 13 bir height: Burada

i kullanma kod Daha küçük bir font daha geniş bir genişliğe neden olur?

+0

Hm, Yeniden üretemiyorum. İşte 44,15 ve 53,16 aldım. Monitörde 120dpi var. – TaW

+0

Not: StringFormat.TypographicGenic ile Graphics.MeasureString dışındakilerin tümü, sözcükleri örtüşmeden çıkışı bir araya getirmenize izin vermek için biraz boşluk ekleyeceğini unutmayın. – TaW

+0

@TaW Monitörüm varsayılan 96dpi'de çalışıyor. TextRenderer, SizeF ile sonuçlanan bir dizeyi ölçecek herhangi bir yöntem sunmuyor. Adeditonal dolgu sayesinde boyutun daha büyük olduğunu umursamıyorum, sadece daha küçük bir font boyutunun daha büyük genişlikte nasıl sonuçlandığını merak ediyordum. – dm1988

cevap

2

özellikle neden mümkün olacağını ele almak için bir araya bu örnek konsol uygulaması koydu. Bu, TextRenderer boyutlarını dahili olarak değerlendirdiğinden, 7 & 8 yazı tipi boyutlarını sırasıyla 7,5 & 8.25 olarak ayarladığımı belirtmek gerekir.

using System; 
using System.Drawing; 
using System.Linq; 
using System.Runtime.InteropServices; 

namespace FontSizeDifference 
{ 
    static class Program 
    { 
     [StructLayout(LayoutKind.Sequential)] 
     struct ABCFLOAT 
     { 
      public float abcfA; 
      public float abcfB; 
      public float abcfC; 
     } 

     [DllImport("gdi32.dll")] 
     static extern bool GetCharABCWidthsFloat(IntPtr hdc, int iFirstChar, int iLastChar, [Out] ABCFLOAT[] lpABCF); 

     [DllImport("gdi32.dll", CharSet = CharSet.Auto, EntryPoint = "SelectObject", SetLastError = true)] 
     static extern IntPtr SelectObject(IntPtr hdc, IntPtr obj); 

     [DllImport("gdi32.dll", EntryPoint = "DeleteObject")] 
     static extern bool DeleteObject([In] IntPtr hObject); 

     [StructLayout(LayoutKind.Sequential)] 
     struct KERNINGPAIR 
     { 
      public ushort wFirst; 
      public ushort wSecond; 
      public int iKernAmount; 
     } 

     [DllImport("gdi32.dll")] 
     static extern int GetKerningPairs(IntPtr hdc, int nNumPairs, [Out] KERNINGPAIR[] lpkrnpair); 

     [STAThread] 
     static void Main() 
     { 
      var fonts = new[] { 
       new Font("Arial", 7.5f, FontStyle.Regular), 
       new Font("Arial", 8.25f, FontStyle.Regular) 
      }; 
      string textToMeasure = "START"; 

      using (Graphics g = Graphics.FromHwnd(IntPtr.Zero)) 
      { 
       IntPtr hDC = g.GetHdc(); 

       foreach (Font font in fonts) 
       { 
        float totalWidth = 0F; 
        IntPtr hFont = font.ToHfont(); 

        // Apply the font to dc 
        SelectObject(hDC, hFont); 

        int pairCount = GetKerningPairs(hDC, short.MaxValue, null); 
        var lpkrnpair = new KERNINGPAIR[pairCount]; 
        GetKerningPairs(hDC, pairCount, lpkrnpair); 

        Console.WriteLine("\r\n" + font.ToString()); 

        for (int ubound = textToMeasure.Length - 1, i = 0; i <= ubound; ++i) 
        { 
         char c = textToMeasure[i]; 
         ABCFLOAT characterWidths = GetCharacterWidths(hDC, c); 
         float charWidth = (characterWidths.abcfA + characterWidths.abcfB + characterWidths.abcfC); 
         totalWidth += charWidth; 

         int kerning = 0; 
         if (i < ubound) 
         { 
          kerning = GetKerningBetweenCharacters(lpkrnpair, c, textToMeasure[i + 1]).iKernAmount; 
          totalWidth += kerning; 
         } 

         Console.WriteLine(c + ": " + (charWidth + kerning) + " (" + charWidth + " + " + kerning + ")"); 
        } 

        Console.WriteLine("Total width: " + totalWidth); 

        DeleteObject(hFont); 
       } 

       g.ReleaseHdc(hDC); 
      } 
     } 

     static KERNINGPAIR GetKerningBetweenCharacters(KERNINGPAIR[] lpkrnpair, char first, char second) 
     { 
      return lpkrnpair.Where(x => (x.wFirst == first) && (x.wSecond == second)).FirstOrDefault(); 
     } 

     static ABCFLOAT GetCharacterWidths(IntPtr hDC, char character) 
     { 
      ABCFLOAT[] values = new ABCFLOAT[1]; 
      GetCharABCWidthsFloat(hDC, character, character, values); 
      return values[0]; 
     } 
    } 
} 

Her bir yazı tipi boyutu için, karakter aralığı dahil olmak üzere her karakterin genişliğini verir. 96 DPI anda, benim için bu sonuçları içinde:

[Yazı: Adı = Arial, Boyut = 7.5, Birimler = 3, GdiCharSet = 1, GdiVerticalFont = False]
S: 7 (7 + 0)
T: 6 (7 + -1)
A: 7 (7 + 0)
R: 7 (7 + 0)
T: 7 (7 + 0)
toplam genişliği: 34

[Yazı tipi: Adı = Arial, Boyut = 8.25, Birimler = 3, GdiCharSet = 1, GdiVerticalFont = False]
S: 7 (7 + 0)
T: 5 (6 + -1)
A: 8 (8 + 0)
R: 7 (7 + 0)
T: 6 (6 + 0)
toplam genişliği: 33 Açıkçası TextRenderer tarafından yapılan ölçümler için kesin formülü ele ettik rağmen

, aynı width- göstermek etmez tutarsızlık. Yazı tipi boyutu 7'de, tüm karakterler 7 genişliğindedir. Ancak, yazı tipi boyutu 8'de, karakter genişlikleri değişmeye başlar, bazıları daha büyük, biraz daha küçük, sonuçta daha küçük bir genişliğe kadar eklenir.

1

TextRenderer.MeasureText doğru değeri veriyor gibi görünüyor, ancak daha küçük yazı tipi bazı glifler için daha büyük harf aralığı içeriyor.

Aşağıda, "TTTTTTTTT" metninin nasıl göründüğünü görebilirsiniz. Üstteki, Arial 7, diğerinin ise Arial 8.

Daha büyük yazı tipi için harfler arasında boşluk yoktur. Daha büyük bir yazı daha küçük bir genişliğe üretmek için

enter image description here

İlgili konular