mirror of https://github.com/lianthony/NT4.0
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.
532 lines
16 KiB
532 lines
16 KiB
/************************* MODULE HEADER ***********************************
|
|
* ctt2rle
|
|
* Convert Win 3.1 CTT format tables to NT's RLE spec.
|
|
*
|
|
* Copyright (C) 1992 - 1993, Microsoft Corporation.
|
|
*
|
|
****************************************************************************/
|
|
|
|
|
|
#include <precomp.h>
|
|
#include <winddi.h>
|
|
#include <udmindrv.h>
|
|
#include <udpfm.h>
|
|
#include <raslib.h>
|
|
#include <libproto.h>
|
|
#include <ntrle.h>
|
|
#include "rasdd.h"
|
|
|
|
|
|
/*
|
|
* Some useful definitions for memory sizes and masks.
|
|
*/
|
|
|
|
#define BBITS 8 /* Bits in a byte */
|
|
#define DWBITS (BBITS * sizeof( DWORD )) /* Bits in a DWORD */
|
|
#define DW_MASK (DWBITS - 1)
|
|
|
|
|
|
/************************ Function Header ***********************************
|
|
* pntrleConvCTT
|
|
* Convert a Win 3.1 CTT structure into the corresponding NT RLE
|
|
* format data. Allocates memory from the heap for this.
|
|
*
|
|
* RETURNS:
|
|
* Pointer to the NT_RLE structure generated; NULL on failure.
|
|
*
|
|
* HISTORY:
|
|
* 13:10 on Thu 04 Mar 1993 -by- Lindsay Harris [lindsayh]
|
|
* Use correct mapping from Win 3.1 character set to Unicode.
|
|
*
|
|
* 14:18 on Tue 01 Dec 1992 -by- Lindsay Harris [lindsayh]
|
|
* First version.
|
|
*
|
|
****************************************************************************/
|
|
|
|
NT_RLE *
|
|
pntrleConvCTT( hheap, pCTT, bOffset, iChMin, iChMax )
|
|
HANDLE hheap; /* Access to heap - temporary and long term use */
|
|
TRANSTAB *pCTT; /* Pointer to the 3.1 format translate table */
|
|
BOOL bOffset; /* If true, WCRUN.phg is offset, else address */
|
|
int iChMin; /* Lowest glyph handle we create */
|
|
int iChMax; /* Highest glyph handle we create */
|
|
{
|
|
|
|
|
|
int iI; /* Loop index */
|
|
int iMax; /* Find the longest data length for CTT_WTYPE_COMPOSE */
|
|
int cHandles; /* The number of handles we need */
|
|
int cjExtra; /* Extra storage needed for offset modes */
|
|
int cjTotal; /* Total amount of storage to be requested */
|
|
int iIndex; /* Index we install in the HGLYPH for widths etc */
|
|
int cRuns; /* Number of runs we create */
|
|
|
|
NT_RLE ntrle; /* Our stuff - while building it up */
|
|
NT_RLE *pntrle; /* Allocated memory, and returned to caller */
|
|
|
|
HGLYPH *phg; /* For working through the array of HGLYPHS */
|
|
|
|
BYTE *pb; /* Current address in overflow area */
|
|
BYTE *pbBase; /* Start of overflow area containing data */
|
|
|
|
WCRUN *pwcr; /* Scanning the run data */
|
|
|
|
DWORD *pdwBits; /* For figuring out runs */
|
|
DWORD cdwBits; /* Size of this area */
|
|
|
|
BOOL bInRun; /* For processing run accumulations */
|
|
|
|
BYTE ajAnsi[ 256 ];
|
|
WCHAR awch[ 256 ]; /* Converted array of points */
|
|
WCHAR wchMin; /* Find the first unicode value */
|
|
WCHAR wchMax; /* Find the last unicode value */
|
|
|
|
|
|
|
|
/*
|
|
* Since we can have up to 4 bytes per entry without going to the
|
|
* offset mode, we scan the data to see if any entries are longer
|
|
* than 4 bytes. If so, offset mode is required, otherwise we
|
|
* can simply put the data into the glyph handles.
|
|
*/
|
|
|
|
ZeroMemory( &ntrle, sizeof( ntrle ) );
|
|
|
|
ntrle.wchFirst = min( iChMin, pCTT->chFirstChar );
|
|
ntrle.wchLast = max( iChMax, pCTT->chLastChar );
|
|
|
|
cHandles = ntrle.wchLast - ntrle.wchFirst + 1;
|
|
|
|
if( cHandles > 256 )
|
|
return NULL; /* This code does not handle that situation */
|
|
|
|
cjExtra = 0; /* Presume no extra storage required */
|
|
|
|
|
|
/* See what we have, and if extra storage is needed */
|
|
|
|
#define OVERFLOW_SZ sizeof( WORD )
|
|
|
|
switch( pCTT->wType )
|
|
{
|
|
case CTT_WTYPE_COMPOSE: /* Look for the longest length available */
|
|
|
|
iMax = -1;
|
|
|
|
for( iI = pCTT->chLastChar - pCTT->chFirstChar; --iI >= 0; )
|
|
{
|
|
int iLen;
|
|
|
|
iLen = pCTT->uCode.psCode[ iI + 1 ] - pCTT->uCode.psCode[ iI ];
|
|
if( iLen > OVERFLOW_SZ )
|
|
{
|
|
/*
|
|
* Need to use the overflow arrangement, so remember
|
|
* how much storage is required.
|
|
*/
|
|
|
|
cjExtra += iLen;
|
|
}
|
|
if( iLen > iMax )
|
|
iMax = iLen;
|
|
}
|
|
|
|
|
|
if( iMax <= OVERFLOW_SZ )
|
|
{
|
|
/* Can all fit in DWORD, so use that directly */
|
|
ntrle.wType = RLE_DIRECT; /* Allows up to 4 bytes */
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
* Requires an offset style format. We need to decide
|
|
* how much extra storage to allocate for these, over
|
|
* and above the HGLYPHS. This is not hard: we allocate
|
|
* one byte for all glyphs not covered by the CTT, then
|
|
* add as much as the CTT currently uses.
|
|
*/
|
|
|
|
/*
|
|
* For now, assume that we can use the short form of offset.
|
|
* This may be changed when we calculate storage size later.
|
|
*/
|
|
|
|
/* We know there are <= 256 entries */
|
|
ntrle.wType = RLE_LI_OFFSET; /* Length, Index + 2 bytes offset */
|
|
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CTT_WTYPE_DIRECT: /* Single byte - easy to handle */
|
|
ntrle.wType = RLE_DIRECT;
|
|
break;
|
|
|
|
case CTT_WTYPE_PAIRED: /* Pair of bytes, overstruck */
|
|
ntrle.wType = RLE_PAIRED;
|
|
break;
|
|
|
|
|
|
default:
|
|
#if DBG
|
|
DbgPrint( "Rasdd!pntrleConvCTT: Invalid wtype = %d\n", pCTT->wType );
|
|
#endif
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* We need to figure out how many runs are required to describe
|
|
* this font. First obtain the correct Unicode encoding of these
|
|
* values, then examine them to find the number of runs, and
|
|
* hence much extra storage is required.
|
|
*/
|
|
|
|
for( iI = 0; iI < cHandles; ++iI )
|
|
ajAnsi[ iI ] = (BYTE)(iI + ntrle.wchFirst); /* We know it is < 256 */
|
|
|
|
#ifdef NTGDIKM
|
|
|
|
EngMultiByteToUnicodeN(awch,cHandles * sizeof(WCHAR),NULL,ajAnsi,cHandles);
|
|
|
|
#else
|
|
|
|
MultiByteToWideChar( CP_ACP, 0, ajAnsi, cHandles, awch, cHandles );
|
|
|
|
#endif
|
|
|
|
/*
|
|
* Find the largest Unicode value, then allocate storage to allow us
|
|
* to create a bit array of valid unicode points. Then we can
|
|
* examine this to determine the number of runs.
|
|
*/
|
|
|
|
for( wchMax = 0, wchMin = 0xffff, iI = 0; iI < cHandles; ++iI )
|
|
{
|
|
if( awch[ iI ] > wchMax )
|
|
wchMax = awch[ iI ];
|
|
if( awch[ iI ] < wchMin )
|
|
wchMin = awch[ iI ];
|
|
}
|
|
/*
|
|
* Note that the expression 1 + wchMax IS correct. This comes about
|
|
* from using these values as indices into the bit array, and that
|
|
* this is essentially 1 based.
|
|
*/
|
|
|
|
cdwBits = (1 + wchMax + DWBITS - 1) / DWBITS * sizeof( DWORD );
|
|
|
|
if( !(pdwBits = (DWORD *)HeapAlloc( hheap, 0, cdwBits )) )
|
|
{
|
|
return NULL; /* Nothing going */
|
|
}
|
|
|
|
ZeroMemory( pdwBits, cdwBits );
|
|
|
|
/* Set bits in this array corresponding to Unicode code points */
|
|
for( iI = 0; iI < cHandles; ++iI )
|
|
{
|
|
pdwBits[ awch[ iI ] / DWBITS ] |= (1 << (awch[ iI ] & DW_MASK));
|
|
}
|
|
|
|
/*
|
|
* Now we can examine the number of runs required. For starters,
|
|
* we stop a run whenever a hole is discovered in the array of 1
|
|
* bits we just created. Later we MIGHT consider being a little
|
|
* less pedantic.
|
|
*/
|
|
|
|
bInRun = FALSE;
|
|
cRuns = 0; /* None so far */
|
|
|
|
for( iI = 1; iI <= (int)wchMax; ++iI )
|
|
{
|
|
if( pdwBits[ iI / DWBITS ] & (1 << (iI & DW_MASK)) )
|
|
{
|
|
/* Not in a run: is this the end of one? */
|
|
if( !bInRun )
|
|
{
|
|
/* It's time to start one */
|
|
bInRun = TRUE;
|
|
++cRuns;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( bInRun )
|
|
{
|
|
/* Not any more! */
|
|
bInRun = FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
cjTotal = sizeof( ntrle ) + (cRuns - 1) * sizeof( WCRUN ) +
|
|
cHandles * sizeof( HGLYPH ) + cjExtra;
|
|
|
|
|
|
if( ntrle.wType == RLE_LI_OFFSET && cjTotal > 0xffff )
|
|
{
|
|
/*
|
|
* Won't fit, so need to go to the 24 bit offset + index. We
|
|
* assume we need 3 extra bytes for each entry: this is likely
|
|
* to be pessimistic, but we need to add 2 bytes ALIGNED on a
|
|
* WORD boundary, so now is the time to play it safe and assume
|
|
* ALL entries will require padding.
|
|
*/
|
|
|
|
ntrle.wType = RLE_L_OFFSET;
|
|
cjTotal += cHandles * (sizeof( WORD ) + 1);
|
|
#if DBG
|
|
DbgPrint( "^G.... CANNOT HANDLE THIS...\n" );
|
|
#endif
|
|
}
|
|
|
|
if( !(pntrle = (NT_RLE *)HeapAlloc( hheap, 0, cjTotal )) )
|
|
{
|
|
HeapFree( hheap, 0, (LPSTR)pdwBits );
|
|
|
|
return pntrle;
|
|
}
|
|
|
|
|
|
/* For calculating offsets, we need these addresses */
|
|
pbBase = (BYTE *)pntrle;
|
|
|
|
ZeroMemory( pbBase, cjTotal ); /* Safer if we miss something */
|
|
|
|
|
|
phg = (HGLYPH *)(pbBase + sizeof( ntrle ) + (cRuns - 1) * sizeof( WCRUN ));
|
|
pb = (BYTE *)phg + cHandles * sizeof( HGLYPH );
|
|
|
|
pntrle->wType = ntrle.wType; /* Mode we are using */
|
|
pntrle->bMagic0 = RLE_MAGIC0;
|
|
pntrle->bMagic1 = RLE_MAGIC1;
|
|
pntrle->cjThis = cjTotal;
|
|
pntrle->wchFirst = wchMin; /* Lowest unicode code point */
|
|
pntrle->wchLast = wchMax; /* Highest unicode code point */
|
|
|
|
pntrle->fdg.cjThis = sizeof( FD_GLYPHSET ) + (cRuns - 1) * sizeof( WCRUN );
|
|
pntrle->fdg.cGlyphsSupported = cHandles;
|
|
pntrle->fdg.cRuns = cRuns;
|
|
|
|
pntrle->fdg.awcrun[ 0 ].wcLow = ntrle.wchFirst;
|
|
pntrle->fdg.awcrun[ 0 ].cGlyphs = cHandles;
|
|
pntrle->fdg.awcrun[ 0 ].phg = phg;
|
|
|
|
|
|
/*
|
|
* We now wish to fill in the awcrun data. Filling it in now
|
|
* simplifies operations later on. Now we can scan the bit array
|
|
* data, and so easily figure out how large the runs are and
|
|
* where abouts a particular HGLYPH is located.
|
|
*/
|
|
|
|
bInRun = FALSE;
|
|
cRuns = 0; /* None so far */
|
|
iMax = 0; /* Count glyphs for address arithmetic */
|
|
|
|
for( iI = 1; iI <= (int)wchMax; ++iI )
|
|
{
|
|
if( pdwBits[ iI / DWBITS ] & (1 << (iI & DW_MASK)) )
|
|
{
|
|
/* Not in a run: is this the end of one? */
|
|
if( !bInRun )
|
|
{
|
|
/* It's time to start one */
|
|
bInRun = TRUE;
|
|
pntrle->fdg.awcrun[ cRuns ].wcLow = (WCHAR)iI;
|
|
pntrle->fdg.awcrun[ cRuns ].cGlyphs = 0;
|
|
pntrle->fdg.awcrun[ cRuns ].phg = phg + iMax;
|
|
}
|
|
pntrle->fdg.awcrun[ cRuns ].cGlyphs++; /* One more */
|
|
++iMax;
|
|
}
|
|
else
|
|
{
|
|
if( bInRun )
|
|
{
|
|
/* Not any more! */
|
|
bInRun = FALSE;
|
|
++cRuns; /* Onto the next structure */
|
|
}
|
|
}
|
|
}
|
|
|
|
if( bInRun )
|
|
++cRuns; /* It has finished now */
|
|
|
|
|
|
/*
|
|
* Now go fill in the array of HGLYPHS. The actual format varies
|
|
* depending upon the range of glyphs, and upon the CTT format.
|
|
*/
|
|
|
|
for( iIndex = 0, iI = ntrle.wchFirst; iI <= ntrle.wchLast; ++iI, ++iIndex )
|
|
{
|
|
|
|
int iVal; /* Needs an address */
|
|
int cjData; /* Length of data to use */
|
|
WCHAR wchTemp; /* For Unicode mapping */
|
|
|
|
BYTE *pbData; /* Data to convert/move */
|
|
|
|
UHG uhg; /* Clearer (?) access to HGLYPH contents */
|
|
|
|
/*
|
|
* Need to map this BYTE value into the appropriate WCHAR
|
|
* value, then look for the location of the phg that fits.
|
|
*/
|
|
|
|
wchTemp = awch[ iIndex ];
|
|
phg = NULL; /* Flag that we failed */
|
|
pwcr = pntrle->fdg.awcrun;
|
|
|
|
for( iMax = 0; iMax < cRuns; ++iMax )
|
|
{
|
|
if( pwcr->wcLow <= wchTemp &&
|
|
(pwcr->wcLow + pwcr->cGlyphs) > wchTemp )
|
|
{
|
|
/* Found the range, so now select the slot */
|
|
phg = pwcr->phg + wchTemp - pwcr->wcLow;
|
|
|
|
break;
|
|
}
|
|
++pwcr;
|
|
}
|
|
|
|
|
|
if( phg == NULL )
|
|
continue; /* Should not happen */
|
|
|
|
|
|
if( iI >= pCTT->chFirstChar && iI <= pCTT->chLastChar )
|
|
{
|
|
/*
|
|
* We need to look at the CTT data to see what we need to do.
|
|
* How we do it depends upon the format we are using and
|
|
* decided upon above.
|
|
*/
|
|
|
|
WCHAR wchTemp;
|
|
|
|
|
|
wchTemp = iI - pCTT->chFirstChar;
|
|
|
|
switch( pCTT->wType )
|
|
{
|
|
case CTT_WTYPE_DIRECT:
|
|
pbData = &pCTT->uCode.bCode[ wchTemp ];
|
|
cjData = 1;
|
|
break;
|
|
|
|
case CTT_WTYPE_PAIRED:
|
|
pbData = &pCTT->uCode.bPairs[ wchTemp ][ 0 ];
|
|
cjData = *(pbData + 1) ? 2 : 1;
|
|
break;
|
|
|
|
case CTT_WTYPE_COMPOSE:
|
|
pbData = (BYTE *)pCTT + pCTT->uCode.psCode[ wchTemp ];
|
|
cjData = pCTT->uCode.psCode[ wchTemp + 1 ] -
|
|
pCTT->uCode.psCode[ wchTemp ];
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
/* Simple extension of the glyph index */
|
|
pbData = (BYTE *)&iVal;
|
|
iVal = iI;
|
|
cjData = (iI & 0xff00) ? 2 : 1;
|
|
}
|
|
|
|
/*
|
|
* Now write out the resulting data. We have both an
|
|
* address and a length, so turn this data into the desired
|
|
* format, as decided above.
|
|
*/
|
|
|
|
switch( ntrle.wType )
|
|
{
|
|
case RLE_L_OFFSET:
|
|
/* Data is located following the array of HGLYPHs */
|
|
pb = (BYTE *)((int)((pb + sizeof( WORD ))) & ~(sizeof( WORD ) - 1));
|
|
|
|
/* Start of data is a WORD aligned WORD containing the index */
|
|
*((WORD *)pb) = iIndex;
|
|
pb += sizeof( WORD );
|
|
|
|
memcpy( pb, pbData, cjData );
|
|
*phg = (HGLYPH)((cjData << 24) | (pb - pbBase));
|
|
pb += cjData;
|
|
break;
|
|
|
|
case RLE_LI_OFFSET: /* 8 bits index, length + 16 bit offset */
|
|
|
|
if( cjData <= OVERFLOW_SZ )
|
|
{
|
|
/* Data fits in HGLYPH directly */
|
|
uhg.rlic.b0 = *pbData;
|
|
uhg.rlic.b1 = cjData > 1 ? *(pbData + 1) : '\0';
|
|
}
|
|
else
|
|
{
|
|
/* Data must be placed into the overflow area at the end */
|
|
uhg.rli.wOffset = pb - pbBase;
|
|
memcpy( pb, pbData, cjData );
|
|
pb += cjData;
|
|
}
|
|
uhg.rli.bIndex = iIndex;
|
|
uhg.rli.bLength = cjData;
|
|
*phg = uhg.hg;
|
|
break;
|
|
|
|
case RLE_DIRECT: /* One or two bytes, as is */
|
|
case RLE_PAIRED: /* Two bytes, overstruck */
|
|
|
|
/* Relatively straight forward, depends upon CTT format */
|
|
uhg.rd.b0 = *pbData;
|
|
uhg.rd.b1 = cjData > 1 ? *(pbData + 1) : '\0';
|
|
uhg.rd.wIndex = iIndex;
|
|
*phg = uhg.hg;
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* If the bOffset parameter is true, then we are to return offset
|
|
* values in the fdg.awcrun[].phg fields. These are offsets relative
|
|
* to the beginning of the NT_RLE structure. Typically these are used
|
|
* when converting the CTT tables to RLE format for inclusion in
|
|
* the resource data of NT built minidrivers. The addresses are used
|
|
* when doing the conversion on the fly within rasdd.
|
|
*/
|
|
|
|
if( bOffset )
|
|
{
|
|
pwcr = pntrle->fdg.awcrun; /* Base address of WCRUNs */
|
|
|
|
for( iI = 0; iI < cRuns; ++iI, ++pwcr )
|
|
{
|
|
(BYTE *)pwcr->phg -= (DWORD)pbBase;
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
if( (pb - pbBase) > cjTotal )
|
|
{
|
|
DbgPrint( "Rasdd!ctt2rle: overflow of data area: alloc %ld, used %ld\n",
|
|
cjTotal, pb - pbBase );
|
|
}
|
|
#endif
|
|
|
|
HeapFree( hheap, 0, (LPSTR)pdwBits );
|
|
|
|
return pntrle;
|
|
}
|