Laden...

Font Ascend, Descend und Leading

Letzter Beitrag vor 16 Jahren 20 Posts 3.514 Views
Font Ascend, Descend und Leading

Moin moin,

ich habe für ein Problem ein Beispiel gefunden womit ich Text besser auf einer zeichenoberfläche ausrichten kann.


// Ascent for Arial font is 728.
float arialAscent = 728;
// Descent for Arial font is -210.
float arialDescent = -210;
// Leading for Arial font is 1088.
float arialLeading = 1088;

Diese Werte sind auf die Schriftart "Arial" beschränkt. Ich benötige jedoch dynamisch die Bestimmung dieser Werte ohne nun alle möglichen Schriftarten in Windows selbst aufzuschreiben.

Nun die Frage ob jemand weiß wie ich an die Werte von den einzelnen Schriftarten komme?

Hoffe jemand kann mir helfen! Bei Fragen, fragen 😉.

gruß
mbk_chilli

Die drei Tugenden eines Programmierers:
Faulheit, Ungeduld und Hochmut!

Ich beschäftige mich derzeit auch damit... brauch das auch, gut dass es die Suche gibt 😉 Hiermit möchte ich diesen Thread "wiederbeleben".

Ich bin soweit gekommen (mit GDI+)

Font cf=new Font("Arial", 32);
int ascent=(int)(cf.GetHeight()*cf.FontFamily.GetCellAscent(cf.Style) / cf.FontFamily.GetLineSpacing(cf.Style));
int descent=(int)(cf.GetHeight()*cf.FontFamily.GetCellDescent(cf.Style) / cf.FontFamily.GetLineSpacing(cf.Style));

Jedoch bekomme ich hier noch nicht die ganz genauen Werte, vielleicht kennt jemand eine andere Lösung?!

trust is a weakness,
betrayal is the hidden blade

Hallo,

was meint ihr denn mit "Ausrichten"?
Wenn es darum geht, einen Text in einem Bereich (Rectangle) auszurichten, gibt es
die Klasse StringFormat.

Grüße,

psy

Weißt du, was Ascent und Descent bei einem Font ist? 😉

Also.. es gibt bei Buchstaben eine gedachte linie... alles was unter dieser Linie ist, ist Descent (zb bei j, der Hacken), was darüber ist, ist Ascent (alles außer der hacken beim j) .. das gibts dann noch links und rechts, das interessiert uns aber in dem Fall jetzt nicht.

Und ich brauch den genauen Ascent und Descent von nem Font 😉

Kennt sich da jemand aus?

trust is a weakness,
betrayal is the hidden blade

Bei der Windows GDI gibt es die Funktion GetTextMetrics, welche eine TEXTMETRIC-Struktur zurückliefert, in der u.a. Ascent und Descent des aktuellen Fonts definiert sind (s. http://www.pinvoke.net/default.aspx/gdi32/GetTextMetrics.html)

Danke, das kenn ich schon 😉 Ich möchte pinvoke vermeiden, da dann wieder Abhängigkeiten enstehen... der Code soll auf x86 und x64 Architekturen laufen -> .Net

trust is a weakness,
betrayal is the hidden blade

Hi KenshinX,

ja, jetzt bin ich wohl schlauer 🙂 . Die Frage ist aber nach wie vor, ob
du diese Werte überhaupt brauchst. Und zum Ausrichten brauchst du sie halt nicht.

Grüße,

psy

Nene schau... ich brauch die werte, da ich tables usw alles selbst zeichne

und da brauch ich cellAscent, cellDescent, ExternalLeading ...

ExternalLeading hab ich schon

nur cellAscent und cellDescent sind leider noch zu ungenau beim Ascent ists oft +-1, beim Descent jedoch oft mal bis zu 4 Unterschied... und das haut halt rein bei den Berechnungen.

Also, irgendwelche Vorschläge? 😉

trust is a weakness,
betrayal is the hidden blade

Hmm ich will dich ja nicht nerven, aber selbst zum Zeichnen einer Table
brauchst du das nicht.
Ich habe mal quick'n'dirty etwas Code geschrieben und ein Bild angehangen.

Sollte das nicht reichen?


         // Table erstellen
         DataTable aTable = new DataTable();
         aTable.Columns.Add(new DataColumn("Spalte 1"));
         aTable.Columns.Add(new DataColumn("Spalte 2"));
         aTable.Columns.Add(new DataColumn("Spalte 3"));
         aTable.Rows.Add(new object[] {"Wert 1", "Wert 2", "Wert 3"});
         aTable.Rows.Add(new object[] {"Wert 4", "Wert 5", "Wert 6"});
         aTable.Rows.Add(new object[] {"Wert 7", "Wert 8", "Wert 9"});        

         // Bild
         Image aImage = new Bitmap(pictureBox1.Width, pictureBox1.Height);

         // Graphics zum Zeichnen
         Graphics aGraphics = Graphics.FromImage(aImage);
         aGraphics.SmoothingMode = SmoothingMode.HighQuality;

         // StringFormat
         StringFormat aStringFormat = new StringFormat();
         aStringFormat.Alignment = StringAlignment.Center;
         aStringFormat.LineAlignment = StringAlignment.Center;

         // Font
         Font aFont = new Font("Arial", 11.0f);

         // BorderPen
         Pen aBorderPen = new Pen(Color.Blue, 2.0f);

         // FontBrush
         SolidBrush aFontBrush = new SolidBrush(Color.Black);

         // StartPos
         Point aPos = new Point(10, 10);

         // Cells
         foreach (DataRow aDataRow in aTable.Rows)
         {
            object[] aRow = aDataRow.ItemArray;

            Rectangle aRect = new Rectangle(0, 0, 1, 1);
            foreach (object aRowEntry in aRow)
            {
               Size aSize = aGraphics.MeasureString(aRowEntry.ToString(), aFont, 500, aStringFormat).ToSize();
               aRect = new Rectangle(aPos, aSize);

               // Celle vergrößern, damit Text etwas mehr Platz hat
               aRect.Inflate(5, 5);

               aGraphics.DrawString(aRowEntry.ToString(), aFont, aFontBrush, aRect, aStringFormat);
               aGraphics.DrawRectangle(aBorderPen, aRect);

               aPos.X += aRect.Width + 5; // Zwischenraum X-Richtung
            }

            aPos.X = 10;
            aPos.Y += aRect.Height + 5; // Zwischenraum Y-Richtung
         }

         // Zuweisung
         pictureBox1.Image = aImage;
         // Dispose
         aGraphics.Dispose();
         aStringFormat.Dispose();
         aFont.Dispose();
         aBorderPen.Dispose();
         aFontBrush.Dispose();

Grüße,

psy

Danke für das Beispiel 😉
Es geht einfach darum, dass ein 13 Jahre altes Programm nach C# portiert werden soll und der Code an sich nicht verändert... und da werden eigene Strukturen verwendet... es wird eine word datei ausgelesen (aufbau ist wie ein stack) ... und da muss ich das dynamisch aus den fonts generieren, also die abstände (nicht nur für die tables, auch für den normalen text). Das ist der genaue Grund ;o)

Trotzdem danke für die viele Mühe

trust is a weakness,
betrayal is the hidden blade

13 Jahre altes Programm portieren ....

Na dann viel Spaß noch 🙂

Du wirst lachen, aber ich bin schon fast fertig 😉 Sind nur noch so Kleinigkeiten... unter anderem eben die genaue Berechnung des blöden Ascent und Descent (External Leading hab ich schon g) ...

Also wenn jemand einen Vorschlag hat, ich bin für alles offen 😉
Sollte ganz genau sein... also der Font Ascent und Descent

Danke im Voraus!

trust is a weakness,
betrayal is the hidden blade

Hat niemand eine Idee wie man das richtig macht? 😕

trust is a weakness,
betrayal is the hidden blade

Font Ascent und Descent

Hi an alle!

Ich weiß es gibt schon einen Thread der das Thema behandelt (hat anfangs um etwas anderes gehandelt). Ich starte mit Absicht diesen neuen Thread und bitte um Hilfe:

Ich portiere eine Class-Library von C++ nach C# ... in C++ wurde die Methode GetTextMetrics aufgerufen und von einem Font den Ascent und Descent zu bekommen. Ich möchte es vermeiden pinvoke zu benutzen, daher frage ich ob jemand eine Managed variante kennt?

Habs schon mit den Methoden GetCellAscent bzw. GetCellDescent der Klasse FontFamily versucht, jedoch sind die Ergebnisse zu ungenau 😕

Vielen Dank im Voraus!
KenshinX

trust is a weakness,
betrayal is the hidden blade

Hallo KenshinX,

ist immer noch haargenau das gleiche Thema. Deshalb ==> zusammengefügt.

herbivore

Gnah ich weiß, sorry aber hier hat einfach niemand mehr was geschrieben... aber anscheinend kennt sich damit leider niemand aus 😦

trust is a weakness,
betrayal is the hidden blade

Hallo KenshinX,

ich denke schon, dass es hier Leute gibt, die sich damit auskennen. Es wurde ja schon einen Lösung genannt. Die willst du ja aber nicht. Vielleicht gibt es für dein Problem einfach keine Alternative zu P/Invoke. Wenn du das genau wissen willst und es dir so wichtig ist, dann musst du mal das Geld für eine Supportanfrage bei MS investieren. Ich vermute, dass die dir sagen werden, dass du P/Invoke benutzen musst. Das führt ja aber nicht zwangsläufig zu weniger Portabilität. So wie ich es verstehe, hat ja dein altes Programm auch die Funktionen benutzt, die du momentan um keinen Preis mehr benutzen willst. Gut, natürlich kann es dein Ziel sein, dass das neue Programm portabler ist als das alte. Aber auch das bekommst du hin, indem du die P/Invoke-Aufrufe in eine eigene Assembly kapselst, von der du für jedes Zielsystem (bzw. jede Gruppe von Zielsystemen) eine passende Version zur Verfügung stellst und lädst. Im schlimmsten Fall sind dann bestimmte Funktionalitäten des Programms unter bestimmte Zielsystemen nicht verfügbar bzw. müssen nachprogrammiert werden, um sie zur Verfügung zu haben. Wenn du verstehst, was ich meine.

herbivore

Hallo,

wenn wirklich alle Stricke reißen, gibs immernoch, die verdammt unschöne, aber mögliche Möglichkeit,

Buchstaben aus der Schriftart in einer sehr vergrößerten Variante in ein temporäres Bild zu zeichnen.
Man kreire sich ein weißes Bitmap (500x500 oder so), zeichne das Schriftzeichen drauf, und bestimme die Höhe (also Abstand zwischen letzter weißer Zeile oben und erster unten)

Das Ganze dann für drei Buchstaben (Q, Z, z) oder so und noch zweizeilig...
Dann kannste das daraus eigentlich alles berechnen.

Ich weiß, ist nich schön, aber möglich. evtl kann man ja auch nur "fast" zeichnen,
und

MeasureCharacterRanges()

bzw

MeasureString()

dazu missbrauchen.

(weiß aber nicht, ob diese Methoden wirklich ein "perfekt passendes" Rechteck zurückgeben, oder da noch Fleisch dazwischen is.

Ein Probieren wärs wert.

beste Grüße
zommi

@herbivore
super danke für deine Antwort 😉 Ich glaub ich werds so machen...

@zommi
auch dir vielen dank für deine Mühe aber ich glaub darunter würd die performance zu sehr leiden 🙂

trust is a weakness,
betrayal is the hidden blade

Kennt sich vl jemand mit dem VisualStyleRenderer aus?

trust is a weakness,
betrayal is the hidden blade