verschiedene Schriftgrößen auf einer Höhe ausrichten?

  • Hi,
    ich möchte in meinem Skin flatPlus gerne verschiedene Schriftgrößen auf einer Höhe ausrichten, und komme nicht ganz weiter. Vielleicht hat ja jemand einen Rat für mich :)
    Hier ist das passende Ticket http://projects.vdr-developer.org/issues/1884


    Im genauen geht es darum die Sekunden der Aufnahme kleiner darzustellen also im Format:
    HH:MM:SS


    Hier mal eine Übersicht übe die Font Metric
    [Blockierte Grafik: http://i.imgur.com/yZxVRd0.png]


    HH:MM wird mit Top = 0 und z.B. Schriftgröße 50 gezeichnet.
    Wenn die Sekunden nun eine Schriftgröße von z.B. 20 hat, ist die Frage mit welchem Top muss ich die Sekunden zeichnen damit sie auf gleicher Grundlinie ausgerichtet sind?


    Wen man sich die Font Metric anschaut habe ich mir so gedacht, ich muss einfach vom Ascender vom Font für HH:MM den Ascender vom Font für die Sekunden abziehen und das ergibt den Top?
    Aber entweder funktioniert das nicht so einfach oder ich habe noch einen Fehler den Ascender zu bestimmen.


    Ich habe mir für den Ascender einfach ein bisschen Quellcode aus dem VDR geklaut :)
    Der sieht ungefähr so aus:


    Ich muss gestehen ich kenn mich 0 mit freetype aus und habe das so ziemlig 1:1 übernommen.


    Top für Sekunden berechne ich dann wie folgt:

    Code
    int fontAscender = GetFontAscender(Setup.FontOsd, fontHeight);
        int fontSecsAscender = GetFontAscender(Setup.FontOsd, fontSecs->Height());
        int topSecs = fontAscender - fontSecsAscender;


    Aber wie gesagt irgendwie stimmen die Werte nicht oder die Berechnung ist falsch.


    Vielleicht kennt sich ja jemand besser mit freetype aus als ich und kann mir helfen :)


    Grüße
    Martin

  • Der Gedanke ist schon richtig, die Schriften müssen an der Grundlinie ausgerichtet werden.
    Mit freetype kenne ich mich auch nicht aus, hab aber sowas schon unter Windows mit der Win32-API und auch WPF gemacht. Hast du denn die Werte einfach mal ausgegeben? Was kommt denn da raus?
    Beim Zeichnen musst du dann deine y-Position der Sekunden um topSecs nach unten schieben.


    Lars.

  • Ja ein paar Debug Ausgaben werde ich die Tage mal nachreichen damit man mal sieht was für Werte dort rauskommen.
    Ist ja schonmal schön das der Gedankengang richtig ist :) MegaV0lt und ich haben schon ganz schön gegrübelt (siehe redmine) :wand


    Grüße
    Martin

  • Es hilft sonst, Rechtecke zu zeichnen, damit man weiß, wie der Text positioniert wird.
    Ich lese mir das in Redmine mal durch, da sind ja auch ein paar Zahlen drin... :)


    Lars.

  • Ich bin mal so frei:

    Code
    Aug 05 10:35:17 [vdr] [32036] fontHeight: 50 fontBaseHeight: 45 fontSecsHeight: 34 fontSecsBaseHeight: 31 topSecs: 11 (70%) OK 
    Aug 05 10:43:24 [vdr] [32036] fontHeight: 50 fontBaseHeight: 45 fontSecsHeight: 43 fontSecsBaseHeight: 39 topSecs: 2 (90%) Sekunden zu weit oben 
    Aug 05 10:45:34 [vdr] [32036] fontHeight: 50 fontBaseHeight: 45 fontSecsHeight: 18 fontSecsBaseHeight: 16 topSecs: 27 (40%) Sekunden zu weit unten


    Die verwendete Schrift ist VDRPTSans. fontBaseHight/fontSecsBaseHight ist der Ascender, der meiner Meinung nach eher bei 40 liegen müsste


    Folgende Punkte sind Unklar:
    Ist FontHight der ganze Font mit dem Leadings oder nur die bbox?
    Ist der Ascender die Strecke von der Baseline nach ganz oben oder ist da noch irgend ein Leading mit drin?


    OT: Müsste der VDR nicht so eine Funktion mit an Bord haben? Genau so schön wäre die Möglichkeit im VDR den Text vom EPG auch in Blocksatz darstellen zu können.

  • FT_Set_Char_Size scheint standardmäßig mit 72dpi zu rechnen. Hast du mal andere Werte probiert? Vielleicht rundet er dann nicht mehr so stark.
    http://www.freetype.org/freety…ace.html#FT_Set_Char_Size


    Sind die 50 für die Fontgröße eigentlich Pixel oder 50pt?


    Lars.

  • Laut http://www.freetype.org/freetype2/docs/tutorial/step2.html unter Punkt "3. Global glyph metrics":


    "height" ist quasi von baseline zu baseline, das ist für mehrzeiligen Text interessant, damit die Zeilenabstände "schön" sind.


    Lars.

  • 1pt ist ja 1/72 inch, d.h. bei 72dpi ist 1pt = 1px. Wenn du die wirklichen dpi kennst (zur Not einstellbar in der Config?), dann kannst du die "richtigen" Pixel ausrechnen lassen.
    Meistens wird bei Bildschirmen mit 96dpi gerechnet. Aber ein bisschen probieren schadet bestimmt nicht.


    Lars.

  • In IView gibt es auch eine Messfunktion. Anhand eines Screenshots habe ich mal gemessen. Die 45 können nicht stimmen. Im Bild sieht man wie weit der senkrechte Messstrich nach oben geht. Ich habe noch eine Rote Linie zur Marke gesetzt; da sieht man, dass die dann überlappen würde. Das Bild selbst ist vergrößert. IView misst aber trotzdem die Pixel des 1:1 Bildes:
    [Blockierte Grafik: http://i.imgur.com/QUF77MC.png]
    Ist das wirklich so, dass der Font mit 0 oder -1 oben anliegt?

  • So im git sind ein nun ein paar Debug Ausgaben. Das sieht nun so aus.



    Code
    int fontAscender = GetFontAscender(Setup.FontOsd, fontHeight);
        int fontSecsAscender = GetFontAscender(Setup.FontOsd, fontSecs->Height());
        int topSecs = fontAscender - fontSecsAscender;
        dsyslog("fontHeight: %d fontAscender: %d fontSecsHeight: %d fontSecsAscender: %d topSecs: %d", fontHeight, fontAscender, fontSecs->Height(), fontSecsAscender, topSecs);


    Meine Debug Ausgabe sieht nun wie folgt aus

    Code
    Aug  6 17:53:42 Manu vdr: [12468] fontHeight: 50 fontAscender: 47 fontSecsHeight: 20 fontSecsAscender: 19 topSecs: 28
    Aug  6 17:53:43 Manu vdr: [12468] GetFontAscender font: Ubuntu:Medium height: 50 asc: 47 desc: -10
    Aug  6 17:53:43 Manu vdr: [12468] GetFontAscender font: Ubuntu:Medium height: 20 asc: 19 desc: -4


    Und die Sekunden sind wie gehabt zu tief :wand


    Ich bin für jeden Tipp dankbar!


    Grüße
    Martin

  • Kannst du die Position der baseline als Referenz für das Zeichnen nehmen?
    Also den großen Text bei yBaseline - fontAscender zeichnen und den kleinen bei yBaseline - fontSecsAscender?


    Ich muss jetzt erst mal weg, bin aber evtl. in drei Stunden am Rechner für ein Experiment.


    Lars

  • Ich habe nochmal Rechtangles gezeichnet damit man die Positionen und höhen besser sieht.


    Rot:
    Top = 0
    Height = fontHeight


    Grün:
    Top = topsSecs
    Height = fontSecsHeight


    Gelb:
    Top = 0
    Height = fontAscender


    Blau:
    Top = topsSecs
    Height = fontSecsAscender


    Hier sieht man schön das Gelb + Blau eine gleiche Basislinie hat, also die Berechnung stimmt soweit. Aber der Ascender scheint viel zu hoch zu sein, es geht ja viel Tiefer als das "0:05".


    Grüße
    Martin

  • Ok. Rot und Grün ist ein wenig sinnfrei, da die Höhen der Fonts und der Ascend vom kleinen Font nicht viel miteinander zu tun haben. Aber dann hat man einen Vorstellung davon.


    Gelb und Blau sehen gut aus. Dass das Rechteck über die Zahlen hinausragen, ist auch ok, da es ja der globale Ascend ist, d.h. es kann in dem Font Zeichen geben, die größer sind.


    Kannst du den Ascend der beiden Fonts des Zeichens 0 auslesen? Bei den Zahlen gehe ich einfach mal davon aus, dass alle gleich groß sind. Vielleicht passt es da ja besser.


    (Leider hat sich meine Testkiste irgendwie ein wenig verabschiedet, das Ding muss ich erst mal neu installieren, das schaffe ich heute nicht mehr. Aber vielleicht kann ich trotzdem noch ein wenig probieren...)


    Lars.

  • Evtl. musst du noch Debug-Ausgaben in vdr's "cFreetypeFont::DrawText(cPixmap *Pixmap, ..." (font.c) einbauen.
    Ich schätze mal, Antialiasing ist aktiv bei dir? Dann werden die Buchstaben-Pixel ja so in das Pixmap übertragen:

    Code
    Pixmap->DrawPixel(cPoint(x + pitch + g->Left() + kerning, y + row + (height - Bottom() - g->Top())), AlphaBlend(ColorFg, ColorBg, bt));


    "Bottom" dürfte der Descender sein (ist also negativ), "Top" ist bitmap_top aus FT_GlyphSlot (siehe http://www.freetype.org/freety…face.html#FT_GlyphSlotRec).
    Keine Ahnung, ob das jetzt Einfluss hat. Ich stochere nur ein wenig hier und da und lese mich in Freetype ein...


    Lars.

  • Gelb und Blau sehen gut aus. Dass das Rechteck über die Zahlen hinausragen, ist auch ok, da es ja der globale Ascend ist, d.h. es kann in dem Font Zeichen geben, die größer sind.


    Ja das ist schon richtig das es Zeichen gibt die weiter nach oben gehen. Das sieht man ja auch bei Gelb + Blau das sie weiter oben anfangen. Wenn man sich aber das Bild mit den Font Metricen anschaut müsste der Ascender immer an der Grundlinie enden und das tut er in meinem Fall nicht.


    Kannst du den Ascend der beiden Fonts des Zeichens 0 auslesen? Bei den Zahlen gehe ich einfach mal davon aus, dass alle gleich groß sind. Vielleicht passt es da ja besser.


    Ja das habe ich nun auch schon überlegt. Mir einen einzelnes Zeichen also einen "Glyph" zu holen und dort die genauen Abmessungen herausholen. Das muss ich mir am Wochenende einmal anschauen.


    Debug Ausgaben im VDR bei der direkten Ausgabe ist auch noch eine Gute Idee mal gucken ob man da noch was erkennt.


    Danke auf jedenfall für deine Unterstützung!


    Grüße
    Martin

  • An der Linie (1 Pixel, Gelb) sieht man , das der Ascender definitiv falsch ist:
    [Blockierte Grafik: http://i.imgur.com/dPCKICv.png
    Laut Definition müsste die 0:05:00 dort aufsitzen. Wenn ich im Quelltext bei mir wo ein Ascender von 45 (VDRPTSans, Größe: 3,9 (50)) gemeldet wird 5 Abziehe passt es bis auf 1 Pixel fast genau.

    Code
    int fontAscender = GetFontAscender(Setup.FontOsd, fontHeight) - 7;
    ... 
    int topSecs = fontAscender - (fontAscender * Config.TimeSecsScale * 100.0);


    ^ Allerdings kann ich dann fontSecsAscender nicht verwenden, da der Wert unbekannt ist. Ich berechnen den Wert über den TimeSecScale-Faktor


    Die Frage ist nun, warum der Ascender zu groß ist, und wo die 7 Pixel her kommen?


    Edit: Im Bild ist der Abstand von 00:05 zur Gelben Linie 7 Pixel.
    Im Log von _Martin_ steht

    Zitat

    GetFontAscender font: Ubuntu:Medium height: 50 asc: 47 desc: -10

    Das ist auch unlogisch, weil Ascender + Descender = 57. Also 7 Pixel mehr als die Höhe des gesamten Fonts! Da sind sie wieder die 7 Pixel...
    Vielleicht muss man das was zu viel raus kommt einfach vom Ascender wieder abziehen?


    Code
    RealAscender = fontAscender - ((fontAscender - fontDescendet) - fontHight); // In der Klammer - weil Descender negativ ist
    Real Ascender= 47 - ((47 - -10) - 50); // Mit den Werten. Sollte 40 ergeben...
  • Ich habe das jetzt mal ausprobiert:

    Code
    error = FT_Set_Char_Size(face, CharWidth * 64, CharHeight * 64, 0, 0);
                	if (!error) {
                    	dsyslog("GetFontAscender font: %s height: %d asc: %d desc: %d", Name, CharHeight, face->size->metrics.ascender/64, face->size->metrics.descender/64);
                    	//Ascender = face->size->metrics.ascender/64;
                    	Ascender = face->size->metrics.ascender/64 - ((face->size->metrics.ascender/64 - face->size->metrics.descender/64) - CharHeight);
                    	dsyslog("GetFontAscender calculated ascender: %d", Ascender);

    Die letzten drei Zeilen sind geändert.
    Die komplette baserender.c


    Ergibt folgende Logs:


    Hier die Bilder dazu:
    40% 1 Pixel zu hoch Rundungsfehler?
    [Blockierte Grafik: http://i.imgur.com/HrDjrwo.png
    70% 1 Pixel zu hoch Rundungsfehler?
    [Blockierte Grafik: http://i.imgur.com/8l3JNDo.png
    90%
    [Blockierte Grafik: http://i.imgur.com/U2KICU1.png
    Sieht eigentlich gut aus... Hab nicht viel Ahnung vom Programmieren und bin eigentlich recht überrascht, dass es so gut aussieht. Nun müssten andere auch mal testen. Vor allem auch mit anderen Fonts

  • Code
    Ascender = face->size->metrics.ascender/64 - ((face->size->metrics.ascender/64 - face->size->metrics.descender/64) - CharHeight);


    Wenn ich das mal mathematisch auflöse, steht da nichts anderes als:

    Code
    Ascender = face->size->metrics.descender/64 + CharHeight;


    Da der Descender negativ ist, wird die CharHeight also um diesen Betrag reduziert.


    Hilf mir mal einer auf die Sprünge: Wie liegt das Koordinatensystem im OSD? Ist 0,0 links oben? Die Position in DrawText ist doch eigentlich die linke, obere Ecke des Kastens, in dem der Text gezeichnet wird, oder?


    Lars.

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!