2012-02-01 13 views
10

मैं संख्या जहां बीच में अंक में से कुछ फ़ॉन्ट आकार और वजन में वृद्धि से जोर दिया जाता है मुद्रित करने के लिए की जरूरत है। नीचे दिए गए उदाहरण में, 456 पर जोर दिया गया है।GDI एक आधार रेखा पर विभिन्न आकारों के साथ + ड्राइंग पाठ है बंद-दर-1px समस्याओं

enter image description here

फ़ॉन्ट और दो आकारों का इस्तेमाल किया उपयोगकर्ता के विन्यास कर रहे हैं।

वर्तमान कोड Graphics.DrawString(...) करने के लिए तीन कॉल का उपयोग करता है।

समस्या मैं कर रहा हूँ

है कि सबसे अधिक फोंट के साथ, मैं बंद-दर-1pixel समस्याओं (ग्रे लाइन के सापेक्ष, 456 एक अतिरिक्त पिक्सेल उच्च कि अन्य अंकों बैठा है) देख रहा हूँ है:

enter image description here

मैं अपनी पोस्ट के निचले भाग में कुछ डिबगिंग विभिन्न फोंट के लिए (बॉब पॉवेल सूत्र के) डंप संलग्न किया है। अन्य तकनीकों ने इसी तरह के परिणाम दिए।

आदेश आम आधाररेखा पर पाठ मुद्रित करने के लिए, एक आधारभूत एक विशेष Font के लिए ऑफसेट की गणना की जरूरत है।

पहले, MSDN के कोड: http://msdn.microsoft.com/en-us/library/xwf9s90b(v=vs.80).aspx

ascent = fontFamily.GetCellAscent(FontStyle.Regular); 
ascentPixel = font.Size * ascent/fontFamily.GetEmHeight(FontStyle.Regular) 

दूसरा, से कोड: Using GDI+, what's the easiest approach to align text (drawn in several different fonts) along a common baseline?

अंत में, बॉब पावेल के पद से कोड: http://www.bobpowell.net/formattingtext.htm

यहाँ मेरी है मैं तीन तकनीकों का उपयोग कर की कोशिश की है आकर्षित विधि:

private void DrawOnBaseline(Graphics g, string text, FontWithBaseline fwb, Brush brush, float x, float y) { 
    g.DrawString(text, fwb.Font, brush, x, y - fwb.Baseline, StringFormat.GenericTypographic); 
} 

कहाँ FontWithBaseline बस अपने संबंधित आधारभूत गणना के साथ एक फ़ॉन्ट एकत्रित करती है:

public class FontWithBaseline { 
    private Font m_font; 
    private float m_baseline; 

    public FontWithBaseline(Font font) { 
    m_font = font; 
    m_baseline = CalculateBaseline(font); 
    } 

    public Font Font { get { return m_font; } } 
    public float Baseline { get { return m_baseline; } } 

    private static float CalculateBaseline(Font font) { 
    ... // I've tried the three formulae here. 
    } 
} 

मैं अभी तक Graphics.TestRenderingHint के साथ प्रयोग नहीं किया है। क्या यह जादू सॉस है? मुझे क्या याद आ रही है? क्या कोई वैकल्पिक एपीआई है जिसका मैं उपयोग कर सकता हूं, जहां मैं बेसलाइन के वाई समन्वय को आपूर्ति करने के लिए कॉल कहता हूं?

enter image description here


अद्यतन 1

मैं @LarsTech के साथ मेरे कोड अंतर्वेशित। वह एक बहुत अलग कर रहा था; वह जोड़ रहा था। हालांकि, यहां तक ​​कि यह संस्करण भी इस मुद्दे को ठीक नहीं करता है।

protected override void OnPaint(PaintEventArgs e) { 
    base.OnPaint(e); 
    TryLarsTechnique(e); 
} 

private void TryLarsTechnique(PaintEventArgs e) { 
    base.OnPaint(e); 
    Graphics g = e.Graphics; 
    GraphicsContainer c = g.BeginContainer(); 
    g.Clear(Color.White); 
    g.SmoothingMode = SmoothingMode.AntiAlias; 
    g.TextRenderingHint = TextRenderingHint.AntiAlias; 
    Font small = new Font("Arial", 13, FontStyle.Regular, GraphicsUnit.Pixel); 
    Font large = new Font("Arial", 17, FontStyle.Bold, GraphicsUnit.Pixel); 

    int x = 100; 
    int y = 100; 
    x += DrawLars(g, "12.3", small, x, y); 
    x += DrawLars(g, "456", large, x, y); 
    x += DrawLars(g, "8", small, x, y); 
    g.EndContainer(c); 
} 

// returns width of text 
private int DrawLars(Graphics g, string text, Font font, int x, int y) { 
    float offset = font.SizeInPoints/
       font.FontFamily.GetEmHeight(font.Style) * 
       font.FontFamily.GetCellAscent(font.Style); 
    float pixels = g.DpiY/72f * offset; 
    int numTop = y - (int)(pixels + 0.5f);  
    TextRenderer.DrawText(g, text, font, new Point(x, numTop), Color.Black, Color.Empty, TextFormatFlags.NoPadding); 
    return TextRenderer.MeasureText(g, text, font, Size.Empty, TextFormatFlags.NoPadding).Width; 
} 

मैं सोच रहा हूँ कि क्या GraphicsUnit.Pixel का उपयोग कर फ़ॉन्ट आकार को निर्दिष्ट दोषी है: यहाँ कोड है। शायद किसी विशेष फ़ॉन्ट के लिए पसंदीदा आकारों को खोजने का कोई तरीका है?


अद्यतन 2

मैं यह पूरी तरह से या तो समस्या का समाधान नहीं होता है, पिक्सल के बजाय अंक में फ़ॉन्ट आकार को निर्दिष्ट करने की कोशिश की है, और। ध्यान दें कि केवल पूरे बिंदु आकार का उपयोग मेरे मामले में एक विकल्प नहीं है। यह देखने के लिए कि क्या यह संभव है, मैंने विंडोज वर्डपैड पर यह कोशिश की। 96 डीपीआई (और परिभाषा के अनुसार 72 अंक प्रति इंच) का उपयोग करके आकार, 17 पीएक्स, 13 पीएक्स अनुवाद 12.75 और 9.75। यहाँ उत्पादन की तुलना में है:

enter image description here

सूचना कैसे छोटे फोंट एक पिक्सेल स्तर पर एक ही ऊंचाई है। तो वर्डपैड किसी भी तरह से सुविधाजनक मानों के लिए फ़ॉन्ट आकार को गोल किए बिना यह सही करने का प्रबंधन करता है।

उत्तर

5

आपने समस्या को पुन: उत्पन्न करने के लिए पर्याप्त कोड नहीं दिखाया है, इसलिए यहां दिया गया बॉब पॉवेल उदाहरण का उपयोग करके एक कामकाजी उदाहरण है।

प्रदर्शन केवल कोड:

private void panel1_Paint(object sender, PaintEventArgs e) { 
    e.Graphics.Clear(Color.White); 
    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias; 
    e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias; 

    string[] numbers = new string[] { "1", "2", ".", "3", "4", "5", "6", "8" }; 

    int x = 10; 
    int y = 30; 

    foreach (string num in numbers) { 
    Font testFont; 
    if (num == "4" || num == "5" || num == "6") 
     testFont = new Font("Arial", 16, FontStyle.Bold); 
    else 
     testFont = new Font("Arial", 11, FontStyle.Regular); 

    float offset = testFont.SizeInPoints/
        testFont.FontFamily.GetEmHeight(testFont.Style) * 
        testFont.FontFamily.GetCellAscent(testFont.Style); 
    float pixels = e.Graphics.DpiY/72f * offset; 

    int numTop = y - (int)(pixels + 0.5f); 

    TextRenderer.DrawText(e.Graphics, num, testFont, new Point(x, numTop), 
          Color.Black, Color.Empty, TextFormatFlags.NoPadding); 

    x += TextRenderer.MeasureText(e.Graphics, num, testFont, 
            Size.Empty, TextFormatFlags.NoPadding).Width; 
    } 

    e.Graphics.DrawLine(Pens.Red, new Point(5, y + 1), new Point(x + 5, y + 1)); 
} 

यह पैदा करता है:

enter image description here

+0

इसके लिए धन्यवाद। मैंने अपना कोड जोड़ने और अपना दृष्टिकोण शामिल करने के लिए अपना प्रश्न अपडेट कर लिया है। '0.5 एफ' का जोड़ा कुछ नया था। हां, मुझे अभी भी समस्या दिखाई दे रही है। फ़ॉन्ट आकार 17 पिक्सेल + 13 पिक्सल का उपयोग करने का प्रयास करें; मुझे संदेह है कि आप भी समस्या देखेंगे। –

+0

@DilumRanatunga '0.5f' सीधे बॉब पॉवेल के उदाहरण से आया (उस लिंक किए गए पृष्ठ के नीचे देखें)। हां, 'GraphicsUnit.Pixel' का उपयोग करके इसे एक पिक्सेल अपनाना पड़ता है। यकीन नहीं क्यों, लेकिन इसे छोड़कर उन्हें फिर से लाइन में खींचा। मेरा मानना ​​है कि 'GraphicsUnit.Point' डिफ़ॉल्ट है, और इसका उपयोग करते समय, यह भी काम करता है। – LarsTech

+0

@DilumRanatunga यदि मैं कोड को GraphicsUnit.Pixel में बदलता हूं और फिर अपने फ़ॉन्ट आकार के रूप में '12.75f' और' 9.75' का उपयोग करता हूं, तो यह सही ढंग से लाइन करता है। मुझे नहीं लगता * वर्कपैड कोई गोल कर रहा है, मुझे लगता है कि यह सुविधा के लिए उपयोगकर्ता को सिर्फ एक पूर्ण संख्या दिखा रहा है। मैं गलत हो सकता हूं। विजुअल स्टूडियो डिजाइनर डिफ़ॉल्ट 'माइक्रोसॉफ्ट सैन्स सेरिफ़' फ़ॉन्ट के लिए '8.25pt' दिखाता है, लेकिन यदि आप फ़ॉन्ट बदलने के लिए संवाद बॉक्स पर क्लिक करते हैं, तो आप केवल ड्रॉप डाउन में पूरी संख्या देखते हैं। सुनिश्चित नहीं है कि यह आपकी मदद करता है या नहीं। – LarsTech

2

हो सकता है कि समस्या यह है कि आप pixels में अपना फ़ॉन्ट आकार को निर्दिष्ट कर रहे हैं, जबकि अपनी ऑफसेट points में गणना की जाती है और वापस परिवर्तित है pixels में। यह सभी प्रकार के अपर्याप्तताओं को पेश कर सकता है।

points में फ़ॉन्ट आकार निर्दिष्ट करने का प्रयास करें और देखें कि यह काम करता है या नहीं।

+0

मैं मानता हूं कि एक गोल करने वाला मुद्दा अंतर्निहित कारण भी हो सकता है। लेकिन मुझे इसे प्रोग्रामेटिक स्तर पर संबोधित करने की ज़रूरत है। मेरा दूसरा अपडेट देखें। विंडोज वर्डपैड यह सब काम करने का प्रबंधन करता है ... –

+0

निश्चित रूप से आपने अंक में फ़ॉन्ट आकार सेट करने का प्रयास किया है? आपके परिणाम क्या थे? मैं पूछ रहा हूं क्योंकि यह क्या हो रहा है इसके बारे में एक सुराग हो सकता है। – Coincoin

+0

मैंने अंक का उपयोग करने का प्रयास किया। कुछ फ़ॉन्ट आकारों के लिए, यह काम करता है। समस्या यह है कि मैं अपने समाधान को उन फ़ॉन्ट आकारों तक सीमित नहीं कर सकता। मेरे नियंत्रण को उपयोगकर्ता निर्दिष्ट आकारों का समर्थन करने की आवश्यकता है। जब संख्या में बहुत अधिक अंक होते हैं तो इसे आकार के अनुपात को आनुपातिक रूप से स्केल करने की भी आवश्यकता होती है।यदि 'अच्छे' आकार खोजने के लिए एक प्रोग्रामेटिक तरीका था, और ऐसे कई आकार थे, तो मैं इस तरह के दृष्टिकोण को अपना सकता था। –

1

Graphics.TextRenderingHint ग्रिड फिटिंग का उपयोग करने के लिए सेट किया जाता है, पिक्सल में एक छोटा ट्रू टाइप फॉन्ट की वास्तविक मैट्रिक्स GDI द्वारा + फॉन्ट के VDMX table बजाय बस स्केलिंग और इसकी डिजाइन मैट्रिक्स गोलाई से खोज के माध्यम से निर्धारित होते हैं। ग्राफिक्स के माध्यम से कदम उठाने से मुझे यही लगता है। अलग-अलग हिस्सों में ड्रॉस्ट्रिंग।

संबंधित मुद्दे