|
|
1.1 root 1: #include <windows.h>
2: #include <string.h>
1.1.1.2 root 3: #include <math.h>
1.1 root 4:
1.1.1.2 root 5: #if defined (WIN32)
6: #define _MoveTo(hdc,x,y) MoveToEx(hdc,x,y,NULL)
7: #else
8: #define _MoveTo(hdc,x,y) MoveTo(hdc,x,y)
9: #endif
1.1 root 10:
1.1.1.2 root 11: // These are the 'exported' functions from this file:
12: void DrawAscii (HDC hdc, RECT *pRect, WORD direction);
13: void DrawGlyph (HDC hdc, RECT *pRect, BYTE glyph, HFONT hfont);
14: BYTE FindChar (HDC hdc, RECT *pRect, int x, int y);
1.1 root 15:
1.1.1.2 root 16: // A data structure that DrawAscii will use:
1.1 root 17: char ascii[]=
1.1.1.2 root 18: {
19: // Low Ascii:
20:
21: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
22: 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
23:
24: // Standard Ascii:
25:
26: ' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',',
27: '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
28: ':', ';', '<', '=', '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F',
29: 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
30: 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', '\\', ']', '^', '_', '`',
31: 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
32: 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
33: '{', '|', '}', '~', '',
34:
35: // High Ascii:
36:
37: '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
38: '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
39: '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
40: '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
41: '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
42: '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
43: '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
44: '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
45:
1.1.1.3 ! root 46: '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
! 47: '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
! 48: '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
! 49: '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
! 50: '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
! 51: '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
! 52: '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
! 53: '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
! 54:
! 55:
1.1.1.2 root 56: // End of the list:
57:
58: 000, 000};
1.1 root 59:
60: /* A function that the CharSet window will use to display the text */
1.1.1.2 root 61: void DrawAscii (HDC hdc, RECT *pRect, WORD direction)
62: {
63: BYTE *pch;
64: int h, w, incx, incy, width;
65: unsigned int wDisplay;
66: POINT pt;
67: TEXTMETRIC tm;
68: BOOL bLineMode = FALSE;
69:
70:
71: GetTextMetrics (hdc, &tm);
72: h = tm.tmHeight;
73: w = tm.tmMaxCharWidth;
74:
75: incx = 0;
76: incy = h;
77: pt.x = 0;
78: pt.y = 0;
79:
80: //
81: pt.y = tm.tmAscent + tm.tmExternalLeading;
82: //
83:
84: pch = &(ascii[tm.tmFirstChar]);
85: wDisplay = pRect->right -pRect->left;
86:
87: //
88: SetTextAlign (hdc, TA_BASELINE | TA_CENTER);
89: SetBkMode (hdc, TRANSPARENT);
90: //
91:
92: while (pch[0] && (pch[0]<=tm.tmLastChar)) {
93: #if defined (WIN32)
94: SIZE size;
95: GetTextExtentPoint (hdc, pch, 1, &size);
96: width = size.cx;
97: #else
98: width = LOWORD (GetTextExtent (hdc, pch, 1));
99: #endif
100: if ((unsigned)(pt.x + width) > wDisplay) {
101: pt.x = 0;
102: pt.y += incy;
103: }
104: TextOut (hdc, pt.x + (width/2), pt.y, pch, 1);
105: pt.x += width;
106: pch++;
107: }
108: return;
1.1 root 109:
1.1.1.2 root 110: direction;
111: }
112:
113: // Return the character that was drawn at the provided location
114: // This allows us to 'click' on a character, and determined what
115: // it was we actually clicked on.
116: BYTE FindChar (HDC hdc, RECT *pRect, int x, int y)
117: {
118: BYTE *pch;
119: int h, w, incx, incy, width;
120: unsigned int wDisplay;
121: POINT pt;
122: TEXTMETRIC tm;
123: BOOL bLineMode = FALSE;
124:
125:
126: GetTextMetrics (hdc, &tm);
127: h = tm.tmHeight;
128: w = tm.tmMaxCharWidth;
129:
130: incx = 0;
131: incy = h;
132: pt.x = 0;
133: pt.y = 0;
134:
135: pch = &(ascii[tm.tmFirstChar]);
136: wDisplay = pRect->right -pRect->left;
137:
138: while (pch[0] && (pch[0]<=tm.tmLastChar)) {
139: #if defined (WIN32)
140: SIZE size;
141: GetTextExtentPoint (hdc, pch, 1, &size);
142: width = size.cx;
143: #else
144: width = LOWORD (GetTextExtent (hdc, pch, 1));
145: #endif
146: if ((unsigned)(pt.x + width) > wDisplay) {
147: pt.x = 0;
148: pt.y += incy;
149: }
150: if ((x>=pt.x) && (x <=(pt.x+width)) && (y>=pt.y) && (y<=pt.y+incy)) return pch[0];
151: pt.x += width;
152: pch++;
153: }
154: return 0;
155: }
156:
157: // Essentially, a StretchBlt, but draws cicular pels.
158: BOOL CircleBlt (HDC hdcDest, int xDst, int yDst, int iWidthDst, int iHeightDst, HDC hdcSrc, int xSrc, int ySrc, int iWidthSrc, int iHeightSrc, DWORD dwROP)
159: {
160: int x, y, x1, y1, x2, y2;
161: DWORD rgb;
162: float fXUnit, fYUnit;
163: HBRUSH hbrush, hbrushOld;
164:
165: if (iWidthSrc != 0){
166: fXUnit = (float)iWidthDst / (float)iWidthSrc;
167: } else {
168: fXUnit = (float)iWidthDst;
169: }
170: if (iHeightSrc != 0) {
171: fYUnit = (float)iHeightDst / (float)iHeightSrc;
172: } else {
173: fYUnit = (float)iHeightDst;
174: }
175:
176: for (y=ySrc; y<(ySrc+iHeightSrc); y++) {
177: for (x=xSrc; x<(xSrc+iWidthSrc); x++) {
178:
179: rgb = GetPixel (hdcSrc, x, y);
180: if (rgb != -1 && rgb != 0x00FFFFFF) {
181: hbrush = CreateSolidBrush (rgb);
182: hbrushOld = SelectObject (hdcDest, hbrush);
183: x1 = xDst + (int)((x-xSrc)*fXUnit);
184: y1 = yDst + (int)((y-ySrc)*fYUnit);
185: x2 = xDst + (int)(((x-xSrc)+1)*fXUnit)+1;
186: y2 = yDst + (int)(((y-ySrc)+1)*fYUnit)+1;
187: Ellipse (hdcDest, x1, y1, x2, y2);
188: DeleteObject(SelectObject(hdcDest, hbrushOld));
189: }
190: }
191: }
1.1 root 192:
1.1.1.2 root 193: return TRUE;
194:
195: dwROP;
196: }
1.1 root 197:
1.1.1.2 root 198: double Radian(double ang)
199: {
200: return ang * (double)3.1415926535 / (double)180.0;
201: }
202:
203: void CalcRot (double x, double y, double ang, double* x1, double* y1)
204: {
205: ang = Radian(-ang);
206: *x1 = (x * cos(ang)) - (y * sin(ang));
207: *y1 = (x * sin(ang)) + (y * cos(ang));
208: }
209:
210: void DrawGlyph (HDC hdc, RECT *pRect, BYTE glyph, HFONT hfont)
211: {
212: TEXTMETRIC tm;
213: LOGFONT lf;
214: int wChar, h1, h2, w1, w2, x, y;
215: double xTL, yTL, xTR, yTR, xBL, yBL, xBR, yBR, xML, yML, xMR, yMR;
216: int cWidth, cExtentW, cExtentH;
217: int unit, margin;
218: RECT rect, rectChar;
219: HDC hdcMem;
220: HBITMAP hbitmap, hbitmapOld;
221: HFONT hfontOld, hfontTmp;
222: char szText[80];
223: double fAng, fWa, fWb, fHa, fHb, fHeight, fWidth;
224: BOOL bRotateable;
225: double fxOff, fyOff;
226: #if defined(TT_AVAILABLE)
227: ABC abc;
228: #endif
229:
230: GetTextMetrics (hdc, &tm);
231: hfontTmp = SelectObject (hdc, GetStockObject(SYSTEM_FONT));
232: GetObject (hfontTmp, sizeof(LOGFONT), &lf);
233:
234: // Some fields of 'lf' need to be whacked out depending on the type of
235: // font involved. For instance, lfEscapement should only be non-zero for
236: // rotatable fonts.
237: bRotateable = FALSE;
238: #if defined (TMPF_VECTOR)
239: bRotateable = (tm.tmPitchAndFamily & TMPF_VECTOR);
240: #endif
241: #if defined (TMPF_TRUETYPE)
242: bRotateable |= (tm.tmPitchAndFamily & TMPF_TRUETYPE);
243: #endif
244: if (!bRotateable) {
245: lf.lfEscapement = 0;
1.1 root 246: }
247:
1.1.1.2 root 248: SelectObject (hdc, hfontTmp);
249: GetCharWidth (hdc, glyph, glyph, &cWidth);
250:
251: #if defined (WIN32)
252: {
253: SIZE size;
254: GetTextExtentPoint (hdc, (LPSTR)&glyph, 1, &size);
255: cExtentW = size.cx;
256: cExtentH = size.cy;
257: }
258: #else
259: cExtentW = LOWORD (GetTextExtent (hdc, (LPSTR)&glyph, 1));
260: cExtentH = HIWORD (GetTextExtent (hdc, (LPSTR)&glyph, 1));
261: #endif
262:
263: wChar = max(cWidth, cExtentW);
264:
265: #if defined(TT_AVAILABLE)
266: if (GetCharABCWidths (hdc, (UINT)glyph, (UINT)glyph, &abc)) {
267: wChar = abc.abcA + abc.abcB + abc.abcC;
268: wChar = max(abc.abcA,0) + max (abc.abcB,0) + max (abc.abcC,0);
269: } else {
270: abc.abcA = 0;
271: abc.abcB = wChar;
272: abc.abcC = 0;
273: }
274: #endif
275:
276: // ****
277: // Lets figure out how large of a bitmap we need to draw this character into.
278: // This will take lfEscapement into account.
279:
280: // Turn the 'escapement' value into a valid angle
281: fAng = 90.0 - ((double)lf.lfEscapement/10.0);
282:
283: // We now need to calculate two values for height and width. These
284: // represent the bases of the triangles that are formed as the
285: // character cell rotates. Thus fWa+fWb is the 'width' of the space
286: // required by the given character at the current rotation.
287: // At 0, 90, 180, 270 and 360, one of the two values will be '0'.
288: fWa = (double)cExtentW * sin(Radian(fAng));
289: fHa = (double)cExtentW * sin(Radian((double)lf.lfEscapement/10.0));
290: fHb = (double)cExtentH * sin(Radian(fAng));
291: fWb = (double)cExtentH * sin(Radian((double)lf.lfEscapement/10.0));
292:
293: // This gives us a width/height of:
294: fHeight = fabs(fHa) + fabs(fHb);
295: fWidth = fabs(fWa) + fabs(fWb);
296: // ****
297:
298: h1 = pRect->bottom - pRect->top;
299: h2 = tm.tmHeight + tm.tmExternalLeading;
300: h2 = (int)fHeight;
301: if (h2 == 0) {
302: MessageBeep (0);
303: h2 = 10;
304: }
305:
306: w1 = pRect->right - pRect->left;
307: w2 = (int)fWidth;
308:
309: unit = (h1 / h2);
310:
311: margin = (h1 - (unit * h2)) / 2;
312: margin = 0;
313: // Define a rectangle that will enclose our drawing area
314: SetRect (&rect, 0, 0, wChar*unit, (tm.tmHeight*unit) + (tm.tmExternalLeading*unit));
315: OffsetRect (&rect, margin, margin);
316: // Define a rectangle that will define the bounding box of the character
317: SetRect (&rectChar, 0, 0, wChar*unit, tm.tmHeight*unit);
318: OffsetRect (&rectChar, margin, margin + (tm.tmExternalLeading*unit));
319:
320:
321: // ****
322: // These are floating point values.
323: SetRect (&rect, 0, 0, (int)(fWidth)*unit, ((int)(fHeight)*unit) + (tm.tmExternalLeading*unit));
324: OffsetRect (&rect, margin, margin);
325: // Define a rectangle that will define the bounding box of the character
326: SetRect (&rectChar, 0, 0, (int)(fWidth)*unit, ((int)(fHeight)*unit));
327: OffsetRect (&rectChar, margin, margin + (tm.tmExternalLeading*unit));
328:
329: // Calculate the points of the 'character cell'. This will take full
330: // rotation into consideration.
331: CalcRot (0, 0, (double)lf.lfEscapement/10.0, &xTL, &yTL);
332: CalcRot ((double)cExtentW, 0, (double)lf.lfEscapement/10.0, &xTR, &yTR);
333: CalcRot (0, (double)cExtentH, (double)lf.lfEscapement/10.0, &xBL, &yBL);
334: CalcRot ((double)cExtentW, (double)cExtentH, (double)lf.lfEscapement/10.0, &xBR, &yBR);
335: CalcRot (0, (double)tm.tmAscent, (double)lf.lfEscapement/10.0, &xML, &yML);
336: CalcRot ((double)cExtentW, (double)tm.tmAscent, (double)lf.lfEscapement/10.0, &xMR, &yMR);
337:
338: fxOff = min(xTL, min(xTR, min(xBL, xBR)));
339: fyOff = min(yTL, min(yTR, min(yBL, yBR)));
340:
341: // Draw a rectangle around the drawing limits of the character.
342: _MoveTo (hdc, (int)((xTL-fxOff)*(double)unit), (int)((yTL-fyOff)*(double)unit));
343: LineTo (hdc, (int)((xTR-fxOff)*(double)unit), (int)((yTR-fyOff)*(double)unit));
344: LineTo (hdc, (int)((xBR-fxOff)*(double)unit), (int)((yBR-fyOff)*(double)unit));
345: LineTo (hdc, (int)((xBL-fxOff)*(double)unit), (int)((yBL-fyOff)*(double)unit));
346: LineTo (hdc, (int)((xTL-fxOff)*(double)unit), (int)((yTL-fyOff)*(double)unit));
347:
348: // Draw the baseline, which indicates the advance width of the character
349: _MoveTo (hdc, (int)((xML-fxOff)*(double)unit), (int)((yML-fyOff)*(double)unit));
350: LineTo (hdc, (int)((xMR-fxOff)*(double)unit), (int)((yMR-fyOff)*(double)unit));
351:
352: hdcMem = CreateCompatibleDC (hdc);
353: if (hdcMem) {
354: hbitmap = CreateCompatibleBitmap (hdc, (int)(fWidth), (int)(fHeight));
355: if (hbitmap) {
356: hbitmapOld = SelectObject (hdcMem, hbitmap);
357: BitBlt (hdcMem, 0, 0, (int)(fWidth), (int)(fHeight), NULL, 0, 0, WHITENESS);
358: hfontOld = SelectObject (hdcMem, hfont);
359:
360: SetTextAlign (hdcMem, TA_LEFT | TA_BASELINE);
361: if (TextOut (hdcMem, (int)(xML-fxOff), (int)(yML-fyOff), (LPSTR)&glyph, 1)) {
362:
363:
364: /*
365: // Just for debugging, lets mark some special pixels
366: SetPixel (hdcMem, (int)(xML-fxOff), (int)(yML-fyOff), 0x808080); // Base Lft
367: SetPixel (hdcMem, (int)(xTL-fxOff), (int)(yTL-fyOff), 0x808080); // Top Left
368: SetPixel (hdcMem, (int)(xTR-fxOff), (int)(yTR-fyOff), 0x808080); // Top Right
369: SetPixel (hdcMem, (int)(xBL-fxOff), (int)(yBL-fyOff), 0x808080); // Btm Left
370: SetPixel (hdcMem, (int)(xBR-fxOff), (int)(yBR-fyOff), 0x808080); // Btm Right
371: SetPixel (hdcMem, (int)(xML-fxOff), (int)(yML-fyOff), 0x808080); // Base Lft
372: SetPixel (hdcMem, (int)(xMR-fxOff), (int)(yMR-fyOff), 0x808080); // Base Rt
373: */
374:
375: CircleBlt(hdc, margin, margin,
376: rectChar.right-rectChar.left, rectChar.bottom-rectChar.top,
377: hdcMem, 0, 0, (int)(fWidth), (int)(fHeight), SRCPAINT);
378:
379: } else {
380: MessageBox (GetFocus(),
381: "Unable to perform TextOut", "DisplayGlyph", MB_OK);
382: }
383: SelectObject (hdcMem, hbitmapOld);
384: SelectObject (hdcMem, hfontOld);
385: DeleteObject (hbitmap);
386: } else {
387: MessageBox (GetFocus(), "Unable To create Bitmap", "DisplayGlyph", MB_OK);
388: }
389: DeleteDC (hdcMem);
390: } else {
391: MessageBox (GetFocus(), "Unable to create DC", "DisplayGlyph", MB_OK);
392: }
393:
394: hfontTmp = CreateFont(14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VARIABLE_PITCH | FF_SWISS, "");
395:
396: if (hfontTmp) {
397: hfontOld = SelectObject (hdc, hfontTmp);
398: x = rect.right + 10;
399: GetTextMetrics (hdc, &tm);
400:
401: y = tm.tmHeight + tm.tmExternalLeading;
402:
403: y += tm.tmHeight + tm.tmExternalLeading;
404: wsprintf (szText, "Character = '%c' %u (0x%X)", (char)glyph, (int)glyph, (int)glyph);
405: TextOut (hdc, x, y, szText, lstrlen(szText));
406:
407: y += tm.tmHeight + tm.tmExternalLeading;
408: wsprintf (szText, "CharWidth = %i", cWidth);
409: TextOut (hdc, x, y, szText, lstrlen(szText));
410:
411: // ABC Width - Eventually, I want to 'draw' this into the character
412: // cell, but for now, this at least makes the information easily
413: // available:
414: #if defined (TT_AVAILABLE)
415: y += tm.tmHeight + tm.tmExternalLeading;
416: wsprintf (szText, "A|B|C = %i | %u | %i", abc.abcA, abc.abcB, abc.abcC);
417: TextOut (hdc, x, y, szText, lstrlen(szText));
418: #endif
419:
420: y += tm.tmHeight + tm.tmExternalLeading;
421: wsprintf (szText, "CharExtentW = %i", cExtentW);
422: TextOut (hdc, x, y, szText, lstrlen(szText));
423:
424: y += tm.tmHeight + tm.tmExternalLeading;
425: wsprintf (szText, "CharExtentH = %i", cExtentH);
426: TextOut (hdc, x, y, szText, lstrlen(szText));
427:
428: // These are for some values I was using to debug the character
429: // cell rotation calculation:
430:
431: //y += tm.tmHeight + tm.tmExternalLeading;
432: //wsprintf (szText, "(%i,%i) : (%i,%i) [%i]", (int)xTL, (int)yTL, (int)xTR, (int)yTR,(int)(((double)lf.lfEscapement/10.0)*10));
433: //TextOut (hdc, x, y, szText, lstrlen(szText));
434:
435: //y += tm.tmHeight + tm.tmExternalLeading;
436: //wsprintf (szText, "(%i,%i) : (%i,%i)", (int)xML, (int)yML, (int)xMR, (int)yMR);
437: //TextOut (hdc, x, y, szText, lstrlen(szText));
438:
439: //y += tm.tmHeight + tm.tmExternalLeading;
440: //wsprintf (szText, "(%i,%i) : (%i,%i)", (int)xBL, (int)yBL, (int)xBR, (int)yBR);
441: //TextOut (hdc, x, y, szText, lstrlen(szText));
442:
443: //y += tm.tmHeight + tm.tmExternalLeading;
444: //wsprintf (szText, "fAng = %i", (int)(fAng));
445: //TextOut (hdc, x, y, szText, lstrlen(szText));
446:
447: //y += tm.tmHeight + tm.tmExternalLeading;
448: //wsprintf (szText, "fHa = %i", (int)(fHa));
449: //TextOut (hdc, x, y, szText, lstrlen(szText));
450:
451: //y += tm.tmHeight + tm.tmExternalLeading;
452: //wsprintf (szText, "fHb = %i", (int)(fHb));
453: //TextOut (hdc, x, y, szText, lstrlen(szText));
454:
455: //y += tm.tmHeight + tm.tmExternalLeading;
456: //wsprintf (szText, "fWa = %i", (int)(fWa));
457: //TextOut (hdc, x, y, szText, lstrlen(szText));
458:
459: //y += tm.tmHeight + tm.tmExternalLeading;
460: //wsprintf (szText, "fWb = %i", (int)(fWb));
461: //TextOut (hdc, x, y, szText, lstrlen(szText));
462:
463: //y += tm.tmHeight + tm.tmExternalLeading;
464: //wsprintf (szText, "fWd = %i", (int)(fWd));
465: //TextOut (hdc, x, y, szText, lstrlen(szText));
466:
467: //y += tm.tmHeight + tm.tmExternalLeading;
468: //wsprintf (szText, "fHd = %i", (int)(fHd));
469: //TextOut (hdc, x, y, szText, lstrlen(szText));
470:
471: //y += tm.tmHeight + tm.tmExternalLeading;
472: //wsprintf (szText, "fHeight = %i", (int)(fHeight));
473: //TextOut (hdc, x, y, szText, lstrlen(szText));
474:
475: //y += tm.tmHeight + tm.tmExternalLeading;
476: //wsprintf (szText, "fWidth = %i", (int)(fWidth));
477: //TextOut (hdc, x, y, szText, lstrlen(szText));
478:
479: SelectObject (hdc, hfontOld);
480: DeleteObject (hfontTmp);
481: }
1.1 root 482: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.