|
|
1.1 root 1: #include "windows.h"
2: #include <windowsx.h>
3: #include "fontedit.h"
4: #include "fcntl.h"
5: #include "memory.h"
6: #include "stdio.h"
7: #include "commdlg.h"
8:
9:
10: /****************************************************************************/
11: /* Shared Variables */
12: /****************************************************************************/
13: extern CHAR *PASCAL VerifyHeaderContents();/* checks integrity of header */
14:
15: extern FontHeaderType font; /* Structure of Font File Header */
16: extern LONG lSizeOfOldGlyph20; /* Old packed 2.0 glyph info size. */
17: extern LONG lSizeOfOldGlyph30; /* Old packed 3.0 glyph info size. */
18: extern LONG lSizeOfOldFontHeader; /* Old packed font header size. */
19: extern LONG lSizeOfOldFontHeader30; /* Old 3.0 packed font header size. */
20: extern CHAR szFaceName[]; /* Face Name of Font */
21: extern DWORD offsets[]; /* Offsets Table */
22:
23: extern BOOL fReadOnly;
24: extern BOOL fChanged; /* Note if we did anything */
25: extern BOOL fLoaded; /* Set if a font is loaded */
26: extern INT iFontFormatPrev; /* Set to the id of prev.font format */
27: extern INT iFontFormat; /* Set to the id of current font format */
28:
29: extern HWND hFont; /* Handle to Show window */
30: extern HWND hBox; /* Handle to Edit Window */
31: extern HDC hMemDC; /* Handle to Memory Display Context */
32: extern HBITMAP hBitmap; /* Handle to our work bit map */
33: extern CHAR matBox [wBoxLim] [kBoxLim]; /* array to hold Box */
34:
35: extern CHAR *vrgsz[]; /* string table */
36: extern OFSTRUCT ofstrFile;
37: extern BOOL NewFile; /* flag indicating if file was opened
38: by selecting NEW on menu */
39: FontHeaderType fontBuffer; /* temporary buffer of Font File Header */
40: WORD cHeader, cTable;
41: HFILE nNewFile; /* NT file handle */
42:
43:
44: /****************************************************************************/
45: /* Local Variables */
46: /****************************************************************************/
47:
48: DWORD Proport(DWORD, DWORD, DWORD, DWORD); /* Reproportions a value */
49:
50: CHAR *lpFontBody = NULL; /* Pointer to Font Body */
51: CHAR *lpWork = NULL; /* Pointer to Work Area */
52: HDC hNewMemDC;
53: HDC hBoxMemDC;
54: HBITMAP hNewBitmap;
55: HBITMAP hBoxBitmap;
56: HCURSOR hOldCursor = NULL; /* Holds Arrow while we show Hourglass */
57: HCURSOR hHourGlass = NULL;
58: DWORD oldMode; /* For StretchBltMode */
59: BYTE *lp1, *lp2; /* Pointers to bitmaps in format N */
60:
61: FontHeader30 font30;
62:
63: #define ALPHA_CNT 26
64: #define TOTAL_WEIGHTS 1000
65: #define FSF_FIXED 0x0001
66: #define FSF_PROPORTIONAL 0x0002
67:
68: SHORT widthweights[ALPHA_CNT + 1] =
69: {
70: 64, /* a
71: 14, /* b */
72: 27, /* c */
73: 35, /* d */
74: 100, /* e */
75: 20, /* f */
76: 14, /* g */
77: 42, /* h */
78: 63, /* i */
79: 3 , /* j */
80: 6 , /* k */
81: 35, /* l */
82: 20, /* m */
83: 56, /* n */
84: 56, /* o */
85: 17, /* p */
86: 4 , /* q */
87: 49, /* r */
88: 56, /* s */
89: 71, /* t */
90: 31, /* u */
91: 10, /* v */
92: 18, /* w */
93: 3 , /* x */
94: 18, /* y */
95: 2 , /* z */
96: 166, /* space, must be last, to use with the following
97: code */
98: };
99:
100: /****************************************************************************/
101: /* Local Functions */
102: /****************************************************************************/
103:
104: VOID NewAverage(VOID);
105: BOOL GetNewMap(DWORD, DWORD);
106: VOID UseNewMap(VOID);
107: VOID ShrinkFont(DWORD, DWORD);
108:
109: /****************************************************************************
110: * WORD ConvertToBitmapFormat(width, phase, height)
111: *
112: * purpose : Takes a part of the font file and converts it to a string of
113: * bytes for a single scan of bitmap for a character.
114: *
115: * params : WORD width : width of the character in pixels(bits)
116: * WORD phase : current deviation from byte alignment (pixels)
117: * WORD height: height of character(pixels)
118: *
119: * returns : WORD phase : new deviation from byte alignment (pixels)
120: *
121: * side effects : modifies pointers lp1 and lp2 (pointing to work space and
122: * font body respectively)
123: *
124: ****************************************************************************/
125: DWORD PASCAL
126: ConvertToBitmapFormat(
127: DWORD width, /* width of the character in pixels(bits) */
128: DWORD phase, /* current deviation from byte alignment (pixels) */
129: DWORD height /* height of character(pixels) */
130: )
131: {
132: INT w;
133: WORD j;
134:
135: /* in the font file format characters are stored consecutively in
136: column-major ordering (columns of char 1 followed by columns of char
137: 2 ... etc.). lp2 points to start of columns of current character.
138: lp1 points to start of row of bitmap for character. */
139:
140: for (w = width; w > 0; w -= 8){
141: if (phase == 0){
142: /* easy case */
143: *lp1++ = *lp2;
144:
145: if (w < 8)
146: phase = w;
147: }
148: else{
149:
150: --lp1;
151: j = (WORD)*lp1;
152: j <<= 8;
153: j |= (((WORD)*lp2) << (8 - phase));
154: *lp1++ = (BYTE)(j >> 8);
155: *lp1++ = (BYTE)j;
156: if (w < 8){
157: phase += w;
158: if (phase <= 8)
159: lp1--; /* back up pointer */
160: phase &= 7;
161: }
162: }
163: lp2 += height; /* move to next column */
164: }
165: return phase;
166: }
167:
168: /****************************************************************************
169: * char * VerifyTableContents()
170: *
171: * purpose : scan the offsets table of file just read and check if
172: * width and offsets lie within limits
173: *
174: * params : none
175: *
176: * returns : char * szError : ptr to Error message if table not OK
177: * NULL otherwise
178: *
179: * side effects : none
180: *
181: ****************************************************************************/
182: CHAR * PASCAL
183: VerifyTableContents(
184: VOID
185: )
186: {
187: PBYTE pjGlyphData;
188: GLYPHINFO_20 gi2T20; /* temp ptr to a 2.0 style table*/
189: GLYPHINFO_30 gi3T30; /* temp ptr to a 2.0 style table*/
190: INT i;
191:
192: /* separate loops written for the 2.0 and 3.0 font processing because
193: a single loop would involve too many checks (of font type) within
194: the loop and slow down processing */
195: if (iFontFormat == ID_FORMAT2){
196: pjGlyphData = (lpFontBody +1);
197:
198: /* view table as 2.0 table */
199:
200: /* check that each and every width and offset lie within limits */
201:
202: for (i=0; i < (fontBuffer.LastChar - fontBuffer.FirstChar + 1); i++) {
203:
204: vGlyphInfo20FromBuffer (pjGlyphData, &gi2T20);
205:
206: if (gi2T20.GIwidth > 64)
207: return vszTableWidthsBad;
208:
209: if ((gi2T20.GIoffset > (UINT)WORD_LIMIT) ||
210: (gi2T20.GIoffset < 0) )
211: return vszTableOffsetsBad;
212:
213: pjGlyphData += lSizeOfOldGlyph20;
214: }
215: }
216: else{
217:
218: pjGlyphData = lpFontBody;
219:
220: /* view table as 3.0 table */
221: /* check that each and every width and offset lie within limits */
222:
223: for (i=0; i< (fontBuffer.LastChar - fontBuffer.FirstChar +1); i++) {
224:
225: vGlyphInfo30FromBuffer (pjGlyphData, &gi3T30);
226:
227: if (gi3T30.GIwidth > 64)
228: return vszTableWidthsBad;
229:
230: if (gi3T30.GIoffset < (DWORD)0)
231: return vszTableOffsetsBad;
232:
233: pjGlyphData += lSizeOfOldGlyph30;
234: }
235: }
236: return NULL;
237: }
238:
239: /****************************************************************************
240: * char * FontLoad()
241: *
242: * purpose: reads in the specified font file and creates a work bitmap for
243: * the editor. Also creates a local bitmap-offset table for easy
244: * access to the characters in the bitmap
245: *
246: * params : pszFileName - File Name to open.
247: *
248: * returns: ptr to NULL string if Open goes off OK
249: * ptr to error message string otherwise
250: *
251: * side effects: lots
252: *
253: ****************************************************************************/
254: CHAR *
255: FontLoad(
256: CHAR *pszFileName,
257: OFSTRUCT *pofsReOpenInfo
258: )
259: {
260:
261: CHAR *lpFontBodySav = NULL; /* local pointer to font body */
262: DWORD len, fontlen; /* length of font body (bytes)*/
263: UINT i;
264: INT mf; /* menu function ID */
265: DWORD iWorkLen; /* length of work area (bytes) */
266: HDC hDC;
267: CHAR * pszError; /* error msg if header is messed up */
268:
269: DWORD row, height, width,phase;
270: DWORD offset;
271: GLYPHINFO_20 gi2GlyphTable20; /* Pointer into 2.0 style offsets table */
272: GLYPHINFO_30 gi3GlyphTable30; /* Pointer into 3.0 style offsets table */
273: PBYTE pjGlyphData; /* Pointer to Glyph information buffer. */
274:
275: BYTE cDummy [CCHEXTRA]; /* dummy buffer for unneeded 3.0 header
276: * info
277: */
278:
279: /* Put up an hourglass ... this may take a while */
280: if (!hHourGlass)
281: hHourGlass = LoadCursor(NULL, IDC_WAIT); /* Get Hourglass */
282: hOldCursor = SetCursor(hHourGlass); /* Show hourglass */
283:
284: /* open file for read. */
285: nNewFile = (HFILE)OpenFile (pszFileName, pofsReOpenInfo, OF_READ);
286:
287: if (nNewFile < 0) {
288:
289: return vszErrorOpeningFile;
290: }
291:
292: //- ReadFile: Here is where we need to make some adjustments in order to
293: //- read the file in to a new DWORD aligned format.
294: {
295: BYTE jBuffer [200];
296:
297:
298: /* Read the header */
299: if (_lread ((HFILE) nNewFile, (LPSTR)&jBuffer, lSizeOfOldFontHeader) !=
300: (UINT)lSizeOfOldFontHeader) {
301:
302: _lclose((HFILE)nNewFile);
303: return vszErrorReadingHdr;
304: }
305:
306: //
307: // Call conversion routine to give us a properly aligned buffer.
308: //
309:
310: vFontStructFromBuffer (
311: (PBYTE)&jBuffer,
312: &fontBuffer
313: );
314:
315: }
316:
317: /* Check the version number -- make sure it's a font */
318: switch (fontBuffer.Version)
319: {
320: case 0x200:
321: iFontFormat = ID_FORMAT2;
322: break;
323: case 0x300: /* added 1/19/88 */
324: iFontFormat = ID_FORMAT3;
325: /* read in the extra fields into a dummy buffer ... they don't
326: * mean anything to us at this stage.
327: */
328: if ((_lread((HFILE)nNewFile, (LPSTR)cDummy, CCHEXTRA))
329: != CCHEXTRA){
330: _lclose((HFILE)nNewFile);
331: return vszErrorReadingHdr;
332: }
333:
334: break;
335: default: /* Anything else -- toughies */
336: _lclose((HFILE)nNewFile);
337: return vszUnknownFormat;
338: }
339:
340: /* check if contents of font header are sensible. If not,
341: give an error message and quit */
342:
343: if ((pszError = VerifyHeaderContents()) != NULL) {
344:
345: _lclose((HFILE)nNewFile);
346: return pszError;
347: }
348:
349: /* Ready to load -- Check if we will be overwriting */
350: if (fLoaded)
351: {
352: DeleteGlobalBitmap();
353: fLoaded = FALSE;
354: }
355:
356: /* Allocate space for font body and Face Name and read them in */
357: len= (fontBuffer.Size - lSizeOfOldFontHeader); /* Compute size */
358:
359: if ((lpFontBody = (LPSTR)GlobalAlloc(GMEM_ZEROINIT, (LONG)len)) == 0) {
360:
361: _lclose((HFILE)nNewFile);
362: return vszNotEnoughMem; /* Get Handle to space */
363: }
364:
365: if (iFontFormat == ID_FORMAT3)
366: fontlen = len - CCHEXTRA;
367: else
368: fontlen = len;
369:
370: lpFontBodySav = lpFontBody; /* save ptr to font body */
371: while (fontlen >= (DWORD)SEGMENT_SIZE) {
372:
373: /* file read method if font file size is 64k bytes or greater.
374: file is read in in chunks of 65536 (SEGMENT_SIZE), taking care to
375: position buffer ptr at 64k boundary each time */
376:
377: /* First read in the maximum number of bytes _lread can read (65534) */
378: if ((_lread((HFILE)nNewFile, lpFontBodySav, WORD_LIMIT)) == WORD_LIMIT) {
379:
380: lpFontBodySav += WORD_LIMIT; /* buffer ptr moved up by 64k bytes */
381: fontlen -= WORD_LIMIT; /* fontlen = no of bytes left to read */
382:
383: } else {
384:
385: GlobalFree (lpFontBody);
386: _lclose((HFILE)nNewFile);
387: return vszErrorReadingBody;
388: }
389:
390: /* read in an additional two bytes to reach end of segment */
391: if ((_lread((HFILE)nNewFile, lpFontBodySav, 2)) == 2) {
392:
393: lpFontBodySav += 2; /* buffer ptr moved up by 2 bytes */
394: fontlen -= 2; /* fontlen = no of bytes left to read */
395:
396: } else {
397:
398: GlobalFree (lpFontBody);
399: _lclose((HFILE)nNewFile);
400: return vszErrorReadingBody;
401: }
402: }
403:
404: /* read the partially filled segment */
405: if ((_lread((HFILE)nNewFile, lpFontBodySav, (DWORD)fontlen)) != (UINT) fontlen) {
406:
407: GlobalFree (lpFontBody);
408: _lclose((HFILE)nNewFile);
409: return vszErrorReadingBody;
410: }
411:
412: /* Close the file */
413: _lclose((HFILE)nNewFile);
414:
415: /* check if the offset table entries are within allowable limits.
416: If not give an error message, clean up and quit */
417: if ((pszError = VerifyTableContents()) != NULL) {
418:
419: GlobalFree (lpFontBody);
420: return pszError;
421: }
422:
423: /* now that everything has been checked, move buffer to font */
424: font = fontBuffer;
425:
426: /* Make local copies of FaceName and Device Name */
427: if (font.Face){
428:
429: lstrcpy((LPSTR)szFaceName, lpFontBody + font.Face -
430: (iFontFormat == ID_FORMAT2 ?
431: lSizeOfOldFontHeader :
432: lSizeOfOldFontHeader30-1));
433: } else {
434:
435: lstrcpy((LPSTR)szFaceName, (LPSTR)"");
436: }
437:
438: for (i = 0; i <= 256; i++) /* Zero offsets Table for below */
439: offsets[i] = 0;
440:
441: /* compute work space needed if a 3.0 file. This has to be done since
442: 3.0 files are compressed versions of 2.0 files and may need a
443: work bitmap bigger than the actual font body size */
444:
445: if (iFontFormat == ID_FORMAT3) {
446:
447: cTable = (WORD) (6 * (font.LastChar - font.FirstChar + 2));
448: iWorkLen = 0;
449:
450: pjGlyphData = lpFontBody;
451:
452: /* work bitmap size = sum of sizes of all characters in font */
453:
454: for (i = font.FirstChar; i <= font.LastChar; i++) {
455:
456: vGlyphInfo30FromBuffer (pjGlyphData, &gi3GlyphTable30);
457:
458: iWorkLen += ((gi3GlyphTable30.GIwidth +7) >> 3) * font.PixHeight;
459:
460: pjGlyphData += lSizeOfOldGlyph30;
461: }
462:
463: } else { /* 2.0 file */
464:
465: cTable = (WORD)(4 * (font.LastChar - font.FirstChar + 2));
466: /* compute table length */
467: iWorkLen = len; /* work space for a 2.0 file is the same as the
468: length of the font body */
469: }
470:
471: //- Add some extra space for dword alignment.
472: iWorkLen += (font.PixHeight * sizeof (DWORD));
473: /* Get work space */
474:
475: if ((lpWork = (LPSTR)GlobalAlloc (GMEM_ZEROINIT, (LONG)iWorkLen)) == 0) {
476:
477: GlobalFree (lpFontBody);
478: return vszNotEnoughMem;
479: }
480:
481: lp1 = lpWork;
482:
483: height = (DWORD) font.PixHeight;
484: offset = 0;
485: /* put the font file into bitmap format */
486: if (iFontFormat == ID_FORMAT2){ /* table in 2.0 format */
487: for (row = 0; row < height; row++){
488:
489: /* view table as a 2.0 style table */
490: pjGlyphData = lpFontBody + 1;
491:
492: phase = 0;
493:
494: for (i = 0; i < (UINT)(font.LastChar - font.FirstChar + 1); i++) {
495:
496: vGlyphInfo20FromBuffer (pjGlyphData, &gi2GlyphTable20);
497:
498: width = (DWORD) gi2GlyphTable20.GIwidth;
499:
500: /* size of each table element = 4bytes */
501: lp2 = lpFontBody + (gi2GlyphTable20.GIoffset -
502: lSizeOfOldFontHeader) + row;
503:
504: pjGlyphData += lSizeOfOldGlyph20;
505:
506: /* offset ends up as the sum of the widths */
507: if (row == 0) /* Once is enough */
508: offsets[i + font.FirstChar + 1] = offset += width;
509:
510: /* create a single scan of bitmap for character */
511: phase = ConvertToBitmapFormat (width, phase, height);
512: }
513: if ((lp1 - lpWork) & 1)
514: *lp1++ = 0; /* Round lp1 up to Word Boundary */
515: #ifdef DWORDROUND
516: if ((lp1 - lpWork) & 2) {
517: *lp1++ = 0; /* Round lp1 up to DWord Boundary */
518: *lp1++ = 0; /* Round lp1 up to DWord Boundary */
519: }
520: #endif
521: //if (((offset + 7) >> 3) & 1)
522: //*lp1++ = 0; /* Round lp1 up to Word Boundary */
523: //if (((offset + 7) >> 3) & 2) {
524: //*lp1++ = 0; /* Round lp1 up to DWord Boundary */
525: //*lp1++ = 0; /* Round lp1 up to DWord Boundary */
526: //}
527: }
528: }
529: /* separate loops written for the 2.0 and 3.0 font processing because
530: a single loop would involve too many checks (of font type) within
531: the loop and slow down processing */
532: else { /* table in 3.0 format */
533:
534: for (row = 0; row < height; row++){
535:
536: phase = 0;
537: /* view table as a 3.0 style table */
538: pjGlyphData = lpFontBody;
539:
540: for (i = 0; i < (UINT)(font.LastChar - font.FirstChar + 1); i++) {
541:
542: vGlyphInfo30FromBuffer (pjGlyphData, &gi3GlyphTable30);
543:
544: width = gi3GlyphTable30.GIwidth;
545:
546: /* size of each table element = 6bytes */
547: lp2 = lpFontBody + (gi3GlyphTable30.GIoffset -
548: lSizeOfOldFontHeader30 +1) + row;
549:
550: pjGlyphData += lSizeOfOldGlyph30;
551:
552: /* offset ends up as the sum of the widths */
553: if (row == 0) /* Once is enough */
554: offsets[i + font.FirstChar + 1] = offset += width;
555:
556: /* create a single scan of bitmap for character */
557: phase = ConvertToBitmapFormat (width, phase, height);
558: }
559: if ((lp1 - lpWork) & 1)
560: *lp1++ = 0; /* Round lp1 up to Word Boundary */
561: #ifdef DWORDROUND
562: if ((lp1 - lpWork) & 2) {
563: *lp1++ = 0; /* Round lp1 up to DWord Boundary */
564: *lp1++ = 0; /* Round lp1 up to DWord Boundary */
565: }
566: #endif
567: }
568: }
569: font.WidthBytes = (WORD) (((offset + 15) >> 4) << 1);
570: /* fixup NEWFON error */
571:
572: GlobalFree(lpFontBody);
573: lpFontBody = lpWork; /* So that below we free the other buffer */
574: /* Create a WINDOWS bitmap to move the font definition bits into */
575:
576: hDC = GetDC (hFont); /* DC to be compatible with */
577: hBitmap = CreateBitmap(
578: (INT)font.WidthBytes << 3, /* Width of font in pixels */
579: (INT)font.PixHeight,
580: 1, 1, (LPBYTE)NULL);
581: hMemDC = CreateCompatibleDC(hDC); /* Create a DC */
582: SelectObject(hMemDC, hBitmap); /* Relate the two of them */
583: ReleaseDC(hFont, hDC); /* Done with font DC */
584:
585: /* Move the bits in */
586: SetBitmapBits(hBitmap,
587: (DWORD)font.WidthBytes * (DWORD)font.PixHeight,(CHAR *)lpWork);
588:
589: /* Free up the space we loaded the file into */
590: GlobalFree(lpFontBody);
591: fLoaded = TRUE;
592: {
593: HMENU hMenu;
594:
595: hMenu = GetMenu(hBox); /* Gray menu if no clipboard bitmap */
596: mf = (font.Family & 1) ? MF_ENABLED : MF_GRAYED;
597: EnableMenuItem(hMenu, FONT_SAVE, MF_ENABLED);
598: EnableMenuItem(hMenu, FONT_SAVEAS, MF_ENABLED);
599: EnableMenuItem(hMenu, 1, MF_BYPOSITION | MF_ENABLED);
600: EnableMenuItem(hMenu, 2, MF_BYPOSITION | MF_ENABLED);
601: EnableMenuItem(hMenu, 3, MF_BYPOSITION | MF_ENABLED);
602: EnableMenuItem(hMenu, 4, MF_BYPOSITION | mf);
603: EnableMenuItem(hMenu, 5, MF_BYPOSITION | MF_ENABLED);
604: EnableMenuItem(hMenu, 6, MF_BYPOSITION | MF_ENABLED);
605: DrawMenuBar(hBox);
606: }
607: SetCursor(hOldCursor); /* Restore regular cursor */
608: return "";
609: }
610:
611: /**************************************
612: * compares nBytes bytes of s1 and s2 *
613: **************************************/
614: BOOL
615: ByteCompare (
616: CHAR *s1,
617: CHAR *s2,
618: DWORD nBytes
619: )
620: {
621: for ( ; nBytes > 0; nBytes--)
622: if (*s1++ != *s2++)
623: return FALSE;
624: return TRUE;
625: }
626:
627: /***********************************
628: * copies nBytes bytes of s2 to s1 *
629: ***********************************/
630: BOOL
631: ByteCopy(
632: CHAR *s1,
633: CHAR *s2,
634: LONG nBytes
635: )
636: {
637: for ( ; nBytes > 0; nBytes--)
638: *s1++ = *s2++;
639: return TRUE;
640: }
641:
642: /****************************************************************************
643: * VOID ConvertToFileFormat(width, phase, height)
644: *
645: * purpose : Takes a part of the bitmap (corresponding to a single character)
646: * and converts it to a string of bytes in the font file format
647: *
648: * params : WORD width : width of the character in pixels(bits)
649: * WORD phase : current deviation from byte alignment (pixels)
650: * WORD height: height of character(pixels)
651: *
652: * returns: WORD phase : new deviation from byte alignment (pixels)
653: *
654: * side effects : modifies pointers lp1 and lp2 (pointing to font body and work
655: * space respectively)
656: *
657: ****************************************************************************/
658: DWORD PASCAL
659: ConvertToFileFormat(
660: DWORD width,
661: DWORD phase,
662: DWORD height
663: )
664: {
665: INT w;
666:
667: for (w = width; w > 0; w -= 8){ /* for each byte of font */
668: if (phase == 0){ /* easy case */
669:
670: BYTE b;
671:
672: b = *lp1++;
673: if (w < 8){
674:
675: phase = (DWORD) w;
676: b >>= 8 - w; /* Clear left side bits */
677: b <<= 8 - w;
678: }
679: *lp2 = b;
680: }
681: else{
682:
683: DWORD j;
684:
685: lp1--; /* Re-read byte prevously read */
686: //j = (DWORD) ((BYTE)*lp1++ << 8) | ((BYTE)*lp1++);
687: j = (DWORD)((BYTE)*lp1++ << 8);
688: j |= (DWORD) ((BYTE)*lp1++);
689: if (w < 8){
690:
691: j >>= 16 - phase - (w & 7); /* shove it right */
692: j <<= 8 - (w & 7); /* Left justify in low byte */
693: phase += (DWORD) w;
694: if (phase <= 8)
695: lp1--; /* back up pointer */
696: phase &= 7;
697: }
698: else
699: j >>= 8 - phase;
700: *lp2 = (BYTE)j;
701: }
702: lp2 += height; /* move to next column */
703: }
704: return phase;
705: }
706:
707: /****************************************************************************
708: * char * FontSave()
709: *
710: * purpose: saves the work bitmap in the required font file format (2.0 or
711: * 3.0 and cleans up
712: *
713: * params : none
714: *
715: * returns: ptr to a NULL string if Save goes off OK
716: * ptr to error message string otherwise
717: *
718: * side effects: lots
719: *
720: ****************************************************************************/
721:
722: CHAR *
723: FontSave(
724: CHAR *pszFileName,
725: OFSTRUCT *pofsReOpenInfo
726: )
727: {
728: DWORD bytecount; /* number of bytes returned by lwrite */
729: DWORD size; /* total size of font */
730:
731: WORD height, row;
732: DWORD i, fontlen;
733: DWORD cBody, cFont,cFontsav, cFace;
734: CHAR *lpFont; /* ponter to font body */
735: CHAR * sz;
736: DWORD iMax;
737: WORD widthsav;
738: PBYTE pjGlyphData;
739: PBYTE pjGlyphSave;
740: GLYPHINFO_20 gi2GlyphTable20; /* 2.0 style Glyph data struct */
741: GLYPHINFO_30 gi3GlyphTable30; /* 3.0 style Glyph data struct */
742:
743: NewAverage(); /* force ave width to be recomputed 8/17/87 BobM */
744:
745: /* reset file pointer */
746: nNewFile = (HFILE)OpenFile (pszFileName, pofsReOpenInfo, OF_WRITE | OF_REOPEN);
747:
748: if (nNewFile < (HFILE) 0) {
749:
750: return vszErrorOpeningFile;
751: }
752:
753: /* Put up an houglass ... this may take a while */
754: if (!hHourGlass)
755: hHourGlass = LoadCursor (NULL, IDC_WAIT); /* Get Hourglass */
756: hOldCursor = SetCursor (hHourGlass); /* Show hourglass */
757:
758: height = font.PixHeight;
759: cBody = (DWORD)height * (DWORD)font.WidthBytes;
760:
761: /* Recompute file size and update header */
762: if (iFontFormat == ID_FORMAT2)
763: cHeader = (WORD)(lSizeOfOldFontHeader +1);
764: else
765: cHeader = (WORD)(lSizeOfOldFontHeader30 - 1);
766:
767: /* if of 2.0 type, check if size will exceed 64kbytes. If yes, saving
768: in 2.0 format will result in loss of information (because offset table
769: of 2.0 file is composed of 16bit words). Warn user and ask if file can
770: be saved as a 3.0 file */
771:
772: if (iFontFormat == ID_FORMAT2)
773: {
774: if (((DWORD)cHeader + (DWORD)(lSizeOfOldGlyph20 * (font.LastChar -
775: font.FirstChar+2)) + (DWORD)cBody) >= WORD_LIMIT)
776: if (MessageBox(hBox, vszTooBigFor20, vszWarning,
777: IDOK | IDCANCEL |IDNO) == IDYES)
778: iFontFormat = ID_FORMAT3;
779: }
780:
781: if (iFontFormat == ID_FORMAT2) {
782:
783: /* allocate space for a 2.0 style offsets table */
784: cTable = (WORD)(lSizeOfOldGlyph20 *
785: (font.LastChar - font.FirstChar + 2));
786:
787: } else {
788:
789: /* allocate space for a 3.0 style offsets table */
790: cTable = (WORD)(lSizeOfOldGlyph30 *
791: (font.LastChar - font.FirstChar + 2));
792: }
793:
794: pjGlyphData = (LPSTR)GlobalAlloc (GMEM_ZEROINIT, (DWORD)cTable);
795:
796: if (pjGlyphData == 0) {
797:
798: _lclose((HFILE)nNewFile);
799: return vszNotEnoughMem;
800: }
801:
802: pjGlyphSave = pjGlyphData;
803:
804: size = cHeader + cTable;
805: iMax = font.LastChar - font.FirstChar + 1;
806:
807: /* create offsets table of font file */
808: for (i = 0; i <= iMax; i++){
809:
810: DWORD width, charSize;
811:
812: width = offsets[i + font.FirstChar + 1] - offsets[i + font.FirstChar];
813:
814: if (i == iMax) {
815: width = 8; /* Sentinal blank */
816: }
817:
818: if (iFontFormat == ID_FORMAT2){
819:
820: gi2GlyphTable20.GIwidth = (SHORT)width;
821: gi2GlyphTable20.GIoffset = (SHORT)size;
822:
823: vBufferFromGlyphInfo20 (&gi2GlyphTable20, pjGlyphData);
824:
825: pjGlyphData += lSizeOfOldGlyph20;
826:
827: } else {
828:
829: gi3GlyphTable30.GIwidth = (SHORT)width;
830: gi3GlyphTable30.GIoffset = (INT)size;
831:
832: vBufferFromGlyphInfo30 (&gi3GlyphTable30, pjGlyphData);
833:
834: pjGlyphData += lSizeOfOldGlyph30;
835: }
836:
837: charSize = height * ((width + 7) >> 3); /* size in bytes */
838:
839: if ((size + charSize) < size){ /* Overflow? */
840:
841: GlobalFree (pjGlyphData);
842: _lclose((HFILE)nNewFile);
843: return vszFileTooLarge;
844:
845: }
846: size += charSize;
847: }
848:
849: /* Update stuff in the header */
850:
851: font.Face = (DWORD)size;
852: cFace = (WORD)lstrlen (szFaceName) + 1; /* Allow for \0 */
853: size += cFace;
854: font.Size = (DWORD)size; /* new file size */
855: font.BitsOffset = (DWORD)(cHeader + cTable);
856: font.Device = (DWORD)NULL; /* Device Name must be NULL */
857: cFontsav = size - cHeader - cTable;
858: cFont =cFontsav;
859:
860: /* alloc extra byte for lp1 in case it needs it */
861: if (!(lpFontBody = (LPSTR)GlobalAlloc (GMEM_ZEROINIT, (LONG)cBody +
862: height * 4))) {
863:
864: _lclose((HFILE)nNewFile);
865: return vszNotEnoughMem;
866: }
867:
868: GetBitmapBits (hBitmap, (DWORD)cBody, lpFontBody);
869:
870: /* save current WidthBytes */
871: widthsav = font.WidthBytes;
872:
873: /* MD - reset WidthBytes from computed width */
874: font.WidthBytes = (WORD) (cFont - cFace)/ height;
875:
876: /* Allocate a block to put bitmap into */
877: if ((lpFont = lpWork = GlobalAlloc (GMEM_ZEROINIT,(LONG)cFont)) == 0)
878: {
879: GlobalFree (lpFontBody);
880: _lclose((HFILE)nNewFile);
881: return vszNotEnoughMem;
882: }
883:
884: lp1 = lpFontBody;
885:
886: /* convert bitmap to file format */
887: if (iFontFormat == ID_FORMAT2){ /* offsets table in 2.0 format */
888: INT nChars;
889: nChars = font.LastChar - font.FirstChar +1;
890:
891: for (row = 0; row < height; row++){
892:
893: DWORD phase;
894:
895: phase = 0;
896:
897: pjGlyphData = pjGlyphSave;
898:
899: for (i = 0; i < (DWORD) nChars; i++) {
900:
901: INT width;
902:
903: vGlyphInfo20FromBuffer (pjGlyphData, &gi2GlyphTable20);
904:
905: width = gi2GlyphTable20.GIwidth;
906:
907: lp2 = (BYTE *)(lpWork + (gi2GlyphTable20.GIoffset -
908: cHeader - cTable + row));
909:
910: pjGlyphData += lSizeOfOldGlyph20;
911:
912: phase = ConvertToFileFormat (width, phase, height);
913: }
914: if ((lp1 - lpWork) & 1)
915: lp1++; /* Round lp1 up to Word Boundary */
916: #ifdef DWORDROUND
917: if ((lp1 - lpWork) & 2) {
918: lp1++; /* Round lp1 up to DWord Boundary */
919: lp1++; /* Round lp1 up to DWord Boundary */
920: }
921: #endif
922: //if(((offsets[font.LastChar + 1] + 7) >> 3) & 1)
923: //lp1++; /* Round lp1 up to Word Boundary */
924: }
925: }
926: /* separate loops written for the 2.0 and 3.0 font processing because
927: a single loop would involve too many checks (of font type) within
928: the loop and slow down processing */
929: else{ /* table in 3.0 format */
930:
931: INT nChars;
932: nChars = font.LastChar - font.FirstChar +1;
933: for (row = 0; row < height; row++){
934:
935: DWORD phase;
936:
937: phase = 0;
938: pjGlyphData = pjGlyphSave;
939:
940: for (i = 0; i < (DWORD) nChars; i++) {
941:
942: INT width;
943:
944: vGlyphInfo30FromBuffer (pjGlyphData, &gi3GlyphTable30);
945:
946: width = gi3GlyphTable30.GIwidth;
947:
948: lp2 = (BYTE *)(lpWork + (gi3GlyphTable30.GIoffset -
949: cHeader - cTable + row));
950:
951: pjGlyphData += lSizeOfOldGlyph30;
952:
953: phase = ConvertToFileFormat (width, phase, height);
954: }
955: if ((lp1 - lpWork) & 1)
956: lp1++; /* Round lp1 up to Word Boundary */
957: #ifdef DWORDROUND
958: if ((lp1 - lpWork) & 2) {
959: lp1++; /* Round lp1 up to DWord Boundary */
960: lp1++; /* Round lp1 up to DWord Boundary */
961: }
962: #endif
963: //if(((offsets[font.LastChar + 1] + 7) >> 3) & 1)
964: //lp1++; /* Round lp1 up to Word Boundary */
965: }
966: }
967:
968: /* Restore start of data. */
969: pjGlyphData = pjGlyphSave;
970:
971: lp2 -= height - 1; /* Back up to start of character */
972: for (i = 0; i < height; i++)
973: *lp2++ = 0; /* Fill in guaranteed blank character */
974:
975: font.Version = 0x200;
976:
977: /****** code for compaction in 3.0 fmt borrowed from CMPCTFON ******/
978: if (iFontFormat== ID_FORMAT3){
979: DWORD iDefBitmapSize = 0; /* size of default char */
980: DWORD cch = 0; /* count of number of default char */
981: #if 0
982: GLYPHINFO_30 *cur_char; /* current element of offset table */
983: GLYPHINFO_30 *move_char;
984: /* element from which moving is to be done */
985: LONG iDefBitmapOffset; /* offset of default char */
986: INT iDefBitmapWidth; /* width of default char */
987: static LONG iEndOfBitmaps; /* address of end of font body */
988: INT iFirstC; /* first char in font */
989: INT iLastC; /* last char in font */
990: INT i,j;
991: WORD width;
992: CHAR *rgbFont; /* pointer to font body */
993: DWORD Offset;
994:
995: GDI seems to understand compressed 2.0 external formats but not
996: compressed 3.0 formats, and this is causing it to crash loading a 3.0
997: format compressed font. Since compression does not affect the
998: validity of the font, This code is disabled temporarily till
999: this problem is verified. Again, the font is perfectly usable in this
1000: form, though a trifle bigger than desired - LR 20/26/90
1001:
1002:
1003: Note that this will now not work after the conversion to NT.
1004: the glyph table needs to accessed as above. t-davema 8/20/91
1005:
1006: iFirstC = font.FirstChar & 0x0ff;
1007: iLastC = font.LastChar & 0x0ff;
1008:
1009: iEndOfBitmaps = (LONG)font.BitsOffset+((LONG)font.WidthBytes *
1010: (LONG)font.PixHeight);
1011: rgbFont = (CHAR *)lpFont; /* start of font body */
1012: cur_char =(GLYPHINFO_30 *) lpTable; /* start of offset table */
1013:
1014: /* calculate some parameters for the default char */
1015: iDefBitmapOffset = cur_char[font.DefaultChar].GIoffset;
1016: iDefBitmapWidth = cur_char[font.DefaultChar].GIwidth;
1017: iDefBitmapSize = (DWORD)cur_char[font.DefaultChar+1].GIoffset
1018: - (DWORD)iDefBitmapOffset;
1019:
1020: /* scan the font body via the offsets table. If a default char
1021: is recognised, move all the bytes to it's right left by the
1022: size of the default char.Make all offset table entries of default
1023: char point to one image of the char (the earliest occuring image) */
1024: for (i = iFirstC; i <= iLastC; ++i) {
1025:
1026: /* important: Check for limiting conditions (in case break char
1027: was modified?)*/
1028: if (cur_char->GIoffset == iDefBitmapOffset){
1029: cur_char++;
1030: continue;
1031: }
1032:
1033: Offset = cur_char->GIoffset -cHeader -cTable;
1034: /* proceed to compare images only if widths are equal */
1035: if ((cur_char->GIwidth == iDefBitmapWidth) &&
1036: (ByteCompare (&rgbFont [Offset],
1037: &rgbFont[iDefBitmapOffset-cHeader-cTable],
1038: (DWORD)iDefBitmapSize) == TRUE)){
1039:
1040: /* set offset to earliest occurence of the default char */
1041: if (cur_char->GIoffset < iDefBitmapOffset){
1042: iDefBitmapOffset = cur_char->GIoffset;
1043: }
1044: else {
1045: if (i != iLastC){
1046: /* move bytes to right of default char left by the
1047: size of the char */
1048: ByteCopy (&rgbFont [ Offset],
1049: &rgbFont [ Offset+ iDefBitmapSize],
1050: (LONG)(iEndOfBitmaps -
1051: ((cur_char + 1)->GIoffset)));
1052:
1053: /* correct the offset table entries */
1054: move_char = cur_char + 1;
1055: for (j=i; j < iLastC; ++j){
1056: move_char->GIoffset -= (LONG)iDefBitmapSize;
1057: move_char++;
1058: }
1059: }
1060: iEndOfBitmaps -= iDefBitmapSize;
1061: /* move End-of-font to the left */
1062: cur_char->GIoffset = iDefBitmapOffset;
1063: /* point offset of cuurent char to default char */
1064: cch++;
1065: }
1066: }
1067: cur_char++;
1068: }
1069: #endif
1070: /* recalculate some font attributes */
1071: lp2 -= (cch * iDefBitmapSize + height);
1072: for (i = 0; i < height; i++)
1073: *lp2++ = 0; /* Fill in guaranteed blank character */
1074:
1075: cFont -= cch * iDefBitmapSize;
1076: font.WidthBytes = (WORD) (cFont - cFace)/ height;
1077: font.Size = (DWORD) (cFont + cHeader + cTable);
1078: font.Face = font.Size - cFace ;
1079: font.Version = 0x300;
1080:
1081: /* copy info into 3.0 (new) format header and set the additional
1082: fields */
1083: ByteCopy ((LPSTR)&font30, (LPSTR)&font, (DWORD)sizeof (font));
1084: font30.fsFlags = 0;
1085: font30.fsFlags = (font.Family & 1 ? FSF_PROPORTIONAL : FSF_FIXED);
1086: font30.fsAspace = 0;
1087: font30.fsBspace = 0;
1088: font30.fsCspace = 0;
1089: font30.fsColorPointer = 0L;
1090: for (i = 0; i < 4 ; i++)
1091: font30.fsReserved[i] = 0L;
1092: }
1093:
1094: /* Add the FaceName, if any, to the end of the bitmap */
1095: lstrcpy((LPSTR)lp2, (LPSTR)szFaceName);
1096:
1097: /*
1098: * Again we need to do some tricky things to get the header output
1099: * correct. We want to run it through the conversion backwards until
1100: * we get the packed structure.
1101: */
1102: {
1103: BYTE jOutputBuffer [sizeof (font30)];
1104:
1105: if (iFontFormat == ID_FORMAT2) {
1106:
1107: vBufferFromFontStruct (&font, (PBYTE)&jOutputBuffer);
1108:
1109: } else {
1110:
1111: vBufferFromFont30Struct (&font30, (PBYTE)&jOutputBuffer);
1112: }
1113:
1114: bytecount = _lwrite((HFILE)nNewFile, (PBYTE)&jOutputBuffer, (DWORD)cHeader);
1115: }
1116:
1117: /* Write out Header Information */
1118: if (bytecount == cHeader) {
1119:
1120: /* Write out OffsetsTable */
1121: if (cTable == 0 || (_lwrite((HFILE)nNewFile, pjGlyphData, (DWORD)cTable)
1122: == (UINT)cTable)){
1123: /* Write out Body */
1124: fontlen = cFont;
1125: while (fontlen >= SEGMENT_SIZE){
1126:
1127: /* file write method if font size is 64k or greater
1128: file is written in chunks of 65536 bytes (SEGMENT_SIZE)-lr */
1129:
1130: /* First write as many bytes as _lwrite will allow(65534) */
1131: if (_lwrite((HFILE)nNewFile, (CHAR *)lpFont, WORD_LIMIT) ==
1132: WORD_LIMIT){
1133: fontlen -= WORD_LIMIT;
1134: /* fontlen = no of bytes left to write*/
1135: lpFont+= WORD_LIMIT; /* buffer ptr moved up by 64k */
1136: }
1137: else
1138: sz = vszErrorWritingBody;
1139:
1140: /* write the two bytes remaining in the segment */
1141: if (_lwrite((HFILE)nNewFile, (CHAR *)lpFont, 2) == 2){
1142: fontlen -= 2; /* fontlen = no of bytes left to write*/
1143: lpFont+= 2; /* buffer ptr moved up by 2 */
1144: }
1145: else
1146: sz = vszErrorWritingBody;
1147: }
1148: /* segment only partially filled. Write the remaining bytes */
1149: if (_lwrite((HFILE)nNewFile, (CHAR *)lpFont, (DWORD)fontlen) ==
1150: (UINT) fontlen){
1151: fChanged = FALSE;
1152: sz= "";
1153: }
1154: else
1155: sz = vszErrorWritingBody;
1156: }
1157: else
1158: sz = vszErrorWritingOffsets;
1159: }
1160: else
1161: sz = vszErrorWritingHdr;
1162:
1163: /* hack: Restore saved value of widthbytes, eliminating a variety
1164: of minor scrolling problems that follow after a File/Save */
1165: font.WidthBytes = widthsav;
1166:
1167: _lclose((HFILE)nNewFile);
1168:
1169: /* Tidy up */
1170:
1171: GlobalFree(lpFontBody);
1172: GlobalFree(pjGlyphData);
1173: GlobalFree(lpWork);
1174:
1175: SetCursor(hOldCursor); /* Restore regular cursor */
1176:
1177: return sz;
1178: }
1179:
1180: /****************************************************************************
1181: * BOOL ResizeWidths(wChar)
1182: *
1183: * params : WORD wChar : new width of a single character
1184: *
1185: * purpose: resize work bitmap according to new character width by stretching/
1186: * compressing all characters as neccesary
1187: *
1188: * returns: none
1189: *
1190: * side effects: Work bitmap changes.Some header info (regarding font dimensions
1191: * altered as well
1192: ****************************************************************************/
1193:
1194:
1195: BOOL
1196: ResizeWidths(
1197: DWORD wChar
1198: )
1199: {
1200: DWORD width;
1201: DWORD offset, i;
1202:
1203: /* Create a new bitmap to move the font definition bits into */
1204: width = (font.LastChar - font.FirstChar + 1) * wChar; /* In pixels */
1205: width = (width + 15) >> 4 << 1; /* In even bytes */
1206: if (!GetNewMap(width, font.PixHeight))
1207: return (FALSE);
1208:
1209: /* Move the bits in */
1210: offset = 0;
1211: oldMode = SetStretchBltMode(hNewMemDC, COLORONCOLOR);
1212: for (i = font.FirstChar; i <= font.LastChar; i++)
1213: {
1214:
1215: StretchBlt(hNewMemDC, offset, 0,
1216: wChar, font.PixHeight, /* New character */
1217: hMemDC, offsets[i], 0,
1218: font.PixWidth, font.PixHeight, /* Old character */
1219: SRCCOPY);
1220: offsets[i] = offset;
1221: offset += wChar;
1222: }
1223: SetStretchBltMode(hNewMemDC, oldMode);
1224: offsets[font.LastChar + 1] = offset;
1225:
1226: UseNewMap(); /* Switch Pointers and release the space */
1227:
1228: font.HorizRes = (WORD) Proport(font.HorizRes, wChar, font.PixWidth, 999);
1229: font.WidthBytes = (WORD) width; /* Misc. ajustments */
1230: font.PixWidth = font.AvgWidth = (font.MaxWidth = (WORD) wChar);
1231:
1232: return (TRUE);
1233: }
1234:
1235:
1236: /****************************************************************************
1237: * BOOL SpreadWidths(wChar)
1238: *
1239: * purpose: spread/compress work bitmap (with variable width characters)
1240: * in proportion with the maximum character width
1241: *
1242: * params : WORD wChar : new width of a character
1243: *
1244: * returns: none
1245: *
1246: * side effects: Work bitmap changes.Some header info (regarding font dimensions
1247: * altered as well
1248: ****************************************************************************/
1249:
1250: BOOL
1251: SpreadWidths(
1252: DWORD wChar
1253: )
1254: {
1255: DWORD offset, i;
1256: DWORD width, oldWidth, newWidths[257];
1257:
1258: /* Create a new bitmap to move the font definition bits into */
1259: width = 0; /* Compute the new width */
1260: for (i = (DWORD) font.FirstChar; i <= (DWORD) font.LastChar; i++)
1261: {
1262: oldWidth = offsets[i + 1] - offsets[i];
1263: /* Compute new width to nearest whole number */
1264: newWidths[i] = Proport(oldWidth, wChar, font.MaxWidth, wBoxLim - 1);
1265: width += newWidths[i];
1266: }
1267: width = (width + 15) >> 4 << 1; /* In even bytes */
1268: if (!GetNewMap(width, font.PixHeight))
1269: return(FALSE);
1270:
1271: /* Move the bits in */
1272: offset = 0;
1273: oldMode = SetStretchBltMode(hNewMemDC, COLORONCOLOR);
1274: for (i = font.FirstChar; i <= font.LastChar; i++)
1275: {
1276: oldWidth = offsets[i + 1] - offsets[i];
1277: StretchBlt(hNewMemDC, offset, 0,
1278: newWidths[i], font.PixHeight, /* New character */
1279: hMemDC, offsets[i], 0,
1280: oldWidth, font.PixHeight, /* Old character */
1281: SRCCOPY);
1282: offsets[i] = offset;
1283: offset += newWidths[i];
1284: }
1285: SetStretchBltMode(hNewMemDC, oldMode);
1286: offsets[font.LastChar + 1] = offset;
1287:
1288: UseNewMap(); /* Switch Pointers and release the space */
1289: font.HorizRes = (WORD) Proport(font.HorizRes, wChar, font.MaxWidth, 999);
1290: font.WidthBytes = (WORD) width; /* Misc. ajustments */
1291: font.MaxWidth = (WORD) wChar;
1292: NewAverage(); /* Compute new average width */
1293:
1294: return (TRUE);
1295: }
1296:
1297:
1298: /****************************************************************************
1299: * NewAverage()
1300: *
1301: * purpose: recalculate average width of a character in font
1302: *
1303: * params : none
1304: *
1305: * returns: none
1306: *
1307: * side effects: alters the average width parameter in font header
1308: *
1309: ****************************************************************************/
1310: VOID
1311: NewAverage(
1312: VOID
1313: )
1314: {
1315: #ifdef FOO
1316: WORD i, totalwidth;
1317: /* 12/23/85 -- use weighted avg of lower case letters (mikecr) */
1318:
1319: /* width of the space */
1320: totalwidth = (offsets[' ' + 1] - offsets[' ']) * widthweights[ALPHA_CNT];
1321:
1322: for (i = 0; i < ALPHA_CNT; i++)
1323: totalwidth += (offsets['a' + i + 1] - offsets['a' + i]) *
1324: widthweights[i];
1325:
1326: font.AvgWidth = totalwidth / TOTAL_WEIGHTS;
1327:
1328: /* round up if necessary */
1329: if (totalwidth % TOTAL_WEIGHTS >= (TOTAL_WEIGHTS >> 1))
1330: font.AvgWidth++;
1331:
1332: #endif
1333:
1334: /* lets do a simple average here */
1335: font.AvgWidth = (WORD) (((offsets[font.LastChar+1] -
1336: offsets[font.FirstChar]) + (font.LastChar - font.FirstChar)/2) /
1337: (font.LastChar - font.FirstChar + 1));
1338:
1339: if (font.AvgWidth == 0) {
1340: font.AvgWidth++;
1341: }
1342: }
1343:
1344:
1345: /****************************************************************************
1346: * BOOL ResizeBody(width, height)
1347: *
1348: * purpose: adjust work bitmap according to new specified dimensions
1349: *
1350: * params : WORD width : new width of font in pixels
1351: * WORD height : new height of font in pixels
1352: *
1353: * returns: none
1354: *
1355: * side effects: Work bitmap changes.Some header info (regarding font dimensions
1356: * altered as well
1357: ****************************************************************************/
1358:
1359: BOOL
1360: ResizeBody(
1361: DWORD width,
1362: DWORD height
1363: )
1364: {
1365:
1366: /* Create a new bitmap to move the font definition bits into */
1367: if (!GetNewMap(width, height))
1368: return(FALSE);
1369:
1370: /* Move the bits in */
1371: oldMode = SetStretchBltMode(hNewMemDC, COLORONCOLOR);
1372: StretchBlt(hNewMemDC, 0, 0,
1373: width << 3, height, /* New Char. */
1374: hMemDC, 0, 0,
1375: width << 3, font.PixHeight, /* Old Char. */
1376: SRCCOPY);
1377: SetStretchBltMode(hNewMemDC, oldMode);
1378:
1379: UseNewMap(); /* Switch Pointers and release the space */
1380:
1381: font.ExtLeading = (WORD) Proport(font.ExtLeading, height, font.PixHeight, 999);
1382: font.IntLeading = (WORD) Proport(font.IntLeading, height, font.PixHeight, 999);
1383: font.Ascent = (WORD) Proport(font.Ascent, height, font.PixHeight, 32);
1384: font.VertRes = (WORD) Proport(font.VertRes, height, font.PixHeight, 999);
1385: font.Points = (WORD) Proport(font.Points, height, font.PixHeight, 999);
1386: font.PixHeight = (WORD) height; /* Fix misc. header values */
1387: font.WidthBytes = (WORD) width;
1388:
1389: return (TRUE);
1390: }
1391:
1392:
1393: /****************************************************************************
1394: * BOOL NewFirstChar(first)
1395: *
1396: * purpose: redefines first character in font and resizes work bitmap
1397: * accordingly
1398: *
1399: * params : WORD first : new first character to be defined
1400: *
1401: * returns: none
1402: *
1403: * side effects: Work bitmap changes.Some header info (regarding font dimensions
1404: * altered as well
1405: ****************************************************************************/
1406:
1407: BOOL
1408: NewFirstChar(
1409: DWORD first
1410: )
1411: {
1412: DWORD width, wDefault;
1413: DWORD offset, i;
1414: INT dw;
1415:
1416: if (first > font.FirstChar) /* Smaller? */
1417: {
1418: ShrinkFont(first, font.LastChar);
1419: font.FirstChar = (BYTE) first;
1420: /*return(FALSE);*/
1421: return(TRUE);
1422: }
1423:
1424: /* If not smaller we must pad with the default character */
1425: wDefault = offsets[font.DefaultChar + 1] - offsets[font.DefaultChar];
1426: dw = wDefault * (font.FirstChar - first); /* Extra width */
1427: width = offsets[font.LastChar + 1] + dw; /* New width (pixels) */
1428: width = (width + 15) >> 4 << 1; /* Width - even bytes */
1429: if (!GetNewMap(width, font.PixHeight))
1430: return(FALSE); /* New work area */
1431:
1432: /* Move it in in two parts */
1433: /* First move in default characters */
1434: offset = 0;
1435: for (i = first; i < font.FirstChar; i++)
1436: {
1437: BitBlt(hNewMemDC, offset, 0,
1438: wDefault, font.PixHeight,
1439: hMemDC, offsets[font.DefaultChar], 0,
1440: SRCCOPY);
1441: offsets[i] = offset;
1442: offset += wDefault;
1443: }
1444: /* Now move in the rest */
1445: BitBlt(hNewMemDC, offset, 0,
1446: offsets[font.LastChar + 1], font.PixHeight,
1447: hMemDC, 0, 0,
1448: SRCCOPY);
1449:
1450: UseNewMap(); /* Switch Pointers and release the space */
1451:
1452: /* Now fix up offsets table */
1453: for (i = font.FirstChar; i <= (DWORD)(font.LastChar + 1); i++)
1454: offsets[i] = offsets[i] + dw; /* Shift the rest right */
1455: font.WidthBytes = (WORD) width;
1456: font.FirstChar = (BYTE) first;
1457:
1458: return (TRUE);
1459: }
1460:
1461:
1462: /****************************************************************************
1463: * ShrinkFont(first, last)
1464: *
1465: * purpose: redefine the first and last charcter in the font and shrink
1466: * work bitmap accordingly
1467: *
1468: * params : WORD first : new first character to be defined
1469: * WORD last : new last character " " "
1470: *
1471: * returns: none
1472: *
1473: * side effects: Work bitmap changes.Some header info (regarding font dimensions
1474: * altered as well
1475: ****************************************************************************/
1476:
1477: VOID
1478: ShrinkFont(
1479: DWORD first,
1480: DWORD last
1481: )
1482: {
1483: DWORD width, widthPixels;
1484: DWORD i;
1485: INT dw;
1486:
1487: dw = offsets[first] - offsets[font.FirstChar]; /* left shift if any */
1488: widthPixels = offsets[last + 1] - offsets[first]; /* Width in pixels */
1489: width = (widthPixels + 15) >> 4 << 1; /* Width - even bytes */
1490: if (!GetNewMap(width, font.PixHeight))
1491: return; /* New work area.*/
1492:
1493: /* Now move the font into the reduced space */
1494:
1495: BitBlt(hNewMemDC, 0, 0,
1496: widthPixels, font.PixHeight,
1497: hMemDC, offsets[first], 0,
1498: SRCCOPY);
1499:
1500: UseNewMap(); /* Switch Pointers and release the space */
1501:
1502: if (dw) /* Ajust offsets */
1503: {
1504: for (i = first; i <= last + 1; i++)
1505: offsets[i] -= dw;
1506: }
1507:
1508: font.WidthBytes = (WORD) width;
1509:
1510: }
1511:
1512:
1513: /****************************************************************************
1514: * BOOL NewLastChar(last)
1515: *
1516: * purpose: redefines the last character in the font
1517: *
1518: * params : WORD last : number of character to be made the last character
1519: *
1520: * returns: none
1521: *
1522: * side effects: Work bitmap changes.Some header info (regarding font dimensions
1523: * altered as well
1524: *
1525: ****************************************************************************/
1526:
1527: BOOL
1528: NewLastChar(
1529: DWORD last
1530: )
1531: {
1532: DWORD width, wDefault;
1533: DWORD offset, i;
1534: INT dw;
1535:
1536: if (last < font.LastChar) /* Smaller? */
1537: {
1538: ShrinkFont(font.FirstChar, last);
1539: font.LastChar = (BYTE) last;
1540: return(FALSE);
1541: }
1542:
1543: /* If not smaller we must pad with the default character */
1544: wDefault = offsets[font.DefaultChar + 1] - offsets[font.DefaultChar];
1545: dw = wDefault * (last - font.LastChar); /* Extra width */
1546: offset = offsets[font.LastChar + 1]; /* Current end */
1547: width = offset + dw; /* New width (pixels) */
1548: width = (width + 15) >> 4 << 1; /* Width - even bytes */
1549: if (!GetNewMap(width, font.PixHeight))
1550: return(FALSE); /* New work area */
1551:
1552: /* Move it in in two parts */
1553: /* First move in the existing font */
1554: BitBlt(hNewMemDC, 0, 0,
1555: offset, font.PixHeight,
1556: hMemDC, 0, 0,
1557: SRCCOPY);
1558: /* Then move in default characters */
1559: for (i = font.LastChar + 1; i <= last;)
1560: {
1561: BitBlt(hNewMemDC, offset, 0,
1562: wDefault, font.PixHeight,
1563: hMemDC, offsets[font.DefaultChar], 0,
1564: SRCCOPY);
1565: offset += wDefault;
1566: offsets[++i] = offset;
1567: }
1568:
1569: UseNewMap(); /* Switch Pointers and release the space */
1570:
1571: font.WidthBytes = (WORD) width;
1572: font.LastChar = (BYTE) last;
1573:
1574: return (TRUE);
1575: }
1576:
1577:
1578: /****************************************************************************
1579: * BOOL CharWidth(iChar, wBox)
1580: *
1581: * purpose: resizes selected char according to new dimensions. (only for
1582: * variable pitch)
1583: *
1584: * params : BYTE iChar : character to resize
1585: * WORD wBox : new width of char in pixels
1586: *
1587: * returns: none
1588: *
1589: * side effects: work bitmap pixel values and header info(regarding font
1590: * dimensions) altered
1591: *
1592: ****************************************************************************/
1593:
1594: BOOL
1595: CharWidth(
1596: BYTE iChar, /* Character to change */
1597: DWORD wBox /* New width */
1598: )
1599: {
1600: DWORD width, nChars;
1601: DWORD w1, w2, i;
1602: INT dw;
1603:
1604: nChars = font.LastChar - font.FirstChar + 1; /* Character count */
1605: dw = wBox - (offsets[iChar + 1] - offsets[iChar]); /* Width change */
1606: width = offsets[font.LastChar + 1] + dw; /* New width (pixels) */
1607: width = (width + 15) >> 4 << 1; /* Width - even bytes */
1608: if (!GetNewMap(width, font.PixHeight))
1609: return(FALSE); /* New work area */
1610:
1611: /* Move it in in two parts */
1612: /* First move up to and including iChar */
1613: w1 = offsets[iChar + 1]; /* Width (in pixels) to move */
1614: BitBlt(hNewMemDC, 0, 0,
1615: w1 + dw, font.PixHeight,
1616: hMemDC, 0, 0,
1617: SRCCOPY);
1618: /* Now move in the rest */
1619: if (iChar < (BYTE) font.LastChar) /* Part to right of elision */
1620: {
1621: w2 = offsets[font.LastChar + 1] - offsets[iChar + 1];
1622: BitBlt(hNewMemDC, offsets[iChar] + wBox, 0,
1623: w2, font.PixHeight,
1624: hMemDC, offsets[iChar + 1], 0,
1625: SRCCOPY);
1626: }
1627:
1628: UseNewMap(); /* Switch Pointers and release the space */
1629:
1630: /* Now fix up offsets table */
1631: for (i = iChar + 1; /* Where changes start */
1632: i <= (DWORD)(font.LastChar + 1); i++) /* Ajust offsets */
1633: offsets[i] = offsets[i] + dw; /* .. by adding dw */
1634: font.WidthBytes = (WORD) width;
1635: NewAverage();
1636:
1637: return (TRUE);
1638: }
1639:
1640: /****************************************************************************
1641: * BoxToClipboard(ptA, width, height)
1642: *
1643: * purpose: write char (or part of it) to clipboard
1644: *
1645: * params : POINT ptA : upper left coordinate
1646: * DWORD width : width of char in pixels
1647: * DWORD height : height of char in pixels
1648: * returns: none
1649: *
1650: * side effects: none
1651: *
1652: ****************************************************************************/
1653: VOID
1654: BoxToClipboard(
1655: POINT ptA, /* Upper left point */
1656: DWORD width,
1657: DWORD height /* Size */
1658: )
1659: {
1660: HDC hDC;
1661: DWORD x, y;
1662:
1663: hDC = GetDC(hFont); /* DC to be compatible with */
1664: hNewBitmap = CreateBitmap(
1665: width, height,
1666: 1, 1, (LPBYTE)NULL);
1667: hNewMemDC = CreateCompatibleDC(hDC); /* Create a DC */
1668: SelectObject(hNewMemDC, hNewBitmap); /* Relate them */
1669: ReleaseDC(hFont, hDC); /* Done with font DC */
1670:
1671: for (x = 0; x < width; x++)
1672: for (y = 0; y < height; y++)
1673: SetPixel(hNewMemDC, x, y, matBox[x + ptA.x][y + ptA.y] == TRUE ?
1674: BLACK : WHITE);
1675:
1676: /* Now wake up Clipboard and empty it */
1677: if (!OpenClipboard(hFont))
1678: ErrorBox(hBox, vszCannotOpenClip); // , vszCopyingToClip);
1679: else /* Ok: We got the Clipboard */
1680: {
1681: EmptyClipboard();
1682: SetClipboardData(CF_BITMAP, hNewBitmap); /* Tell Clipboard */
1683: }
1684:
1685: /* Tidy things up */
1686: CloseClipboard();
1687: DeleteDC(hNewMemDC);
1688: }
1689:
1690:
1691: /****************************************************************************
1692: * WORD ClipboardToBox(ptA, width, height, fFit)
1693: *
1694: * purpose: copies char (or part of char ) from clipboard to work bitmap
1695: * stretching it if need be
1696: *
1697: * params : PIONT ptA : upper left coordinate
1698: * DWORD width : width of char in pixels
1699: * DWORD height : height of char in pixels
1700: * BOOL fFit : flag to indicate if default width is to be used
1701: * returns: none
1702: *
1703: * side effects: pixel values of bitmap may change for char
1704: *
1705: ****************************************************************************/
1706:
1707: DWORD
1708: ClipboardToBox(
1709: POINT ptA, /* Upper left point */
1710: DWORD width,
1711: DWORD height, /* Size */
1712: BOOL fFit /* Use default width if TRUE */
1713: )
1714: {
1715: BITMAP bitmap;
1716: HDC hDC;
1717: DWORD x, y;
1718: HANDLE hT;
1719:
1720: if (!OpenClipboard(hFont)) {
1721: ErrorBox(hBox, vszCannotOpenClip);
1722: return 0;
1723: }
1724: hNewBitmap = GetClipboardData(CF_BITMAP);
1725:
1726: /* Check if we got something like a character */
1727: if (GetObject(hNewBitmap, sizeof(BITMAP), (LPSTR)&bitmap) != sizeof(BITMAP))
1728: { /* What did we get */
1729: ErrorBox(hBox, vszErrorClip);
1730: CloseClipboard();
1731: return 0;
1732: }
1733:
1734:
1735: if (fFit && ((WORD)bitmap.bmWidth <= font.MaxWidth))
1736: width = bitmap.bmWidth;
1737:
1738: hDC = GetDC(hFont); /* DC to be compatible with */
1739: hBoxBitmap = CreateBitmap(
1740: width, height,
1741: 1, 1, (LPBYTE)NULL);
1742: hBoxMemDC = CreateCompatibleDC(hDC); /* Create a DC */
1743: hT = SelectObject(hBoxMemDC, hBoxBitmap); /* Relate them */
1744: if (hT == NULL || hDC == NULL || hBoxBitmap == NULL || hBoxMemDC == NULL) {
1745: ErrorBox(hBox, vszErrorClip);
1746: CloseClipboard();
1747: DeleteDC(hBoxMemDC);
1748: DeleteObject(hBoxBitmap);
1749: return 0;
1750: }
1751:
1752: /* Get a DC to relate to the Bitmap we just got */
1753: hNewMemDC = CreateCompatibleDC(hDC); /* Create a DC */
1754: hT = SelectObject(hNewMemDC, hNewBitmap); /* Relate them */
1755: ReleaseDC(hFont, hDC); /* Done with font DC */
1756: if (hT == NULL || hNewMemDC == NULL) {
1757: ErrorBox(hBox, vszErrorClip);
1758: CloseClipboard();
1759: DeleteDC(hNewMemDC);
1760: DeleteDC(hBoxMemDC);
1761: DeleteObject(hBoxBitmap);
1762: return 0;
1763: }
1764:
1765: /* Now StretchBlt whatever was on the clipboard into the character */
1766: oldMode = SetStretchBltMode(hBoxMemDC, COLORONCOLOR);
1767: fFit = StretchBlt(hBoxMemDC, 0, 0, width, height,
1768: hNewMemDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);
1769: if (!fFit || !oldMode) {
1770: ErrorBox(hBox, vszErrorClip);
1771: CloseClipboard();
1772: DeleteDC(hNewMemDC);
1773: DeleteDC(hBoxMemDC);
1774: DeleteObject(hBoxBitmap);
1775: return 0;
1776: }
1777: (void)SetStretchBltMode(hBoxMemDC, oldMode);
1778: for (x = 0; x < width; x++)
1779: for (y = 0; y < height; y++)
1780: matBox[x + ptA.x] [y + ptA.y] = (CHAR)(GetPixel(hBoxMemDC, x, y) ?
1781: 0 : 1);
1782: /* Tidy things up */
1783: DeleteDC(hNewMemDC);
1784: DeleteDC(hBoxMemDC);
1785: DeleteObject(hBoxBitmap);
1786: CloseClipboard();
1787: return(width);
1788: }
1789:
1790:
1791: /****************************************************************************
1792: * ToClipboard(iChar, width, height)
1793: *
1794: * purpose: write char in edit box to clipboard
1795: *
1796: * params : BYTE iChar : number of char to be copied to clipboard
1797: * DWORD width : width of char in pixels
1798: * DWORD height : height of char in pixels
1799: *
1800: * returns: none
1801: *
1802: * side effects: none
1803: *
1804: ****************************************************************************/
1805:
1806: VOID
1807: ToClipboard(
1808: BYTE iChar,
1809: DWORD width, /* Here in Pixels */
1810: DWORD height /* Also in Pixels */
1811: )
1812: {
1813: HDC hDC;
1814:
1815: hDC = GetDC(hFont); /* DC to be compatible with */
1816: hNewBitmap = CreateBitmap(
1817: width, /* Width of font in pixels */
1818: height,
1819: 1, 1, (LPBYTE)NULL);
1820: hNewMemDC = CreateCompatibleDC(hDC); /* Create a DC */
1821: SelectObject(hNewMemDC, hNewBitmap); /* Relate them */
1822: ReleaseDC(hFont, hDC); /* Done with font DC */
1823:
1824: BitBlt(hNewMemDC, 0, 0, width, height, /* Move Character in */
1825: hMemDC, offsets[iChar], 0, NOTSRCCOPY);
1826:
1827: /* Now wake up Clipboard and empty it */
1828: if (!OpenClipboard(hFont))
1829: ErrorBox(hBox, vszCannotOpenClip); // , vszCopyingToClip);
1830: else /* Ok: We got the Clipboard */
1831: {
1832: EmptyClipboard();
1833: SetClipboardData(CF_BITMAP, hNewBitmap); /* Tell Clipboard */
1834: }
1835:
1836: /* Tidy things up */
1837: CloseClipboard();
1838: DeleteDC(hNewMemDC);
1839: }
1840:
1841:
1842: /****************************************************************************
1843: * GetNewMap(width, height)
1844: *
1845: * purpose: create new bitmap of the given width and height.
1846: *
1847: * params : WORD width : width of bitmap in pixels
1848: * WORD height : height of bitmap in pixels
1849: *
1850: * returns: TRUE if successful, FALSE otherwise
1851: *
1852: * side effects: Handle and DC values of new DC assigned
1853: *
1854: ****************************************************************************/
1855:
1856: BOOL
1857: GetNewMap(
1858: DWORD width,
1859: DWORD height /* New size */
1860: )
1861: {
1862: HDC hDC;
1863:
1864: if (height==0) /* Check if something stupid is happening */
1865: height=font.PixHeight; /* Fix it */
1866:
1867: /* Put up an houglass ... this may take a while */
1868: if (!hHourGlass)
1869: hHourGlass = LoadCursor(NULL, IDC_WAIT); /* Get Hourglass */
1870: hOldCursor = SetCursor(hHourGlass); /* Show hourglass */
1871:
1872: /* Create a new bitmap to move the font definition bits into */
1873: hDC = GetDC(hFont); /* DC to be compatible with */
1874: hNewBitmap = CreateBitmap(
1875: width << 3, /* Width of font in pixels */
1876: height,
1877: 1, 1, (LPBYTE)NULL);
1878: if (!hNewBitmap)
1879: {
1880: ErrorBox(hBox, vszNotEnoughMem); // , vszAllocatingSpace);
1881: ReleaseDC(hFont, hDC); /* bug# 2380 */
1882: return FALSE;
1883: }
1884:
1885: hNewMemDC = CreateCompatibleDC(hDC); /* Create a DC */
1886: SelectObject(hNewMemDC, hNewBitmap); /* Relate them */
1887: ReleaseDC(hFont, hDC); /* Done with font DC */
1888: PatBlt(hNewMemDC, 0, 0, width << 3, height, BLACKNESS); /* Clear it */
1889: return TRUE;
1890: }
1891:
1892:
1893: /****************************************************************************
1894: * UseNewMap()
1895: *
1896: * params : none
1897: *
1898: * purpose: discard old bitmap and replace it with new one
1899: *
1900: * returns: none
1901: *
1902: * side effects: Handle to old bitmap and handle to old bitmap DC replaced
1903: * by those of new bitmap respectively
1904: *
1905: ****************************************************************************/
1906:
1907: VOID
1908: UseNewMap(
1909: VOID
1910: )
1911: {
1912: DeleteDC(hMemDC);
1913: DeleteObject(hBitmap); /* Release old space */
1914: hBitmap = hNewBitmap;
1915: hMemDC = hNewMemDC; /* Release old space */
1916: SetCursor(hOldCursor); /* Restore regular cursor */
1917: }
1918:
1919:
1920:
1921: VOID
1922: DeleteGlobalBitmap(
1923: VOID
1924: )
1925: {
1926: if (hMemDC)
1927: DeleteDC(hMemDC);
1928: if (hBitmap)
1929: DeleteObject(hBitmap);
1930: }
1931:
1932:
1933: DWORD
1934: Proport(
1935: DWORD value,
1936: DWORD top,
1937: DWORD bottom,
1938: DWORD limit
1939: )
1940: /* Reproportion a value by the ratio top/bottom to the nearest integer
1941: * and make sure we are still in range */
1942: {
1943: return min(limit, (DWORD)((1 + 2 * value * top) / (2 * bottom)));
1944: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.