【问题标题】:Delphi graphics32 text layerDelphi graphics32文字图层
【发布时间】:2015-03-18 04:04:41
【问题描述】:

我正在尝试为我的图像编辑应用程序创建一个 textTool,所以我在主窗体上有一个按钮,上面写着“文本工具”。当我单击它时,会显示一个新表单(模式),允许我选择一种字体并在 RichEdit 中输入文本。

我的想法是让用户在 RichEdit 中格式化他的文本,当他满意时,他应该点击模态按钮,文本(格式化)将插入到我图像的新图层中。 另外我的想法是将文本视为文本行,并在新的 Bitmap32 中分别渲染它们,然后将获得的位图分配给新的图层。

为此我使用此功能

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的行并像这样获取每一行的textWidth:

    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 bor),但我的 ImageView 上仍然没有显示任何内容,所以我认为可能是位置有问题?

请帮助我解决这个问题。

非常感谢

【问题讨论】:

  • 只是猜测蓝色而不涉及任何细节:您是否在调试器中检查了该位置以确保它没有放置在屏幕外?使用 'p.x - maxwidth' 它可以放置在 ImgView 的边界之外。
  • 我尝试使用问题中提到的固定位置(在底部),但仍然没有任何显示。

标签: delphi delphi-xe graphics32


【解决方案1】:

首先,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 类型)。如果是 clBlack 等 TColor,则其 alpha 值为 0,即完全透明。

此代码应将文本“Test”绘制到左上角。如果您没有看到文字,您可以添加类似

B.Bitmap.Clear(clRed32);

在 SetSize 调用之后。这样,图层的位图背景颜色将设置为红色。因此,您应该能够更轻松地发现图层的边界。

一旦文本出现在屏幕上,您可以通过显示多行文本、调整 x/y 位置等来进一步移动,直到您的代码看起来像您在上面发布的代码。

一些备注:

通过将图层调整为与位图尺寸不同的尺寸,文本将被拉伸。这可能看起来很奇怪,并且文本可能会变得不可读。最终,您可能更希望在调整图层大小后刷新位图上的文本。

如果 AALevel(过采样因子)更高,函数 RenderText(...) 会产生更平滑的输出。但是,值越高,函数调用也会越慢。比例更多或二次,这意味着如果您将值加倍,调用将至少慢 4 倍。实际上,一旦超出处理器的缓存,它甚至会更慢。在这种情况下,您将面临性能大幅下降。

此外,文本宽度会变得准确。在最坏的情况下,它可能会偏离 (2^AALevel * Length(string)) 个像素!

最终使用 v2.0 中新矢量引擎的文本渲染功能可能会更好。虽然这些步骤不像使用相当简单的 RenderText(...) 调用那么简单,但输出看起来更令人赏心悦目,并且与高 AALevel 输出相比要快得多。 TextWidth 也可以非常准确地确定。

【讨论】:

  • 您能否更具体地了解向量方法?我找不到任何使用带有 Graphics32 和文本的矢量的示例,或带有其他任何东西的矢量......或者这些示例可能不是专门用于矢量的,而是包含矢量方法?请向我展示一些有关如何创建带有包含格式化(字体、大小、颜色、透明度)文本的向量的图层的代码,我以后可以删除或移动(图层)。
  • 它的使用方式与 RenderText 方法类似。你应该先让它工作,然后替换 RenderText 函数。查看使用 VPR 矢量图形引擎绘制文本的 Examples\Drawing\TextVPR 示例。
  • RenderText 似乎也不允许 Font.Size !?!?!
  • 它使用位图的字体大小。所以改变'B.Bitmap.Font.Size'应该有任何影响。
  • 我似乎无法成功更改渲染文本的颜色(使用矢量方法)。我尝试设置 Layer.Bitmap.Font.Color(将包含矢量文本的图层),但这不起作用,因为该图层基本上是另一个用 Intf.TextToPath(FPath, MyDestRect, CLoremIpsum 绘制的位图的容器, 旗帜);那么在哪里可以设置文字的颜色呢?
猜你喜欢
  • 2015-04-16
  • 1970-01-01
  • 2015-04-21
  • 2015-04-17
  • 1970-01-01
  • 2015-04-18
  • 2015-06-28
  • 2015-04-15
  • 1970-01-01
相关资源
最近更新 更多