|
|
1.1 root 1: /******************************************************************************\
2: *
3: * MODULE: PAINT.C
4: *
5: * PURPOSE: Given an HDC and a pointer to a bounding rectangle
6: * draw all graphics/fonts based on the flags set in
7: * the dwGraphicsOptions global variable.
8: *
9: * FUNTIONS: Paint() - main painting routine
10: * GetFirstGraphicSlot() - computes bounding rect of 1st
11: * graphic
12: * GetNextGraphicSlot() - computes bounding rect of next
13: * graphic
14: * DrawFonts() - draws enumerated fonts
15: * BuildFontList() - builds a list of fonts of fonts
16: * supported by a given DC
17: * MyEnumFaces() - enumerates the font facenames
18: * supported by a given DC
19: * MyEnumCopy() - copies LOGFONT & TEXTMETRIC info
20: * to a global variable
21: * MyEnumCount() - counts total number of fonts
22: * supported by a given DC
23: * FreeFontList() - frees a (BuildFontList-) font list
24: *
25: * COMMENTS: Most of the font-enumeration code "lifted" from NTF.EXE
26: * sample. For more complete documentation have a look a
27: * that.
28: *
29: \******************************************************************************/
30:
31: #include <windows.h>
32: #include <string.h>
33: #include "lookup.h"
34: #include "paint.h"
35: #include "vars.h"
36:
37:
38: /******************************************************************************\
39: *
40: * FUNCTION: Paint
41: *
42: * INPUTS: hdc - device context to paint
43: * lpR - bounding rectangle of device to paint
44: *
45: * RETURNS: TRUE if painting went ok, or
46: * FALSE if error while painting
47: *
48: * GLOBAL VARS: dwGraphicsOptions - current graphics options
49: *
50: * LOCAL VARS: ri - a scratch rectangle with integer elements
51: *
52: \******************************************************************************/
53:
54: BOOL Paint (HDC hdc, LPRECT lpR)
55: {
56: RECTI ri;
57:
58: if (dwGraphicsOptions & ENUMFONTS)
59: {
60: DrawFonts (hdc, lpR);
61: return TRUE;
62: }
63:
64: iDeltaX = (int) ((lpR->right - BORDER)/NUM_GRAPHICS_XSLOTS);
65: iDeltaY = (int) ((lpR->bottom- BORDER)/NUM_GRAPHICS_YSLOTS);
66:
67: GetFirstGraphicSlot (&ri);
68:
69: if (dwGraphicsOptions & ARC)
70: {
71: Arc (hdc, ri.left, ri.top, ri.right, ri.bottom,
72: ri.left, ri.top, ri.right-10, ri.bottom-10);
73: GetNextGraphicSlot (&ri);
74: }
75:
76: if (dwGraphicsOptions & ELLIPSE)
77: {
78: SelectObject (hdc, GetStockObject (DKGRAY_BRUSH));
79: Ellipse (hdc, ri.left, ri.top, ri.right, ri.bottom);
80: GetNextGraphicSlot (&ri);
81: }
82:
83: if (dwGraphicsOptions & LINETO)
84: {
85: int i;
86:
87: for (i = PS_SOLID; i <= PS_DASHDOTDOT; i++)
88: {
89: HPEN hpenSave;
90: HPEN hpen = CreatePen (i, i+1, RGB(0,0,0));
91:
92: hpenSave = SelectObject (hdc, hpen);
93: MoveToEx (hdc, ri.left, ri.top + (i+1)*iDeltaY/7, NULL);
94: LineTo (hdc, ri.right, ri.top + (i+1)*iDeltaY/7);
95: SelectObject (hdc, hpenSave);
96: DeleteObject (hpen);
97: }
98: GetNextGraphicSlot (&ri);
99: }
100:
101: if (dwGraphicsOptions & PIE)
102: {
103: SelectObject (hdc, GetStockObject (LTGRAY_BRUSH));
104: Pie (hdc, ri.left, ri.top, ri.right, ri.bottom,
105: ri.left, ri.top, ri.right-10, ri.bottom-10);
106: GetNextGraphicSlot (&ri);
107: }
108:
109: if (dwGraphicsOptions & POLYBEZIER)
110: {
111: POINT ap[4];
112:
113: ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top;
114: ap[1].x = (LONG) ri.left; ap[1].y = (LONG) ri.bottom;
115: ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top;
116: ap[3].x = (LONG) ri.right; ap[3].y = (LONG) ri.bottom;
117:
118: PolyBezier (hdc, ap, 4);
119: GetNextGraphicSlot (&ri);
120: }
121:
122: if (dwGraphicsOptions & POLYGON)
123: {
124: POINT ap[5];
125:
126: ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top;
127: ap[1].x = (LONG) ri.right; ap[1].y = (LONG) ri.bottom;
128: ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top;
129: ap[3].x = (LONG) ri.left; ap[3].y = (LONG) ri.bottom;
130: ap[4].x = (LONG) ri.left; ap[4].y = (LONG) ri.top;
131:
132: SelectObject (hdc, GetStockObject (BLACK_BRUSH));
133: Polygon (hdc, ap, 4);
134: GetNextGraphicSlot (&ri);
135: }
136:
137: if (dwGraphicsOptions & POLYLINE)
138: {
139: POINT ap[4];
140:
141: ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top;
142: ap[1].x = (LONG) ri.left; ap[1].y = (LONG) ri.bottom;
143: ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top;
144: ap[3].x = (LONG) ri.right; ap[3].y = (LONG) ri.bottom;
145:
146: Polyline (hdc, ap, 4);
147: GetNextGraphicSlot (&ri);
148: }
149:
150: if (dwGraphicsOptions & POLYPOLYGON)
151: {
152: POINT ap[8];
153: int ai[2] = { 4, 4 };
154:
155: ap[0].x = (LONG) ri.left;
156: ap[0].y = (LONG) ri.top;
157: ap[1].x = (LONG) (ri.left + iDeltaX/4);
158: ap[1].y = (LONG) ri.top;
159: ap[2].x = (LONG) (ri.left + iDeltaX/4);
160: ap[2].y = (LONG) (ri.top + iDeltaY/4);
161: ap[3].x = (LONG) ri.left;
162: ap[3].y = (LONG) (ri.top + iDeltaY/4);
163: ap[4].x = (LONG) (ri.right - 2*iDeltaX/3);
164: ap[4].y = (LONG) (ri.bottom - 2*iDeltaY/3);
165: ap[5].x = (LONG) ri.right;
166: ap[5].y = (LONG) (ri.bottom - 2*iDeltaY/3);
167: ap[6].x = (LONG) ri.right;
168: ap[6].y = (LONG) ri.bottom;
169: ap[7].x = (LONG) (ri.right - 2*iDeltaX/3);
170: ap[7].y = (LONG) ri.bottom;
171:
172: SelectObject (hdc, GetStockObject (BLACK_BRUSH));
173: PolyPolygon (hdc, ap, ai, 2);
174: GetNextGraphicSlot (&ri);
175: }
176:
177: if (dwGraphicsOptions & RECTANGLE)
178: {
179: SelectObject (hdc, GetStockObject (LTGRAY_BRUSH));
180: Rectangle (hdc, ri.left, ri.top, ri.right, ri.bottom);
181: GetNextGraphicSlot (&ri);
182: }
183:
184: if (dwGraphicsOptions & ROUNDRECT)
185: {
186: SelectObject (hdc, GetStockObject (DKGRAY_BRUSH));
187: RoundRect (hdc, ri.left, ri.top, ri.right, ri.bottom, 12, 19);
188: GetNextGraphicSlot (&ri);
189: }
190:
191: if (dwGraphicsOptions & STRETCH_BLT)
192: {
193: HBITMAP hbm;
194: BITMAP bm;
195: HDC hdcMem;
196:
197: hbm = LoadBitmap (hInst, "printer");
198: hdcMem = CreateCompatibleDC (hdc);
199: SelectObject (hdcMem, hbm);
200: SetMapMode (hdcMem, GetMapMode(hdc));
201:
202: GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
203: StretchBlt (hdc, ri.left, ri.top, ri.right-ri.left,
204: ri.bottom - ri.top, hdcMem, 0, 0,
205: bm.bmWidth, bm.bmHeight, SRCCOPY);
206:
207: DeleteDC(hdcMem);
208: GetNextGraphicSlot (&ri);
209: }
210:
211: if (dwGraphicsOptions & TEXTOUT)
212: {
213: TextOut (hdc, ri.left, ri.top + iDeltaY/2, "TextOut", 7);
214: GetNextGraphicSlot (&ri);
215: }
216:
217: return TRUE;
218: }
219:
220:
221:
222: /******************************************************************************\
223: *
224: * FUNCTION: GetFirstGraphicSlot
225: *
226: * INPUTS: pri - pointer to a RECTI
227: *
228: * GLOBAL VARS: column - current grpahics column/slot
229: * iDeltax - width of grahics slots
230: * iDeltaY - height of grahics slots
231: *
232: \******************************************************************************/
233:
234: void GetFirstGraphicSlot (PRECTI pri)
235: {
236: pri->left = BORDER;
237: pri->top = BORDER;
238: pri->right = iDeltaX;
239: pri->bottom = iDeltaY;
240:
241: column = 1;
242: }
243:
244:
245:
246: /******************************************************************************\
247: *
248: * FUNCTION: GetNextGraphicSlot
249: *
250: * INPUTS: pri - pointer to a RECTI
251: *
252: * GLOBAL VARS: column - current grpahics column/slot
253: * iDeltax - width of grahics slots
254: * iDeltaY - height of grahics slots
255: *
256: \******************************************************************************/
257:
258: void GetNextGraphicSlot (PRECTI pri)
259: {
260: if (++column <= NUM_GRAPHICS_XSLOTS)
261: {
262: pri->left += iDeltaX;
263: pri->right += iDeltaX;
264: }
265: else
266: {
267: column = 1;
268: pri->left = BORDER;
269: pri->top += iDeltaY;
270: pri->right = iDeltaX;
271: pri->bottom += iDeltaY;
272: }
273: }
274:
275:
276:
277: /******************************************************************************\
278: *
279: * FUNCTION: DrawFonts
280: *
281: * LOCAL VARS: i, j - loop variables
282: * xText - starting x position to draw text
283: * yText - starting y position to draw text
284: * iMaxStrLen - length in pels of string to draw
285: *
286: \******************************************************************************/
287:
288: void DrawFonts (HDC hdc, LPRECT lpR)
289: {
290: int i, j, xText, yText, iMaxStrLen = 0;
291: PARFONTS paf;
292:
293: paf = BuildFontList (hdc);
294: xText = yText = 2;
295: for (i = 0; i < nFaces; i++)
296: {
297: for (j = 0; j < (paf + i)->nFonts; j++)
298: {
299: HFONT hFont, hSaveFont;
300: SIZE size;
301: TEXTMETRIC *pNextTM;
302: POINT LogPtBtmRt;
303:
304: LogPtBtmRt.x = lpR->right;
305: LogPtBtmRt.y = lpR->bottom;
306: if (GetDeviceCaps (hdc, TECHNOLOGY) & DT_RASDISPLAY)
307: LogPtBtmRt.y += TOOLBARHEIGHT;
308: DPtoLP (hdc, &LogPtBtmRt, 1);
309:
310: hFont = CreateFontIndirect ((paf + i)->lf + j);
311: hSaveFont = SelectObject (hdc, hFont);
312: TextOut (hdc, xText, yText, ((paf + i)->lf + j)->lfFaceName,
313: strlen(((paf + i)->lf + j)->lfFaceName));
314:
315: GetTextExtentPoint (hdc, ((paf + i)->lf + j)->lfFaceName,
316: strlen(((paf+i)->lf+j)->lfFaceName),
317: &size);
318: size.cx += 2;
319: iMaxStrLen = iMaxStrLen > (int)size.cx ? iMaxStrLen:
320: (int) size.cx;
321:
322: if (!(i == (nFaces - 1) && j == ((paf + i)->nFonts - 1)))
323: {
324: pNextTM = j < ((paf+i)->nFonts-1) ?
325: (paf+i)->tm+j+1 : (paf+i+1)->tm;
326:
327: if ((yText += (int) ((paf + i)->tm + j)->tmHeight) +
328: (int) pNextTM->tmHeight > (int) LogPtBtmRt.y)
329: {
330: yText = 2;
331: xText += iMaxStrLen + 2;
332: iMaxStrLen = 0;
333: }
334: }
335:
336: SelectObject (hdc, hSaveFont);
337: DeleteObject (hFont);
338: if (xText > (int) LogPtBtmRt.x)
339: {
340: if (GetDeviceCaps (hdc, TECHNOLOGY) & DT_RASDISPLAY)
341: {
342: /********************************************************************\
343: * If we're drawing to the screen & have run out of
344: * room then tell user how many fonts there are left
345: * (that we haven't displayed
346: \********************************************************************/
347:
348: int k;
349: int iFontsLeft = (paf + i)->nFonts - j - 1;
350: char buf[40];
351: SIZE size;
352:
353: for (k = i + 1; k < nFaces; k++)
354: iFontsLeft += (paf + k)->nFonts;
355:
356: wsprintf (buf, "%ld more display fonts (not listed)",
357: iFontsLeft);
358:
359: GetTextExtentPoint (hdc, buf, strlen(buf), &size);
360: TextOut (hdc, lpR->right - size.cx, lpR->bottom - size.cy,
361: buf, strlen(buf));
362: goto done_enumfonts;
363: }
364: else
365: {
366: /********************************************************************\
367: * Else we're drawing to a printer & have filled up
368: * the first page. If there's any fonts left to draw
369: * then start a new page.
370: \********************************************************************/
371:
372: if (!(i == nFaces - 1 && j == (paf + i)->nFonts - 1))
373: { EndPage (hdc);
374: xText = yText = 2;
375: StartPage (hdc);
376: }
377: }
378: }
379: }
380: }
381: done_enumfonts:
382: FreeFontList (paf);
383: }
384:
385:
386:
387:
388: /* In the callback functions from the enumerations, there is a limited
389: * ability to pass in parameters. For that reason, declare the following
390: * global variables to be used by any of the call back functions.
391: *
392: * HDC hdcGlobal;
393: * PARFONTS parFontsGlobal;
394: * int iFace,jFont;
395: * int nFaces;
396: *
397: *
398: * General call structure:
399: *
400: * BuildFontList()
401: * EnumFonts
402: * MyEnumCount()
403: * LocalAlloc
404: * EnumFonts
405: * MyEnumFaces()
406: * EnumFonts
407: * MyEnumCount()
408: * LocalAlloc
409: * LocalAlloc
410: * LocalAlloc
411: * EnumFonts
412: * MyEnumCopy()
413: */
414:
415:
416:
417: /******************************************************************************\
418: *
419: * FUNCTION: BuildFontList
420: *
421: * GLOBAL VARS: (see above)
422: *
423: \******************************************************************************/
424:
425: PARFONTS BuildFontList (HDC hdcIn)
426: {
427: nFaces = 0;
428:
429: hdcGlobal = hdcIn;
430:
431: /****************************************************************************\
432: * count the total number of face names.
433: \****************************************************************************/
434:
435: EnumFonts (hdcGlobal, NULL, (PROC)MyEnumCount, (LPARAM)&nFaces);
436:
437: /****************************************************************************\
438: * allocate the pointer to the array of PArFont structures.
439: \****************************************************************************/
440:
441: parFontsGlobal = LocalAlloc (LPTR, sizeof(ARFONTS) * (nFaces+1));
442:
443: /****************************************************************************\
444: * step through all fonts again. For each one fill a LOGFONT and
445: * a TEXTMETRIC stucture.
446: \****************************************************************************/
447:
448: iFace = 0;
449: EnumFonts (hdcGlobal, NULL, (PROC)MyEnumFaces, NULL);
450:
451: return parFontsGlobal;
452: }
453:
454:
455:
456: /******************************************************************************\
457: *
458: * FUNCTION: MyEnumFaces
459: *
460: * GLOBAL VARS: (see above)
461: *
462: \******************************************************************************/
463:
464: int APIENTRY MyEnumFaces (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
465: DWORD fFontType, LPVOID lpData)
466: {
467: int nFonts;
468:
469: nFonts = 0;
470: EnumFonts (hdcGlobal, lpLogFont->lfFaceName, (PROC)MyEnumCount,
471: (LPARAM)&nFonts);
472:
473: parFontsGlobal[iFace].lf = LocalAlloc (LPTR,
474: sizeof(LOGFONT) * nFonts);
475: parFontsGlobal[iFace].tm = LocalAlloc (LPTR,
476: sizeof(TEXTMETRIC) * nFonts);
477: parFontsGlobal[iFace].Type = LocalAlloc (LPTR,
478: sizeof(int) * nFonts);
479:
480: if ((parFontsGlobal[iFace].lf == NULL) ||
481: (parFontsGlobal[iFace].tm == NULL) ||
482: (parFontsGlobal[iFace].Type == NULL)) {
483: MessageBox (NULL, "alloc failed", "HEY!", MB_ICONSTOP | MB_OK);
484: return FALSE;
485: }
486:
487: parFontsGlobal[iFace].nFonts = nFonts;
488:
489: jFont = 0;
490: EnumFonts (hdcGlobal, lpLogFont->lfFaceName, (PROC)MyEnumCopy, NULL);
491:
492: iFace++;
493:
494: return TRUE;
495: }
496:
497:
498:
499: /******************************************************************************\
500: *
501: * FUNCTION: MyEnumCopy
502: *
503: * GLOBAL VARS: (see above)
504: *
505: \******************************************************************************/
506:
507: int APIENTRY MyEnumCopy (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
508: DWORD fFontType, LPVOID lpData)
509: {
510: LOGFONT *lplf;
511: TEXTMETRIC *lptm;
512: int *pType;
513:
514: lplf = parFontsGlobal[iFace].lf;
515: lptm = parFontsGlobal[iFace].tm;
516: pType = parFontsGlobal[iFace].Type;
517:
518: lplf[jFont] = *lpLogFont;
519: lptm[jFont] = *lpTEXTMETRICs;
520: pType[jFont] = fFontType;
521:
522: jFont++;
523: return TRUE;
524: }
525:
526:
527:
528: /******************************************************************************\
529: *
530: * FUNCTION: MyEnumCount
531: *
532: * GLOBAL VARS: (see above)
533: *
534: \******************************************************************************/
535:
536: int APIENTRY MyEnumCount (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
537: DWORD fFontType, LPVOID lpData)
538: {
539: (*(LPINT)lpData)++;
540: return TRUE;
541: }
542:
543:
544:
545: /******************************************************************************\
546: *
547: * FUNCTION: FreeFontList
548: *
549: * INPUTS: paf - pointer to ARFONTS struct to free
550: *
551: * LOCAL VARS: i - loop variable
552: *
553: \******************************************************************************/
554:
555: void FreeFontList (PARFONTS paf)
556: {
557: int i;
558:
559: for (i = 0; i < nFaces; i++)
560: { LocalFree (LocalHandle ((LPSTR) ((paf + i)->lf )));
561: LocalFree (LocalHandle ((LPSTR) ((paf + i)->tm )));
562: LocalFree (LocalHandle ((LPSTR) ((paf + i)->Type)));
563: }
564: LocalFree (LocalHandle ((LPSTR) paf));
565: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.