Rendering di testo usando la libreria di caratteri | .NET
Panoramica
Se hai mai desiderato avere la funzionalità di rendere il testo in un’immagine, l’articolo qui ti insegnerà come farlo con caratteri di qualsiasi formato, supportato dalla libreria di caratteri usando la soluzione API Aspose.Font. La libreria consente di convertire facilmente il testo in immagini e aggiungere testo a qualsiasi immagine.
Rendering Testo
Utilizzare il metodo
DrawText della classe
RenderingUtils per disegnare testo in un’immagine. L’esempio visualizza «Hello world» in Verdana e salva il flusso PNG in Text.png.
Impostare DataDir sulla cartella contenente TTF/verdana.ttf e TTF/LatoWeb-Regular.ttf e OutputDir su una cartella di output esistente. Gli esempi usano gli spazi dei nomi Aspose.Font, Aspose.Font.Sources, Aspose.Font.Renderers, System, System.IO. Nel progetto di test, BaseTests fornisce le cartelle e la configurazione della licenza.
1// Render text to a PNG image
2
3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
5string text = "Hello world";
6string outFile = Path.Combine(OutputDir, "Text.png");
7using (Stream image = RenderingUtils.DrawText(font, text, 18))
8{
9 image.Position = 0;
10 using FileStream output = File.Create(outFile);
11 image.CopyTo(output);
12}Risultato dell’implementazione:

Il metodo DrawText consente di impostare la spaziatura della linea ed eseguire un avvolgimento di testo word-by-word automatico.
Nell’esempio di codice seguente, abbiamo specificato il tipo di spaziatura della linea linepacingType.pixels e impostarlo su 10 e abbiamo impostato la larghezza massima dell’immagine su 450.
Tutto il testo che non può essere visualizzato correttamente nell’intervallo dato (nel nostro caso è 450) verrà avvolto su una nuova linea.
L’esempio ripete «Hello world» in Verdana per superare la larghezza di 450 pixel e distribuire il testo su più righe. Il risultato viene salvato in WrappedText.png:
1// Render wrapped text with pixel line spacing
2
3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
5string text = "Hello world Hello world Hello world Hello world Hello world Hello world";
6string outFile = Path.Combine(OutputDir, "WrappedText.png");
7using (Stream image = RenderingUtils.DrawText(font, text, 22, RenderingUtils.LineSpacingType.Pixels, 10, 450))
8{
9 image.Position = 0;
10 using FileStream output = File.Create(outFile);
11 image.CopyTo(output);
12}Risultato dell’implementazione:

DrawText() restituisce un flusso PNG. Gli esempi ne riportano la posizione all’inizio, lo copiano in un file e rilasciano entrambi i flussi.
La famiglia di funzioni per il metodo DrawText() copre il testo standard o l’output di testo multiline. Ma, in alcuni casi, potrebbe essere necessario un output personalizzato del testo, ad esempio, quando si desidera comprimere, allungare, ruotare il testo ad angolo o qualcos’altro. In questo caso, è necessario personalizzare l’output in base alle tue esigenze.
Rendering di testo personalizzato
Gli esempi seguenti disegnano i contorni dei glifi con System.Drawing.Common in Windows, su un’area di 960 x 720 pixel a 300 DPI. Importare anche gli spazi dei nomi Aspose.Font.Glyphs, Aspose.Font.Rendering, Aspose.Font.RenderingPath, System.Drawing, System.Drawing.Drawing2D, System.Drawing.Imaging.
Per disegnare
glifi in Aspose.Font, si utilizza uno dei metodi RenderGlyph() della classe
GlyphOutlineRenderer. Tutti questi metodi sovraccaricati sono dichiarati nell’interfaccia
IGlyphRenderer.
Come parametro, dobbiamo passare a questi metodi un riferimento all’indice di carattere, glyphid o glyph e coordinate di output del glifo. Per trasferire l’ultimo parametro, viene utilizzata una matrice speciale rappresentata dall’oggetto Aspose.Font
TransformationMatrix.
Di seguito mostriamo come utilizzare gli oggetti del tipo
TransformationMatrix per passare le coordinate di output del glifo ai metodi della famiglia renderglyph().
Quindi, per disegnare un glifo, dobbiamo creare un oggetto del tipo Glyphoutlinerender. Ma un tale oggetto non può disegnare un glifo da solo. Richiede funzionalità esterne, che è descritta dall’interfaccia iglyphoutlinepainter. Per utilizzare l’oggetto glyphoutlinerender dovrebbe essere fornito con un’implementazione del iglyphoutlinePainter. Di seguito puoi vedere una semplice implementazione di questa interfaccia. Creiamo la classeGlyphoutLinePainterche richiede un oggetto di System.Drawing.Drawing2d.Graphicspath per gli obiettivi di disegno grafico.
Di seguito è riportata l’implementazione dell’interfaccia. Aggiungere gli overload di CustomDrawText() e il metodo FontWidthToImageWidth() mostrati più avanti alla classe GlyphOutlinePainter. Nel progetto di esempi, questi membri sono in una seconda dichiarazione parziale della stessa classe.
1// Implement a glyph outline painter
2
3public partial class GlyphOutlinePainter : IGlyphOutlinePainter
4{
5 private readonly GraphicsPath path;
6 private PointF currentPoint;
7
8 public GlyphOutlinePainter(GraphicsPath path)
9 {
10 this.path = path;
11 }
12
13 public void MoveTo(MoveTo moveTo)
14 {
15 path.CloseFigure();
16 currentPoint = new PointF((float)moveTo.X, (float)moveTo.Y);
17 }
18
19 public void LineTo(LineTo lineTo)
20 {
21 var next = new PointF((float)lineTo.X, (float)lineTo.Y);
22 path.AddLine(currentPoint, next);
23 currentPoint = next;
24 }
25
26 public void CurveTo(CurveTo curveTo)
27 {
28 var next = new PointF((float)curveTo.X3, (float)curveTo.Y3);
29 path.AddBezier(currentPoint, new PointF((float)curveTo.X1, (float)curveTo.Y1),
30 new PointF((float)curveTo.X2, (float)curveTo.Y2), next);
31 currentPoint = next;
32 }
33
34 public void ClosePath()
35 {
36 path.CloseFigure();
37 }
38}Dopo l’implementazione di
iglyphoutlinepainter, possiamo usare oggetti del suo tipo per rendere un singolo glifo passandoli alla famiglia
Glyphoutlinerender e chiamando i corrispondenti metodi sovraccarichi del renderglyph() Famiglia.
Per rendere una stringa di testo, dobbiamo ottenere il glyphid per ogni carattere e quindi, usando un oggetto di
glyphoutlinerender di tipo Chiama uno dei metodi della famiglia renderglyph(), passando le coordinate del Glyph corrispondente.
Diamo un’occhiata a un esempio di produzione di una riga di testo usando la libreria Aspose.Font. Sarà costruito nella forma del metodo CustomDrawText(), che accetta parametri - *CustomDrawText *(testo di stringa, font ifont, doppio fontsize, spazzole, brusco, cespuglio di textbrush, outfile della stringa).
Crea il metodo CustomDrawText() che disegna il testo specificato nell’oggetto
System.Drawing.bitmap e salva la bitmap risultante sul disco.
Ciò includerà i seguenti passaggi:
- Iterare tutti i simboli in una stringa di testo.
- Ottieni l’identificatore di glifi per ogni simbolo elaborato - GID.
- Creare un oggetto di * Tipo di GlyphoutLinePainter * richiesto dal sottosistema di rendering per disegnare il glifo corrente.
- Crea un oggetto del tipo aspose.font.renders.glyphoutlinerender e passa l’oggetto appena creato diGlyphoutlinePainterTipo nel costruttore per Glyphoutlinerender. Questo oggetto Glyphoutlinerender è destinato a rendere glifi specificati.
- Esegue il rendering del glifo attualmente elaborato utilizzando il metodo GlyphOutlineRenderer.RenderGlyph(). L’oggetto TransformationMatrix viene utilizzato per specificare le coordinate del glifo. Il glifo da visualizzare è specificato dal parametro gid.
Passaggi ausiliari per questa strategia
- In modalità orizzontale la linea di base sull’asse Y rimane costante; in modalità verticale si sposta per ogni glifo successivo.
- In modalità orizzontale la coordinata X aumenta della larghezza del glifo precedente e del kerning della coppia, moltiplicati per il coefficiente di spaziatura.
- Entrambe le coordinate ‘x’ e ‘y’ vengono passate nell’oggettoTransformationMatrixusato da glyphoutlinerender per disegnare glifi.
- L’avanzamento orizzontale viene calcolato per ogni glifo successivo; in modalità verticale la coordinata X rimane fissa.
- L’oggetto di tipo GlyphOutlineRenderer disegna glifi con l’aiuto di GlyphOutlinePainter non direttamente in Bitmap, ma nell’oggetto GraphicsPath passato al costruttore per GlyphOutlinePainter, quindi utilizziamo l’oggetto di tipo System.Drawing.Graphics per disegnare GraphicsPath in Bitmap.
- Il metodo FontWidthToImageWidth() converte la larghezza del glifo dalle unità del font in pixel.
Il primo overload crea e rilascia una bitmap. Il secondo accetta una bitmap di proprietà del codice chiamante e supporta spaziatura, coordinate, sovrapposizioni e output verticale. Aggiungere entrambi gli overload a GlyphOutlinePainter:
1// Render text with spacing, coordinates, overlays and vertical layout
2
3public static void CustomDrawText(string text, IFont font, double fontSize,
4 Brush backgroundBrush, Brush textBrush, string outFile)
5{
6 using var bitmap = new Bitmap(960, 720);
7 CustomDrawText(text, font, fontSize, backgroundBrush, textBrush, outFile, bitmap);
8}
9
10public static void CustomDrawText(string text, IFont font, double fontSize,
11 Brush backgroundBrush, Brush textBrush, string outFile, Bitmap bitmap,
12 double kerningCoefficient = 1, double coordinateX = 0, double coordinateY = 0, bool topDown = false)
13{
14 const double dpi = 300;
15 double scale = fontSize * dpi / 72;
16 bitmap.SetResolution((float)dpi, (float)dpi);
17 using (Graphics graphics = Graphics.FromImage(bitmap))
18 {
19 // A transparent background preserves an existing image for overlays.
20 graphics.FillRectangle(backgroundBrush, 0, 0, bitmap.Width, bitmap.Height);
21 graphics.SmoothingMode = SmoothingMode.HighQuality;
22 GlyphId? previousGid = null;
23 double glyphXCoordinate = coordinateX;
24 double glyphYCoordinate = coordinateY + scale;
25
26 foreach (char character in text)
27 {
28 GlyphId gid = font.Encoding.DecodeToGid(character);
29 if (gid == null) continue;
30 Glyph glyph = font.GlyphAccessor.GetGlyphById(gid);
31 if (glyph == null) continue;
32
33 if (previousGid != null)
34 {
35 if (topDown)
36 glyphYCoordinate += scale;
37 else
38 {
39 double advance = FontWidthToImageWidth(font.Metrics.GetGlyphWidth(previousGid),
40 glyph.SourceResolution, fontSize, dpi);
41 double kerning = font.Metrics.GetKerningValue(previousGid, gid)
42 / (double)glyph.SourceResolution * scale;
43 // Like the source example, the coefficient scales the whole advance.
44 glyphXCoordinate += (advance + kerning) * kerningCoefficient;
45 }
46 }
47
48 using var path = new GraphicsPath();
49 var painter = new GlyphOutlinePainter(path);
50 var renderer = new GlyphOutlineRenderer(painter);
51 var matrix = new TransformationMatrix(new double[]
52 {
53 scale, 0, 0, -scale, glyphXCoordinate, glyphYCoordinate
54 });
55 renderer.RenderGlyph(font, gid, matrix);
56 path.FillMode = FillMode.Winding;
57 graphics.FillPath(textBrush, path);
58 previousGid = gid;
59 }
60 }
61 // The caller owns the supplied bitmap and may reuse it for another overlay.
62 bitmap.Save(outFile, ImageFormat.Png);
63}Aggiungere alla stessa classe il metodo ausiliario che converte la larghezza dalle unità del font in pixel:
1// Convert font units to image pixels
2
3private static double FontWidthToImageWidth(double width, int fontSourceResolution,
4 double fontSize, double dpi = 300)
5{
6 return width / fontSourceResolution * fontSize * dpi / 72;
7}L’esempio visualizza «Hello world» in Verdana nero su bianco e in Lato blu su giallo. Salva Custom_Verdana.png e Custom_Lato.png:
1// Render two fonts with a custom glyph painter
2
3string verdanaPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
4string latoPath = Path.Combine(DataDir, "TTF", "LatoWeb-Regular.ttf");
5Font verdana = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(verdanaPath)));
6Font lato = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(latoPath)));
7string verdanaOutput = Path.Combine(OutputDir, "Custom_Verdana.png");
8string latoOutput = Path.Combine(OutputDir, "Custom_Lato.png");
9GlyphOutlinePainter.CustomDrawText("Hello world", verdana, 24, Brushes.White, Brushes.Black, verdanaOutput);
10GlyphOutlinePainter.CustomDrawText("Hello world", lato, 24, Brushes.Yellow, Brushes.Blue, latoOutput);Risultato dell’implementazione:
Verdana
Lato
Kerning
Il metodo ottiene il kerning delle coppie dal font. kerningCoefficient: 1.25 aumenta del 25% l’intero avanzamento orizzontale (larghezza del glifo precedente più kerning della coppia). L’esempio usa Verdana e salva IncreasedSpacing.png:
1// Increase the horizontal glyph advance
2
3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
5string outFile = Path.Combine(OutputDir, "IncreasedSpacing.png");
6using var bitmap = new Bitmap(960, 720);
7GlyphOutlinePainter.CustomDrawText("Hello world", font, 18, Brushes.White, Brushes.Black,
8 outFile, bitmap, kerningCoefficient: 1.25);Risultato dell’implementazione:
Verdana con coefficiente di spaziatura 1.25
Rendering Testo per coordinate
Posizionare il testo con coordinateX e coordinateY. Per ottenere la prima linea di base, il metodo aggiunge fontSize * 300 / 72 pixel a coordinateY. A 18 punti, coordinateX: 300 e coordinateY: 225 la collocano in (300, 300). Il risultato viene salvato in PositionedText.png:
1// Position text at explicit coordinates
2
3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
5string outFile = Path.Combine(OutputDir, "PositionedText.png");
6using var bitmap = new Bitmap(960, 720);
7// At 18 points and 300 DPI the 75-pixel baseline offset makes the baseline Y=300.
8GlyphOutlinePainter.CustomDrawText("Hello world", font, 18, Brushes.White, Brushes.Black,
9 outFile, bitmap, coordinateX: 300, coordinateY: 225);Risultato dell’implementazione:
Verdana, prima linea di base a X=300 e Y=300
Come aggiungere il testo a un’immagine
Per aggiungere testo a un’immagine esistente, passare una bitmap e un pennello di sfondo trasparente al metodo comune. Il pennello trasparente conserva i pixel esistenti.
L’overload di CustomDrawText() che accetta una bitmap supporta già questo scenario. Disegna sull’immagine fornita e la salva in PNG; la bitmap resta di proprietà del codice chiamante.
L’esempio crea OverlayBase.png in OutputDir, apre l’immagine e aggiunge un’ombra grigia e un’annotazione marrone. Salva separatamente Shadow.png e ShadowAnnotated.png; non occorre un’immagine di input esterna:
1// Add a shadow and annotation to an existing image
2
3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
5string inputImagePath = Path.Combine(OutputDir, "OverlayBase.png");
6GlyphOutlinePainter.CustomDrawText("Hello world", font, 17, Brushes.White, Brushes.Black, inputImagePath);
7using var bitmap = new Bitmap(inputImagePath);
8string shadowFile = Path.Combine(OutputDir, "Shadow.png");
9GlyphOutlinePainter.CustomDrawText("Hello world", font, 17, Brushes.Transparent, Brushes.Gray,
10 shadowFile, bitmap, coordinateX: -3);
11string annotatedFile = Path.Combine(OutputDir, "ShadowAnnotated.png");
12GlyphOutlinePainter.CustomDrawText("<= Shadow effect", font, 17, Brushes.Transparent, Brushes.Brown,
13 annotatedFile, bitmap, coordinateX: 400);Risultato dell’implementazione:
Verdana con ombra
Verdana con ombra e annotazione. L’annotazione è tagliata sul bordo destro dell’area larga 960 pixel.
Output del testo dall’alto verso il basso
Lo stesso overload supporta l’output verticale con topDown: true. Posiziona il primo glifo sulla linea di base iniziale e sposta ogni glifo successivo di fontSize * 300 / 72 pixel verso il basso.
L’esempio visualizza «Top down» in Verdana a X=400 e salva TopDown.png. Con coordinateY pari a zero e una dimensione di 18 punti, la prima linea di base si trova a Y=75 pixel:
1// Render text vertically from top to bottom
2
3string fontPath = Path.Combine(DataDir, "TTF", "verdana.ttf");
4Font font = Font.Open(new FontDefinition(FontType.TTF, "ttf", new FileSystemStreamSource(fontPath)));
5string outFile = Path.Combine(OutputDir, "TopDown.png");
6using var bitmap = new Bitmap(960, 720);
7GlyphOutlinePainter.CustomDrawText("Top down", font, 18, Brushes.White, Brushes.Black,
8 outFile, bitmap, coordinateX: 400, topDown: true);Risultato dell’implementazione:
Verdana, dall’alto verso il basso
Ulteriori informazioni
Il metodo usa 300 DPI. scale = fontSize * dpi / 72 converte la dimensione del font da punti a pixel. glyphXCoordinate e glyphYCoordinate definiscono la posizione della linea di base del glifo. In modalità orizzontale, l’avanzamento successivo comprende la larghezza del glifo precedente e il kerning della coppia fornito dal font; kerningCoefficient moltiplica la loro somma.