|
|
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: * Microsoft Developer Support
31: * Copyright (c) 1992 Microsoft Corporation
32: *
33: \******************************************************************************/
34:
35: #include <windows.h>
36: #include <string.h>
37: #include "common.h"
38: #include "paint.h"
39:
40:
41:
42: /******************************************************************************\
43: *
44: * FUNCTION: Paint
45: *
46: * INPUTS: hdc - device context to paint
47: * lpRect - bounding rectangle of device to paint
48: *
49: * RETURNS: TRUE if painting went ok, or
50: * FALSE if error while painting
51: *
52: \******************************************************************************/
53:
54: BOOL Paint (HDC hdc, LPRECT lpRect)
55: {
56: RECT rect;
57: HPEN hpenSave;
58: RECTI ri;
59:
60: if (gdwGraphicsOptions & DRAWAXIS)
61: {
62:
63: //
64: // draw axis
65: //
66:
67: rect = *lpRect;
68:
69: hpenSave = SelectObject (hdc, GetStockObject (BLACK_PEN));
70:
71: //
72: // if giMapMode == MM_TEXT, MM_ANISOTROPIC then (0,0) is upper left corner
73: //
74:
75: if (giMapMode == MM_TEXT || giMapMode == MM_ANISOTROPIC)
76: {
77: MoveToEx (hdc, rect.left - glcyMenu/2, rect.bottom, NULL);
78: LineTo (hdc, rect.left, rect.bottom + glcyMenu/2);
79: LineTo (hdc, rect.left + glcyMenu/2, rect.bottom);
80:
81: MoveToEx (hdc, rect.left, rect.bottom + glcyMenu/2, NULL);
82: LineTo (hdc, rect.left, rect.top);
83: LineTo (hdc, rect.right + glcyMenu/2, rect.top);
84:
85: MoveToEx (hdc, rect.right, rect.top - glcyMenu/2, NULL);
86: LineTo (hdc, rect.right + glcyMenu/2, rect.top);
87: LineTo (hdc, rect.right, rect.top + glcyMenu/2);
88: }
89:
90: //
91: // else (0,0) is lower left corner
92: //
93:
94: else
95: {
96: MoveToEx (hdc, rect.left - glcyMenu/2, rect.bottom, NULL);
97: LineTo (hdc, rect.left, rect.bottom + glcyMenu/2);
98: LineTo (hdc, rect.left + glcyMenu/2, rect.bottom);
99:
100: MoveToEx (hdc, rect.left, rect.bottom + glcyMenu/2, NULL);
101: LineTo (hdc, rect.left, rect.top);
102: LineTo (hdc, rect.right + glcyMenu/2, rect.top);
103:
104: MoveToEx (hdc, rect.right, rect.top + glcyMenu/2, NULL);
105: LineTo (hdc, rect.right + glcyMenu/2, rect.top);
106: LineTo (hdc, rect.right, rect.top - glcyMenu/2);
107: }
108: }
109:
110: SelectObject (hdc, hpenSave);
111:
112: //
113: // look at bits in gdwGraphicsOptions & determine which graphics to draw
114: //
115:
116: if (gdwGraphicsOptions & ENUMFONTS)
117: {
118: DrawFonts (hdc, lpRect);
119: return TRUE;
120: }
121:
122: giDeltaX = (int) ((lpRect->right - BORDER) / NUM_GRAPHICS_XSLOTS);
123: giDeltaY = (int) ((lpRect->bottom - lpRect->top - BORDER)
124: / NUM_GRAPHICS_YSLOTS);
125:
126: GetFirstGraphicSlot (lpRect, &ri);
127:
128: if (gdwGraphicsOptions & ARC)
129: {
130: Arc (hdc, ri.left, ri.top, ri.right, ri.bottom,
131: ri.left, ri.top, ri.right-10, ri.bottom-10);
132: GetNextGraphicSlot (&ri);
133: }
134:
135: if (gdwGraphicsOptions & ELLIPSE)
136: {
137: Ellipse (hdc, ri.left, ri.top, ri.right, ri.bottom);
138: GetNextGraphicSlot (&ri);
139: }
140:
141: if (gdwGraphicsOptions & LINETO)
142: {
143: int i;
144:
145: for (i = PS_SOLID; i <= PS_DASHDOTDOT; i++)
146: {
147: MoveToEx (hdc, ri.left, ri.top + (i+1)*giDeltaY/7, NULL);
148: LineTo (hdc, ri.right, ri.top + (i+1)*giDeltaY/7);
149: }
150: GetNextGraphicSlot (&ri);
151: }
152:
153: if (gdwGraphicsOptions & PIE)
154: {
155: Pie (hdc, ri.left, ri.top, ri.right, ri.bottom,
156: ri.left, ri.top, ri.right-10, ri.bottom-10);
157: GetNextGraphicSlot (&ri);
158: }
159:
160: if (gdwGraphicsOptions & PLG_BLT)
161: {
162: HBITMAP hbm;
163: BITMAP bm;
164: HDC hdcMem;
165: POINT ap[3];
166:
167: hbm = LoadBitmap (ghInst, "printer");
168: hdcMem = CreateCompatibleDC (hdc);
169: SelectObject (hdcMem, hbm);
170:
171: GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
172:
173: //
174: // special case here because PlgBlt requires coordinates
175: // of upper left, upper right, & lower left
176: //
177:
178: ap[0].x = (LONG) (ri.left + (ri.right - ri.left)/4);
179: ap[0].y = (LONG) (ri.top + (ri.bottom - ri.top)/4);
180: ap[1].x = (LONG) ri.right;
181: ap[1].y = (LONG) ri.top;
182: ap[2].x = (LONG) ri.left;
183: ap[2].y = (LONG) ri.bottom;
184:
185: PlgBlt (hdc, ap, hdcMem, 0, 0, bm.bmWidth, bm.bmHeight, NULL, 0, 0);
186:
187: DeleteDC(hdcMem);
188: GetNextGraphicSlot (&ri);
189:
190: }
191:
192: if (gdwGraphicsOptions & POLYBEZIER)
193: {
194: POINT ap[4];
195:
196: ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top;
197: ap[1].x = (LONG) ri.left; ap[1].y = (LONG) ri.bottom;
198: ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top;
199: ap[3].x = (LONG) ri.right; ap[3].y = (LONG) ri.bottom;
200:
201: PolyBezier (hdc, ap, 4);
202: GetNextGraphicSlot (&ri);
203: }
204:
205: if (gdwGraphicsOptions & POLYGON)
206: {
207: POINT ap[5];
208:
209: ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top;
210: ap[1].x = (LONG) ri.right; ap[1].y = (LONG) ri.bottom;
211: ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top;
212: ap[3].x = (LONG) ri.left; ap[3].y = (LONG) ri.bottom;
213: ap[4].x = (LONG) ri.left; ap[4].y = (LONG) ri.top;
214:
215: Polygon (hdc, ap, 4);
216: GetNextGraphicSlot (&ri);
217: }
218:
219: if (gdwGraphicsOptions & POLYLINE)
220: {
221: POINT ap[4];
222:
223: ap[0].x = (LONG) ri.left; ap[0].y = (LONG) ri.top;
224: ap[1].x = (LONG) ri.left; ap[1].y = (LONG) ri.bottom;
225: ap[2].x = (LONG) ri.right; ap[2].y = (LONG) ri.top;
226: ap[3].x = (LONG) ri.right; ap[3].y = (LONG) ri.bottom;
227:
228: Polyline (hdc, ap, 4);
229: GetNextGraphicSlot (&ri);
230: }
231:
232: if (gdwGraphicsOptions & POLYPOLYGON)
233: {
234: POINT ap[8];
235: int ai[2] = { 4, 4 };
236:
237: ap[0].x = (LONG) ri.left;
238: ap[0].y = (LONG) ri.top;
239: ap[1].x = (LONG) (ri.left + giDeltaX/4);
240: ap[1].y = (LONG) ri.top;
241: ap[2].x = (LONG) (ri.left + giDeltaX/4);
242: ap[2].y = (LONG) (ri.top + giDeltaY/4);
243: ap[3].x = (LONG) ri.left;
244: ap[3].y = (LONG) (ri.top + giDeltaY/4);
245: ap[4].x = (LONG) (ri.right - 2*giDeltaX/3);
246: ap[4].y = (LONG) (ri.bottom - 2*giDeltaY/3);
247: ap[5].x = (LONG) ri.right;
248: ap[5].y = (LONG) (ri.bottom - 2*giDeltaY/3);
249: ap[6].x = (LONG) ri.right;
250: ap[6].y = (LONG) ri.bottom;
251: ap[7].x = (LONG) (ri.right - 2*giDeltaX/3);
252: ap[7].y = (LONG) ri.bottom;
253:
254: PolyPolygon (hdc, ap, ai, 2);
255: GetNextGraphicSlot (&ri);
256: }
257:
258: if (gdwGraphicsOptions & RECTANGLE)
259: {
260: Rectangle (hdc, ri.left, ri.top, ri.right, ri.bottom);
261: GetNextGraphicSlot (&ri);
262: }
263:
264: if (gdwGraphicsOptions & ROUNDRECT)
265: {
266: RoundRect (hdc, ri.left, ri.top, ri.right, ri.bottom, 15, 25);
267: GetNextGraphicSlot (&ri);
268: }
269:
270: if (gdwGraphicsOptions & STRETCH_BLT)
271: {
272: HBITMAP hbm;
273: BITMAP bm;
274: HDC hdcMem;
275:
276: hbm = LoadBitmap (ghInst, "printer");
277: hdcMem = CreateCompatibleDC (hdc);
278: SelectObject (hdcMem, hbm);
279:
280: GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
281:
282: StretchBlt (hdc, ri.left, ri.top, ri.right-ri.left,
283: ri.bottom - ri.top, hdcMem, 0, 0,
284: bm.bmWidth, bm.bmHeight, SRCCOPY);
285:
286: DeleteDC(hdcMem);
287: GetNextGraphicSlot (&ri);
288:
289: }
290:
291: return TRUE;
292: }
293:
294:
295:
296: /******************************************************************************\
297: *
298: * FUNCTION: GetFirstGraphicSlot
299: *
300: * INPUTS: pri - pointer to a RECTI
301: *
302: \******************************************************************************/
303:
304: void GetFirstGraphicSlot (LPRECT lpRect, PRECTI pri)
305: {
306: pri->left = BORDER;
307: pri->top = lpRect->top + BORDER;
308: pri->right = giDeltaX;
309: pri->bottom = giDeltaY;
310:
311: giColumn = 1;
312: }
313:
314:
315:
316: /******************************************************************************\
317: *
318: * FUNCTION: GetNextGraphicSlot
319: *
320: * INPUTS: pri - pointer to a RECTI
321: *
322: \******************************************************************************/
323:
324: void GetNextGraphicSlot (PRECTI pri)
325: {
326: if (++giColumn <= NUM_GRAPHICS_XSLOTS)
327: {
328: pri->left += giDeltaX;
329: pri->right += giDeltaX;
330: }
331: else
332: {
333: giColumn = 1;
334:
335: pri->left = BORDER;
336: pri->top += giDeltaY;
337: pri->right = giDeltaX;
338: pri->bottom += giDeltaY;
339: }
340: }
341:
342:
343:
344: /******************************************************************************\
345: *
346: * FUNCTION: DrawFonts
347: *
348: * INPUTS: hdc - device context to enumerate from & draw on
349: * pRect - pointer to bounding rect to draw fonts in
350: *
351: * LOCAL VARS: i, j - loop variables
352: * xText - starting x position to draw text
353: * yText - starting y position to draw text
354: * iMaxStrLen - length in pels of string to draw
355: *
356: \******************************************************************************/
357:
358: void DrawFonts (HDC hdc, LPRECT lpRect)
359: {
360: int i, j, xText, yText, iMaxStrLen = 0;
361: PARFONTS paf;
362:
363: paf = BuildFontList (hdc);
364:
365: xText = yText = 2;
366:
367: //
368: // set the appropriate text align mode depending on
369: // whether we're drawing from top down or bottom up
370: //
371:
372: if (giMapMode == MM_TEXT | giMapMode == MM_ANISOTROPIC)
373:
374: SetTextAlign (hdc, TA_TOP);
375:
376: else
377:
378: SetTextAlign (hdc, TA_BOTTOM);
379:
380: for (i = 0; i < nFaces; i++)
381: {
382: for (j = 0; j < (paf + i)->nFonts; j++)
383: {
384: HFONT hFont, hSaveFont;
385: SIZE size;
386: POINT LogPtExtent;
387:
388: LogPtExtent.x = lpRect->right;
389: LogPtExtent.y = lpRect->bottom;
390:
391: hFont = CreateFontIndirect ((paf + i)->lf + j);
392:
393: hSaveFont = SelectObject (hdc, hFont);
394:
395: TextOut (hdc, xText, yText, ((paf + i)->lf + j)->lfFaceName,
396: strlen(((paf + i)->lf + j)->lfFaceName));
397:
398: GetTextExtentPoint (hdc, ((paf + i)->lf + j)->lfFaceName,
399: strlen(((paf+i)->lf+j)->lfFaceName),
400: &size);
401: size.cx += 2;
402: iMaxStrLen = iMaxStrLen > (int)size.cx ? iMaxStrLen: (int) size.cx;
403:
404: if (!(i == (nFaces - 1) && j == ((paf + i)->nFonts - 1)))
405: {
406: TEXTMETRIC *pNextTM;
407:
408: pNextTM = j < ((paf+i)->nFonts-1) ?
409: (paf+i)->tm+j+1 : (paf+i+1)->tm;
410:
411: //
412: // add in the height of the face name we just drew
413: //
414:
415: yText += (int) ((paf + i)->tm + j)->tmHeight;
416:
417: //
418: // if the next facename will be drawn outside the bounding rect then
419: // start at first line of next column
420: //
421:
422: if (yText + (int) pNextTM->tmHeight > (int) LogPtExtent.y)
423: {
424: yText = 2;
425: xText += iMaxStrLen + 2;
426: iMaxStrLen = 0;
427: }
428: }
429:
430: SelectObject (hdc, hSaveFont);
431: DeleteObject (hFont);
432:
433: if (xText > (int) LogPtExtent.x)
434: {
435: if (GetDeviceCaps (hdc, TECHNOLOGY) & DT_RASDISPLAY)
436: {
437: //
438: // If we're drawing to the screen & have run out of
439: // room then tell user how many fonts there are left
440: // (that we haven't displayed)
441: //
442:
443: int k;
444: int iFontsLeft = (paf + i)->nFonts - j - 1;
445: char buf[40];
446: SIZE size;
447:
448:
449: for (k = i + 1; k < nFaces; k++)
450:
451: iFontsLeft += (paf + k)->nFonts;
452:
453: wsprintf (buf, "%ld more display fonts (not listed)",
454: iFontsLeft);
455:
456: GetTextExtentPoint (hdc, buf, strlen(buf), &size);
457:
458: if ((xText = lpRect->right - size.cx) < glcyMenu + 1)
459:
460: xText = glcyMenu/2 + 1;
461:
462: TextOut (hdc, xText, lpRect->bottom, buf, strlen(buf));
463:
464: goto done_enumfonts;
465: }
466:
467: else
468: {
469: //
470: // Else we're drawing to a printer & have filled up
471: // the first page. If there's any fonts left to draw
472: // then start a new page.
473: //
474:
475: if (!(i == nFaces - 1 && j == (paf + i)->nFonts - 1))
476: {
477: EndPage (hdc);
478: xText = yText = 2;
479: StartPage (hdc);
480: }
481: }
482: }
483: }
484: }
485:
486: done_enumfonts:
487:
488: FreeFontList (paf);
489: }
490:
491:
492:
493:
494: /* In the callback functions for the enumerations, there is a limited
495: * ability to pass in parameters. For that reason, declare the following
496: * global variables to be used by any of the call back functions.
497: *
498: * HDC hdcGlobal;
499: * PARFONTS parFontsGlobal;
500: * int iFace,jFont;
501: * int nFaces;
502: *
503: *
504: * General call structure:
505: *
506: * BuildFontList
507: * EnumFonts
508: * MyEnumCount
509: * LocalAlloc
510: * EnumFonts
511: * MyEnumFaces
512: * EnumFonts
513: * MyEnumCount
514: * LocalAlloc
515: * LocalAlloc
516: * LocalAlloc
517: * EnumFonts
518: * MyEnumCopy
519: */
520:
521:
522:
523: /******************************************************************************\
524: *
525: * FUNCTION: BuildFontList
526: *
527: * GLOBAL VARS: (see above)
528: *
529: \******************************************************************************/
530:
531: PARFONTS BuildFontList (HDC hdcIn)
532: {
533: nFaces = 0;
534:
535: hdcGlobal = hdcIn;
536:
537: //
538: // count the total number of face names.
539: //
540:
541: EnumFonts (hdcGlobal, NULL, (FONTENUMPROC)MyEnumCount, (LPARAM)&nFaces);
542:
543: //
544: // allocate the pointer to the array of PArFont structures.
545: //
546:
547: parFontsGlobal = (PARFONTS) LocalAlloc (LPTR, sizeof(ARFONTS) * (nFaces+1));
548:
549: //
550: // step through all fonts again. For each one fill a LOGFONT and
551: // a TEXTMETRIC stucture.
552: //
553:
554: iFace = 0;
555: EnumFonts (hdcGlobal, NULL, (FONTENUMPROC)MyEnumFaces, NULL);
556:
557: return parFontsGlobal;
558: }
559:
560:
561:
562: /******************************************************************************\
563: *
564: * FUNCTION: MyEnumFaces
565: *
566: * GLOBAL VARS: (see above)
567: *
568: \******************************************************************************/
569:
570: int CALLBACK MyEnumFaces (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
571: DWORD fFontType, LPVOID lpData)
572: {
573: int nFonts;
574:
575: nFonts = 0;
576: EnumFonts (hdcGlobal, lpLogFont->lfFaceName, (FONTENUMPROC)MyEnumCount,
577: (LPARAM)&nFonts);
578:
579: parFontsGlobal[iFace].lf = (LOGFONT *) LocalAlloc (LPTR,
580: sizeof(LOGFONT) *
581: nFonts);
582: parFontsGlobal[iFace].tm = (TEXTMETRIC *) LocalAlloc (LPTR,
583: sizeof(TEXTMETRIC) *
584: nFonts);
585: parFontsGlobal[iFace].Type = (int *) LocalAlloc (LPTR,
586: sizeof(int) *
587: nFonts);
588:
589: if ((parFontsGlobal[iFace].lf == NULL) ||
590: (parFontsGlobal[iFace].tm == NULL) ||
591: (parFontsGlobal[iFace].Type == NULL))
592: {
593: ErrMsgBox ("LocalAlloc failed", ERR_MOD_NAME);
594: return FALSE;
595: }
596:
597: parFontsGlobal[iFace].nFonts = nFonts;
598:
599: jFont = 0;
600: EnumFonts (hdcGlobal, lpLogFont->lfFaceName, (FONTENUMPROC)MyEnumCopy, NULL);
601:
602: iFace++;
603:
604: return TRUE;
605: }
606:
607:
608:
609: /******************************************************************************\
610: *
611: * FUNCTION: MyEnumCopy
612: *
613: * GLOBAL VARS: (see above)
614: *
615: \******************************************************************************/
616:
617: int CALLBACK MyEnumCopy (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
618: DWORD fFontType, LPVOID lpData)
619: {
620: LOGFONT *lplf;
621: TEXTMETRIC *lptm;
622: int *pType;
623:
624: lplf = parFontsGlobal[iFace].lf;
625: lptm = parFontsGlobal[iFace].tm;
626: pType = parFontsGlobal[iFace].Type;
627:
628: lplf[jFont] = *lpLogFont;
629: lptm[jFont] = *lpTEXTMETRICs;
630: pType[jFont] = fFontType;
631:
632: jFont++;
633: return TRUE;
634: }
635:
636:
637:
638: /******************************************************************************\
639: *
640: * FUNCTION: MyEnumCount
641: *
642: * GLOBAL VARS: (see above)
643: *
644: \******************************************************************************/
645:
646: int CALLBACK MyEnumCount (LPLOGFONT lpLogFont, LPTEXTMETRIC lpTEXTMETRICs,
647: DWORD fFontType, LPVOID lpData)
648: {
649: (*(LPINT)lpData)++;
650: return TRUE;
651: }
652:
653:
654:
655: /******************************************************************************\
656: *
657: * FUNCTION: FreeFontList
658: *
659: * INPUTS: paf - pointer to ARFONTS struct to free
660: *
661: \******************************************************************************/
662:
663: void FreeFontList (PARFONTS paf)
664: {
665: int i;
666:
667: for (i = 0; i < nFaces; i++)
668: {
669: LocalFree (LocalHandle ((LPSTR) ((paf + i)->lf )));
670: LocalFree (LocalHandle ((LPSTR) ((paf + i)->tm )));
671: LocalFree (LocalHandle ((LPSTR) ((paf + i)->Type)));
672: }
673: LocalFree (LocalHandle ((LPSTR) paf));
674: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.