|
|
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.