|
|
1.1 root 1: //--------------------------------------------------------------------------
2: //
3: // Module Name: FONTTREE
4: //
5: // Brief Description: Device font tree querying routines
6: //
7: // Author: Kent Settle (kentse)
8: // Created: 18-Apr-1991
9: //
10: // Copyright (C) 1991 - 1992 Microsoft Corporation.
11: //
12: // This module contains DrvQueryFontTree.
13: //
14: // History:
15: // 18-Apr-1991 -by- Kent Settle (kentse)
16: // Created.
17: //--------------------------------------------------------------------------
18:
19: #include "pscript.h"
20: #include "enable.h"
21: #include "mapping.h"
22: #include <string.h>
23:
24: #define MAX_MAPSUBTABLES 256
25: #define MAX_GLYPHTABLES 16
26: #define MAX_GLYPHS 16
27:
28: PVOID BuildGLYPHSET(PDEVDATA, ULONG);
29: PVOID BuildKernPairs(PDEVDATA, ULONG);
30:
31: //--------------------------------------------------------------------------
32: // PVOID DrvQueryFontTree (dhpdev,iFile,iFace,iMode)
33: // DHPDEV dhpdev;
34: // ULONG iFile;
35: // ULONG iFace;
36: // ULONG iMode;
37: // ULONG *pid;
38: //
39: // This function is used by GDI to obtain pointers to tree structures that
40: // define one of the following.
41: //
42: // 1 The mapping from Unicode to glyph handles, including glyph
43: // variants;
44: // 2 The mapping of ligatures and their variants to glyph handles;
45: // 3 The mapping of kerning pairs to kerning handles.
46: //
47: // Parameters:
48: // dhpdev
49: // This is a PDEV handle returned from an earlier call to DrvEnablePDEV.
50: // iFile
51: // This identifies the font file (if device supports loading font files
52: // using the DDI).
53: // iFace
54: // This is the index of the driver font. The index of the first font
55: // is one.
56: // iMode
57: // This defines the type of information to be returned. This may take
58: // one of the following values:
59: //
60: // QFT_UNICODE GDI requests a pointer to a TREE_UNICODE structure
61: // that defines the mappings from single Unicode characters
62: // to glyph handles. This includes all glyph variants.
63: //
64: // QFT_LIGATURES GDI requests a pointer to a TREE_LIGATURES
65: // structure that defines the mapping from strings
66: // of Unicode characters to glyph handles. This
67: // includes all ligature variants.
68: //
69: // QFT_KERNPAIRS GDI requests a pointer to a TREE_KERNPAIRS
70: // structure that define the mappings from pairs
71: // of Unicode characters to kerning pair handles.
72: // These kerning handles are later passed to
73: // DrvQueryFontData to obtain kerning corrections.
74: //
75: // Returns:
76: // The return value is a pointer to the requested structure. This
77: // structure is to remain unchanged during the lifetime of the
78: // associated PDEV.
79: //
80: // Note: The following explanation was "borrowed" from lindsayh and the
81: // Generic driver.
82: //
83: // COMMENTS ON THE UNICODE TREE STRUCTURES:
84: // The following is intended to help understand the strange operations
85: // being done in the following function. UNICODE is a sparse encoding,
86: // so a tree structure is used to store the data. The following function
87: // produces a tree, the leaves of which are the GLYPH HANDLES that the
88: // engine passes to us to identify perticular glyphs. These handles are
89: // 32 bits long, contents up to the driver. We need to allocate storage
90: // for these and fill it in. The first step is to determine how much
91: // storage is needed. This requires understanding how the tree is built.
92: // The tree has 3 levels. At the top level there is a MAPTABLE
93: // structure. This has as many as 256 sub trees. These correspond to
94: // the 8 MSBs of the unicode value. This structure is folllowed by up to
95: // 256 PTRDIFFs (each a long). The structure itself contains a 256 byte
96: // array: this is an index into the array of PTRDIFFs following. Hence,
97: // there only needs to be as many PTRDIFFs as there are subtrees (plus 1,
98: // for the "no entry" value). For example, if there is only subtree,
99: // there need be only 2 PTRDIFFs - the active one, and a 0 entry. The
100: // byte array will mostly contain the index to the 0 entry, but the
101: // active entry will point at the other PTRDIFF.
102: //
103: // Each of the above active PTRDIFFs points to a MAPSUBTABLE. Each of
104: // these can handle 16 sub trees. It uses the same method as the MAPTABLE
105: // to handle sparseness - i.e. there is a 16 byte array containing
106: // indices into the array of PTRDIFFs following. The 16 byte array
107: // is indexed by the next 4 bits in the UNICODE value (i.e. the high
108: // nibble of the low byte). These PTRDIFFs point to GLYPHTABLEs,
109: // the next lower level in the tree.
110: //
111: // The final layer is the GLYPHTABLE data. Each of these contains
112: // up to 16 GLYPH HANDLEs, and is indexed by the 4 LSBs of the UNICODE
113: // value. Like the MAPSUBTABLE, there is a byte array containing
114: // index values of the glyph handles following.
115: //
116: // HOW MUCH MEMORY IS NEEDED??
117: // The tricky part is now determining how much memory to allocate for
118: // these structures. The answer is: a DWORD for each GLYPH HANDLE,
119: // as many GLYPHTABLEs as there are groups defined by the high order
120: // 12 bits of the UNICODE value (i.e., up to 4096), as many MAPSUBTABLES
121: // as there are groups of 16 GLYPHTABLES (up to 256), plus a MAPTABLE
122: // to amalgamate the top level. As well, the MAPTABLE and MAPSUBTABLE
123: // require PTRDIFFs to the lower level - this is as many as there are
124: // lower level entities.
125: //
126: // Determining this is done as follows: allocate a 64k BIT array,
127: // considered as an array of 4096 WORDS (16 bits each). For every
128: // available glyph, set the corresponding bit in the array, and
129: // increment a counter. At the end of this stage, we have a count of
130: // the number of (non-zero) GLYPH HANDLES needed. Now, by scanning
131: // the bit array by WORD, count each non-zero word. This tells us
132: // how many GLYPHTABLEs are required. A second bit array is also
133: // updated at this time. This array consists of 256 bits, one for
134: // each of the possible entries in the MAPTABLE. Passing through the
135: // WORD array, we can also set bits in the 256 bit array corresponding
136: // to the number of MAPTABLES required. Finally, counting the number
137: // of set bits in the 256 bit array gives us the number of MAPTABLES
138: // required. Given this information, it is possible to determine
139: // the amount of storage required. Note that it is necessary to allow
140: // for a 0 entry in the PTRDIFF and HGLYPH arrays.
141: //
142: // If an error occurs, NULL should be returned and an error code should
143: // be logged.
144: //
145: // History:
146: // 18-Apr-1991 -by- Kent Settle (kentse)
147: // Wrote it.
148: //--------------------------------------------------------------------------
149:
150: PVOID DrvQueryFontTree (dhpdev,iFile,iFace,iMode,pid)
151: DHPDEV dhpdev;
152: ULONG iFile;
153: ULONG iFace;
154: ULONG iMode;
155: ULONG *pid;
156: {
157: PDEVDATA pdev;
158:
159: UNREFERENCED_PARAMETER(iFile);
160:
161: // This can be used by the driver to flag or id the data returned.
162: // May be useful for deletion of the data later by DrvFree().
163:
164: *pid = 0; // don't need to use for this driver
165:
166: // get a pointer to our PDEV.
167:
168: pdev = (PDEVDATA)dhpdev;
169:
170: if (bValidatePDEV(pdev) == FALSE)
171: {
172: RIP("PSCRIPT!DrvQueryFontTree: invalid PDEV.");
173: SetLastError(ERROR_INVALID_PARAMETER);
174: return((PVOID)NULL);
175: }
176:
177: // validate the iFace. we should only be called for device fonts,
178: // ie iFace >= 1.
179:
180: if ((iFace < 1) || (iFace > (pdev->cDeviceFonts + pdev->cSoftFonts)))
181: {
182: RIP("PSCRPT!BuildGLYPHSET: invalid iFace.\n");
183: SetLastError(ERROR_INVALID_PARAMETER);
184: return((PVOID)NULL);
185: }
186:
187: switch (iMode)
188: {
189: case QFT_GLYPHSET:
190: return(BuildGLYPHSET(pdev, iFace));
191: break;
192:
193: case QFT_KERNPAIRS:
194: return(BuildKernPairs(pdev, iFace));
195: break;
196:
197: default:
198: RIP("PSCRIPT!DrvQueryFontTree: invalid iMode.\n");
199: SetLastError(ERROR_INVALID_PARAMETER);
200: return((PVOID)NULL);
201: }
202: }
203:
204: //--------------------------------------------------------------------------
205: // PVOID BuildGLYPHSET(pdev, iFace)
206: // PDEVDATA pdev;
207: // ULONG iFace;
208: //
209: // If an error occurs, NULL should be returned and an error code should
210: // be logged.
211: //
212: // History:
213: // 10-Feb-1992 -by- Kent Settle (kentse)
214: // Borrowed some of if from RASDD, wrote the rest.
215: //--------------------------------------------------------------------------
216:
217: PVOID BuildGLYPHSET(pdev, iFace)
218: PDEVDATA pdev;
219: ULONG iFace;
220: {
221: PNTFM pntfm; // pointer to font metrics.
222: PUCMap pmap; // pointer to UNICODE<->PSCRIPT mapping table.
223: PUCMap pmapReset; // place to save pointer.
224: DWORD i; // loop counter.
225: PBYTE pCharCode; // pointer to character code.
226: PBYTE pCharReset; // place to save pointer.
227: WCHAR wchCurrent; // current UNICODE value.
228: WCHAR wchPrevious; // previous UNICODE value.
229: DWORD cGlyphs; // count of glyph handles.
230: DWORD cRuns; // count of runs within FD_GLYPHSET.
231: DWORD cbTotalMem; // count of bytes needed for FD_GLYPHSET.
232: HGLYPH *phg; // pointer to HGLYPH's.
233: FD_GLYPHSET *pGLYPHSET; // pointer to FD_GLYPHSET.
234: WCRUN *pWCRUN; // pointer to WCRUN.
235: PULONG pulUCTree; // pointer to UNICODE tree.
236:
237: // get the font information for the given font.
238:
239: pntfm = pdev->pfmtable[iFace - 1].pntfm;
240:
241: // point to the appropriate mapping table in mapping.h.
242:
243: if (!strcmp((char *)pntfm + pntfm->loszFontName, "Symbol"))
244: pmap = SymbolMap;
245:
246: else if (!strcmp((char *)pntfm + pntfm->loszFontName, "ZapfDingbats"))
247: pmap = DingbatsMap;
248: else
249: pmap = LatinMap;
250:
251: pmapReset = pmap;
252:
253: // for every character in the mapping table, do a lookup in the NTFM
254: // structure to find a matching PostScript character code. For each
255: // character found, we can extract the corresponding UNICODE value.
256: // remember that the character codes are sitting in a BYTE array
257: // which is sitting directly after a (USHORT) array of character
258: // widths.
259:
260: pCharCode = ((PBYTE)pntfm + pntfm->loCharMetrics +
261: DWORDALIGN(pntfm->cCharacters * sizeof(USHORT)));
262:
263: // save the original pointer.
264:
265: pCharReset = pCharCode;
266:
267: cRuns = 1; // there must be at least one run!
268: cGlyphs = 0;
269:
270: // set wchPrevious equal to first UNICODE character code.
271:
272: wchPrevious = (WCHAR)pmap->usUCValue;
273:
274: while (pmap->szChar)
275: {
276: for (i = 0; i < (DWORD)pntfm->cCharacters; i++)
277: {
278: // search through all the characters in the NTFM structure,
279: // looking for a matching PostScript character code. remember
280: // that the high bit is used to indicate the font needs
281: // to be remapped. so ignore the high bit while checking
282: // for a character match.
283:
284: if ((CHAR)*pCharCode == (CHAR)pmap->usPSValue)
285: {
286: // we have found the character, now get its UNICODE value
287: // and set its BIT in the BIT array. also, increment the
288: // glyph count, if this UNICODE value has not yet been used.
289: // since the mapping tables in mapping.h are sorted by
290: // UNICODE values, we can simply check this value against
291: // the one we found last time. if it is the same, ignore
292: // it, if it is different, use it.
293:
294: wchCurrent = (WCHAR)pmap->usUCValue;
295:
296: if (wchCurrent != wchPrevious)
297: {
298: cGlyphs++;
299:
300: // see if we are starting new run.
301:
302: if ((wchCurrent - wchPrevious) != 1)
303: cRuns++;
304: }
305:
306: wchPrevious = wchCurrent;
307: break;
308: }
309:
310: pCharCode++;
311: }
312:
313: // point back to start of character list in NTFM structure.
314:
315: pCharCode = pCharReset;
316:
317: // point to next character in mapping table.
318:
319: pmap++;
320: }
321:
322: // allocate memory to build the FD_GLYPHSET structure in. this
323: // include space for the FD_GLYPHSET structure itself, as well
324: // as space for all the glyph handles.
325:
326: cbTotalMem = (cGlyphs * sizeof(HGLYPH)) + (cRuns * sizeof(WCRUN)) +
327: sizeof(FD_GLYPHSET) - sizeof(WCRUN);
328:
329: // DWORD bound it.
330:
331: cbTotalMem = (cbTotalMem + 3) & ~3;
332:
333: // this memory is to be kept around until the pdev is destroyed, so
334: // we don't have to free this memory until the heap is destroyed.
335:
336: phg = pulUCTree = (PVOID)HeapAlloc(pdev->hheap, 0, cbTotalMem);
337:
338: if (phg == NULL)
339: {
340: RIP("PSCRIPT!BuildGLYPHSET: HeapAlloc for phg failed.\n");
341: return((PVOID)NULL);
342: }
343:
344: // fill in the FD_GLYPHSET structure.
345:
346: pGLYPHSET = (FD_GLYPHSET *)phg;
347:
348: pGLYPHSET->cjThis = sizeof(FD_GLYPHSET) + (cRuns - 1) * sizeof(WCRUN);
349: pGLYPHSET->flAccel = 0; // no accelerators for us.
350: pGLYPHSET->cGlyphsSupported = cGlyphs;
351: pGLYPHSET->cRuns = cRuns;
352:
353: // now set the phg pointer to the first WCRUN structure.
354:
355: (BYTE *)phg += sizeof(FD_GLYPHSET) - sizeof(WCRUN);
356:
357: // point to first WCRUN in array.
358:
359: pWCRUN = (WCRUN *)phg;
360:
361: // point to data area for glyph handles.
362:
363: (BYTE *)phg += sizeof(WCRUN) * cRuns;
364:
365: // for every character in the font, do a lookup in the mapping
366: // table in mapping.h to find the corresponding UNICODE value.
367: // first point to the character codes in the NTFM structure.
368: // remember that the character codes are sitting in a BYTE array
369: // which is sitting directly after a (USHORT) array of character
370: // widths.
371:
372: pCharCode = pCharReset;
373: pmap = pmapReset;
374:
375: // locate the first glyph, and initialize the first WCRUN.
376:
377: for (i = 0; i < (DWORD)pntfm->cCharacters; i++)
378: {
379: // search for the matching code in mapping.h. remember
380: // that the high bit is used to indicate the font needs
381: // to be remapped. so ignore the high bit while checking
382: // for a character match.
383:
384: if ((CHAR)*pCharCode == (CHAR)pmap->usPSValue)
385: {
386: // we have found the character, now get its UNICODE value
387: // and set its BIT in the BIT array. also, increment the
388: // glyph count, if this UNICODE value has not yet been used.
389: // since the mapping tables in mapping.h are sorted by
390: // UNICODE values, we can simply check this value against
391: // the one we found last time. if it is the same, ignore
392: // it, if it is different, use it.
393:
394: wchPrevious = (WCHAR)pmap->usUCValue;
395:
396: pWCRUN->wcLow = wchPrevious;
397: pWCRUN->cGlyphs = 1;
398: pWCRUN->phg = phg;
399:
400: // store the glyph handle, which we will store as the
401: // PostScript character code.
402:
403: *phg++ = (HGLYPH)*pCharCode;
404:
405: break;
406: }
407:
408: // point to the next character in the NTFM structure.
409:
410: pCharCode++;
411: }
412:
413: // move to the second character in the mapping table.
414:
415: pmap++;
416:
417: while (pmap->szChar)
418: {
419: // reset pointer to start of character list in NTFM structure.
420:
421: pCharCode = pCharReset;
422:
423: for (i = 0; i < ((DWORD)pntfm->cCharacters - 1); i++)
424: {
425: // search for the matching code in mapping.h. remember
426: // that the high bit is used to indicate the font needs
427: // to be remapped. so ignore the high bit while checking
428: // for a character match.
429:
430: if ((CHAR)*pCharCode == (CHAR)pmap->usPSValue)
431: {
432: // we have found the character, now get its UNICODE value
433: // and set its BIT in the BIT array. also, increment the
434: // glyph count, if this UNICODE value has not yet been used.
435: // since the mapping tables in mapping.h are sorted by
436: // UNICODE values, we can simply check this value against
437: // the one we found last time. if it is the same, ignore
438: // it, if it is different, use it.
439:
440: wchCurrent = (WCHAR)pmap->usUCValue;
441:
442: if (wchCurrent != wchPrevious)
443: {
444: // see if we are starting a new run.
445:
446: if ((wchCurrent - wchPrevious) != 1)
447: {
448: // start the new WCRUN.
449:
450: pWCRUN++;
451: pWCRUN->wcLow = wchCurrent;
452: pWCRUN->cGlyphs = 0;
453: pWCRUN->phg = phg;
454: }
455:
456: // fill in the glyph handle.
457:
458: pWCRUN->cGlyphs++;
459: *phg++ = (HGLYPH)*pCharCode;
460: }
461:
462: wchPrevious = wchCurrent;
463: break;
464: }
465:
466: pCharCode++;
467: }
468:
469: // point to next character in mapping table.
470:
471: pmap++;
472: }
473:
474: return(pulUCTree);
475: }
476:
477:
478: //--------------------------------------------------------------------------
479: // PVOID BuildKernPairs(pdev, iFace)
480: // PDEVDATA pdev;
481: // ULONG iFace;
482: //
483: // This routine returns a pointer to a zero terminated array of
484: // FD_KERNINGPAIR structures. They should be sorted in order such that
485: // the first character is the most significant, and the second character
486: // is the least.
487: //
488: // If an error occurs, NULL should be returned and an error code should
489: // be logged.
490: //
491: // History:
492: // 12-Mar-1992 -by- Kent Settle (kentse)
493: // Wrote it.
494: //--------------------------------------------------------------------------
495:
496: PVOID BuildKernPairs(pdev, iFace)
497: PDEVDATA pdev;
498: ULONG iFace;
499: {
500: PNTFM pntfm; // pointer to font metrics.
501: FD_KERNINGPAIR *pKernPairs; // pointer to FD_KERNINGPAIRs.
502: FD_KERNINGPAIR *pKernPairsSave; // pointer to FD_KERNINGPAIRs.
503: DWORD cjMem; // count of bytes.
504: DWORD cKernPairs; // cound of kernpairs.
505: FD_KERNINGPAIR *pkp; // pointer to kernpair in ntfm struct.
506:
507: // get the font information for the given font.
508:
509: pntfm = pdev->pfmtable[iFace - 1].pntfm;
510:
511: // allocate enough memory to hold all the FD_KERNINGPAIR strutures.
512: // remember to allocate room for the zero terminated structure.
513: // NOTE! the memory allocated here is never explicitly freed. this
514: // will happen when the pdev, and therefore the heap, is destroyed.
515: // this is done, since this memory is supposed to remain here for
516: // the engine until the pdev is destroyed.
517:
518: cKernPairs = (DWORD)pntfm->cKernPairs;
519: cjMem = ((cKernPairs + 1) * sizeof(FD_KERNINGPAIR));
520:
521: if (!(pKernPairs = (FD_KERNINGPAIR *)HeapAlloc(pdev->hheap, 0, cjMem)))
522: {
523: RIP("PSCRIPT!BuildKernPairs: HeapAlloc for pKernPairs failed.\n");
524: return((PVOID)NULL);
525: }
526:
527: // save a copy of the original pointer.
528:
529: pKernPairsSave = pKernPairs;
530:
531: // fill in the FD_KERNINGPAIR structure for each kerning pair.
532:
533: pkp = (FD_KERNINGPAIR *)((BYTE *)pntfm + pntfm->loKernPairs);
534:
535: while (cKernPairs--)
536: *pKernPairs++ = *pkp++;
537:
538: // fill in the zero terminating FD_KERNINGPAIR structure.
539:
540: pKernPairs->wcFirst = (WCHAR)'\0';
541: pKernPairs->wcSecond = (WCHAR)'\0';
542: pKernPairs->fwdKern = (FWORD)0;
543:
544: return(pKernPairsSave);
545: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.