Leaked source code of windows server 2003
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.
 
 
 
 
 
 

423 lines
12 KiB

/*++
Copyright (c) 1996 - 1999 Microsoft Corporation
Module Name:
ctt2rle.c
Abstract:
Convert Win 3.1 CTT CTT_WTYPE_DIRECT format tables to NT 4.0 RLE spec.
Environment:
Windows NT Unidrv driver
Revision History:
01/10/97 -ganeshp-
Created
--*/
#include "font.h"
/*
* Some useful definitions for memory sizes and masks.
*/
#define DW_MASK (DWBITS - 1)
#define OVERFLOW_SZ sizeof( WORD )
NT_RLE *
PNTRLE1To1(
IN BOOL bSymbolCharSet,
int iFirst,
int iLast
)
/*++
Routine Description:
Generates a simple mapping format for the RLE stuff. This is
typically used for a printer with a 1:1 mapping to the Windows
character set.
Arguments:
iFirst The lowest glyph in the range.
iLast The last glyph in the range (inclusive).
Return Value:
Address of NT_RLE structure allocated from heap; NULL on failure.
Note:
2/10/1997 -ganeshp-
Created it.
--*/
{
/*
* Operation is simple. We create a dummy CTT that is a 1:1 mapping,
* then call the conversion function to generate the correct values.
*/
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 *pntrle; /* Allocated memory, and returned to caller */
UHG uhg; /* Clearer (?) access to HGLYPH contents */
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 */
DWORD cbWch;
BOOL bInRun; /* For processing run accumulations */
BYTE ajAnsi[ 256 ];
WCHAR wchMin; /* Find the first unicode value */
WCHAR wchMax; /* Find the last unicode value */
WCHAR awch[ 512 ]; /* Converted array of points */
ASSERT(iFirst == 0x20 && iLast == 0xFF);
cHandles = iLast - iFirst + 1;
if( cHandles > 256 )
return NULL; /* This code does not handle that situation */
cjExtra = 0; /* Presume no extra storage required */
/*
* 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.
*/
ZeroMemory(awch, sizeof(awch));
for( iI = 0; iI < cHandles; ++iI )
ajAnsi[ iI ] = (BYTE)(iI + iFirst);
#ifndef WINNT_40 //NT 5.0
//
// force Windows ANSI codepage
//
if( -1 == (cbWch = EngMultiByteToWideChar(1252,
awch,
(ULONG)(cHandles * sizeof(WCHAR)),
(PCH) ajAnsi,
(ULONG) cHandles)))
{
#if DBG
DbgPrint( "EngMultiByteToWideChar failed \n");
#endif
return NULL;
}
cHandles = cbWch;
#else // NT 4.0
EngMultiByteToUnicodeN(awch,cHandles * sizeof(WCHAR),NULL,ajAnsi,cHandles);
#endif //!WINNT_40
/*
* 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.
*/
if (bSymbolCharSet)
{
for (iI = 0; iI < NUM_OF_SYMBOL; iI ++)
{
awch[cHandles + iI] = SYMBOL_START + iI;
}
cHandles += NUM_OF_SYMBOL;
}
for( wchMax = 0, wchMin = 0xffff, iI = 0; iI < cHandles; ++iI )
{
//
// Bugfix: Euro currency symbol doesn't print.
// Euro currency symbols Unicode is U+20AC. NLS Unicode to Multibyte
// table converts 0x80 (Multi byte) to U+20AC. We have to exclude
// 0x80 from ASCII table. So that we don't substitute U+20AC with
// device font 0x80.
//
if (awch[ iI ] == 0x20ac)
continue;
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 *)MemAllocZ(cdwBits )) )
{
return NULL; /* Nothing going */
}
/*
* Set bits in this array corresponding to Unicode code points
*/
for( iI = 0; iI < cHandles; ++iI )
{
if (awch[ iI ] == 0x20ac)
continue;
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( NT_RLE ) +
(cRuns - 1) * sizeof( WCRUN ) +
cHandles * sizeof( HGLYPH ) +
cjExtra;
//
// Allocate Real NTRLE
//
if( !(pntrle = (NT_RLE *)MemAllocZ( cjTotal )) )
{
MemFree((LPSTR)pdwBits );
return pntrle;
}
//
// For calculating offsets, we need these addresses
//
pbBase = (BYTE *)pntrle;
//
// FD_GLYPHSET contains the first WCRUN data structure,
// so that cRun - 1 is correct.
//
phg = (HGLYPH *)(pbBase + sizeof( NT_RLE ) + (cRuns - 1) * sizeof( WCRUN ));
pb = (BYTE *)phg + cHandles * sizeof( HGLYPH );
pntrle->wType = RLE_DIRECT;
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 = pntrle->wchFirst;
pntrle->fdg.awcrun[ 0 ].cGlyphs = (WORD)cHandles;
pntrle->fdg.awcrun[ 0 ].phg = (HGLYPH*)((BYTE *)phg - pbBase);
/*
* 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 = (HGLYPH*)((PBYTE)(phg + iMax) - pbBase);
}
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 = iFirst; iI <= iLast; ++iI, ++iIndex )
{
WCHAR wchTemp; /* For Unicode mapping */
/*
* Need to map this BYTE value into the appropriate WCHAR
* value, then look for the location of the phg that fits.
*/
wchTemp = awch[ iIndex ];
if (wchTemp == 0x20ac)
continue;
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
*/
if (pwcr->phg)
phg = (HGLYPH*)((ULONG_PTR)pbBase + (ULONG_PTR)pwcr->phg) + wchTemp - pwcr->wcLow;
else
phg = NULL;
break;
}
++pwcr;
}
if( phg == NULL )
continue; /* Should not happen */
uhg.rd.b0 = *((PBYTE)&iI);
uhg.rd.b1 = 0;
uhg.rd.wIndex = (WORD)iIndex;
*phg = uhg.hg;
}
if (bSymbolCharSet)
{
pwcr = pntrle->fdg.awcrun;
phg = NULL;
for ( iMax = 0; iMax < cRuns; ++iMax)
{
if (SYMBOL_START == pwcr->wcLow)
{
/*
* Found the range, so now select the slot
*/
if (pwcr->phg)
phg = (HGLYPH*)((ULONG_PTR)pbBase + (ULONG_PTR)pwcr->phg);
else
phg = NULL;
break;
}
++pwcr;
}
if (phg)
{
for (iI = SYMBOL_START; iI <= SYMBOL_END; iI ++, iIndex++, phg++)
{
uhg.rd.b0 = *((PBYTE)&iI);
uhg.rd.b1 = 0;
uhg.rd.wIndex = (WORD)iIndex;
*phg = uhg.hg;
}
}
}
//
// Error check
//
if( (pb - pbBase) > cjTotal )
{
ERR(( "Rasdd!ctt2rle: overflow of data area: alloc %ld, used %ld\n", cjTotal, pb - pbBase ));
}
MemFree( (LPSTR)pdwBits );
return pntrle;
}