Windows NT 4.0 source code leak
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

/************************* 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;
}