Delphi graphics32 文字图层
Delphi graphics32 text layer
我正在尝试为我的图像编辑应用程序创建一个文本工具,所以我在主窗体上有一个按钮显示 "Text tool"。当我单击它时,会显示一个新表单(模态),允许我 select 一种字体并在 RichEdit 中输入文本。
我的想法是让用户在 RichEdit 中格式化他的文本,当他满意时,他应该单击模态按钮,文本(格式化的)将插入到我的图像中的新层中。
另外我的想法是将文本视为文本行并在新的Bitmap32中单独渲染它们,然后将获得的位图分配给新的Layer。
为此我使用了这个函数
function GetTextWidth(const Text: string; const Font: TFont): Integer;
var
Canvas: TCanvas;
begin
Canvas := TCanvas.Create;
try
Canvas.Handle := GetDC(0);
try
Canvas.Font.Assign(Font);
Result := Canvas.TextWidth(Text);
finally
ReleaseDC(0, Canvas.Handle);
end;
finally
Canvas.Free;
end;
end;
并解析 richedit 的行并像这样获取每一行的文本宽度:
for q := 0 to TextEditor.RichEdit1.Lines.Count-1 do
begin
latime:=GetTextWidth(TextEditor.RichEdit1.Lines[q], TextEditor.RichEdit1.Font);
Memo1.Lines.Add('Text row '+IntToStr(q)+' width='+IntToStr(latime));
end;
因此我将轻松获得最大宽度线 (maxwidth),我打算将其用于生成 Bitmap32。
因此,对于我的 Bitmap32,我使用了以下代码(不幸的是,它没有显示任何内容)
// generating the Bitmap32 to place text on it
tmp := TBitmap32.Create;
tmp.SetSize(maxwidth, textLineHeight*TextLineCount);
for q := 0 to textLineCount-1 do
begin
tmp.RenderText(maxwidth,textLineHeight,TextEditor.RichEdit1.Lines[q],1,myFont.Color);
Memo1.Lines.Add('rendering line of text:'+TextEditor.RichEdit1.Lines[q]);
end;
// Generating the text layer
B := TBitmapLayer.Create(ImgView.Layers);
// Assigning the 'written' bitmap to the new layer
B.Bitmap.Assign(tmp);
B.Bitmap.DrawMode:=dmBlend;
// Positioning
with ImgView.GetViewportRect do
P := ImgView.ControlToBitmap(GR32.Point((Right + Left) div 2, (Top + Bottom) div 2));
// Sizing the layer
B.Location:=GR32.FloatRect(P.X - maxwidth, P.Y - textLineHeight, P.X + maxwidth, P.Y + textLineHeight);
// displaying the new text layer
imgView.Invalidate;
所以我没有得到任何错误,但是新图层没有显示...就像什么都没发生一样。
我尝试使用固定的宽度和高度值(我都使用了 200 或两者),但我的 ImageView 上仍然没有显示任何内容,所以我认为它一定是位置有问题?
请帮我解决这个问题。
非常感谢
首先,RenderText 函数不支持任何高级格式(以 RichEdit 提供的扩展功能的形式)。它只是将具有位图字体 属性 属性的字符串(按原样)输出到某个位置(在您的情况下为定位 maxwidth / textLineHeight)。
为了解决这个问题,我将从一个更简单的代码开始。类似于:
B := TBitmapLayer.Create(ImgView.Layers);
B.Location := FloatRect(0, 0, 100, 100);
B.Bitmap.SetSize(100, 100);
B.Bitmap.RenderText(0, 0, 'Test', 1, clBlack32);
B.Bitmap.DrawMode := dmBlend;
注意这里使用clBlack32作为颜色而不是clBlack因为后者不包含关于透明度的信息。可能是您使用的颜色(在 myFont.Color 中)是 TColor 类型(而不是 TColor32 类型)。如果它是 TColor,例如 clBlack,它的 alpha 值为 0,等于完全透明。
此代码应将文本 'Test' 绘制到左上角位置。如果您没有看到文字,您可以添加类似
的内容
B.Bitmap.Clear(clRed32);
在 SetSize 调用之后。这样图层的位图背景颜色将设置为红色。因此,您应该能够更轻松地发现图层的边界。
文本显示在屏幕上后,您可以通过显示多行文本、调整 x / y 位置等进一步移动,直到您的代码看起来像上面发布的代码。
一些备注:
通过将图层调整为与位图尺寸不同的尺寸,文本将被拉伸。这可能看起来很奇怪,并且文本可能变得不可读。最后,您可能更愿意在调整图层大小后刷新位图上的文本。
如果 AALevel(过采样因子)较高,函数 RenderText(...) 会产生更平滑的输出。但是,该值越高,函数调用也会越慢。比例是更多的或二次的,这意味着如果你将值加倍,调用将至少慢 4 倍。实际上,一旦超出处理器的缓存,它甚至会更慢。在这种情况下,您将面临性能大幅下降。
此外,文本宽度将变得准确。在最坏的情况下,它可以关闭 (2^AALevel * Length(string)) 个像素!
最终使用 v2.0 中新矢量引擎的文本渲染功能可能会更好。虽然这些步骤不像相当简单的 RenderText(...) 调用那样直接,但输出看起来更赏心悦目,并且与高 AALevel 输出相比要快得多。还可以以非常准确的方式确定 TextWidth。
我正在尝试为我的图像编辑应用程序创建一个文本工具,所以我在主窗体上有一个按钮显示 "Text tool"。当我单击它时,会显示一个新表单(模态),允许我 select 一种字体并在 RichEdit 中输入文本。
我的想法是让用户在 RichEdit 中格式化他的文本,当他满意时,他应该单击模态按钮,文本(格式化的)将插入到我的图像中的新层中。 另外我的想法是将文本视为文本行并在新的Bitmap32中单独渲染它们,然后将获得的位图分配给新的Layer。
为此我使用了这个函数
function GetTextWidth(const Text: string; const Font: TFont): Integer;
var
Canvas: TCanvas;
begin
Canvas := TCanvas.Create;
try
Canvas.Handle := GetDC(0);
try
Canvas.Font.Assign(Font);
Result := Canvas.TextWidth(Text);
finally
ReleaseDC(0, Canvas.Handle);
end;
finally
Canvas.Free;
end;
end;
并解析 richedit 的行并像这样获取每一行的文本宽度:
for q := 0 to TextEditor.RichEdit1.Lines.Count-1 do
begin
latime:=GetTextWidth(TextEditor.RichEdit1.Lines[q], TextEditor.RichEdit1.Font);
Memo1.Lines.Add('Text row '+IntToStr(q)+' width='+IntToStr(latime));
end;
因此我将轻松获得最大宽度线 (maxwidth),我打算将其用于生成 Bitmap32。
因此,对于我的 Bitmap32,我使用了以下代码(不幸的是,它没有显示任何内容)
// generating the Bitmap32 to place text on it
tmp := TBitmap32.Create;
tmp.SetSize(maxwidth, textLineHeight*TextLineCount);
for q := 0 to textLineCount-1 do
begin
tmp.RenderText(maxwidth,textLineHeight,TextEditor.RichEdit1.Lines[q],1,myFont.Color);
Memo1.Lines.Add('rendering line of text:'+TextEditor.RichEdit1.Lines[q]);
end;
// Generating the text layer
B := TBitmapLayer.Create(ImgView.Layers);
// Assigning the 'written' bitmap to the new layer
B.Bitmap.Assign(tmp);
B.Bitmap.DrawMode:=dmBlend;
// Positioning
with ImgView.GetViewportRect do
P := ImgView.ControlToBitmap(GR32.Point((Right + Left) div 2, (Top + Bottom) div 2));
// Sizing the layer
B.Location:=GR32.FloatRect(P.X - maxwidth, P.Y - textLineHeight, P.X + maxwidth, P.Y + textLineHeight);
// displaying the new text layer
imgView.Invalidate;
所以我没有得到任何错误,但是新图层没有显示...就像什么都没发生一样。
我尝试使用固定的宽度和高度值(我都使用了 200 或两者),但我的 ImageView 上仍然没有显示任何内容,所以我认为它一定是位置有问题?
请帮我解决这个问题。
非常感谢
首先,RenderText 函数不支持任何高级格式(以 RichEdit 提供的扩展功能的形式)。它只是将具有位图字体 属性 属性的字符串(按原样)输出到某个位置(在您的情况下为定位 maxwidth / textLineHeight)。
为了解决这个问题,我将从一个更简单的代码开始。类似于:
B := TBitmapLayer.Create(ImgView.Layers);
B.Location := FloatRect(0, 0, 100, 100);
B.Bitmap.SetSize(100, 100);
B.Bitmap.RenderText(0, 0, 'Test', 1, clBlack32);
B.Bitmap.DrawMode := dmBlend;
注意这里使用clBlack32作为颜色而不是clBlack因为后者不包含关于透明度的信息。可能是您使用的颜色(在 myFont.Color 中)是 TColor 类型(而不是 TColor32 类型)。如果它是 TColor,例如 clBlack,它的 alpha 值为 0,等于完全透明。
此代码应将文本 'Test' 绘制到左上角位置。如果您没有看到文字,您可以添加类似
的内容B.Bitmap.Clear(clRed32);
在 SetSize 调用之后。这样图层的位图背景颜色将设置为红色。因此,您应该能够更轻松地发现图层的边界。
文本显示在屏幕上后,您可以通过显示多行文本、调整 x / y 位置等进一步移动,直到您的代码看起来像上面发布的代码。
一些备注:
通过将图层调整为与位图尺寸不同的尺寸,文本将被拉伸。这可能看起来很奇怪,并且文本可能变得不可读。最后,您可能更愿意在调整图层大小后刷新位图上的文本。
如果 AALevel(过采样因子)较高,函数 RenderText(...) 会产生更平滑的输出。但是,该值越高,函数调用也会越慢。比例是更多的或二次的,这意味着如果你将值加倍,调用将至少慢 4 倍。实际上,一旦超出处理器的缓存,它甚至会更慢。在这种情况下,您将面临性能大幅下降。
此外,文本宽度将变得准确。在最坏的情况下,它可以关闭 (2^AALevel * Length(string)) 个像素!
最终使用 v2.0 中新矢量引擎的文本渲染功能可能会更好。虽然这些步骤不像相当简单的 RenderText(...) 调用那样直接,但输出看起来更赏心悦目,并且与高 AALevel 输出相比要快得多。还可以以非常准确的方式确定 TextWidth。