c # DrawString - messen Sie Begrenzungsrahmen für jedes Zeichen

8

Bevor ich eine Zeichenkette an Graphics.DrawString () übergebe, möchte ich genau wissen, wo jedes Zeichen sein wird - nicht nur, dass es Offset und Breite ist, sondern seine genaue Begrenzungsbox mit Aufstieg / Abstieg Machen Sie Kollisionserkennung auf der Zeichenebene, anstatt die gesamte Zeilenhöhe zu verwenden, die Graphics.MeasureString () mir gibt.

Ich kann anscheinend keine Beispiele dafür finden, die genau die Begrenzungsbox für jedes Zeichen zurückgeben. Wie kann dies in c # / GDI + gemacht werden?

Im Idealfall möchte ich jedes der grauen Rechtecke wie in diesem Bild erhalten:

    
powlette 28.08.2013, 20:40
quelle

5 Antworten

3

Ich glaube nicht, dass es möglich ist, Zeichen in einer Zeichenfolge in GDI + genau zu messen. Selbst wenn Sie Subpixel-Positionierung und Kerning usw. vergessen haben, was bedeutet, dass die Zeichen in der gezeichneten Zeichenkette abhängig vom Kontext in der Zeichenkette und Position auf dem Bildschirm und den ClearType-Einstellungen unterschiedliche Größen haben, hat MeasureString die Gewohnheit, Füll- und Fudge-Faktoren hinzuzufügen kann nicht leicht die gewünschten Informationen daraus bekommen.

Ein Ansatz, der funktioniert, ist das Messen des ersten Zeichens, dann der ersten zwei Zeichen, dann der ersten drei Zeichen usw., so dass Sie eine ungefähre Vorstellung davon bekommen, wo sie alle landen werden, wenn sie in einem einzigen Treffer gezeichnet werden . Dann müssen Sie wahrscheinlich jeden Char erneut messen, um seine Höhe zu bestimmen. Wenn MeasureString nicht die Zeichenhöhe angibt, sondern stattdessen die Schrifthöhe angibt, müssen Sie eventuell jedes Zeichen in eine Bitmap im Offscreen-Format konvertieren und dann die Pixel scannen, um die wahre Höhe des Zeichens zu ermitteln.

An diesem Punkt finden Sie vielleicht, dass es besser ist, auf eine Font-API der unteren Ebene zuzugreifen, die Ihnen nur die Informationen liefert, die Sie direkt von der Schriftart benötigen. Aber dann müssen Sie wahrscheinlich etwas anderes als GDO + verwenden, um es zu rendern, da die Chancen, dass es mit dem übereinstimmt, was Sie herausgefunden haben, nicht gut sind.

(Kannst du mir sagen, dass ich bereits ein Problem mit der Qualität des GDI + -Resigner-Renderers habe?)

    
Jason Williams 28.08.2013 22:29
quelle
3

EDIT: Dies ist die Lösung, die ich verwendet habe, aufbauend auf @ Saykas Beispiel und einem Trick, um die tatsächliche Zeichenbreite zu erhalten:

Wenn Sie eine Zeichenkette an X, Y mit der Schriftart in Grafik g1 zeichnen, können Sie jede Zeichenkette mit diesen Rechtecken zeichnen:

%Vor%

Sieht so aus:

    
powlette 29.08.2013 13:43
quelle
2

Hier ist der Code

%Vor%

. .

.

.

.

.

Gemessener erster schwarzer Punkt von links, dann rechts, dann oben und unten. Rate, wenn das hilft ..

    
Sayka 28.08.2013 23:16
quelle
0

Erstellen Sie ein unsichtbares Fenster für Messzwecke mit genau der gleichen Größe und Schriftart, was Sie im "echten" Fenster haben. Danach können Sie die einzelnen Bounding-Boxen der Zeichen abziehen, indem Sie weitere Daten zusammenführen:

  • Rechteck der Auswahl des einzelnen Zeichens, das die linken und rechten Grenzen des Zeichens angeben kann. Leider ist die Höhe davon die volle Höhe der Zeile
  • Höhe aus Daten von MeasureCharacterRanges () oder ähnlicher Technik

Ich stimme allerdings mit @Jason Williams überein. "Padding- und Fudge-Faktoren" können die Ergebnisse ein wenig verzerren.

    
Csaba Toth 28.08.2013 22:57
quelle
0

Wenn die Leistung nicht kritisch ist, würde ich meinen, Sie könnten die genauesten Ergebnisse erzielen, indem Sie die Zeichen in Pfade umwandeln und diese untersuchen. Ich bin nicht sicher, der beste Weg, Kerning Probleme zu behandeln, aber für Schriften ohne Ligaturen könnte man wahrscheinlich die Begrenzungsrahmen für Zeichen isoliert, relativ zu ihren Startpunkten gemessen, und dann die Startpunkte jedes Zeichens im Kerned bestimmen Zeichenfolge. Bei Schriftarten mit Ligaturen müssen einzelne Zeichen nicht immer eindeutige Glyphen enthalten. Wenn beispielsweise eine Schriftart eine "ffi" -Ligatur aufweist, kann das Wort "offing" nur vier Glyphen enthalten: "o", "ffi", "n" und "g"; es wäre bedeutungslos, nach der Begrenzungsbox des "Ich" zu fragen.

    
supercat 28.08.2013 23:10
quelle

Tags und Links