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.
1123 lines
33 KiB
1123 lines
33 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
makentf.c
|
|
|
|
Abstract:
|
|
|
|
Utility to convert AFM file(s) to NTF file.
|
|
|
|
Environment:
|
|
|
|
Windows NT PostScript driver.
|
|
|
|
Revision History:
|
|
|
|
02/16/98 -ksuzuki-
|
|
Added OCF font support.
|
|
|
|
09/08/97 -ksuzuki-
|
|
Added code to look for PSFAMILY.DAT file from the directory where
|
|
makentf is invoked.
|
|
|
|
09/16/96 -PPeng-
|
|
Add the fucntion to write PS Encoding vectors out - for debugging and
|
|
create PS Encoding Arrays as PScript resource files.
|
|
|
|
09/16/96 -slam-
|
|
Created.
|
|
|
|
mm/dd/yy -author-
|
|
description
|
|
|
|
--*/
|
|
|
|
#include <windows.h>
|
|
|
|
#include "lib.h"
|
|
#include "ppd.h"
|
|
#include "pslib.h"
|
|
#include "afm2ntm.h"
|
|
#include "cjkfonts.h"
|
|
#include "writentf.h"
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
HINSTANCE ghInstance;
|
|
PUPSCODEPT UnicodetoPs;
|
|
PTBL pFamilyTbl;
|
|
PSTR pAFMCharacterSetString;
|
|
PSTR Adobe_Japan1_0 = "Adobe-Japan1-0\n";
|
|
DWORD dwLastErr;
|
|
PSTR pAFMFileName = NULL;
|
|
BOOL bVerbose = FALSE;
|
|
BOOL bOptimize = FALSE;
|
|
|
|
// Number of auxiliary character set. Its cheif
|
|
// purpose is to support 83pv.
|
|
#define NUM_AUX_CS 1
|
|
|
|
// This macro is used to see whether the argument
|
|
// matches the differential between CS_SHIFTJIS
|
|
// and CS_WEST_MAX.
|
|
#define IS_CS_SHIFTJIS(delta) \
|
|
((delta) == (CS_SHIFTJIS - CS_WEST_MAX))
|
|
|
|
//
|
|
// Prototype
|
|
//
|
|
BOOL
|
|
WritePSEncodings(
|
|
IN PWSTR pwszFileName,
|
|
IN WINCPTOPS *CPtoPSList,
|
|
IN DWORD dwPages
|
|
);
|
|
BOOL NeedBuildMoreNTM(
|
|
PBYTE pAFM
|
|
);
|
|
|
|
|
|
void __cdecl
|
|
main(
|
|
int argc,
|
|
char **argv
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Makentf takes four steps to create a .NTF file.
|
|
|
|
Step 1: Initialization.
|
|
|
|
Step 2: Convert AFM(s) to NTM(s).
|
|
|
|
Step 3: Write GLYPHSETDATA(s) and NTM(s) to a .NTF file.
|
|
|
|
Step 4: Clean up.
|
|
|
|
Arguments:
|
|
|
|
argc - The path of and arguments given to this program.
|
|
argv - The number of elements pointed to by argc.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
WCHAR wstrNTFFile[MAX_PATH];
|
|
WCHAR wstrAFMFile[MAX_PATH];
|
|
WCHAR wstrDATFile[MAX_PATH];
|
|
WCHAR DatFilePath[MAX_PATH];
|
|
PNTM *aPNTM;
|
|
PNTM pNTM;
|
|
PGLYPHSETDATA *aGlyphSets;
|
|
PWINCODEPAGE *aWinCodePages;
|
|
PWINCODEPAGE pAllWinCodePages[CS_MAX];
|
|
PUPSCODEPT pFontChars;
|
|
CHSETSUPPORT flCsupFont, flCsupGlyphSet, flCsupMatch, flCsupAll;
|
|
ULONG cNumNTM, cSizeNTM, ulLength, nUnicodeChars;
|
|
PULONG *aUniPsTbl;
|
|
LONG lMatch, lMatchAll;
|
|
PBYTE pAFM;
|
|
FLONG flCurCset, flLastCset;
|
|
ULONG cNumGlyphSets, cSizeGlyphSets;
|
|
DWORD ulFileSize;
|
|
PBYTE pFamDatFile;
|
|
PBYTE pCMaps[CMAPS_PER_COL];
|
|
HANDLE hmodule, hModCMaps[CMAPS_PER_COL];
|
|
USHORT cNTMCurFont;
|
|
INT nArgcOffset;
|
|
LONG c;
|
|
ULONG i, j;
|
|
BOOL bIs90mspFont;
|
|
BOOL bIsKSCmsHWFont;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Step 1: Initialization.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Check if there are enough parameters.
|
|
//
|
|
if (argc == 1)
|
|
{
|
|
printf("MakeNTF usage:\n");
|
|
printf("1. MakeNTF [-v] [-o] <NTF> <AFMs>\n");
|
|
printf(" Create an NTF file from AFM files.\n");
|
|
printf(" -v: verbose (print various info)\n");
|
|
printf(" -o: optimize (write glyphset only referenced)\n");
|
|
printf("\n");
|
|
printf("2. MakeNTF <PSEncodingNameList>\n");
|
|
printf(" Generate PS encoding name list.\n");
|
|
return;
|
|
}
|
|
|
|
wstrNTFFile[0] = 0;
|
|
|
|
if (argc == 2)
|
|
{
|
|
ulLength = strlen(argv[1]) + 1;
|
|
MULTIBYTETOUNICODE(wstrNTFFile,
|
|
ulLength*sizeof(WCHAR),
|
|
NULL,
|
|
argv[1],
|
|
ulLength);
|
|
WritePSEncodings(wstrNTFFile, &aPStoCP[0], CS_MAX);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
nArgcOffset = 0;
|
|
|
|
for (i = 1; i <= 2; i++)
|
|
{
|
|
if (!strcmp(argv[i], "-v"))
|
|
{
|
|
bVerbose = TRUE;
|
|
nArgcOffset++;
|
|
}
|
|
if (!strcmp(argv[i], "-o"))
|
|
{
|
|
bOptimize = TRUE;
|
|
nArgcOffset++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bVerbose) printf("%%%%[Begin MakeNTF]%%%%\n\n");
|
|
|
|
//
|
|
// Initiliaze variables that relate to memory allocation.
|
|
//
|
|
aPNTM = NULL;
|
|
aGlyphSets = NULL;
|
|
pFamilyTbl = NULL;
|
|
UnicodetoPs = NULL;
|
|
aUniPsTbl = NULL;
|
|
aWinCodePages = NULL;
|
|
cNumNTM = cSizeNTM = 0;
|
|
cNumGlyphSets = cSizeGlyphSets = 0;
|
|
|
|
//
|
|
// Initialize Glyphset counter, list of all possible Windows charsets.
|
|
//
|
|
for (i =0; i < CS_MAX; i++)
|
|
{
|
|
pAllWinCodePages[i] = &aStdCPList[i];
|
|
}
|
|
|
|
//
|
|
// Create a copy of the Unicode->PS char mapping table and sort it
|
|
// in Unicode point order.
|
|
//
|
|
if ((UnicodetoPs =
|
|
(PUPSCODEPT) MemAllocZ((size_t) sizeof(UPSCODEPT) * NUM_PS_CHARS))
|
|
== NULL)
|
|
{
|
|
dwLastErr = GetLastError();
|
|
ERR(("makentf - main: malloc for UnicodetoPs (%ld)\n", dwLastErr));
|
|
return;
|
|
}
|
|
memcpy(UnicodetoPs, PstoUnicode, (size_t) sizeof(UPSCODEPT) * NUM_PS_CHARS);
|
|
qsort(UnicodetoPs,
|
|
(size_t) NUM_PS_CHARS,
|
|
(size_t) sizeof(UPSCODEPT),
|
|
CmpUniCodePts);
|
|
|
|
//
|
|
// Build complete path name for PS family DAT file.
|
|
//
|
|
GetCurrentDirectory(MAX_PATH, DatFilePath);
|
|
StringCchCatW(DatFilePath, CCHOF(DatFilePath), DatFileName);
|
|
|
|
//
|
|
// Open PS font family .DAT file and build the font family table.
|
|
//
|
|
if (!(hmodule = MapFileIntoMemory(DatFilePath, &pFamDatFile, &ulFileSize)))
|
|
{
|
|
//
|
|
// One more try: look for it from the directory where makentf is
|
|
// invoked (or from the root directory).
|
|
//
|
|
DECLSPEC_IMPORT LPWSTR* APIENTRY CommandLineToArgvW(LPCWSTR, int*);
|
|
LPWSTR p, pLast, *pCmdLine;
|
|
int nArgc;
|
|
|
|
pCmdLine = CommandLineToArgvW(GetCommandLineW(), &nArgc);
|
|
if (pCmdLine == NULL)
|
|
{
|
|
dwLastErr = GetLastError();
|
|
ERR(("makentf - main: CommandLineToArgvW (%ld)\n", dwLastErr));
|
|
UnmapFileFromMemory(hmodule);
|
|
goto CLEAN_UP;
|
|
}
|
|
StringCchCopyW(DatFilePath, CCHOF(DatFilePath), pCmdLine[0]);
|
|
GlobalFree(pCmdLine);
|
|
|
|
p = pLast = DatFilePath;
|
|
while ((p = wcsstr(p, L"\\")) != NULL)
|
|
{
|
|
pLast = p;
|
|
p += 2;
|
|
}
|
|
StringCchCopyW(pLast, CCHOF(DatFilePath) - (pLast - DatFilePath), DatFileName);
|
|
hmodule = MapFileIntoMemory(DatFilePath, &pFamDatFile, &ulFileSize);
|
|
if (!hmodule)
|
|
{
|
|
dwLastErr = GetLastError();
|
|
ERR(("makentf - main: can't open PSFAMILY.DAT file (%ld)\n", dwLastErr));
|
|
UnmapFileFromMemory(hmodule);
|
|
goto CLEAN_UP;
|
|
}
|
|
}
|
|
BuildPSFamilyTable(pFamDatFile, &pFamilyTbl, ulFileSize);
|
|
UnmapFileFromMemory(hmodule);
|
|
|
|
//
|
|
// Allocate memory to store NTM pointers.
|
|
//
|
|
// We quadruple the number of the arguments of this program to get the
|
|
// number of NTM pointer. This is because
|
|
//
|
|
// 1) we need four NTM pointers maximum (two for H and V plus two for J
|
|
// 90ms and 83pv) for a CJK AFM, but,
|
|
// 2) we don't know at this time that how many of CJK AFMs we are going
|
|
// to process.
|
|
//
|
|
// Since we're only allocating pointers here it's usually OK to quadruple
|
|
// the number of the arguments and use it as the number of NTM pointers
|
|
// we need. (Don't forget to subtract two - one for the name of this
|
|
// program and the other for the target NTM file name - from the number
|
|
// of the arguments prior to quadruple.)
|
|
//
|
|
|
|
// Add 90msp-RKSJ support. we need 2 more NTFs - H and V for 90msp.
|
|
// So I change the estimation number from 4 to 6. Jack 3/15/2000
|
|
// aPNTM = MemAllocZ(((argc - 2 - nArgcOffset) * 4) * sizeof(PNTM));
|
|
|
|
aPNTM = MemAllocZ(((argc - 2 - nArgcOffset) * 6) * sizeof(PNTM));
|
|
if (aPNTM == NULL)
|
|
{
|
|
dwLastErr = GetLastError();
|
|
ERR(("makentf - main: malloc for aPNTM (%ld)\n", dwLastErr));
|
|
goto CLEAN_UP;
|
|
}
|
|
|
|
//
|
|
// Allocate memory to store pointers to Glyphset related data. We don't
|
|
// know how many Glyphsets we will need - but we know it will be at most
|
|
// equal to the number of character sets we support, although this will
|
|
// probably never occur. Since we're only allocating ptrs here we'll go
|
|
// ahead and alloc the max. Don't forget an extra entry for the Unicode
|
|
// GLYPHSET data.
|
|
//
|
|
|
|
i = CS_WEST_MAX + (CS_MAX - CS_WEST_MAX + NUM_AUX_CS) * 2;
|
|
|
|
if ((aGlyphSets = MemAllocZ(i * sizeof(PGLYPHSETDATA))) == NULL)
|
|
{
|
|
dwLastErr = GetLastError();
|
|
ERR(("makentf - main: malloc for aGlyphSets (%ld)\n", dwLastErr));
|
|
goto CLEAN_UP;
|
|
}
|
|
if ((aUniPsTbl = MemAllocZ(i * sizeof(PULONG))) == NULL)
|
|
{
|
|
dwLastErr = GetLastError();
|
|
ERR(("makentf - main: malloc for aUniPsTbl (%ld)\n", dwLastErr));
|
|
goto CLEAN_UP;
|
|
}
|
|
if ((aWinCodePages = MemAllocZ(i * sizeof(PWINCODEPAGE))) == NULL)
|
|
{
|
|
dwLastErr = GetLastError();
|
|
ERR(("makentf - main: malloc for aWinCodePages (%ld)\n", dwLastErr));
|
|
goto CLEAN_UP;
|
|
}
|
|
|
|
//
|
|
// Precreate Western GLYPHSETs.
|
|
// Note that this for loop assumes that the enum numbers from CS_228 to
|
|
// CS_WEST_MAX are in ascending order incrementally.
|
|
//
|
|
if (bVerbose && !bOptimize) printf("%%%%[Begin Precreate Western Glyphsets]%%%%\n\n");
|
|
|
|
for (i = CS_228; i < CS_WEST_MAX; i++, cNumGlyphSets++)
|
|
{
|
|
aWinCodePages[cNumGlyphSets] = &aStdCPList[i];
|
|
CreateGlyphSets(&aGlyphSets[cNumGlyphSets],
|
|
aWinCodePages[cNumGlyphSets],
|
|
&aUniPsTbl[cNumGlyphSets]);
|
|
cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize;
|
|
}
|
|
|
|
if (bVerbose && !bOptimize) printf("%%%%[End Precreate Western Glyphsets]%%%%\n\n");
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Step 2: Convert AFM(s) to NTM(s).
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
if (bVerbose) printf("%%%%[Begin Covert AFM to NTM]%%%%\n\n");
|
|
|
|
for (i = 2 + nArgcOffset; i < (ULONG)argc; i++)
|
|
{
|
|
//
|
|
// Get AFM filename.
|
|
//
|
|
ulLength = strlen(argv[i]) + 1;
|
|
MULTIBYTETOUNICODE(wstrAFMFile,
|
|
ulLength*sizeof(WCHAR),
|
|
NULL,
|
|
argv[i],
|
|
ulLength);
|
|
|
|
//
|
|
// Map AFM file into memory.
|
|
//
|
|
if (!(hmodule = MapFileIntoMemory(wstrAFMFile, &pAFM, NULL)))
|
|
{
|
|
dwLastErr = GetLastError();
|
|
ERR(("makentf - main: MapFileIntoMemory (%ld)\n", dwLastErr));
|
|
goto CLEAN_UP;
|
|
}
|
|
|
|
pAFMFileName = argv[i];
|
|
|
|
bIs90mspFont = FALSE;
|
|
bIsKSCmsHWFont = FALSE;
|
|
|
|
//
|
|
// Initialization of pAFMCharacterSet must be done here
|
|
// *before* CREATE_OCF_DATA_FROM_CID_DATA tag. The cheif
|
|
// purpose of the initialization here is to support
|
|
// OCF/83pv font.
|
|
//
|
|
pAFMCharacterSetString = FindAFMToken(pAFM, PS_CHARSET_TOK);
|
|
CREATE_OCF_DATA_FROM_CID_DATA:
|
|
|
|
//
|
|
// Determine which charsets this font supports. To find that,
|
|
// we use the following variables.
|
|
//
|
|
// flCsupFont: Combination of charset of the target font
|
|
// flCsupGlyphSet: Charset of the target font's glyphset
|
|
// lMatch: Index corresponding to CHSETSUPPORT, or -1
|
|
// flCsupMatch: Combination of charset of a closest font, or 0
|
|
//
|
|
flCsupFont = GetAFMCharSetSupport(pAFM, &flCsupGlyphSet);
|
|
|
|
CREATE_90MSP_RKSJ_NTM:
|
|
CREATE_KSCMS_HW_NTM:
|
|
lMatch = -1;
|
|
flCsupMatch = 0;
|
|
if (flCsupGlyphSet == CS_NOCHARSET)
|
|
{
|
|
//
|
|
// Determine if the current font matches any of the codepages
|
|
// we have created so far.
|
|
//
|
|
lMatch = FindClosestCodePage(aWinCodePages,
|
|
cNumGlyphSets,
|
|
flCsupFont,
|
|
&flCsupMatch);
|
|
}
|
|
else
|
|
{
|
|
if (flCsupGlyphSet == CS_228)
|
|
lMatch = 0;
|
|
else if (flCsupGlyphSet == CS_314)
|
|
lMatch = 1;
|
|
flCsupMatch = flCsupFont;
|
|
}
|
|
|
|
if ((flCsupGlyphSet == CS_NOCHARSET)
|
|
&&
|
|
((lMatch == -1) || ((flCsupMatch & flCsupFont) != flCsupFont)))
|
|
{
|
|
//
|
|
// Either:
|
|
// We haven't created a charset which could be used to represent
|
|
// this font so far.
|
|
// -or-
|
|
// We know this font supports at least 1 of the charsets we have
|
|
// created, but there might be a better match in the list of all
|
|
// possible charsets.
|
|
//
|
|
lMatchAll = FindClosestCodePage(pAllWinCodePages,
|
|
CS_MAX,
|
|
flCsupFont,
|
|
&flCsupAll);
|
|
if ((flCsupAll == flCsupFont)
|
|
|| (flCsupAll & flCsupFont) > (flCsupMatch & flCsupFont))
|
|
{
|
|
//
|
|
// Found a better match in a codepage which has not yet
|
|
// been created.
|
|
//
|
|
lMatch = lMatchAll;
|
|
|
|
//
|
|
// Create a GLYPHSETDATA struct for this codepage and add
|
|
// it to the list of those we've created so far.
|
|
//
|
|
aWinCodePages[cNumGlyphSets] = &aStdCPList[lMatch];
|
|
|
|
//
|
|
// Determine if this is a CJK font.
|
|
//
|
|
if (lMatch < CS_WEST_MAX)
|
|
{
|
|
//
|
|
// Western font.
|
|
//
|
|
CreateGlyphSets(&aGlyphSets[cNumGlyphSets],
|
|
aWinCodePages[cNumGlyphSets],
|
|
&aUniPsTbl[cNumGlyphSets]);
|
|
|
|
cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize;
|
|
|
|
//
|
|
// Glyphset for this font is the one we just created.
|
|
//
|
|
lMatch = cNumGlyphSets;
|
|
cNumGlyphSets += 1;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// CJK font.
|
|
//
|
|
// Map the CMap files on memory first.
|
|
//
|
|
j = (ULONG)lMatch - CS_WEST_MAX;
|
|
|
|
for (c = 0; c < CMAPS_PER_COL; c++)
|
|
{
|
|
hModCMaps[c] = MapFileIntoMemory(CjkFnameTbl[j][c],
|
|
&pCMaps[c], NULL);
|
|
if (hModCMaps[c] == NULL)
|
|
{
|
|
while (--c >= 0)
|
|
{
|
|
UnmapFileFromMemory(hModCMaps[c]);
|
|
}
|
|
dwLastErr = GetLastError();
|
|
ERR(("makentf - main: MapFileIntoMemory (%ld)\n", dwLastErr));
|
|
goto CLEAN_UP;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Since we're creating 2 GLYPHSETs (H and V variants)
|
|
// Create 2 codepage entries which point to the same
|
|
// Win codepage.
|
|
//
|
|
aWinCodePages[cNumGlyphSets + 1] = &aStdCPList[lMatch];
|
|
|
|
//
|
|
// Use the CMap files to create the new GLYPHSETs.
|
|
//
|
|
CreateCJKGlyphSets(&pCMaps[0],
|
|
&pCMaps[2],
|
|
&aGlyphSets[cNumGlyphSets],
|
|
aWinCodePages[cNumGlyphSets],
|
|
&aUniPsTbl[cNumGlyphSets]);
|
|
|
|
//
|
|
// Unmap the CMap files.
|
|
//
|
|
for (c = 0; c < CMAPS_PER_COL; c++)
|
|
{
|
|
UnmapFileFromMemory(hModCMaps[c]);
|
|
}
|
|
|
|
//
|
|
// We've created both an H and V GLYPHSET.
|
|
//
|
|
cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize;
|
|
cSizeGlyphSets += aGlyphSets[cNumGlyphSets + 1]->dwSize;
|
|
|
|
//
|
|
// Glyphsets for this font are the ones we just created.
|
|
//
|
|
lMatch = cNumGlyphSets;
|
|
cNumGlyphSets += 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Determine number of NTMs to be created for this font.
|
|
//
|
|
cNTMCurFont =
|
|
(aWinCodePages[lMatch]->pCsetList[0] < CS_WEST_MAX) ? 1 : 2;
|
|
|
|
do
|
|
{
|
|
//
|
|
// Generate NTM from AFM.
|
|
//
|
|
aPNTM[cNumNTM] = AFMToNTM(pAFM,
|
|
aGlyphSets[lMatch],
|
|
aUniPsTbl[lMatch],
|
|
((flCsupGlyphSet != CS_NOCHARSET) ? &flCsupFont : NULL),
|
|
((flCsupFont & CS_CJK) ? TRUE : FALSE),
|
|
bIs90mspFont | bIsKSCmsHWFont);
|
|
|
|
if (aPNTM[cNumNTM] != NULL)
|
|
{
|
|
//
|
|
// Put the NTMs into a data array for WriteNTF.
|
|
//
|
|
cSizeNTM += NTM_GET_SIZE(aPNTM[cNumNTM]);
|
|
cNumNTM++;
|
|
}
|
|
else
|
|
{
|
|
ERR(("makentf - main: AFMToNTM failed to create NTM:%s\n", argv[i]));
|
|
}
|
|
|
|
cNTMCurFont--;
|
|
lMatch++;
|
|
} while (cNTMCurFont);
|
|
|
|
//
|
|
// 90msp font support. jjia 3/16/2000
|
|
//
|
|
if (flCsupFont == CSUP(CS_SHIFTJIS))
|
|
{
|
|
if (NeedBuildMoreNTM(pAFM))
|
|
{
|
|
flCsupFont = CSUP(CS_SHIFTJISP);
|
|
bIs90mspFont = TRUE;
|
|
goto CREATE_90MSP_RKSJ_NTM; // here we go again!
|
|
}
|
|
}
|
|
bIs90mspFont = FALSE;
|
|
|
|
if (flCsupFont == CSUP(CS_HANGEUL))
|
|
{
|
|
if (NeedBuildMoreNTM(pAFM))
|
|
{
|
|
flCsupFont = CSUP(CS_HANGEULHW);
|
|
bIsKSCmsHWFont = TRUE;
|
|
goto CREATE_KSCMS_HW_NTM; // here we go again!
|
|
}
|
|
}
|
|
bIsKSCmsHWFont = FALSE;
|
|
|
|
//
|
|
// OCF/83pv font support. Create OCF glyphset and NTM data from
|
|
// CID AFM file.
|
|
//
|
|
if ((flCsupFont == CSUP(CS_SHIFTJIS)) ||
|
|
(flCsupFont == CSUP(CS_SHIFTJISP)))
|
|
{
|
|
pAFMCharacterSetString = Adobe_Japan1_0;
|
|
goto CREATE_OCF_DATA_FROM_CID_DATA; // here we go again!
|
|
}
|
|
|
|
UnmapFileFromMemory(hmodule);
|
|
}
|
|
|
|
if (bVerbose) printf("%%%%[End Convert AFM to NTM]%%%%\n\n");
|
|
|
|
//
|
|
// Create Unicode GLYPHSET. This glyphset is created here since we don't
|
|
// want any NTMs to reference this glyphset.
|
|
//
|
|
if (bVerbose && !bOptimize) printf("%%%%[Begin Create Unicode glyphset]%%%%\n\n");
|
|
|
|
CreateGlyphSets(&aGlyphSets[cNumGlyphSets],
|
|
&UnicodePage,
|
|
&aUniPsTbl[cNumGlyphSets]);
|
|
cSizeGlyphSets += aGlyphSets[cNumGlyphSets]->dwSize;
|
|
cNumGlyphSets++;
|
|
|
|
if (bVerbose && !bOptimize) printf("%%%%[End Create Unicode glyphset]%%%%\n\n");
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Step 3: Write GLYPHSETDATA(s) and NTM(s) to a .NTF file.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
if (bVerbose) printf("%%%%[Begin Write NTF]%%%%\n\n");
|
|
|
|
ulLength = strlen(argv[1 + nArgcOffset]) + 1;
|
|
MULTIBYTETOUNICODE(
|
|
wstrNTFFile,
|
|
ulLength*sizeof(WCHAR),
|
|
NULL,
|
|
argv[1 + nArgcOffset],
|
|
ulLength);
|
|
|
|
if (!WriteNTF(wstrNTFFile,
|
|
cNumGlyphSets,
|
|
cSizeGlyphSets,
|
|
aGlyphSets,
|
|
cNumNTM,
|
|
cSizeNTM,
|
|
aPNTM
|
|
))
|
|
{
|
|
ERR(("makentf: main - Can't write .NTF file\n"));
|
|
}
|
|
|
|
if (bVerbose) printf("%%%%[End Write NTF]%%%%\n\n");
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Step 4: Clean up.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
CLEAN_UP:
|
|
for (i = 0; i < cNumNTM; i++)
|
|
{
|
|
MemFree(aPNTM[i]);
|
|
}
|
|
for (i = 0; i < cNumGlyphSets; i++)
|
|
{
|
|
MemFree(aGlyphSets[i]);
|
|
if (aUniPsTbl[i] != NULL)
|
|
{
|
|
//
|
|
// Could have a null ptr if this is a Pi Font.
|
|
//
|
|
MemFree(aUniPsTbl[i]);
|
|
}
|
|
}
|
|
|
|
MemFree(aPNTM ? aPNTM : NULL);
|
|
MemFree(aGlyphSets ? aGlyphSets : NULL);
|
|
MemFree(pFamilyTbl ? pFamilyTbl : NULL);
|
|
MemFree(UnicodetoPs ? UnicodetoPs : NULL);
|
|
MemFree(aUniPsTbl ? aUniPsTbl : NULL);
|
|
MemFree(aWinCodePages ? aWinCodePages : NULL);
|
|
|
|
if (bVerbose) printf("%%%%[End MakeNTF]%%%%\n\n");
|
|
}
|
|
|
|
|
|
//
|
|
// Formating functions - copied from PScript\Output.c
|
|
//
|
|
INT
|
|
OPVsprintf(
|
|
OUT LPSTR buf,
|
|
IN LPCSTR fmtstr,
|
|
IN va_list arglist
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Takes a pointer to an argument list, then formats and writes
|
|
the given data to the memory pointed to by buffer.
|
|
|
|
Arguments:
|
|
|
|
buf Storage location for output
|
|
fmtstr Format specification
|
|
arglist Pointer to list of arguments
|
|
|
|
Return Value:
|
|
|
|
Return the number of characters written, not including
|
|
the terminating null character, or a negative value if
|
|
an output error occurs.
|
|
|
|
[Note:]
|
|
|
|
This is NOT a full implementation of "vsprintf" as found
|
|
in the C runtime library. Specifically, the only form of
|
|
format specification allowed is %type, where "type" can
|
|
be one of the following characters:
|
|
|
|
d INT signed decimal integer
|
|
l LONG signed decimal integer
|
|
u ULONG unsigned decimal integer
|
|
s CHAR* character string
|
|
c CHAR character
|
|
x,X DWORD hex number (emits at least two digits, uppercase)
|
|
b BOOL boolean (true or false)
|
|
f LONG 24.8 fixed-pointed number
|
|
o CHAR octal number
|
|
|
|
--*/
|
|
|
|
{
|
|
LPSTR ptr = buf;
|
|
|
|
ASSERT(buf && fmtstr);
|
|
|
|
while (*fmtstr != NUL) {
|
|
|
|
if (*fmtstr != '%') {
|
|
|
|
// Normal character
|
|
|
|
*ptr++ = *fmtstr++;
|
|
|
|
} else {
|
|
|
|
// Format specification
|
|
|
|
switch (*++fmtstr) {
|
|
|
|
case 'd': // signed decimal integer
|
|
|
|
_ltoa((LONG) va_arg(arglist, INT), ptr, 10);
|
|
ptr += strlen(ptr);
|
|
break;
|
|
|
|
case 'l': // signed decimal integer
|
|
|
|
_ltoa(va_arg(arglist, LONG), ptr, 10);
|
|
ptr += strlen(ptr);
|
|
break;
|
|
|
|
case 'u': // unsigned decimal integer
|
|
|
|
_ultoa(va_arg(arglist, ULONG), ptr, 10);
|
|
ptr += strlen(ptr);
|
|
break;
|
|
|
|
case 's': // character string
|
|
|
|
{ LPSTR s = va_arg(arglist, LPSTR);
|
|
|
|
while (*s)
|
|
*ptr++ = *s++;
|
|
}
|
|
break;
|
|
|
|
case 'c': // character
|
|
|
|
*ptr++ = va_arg(arglist, CHAR);
|
|
break;
|
|
|
|
case 'x':
|
|
case 'X': // hexdecimal number
|
|
|
|
{ ULONG ul = va_arg(arglist, ULONG);
|
|
INT ndigits = 8;
|
|
|
|
while (ndigits > 2 && ((ul >> (ndigits-1)*4) & 0xf) == 0)
|
|
ndigits--;
|
|
|
|
while (ndigits-- > 0)
|
|
*ptr++ = HexDigit(ul >> ndigits*4);
|
|
}
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
{ CHAR ch = va_arg(arglist, CHAR);
|
|
|
|
*ptr++ = (char)((ch & 0xC0) >> 6) + (char)'0';
|
|
*ptr++ = (char)((ch & 0x38) >> 3) + (char)'0';
|
|
*ptr++ = (char)(ch & 0x07) + (char)'0';
|
|
}
|
|
break;
|
|
|
|
case 'b': // boolean
|
|
|
|
StringCchCopyA(ptr, (size_t)((ptr - buf)/sizeof(CHAR)), (va_arg(arglist, BOOL)) ? "true" : "false");
|
|
ptr += strlen(ptr);
|
|
break;
|
|
|
|
case 'f': // 24.8 fixed-pointed number
|
|
|
|
{
|
|
LONG l = va_arg(arglist, LONG);
|
|
ULONG ul, scale;
|
|
|
|
// sign character
|
|
|
|
if (l < 0) {
|
|
*ptr++ = '-';
|
|
ul = -l;
|
|
} else
|
|
ul = l;
|
|
|
|
// integer portion
|
|
|
|
_ultoa(ul >> 8, ptr, 10);
|
|
ptr += strlen(ptr);
|
|
|
|
// fraction
|
|
|
|
ul &= 0xff;
|
|
if (ul != 0) {
|
|
|
|
// We output a maximum of 3 digits after the
|
|
// decimal point, but we'll compute to the 5th
|
|
// decimal point and round it to 3rd.
|
|
|
|
ul = ((ul*100000 >> 8) + 50) / 100;
|
|
scale = 100;
|
|
|
|
*ptr++ = '.';
|
|
|
|
do {
|
|
|
|
*ptr++ = (CHAR) (ul/scale + '0');
|
|
ul %= scale;
|
|
scale /= 10;
|
|
|
|
} while (scale != 0 && ul != 0) ;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
if (*fmtstr != NUL)
|
|
*ptr++ = *fmtstr;
|
|
else {
|
|
ERR(("Invalid format specification\n"));
|
|
fmtstr--;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Skip the type characterr
|
|
|
|
fmtstr++;
|
|
}
|
|
}
|
|
|
|
*ptr = NUL;
|
|
return (INT)(ptr - buf);
|
|
}
|
|
|
|
|
|
|
|
INT
|
|
OPSprintf(
|
|
OUT LPSTR buf,
|
|
IN LPCSTR fmtstr,
|
|
IN ...
|
|
)
|
|
|
|
{
|
|
va_list arglist;
|
|
INT iRc;
|
|
|
|
va_start(arglist, fmtstr);
|
|
iRc = OPVsprintf(buf, fmtstr, arglist);
|
|
va_end(arglist);
|
|
|
|
return iRc;
|
|
}
|
|
|
|
|
|
int __cdecl compareWinCpt(const void *elem1, const void *elem2)
|
|
{
|
|
PWINCPT p1;
|
|
PWINCPT p2;
|
|
|
|
p1 = (PWINCPT)elem1;
|
|
p2 = (PWINCPT)elem2;
|
|
|
|
if (p1->usWinCpt == p2->usWinCpt)
|
|
return(0);
|
|
else if (p1->usWinCpt < p2->usWinCpt)
|
|
return(-1);
|
|
else
|
|
return(1);
|
|
}
|
|
|
|
|
|
VOID
|
|
SortWinCPT(
|
|
IN OUT WINCPT *pSortedWinCpts,
|
|
IN WINCPTOPS *pCPtoPS
|
|
)
|
|
{
|
|
// pSortedWinCpts must point to a buffer big enough sizeof(WINCPT)* MAX_CSET_CHARS)
|
|
|
|
memcpy(pSortedWinCpts, &(pCPtoPS->aWinCpts), sizeof(WINCPT)* MAX_CSET_CHARS);
|
|
|
|
qsort(pSortedWinCpts, pCPtoPS->ulChCnt, sizeof(WINCPT), compareWinCpt);
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// This function reads a list of CP to PS Name tables and writes an Text file
|
|
// with the corresponding PostScript Encoding arrays
|
|
// Need to run this whenever we changed the Mapping tables
|
|
//
|
|
// Format:
|
|
// 10 20 30 40
|
|
// 1234567890123456789012345678901234567890
|
|
// CodePage = dddd (name)
|
|
// /name_up_to_32 % XX
|
|
//
|
|
|
|
BOOL
|
|
WritePSEncodings(
|
|
IN PWSTR pwszFileName,
|
|
IN WINCPTOPS *CPtoPSList,
|
|
IN DWORD dwPages
|
|
)
|
|
{
|
|
HANDLE hFile;
|
|
ULONG i, j, k, l;
|
|
WINCPTOPS *pCPtoPS;
|
|
WINCPT sortedWinCpts[MAX_CSET_CHARS]; // maxiaml 255 chars
|
|
char buffer[256];
|
|
DWORD dwLen, ulByteWritten;
|
|
|
|
|
|
hFile = CreateFile(pwszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL,
|
|
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
ERR(("WritePSEncodings:CreateFile\n"));
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
for (i = 0; i < dwPages; i++)
|
|
{
|
|
pCPtoPS = CPtoPSList + i;
|
|
|
|
dwLen = OPSprintf(buffer, "\n\n CodePage = %d (%s)\n",
|
|
pCPtoPS->usACP, pCPtoPS->pGSName);
|
|
|
|
if (!WriteFile(hFile, buffer, dwLen, (LPDWORD)&ulByteWritten, (LPOVERLAPPED)NULL)
|
|
|| ulByteWritten != dwLen)
|
|
{
|
|
ERR(("WritePSEncodings:WriteFile\n"));
|
|
CloseHandle(hFile);
|
|
return(FALSE);
|
|
}
|
|
|
|
SortWinCPT(&(sortedWinCpts[0]), pCPtoPS);
|
|
|
|
k = sortedWinCpts[0].usWinCpt;
|
|
for (j = 0; j < pCPtoPS->ulChCnt; j++, k++)
|
|
{
|
|
while (k < sortedWinCpts[j].usWinCpt)
|
|
{
|
|
dwLen = OPSprintf(buffer, " %% %X\n", k);
|
|
if (!WriteFile(hFile, buffer, dwLen, (LPDWORD)&ulByteWritten, (LPOVERLAPPED)NULL)
|
|
|| ulByteWritten != dwLen)
|
|
{
|
|
ERR(("WritePSEncodings:WriteFile\n"));
|
|
CloseHandle(hFile);
|
|
return(FALSE);
|
|
}
|
|
k++;
|
|
}
|
|
|
|
dwLen = OPSprintf(buffer, " %% %X\n", sortedWinCpts[j].usWinCpt);
|
|
strncpy(buffer, "/", 1);
|
|
l = strlen(sortedWinCpts[j].pPsName);
|
|
strncpy(buffer + 1, sortedWinCpts[j].pPsName, l);
|
|
if (!WriteFile(hFile, buffer, dwLen, (LPDWORD)&ulByteWritten, (LPOVERLAPPED)NULL)
|
|
|| ulByteWritten != dwLen)
|
|
{
|
|
ERR(("WritePSEncodings:WriteFile\n"));
|
|
CloseHandle(hFile);
|
|
return(FALSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
//
|
|
// This causes the error message to show up in your command window
|
|
// instead of the kernel debugger window.
|
|
//
|
|
|
|
ULONG _cdecl
|
|
DbgPrint(
|
|
PCSTR pstrFormat,
|
|
...
|
|
)
|
|
|
|
{
|
|
va_list ap;
|
|
|
|
va_start(ap, pstrFormat);
|
|
vprintf(pstrFormat, ap);
|
|
va_end(ap);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
VOID
|
|
DbgBreakPoint(
|
|
VOID
|
|
)
|
|
|
|
{
|
|
exit(-1);
|
|
}
|
|
|
|
|
|
BOOL NeedBuildMoreNTM(
|
|
PBYTE pAFM
|
|
)
|
|
{
|
|
PPSFAMILYINFO pFamilyInfo;
|
|
PSZ pszFontName;
|
|
|
|
pFamilyInfo = NULL;
|
|
pszFontName = FindAFMToken(pAFM, PS_FONT_NAME_TOK);
|
|
|
|
if (NULL ==pszFontName) return FALSE;
|
|
|
|
pFamilyInfo = (PPSFAMILYINFO) bsearch(pszFontName,
|
|
(PBYTE) (((PPSFAMILYINFO) (pFamilyTbl->pTbl))[0].pFontName),
|
|
pFamilyTbl->usNumEntries,
|
|
sizeof(PSFAMILYINFO),
|
|
StrCmp);
|
|
if (pFamilyInfo)
|
|
{
|
|
if (pFamilyInfo->usPitch != DEFAULT_PITCH)
|
|
return TRUE;
|
|
if (pFamilyInfo > ((PPSFAMILYINFO) (pFamilyTbl->pTbl)))
|
|
{
|
|
pFamilyInfo = pFamilyInfo - 1;
|
|
if (!StrCmp(pFamilyInfo->pFontName, pszFontName) &&
|
|
(pFamilyInfo->usPitch != DEFAULT_PITCH))
|
|
return TRUE;
|
|
}
|
|
pFamilyInfo = pFamilyInfo + 1;
|
|
if (pFamilyInfo <
|
|
(((PPSFAMILYINFO) (pFamilyTbl->pTbl)) + pFamilyTbl->usNumEntries))
|
|
{
|
|
pFamilyInfo = pFamilyInfo + 1;
|
|
if (!StrCmp(pFamilyInfo->pFontName, pszFontName) &&
|
|
(pFamilyInfo->usPitch != DEFAULT_PITCH))
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|