Schriftgröße an rect-Breite anpassen



  • Hallo,

    ich möchte einen einzeiligen Text über eine bestimmte Pixel-Breite ausgeben. Die Höhe der Schrift muss daher nicht berücksichtigt werden. Momentan löse ich das über folgenden Code:

    Font *font = new Font(&FontFamily(L"Arial"), f_size, FontStyleRegular, UnitPixel);
    
    	while (gdi_rect.Width<grenze)
    	{
    		f_size++;
    		font = new Font(&FontFamily(L"Arial"), f_size, FontStyleRegular, UnitPixel);
    		graphics.MeasureString(breiter_text, -1, font, desk_rect, &gdi_rect);
    	}
    		f_size--;
    		font = new Font(&FontFamily(L"Arial"), f_size, FontStyleRegular, UnitPixel);
    		graphics.MeasureString(breiter_text, -1, font, desk_rect, &gdi_rect);
    

    Die Variable grenze ist die Client-Breite meines Fensters. Die Variable f_size initialisiere ich mit 1 und zähle dann hoch. Der Code funktioniert zwar, aber irgendwie habe ich das Gefühl, dass ich nun etliche Font-Instanzen erzeuge und nicht wieder freigebe?!?

    Wie würdet ihr mit gdiplus die Schriftgröße eines Einzeilers an eine gegebene rect-Breite anpassen?

    Viele Grüße!



  • Ich kenne mich mit gdiplus nicht aus. Aber Deine viel zu vielen Instanzen kriegst Du wieder weg, wenn Du als erste Instruktion in der Schleife und direkt nach der Schleife jeweils ein

    delete font;
    

    einfügst.



  • User13021995 schrieb:

    Wie würdet ihr mit gdiplus die Schriftgröße eines Einzeilers an eine gegebene rect-Breite anpassen?

    Ich gehe mal davon aus, das diese Methode nicht das macht was du meinst ?
    The Graphics::DrawString method draws a string based on a font, a layout rectangle, and a format.

    Graphics::DrawString(WCHAR*,INT,Font*,RectF&,StringFormat*,Brush*);
    

    Eine Möglichkeit könnte sein, den Skalierungsfaktor zu berechnen, statt zig Schleifendurchläufe unnötig auszuprobieren.



  • Hallo,

    herzlichen Dank für eure Tipps. Ich habe es jetzt ohne Schleife versucht und es scheint zu funktionieren:

    int f_size = 10;
    	Font *font = new Font(&FontFamily(L"Arial"), f_size, FontStyleRegular, UnitPixel);
    	graphics.MeasureString(breiter_text, -1, font, desk_rect, &gdi_rect);
    	delete font;
    	float breite1=gdi_rect.Width;
    	font = new Font(&FontFamily(L"Arial"), f_size+1, FontStyleRegular, UnitPixel);
    	graphics.MeasureString(breiter_text, -1, font, desk_rect, &gdi_rect);
    	delete font;
    	float breite2=gdi_rect.Width;
    	float aufschlag = (grenze - breite1)/(breite2-breite1)+0.5;
    	f_size = f_size + (int) aufschlag;
    

    Viele Grüße,
    User13021995



  • Einfach hochrechnen funktioniert nicht zuverlässig wenn Grid-Fitting und Hinting gemacht wird. Bei GDI+ kann man soweit ich weiss beides ausschalten, bei GDI aber nicht.

    Ein guter Mittelweg ist eine binäre Suche. Die bekommt trotz Grid-Fitting und Hinting ein korrektes Ergebnis raus, ist aber immer noch viel viel schneller als "+1".



  • Hallo hustbaer,

    vielen Dank für den Tipp.

    Ich habe in Bezug auf Hinting und Grid-Fit folgende Funktion gefunden:
    graphics.SetTextRenderingHint();
    Allerdings verstehe ich nicht, wieso meine Schrift nur mit dem Parameter TextRenderingHintSystemDefault gut aussieht...ich habe alle Parameter einzeln probiert, bei allen sieht die Schrift irgendwie fransig aus. Bei TextRenderingHintSingleBitPerPixel hätte ich das ja auch erwartet, aber spätestens bei den Aliasing-Parametern hatte ich mit einer sauberen Schrift gerechnet. Bei Default hätte ich auch erwartet, dass er einem der anderen Parameter entspricht...eben jenem, der Systemweit voreingestellt ist. Eine Schrift mit Treppen-Effekt würde ich natürlich nur sehr ungern benutzen.

    Lässt sich nicht ungefähr vorhersagen, mit wie viel Prozent Abweichung aufgrund dieser typografischen Darstellungs-Verbesserungen in der Praxis maximal zu rechnen ist? Nutzt es was, wenn man für die Berechnung des Skalierungs-Faktors die Variable f_size auf einen größeren Wert wie z.B. 100 stellt? Ich bin mir nicht sicher, ob sich bei kleinen Schriftgrößen derartige Techniken nicht stärker auswirken können als bei größeren Schriftengrößen...
    Ich könnte mir auch durchaus vorstellen, z.B. nur 95% der Client-Breite für MeasureString zu verwenden, damit ich bezüglich Hinting und Grid-Fit auf der sicheren Seite bin. Es geht mir mehr darum, die Schrift besonders groß und deutlich im Fenster anzuzeigen, diese muss aber nicht auf den Millimeter genau bis an den Rand reichen...diese Vereinfachung hatte ich vorher zwar nicht im Sinn, aber da hatte ich auch noch nicht mit der Komplexität der Theorie gerechnet, die hinter dieser Aufgabe steckt.

    Zum Thema binäre Suche habe ich auch mal recherchiert und bin immer wieder auf Algorithmen gestoßen, die sich auf eine bekannte Anzahl von zu durchsuchenden Elementen beziehen und sich durch Halbieren des Bereiches zwischen oberer und unterer Grenze an den gesuchten Wert herantasten. Wie hast Du Dir in meinem Fall die Wahl der oberen Grenze vorgestellt? Einfach eine sehr große Schriftgröße wählen(z.B. 1000) und darauf vertrauen, dass die Bildschirm-Auflösung in den nächsten Jahren nicht groß genug werden? Oder von 1 ausgehend mit 2er-Potenzen die obere Grenze der Schriftgröße ausloten und dann im letzten Bereich wieder in die untere Richtung herantasten? Sorry, mit diesen Algorithmen habe ich noch nicht so viel Erfahrung...

    Viele Grüße,
    User13021995


Anmelden zum Antworten