Renderização de texto usando a biblioteca de fontes | .NET
Visão geral
Se você alguma vez quis ter o recurso de renderizar um texto em uma imagem, o artigo aqui ensinará como fazê -lo com fontes de qualquer formato, suportado pela Biblioteca de fontes usando a solução API ASPOPE.FONT. A biblioteca permite converter o texto facilmente em imagens e adicionar texto a qualquer imagem.
Renderizando texto
Para inserir o texto em uma imagem, você precisará usar drawText Método da classe renderingutils. O código abaixo mostra como adicionar o texto “Hello World”, escrito na fonte Arial a uma imagem chamada “arial.png”.
1 var dataDir = @"C:\Temp\";
2 var fileName = dataDir + "arial.ttf"; //Font file name with full path
3 var outFile = dataDir + "arial.png";
4 var fontDefinition = new FontDefinition(FontType.TTF, new FontFileDefinition("ttf", new FileSystemStreamSource(fileName)));
5 var ttfFont = Font.Open(fontDefinition) as TtfFont;
6
7 var stream = Aspose.Font.Renderers.RenderingUtils.DrawText(ttfFont, "Hello world", 18);
8
9 var bitmap = new Bitmap(stream);
10 bitmap.Save(outFile);
O resultado da implementação:
O método drawText permite definir o espaçamento da linha e executar o embrulho de texto de palavra por palavra automática.
No exemplo do código abaixo, especificamos o tipo de espaçamento de linha linespacingType.pixels e o definimos como 10, e definimos a largura máxima da imagem como 450.
Todo o texto que não pode ser exibido corretamente no intervalo especificado (no nosso caso é 450) será envolvido em uma nova linha.
O código cortado mostra como renderizar texto “Hello World” em fonte Arial com a embalagem da próxima linha:
1 var dataDir = @"C:\Temp\";
2 var fileName = dataDir + "arial.ttf"; //Font file name with full path
3 var outFile = dataDir + "arial.png";
4 var fontDefinition = new FontDefinition(FontType.TTF, new FontFileDefinition("ttf", new FileSystemStreamSource(fileName)));
5 var ttfFont = Font.Open(fontDefinition) as TtfFont;
6 var lineSpacingType = LineSpacingType.Pixels;
7
8 var stream = DrawText(ttfFont, "Hello world", 22, lineSpacingType, 10, 450);
9
10 var bitmap = new Bitmap(stream);
11
12 bitmap.Save(outFile);
O resultado da implementação:
Neste exemplo, você viu como você pode transformar o texto em uma imagem com apenas uma linha de código.
A família de funções para o método drawText()
abrange texto padrão ou saída de texto multilina. Mas, em alguns casos, você pode precisar de uma saída personalizada do texto, por exemplo, quando deseja comprimir, esticar, girar o texto em um ângulo ou outra coisa. Nesse caso, você precisa personalizar a saída de acordo com suas necessidades.
Renderização de texto personalizada
O próximo exemplo mostra uma maneira mais avançada (personalizada) de converter texto em uma imagem.
Para desenhar
glifos dentro de Aspose.font, usa um dos métodos renderglyph()
da classe
glyphoutlineRenderer. Todos esses métodos sobrecarregados são declarados na interface
iglyphRienderer.
Como parâmetro, devemos passar para esses métodos uma referência à fonte, glifídeo ou índice de glifos e as coordenadas de saída do glifo. Para transferir o último parâmetro, uma matriz especial representada pelo objeto Aspose.font
transformationMatrix é usada.
Abaixo, mostramos como usar objetos da
transformationMatrix tipo para passar as coordenadas de saída do glifo para os métodos da família renderglyph()
.
Portanto, para desenhar um glifo, precisamos criar um objeto do tipo glyphoutlineRender. Mas esse objeto não pode desenhar um glifo por conta própria. Requer funcionalidade externa, descrita pela interface iglyphoutLinePainter. Para usar o objeto glyphoutlineRenderer, deve ser fornecido com uma implementação do iglyphoutLinePainter. Abaixo, você pode ver uma implementação simples desta interface. Vamos criar a classeglyphoutlinepainterque requer um objeto de System.drawing.drawing2d.graphicsPath Tipo para objetivos de desenho gráfico.
A implementação é ilustrada abaixo.
1 Classe pública GlyphoutlinePainter: iglyphoutlinePainter
2 {
3 Private GraphicsPath _Path;
4 private Pointf _currentPoint;
5
6 public GlyphOutlinePainter(GraphicsPath path)
7 {
8 _path = path;
9 }
10
11 public void MoveTo(MoveTo moveTo)
12 {
13 _path.CloseFigure();
14 _currentPoint.X = (float)moveTo.X;
15 _currentPoint.Y = (float)moveTo.Y;
16 }
17
18 public void LineTo(LineTo lineTo)
19 {
20 float x = (float)lineTo.X;
21 float y = (float)lineTo.Y;
22 _path.AddLine(_currentPoint.X, _currentPoint.Y, x, y);
23 _currentPoint.X = x;
24 _currentPoint.Y = y;
25 }
26
27 public void CurveTo(CurveTo curveTo)
28 {
29 float x3 = (float)curveTo.X3;
30 float y3 = (float)curveTo.Y3;
31
32 _path.AddBezier(
33 _currentPoint.X,
34 _currentPoint.Y,
35 (float)curveTo.X1,
36 (float)curveTo.Y1,
37 (float)curveTo.X2,
38 (float)curveTo.Y2,
39 x3,
40 y3);
41
42 _currentPoint.X = x3;
43 _currentPoint.Y = y3;
44 }
45
46 public void ClosePath()
47 {
48 _path.CloseFigure();
49 }
50 }
Após a implementação
iglyphoutLinePainter, podemos usar objetos de seu tipo para renderizar um glifo individual, passando -os para o
glyphoutlineRenderer e chamando os métodos sobrecarregados correspondentes da família renderglyph()
.
Para renderizar uma sequência de texto, necessitamos de obter o glyphId para cada caractere e depois, utilizando um objeto do tipo
GlyphOutlineRenderer, chamar um dos métodos da família RenderGlyph()
, passando as coordenadas do glifo correspondente.
Vamos dar uma olhada em um exemplo de saída de uma linha de texto usando a biblioteca Aspose.font. Ele será construído na forma do método CustomDrawText()
, que aceita parâmetros - *CustomDrawText *(texto da string, font ifent, fontsize duplo, escova de fundo, pincel textbrush, string outfile).
Crie o método CustomDrawText()
que atrai o texto especificado no objeto
System.Drawing.bitmap e salva o bitmap resultante no disco.
Isso incluirá as seguintes etapas:
- Itera todos os símbolos em uma string de texto.
- Obtenha identificador de glifos para cada símbolo processado - GID.
- Crie um objeto do tipo glyphoutLinePainter, necessário pelo subsistema de renderização para desenhar o glifo atual.
- Crie um objeto do tipo aspose.font.renderers.glyphoutlineRenderer e passe o objeto recém -criado de glyphoutlinePainter digite no construtor para glyphoutlineRenderer. Este objeto GLYPHOUTLINERENDERER destina -se a renderizar glifos especificados.
- Atualmente, renderizou o glifo do processo usando o método glyphoutlineRender.renderglyph(). Aspose.fonts.matrix O objeto é usado para especificar coordenadas glifos. O glifo para renderizar é especificado pelo parâmetro gid.
Etapas auxiliares para esta estratégia
- As coordenadas de glifos para o eixo ‘y’ são constantes para este trecho de código.
- As coordenadas de glifos para o eixo ‘x’ são calculadas para cada glifo processado.
- As coordenadas ‘x’ e ‘y’ são passadas paraaspose.fonts.matrixobjeto usado por glyphoutlineRenderer para desenhar glifos.
- A distância entre os glifos justos e previamente processados é calculada em todas as etapas de iteração. Afeta todas as coordenadas do glifo ‘x’.
- O objeto do tipo GlyphOutlineRenderer desenha glifos com a ajuda de GlyphOutlinePainter não diretamente no Bitmap, mas no objeto GraphicsPath passado para o construtor de GlyphOutlinePainter, pelo que utilizamos o objeto do tipo System.Drawing.Graphics para desenhar GraphicsPath em Bitmap.
- O método fontWidthToImageWith() calcula a largura do glifo para o sistema de coordenadas de bitmap.
A implementação do método CustomDrawText() é mostrada abaixo.
1 public static void CustomDrawText (texto da string, fonte ifont, Fontsize duplo, pincel BackgroundBrush, pincel TextBrush, String Outfile)
2 {
3 // Obtenha identificadores de glifos para cada símbolo na linha de texto
4 Glifídeo [] gids = novo glifídeo [text.length];
5
6 for (int i = 0; i < text.Length; i++)
7 gids[i] = font.Encoding.DecodeToGid(text[i]);
8
9 // Set common drawing settings
10 double dpi = 300;
11 double resolutionCorrection = dpi / 72; // 72 is font's internal dpi
12
13 // Prepare output bitmap
14 Bitmap outBitmap = new Bitmap(960, 720);
15
16
17 outBitmap.SetResolution((float)dpi, (float)dpi);
18
19 Graphics outGraphics = Graphics.FromImage(outBitmap);
20 outGraphics.FillRectangle(backgroundBrush, 0, 0, outBitmap.Width, outBitmap.Height);
21 outGraphics.SmoothingMode = SmoothingMode.HighQuality;
22
23 //Declare coordinate variables and a previous gid
24 GlyphId previousGid = null;
25 double glyphXCoordinate = 0;
26 double glyphYCoordinate = fontSize * resolutionCorrection;
27
28 // The loop paints every glyph in gids
29 foreach (GlyphId gid in gids)
30 {
31 // if the font contains the gid
32 if (gid != null)
33 {
34 Glyph glyph = font.GlyphAccessor.GetGlyphById(gid);
35 if (glyph == null)
36 continue;
37
38 // The path that accepts drawing instructions
39 GraphicsPath path = new GraphicsPath();
40
41 // Create IGlyphOutlinePainter implementation
42 GlyphOutlinePainter outlinePainter = new GlyphOutlinePainter(path);
43
44 // Create the renderer
45 Aspose.Font.Renderers.IGlyphRenderer renderer = new Aspose.Font.Renderers.GlyphOutlineRenderer(outlinePainter);
46
47 // Get common glyph properties
48 double kerning = 0;
49
50 // Get kerning value
51
52 if (previousGid != null)
53 {
54 kerning = (font.Metrics.GetKerningValue(previousGid, gid) / glyph.SourceResolution) * fontSize * resolutionCorrection;
55 kerning += FontWidthToImageWith(font.Metrics.GetGlyphWidth(previousGid), glyph.SourceResolution, fontSize);
56 }
57
58 // Glyph positioning - increase glyph X coordinate according to kerning distance
59 glyphXCoordinate += kerning;
60
61 // Glyph placement matrix
62 TransformationMatrix glyphMatrix = new TransformationMatrix(
63 new double[]
64 { fontSize * resolutionCorrection,
65 0,
66 0,
67 // negative because of the bitmap coordinate system begins from the top
68 - fontSize*resolutionCorrection,
69 glyphXCoordinate,
70 glyphYCoordinate
71 });
72
73 // Render the current glyph
74 renderer.RenderGlyph(font, gid, glyphMatrix);
75
76 // Fill the path
77 path.FillMode = FillMode.Winding;
78
79 outGraphics.FillPath(textBrush, path);
80 }
81
82 //Set current gid as previous to get correct kerning for next glyph
83 previousGid = gid;
84 }
85
86 //Save the results
87 outBitmap.Save(outFile);
88 }
Método de utilidade para converter a largura da fonte em largura da imagem
1 estático duplo fontWidthToImagewith (largura dupla, int fontsourcerceresuluição, fontsize duplo, dpi duplo = 300)
2 {
3 Duplo ResolutionCorrection = DPI / 72; // 72 é o DPI interno da fonte
4
5 return (width / fontSourceResulution) * fontSize * resolutionCorrection;
6 }
O próximo snippet de código mostra como renderizar o texto “Hello World” usando o método CustomDrawText()
.
1 var dataDir = @"C:\Temp\";
2 var fileName1 = dataDir + "arial.ttf"; //Font file name with full path
3 var fileName2 = dataDir + "calibrii.ttf"; //Font file name with full path
4
5 var fontDefinition1 = new FontDefinition(FontType.TTF, new FontFileDefinition("ttf", new FileSystemStreamSource(fileName1)));
6 var ttfFont1 = Font.Open(fontDefinition1) as TtfFont;
7
8 var fontDefinition2 = new FontDefinition(FontType.TTF, new FontFileDefinition("ttf", new FileSystemStreamSource(fileName2)));
9 var ttfFont2 = Font.Open(fontDefinition2) as TtfFont;
10
11 GlyphOutlinePainter.CustomDrawText("Hello world", ttfFont1, 24, Brushes.White, Brushes.Black, dataDir + "Hello_Arial_out.png");
12 GlyphOutlinePainter.CustomDrawText("Hello world", ttfFont2, 24, Brushes.Yellow, Brushes.Blue, dataDir + "Hello_Calibri_out.png");
Implementando o código, obteremos o seguinte resultado:
O resultado da implementação:
Arial
Calibri
Kerning
Usando o valor da variável * Kerning *, você pode alterar a distância entre os glifos. Agora vamos reescrever o código na próxima maneira:
1
2 // Posicionamento do glifo - Aumente o glifo x coordenada de acordo com a distância de kerning
3 kerning *= 1,25;
4 glyphxcoordinate += kerning;
O próximo resultado será obtido:
O resultado da implementação:
Arial kernint
Calibri kerning
Renderizar texto por coordenadas
As variáveis glyphxcoordinate e glifycoordinate são responsáveis pelas coordenadas da saída de texto. Alterando o código da seguinte forma:
1 // declarar variáveis de coordenadas e o GID anterior
2 Glifídeo anteriorgid = nulo;
3 dupla glifxcoordinada = 300;
4 glifycoordinada dupla = 300;
O próximo resultado será obtido:
O resultado da implementação:
Arial x=300 y=300
Calibri x=300 y=300
Como adicionar o texto a uma imagem
Você também pode exibir o texto em uma imagem existente. Para isso, reescreveremos o código da seguinte forma:
1
2 public static void CustomDrawText (texto da string, fonte ifont, Double FontSize, Bornchbrush Background, escova Textbrush, String Outfile, Bitmap Bitmap, Kerningcoefficiente duplo = 1, coordenado duplo = 0, coordenada dupla = 0)
3 {
4 // Obtenha identificadores de glifos para cada símbolo na linha de texto
5 Glifídeo [] gids = novo glifídeo [text.length];
6
7 for (int i = 0; i < text.Length; i++)
8 gids[i] = font.Encoding.DecodeToGid(text[i]);
9
10 // Set common drawing settings
11 double dpi = 300;
12 double resolutionCorrection = dpi / 72; // 72 is font's internal dpi
13
14 // Prepare the output bitmap
15 Bitmap outBitmap = bitmap;
16
17 outBitmap.SetResolution((float)dpi, (float)dpi);
18
19 Graphics outGraphics = Graphics.FromImage(outBitmap);
20 outGraphics.FillRectangle(backgroundBrush, 0, 0, outBitmap.Width, outBitmap.Height);
21 outGraphics.SmoothingMode = SmoothingMode.HighQuality;
22
23 //Declare coordinate variables and the previous gid
24 GlyphId previousGid = null;
25 double glyphXCoordinate = coordinateX;
26 double glyphYCoordinate = coordinateY;
27
28 glyphYCoordinate += fontSize * resolutionCorrection;
29
30 //The loop paints every glyph in gids
31 foreach (GlyphId gid in gids)
32 {
33 // if the font contains the gid
34 if (gid != null)
35 {
36 Glyph glyph = font.GlyphAccessor.GetGlyphById(gid);
37 if (glyph == null)
38 continue;
39
40 // The path that accepts drawing instructions
41 GraphicsPath path = new GraphicsPath();
42
43 // Create the IGlyphOutlinePainter implementation
44 GlyphOutlinePainter outlinePainter = new GlyphOutlinePainter(path);
45
46 // Create the renderer
47 Aspose.Font.Renderers.IGlyphRenderer renderer = new Aspose.Font.Renderers.GlyphOutlineRenderer(outlinePainter);
48
49 // Get common glyph properties
50 double kerning = 0;
51
52 // Get the kerning value
53
54 if (previousGid != null)
55 {
56 kerning = (font.Metrics.GetKerningValue(previousGid, gid) / glyph.SourceResolution) * fontSize * resolutionCorrection;
57 kerning += FontWidthToImageWith(font.Metrics.GetGlyphWidth(previousGid), glyph.SourceResolution, fontSize);
58 }
59
60 // Glyph positioning - increase the glyph X coordinate according to the kerning distance
61 glyphXCoordinate += kerning * kerningCoefficient;
62
63 // Glyph placement matrix
64 TransformationMatrix glyphMatrix = new TransformationMatrix(
65 new double[]
66 { fontSize * resolutionCorrection,
67 0,
68 0,
69 // negative because of the bitmap coordinate system begins from the top
70 - fontSize*resolutionCorrection,
71 glyphXCoordinate,
72 glyphYCoordinate
73 });
74
75 // Render the current glyph
76 renderer.RenderGlyph(font, gid, glyphMatrix);
77
78 // Fill the path
79 path.FillMode = FillMode.Winding;
80
81 outGraphics.FillPath(textBrush, path);
82 }
83
84 //Set the current gid as previous to get the correct kerning for the next glyph
85 previousGid = gid;
86 }
87
88 //Save the results
89 outBitmap.Save(outFile);
90 }
Vamos modificar a maneira como o método é chamado:
1 var dataDir = @"C:\Temp\";
2 var fileName1 = dataDir + "arial.ttf"; //Font file name with full path
3
4 var fontDefinition1 = new FontDefinition(FontType.TTF, new FontFileDefinition("ttf", new FileSystemStreamSource(fileName1)));
5 var ttfFont1 = Font.Open(fontDefinition1) as TtfFont;
6
7 var bitmap = new Bitmap(960, 720);
8
9 GlyphOutlinePainter.CustomDrawText("Hello world", ttfFont1, 17, Brushes.White, Brushes.Black, dataDir + "Hello_Arial_out.png", bitmap);
10
11 var inputImagePath = dataDir + "Hello_Arial_out.png";
12 var bitmapAddText = new Bitmap(inputImagePath);
13
14 GlyphOutlinePainter.CustomDrawText("Hello world", ttfFont1, 17, Brushes.Transparent, Brushes.Gray, dataDir + "Hello_Arial_Shadow_out.png", bitmapAddText, 1, -3);
15
16 GlyphOutlinePainter.CustomDrawText("<= Shadow effect", ttfFont1, 17, Brushes.Transparent, Brushes.Brown, dataDir + "Hello_Arial_Shadow_out.png", bitmapAddText, 1, 400);
O resultado da implementação:
Arial shadow effect
Emitindo o texto de cima para baixo
Para exibir o texto de cima para baixo, vamos fazer as seguintes alterações no método CustomDrawText()
.
1 public static void CustomDrawText (texto da string, fonte ifont, fontsize duplo, pincel BackgroundBrush, pincel Textbrush, String Outfile, bitmap bitmap, duplo kerningcoeffect = 1, coordeninado duplo = 0, coordenada dupla = 0, bool towdown = false)
2 {
3 // Obtenha identificadores de glifos para cada símbolo na linha de texto
4 Glifídeo [] gids = novo glifídeo [text.length];
5
6 for (int i = 0; i < text.Length; i++)
7 gids[i] = font.Encoding.DecodeToGid(text[i]);
8
9 // Set common drawing settings
10 double dpi = 300;
11 double resolutionCorrection = dpi / 72; // 72 is font's internal dpi
12
13 // Prepare the output bitmap
14 Bitmap outBitmap = bitmap;
15
16 outBitmap.SetResolution((float)dpi, (float)dpi);
17
18 Graphics outGraphics = Graphics.FromImage(outBitmap);
19 outGraphics.FillRectangle(backgroundBrush, 0, 0, outBitmap.Width, outBitmap.Height);
20 outGraphics.SmoothingMode = SmoothingMode.HighQuality;
21
22 //Declare coordinate variables and the previous gid
23 GlyphId previousGid = null;
24 double glyphXCoordinate = coordinateX;
25 double glyphYCoordinate = coordinateY;
26
27 glyphYCoordinate += fontSize * resolutionCorrection;
28
29 //The loop paints every glyph in gids
30 foreach (GlyphId gid in gids)
31 {
32 // if the font contains the gid
33 if (gid != null)
34 {
35 Glyph glyph = font.GlyphAccessor.GetGlyphById(gid);
36 if (glyph == null)
37 continue;
38
39 // The path that accepts drawing instructions
40 GraphicsPath path = new GraphicsPath();
41
42 // Create IGlyphOutlinePainter implementation
43 GlyphOutlinePainter outlinePainter = new GlyphOutlinePainter(path);
44
45 // Create the renderer
46 Aspose.Font.Renderers.IGlyphRenderer renderer = new Aspose.Font.Renderers.GlyphOutlineRenderer(outlinePainter);
47
48 // Get common glyph properties
49 double kerning = 0;
50
51 // Get kerning value
52 if (previousGid != null && !topDown)
53 {
54 kerning = (font.Metrics.GetKerningValue(previousGid, gid) / glyph.SourceResolution) * fontSize * resolutionCorrection;
55 kerning += FontWidthToImageWith(font.Metrics.GetGlyphWidth(previousGid), glyph.SourceResolution, fontSize);
56 }
57
58 if (topDown)
59 {
60 glyphYCoordinate += fontSize * resolutionCorrection;
61 }
62 else
63 {
64 // Glyph positioning - increase the glyph X coordinate according to kerning distance
65 glyphXCoordinate += kerning * kerningCoefficient;
66 }
67
68 // Glyph placement matrix
69 TransformationMatrix glyphMatrix = new TransformationMatrix(
70 new double[]
71 { fontSize * resolutionCorrection,
72 0,
73 0,
74 // negative because the bitmap coordinate system begins from the top
75 - fontSize*resolutionCorrection,
76 glyphXCoordinate,
77 glyphYCoordinate
78 });
79
80 // Render the current glyph
81 renderer.RenderGlyph(font, gid, glyphMatrix);
82
83 // Fill the path
84 path.FillMode = FillMode.Winding;
85
86 outGraphics.FillPath(textBrush, path);
87 }
88
89 //Set the current gid as previous to get correct kerning for the next glyph
90 previousGid = gid;
91 }
92
93 //Save the results
94 outBitmap.Save(outFile);
95 }
O código da chamada do método terá a próxima aparência:
1 var dataDir = @"C:\Temp\";
2 var fileName1 = dataDir + "arial.ttf"; //Font file name with full path
3 var fontDefinition1 = new FontDefinition(FontType.TTF, new FontFileDefinition("ttf", new FileSystemStreamSource(fileName1)));
4 var ttfFont1 = Font.Open(fontDefinition1) as TtfFont;
5 var bitmap = new Bitmap(960, 720);
6
7 GlyphOutlinePainter.CustomDrawText("Top down", ttfFont1, 18, Brushes.White, Brushes.Black, dataDir + "Hello_Arial_TopDown.png", bitmap, 1, 400, 00, true);
O resultado da implementação:
Arial top to down
Informações adicionais
1 DPI duplo; // pontos por polegada
2 Duplo ResolutionCorrection = DPI / 72; // 72 é o DPI interno da fonte
3 // coordenam variáveis
4 glifxcoordinado duplo; // x
5 glifycoordinada dupla; // y;
6 // Kerning - espaçamento horizontal entre duas letras
7 duplo kerning = 0;