2006. május 18., csütörtök
How to calculate the bounding box for every character in a rotated text
Problem/Question/Abstract:
I need to calculate the bounding box (the rotated bounding box) for every character in a rotated text, for later allowing selection by picking inside this bounding box. What is the best method for doing that? Using GetCharABCWidths together with GetTextMetrics and later rotate myself every single character bounding box? I cannot use GetGlyphOutline to extract vector information because it will be too slow for my application that needs to draw thousands of text.
Answer:
I work with WinGDI32 routines to handle rotated text via transforming the device context. You can automatically get the extention coordinates in DC units by the affine transformation data. To illustrate this I give you the code from my extended TDrawer Object. This object handles some BGI like routintes like text justify and so on.
procedure TDrawer.fOutStringXYW(w: Double; x, y: Integer; S: string);
var
nx, ny, xw, xh: Integer;
O, T: TXForm;
begin
nx := 0;
ny := 0;
xw := TheDraw.Textwidth(S); {the common routine}
xh := TheDraw.TextHeight('Ag' + S); {not fine but fast}
{handle the justification to get the exact root point for text out}
case TextJust of
tjCenterTop:
begin
nx := -xw div 2;
ny := 0;
end;
tjCenterBottom:
begin
nx := -xw div 2;
ny := -xh;
end;
tjCenterCenter:
begin
nx := -xw div 2;
ny := -xh div 2;
end;
tjLeftTop:
begin
nx := 0;
ny := 0;
end;
tjLeftCenter:
begin
nx := 0;
ny := -xh div 2;
end;
tjLeftBottom:
begin
nx := 0;
ny := -xh;
end;
tjRightCenter:
begin
nx := -xw;
ny := -xh div 2;
end;
tjRightTop:
begin
nx := -xw;
ny := 0;
end;
tjRightBottom:
begin
nx := -xw;
ny := -xh;
end;
end;
{WinGDI Routines start here}
SetGraphicsMode(TheDraw.Handle, GM_Advanced);
{Angle in degree}
T.eM11 := 1 * Cos(w / 360 * Pi * 2);
T.eM22 := 1 * Cos(w / 360 * Pi * 2);
T.eM12 := 1 * Sin(w / 360 * Pi * 2);
T.eM21 := 1 * -Sin(w / 360 * Pi * 2);
T.eDX := X;
T.eDY := Y;
GetWorldTransform(TheDraw.Handle, O);
ModifyWorldTransform(TheDraw.Handle, T, MWT_LEFTMULTIPLY);
// TheDraw.Pen.Style := psClear;
// TheDraw.Rectangle(nx - 1, ny - 1, nx + xw + 3, ny + xh + 2);
{here should comes your code to get out the extention of your text.
You see the variables above nx, ny, xw, xh. Outextention would be ...}
// out_nx1 := round(nx * T.eM11 + ny * T.aM12 + TeDX);
// out_ny1 := round(nx * T.eM21 + ny * T.aM22 + TeDY);
// out_nx2 := round((nx + xw) * T.eM11 + (ny + xh) * T.aM12 + TeDX);
// out_ny2 := round((nx + xw) * T.eM21 + (ny + xy) * T.aM22 + TeDY);
{now you have to sort your data that out_nx1< out_nx2 and out_ny1<_out_ny2 and
you will have exact your boundingbox coordinates}
TheDraw.TextOut(nx, ny, S);
T.eM11 := 1;
T.eM22 := 1;
T.eM12 := 0;
T.eM21 := 0;
T.eDX := 0;
T.eDY := 0;
SetWorldTransform(TheDraw.Handle, O);
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése