You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1361 lines
37 KiB
1361 lines
37 KiB
/*++
|
|
|
|
Copyright (c) 1996 Adobe Systems Incorporated
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cjkfonts.c
|
|
|
|
Abstract:
|
|
|
|
Convert CJK AFMs to NTMs.
|
|
|
|
Environment:
|
|
|
|
Windows NT PostScript driver: makentf utility.
|
|
|
|
Revision History:
|
|
|
|
02/10/98 -ksuzuki-
|
|
Added OCF font support using 83pv font; did code cleanup, especially
|
|
of the CreateCJKGlyphSets function.
|
|
|
|
01/13/96 -rkiesler-
|
|
Wrote it.
|
|
-*/
|
|
|
|
#include "lib.h"
|
|
#include "ppd.h"
|
|
#include "pslib.h"
|
|
#include "psglyph.h"
|
|
#include "afm2ntm.h"
|
|
#include "cjkfonts.h"
|
|
#include "winfont.h"
|
|
|
|
extern BOOL bVerbose;
|
|
|
|
ULONG
|
|
CreateCJKGlyphSets(
|
|
PBYTE *pUV2CCMaps,
|
|
PBYTE *pUV2CIDMaps,
|
|
PGLYPHSETDATA *pGlyphSets,
|
|
PWINCODEPAGE pWinCodePage,
|
|
PULONG *pUniPsTbl
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given memory mapped file ptrs to H and V Unicode to CharCode map files
|
|
and H and V Unicode to CID map files, create 2 GLYPHSETDATA structures
|
|
which represent H and V variants of the character collection. Create
|
|
ptrs to 2 tables which map glyph indices to CIDs for each variant.
|
|
|
|
Arguments:
|
|
|
|
pUV2CCMaps - Pointer to two memory mapped map files. These map Unicode
|
|
value to corresponding character code. pUV2CCMaps[0] and pUV2CCMaps[1]
|
|
for H and V respectively.
|
|
|
|
pUV2CIDMaps - Pointer to two memory mapped map files. These Unicode to
|
|
corresponding CID. pUV2CIDMaps[0] and pUV2CIDMaps[1] for H and V
|
|
respectively.
|
|
|
|
pGlyphSets - two position array of GLYPHSETDATA pointers which upon
|
|
successful completion contain the addresses of the newly allocated
|
|
GLYPHSETDATA structs representing the H and V variants of the char
|
|
collection.
|
|
|
|
pWinCodePage - Pts to a WINCODEPAGE struct which provides Windows
|
|
specific info about this charset.
|
|
|
|
pUniPsTbl - two position array of ULONG ptrs which each pts to a table
|
|
which maps 0-based Glyph Indices of chars in the GLYPHRUNS of the
|
|
GLYPHSETDATA for this char collection to CIDs.
|
|
|
|
Return Value:
|
|
|
|
TRUE => success.
|
|
FALSE => error.
|
|
|
|
--*/
|
|
|
|
{
|
|
PBYTE pToken, pGlyphSetName;
|
|
ULONG cChars, cRuns, cRanges, curCID;
|
|
USHORT cCharRun;
|
|
PGLYPHRUN pGlyphRuns;
|
|
PCMAP pUv2CcMap[NUM_VARIANTS];
|
|
PCMAP pUv2CidMap[NUM_VARIANTS];
|
|
ULONG c, i, uv;
|
|
PVOID pMapTbl;
|
|
PCMAPRANGE pCMapRange;
|
|
PCMAP pSrchCMap;
|
|
ULONG cGlyphSetBytes[NUM_VARIANTS], cSizeBytes[NUM_VARIANTS];
|
|
BOOLEAN bFound, bInRun;
|
|
USHORT wcRunStrt;
|
|
DWORD dwGSNameSize, dwCodePageInfoSize, dwGlyphRunSize, dwCPIGSNameSize;
|
|
DWORD dwEncodingNameOffset;
|
|
PCODEPAGEINFO pCodePageInfo;
|
|
BOOL bSingleCodePage;
|
|
|
|
|
|
if (bVerbose) printf("%%%%[Begin Create CJK glyphset]%%%%\n\n");
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Create the local Unicode->CharCode and Unicode->CID Maps sorted in
|
|
// starting Unicode order.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Get pointer to, and determine size of, the name strings for each variant.
|
|
//
|
|
for (i = 0; i < NUM_VARIANTS; i++)
|
|
{
|
|
//
|
|
// Process the Unicode->CharCode map to determine the number of its
|
|
// chars and runs.
|
|
//
|
|
if (NumUV2CCRuns(pUV2CCMaps[i], &cRuns, &cChars) == FALSE)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Alloc memory for create local CMap structs needed to build
|
|
// GLYPHSETs.
|
|
//
|
|
pUv2CcMap[i] = (PCMAP)MemAllocZ(sizeof(CMAP) + sizeof(CMAPRANGE) * (cRuns - 1));
|
|
if (pUv2CcMap[i] == NULL)
|
|
{
|
|
ERR(("makentf - CreateCJKGlyphSets: MemAllocZ\n"));
|
|
return(FALSE);
|
|
}
|
|
pUv2CcMap[i]->cChars = cChars;
|
|
|
|
if (BuildUV2CCMap(pUV2CCMaps[i], pUv2CcMap[i]) == FALSE)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Sort the CMap ranges in starting Unicode order.
|
|
//
|
|
qsort(pUv2CcMap[i]->CMapRange,
|
|
(size_t)pUv2CcMap[i]->cRuns,
|
|
(size_t)sizeof(CMAPRANGE),
|
|
CmpCMapRunsChCode);
|
|
|
|
//
|
|
// Process the Unicode->CID map to determine the number of its
|
|
// chars and runs.
|
|
//
|
|
if (NumUV2CIDRuns(pUV2CIDMaps[i], &cRuns, &cChars) == FALSE)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
pUv2CidMap[i] = (PCMAP)MemAllocZ(sizeof(CMAP) + sizeof(CMAPRANGE) * (cRuns - 1));
|
|
if (pUv2CidMap[i] == NULL)
|
|
{
|
|
ERR(("makentf - CreateCJKGlyphSets: MemAllocZ\n"));
|
|
return(FALSE);
|
|
}
|
|
pUv2CidMap[i]->cChars = cChars;
|
|
|
|
if (BuildUV2CIDMap(pUV2CIDMaps[i], pUv2CidMap[i]) == FALSE)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Sort CMap Ranges in Starting char code order.
|
|
//
|
|
qsort(pUv2CidMap[i]->CMapRange,
|
|
(size_t)pUv2CidMap[i]->cRuns,
|
|
(size_t)sizeof(CMAPRANGE),
|
|
CmpCMapRunsChCode);
|
|
}
|
|
|
|
//
|
|
// CJK fonts never have multiple codepages, but, we figure it out anyway
|
|
// just in case.
|
|
//
|
|
bSingleCodePage = (pWinCodePage->usNumBaseCsets == 1) ? TRUE : FALSE;
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Create H GLYPHSETDATA
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Count chars and runs in H CMaps.
|
|
//
|
|
// Look up all Unicode points in the H Unicode->CID map and the H Unicode->
|
|
// CharCode map to determine number of GLYPHRUNs required for the
|
|
// GLYPHSETDATA we are about to create.
|
|
//
|
|
cChars = cRuns = 0;
|
|
bInRun = bFound = FALSE;
|
|
|
|
for (uv = 0; uv < NUM_UNICODE_CHARS; uv++)
|
|
{
|
|
//
|
|
// Search for the Unicode value in H Unicode->CharCode map.
|
|
//
|
|
pCMapRange = (PCMAPRANGE)bsearch(&uv,
|
|
pUv2CidMap[H_CMAP]->CMapRange,
|
|
pUv2CidMap[H_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun);
|
|
|
|
bFound = (pCMapRange != NULL);
|
|
|
|
if (bFound)
|
|
{
|
|
//
|
|
// Found this unicode value in H Unicode->CID map. Determine if it
|
|
// maps to a CharCode in H Unicode->CharCode map.
|
|
//
|
|
bFound = (bsearch(&uv,
|
|
pUv2CcMap[H_CMAP]->CMapRange,
|
|
pUv2CcMap[H_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun) != NULL);
|
|
|
|
if (bFound)
|
|
{
|
|
cChars++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determine if this is a new run.
|
|
//
|
|
bInRun = bFound && bInRun;
|
|
if (bFound && !bInRun)
|
|
{
|
|
cRuns++;
|
|
bInRun = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Compute amount of memory required for H GLYPHSET.
|
|
// Note to account for the H/V char appended to the GlyphSet name.
|
|
//
|
|
dwGSNameSize = ALIGN4(strlen(pWinCodePage->pszCPname) + 2);
|
|
dwCodePageInfoSize = ALIGN4(pWinCodePage->usNumBaseCsets * sizeof(CODEPAGEINFO));
|
|
dwGlyphRunSize = ALIGN4(cRuns * sizeof(GLYPHRUN));
|
|
|
|
cGlyphSetBytes[H_CMAP] = ALIGN4(sizeof(GLYPHSETDATA));
|
|
cGlyphSetBytes[H_CMAP] += dwGSNameSize;
|
|
cGlyphSetBytes[H_CMAP] += dwCodePageInfoSize;
|
|
cGlyphSetBytes[H_CMAP] += dwGlyphRunSize;
|
|
|
|
//
|
|
// Account for the size of the mapping table.
|
|
//
|
|
cGlyphSetBytes[H_CMAP] += bSingleCodePage ? ALIGN4((cChars * sizeof (WORD))) : (cChars * sizeof (DWORD));
|
|
|
|
//
|
|
// Account for size of CODEPAGE name strings found in CODEPAGEINFO
|
|
// struct(s).
|
|
//
|
|
for (dwCPIGSNameSize = 0, i = 0; i < pWinCodePage->usNumBaseCsets; i++)
|
|
{
|
|
dwCPIGSNameSize += ALIGN4(strlen(aPStoCP[pWinCodePage->pCsetList[i]].pGSName) + 1);
|
|
}
|
|
cGlyphSetBytes[H_CMAP] += dwCPIGSNameSize;
|
|
|
|
//
|
|
// Alloc memory for H GLYPHSET, Unicode->CID mapping table.
|
|
//
|
|
pGlyphSets[H_CMAP] = (PGLYPHSETDATA)MemAllocZ(cGlyphSetBytes[H_CMAP]);
|
|
if (pGlyphSets[H_CMAP] == NULL)
|
|
{
|
|
ERR(("makentf - CreateCJKGlyphSets: malloc\n"));
|
|
return(FALSE);
|
|
}
|
|
|
|
pUniPsTbl[H_CMAP] = (PULONG)MemAllocZ(cChars * sizeof(ULONG));
|
|
if (pUniPsTbl[H_CMAP] == NULL)
|
|
{
|
|
ERR(("makentf - CreateCJKGlyphSets: malloc\n"));
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Init GLYPHSETDATA for H.
|
|
//
|
|
pGlyphSets[H_CMAP]->dwSize = cGlyphSetBytes[H_CMAP];
|
|
pGlyphSets[H_CMAP]->dwVersion = GLYPHSETDATA_VERSION;
|
|
pGlyphSets[H_CMAP]->dwFlags = 0;
|
|
pGlyphSets[H_CMAP]->dwGlyphSetNameOffset = ALIGN4(sizeof(GLYPHSETDATA));
|
|
pGlyphSets[H_CMAP]->dwGlyphCount = cChars;
|
|
pGlyphSets[H_CMAP]->dwCodePageCount = pWinCodePage->usNumBaseCsets;
|
|
pGlyphSets[H_CMAP]->dwCodePageOffset = pGlyphSets[H_CMAP]->dwGlyphSetNameOffset + dwGSNameSize;
|
|
pGlyphSets[H_CMAP]->dwRunCount = cRuns;
|
|
pGlyphSets[H_CMAP]->dwRunOffset = pGlyphSets[H_CMAP]->dwCodePageOffset + dwCodePageInfoSize + dwCPIGSNameSize;
|
|
pGlyphSets[H_CMAP]->dwMappingTableOffset = pGlyphSets[H_CMAP]->dwRunOffset + dwGlyphRunSize;
|
|
|
|
//
|
|
// Set the mapping table type flag to dwFlags field.
|
|
//
|
|
pGlyphSets[H_CMAP]->dwFlags |= bSingleCodePage ? GSD_MTT_WCC : GSD_MTT_DWCPCC;
|
|
|
|
//
|
|
// Store GlyphSet name
|
|
//
|
|
pGlyphSetName = (PBYTE)MK_PTR(pGlyphSets[H_CMAP], dwGlyphSetNameOffset);
|
|
StringCchCopyA(pGlyphSetName, dwGSNameSize, pWinCodePage->pszCPname);
|
|
pGlyphSetName[strlen(pWinCodePage->pszCPname)] = 'H';
|
|
pGlyphSetName[strlen(pWinCodePage->pszCPname) + 1] = '\0';
|
|
|
|
//
|
|
// Initialize a CODEPAGEINFO struct for each base charset supported
|
|
// by this font.
|
|
//
|
|
pCodePageInfo = (PCODEPAGEINFO)MK_PTR(pGlyphSets[H_CMAP], dwCodePageOffset);
|
|
dwEncodingNameOffset = dwCodePageInfoSize;
|
|
|
|
for (i = 0; i < pWinCodePage->usNumBaseCsets; i++, pCodePageInfo++)
|
|
{
|
|
//
|
|
// Save CODEPAGEINFO name, id. We don't use PS encoding vectors.
|
|
//
|
|
pCodePageInfo->dwCodePage = aPStoCP[pWinCodePage->pCsetList[i]].usACP;
|
|
pCodePageInfo->dwWinCharset = (DWORD)aPStoCP[pWinCodePage->pCsetList[i]].jWinCharset;
|
|
pCodePageInfo->dwEncodingNameOffset = dwEncodingNameOffset;
|
|
pCodePageInfo->dwEncodingVectorDataSize = 0;
|
|
pCodePageInfo->dwEncodingVectorDataOffset = 0;
|
|
|
|
//
|
|
// Copy codepage name string to end of array of CODEPAGEINFOs.
|
|
//
|
|
StringCchCopyA((PBYTE)MK_PTR(pCodePageInfo, dwEncodingNameOffset),
|
|
ALIGN4(strlen(aPStoCP[pWinCodePage->pCsetList[i]].pGSName) + 1),
|
|
aPStoCP[pWinCodePage->pCsetList[i]].pGSName);
|
|
|
|
//
|
|
// Adjust the offset to the CodePage name for the next CODEPAGEINFO structure.
|
|
//
|
|
dwEncodingNameOffset -= ALIGN4(sizeof (CODEPAGEINFO));
|
|
dwEncodingNameOffset += ALIGN4(strlen(aPStoCP[pWinCodePage->pCsetList[i]].pGSName) + 1);
|
|
}
|
|
|
|
//
|
|
// Process H Unicode->CID/CharCode maps to determine the number of its
|
|
// chars and runs.
|
|
//
|
|
cRuns = 0;
|
|
cCharRun = 0;
|
|
bInRun = FALSE;
|
|
pGlyphRuns = GSD_GET_GLYPHRUN(pGlyphSets[H_CMAP]);
|
|
pMapTbl = GSD_GET_MAPPINGTABLE(pGlyphSets[H_CMAP]);
|
|
|
|
for (uv = c = 0; (uv < NUM_UNICODE_CHARS) && (c < cChars); uv++)
|
|
{
|
|
pCMapRange = bsearch(&uv,
|
|
pUv2CidMap[H_CMAP]->CMapRange,
|
|
pUv2CidMap[H_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun);
|
|
|
|
bFound = (pCMapRange != NULL);
|
|
|
|
if (bFound)
|
|
{
|
|
curCID = pCMapRange->CIDStrt + uv - pCMapRange->ChCodeStrt;
|
|
|
|
pCMapRange = bsearch(&uv,
|
|
pUv2CcMap[H_CMAP]->CMapRange,
|
|
pUv2CcMap[H_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun);
|
|
|
|
bFound = (pCMapRange != NULL);
|
|
|
|
if (bFound)
|
|
{
|
|
//
|
|
// Found this Unicode value in Unicode->CharCode map. Store in
|
|
// mapping table. Note that CJK fonts only support 1 charset
|
|
// per font.
|
|
//
|
|
pUniPsTbl[H_CMAP][c] = curCID;
|
|
|
|
if (bSingleCodePage)
|
|
{
|
|
if (pCMapRange != NULL)
|
|
((WORD*)pMapTbl)[c] = (WORD)(pCMapRange->CIDStrt + (uv - pCMapRange->ChCodeStrt));
|
|
else
|
|
((WORD*)pMapTbl)[c] = (WORD)uv;
|
|
}
|
|
else
|
|
{
|
|
((DWORD*)pMapTbl)[c] = aPStoCP[pWinCodePage->pCsetList[0]].usACP << 16;
|
|
if (pCMapRange != NULL)
|
|
{
|
|
((DWORD*)pMapTbl)[c] |= pCMapRange->CIDStrt + (uv - pCMapRange->ChCodeStrt);
|
|
}
|
|
else
|
|
{
|
|
((DWORD*)pMapTbl)[c] |= uv;
|
|
}
|
|
}
|
|
|
|
c++;
|
|
cCharRun++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determine if this is a new Unicode run.
|
|
//
|
|
if (bFound && !bInRun)
|
|
{
|
|
//
|
|
// This is the beginning of a new run.
|
|
//
|
|
bInRun = TRUE;
|
|
pGlyphRuns[cRuns].wcLow = (USHORT) (uv & 0xffff);
|
|
}
|
|
|
|
//
|
|
// Determine if this is the end of a run.
|
|
//
|
|
if (bInRun && (!bFound || uv == NUM_UNICODE_CHARS || c == cChars))
|
|
{
|
|
//
|
|
// This is the end of a run.
|
|
//
|
|
bInRun = FALSE;
|
|
pGlyphRuns[cRuns].wGlyphCount = cCharRun;
|
|
cRuns++;
|
|
cCharRun = 0;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Create V GLYPHSETDATA
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Count chars and runs in V maps.
|
|
//
|
|
// For the V GLYPHSETDATA, if a Unicode value is not found in V Unicode->
|
|
// CID map, we will then need to check H Unicode->CID map.
|
|
//
|
|
cChars = cRuns = 0;
|
|
bInRun = bFound = FALSE;
|
|
|
|
for (uv = 0; uv < NUM_UNICODE_CHARS; uv++)
|
|
{
|
|
//
|
|
// Search for the Unicode value in V, and then H Unicode->CID maps if
|
|
// not found.
|
|
//
|
|
pCMapRange = bsearch(&uv,
|
|
pUv2CidMap[V_CMAP]->CMapRange,
|
|
pUv2CidMap[V_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun);
|
|
|
|
bFound = (pCMapRange != NULL);
|
|
|
|
if (bFound == FALSE)
|
|
{
|
|
pCMapRange = bsearch(&uv,
|
|
pUv2CidMap[H_CMAP]->CMapRange,
|
|
pUv2CidMap[H_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun);
|
|
|
|
bFound = (pCMapRange != NULL);
|
|
}
|
|
|
|
if (bFound)
|
|
{
|
|
//
|
|
// Found this unicode value. Determine if it maps to a CharCode in
|
|
// H or V Unicode->CharCode map.
|
|
//
|
|
pCMapRange = bsearch(&uv,
|
|
pUv2CcMap[V_CMAP]->CMapRange,
|
|
pUv2CcMap[V_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun);
|
|
|
|
bFound = (pCMapRange != NULL);
|
|
|
|
if (bFound == FALSE)
|
|
{
|
|
pCMapRange = bsearch(&uv,
|
|
pUv2CcMap[H_CMAP]->CMapRange,
|
|
pUv2CcMap[H_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun);
|
|
|
|
bFound = (pCMapRange != NULL);
|
|
}
|
|
|
|
if (bFound)
|
|
{
|
|
cChars++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determine if this is a new run.
|
|
//
|
|
bInRun = bFound && bInRun;
|
|
if (bFound && !bInRun)
|
|
{
|
|
cRuns++;
|
|
bInRun = TRUE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Compute amount of memory required for V GLYPHSET.
|
|
//
|
|
dwGSNameSize = ALIGN4(strlen(pWinCodePage->pszCPname) + 2);
|
|
dwCodePageInfoSize = ALIGN4(pWinCodePage->usNumBaseCsets * sizeof(CODEPAGEINFO));
|
|
dwGlyphRunSize = ALIGN4(cRuns * sizeof(GLYPHRUN));
|
|
|
|
cGlyphSetBytes[V_CMAP] = ALIGN4(sizeof(GLYPHSETDATA));
|
|
cGlyphSetBytes[V_CMAP] += dwGSNameSize;
|
|
cGlyphSetBytes[V_CMAP] += dwCodePageInfoSize;
|
|
cGlyphSetBytes[V_CMAP] += dwGlyphRunSize;
|
|
|
|
//
|
|
// Account for the size of the mapping table.
|
|
//
|
|
cGlyphSetBytes[V_CMAP] += bSingleCodePage ? ALIGN4((cChars * sizeof (WORD))) : (cChars * sizeof (DWORD));
|
|
|
|
//
|
|
// Account for size of CODEPAGE name strings found in CODEPAGEINFO
|
|
// struct(s).
|
|
//
|
|
for (dwCPIGSNameSize = 0, i = 0; i < pWinCodePage->usNumBaseCsets; i++)
|
|
{
|
|
dwCPIGSNameSize += ALIGN4(strlen(aPStoCP[pWinCodePage->pCsetList[i]].pGSName) + 1);
|
|
}
|
|
cGlyphSetBytes[V_CMAP] += dwCPIGSNameSize;
|
|
|
|
//
|
|
// Alloc memory for V GLYPHSET, Unicode->CID mapping table.
|
|
//
|
|
pGlyphSets[V_CMAP] = (PGLYPHSETDATA)MemAllocZ(cGlyphSetBytes[V_CMAP]);
|
|
if (pGlyphSets[V_CMAP] == NULL)
|
|
{
|
|
ERR(("makentf - CreateCJKGlyphSets: malloc\n"));
|
|
return(FALSE);
|
|
}
|
|
|
|
pUniPsTbl[V_CMAP] = (PULONG)MemAllocZ(cChars * sizeof(ULONG));
|
|
if (pUniPsTbl[V_CMAP] == NULL)
|
|
{
|
|
ERR(("makentf - CreateCJKGlyphSets: malloc\n"));
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Init GLYPHSETDATA for V.
|
|
//
|
|
pGlyphSets[V_CMAP]->dwSize = cGlyphSetBytes[V_CMAP];
|
|
pGlyphSets[V_CMAP]->dwVersion = GLYPHSETDATA_VERSION;
|
|
pGlyphSets[V_CMAP]->dwFlags = 0;
|
|
pGlyphSets[V_CMAP]->dwGlyphSetNameOffset = ALIGN4(sizeof(GLYPHSETDATA));
|
|
pGlyphSets[V_CMAP]->dwGlyphCount = cChars;
|
|
pGlyphSets[V_CMAP]->dwCodePageCount = pWinCodePage->usNumBaseCsets;
|
|
pGlyphSets[V_CMAP]->dwCodePageOffset = pGlyphSets[V_CMAP]->dwGlyphSetNameOffset + dwGSNameSize;
|
|
pGlyphSets[V_CMAP]->dwRunCount = cRuns;
|
|
pGlyphSets[V_CMAP]->dwRunOffset = pGlyphSets[V_CMAP]->dwCodePageOffset + dwCodePageInfoSize + dwCPIGSNameSize;
|
|
pGlyphSets[V_CMAP]->dwMappingTableOffset = pGlyphSets[V_CMAP]->dwRunOffset + dwGlyphRunSize;
|
|
|
|
//
|
|
// Set the mapping table type flag to dwFlags field.
|
|
//
|
|
pGlyphSets[V_CMAP]->dwFlags |= bSingleCodePage ? GSD_MTT_WCC : GSD_MTT_DWCPCC;
|
|
|
|
//
|
|
// Store GlyphSet name
|
|
//
|
|
pGlyphSetName = (PBYTE)MK_PTR(pGlyphSets[V_CMAP], dwGlyphSetNameOffset);
|
|
StringCchCopyA(pGlyphSetName, dwGSNameSize, pWinCodePage->pszCPname);
|
|
pGlyphSetName[strlen(pWinCodePage->pszCPname)] = 'V';
|
|
pGlyphSetName[strlen(pWinCodePage->pszCPname) + 1] = '\0';
|
|
|
|
//
|
|
// Initialize a CODEPAGEINFO struct for each base charset supported
|
|
// by this font.
|
|
//
|
|
pCodePageInfo = (PCODEPAGEINFO) MK_PTR(pGlyphSets[V_CMAP], dwCodePageOffset);
|
|
dwEncodingNameOffset = dwCodePageInfoSize;
|
|
|
|
for (i = 0; i < pWinCodePage->usNumBaseCsets; i++, pCodePageInfo++)
|
|
{
|
|
//
|
|
// Save CODEPAGEINFO name, id. We don't use PS encoding vectors.
|
|
//
|
|
pCodePageInfo->dwCodePage = aPStoCP[pWinCodePage->pCsetList[i]].usACP;
|
|
pCodePageInfo->dwWinCharset = (DWORD)aPStoCP[pWinCodePage->pCsetList[i]].jWinCharset;
|
|
pCodePageInfo->dwEncodingNameOffset = dwEncodingNameOffset;
|
|
pCodePageInfo->dwEncodingVectorDataSize = 0;
|
|
pCodePageInfo->dwEncodingVectorDataOffset = 0;
|
|
|
|
//
|
|
// Copy codepage name string to end of array of CODEPAGEINFOs.
|
|
//
|
|
StringCchCopyA((PBYTE)MK_PTR(pCodePageInfo, dwEncodingNameOffset),
|
|
ALIGN4(strlen(aPStoCP[pWinCodePage->pCsetList[i]].pGSName) + 1),
|
|
aPStoCP[pWinCodePage->pCsetList[i]].pGSName);
|
|
|
|
//
|
|
// Adjust the offset to the CodePage name for the next CODEPAGEINFO structure.
|
|
//
|
|
dwEncodingNameOffset -= sizeof(CODEPAGEINFO);
|
|
dwEncodingNameOffset += ALIGN4(strlen((PSZ)MK_PTR(pCodePageInfo, dwEncodingNameOffset)) + 1);
|
|
}
|
|
|
|
//
|
|
// Create V Glyphset by merging V and H Maps.
|
|
//
|
|
|
|
//
|
|
// Determine number of runs, chars in the Glyphset created when V and H
|
|
// Maps are merged.
|
|
//
|
|
cRuns = 0;
|
|
cCharRun = 0;
|
|
bInRun = bFound = FALSE;
|
|
pGlyphRuns = GSD_GET_GLYPHRUN(pGlyphSets[V_CMAP]);
|
|
pMapTbl = GSD_GET_MAPPINGTABLE(pGlyphSets[V_CMAP]);
|
|
|
|
for (uv = c = 0; (uv < NUM_UNICODE_CHARS) && (c < cChars); uv++)
|
|
{
|
|
pCMapRange = bsearch(&uv,
|
|
pUv2CidMap[V_CMAP]->CMapRange,
|
|
pUv2CidMap[V_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun);
|
|
|
|
bFound = (pCMapRange != NULL);
|
|
|
|
if (bFound == FALSE)
|
|
{
|
|
pCMapRange = bsearch(&uv,
|
|
pUv2CidMap[H_CMAP]->CMapRange,
|
|
pUv2CidMap[H_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun);
|
|
|
|
bFound = (pCMapRange != NULL);
|
|
}
|
|
|
|
//
|
|
// Found this Unicode value. Determine if it maps to a CharCode in H
|
|
// or V Unicode->CC map.
|
|
//
|
|
if (bFound)
|
|
{
|
|
curCID = pCMapRange->CIDStrt + (uv - pCMapRange->ChCodeStrt);
|
|
|
|
pCMapRange = bsearch(&uv,
|
|
pUv2CcMap[V_CMAP]->CMapRange,
|
|
pUv2CcMap[V_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun);
|
|
|
|
bFound = (pCMapRange != NULL);
|
|
|
|
if (bFound == FALSE)
|
|
{
|
|
pCMapRange = bsearch(&uv,
|
|
pUv2CcMap[H_CMAP]->CMapRange,
|
|
pUv2CcMap[H_CMAP]->cRuns,
|
|
sizeof(CMAPRANGE),
|
|
FindChCodeRun);
|
|
|
|
bFound = (pCMapRange != NULL);
|
|
}
|
|
|
|
if (bFound)
|
|
{
|
|
//
|
|
// Found this Unicode value in Unicode->CharCode map. Store in
|
|
// mapping table. Note that CJK fonts only support 1 charset
|
|
// per font.
|
|
//
|
|
pUniPsTbl[V_CMAP][c] = curCID;
|
|
|
|
if (bSingleCodePage)
|
|
{
|
|
if (pCMapRange != NULL)
|
|
((WORD*)pMapTbl)[c] = (WORD)(pCMapRange->CIDStrt + (uv - pCMapRange->ChCodeStrt));
|
|
else
|
|
((WORD*)pMapTbl)[c] = (WORD)uv;
|
|
}
|
|
else
|
|
{
|
|
((DWORD*)pMapTbl)[c] = aPStoCP[pWinCodePage->pCsetList[0]].usACP << 16;
|
|
if (pCMapRange != NULL)
|
|
{
|
|
((DWORD*)pMapTbl)[c] |= pCMapRange->CIDStrt + (uv - pCMapRange->ChCodeStrt);
|
|
}
|
|
else
|
|
{
|
|
((DWORD*)pMapTbl)[c] |= uv;
|
|
}
|
|
}
|
|
|
|
c++;
|
|
cCharRun++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determine if this is a new Unicode run.
|
|
//
|
|
if (bFound && !bInRun)
|
|
{
|
|
//
|
|
// This is the beginning of a new run.
|
|
//
|
|
bInRun = TRUE;
|
|
pGlyphRuns[cRuns].wcLow = (USHORT) (uv & 0xffff);
|
|
}
|
|
|
|
//
|
|
// Determine if this is the end of a run.
|
|
//
|
|
if (bInRun && (!bFound || uv == NUM_UNICODE_CHARS || c == cChars))
|
|
{
|
|
//
|
|
// This is the end of a run.
|
|
//
|
|
bInRun = FALSE;
|
|
pGlyphRuns[cRuns].wGlyphCount = cCharRun;
|
|
cRuns++;
|
|
cCharRun = 0;
|
|
}
|
|
}
|
|
|
|
if (bVerbose)
|
|
{
|
|
for (i = 0; i < NUM_VARIANTS; i++)
|
|
{
|
|
printf("GLYPHSETDATA:dwFlags:%08X\n", pGlyphSets[i]->dwFlags);
|
|
printf("GLYPHSETDATA:dwGlyphSetNameOffset:%s\n",
|
|
(PSZ)MK_PTR(pGlyphSets[i], dwGlyphSetNameOffset));
|
|
printf("GLYPHSETDATA:dwGlyphCount:%ld\n", pGlyphSets[i]->dwGlyphCount);
|
|
printf("GLYPHSETDATA:dwRunCount:%ld\n", pGlyphSets[i]->dwRunCount);
|
|
printf("GLYPHSETDATA:dwCodePageCount:%ld\n", pGlyphSets[i]->dwCodePageCount);
|
|
{
|
|
DWORD dw;
|
|
PCODEPAGEINFO pcpi = (PCODEPAGEINFO)MK_PTR(pGlyphSets[i], dwCodePageOffset);
|
|
for (dw = 1; dw <= pGlyphSets[i]->dwCodePageCount; dw++)
|
|
{
|
|
printf("CODEPAGEINFO#%ld:dwCodePage:%ld\n", dw, pcpi->dwCodePage);
|
|
printf("CODEPAGEINFO#%ld:dwWinCharset:%ld\n", dw, pcpi->dwWinCharset);
|
|
printf("CODEPAGEINFO#%ld:dwEncodingNameOffset:%s\n",
|
|
dw, (PSZ)MK_PTR(pcpi, dwEncodingNameOffset));
|
|
pcpi++;
|
|
}
|
|
}
|
|
printf("\n");
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clean-up: free the local Maps.
|
|
//
|
|
for (i = 0; i < NUM_VARIANTS; i++)
|
|
{
|
|
//
|
|
// Free temporary data structs.
|
|
//
|
|
if (pUv2CcMap[i] != NULL)
|
|
{
|
|
MemFree(pUv2CcMap[i]);
|
|
}
|
|
if (pUv2CidMap[i] != NULL)
|
|
{
|
|
MemFree(pUv2CidMap[i]);
|
|
}
|
|
}
|
|
|
|
if (bVerbose) printf("%%[End Create CJK glyphset]%%%%\n\n");
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOLEAN
|
|
NumUV2CIDRuns(
|
|
PBYTE pCMapFile,
|
|
PULONG pcRuns,
|
|
PULONG pcChars
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given a memory mapped file ptr to a Postscript CMap, determine
|
|
the number of CIDRanges (Runs) and total number of chars.
|
|
|
|
Arguments:
|
|
|
|
pCMapFile - Pointer to a memory mapped CMap file.
|
|
pcRuns - Pointer to a ULONG which will contain the number of runs.
|
|
pcChars - Pointer to a ULONG which will contain the number of chars.
|
|
|
|
Return Value:
|
|
|
|
TRUE => success
|
|
FALSE => error
|
|
|
|
--*/
|
|
{
|
|
PBYTE pToken;
|
|
ULONG cRanges, i;
|
|
USHORT chRunStrt, chRunEnd;
|
|
BYTE LineBuffer[25];
|
|
USHORT usLineLen;
|
|
|
|
*pcRuns = *pcChars = 0;
|
|
|
|
//
|
|
// Search for the CID ranges, and determine the number of runs and
|
|
// total number of chars in this GLYPHSET.
|
|
//
|
|
for (; (pCMapFile = FindStringToken(pCMapFile, CID_RANGE_TOK)) != NULL; )
|
|
{
|
|
GET_NUM_CID_RANGES(pCMapFile, cRanges);
|
|
*pcRuns += cRanges;
|
|
NEXT_LINE(pCMapFile);
|
|
for (i = 0; i < cRanges; i++)
|
|
{
|
|
PARSE_TOKEN(pCMapFile, pToken);
|
|
//
|
|
// Get begin and end range codes.
|
|
//
|
|
if (!AsciiToHex(pToken, &chRunStrt))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
if (!AsciiToHex(pCMapFile, &chRunEnd))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Compute size of run.
|
|
//
|
|
*pcChars += chRunEnd - chRunStrt + 1;
|
|
NEXT_LINE(pCMapFile);
|
|
}
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOLEAN
|
|
BuildUV2CIDMap(
|
|
PBYTE pCMapFile,
|
|
PCMAP pCMap
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given a memory mapped file ptr to a Postscript CMap, create a CMAP
|
|
struture which contains char run information.
|
|
|
|
Arguments:
|
|
|
|
pCMapFile - Pointer to a memory mapped CMap file.
|
|
pCMap - Pointer to pre allocated memory large enough to contain the CMap.
|
|
|
|
Return Value:
|
|
|
|
TRUE => success.
|
|
FALSE => error.
|
|
|
|
--*/
|
|
{
|
|
ULONG i, cRuns, cRanges;
|
|
USHORT chRunStrt, chRunEnd;
|
|
PBYTE pToken;
|
|
|
|
//
|
|
// Process the CMap to determine the number of CID runs
|
|
// and the number of chars in this char collection.
|
|
//
|
|
cRuns = cRanges = 0;
|
|
for (; (pCMapFile = FindStringToken(pCMapFile, CID_RANGE_TOK)) != NULL; )
|
|
{
|
|
GET_NUM_CID_RANGES(pCMapFile, cRanges);
|
|
|
|
//
|
|
// Skip to first range.
|
|
//
|
|
NEXT_LINE(pCMapFile);
|
|
for (i = 0; i < cRanges; i++)
|
|
{
|
|
//
|
|
// Retrieve the start and stop codes.
|
|
//
|
|
PARSE_TOKEN(pCMapFile, pToken);
|
|
|
|
//
|
|
// Get begin and end range codes.
|
|
//
|
|
if (!AsciiToHex(pToken, &chRunStrt))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
if (!AsciiToHex(pCMapFile, &chRunEnd))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
pCMap->CMapRange[cRuns + i].ChCodeStrt = chRunStrt;
|
|
pCMap->CMapRange[cRuns + i].cChars = chRunEnd - chRunStrt + 1;
|
|
|
|
//
|
|
// Get CID.
|
|
//
|
|
PARSE_TOKEN(pCMapFile, pToken);
|
|
pCMap->CMapRange[cRuns + i].CIDStrt = atol(pCMapFile);
|
|
NEXT_LINE(pCMapFile);
|
|
}
|
|
cRuns += cRanges;
|
|
}
|
|
pCMap->cRuns = cRuns;
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOLEAN
|
|
NumUV2CCRuns(
|
|
PBYTE pFile,
|
|
PULONG pcRuns,
|
|
PULONG pcChars
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given a memory mapped file ptr to a Unicode to CharCode mapping,
|
|
determine the number of runs and total number of chars.
|
|
|
|
Arguments:
|
|
|
|
pFile - Pointer to a memory mapped file.
|
|
pcRuns - Pointer to a ULONG which will contain the number of runs.
|
|
pcChars - Pointer to a ULONG which will contain the number of chars.
|
|
|
|
Return Value:
|
|
|
|
TRUE => success
|
|
FALSE => error
|
|
|
|
--*/
|
|
{
|
|
PBYTE pToken;
|
|
USHORT lastUnicode, lastCharCode;
|
|
USHORT currentUnicode, currentCharCode;
|
|
ULONG numChars, numRuns;
|
|
|
|
*pcRuns = *pcChars = 0;
|
|
numChars = numRuns = 0;
|
|
|
|
lastUnicode = lastCharCode = 0;
|
|
currentUnicode = currentCharCode = 0;
|
|
|
|
while (TRUE)
|
|
{
|
|
PARSE_TOKEN(pFile, pToken);
|
|
if (StrCmp(pToken, "EOF") != 0)
|
|
{
|
|
if (!AsciiToHex(pToken, ¤tUnicode))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
PARSE_TOKEN(pFile, pToken);
|
|
if (StrCmp(pToken, "EOF") != 0)
|
|
{
|
|
if (!AsciiToHex(pToken, ¤tCharCode))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
else
|
|
return(FALSE);
|
|
|
|
(*pcChars)++;
|
|
}
|
|
else
|
|
return(TRUE);
|
|
|
|
if ((currentUnicode > (lastUnicode + 1)) ||
|
|
(currentCharCode != (lastCharCode + 1)))
|
|
{
|
|
(*pcRuns)++;
|
|
}
|
|
|
|
lastUnicode = currentUnicode;
|
|
lastCharCode = currentCharCode;
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
BuildUV2CCMap(
|
|
PBYTE pFile,
|
|
PCMAP pCMap
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given a memory mapped file ptr to a Unicode to CharCode mapping,
|
|
create a CMAP struture which contains char run information.
|
|
|
|
Arguments:
|
|
|
|
pFile - Pointer to a memory mapped file.
|
|
pCMap - Pointer to pre allocated memory large enough to contain the CMAP.
|
|
|
|
Return Value:
|
|
|
|
TRUE => success.
|
|
FALSE => error.
|
|
|
|
--*/
|
|
{
|
|
PBYTE pToken;
|
|
USHORT startUnicode, startCharCode;
|
|
USHORT lastUnicode, lastCharCode;
|
|
USHORT currentUnicode, currentCharCode;
|
|
ULONG cRuns;
|
|
BOOL done = FALSE;
|
|
|
|
startUnicode = startCharCode = 0;
|
|
lastUnicode = lastCharCode = 0;
|
|
currentUnicode = currentCharCode = 0;
|
|
cRuns = 0;
|
|
|
|
while (!done)
|
|
{
|
|
PARSE_TOKEN(pFile, pToken);
|
|
if (StrCmp(pToken, "EOF") != 0)
|
|
{
|
|
if (!AsciiToHex(pToken, ¤tUnicode))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
PARSE_TOKEN(pFile, pToken);
|
|
if (StrCmp(pToken, "EOF") != 0)
|
|
{
|
|
if (!AsciiToHex(pToken, ¤tCharCode))
|
|
{
|
|
return(FALSE);
|
|
}
|
|
}
|
|
else
|
|
return(FALSE);
|
|
}
|
|
else
|
|
done = TRUE;
|
|
|
|
if ((currentUnicode > (lastUnicode + 1)) ||
|
|
(currentCharCode != (lastCharCode + 1)) ||
|
|
(done))
|
|
{
|
|
if (startUnicode > 0)
|
|
{
|
|
pCMap->CMapRange[cRuns].ChCodeStrt = startUnicode;
|
|
pCMap->CMapRange[cRuns].cChars = lastUnicode - startUnicode + 1;
|
|
pCMap->CMapRange[cRuns].CIDStrt = startCharCode;
|
|
cRuns++;
|
|
}
|
|
startUnicode = currentUnicode;
|
|
startCharCode = currentCharCode;
|
|
}
|
|
|
|
lastUnicode = currentUnicode;
|
|
lastCharCode = currentCharCode;
|
|
}
|
|
|
|
pCMap->cRuns = cRuns;
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
int __cdecl
|
|
CmpCMapRunsCID(
|
|
const VOID *p1,
|
|
const VOID *p2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compares the starting CID of two CMAPRANGE structs.
|
|
|
|
Arguments:
|
|
|
|
p1, p2 - CMAPRANGEs to compare.
|
|
|
|
Return Value:
|
|
|
|
-1 => p1 < p2
|
|
1 => p1 > p2
|
|
0 => p1 = p2
|
|
|
|
--*/
|
|
{
|
|
PCMAPRANGE ptr1 = (PCMAPRANGE) p1, ptr2 = (PCMAPRANGE) p2;
|
|
|
|
//
|
|
// Compare starting CIDs of the ranges.
|
|
//
|
|
if (ptr1->CIDStrt > ptr2->CIDStrt)
|
|
return(1);
|
|
else if (ptr1->CIDStrt < ptr2->CIDStrt)
|
|
return(-1);
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
int __cdecl
|
|
CmpCMapRunsChCode(
|
|
const VOID *p1,
|
|
const VOID *p2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compares the starting Char Code of two CMAPRANGE structs.
|
|
|
|
Arguments:
|
|
|
|
p1, p2 - CMAPRANGEs to compare.
|
|
|
|
Return Value:
|
|
|
|
-1 => p1 < p2
|
|
1 => p1 > p2
|
|
0 => p1 = p2
|
|
|
|
--*/
|
|
{
|
|
PCMAPRANGE ptr1 = (PCMAPRANGE) p1, ptr2 = (PCMAPRANGE) p2;
|
|
|
|
//
|
|
// Compare starting CIDs of the ranges.
|
|
//
|
|
if (ptr1->ChCodeStrt < ptr2->ChCodeStrt)
|
|
return(-1);
|
|
else if (ptr1->ChCodeStrt > ptr2->ChCodeStrt)
|
|
return(1);
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
int __cdecl
|
|
FindChCodeRun(
|
|
const VOID *p1,
|
|
const VOID *p2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determines if a Charcode falls within a particular CMap run.
|
|
|
|
Arguments:
|
|
|
|
p1 - CID
|
|
p2 - PCMAPRANGE to check
|
|
|
|
Return Value:
|
|
|
|
-1 => p1 < p2
|
|
1 => p1 > p2
|
|
0 => p1 = p2
|
|
|
|
--*/
|
|
{
|
|
PULONG ptr1 = (PULONG) p1;
|
|
PCMAPRANGE ptr2 = (PCMAPRANGE) p2;
|
|
|
|
//
|
|
// Determine if CID is in the current range.
|
|
//
|
|
if (*ptr1 < ptr2->ChCodeStrt)
|
|
return(-1);
|
|
else if (*ptr1 >= (ULONG) ptr2->ChCodeStrt + ptr2->cChars)
|
|
return(1);
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
int __cdecl
|
|
FindCIDRun(
|
|
const VOID *p1,
|
|
const VOID *p2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determines if a CID falls within a particular CMap run.
|
|
|
|
Arguments:
|
|
|
|
p1 - CID
|
|
p2 - PCMAPRANGE to check
|
|
|
|
Return Value:
|
|
|
|
-1 => p1 < p2
|
|
1 => p1 > p2
|
|
0 => p1 = p2
|
|
|
|
--*/
|
|
{
|
|
PULONG ptr1 = (PULONG) p1;
|
|
PCMAPRANGE ptr2 = (PCMAPRANGE) p2;
|
|
|
|
//
|
|
// Determine if CID is in the current range.
|
|
//
|
|
if (*ptr1 < ptr2->CIDStrt)
|
|
return(-1);
|
|
else if (*ptr1 >= ptr2->CIDStrt + ptr2->cChars)
|
|
return(1);
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
CHSETSUPPORT
|
|
IsCJKFont(
|
|
PBYTE pAFM
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine if a font is a CJK (Far Eastern) font.
|
|
|
|
Arguments:
|
|
|
|
pAFM - ptr to memory mapped AFM file
|
|
|
|
Return Value:
|
|
|
|
0 - Font not CJK
|
|
Otherwise, font is CJK, and return value is the Win Codepage value
|
|
|
|
--*/
|
|
{
|
|
PBYTE pToken;
|
|
USHORT i;
|
|
|
|
//
|
|
// Search for CharacterSet token.
|
|
//
|
|
pToken = pAFMCharacterSetString;
|
|
if (pToken == NULL)
|
|
{
|
|
//
|
|
// We can't determine if this font is CJK, so assume it isn't.
|
|
//
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Search for CharSet (actually Adobe Char Collection) name in CJK table.
|
|
//
|
|
for (i = 0; i < CjkColTbl.usNumEntries; i++)
|
|
{
|
|
if (!StrCmp(pToken, (PBYTE) (((PKEY) (CjkColTbl.pTbl))[i].pName)))
|
|
{
|
|
return(CSUP(((PKEY) (CjkColTbl.pTbl))[i].usValue));
|
|
}
|
|
}
|
|
|
|
//
|
|
// Not a recognized CJK font.
|
|
//
|
|
return 0;
|
|
}
|
|
|
|
BOOLEAN
|
|
IsVGlyphSet(
|
|
PGLYPHSETDATA pGlyphSetData
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine if a Glyphset is a CJK V variant. Should ONLY be used with
|
|
CJK Glyphsets, otherwise result could be unpredictable!
|
|
|
|
Arguments:
|
|
|
|
pGlyphSetData - ptr to GLYPHSETDATA
|
|
|
|
Return Value:
|
|
|
|
TRUE - this is a V variant
|
|
FALSE - not a V variant
|
|
|
|
--*/
|
|
{
|
|
PBYTE pName;
|
|
|
|
pName = (PBYTE) MK_PTR(pGlyphSetData, dwGlyphSetNameOffset);
|
|
return((pName[strlen(pName) - 1] == 'V'));
|
|
}
|
|
|
|
BOOLEAN
|
|
IsCIDFont(
|
|
PBYTE pAFM
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine if a font is a CID font.
|
|
|
|
Arguments:
|
|
|
|
pAFM - ptr to memory mapped AFM file
|
|
|
|
Return Value:
|
|
|
|
0 - Font not clone.
|
|
Otherwise, font is a CID font, and return value non-zero.
|
|
|
|
--*/
|
|
{
|
|
PBYTE pToken;
|
|
|
|
if (pToken = FindAFMToken(pAFM, PS_CIDFONT_TOK))
|
|
{
|
|
if (!StrCmp(pToken, "true"))
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|