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