1 /*
2 * file w32_text.c - drawing strings and boxes
3 *
4 * $Id: w32_text.c,v 1.5 2006/02/19 13:33:01 lodott Exp $
5 *
6 * Program XBLAST
7 * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published
11 * by the Free Software Foundation; either version 2; or (at your option)
12 * any later version
13 *
14 * This program is distributed in the hope that it will be entertaining,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.
21 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23 #include "xblast.h"
24 #include "w32_text.h"
25 #include "gui.h"
26
27 #include "w32_color.h"
28 #include "w32_image.h"
29
30 #include "geom.h"
31
32 /*
33 * local macros
34 */
35 #define COLOR_LIGHT (SET_COLOR(31,29,0))
36 #define COLOR_DARK (SET_COLOR( 0, 0,0))
37
38 /*
39 * local types
40 */
41 /* pen types */
42 enum
43 {
44 PEN_LightThick,
45 PEN_LightThin,
46 PEN_DarkThick,
47 PEN_DarkThin,
48 /*---*/
49 NUM_PEN
50 };
51 /* brush types */
52 enum
53 {
54 BRUSH_Light,
55 BRUSH_Dark,
56 /*---*/
57 NUM_BRUSH
58 };
59 /* pen init data */
60 typedef struct
61 {
62 int style;
63 int width;
64 XBColor color;
65 } XBInitPen;
66
67 /*
68 * local variables
69 */
70 static HDC hdcLight;
71 static HDC hdcDark;
72 static HPEN hPen[NUM_PEN];
73 static HBRUSH hBrush[NUM_BRUSH];
74 static HFONT hfont[NUM_FONTS];
75
76 #ifdef MINI_XBLAST
77 static int fontSize[NUM_FONTS] = {
78 14, 12, 10
79 };
80 #else
81 static int fontSize[NUM_FONTS] = {
82 32, 24, 18
83 };
84 #endif
85 static int fontHeight[NUM_FONTS] = {
86 0, 0, 0
87 };
88 static XBInitPen initPen[NUM_PEN] = {
89 {PS_SOLID, 3 * BASE_X / 8, COLOR_LIGHT,},
90 {PS_SOLID, 1, COLOR_LIGHT,},
91 {PS_SOLID, 3 * BASE_X / 8, COLOR_DARK,},
92 {PS_SOLID, 1, COLOR_DARK,},
93 };
94 static XBColor initBrush[NUM_BRUSH] = {
95 COLOR_LIGHT,
96 COLOR_DARK,
97 };
98
99 /*
100 * create dc for drwaing textbox
101 */
102 static HDC
CreateTextDC(HDC hdc,HPEN hPen,HBRUSH hBrush,XBColor textColor)103 CreateTextDC (HDC hdc, HPEN hPen, HBRUSH hBrush, XBColor textColor)
104 {
105 HDC hdcText;
106
107 hdcText = CreateCompatibleDC (hdc);
108 if (NULL == hdcText) {
109 return NULL;
110 }
111 SelectObject (hdcText, hPen);
112 SelectObject (hdcText, hBrush);
113 SetTextColor (hdcText, COLOR_TO_COLORREF (textColor));
114 SetBkMode (hdcText, TRANSPARENT);
115 SetTextAlign (hdcText, TA_CENTER | TA_TOP);
116 SetPolyFillMode (hdcText, WINDING);
117 /* that's all */
118 return hdcText;
119 } /* CreateTextDC */
120
121 /*
122 * library function: InitText
123 * description: initizialize windows resources for drawingh text
124 * parameters: none
125 * return value: XBTrue on success, XBFalse on error
126 */
127 XBBool
InitText(void)128 InitText (void)
129 {
130 int i;
131 HDC hdc;
132 HGDIOBJ old;
133 SIZE size;
134
135 /* initialize fields */
136 hdcLight = hdcDark = NULL;
137 memset (hPen, 0, sizeof (hPen));
138 memset (hBrush, 0, sizeof (hBrush));
139 memset (hfont, 0, sizeof (hfont));
140 /* create pens */
141 for (i = 0; i < NUM_PEN; i++) {
142 hPen[i] =
143 CreatePen (initPen[i].style, initPen[i].width, COLOR_TO_COLORREF (initPen[i].color));
144 }
145 /* create brushes */
146 for (i = 0; i < NUM_BRUSH; i++) {
147 hBrush[i] = CreateSolidBrush (COLOR_TO_COLORREF (initBrush[i]));
148 }
149 /* create logical fonts */
150 hdc = GetDC (window);
151 for (i = 0; i < NUM_FONTS; i++) {
152 hfont[i] = CreateFont (fontSize[i], 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, ANSI_CHARSET,
153 OUT_DEVICE_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
154 VARIABLE_PITCH | FF_SWISS, "MS SansSerif");
155 if (NULL == hfont[i]) {
156 return XBFalse;
157 }
158 /* get default height */
159 old = SelectObject (hdc, hfont[i]);
160 GetTextExtentPoint32 (hdc, "Xj", 2, &size);
161 SelectObject (hdc, old);
162 fontHeight[i] = size.cy;
163 }
164 /* create and config DC for light text */
165 hdcLight = CreateTextDC (hdc, hPen[PEN_LightThick], hBrush[BRUSH_Dark], COLOR_LIGHT);
166 /* create and config DC for dark text */
167 hdcDark = CreateTextDC (hdc, hPen[PEN_DarkThick], hBrush[BRUSH_Light], COLOR_DARK);
168 /* thats's all */
169 ReleaseDC (window, hdc);
170 return XBTrue;
171 } /* InitText */
172
173 /*
174 *
175 */
176 void
FinishText(void)177 FinishText (void)
178 {
179 int i;
180
181 /* pens */
182 for (i = 0; i < NUM_PEN; i++) {
183 if (NULL != hPen[i]) {
184 DeleteObject (hPen[i]);
185 }
186 }
187 /* brushes */
188 for (i = 0; i < NUM_BRUSH; i++) {
189 if (NULL != hBrush[i]) {
190 DeleteObject (hBrush[i]);
191 }
192 }
193 /* fonts */
194 for (i = 0; i < NUM_FONTS; i++) {
195 if (NULL != hfont[i]) {
196 DeleteObject (hfont[i]);
197 }
198 }
199 /* device contextes */
200 if (NULL != hdcLight) {
201 DeleteDC (hdcLight);
202 }
203 if (NULL != hdcDark) {
204 DeleteDC (hdcDark);
205 }
206 } /* FinishText */
207
208 /*
209 * global function: GUI_DrawSimpleTextbox
210 * description: draw a text string with optional box
211 * parameters: text - 0 terminated string to draw
212 * flags - draw mode flags see xblast.h FF_*
213 rect - where to draw
214 * return value: none
215 */
216 void
GUI_DrawSimpleTextbox(const char * text,unsigned flags,const BMRectangle * rect)217 GUI_DrawSimpleTextbox (const char *text, unsigned flags, const BMRectangle * rect)
218 {
219 HGDIOBJ old;
220 int len;
221 int ypos;
222 int xpos;
223 HDC hdc;
224
225 /* sanity checks */
226 assert (rect != NULL);
227 /* get device context */
228 hdc = (flags & FM_Color) ? hdcLight : hdcDark;
229 old = SelectObject (hdc, pix);
230 /* draw boxes */
231 if (flags & FM_Boxed) {
232 Rectangle (hdc, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
233 }
234 /* Draw text */
235 if (text != NULL) {
236 len = strlen (text);
237 ypos = rect->y + (rect->h - fontHeight[flags & FM_Size]) / 2;
238 xpos = rect->x + rect->w / 2;
239 /* x position */
240 SetTextAlign (hdcLight, TA_CENTER | TA_TOP);
241 SetTextAlign (hdcDark, TA_CENTER | TA_TOP);
242 SelectObject (hdc, hfont[flags & FM_Size]);
243 ExtTextOut (hdc, xpos, ypos, ETO_OPAQUE, NULL, text, len, NULL);
244 }
245 /* clean up */
246 SelectObject (hdc, old);
247 } /* GUI_DrawSimpleTextbox */
248
249 /*
250 *
251 */
252 static int
DrawAlignedText(const char * text,int len,unsigned flags,int x,int y,int w,HDC hdc_fg,HDC hdc_bg,HGDIOBJ * pOld)253 DrawAlignedText (const char *text, int len, unsigned flags, int x, int y, int w, HDC hdc_fg,
254 HDC hdc_bg, HGDIOBJ * pOld)
255 {
256 SIZE textSize;
257 int xpos;
258 int dx, dy;
259 int step;
260 int right;
261
262 assert (text != NULL);
263 assert (pOld != NULL);
264 /* Set Font */
265 SelectObject (hdc_fg, hfont[flags & FM_Size]);
266 /* determine length */
267 len++;
268 do {
269 len--;
270 GetTextExtentPoint32 (hdc_fg, text, len, &textSize);
271 } while (textSize.cx > w - 2 * BASE_X);
272 /* set text alignment */
273 switch (flags & FM_Align) {
274 case FF_Right:
275 SetTextAlign (hdc_fg, TA_TOP | TA_RIGHT);
276 SetTextAlign (hdc_bg, TA_TOP | TA_RIGHT);
277 xpos = x + w - BASE_X;
278 right = xpos;
279 break;
280 case FF_Left:
281 SetTextAlign (hdc_fg, TA_TOP | TA_LEFT);
282 SetTextAlign (hdc_bg, TA_TOP | TA_LEFT);
283 xpos = x + BASE_X;
284 right = xpos + textSize.cx;
285 break;
286 default:
287 SetTextAlign (hdc_fg, TA_CENTER | TA_TOP);
288 SetTextAlign (hdc_bg, TA_CENTER | TA_TOP);
289 xpos = x + w / 2;
290 right = xpos + textSize.cx / 2;
291 break;
292 }
293 /* out lined output */
294 if (flags & FM_Outlined) {
295 /* determine size of outlining */
296 if ((flags & FM_Size) == FF_Small) {
297 step = 1;
298 }
299 else {
300 step = BASE_X / 4;
301 }
302 SelectObject (hdc_fg, *pOld);
303 *pOld = SelectObject (hdc_bg, pix);
304 SelectObject (hdc_bg, hfont[flags & FM_Size]);
305 for (dx = -step; dx <= step; dx += step) {
306 for (dy = -step; dy <= step; dy += step) {
307 if (dx || dy) {
308 ExtTextOut (hdc_bg, xpos + dx, y + dy, ETO_OPAQUE, NULL, text, len, NULL);
309 }
310 }
311 }
312 SelectObject (hdc_bg, *pOld);
313 *pOld = SelectObject (hdc_fg, pix);
314 }
315 /* text output */
316 ExtTextOut (hdc_fg, xpos, y, ETO_OPAQUE, NULL, text, len, NULL);
317 /* that's all */
318 return right;
319 } /* DrawAlignedText */
320
321 /*
322 * global function: GUI_DrawTextbox
323 * description: draw a text string with optional box and outlining
324 * parameters: text - 0 terminated string to draw
325 * flags - draw mode flags see xblast.h FF_*
326 rect - where to draw
327 * return value: none
328 */
329 void
GUI_DrawTextbox(const char * text,unsigned flags,const BMRectangle * rect)330 GUI_DrawTextbox (const char *text, unsigned flags, const BMRectangle * rect)
331 {
332 HGDIOBJ old;
333 int len;
334 int ypos;
335 HDC hdc;
336
337 /* sanity checks */
338 assert (rect != NULL);
339 /* get device context */
340 hdc = (flags & FM_Color) ? hdcLight : hdcDark;
341 old = SelectObject (hdc, pix);
342 /* draw boxes */
343 if (flags & FM_Boxed) {
344 if (flags & FM_Transparent) {
345 HGDIOBJ oldPen;
346 if (flags & FM_Color) {
347 oldPen = SelectObject (hdc, hPen[PEN_DarkThin]);
348 }
349 else {
350 oldPen = SelectObject (hdc, hPen[PEN_LightThin]);
351 }
352 for (ypos = 0; ypos < rect->h; ypos += 2) {
353 MoveToEx (hdc, rect->x, rect->y + ypos, NULL);
354 LineTo (hdc, rect->x + rect->w - 1, rect->y + ypos);
355 }
356 SelectObject (hdc, oldPen);
357 MoveToEx (hdc, rect->x, rect->y, NULL);
358 LineTo (hdc, rect->x + rect->w - 1, rect->y);
359 LineTo (hdc, rect->x + rect->w - 1, rect->y + rect->h - 1);
360 LineTo (hdc, rect->x, rect->y + rect->h - 1);
361 LineTo (hdc, rect->x, rect->y);
362 }
363 else {
364 Rectangle (hdc, rect->x, rect->y, rect->x + rect->w, rect->y + rect->h);
365 }
366 }
367 /* Draw text */
368 if (text != NULL) {
369 HDC hdcInv;
370 int right;
371
372 len = strlen (text);
373 ypos = rect->y + (rect->h - fontHeight[flags & FM_Size]) / 2;
374 hdcInv = (flags & FM_Color) ? hdcDark : hdcLight;
375 if (flags & FF_Vertical) {
376 /* vertcial text layout */
377 int i;
378 for (i = 0; i < len; i++) {
379 int h2 = fontHeight[flags & FM_Size];
380 int y2 = rect->y + ( /*height + */ rect->h) / 2 + (2 * i - len + 1) * (h2) / 2;
381 right =
382 DrawAlignedText (text + i, 1, flags, rect->x, y2, rect->w, hdc, hdcInv, &old);
383 }
384 }
385 else {
386 right = DrawAlignedText (text, len, flags, rect->x, ypos, rect->w, hdc, hdcInv, &old);
387 /* draw cursor if needed */
388 if (flags & FF_Cursor) {
389 MoveToEx (hdc, right + 2, rect->y + 4, NULL);
390 LineTo (hdc, right + 2, rect->y + rect->h - 5);
391 }
392 }
393 }
394 /* clean up */
395 SelectObject (hdc, old);
396 } /* GUI_DrawTextbox */
397
398 /*
399 * global function: GUI_DrawPolygon
400 * description: draw an outlined polygon
401 * parameters: x - left side of draw region
402 * y - top side of draw region
403 * w - width of draw region
404 * h - height of draw region
405 * lw - width of outline
406 * points - relative coordinates (0,0 to 1,1)
407 * npoints - number of points
408 * black_white - dark or light fill pattern
409 * return value: none
410 */
411 void
GUI_DrawPolygon(int x,int y,int w,int h,int lw,const BMPoint * points,int npoints,XBBool blackWhite)412 GUI_DrawPolygon (int x, int y, int w, int h, int lw,
413 const BMPoint * points, int npoints, XBBool blackWhite)
414 {
415 int i;
416 POINT *wp;
417 HDC hdc;
418 HGDIOBJ old;
419
420 assert (points != NULL);
421 /* copy points to windows structure */
422 wp = calloc (sizeof (POINT), npoints + 1);
423 assert (wp != NULL);
424 for (i = 0; i < npoints; i++) {
425 wp[i].x = (LONG) (x + w * points[i].x);
426 wp[i].y = (LONG) (y + h * points[i].y);
427 }
428 wp[npoints] = wp[0];
429 /* get device context */
430 hdc = blackWhite ? hdcLight : hdcDark;
431 old = SelectObject (hdc, pix);
432 /* draw polygon */
433 Polygon (hdc, wp, npoints);
434 /* clean up */
435 free (wp);
436 SelectObject (hdc, old);
437 } /* GUI_DrawPolygon */
438
439 /*
440 * end of file w32_text.c
441 */
442