Author: Jonas Bilinkevicius
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.
1
2 procedure TDrawer.fOutStringXYW(w: Double; x, y: Integer; S: string);
3 var
4 nx, ny, xw, xh: Integer;
5 O, T: TXForm;
6 begin
7 nx := 0;
8 ny := 0;
9 xw := TheDraw.Textwidth(S); {the common routine}
10 xh := TheDraw.TextHeight('Ag' + S); {not fine but fast}
11 {handle the justification to get the exact root point for text out}
12 case TextJust of
13 tjCenterTop:
14 begin
15 nx := -xw div 2;
16 ny := 0;
17 end;
18 tjCenterBottom:
19 begin
20 nx := -xw div 2;
21 ny := -xh;
22 end;
23 tjCenterCenter:
24 begin
25 nx := -xw div 2;
26 ny := -xh div 2;
27 end;
28 tjLeftTop:
29 begin
30 nx := 0;
31 ny := 0;
32 end;
33 tjLeftCenter:
34 begin
35 nx := 0;
36 ny := -xh div 2;
37 end;
38 tjLeftBottom:
39 begin
40 nx := 0;
41 ny := -xh;
42 end;
43 tjRightCenter:
44 begin
45 nx := -xw;
46 ny := -xh div 2;
47 end;
48 tjRightTop:
49 begin
50 nx := -xw;
51 ny := 0;
52 end;
53 tjRightBottom:
54 begin
55 nx := -xw;
56 ny := -xh;
57 end;
58 end;
59 {WinGDI Routines start here}
60 SetGraphicsMode(TheDraw.Handle, GM_Advanced);
61 {Angle in degree}
62 T.eM11 := 1 * Cos(w / 360 * Pi * 2);
63 T.eM22 := 1 * Cos(w / 360 * Pi * 2);
64 T.eM12 := 1 * Sin(w / 360 * Pi * 2);
65 T.eM21 := 1 * -Sin(w / 360 * Pi * 2);
66 T.eDX := X;
67 T.eDY := Y;
68 GetWorldTransform(TheDraw.Handle, O);
69 ModifyWorldTransform(TheDraw.Handle, T, MWT_LEFTMULTIPLY);
70 // TheDraw.Pen.Style := psClear;
71 // TheDraw.Rectangle(nx - 1, ny - 1, nx + xw + 3, ny + xh + 2);
72 {here should comes your code to get out the extention of your text.
73 You see the variables above nx, ny, xw, xh. Outextention would be ...}
74 // out_nx1 := round(nx * T.eM11 + ny * T.aM12 + TeDX);
75 // out_ny1 := round(nx * T.eM21 + ny * T.aM22 + TeDY);
76 // out_nx2 := round((nx + xw) * T.eM11 + (ny + xh) * T.aM12 + TeDX);
77 // out_ny2 := round((nx + xw) * T.eM21 + (ny + xy) * T.aM22 + TeDY);
78 {now you have to sort your data that out_nx1< out_nx2 and out_ny1<_out_ny2 and
79 you will have exact your boundingbox coordinates}
80 TheDraw.TextOut(nx, ny, S);
81 T.eM11 := 1;
82 T.eM22 := 1;
83 T.eM12 := 0;
84 T.eM21 := 0;
85 T.eDX := 0;
86 T.eDY := 0;
87 SetWorldTransform(TheDraw.Handle, O);
88 end;
|