2016-03-08 256 views
1

我正在写一个在画布上绘制文本的函数。该功能支持垂直和水平对齐,也支持文本方向。我的问题是,当面向文本时,无法计算正确的对齐方式。这是标头:如何垂直或水平对齐定位文本?

procedure drawText(canvas: TCanvas; pos: TPoint; Text: string; 
    FontName: TFontName; FontSize: integer; FontColor: TColor; Angle: integer; 
    Halign: THorizontalAlignement; Valign: TVerticalAlignement); 

Halign可以左,右或中心,Valign可以是顶部,底部或中心。

一切行之有效的简单的非面向文本用:

h := TextWidth(Text); 
case Halign of 
    haLeft: // do nothing; 
    ; 
    haRight: x := x - h; 
    haCenter: x := x - (h div 2); 
    end; 

    v := TextHeight(Text); 
    case Valign of 
    vaTop: // do nothing; 
     ; 
    vaBottom: y := y - v; 
    vaCenter: y := y - (v div 2); 
    end; 
    Font.Orientation := Angle; 
    textOut(x, y, Text); 

我已经做了很多的尝试,以确定哪些去的地方,我设法根据其对齐参数垂直文本位置,但水平一个错位。

我知道它与方向,宽度和高度有关,但我无法弄清楚如何处理它。

实例调用程序为horitontal规则时:

drawText(bmp.canvas, point(x, viewOption.padding - DocumentRuleTextMargin), 
inttoStr(x), 'arial', 8, clBLack, 0, haCenter, vaBottom); 

呼唤垂直规则的程序(一个谁是烦人): 的drawText(bmp.canvas,点(x - CDocumentRuleTextMargin,Y ),inttostr(y),'arial',8,clBlack,900,haCenter,vaBottom);

这里是结果:

Example 1

我试图通过在程序这样的y位置的计算修正的迹象摆脱这样的:

v := TextHeight(Text); 
    case Valign of 
    vaTop: // do nothing; 
     ; 
    vaBottom: y := y + v; 
    vaCenter: y := y + (v div 2); 
    end; 

和结果对于垂直规则更好,而对于水平方向则最差:

example 2

+0

我希望你先设置角度,然后询问尺寸。 TextExtent为您提供了这些。 –

+0

使用TextRect,先用tfCalcRect。让GDI计算所需的定向宽度和高度。 –

+0

是的。在查询文字大小之前,我曾尝试过很多关注取向的尝试,但它并没有改变所有的位置。 – nico

回答

0

问题是宽度和高度在旋转文本时不会改变。

使用90°旋转时,返回textHeight函数的是实际(可见)宽度。 textWidth代表可见高度。

在这种情况下,不可能使用与水平文本相同的公式,垂直和水平居中90°旋转文本(即:减去宽度的一半到x位置将导致太大的位移) 。

由于我只管理垂直和水平文本,我将通过测试方向属性来使用解决方法。当900然后我切换textHeight和textwidth结果来计算文本的对齐位置。

0

我认为在你的情况下,垂直规则应该是

drawText(bmp.canvas, Point(x - CDocumentRuleTextMargin, y), inttostr(y), 'arial', 8, clBlack, 900, haCenter, vaCenter); 

,因为您要对齐到复选标记,他们需要为中心。改变你的算法移动垂直位置的预期,所以它看起来像你的原始算法是正确的 - 只是你的应用程序是错误的。

+0

实际上,alignements参数的计算计算不准确,因此将其更改为vaCenter不能解决我的问题。这是重点:我正在寻找正确的方式来计算它时,文本是垂直或水平 – nico

1

行 - 简单的没有工作。然后,您需要做的是找到文本的中心位置,并在旋转后从那里计算“左上角”。问题在于我不知道字体围绕哪个点 - 我猜是左上角。假设你的功能如下:

// get centre 
case Halign of 
    haLeft: x1 := x + (h div 2); 
    haRight: x1 := x - (h div 2); 
    haCenter: x1 := x; // do nothing 
    end; 

    v := TextHeight(Text); 
    case Valign of 
    vaTop: y1 := y + (v div 2); 
    vaBottom: y1 := y - (v div 2); 
    vaCenter: y1 := y; // do nothing 
    end; 
    Font.Orientation := Angle; 
    // calculate new top left - depending on whether you are using firemonkey 
    // or VCL you may need to convert to floats and/or use Cosint 
    // x := x1 - (w/2)*CosD(Angle) - (h/2)*SinD(Angle); 
    x := x1 - ((w * CosInt(Angle * 10)) - (h*SinInt(Angle*10)) div 2000); 
    //y := y1 - (w/2)*SinD(Angle) + (h/2)*CosD(Angle); 
    y := y1 - ((w * SinInt(Angle * 10)) - (h*CosInt(Angle*10)) div 2000); 
    textOut(x, y, Text); 

由于你在你的代码中使用Div,我猜你正在使用VCL。

我建议你查找SinInt来解释这里的乘法和除法。评论显示您将在Firemonkey中使用的浮点版本。

我还没有测试过这段代码 - 我只是试图展示数学。你需要微调自己。