2016-03-08 255 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中使用的浮點版本。

我還沒有測試過這段代碼 - 我只是試圖展示數學。你需要微調自己。