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.
1645 lines
48 KiB
1645 lines
48 KiB
/******************************Module*Header*******************************\
|
|
* Module Name: fdquery.c
|
|
*
|
|
* (Brief description)
|
|
*
|
|
* Created: 08-Nov-1990 11:57:35
|
|
* Author: Bodin Dresevic [BodinD]
|
|
*
|
|
* Copyright (c) 1990 Microsoft Corporation
|
|
\**************************************************************************/
|
|
#include "fd.h"
|
|
|
|
ULONG
|
|
cjBmfdDeviceMetrics (
|
|
PFONTCONTEXT pfc,
|
|
FD_DEVICEMETRICS *pdevm
|
|
);
|
|
|
|
VOID
|
|
vStretchCvtToBitmap
|
|
(
|
|
GLYPHBITS *pgb,
|
|
PBYTE pjBitmap, // bitmap in *.fnt form
|
|
ULONG cx, // unscaled width
|
|
ULONG cy, // unscaled height
|
|
ULONG yBaseline,
|
|
PBYTE pjLineBuffer, // preallocated buffer for use by stretch routines
|
|
ULONG cxScale, // horizontal scaling factor
|
|
ULONG cyScale, // vertical scaling factor
|
|
ULONG flSim // simulation flags
|
|
);
|
|
|
|
#ifdef FE_SB // Rotation
|
|
VOID
|
|
vFill_RotateGLYPHDATA (
|
|
GLYPHDATA *pDistinationGlyphData,
|
|
PVOID SourceGLYPHBITS,
|
|
PVOID DistinationGLYPHBITS,
|
|
UINT RotateDegree
|
|
);
|
|
#endif
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BmfdQueryFont
|
|
*
|
|
* Returns:
|
|
* Pointer to IFIMETRICS. Returns NULL if an error occurs.
|
|
*
|
|
* History:
|
|
* 30-Aug-1992 -by- Gilman Wong [gilmanw]
|
|
* IFI/DDI merge.
|
|
*
|
|
* 19-Nov-1990 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
PIFIMETRICS
|
|
BmfdQueryFont (
|
|
DHPDEV dhpdev,
|
|
HFF hff,
|
|
ULONG iFace,
|
|
ULONG_PTR *pid
|
|
)
|
|
{
|
|
FACEINFO *pfai;
|
|
|
|
DONTUSE(dhpdev);
|
|
DONTUSE(pid);
|
|
|
|
//
|
|
// Validate handle.
|
|
//
|
|
if (hff == HFF_INVALID)
|
|
return (PIFIMETRICS) NULL;
|
|
|
|
//
|
|
// We assume the iFace is within range.
|
|
//
|
|
ASSERTGDI(
|
|
(iFace >= 1L) && (iFace <= PFF(hff)->cFntRes),
|
|
"gdisrv!BmfdQueryFont: iFace out of range\n"
|
|
);
|
|
|
|
//
|
|
// Get ptr to the appropriate FACEDATA struct, take into account that
|
|
// iFace values are 1 based.
|
|
//
|
|
pfai = &PFF(hff)->afai[iFace - 1];
|
|
|
|
//
|
|
// Return the pointer to IFIMETRICS.
|
|
//
|
|
return pfai->pifi;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BmfdQueryFontTree
|
|
*
|
|
* This function returns pointers to per-face information.
|
|
*
|
|
* Parameters:
|
|
*
|
|
* dhpdev Not used.
|
|
*
|
|
* hff Handle to a font file.
|
|
*
|
|
* iFace Index of a face in the font file.
|
|
*
|
|
* iMode This is a 32-bit number that must be one of the following
|
|
* values:
|
|
*
|
|
* Allowed ulMode values:
|
|
* ----------------------
|
|
*
|
|
* QFT_LIGATURES -- returns a pointer to the ligature map.
|
|
*
|
|
* QFT_KERNPAIRS -- return a pointer to the kerning pair table.
|
|
*
|
|
* QFT_GLYPHSET -- return a pointer to the WC->HGLYPH mapping table.
|
|
*
|
|
* pid Not used.
|
|
*
|
|
* Returns:
|
|
a Returns a pointer to the requested data. This data will not change
|
|
* until BmfdFree is called on the pointer. Caller must not attempt to
|
|
* modify the data. NULL is returned if an error occurs.
|
|
*
|
|
* History:
|
|
* 30-Aug-1992 -by- Gilman Wong [gilmanw]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
PVOID
|
|
BmfdQueryFontTree (
|
|
DHPDEV dhpdev,
|
|
HFF hff,
|
|
ULONG iFace,
|
|
ULONG iMode,
|
|
ULONG_PTR *pid
|
|
)
|
|
{
|
|
FACEINFO *pfai;
|
|
|
|
DONTUSE(dhpdev);
|
|
DONTUSE(pid);
|
|
|
|
//
|
|
// Validate parameters.
|
|
//
|
|
if (hff == HFF_INVALID)
|
|
return ((PVOID) NULL);
|
|
|
|
// Note: iFace values are index-1 based.
|
|
|
|
if ((iFace < 1L) || (iFace > PFF(hff)->cFntRes))
|
|
{
|
|
RETURN("gdisrv!BmfdQueryFontTree()\n", (PVOID) NULL);
|
|
}
|
|
|
|
//
|
|
// Which mode?
|
|
//
|
|
switch (iMode)
|
|
{
|
|
case QFT_LIGATURES:
|
|
case QFT_KERNPAIRS:
|
|
|
|
//
|
|
// There are no ligatures or kerning pairs for the bitmap fonts,
|
|
// therefore we return NULL
|
|
//
|
|
return ((PVOID) NULL);
|
|
|
|
case QFT_GLYPHSET:
|
|
|
|
//
|
|
// Find glyphset structure corresponding to this iFace:
|
|
//
|
|
pfai = &PFF(hff)->afai[iFace - 1];
|
|
|
|
return ((PVOID) &pfai->pcp->gset);
|
|
|
|
default:
|
|
|
|
//
|
|
// Should never get here.
|
|
//
|
|
RIP("gdisrv!BmfdQueryFontTree(): unknown iMode\n");
|
|
return ((PVOID) NULL);
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* BOOL bReconnectBmfdFont(FONTFILE *pff)
|
|
*
|
|
*
|
|
* Effects: If the file is marked gone, we try to reconnect and see if we can
|
|
* use it again. We clear the exception bit so that the system will
|
|
* be able to use this font again.
|
|
*
|
|
* History:
|
|
* 17-Aug-1994 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
|
|
|
|
BOOL bReconnectBmfdFont(FONTFILE *pff)
|
|
{
|
|
INT i;
|
|
PVOID pvView;
|
|
COUNT cjView;
|
|
|
|
EngAcquireSemaphore(ghsemBMFD);
|
|
if (pff->fl & FF_EXCEPTION_IN_PAGE_ERROR)
|
|
{
|
|
if (!EngMapFontFileFD(pff->iFile, (PULONG*) &pvView, &cjView))
|
|
{
|
|
WARNING("BMFD! can not reconnect this bm font file!!!\n");
|
|
EngReleaseSemaphore(ghsemBMFD);
|
|
return FALSE;
|
|
}
|
|
|
|
for (i = 0; i < (INT)pff->cFntRes; i++)
|
|
{
|
|
pff->afai[i].re.pvResData = (PVOID) (
|
|
(BYTE*)pvView + pff->afai[i].re.dpResData
|
|
);
|
|
}
|
|
|
|
// everything is fine again, clear the bit
|
|
|
|
pff->fl &= ~FF_EXCEPTION_IN_PAGE_ERROR;
|
|
}
|
|
EngReleaseSemaphore(ghsemBMFD);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
*
|
|
* Routine Name:
|
|
*
|
|
* vBmfdScrubGLYPHBITS
|
|
*
|
|
* Routine Description:
|
|
*
|
|
* This procedure will mask off the last byte of each row so that there
|
|
* are no pixels set outside the boundary of the glyph. This problem
|
|
* has been detected in a Bitstream font named ncd0018.fon.
|
|
* This particular font is in the form of a 32-bit resource.
|
|
* The problem came to light because the ATI driver relies
|
|
* on the fact that the glyphs are "scrubbed" and contain no
|
|
* extraneous bits, even outside the glyph boundary.
|
|
*
|
|
* Arguments:
|
|
*
|
|
* pGb - a pointer to a GLYPHBITS structure
|
|
*
|
|
* Called by:
|
|
*
|
|
* BmfdQueryFontData
|
|
*
|
|
* Return Value:
|
|
*
|
|
* None.
|
|
*
|
|
\**************************************************************************/
|
|
|
|
void vBmfdScrubGLYPHBITS(GLYPHBITS *pGb)
|
|
{
|
|
int dp; // number of bytes in each scan
|
|
int cx; // number of pixels per row
|
|
BYTE jMask; // mask for last byte of each row;
|
|
BYTE *pj; // pointer to last byte of row;
|
|
BYTE *pjLast; // sentinel pointer
|
|
static BYTE ajMonoMask[8] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe};
|
|
|
|
cx = pGb->sizlBitmap.cx;
|
|
if ( jMask = ajMonoMask[cx & 7] )
|
|
{
|
|
dp = (cx + 7) / 8;
|
|
pj = pGb->aj + dp - 1;
|
|
pjLast = pj + dp * pGb->sizlBitmap.cy;
|
|
for ( ; pj < pjLast; pj += dp )
|
|
{
|
|
*pj &= jMask;
|
|
}
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BmfdQueryFontData
|
|
*
|
|
* pfo Pointer to a FONTOBJ.
|
|
*
|
|
* iMode This is a 32-bit number that must be one of the following
|
|
* values:
|
|
*
|
|
* Allowed ulMode values:
|
|
* ----------------------
|
|
*
|
|
* QFD_GLYPH -- return glyph metrics only
|
|
*
|
|
* QFD_GLYPHANDBITMAP -- return glyph metrics and bitmap
|
|
*
|
|
* QFD_GLYPHANDOUTLINE -- return glyph metrics and outline
|
|
*
|
|
* QFD_MAXEXTENTS -- return FD_DEVICEMETRICS structure
|
|
*
|
|
* QFD_MAXGLYPHBITMAP -- return size of largest glyph AND its metrics
|
|
*
|
|
* cData Count of data items in the pvIn buffer.
|
|
*
|
|
* pvIn An array of glyph handles.
|
|
*
|
|
* pvOut Output buffer.
|
|
*
|
|
* Returns:
|
|
* If mode is QFD_MAXGLYPHBITMAP, then size of glyph metrics plus
|
|
* largest bitmap is returned.
|
|
*
|
|
* Otherwise, if pvOut is NULL, function will return size of the buffer
|
|
* needed to copy the data requested; else, the function will return the
|
|
* number of bytes written.
|
|
*
|
|
* FD_ERROR is returned if an error occurs.
|
|
*
|
|
* History:
|
|
* 30-Aug-1992 -by- Gilman Wong [gilmanw]
|
|
* Wrote it. Contructed from pieces of BodinD's original
|
|
* BmfdQueryGlyphBitmap() and BmfdQueryOutline() functions.
|
|
\**************************************************************************/
|
|
|
|
LONG
|
|
BmfdQueryFontData (
|
|
FONTOBJ *pfo,
|
|
ULONG iMode,
|
|
HGLYPH hg,
|
|
GLYPHDATA *pgd,
|
|
PVOID pv,
|
|
ULONG cjSize
|
|
)
|
|
{
|
|
PFONTCONTEXT pfc;
|
|
LONG cjGlyphData = 0;
|
|
LONG cjAllData = 0;
|
|
PCVTFILEHDR pcvtfh;
|
|
PBYTE pjBitmap; // raw bitmap in the resource file
|
|
ULONG cxNoSim; // bm width in pels before simulations
|
|
FWORD sAscent;
|
|
#ifdef FE_SB // BmfdQueryFontData()
|
|
PVOID pvDst = NULL;
|
|
LONG cjGlyphDataNoRotate;
|
|
#endif // FE_SB
|
|
|
|
// The net connection died on us, but maybe it is alive again:
|
|
|
|
if (!bReconnectBmfdFont(PFF(pfo->iFile)))
|
|
{
|
|
WARNING("bmfd!bmfdQueryFontData: this file is gone\n");
|
|
return FD_ERROR;
|
|
}
|
|
|
|
// If pfo->pvProducer is NULL, then we need to open a font context.
|
|
//
|
|
if ( pfo->pvProducer == (PVOID) NULL )
|
|
pfo->pvProducer = (PVOID) BmfdOpenFontContext(pfo);
|
|
|
|
pfc = PFC(pfo->pvProducer);
|
|
|
|
if ( pfc == (PFONTCONTEXT) NULL )
|
|
{
|
|
WARNING("gdisrv!bmfdQueryFontData(): cannot create font context\n");
|
|
return FD_ERROR;
|
|
}
|
|
|
|
// What mode?
|
|
|
|
switch (iMode)
|
|
{
|
|
|
|
case QFD_GLYPHANDBITMAP:
|
|
|
|
//
|
|
// This code is left all inline for better performance.
|
|
//
|
|
pcvtfh = &(pfc->pfai->cvtfh);
|
|
sAscent = pfc->pfai->pifi->fwdWinAscender;
|
|
|
|
pjBitmap = pjRawBitmap(hg, pcvtfh, &pfc->pfai->re, &cxNoSim);
|
|
|
|
#ifdef FE_SB // BmfdQueryFontDate(): Compute size of RASTERGLYPH for ROTATION
|
|
|
|
//
|
|
// Compute the size of the RASTERGLYPH. ( GLYPHBITS structure size )
|
|
//
|
|
|
|
// Compute No Rotated GLYPHBITS size.
|
|
|
|
cjGlyphDataNoRotate = cjGlyphDataSimulated (
|
|
pfo,
|
|
cxNoSim * pfc->ptlScale.x,
|
|
pcvtfh->cy * pfc->ptlScale.y,
|
|
(PULONG) NULL,
|
|
0L
|
|
);
|
|
|
|
// Compute Rotated GLYPHBITS size.
|
|
|
|
switch( pfc->ulRotate )
|
|
{
|
|
case 0L :
|
|
case 1800L :
|
|
|
|
cjGlyphData = cjGlyphDataNoRotate;
|
|
|
|
break;
|
|
|
|
case 900L :
|
|
case 2700L :
|
|
|
|
cjGlyphData = cjGlyphDataSimulated (
|
|
pfo,
|
|
cxNoSim * pfc->ptlScale.x,
|
|
pcvtfh->cy * pfc->ptlScale.y,
|
|
(PULONG) NULL,
|
|
pfc->ulRotate
|
|
);
|
|
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Allocate Buffer for Rotation
|
|
//
|
|
|
|
if( pfc->ulRotate != 0L && pv != NULL )
|
|
{
|
|
|
|
// We have to rotate this bitmap. below here , we keep data in temp Buffer
|
|
// And will write this data into pv ,when rotate bitmap.
|
|
// We can't use original pv directly. Because original pv size is computed
|
|
// for Rotated bitmap. If we use this. it may causes access violation.
|
|
// hideyukn 08-Feb-1993
|
|
|
|
// Keep Master pv
|
|
pvDst = pv;
|
|
|
|
// Allocate New pv
|
|
pv = (PVOID)EngAllocMem(0, cjGlyphDataNoRotate, 'dfmB');
|
|
|
|
if( pv == NULL )
|
|
{
|
|
WARNING("BMFD:LocalAlloc for No Rotated bitmap is fail\n");
|
|
return( FD_ERROR );
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
// This Routine is for at ulRotate != 0 && pv == NULL
|
|
//
|
|
// If User want to only GLYPHDATA , We do not do anything for glyphbits
|
|
// at vFill_RotateGLYPHDATA
|
|
//
|
|
// pvDst is only used in case of ulRotate is Non-Zero
|
|
;
|
|
}
|
|
#else
|
|
//
|
|
// Compute the size of the RASTERGLYPH.
|
|
//
|
|
cjGlyphData = cjGlyphDataSimulated (
|
|
pfo,
|
|
cxNoSim * pfc->ptlScale.x,
|
|
pcvtfh->cy * pfc->ptlScale.y,
|
|
(PULONG) NULL
|
|
);
|
|
#endif
|
|
|
|
#ifdef FE_SB
|
|
// !!!
|
|
// !!! Following vComputeSimulatedGLYPHDATA function will set up GLYPHDATA
|
|
// !!! structure with NO Rotation. If We want to Rotate bitmap , We have to
|
|
// !!! re-setup this GLYPHDATA structure. Pls look into end of this function.
|
|
// !!! But No need to ratate bitmap , We don't need to re-set up it.
|
|
// !!! hideyukn 08-Feb-1993
|
|
// !!!
|
|
#endif // FE_SB
|
|
|
|
//
|
|
// Fill in the GLYPHDATA portion (metrics) of the RASTERGLYPH.
|
|
//
|
|
if ( pgd != (GLYPHDATA *)NULL )
|
|
{
|
|
vComputeSimulatedGLYPHDATA (
|
|
pgd,
|
|
pjBitmap,
|
|
cxNoSim,
|
|
pcvtfh->cy,
|
|
(ULONG)sAscent,
|
|
pfc->ptlScale.x,
|
|
pfc->ptlScale.y,
|
|
pfo
|
|
);
|
|
pgd->hg = hg;
|
|
}
|
|
|
|
//
|
|
// Fill in the bitmap portion of the RASTERGLYPH.
|
|
//
|
|
if ( pv != NULL )
|
|
{
|
|
if (cxNoSim == 0)
|
|
{
|
|
// stolen from ttfd:
|
|
|
|
GLYPHBITS *pgb = (GLYPHBITS *)pv;
|
|
|
|
pgb->ptlOrigin.x = 0;
|
|
pgb->ptlOrigin.y = -sAscent;
|
|
|
|
pgb->sizlBitmap.cx = 1; // cheating
|
|
pgb->sizlBitmap.cy = 1; // cheating
|
|
|
|
|
|
*((ULONG *)pgb->aj) = 0; // fill in a blank 1x1 dib
|
|
}
|
|
else
|
|
{
|
|
|
|
if (pfc->flStretch & FC_DO_STRETCH)
|
|
{
|
|
BYTE ajStretchBuffer[CJ_STRETCH];
|
|
if (pfc->flStretch & FC_STRETCH_WIDE)
|
|
{
|
|
EngAcquireSemaphore(ghsemBMFD);
|
|
|
|
// need to put try/except here so as to release the semaphore
|
|
// in case the file disappeares [bodind]
|
|
|
|
#ifndef BMFD_NO_TRY_EXCEPT
|
|
try
|
|
{
|
|
#endif
|
|
vStretchCvtToBitmap(
|
|
pv,
|
|
pjBitmap,
|
|
cxNoSim ,
|
|
pcvtfh->cy ,
|
|
(ULONG)sAscent ,
|
|
pfc->ajStretchBuffer,
|
|
pfc->ptlScale.x,
|
|
pfc->ptlScale.y,
|
|
pfo->flFontType & (FO_SIM_BOLD | FO_SIM_ITALIC));
|
|
#ifndef BMFD_NO_TRY_EXCEPT
|
|
}
|
|
except (EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
WARNING("bmfd! exception while stretching a glyph\n");
|
|
vBmfdMarkFontGone(
|
|
(FONTFILE *)pfc->hff,
|
|
GetExceptionCode()
|
|
);
|
|
}
|
|
#endif
|
|
|
|
EngReleaseSemaphore(ghsemBMFD);
|
|
}
|
|
else
|
|
{
|
|
// we are protected by higher level try/excepts
|
|
|
|
vStretchCvtToBitmap(
|
|
pv,
|
|
pjBitmap,
|
|
cxNoSim ,
|
|
pcvtfh->cy ,
|
|
(ULONG)sAscent ,
|
|
ajStretchBuffer,
|
|
pfc->ptlScale.x,
|
|
pfc->ptlScale.y,
|
|
pfo->flFontType & (FO_SIM_BOLD | FO_SIM_ITALIC));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (pfo->flFontType & (FO_SIM_BOLD | FO_SIM_ITALIC))
|
|
{
|
|
case 0:
|
|
|
|
vCvtToBmp(
|
|
pv ,
|
|
pgd ,
|
|
pjBitmap ,
|
|
cxNoSim ,
|
|
pcvtfh->cy ,
|
|
(ULONG)sAscent
|
|
);
|
|
|
|
break;
|
|
|
|
case FO_SIM_BOLD:
|
|
|
|
vCvtToBoldBmp(
|
|
pv ,
|
|
pgd ,
|
|
pjBitmap ,
|
|
cxNoSim ,
|
|
pcvtfh->cy ,
|
|
(ULONG)sAscent
|
|
);
|
|
|
|
break;
|
|
|
|
case FO_SIM_ITALIC:
|
|
|
|
vCvtToItalicBmp(
|
|
pv ,
|
|
pgd ,
|
|
pjBitmap ,
|
|
cxNoSim ,
|
|
pcvtfh->cy ,
|
|
(ULONG)sAscent
|
|
);
|
|
|
|
break;
|
|
|
|
case (FO_SIM_BOLD | FO_SIM_ITALIC):
|
|
|
|
vCvtToBoldItalicBmp(
|
|
pv ,
|
|
pgd ,
|
|
pjBitmap ,
|
|
cxNoSim ,
|
|
pcvtfh->cy ,
|
|
(ULONG)sAscent
|
|
);
|
|
|
|
break;
|
|
|
|
default:
|
|
RIP("BMFD!WRONG SIMULATION REQUEST\n");
|
|
|
|
}
|
|
}
|
|
}
|
|
// Record the pointer to the RASTERGLYPH in the pointer table.
|
|
|
|
if ( pgd != NULL )
|
|
{
|
|
pgd->gdf.pgb = (GLYPHBITS *)pv;
|
|
}
|
|
|
|
vBmfdScrubGLYPHBITS((GLYPHBITS*)pv);
|
|
}
|
|
|
|
#ifdef FE_SB // BmfdQueryFontData(): Set up GLYPHDATA and GLYPHBITS for Rotation
|
|
|
|
// Check rotation
|
|
|
|
if( pfc->ulRotate != 0L )
|
|
{
|
|
|
|
// Rotate GLYPHDATA and GLYPHBITS
|
|
|
|
// if pv and pvDst is NULL , We only set up GLYPHDATA only
|
|
// and if pgd is NULL , we only set up pvDst
|
|
|
|
if (pvDst)
|
|
memset(pvDst, 0, cjSize);
|
|
|
|
vFill_RotateGLYPHDATA(
|
|
pgd, // GLYPHDATA *pDistinationGlyphData
|
|
pv, // PVOID SourceGLYPHBITS
|
|
pvDst, // PVOID DistinationGLYPHBITS
|
|
pfc->ulRotate // UINT Rotate degree
|
|
);
|
|
|
|
// Free GLYPHBITS tenmorary buffer
|
|
|
|
// !!! Now pvDst is Original buffer from GRE.
|
|
|
|
if( pv != NULL ) VFREEMEM( pv );
|
|
}
|
|
|
|
#endif // FE_SB
|
|
return cjGlyphData;
|
|
|
|
case QFD_MAXEXTENTS:
|
|
//
|
|
// If buffer NULL, return size.
|
|
//
|
|
if ( pv == (PVOID) NULL )
|
|
return (sizeof(FD_DEVICEMETRICS));
|
|
|
|
//
|
|
// Otherwise, copy the data structure.
|
|
//
|
|
else
|
|
return cjBmfdDeviceMetrics(pfc, (FD_DEVICEMETRICS *) pv);
|
|
|
|
case QFD_GLYPHANDOUTLINE:
|
|
default:
|
|
|
|
WARNING("gdisrv!BmfdQueryFontData(): unsupported mode\n");
|
|
return FD_ERROR;
|
|
}
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BmfdQueryAdvanceWidths *
|
|
* *
|
|
* Queries the advance widths for a range of glyphs. *
|
|
* *
|
|
* Sat 16-Jan-1993 22:28:41 -by- Charles Whitmer [chuckwh] *
|
|
* Wrote it. The code is repeated to avoid multiplies wherever possible. *
|
|
* The crazy loop unrolling cuts the time of this routine by 25%. *
|
|
\**************************************************************************/
|
|
|
|
typedef struct _TYPE2TABLE
|
|
{
|
|
USHORT cx;
|
|
USHORT offData;
|
|
} TYPE2TABLE;
|
|
|
|
typedef struct _TYPE3TABLE
|
|
{
|
|
USHORT cx;
|
|
USHORT offDataLo;
|
|
USHORT offDataHi;
|
|
} TYPE3TABLE;
|
|
|
|
BOOL BmfdQueryAdvanceWidths
|
|
(
|
|
FONTOBJ *pfo,
|
|
ULONG iMode,
|
|
HGLYPH *phg,
|
|
LONG *plWidths,
|
|
ULONG cGlyphs
|
|
)
|
|
{
|
|
USHORT *psWidths = (USHORT *) plWidths; // True for the cases we handle.
|
|
|
|
FONTCONTEXT *pfc ;
|
|
FACEINFO *pfai ;
|
|
CVTFILEHDR *pcvtfh ;
|
|
BYTE *pjTable ;
|
|
USHORT xScale ;
|
|
USHORT cxExtra ;
|
|
USHORT cx;
|
|
|
|
if (!bReconnectBmfdFont(PFF(pfo->iFile)))
|
|
{
|
|
WARNING("bmfd!bmfdQueryAdvanceWidths: this file is gone\n");
|
|
return FD_ERROR;
|
|
}
|
|
|
|
// If pfo->pvProducer is NULL, then we need to open a font context.
|
|
//
|
|
if ( pfo->pvProducer == (PVOID) NULL )
|
|
pfo->pvProducer = (PVOID) BmfdOpenFontContext(pfo);
|
|
|
|
pfc = PFC(pfo->pvProducer);
|
|
|
|
if ( pfc == (PFONTCONTEXT) NULL )
|
|
{
|
|
WARNING("bmfd!bmfdQueryAdvanceWidths: cannot create font context\n");
|
|
return FD_ERROR;
|
|
}
|
|
|
|
pfai = pfc->pfai;
|
|
pcvtfh = &(pfai->cvtfh);
|
|
pjTable = (BYTE *) pfai->re.pvResData + pcvtfh->dpOffsetTable;
|
|
xScale = (USHORT) (pfc->ptlScale.x << 4);
|
|
cxExtra = (pfc->flFontType & FO_SIM_BOLD) ? 16 : 0;
|
|
|
|
if (iMode > QAW_GETEASYWIDTHS)
|
|
return(GDI_ERROR);
|
|
|
|
// Retrieve widths from type 2 tables.
|
|
|
|
if (pcvtfh->iVersion == 0x00000200)
|
|
{
|
|
TYPE2TABLE *p2t = (TYPE2TABLE *) pjTable;
|
|
|
|
if (xScale == 16)
|
|
{
|
|
while (cGlyphs > 3)
|
|
{
|
|
cx = p2t[phg[0]].cx;
|
|
psWidths[0] = (cx << 4) + cxExtra;
|
|
cx = p2t[phg[1]].cx;
|
|
psWidths[1] = (cx << 4) + cxExtra;
|
|
cx = p2t[phg[2]].cx;
|
|
psWidths[2] = (cx << 4) + cxExtra;
|
|
cx = p2t[phg[3]].cx;
|
|
psWidths[3] = (cx << 4) + cxExtra;
|
|
|
|
phg += 4; psWidths += 4; cGlyphs -= 4;
|
|
}
|
|
|
|
while (cGlyphs)
|
|
{
|
|
cx = p2t[*phg].cx;
|
|
*psWidths = (cx << 4) + cxExtra;
|
|
phg++,psWidths++,cGlyphs--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (cGlyphs)
|
|
{
|
|
cx = p2t[*phg].cx;
|
|
*psWidths = (cx * xScale) + cxExtra;
|
|
phg++,psWidths++,cGlyphs--;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Retrieve widths from type 3 tables.
|
|
|
|
else
|
|
{
|
|
TYPE3TABLE *p3t = (TYPE3TABLE *) pjTable;
|
|
|
|
if (xScale == 16)
|
|
{
|
|
while (cGlyphs > 3)
|
|
{
|
|
cx = p3t[phg[0]].cx;
|
|
psWidths[0] = (cx << 4) + cxExtra;
|
|
cx = p3t[phg[1]].cx;
|
|
psWidths[1] = (cx << 4) + cxExtra;
|
|
cx = p3t[phg[2]].cx;
|
|
psWidths[2] = (cx << 4) + cxExtra;
|
|
cx = p3t[phg[3]].cx;
|
|
psWidths[3] = (cx << 4) + cxExtra;
|
|
phg += 4; psWidths += 4; cGlyphs -= 4;
|
|
}
|
|
|
|
while (cGlyphs)
|
|
{
|
|
cx = p3t[*phg].cx;
|
|
*psWidths = (cx << 4) + cxExtra;
|
|
phg++,psWidths++,cGlyphs--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (cGlyphs)
|
|
{
|
|
cx = p3t[*phg].cx;
|
|
*psWidths = (cx * xScale) + cxExtra;
|
|
phg++,psWidths++,cGlyphs--;
|
|
}
|
|
}
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
/******************************Public*Routine******************************\
|
|
* BmfdQueryFontFile
|
|
*
|
|
* A function to query per font file information.
|
|
*
|
|
* Parameters:
|
|
*
|
|
* hff Handle to a font file.
|
|
*
|
|
* ulMode This is a 32-bit number that must be one of the following
|
|
* values:
|
|
*
|
|
* Allowed ulMode values:
|
|
* ----------------------
|
|
*
|
|
* QFF_DESCRIPTION -- copies a UNICODE string in the buffer
|
|
* that describes the contents of the font file.
|
|
*
|
|
* QFF_NUMFACES -- returns number of faces in the font file.
|
|
*
|
|
* cjBuf Maximum number of BYTEs to copy into the buffer. The
|
|
* driver will not copy more than this many BYTEs.
|
|
*
|
|
* This should be zero if pulBuf is NULL.
|
|
*
|
|
* This parameter is not used in QFF_NUMFACES mode.
|
|
*
|
|
* pulBuf Pointer to the buffer to receive the data
|
|
* If this is NULL, then the required buffer size
|
|
* is returned as a count of BYTEs. Notice that this
|
|
* is a PULONG, to enforce 32-bit data alignment.
|
|
*
|
|
* This parameter is not used in QFF_NUMFACES mode.
|
|
*
|
|
* Returns:
|
|
*
|
|
* If mode is QFF_DESCRIPTION, then the number of BYTEs copied into
|
|
* the buffer is returned by the function. If pulBuf is NULL,
|
|
* then the required buffer size (as a count of BYTEs) is returned.
|
|
*
|
|
* If mode is QFF_NUMFACES, then number of faces in font file is returned.
|
|
*
|
|
* FD_ERROR is returned if an error occurs.
|
|
*
|
|
* History:
|
|
* 30-Aug-1992 -by- Gilman Wong [gilmanw]
|
|
* Added QFF_NUMFACES mode (IFI/DDI merge).
|
|
*
|
|
* Fri 20-Mar-1992 -by- Bodin Dresevic [BodinD]
|
|
* Wrote it.
|
|
\**************************************************************************/
|
|
|
|
LONG
|
|
BmfdQueryFontFile (
|
|
HFF hff, // handle to font file
|
|
ULONG ulMode, // type of query
|
|
ULONG cjBuf, // size of buffer (in BYTEs)
|
|
PULONG pulBuf // return buffer (NULL if requesting size of data)
|
|
)
|
|
{
|
|
// Verify the HFF.
|
|
|
|
if (hff == HFF_INVALID)
|
|
{
|
|
WARNING("bmfd!BmfdQueryFontFile(): invalid HFF\n");
|
|
return(FD_ERROR);
|
|
}
|
|
|
|
//
|
|
// Which mode?.
|
|
//
|
|
switch(ulMode)
|
|
{
|
|
case QFF_DESCRIPTION:
|
|
//
|
|
// If present, return the description string.
|
|
//
|
|
if ( PFF(hff)->cjDescription != 0 )
|
|
{
|
|
//
|
|
// If there is a buffer, copy the data.
|
|
//
|
|
if ( pulBuf != (PULONG) NULL )
|
|
{
|
|
//
|
|
// Is buffer big enough?
|
|
//
|
|
if ( cjBuf < PFF(hff)->cjDescription )
|
|
{
|
|
WARNING("bmfd!BmfdQueryFontFile(): buffer too small for string\n");
|
|
return (FD_ERROR);
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory((PVOID) pulBuf,
|
|
((PBYTE) PFF(hff)) + PFF(hff)->dpwszDescription,
|
|
PFF(hff)->cjDescription);
|
|
}
|
|
}
|
|
|
|
return (LONG) PFF(hff)->cjDescription;
|
|
}
|
|
|
|
//
|
|
// Otherwise, substitute the facename.
|
|
//
|
|
else
|
|
{
|
|
//
|
|
// There is no description string associated with the font therefore we
|
|
// substitue the facename of the first font in the font file.
|
|
//
|
|
IFIMETRICS *pifi = PFF(hff)->afai[0].pifi;
|
|
PWSZ pwszFacename = (PWSZ)((PBYTE) pifi + pifi->dpwszFaceName);
|
|
ULONG cjFacename = (wcslen(pwszFacename) + 1) * sizeof(WCHAR);
|
|
|
|
//
|
|
// If there is a buffer, copy to it.
|
|
//
|
|
if ( pulBuf != (PULONG) NULL )
|
|
{
|
|
//
|
|
// Is buffer big enough?
|
|
//
|
|
if ( cjBuf < cjFacename )
|
|
{
|
|
WARNING("bmfd!BmfdQueryFontFile(): buffer too small for face\n");
|
|
return (FD_ERROR);
|
|
}
|
|
else
|
|
{
|
|
RtlCopyMemory((PVOID) pulBuf,
|
|
(PVOID) pwszFacename,
|
|
cjFacename);
|
|
}
|
|
}
|
|
return ((LONG) cjFacename);
|
|
}
|
|
|
|
case QFF_NUMFACES:
|
|
return PFF(hff)->cFntRes;
|
|
|
|
default:
|
|
WARNING("gdisrv!BmfdQueryFontFile(): unknown mode\n");
|
|
return FD_ERROR;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/******************************Public*Routine******************************\
|
|
* cjBmfdDeviceMetrics
|
|
*
|
|
*
|
|
* Effects:
|
|
*
|
|
* Warnings:
|
|
*
|
|
* History:
|
|
* 30-Aug-1992 -by- Gilman Wong [gilmanw]
|
|
* Stole it from BodinD's FdQueryFaceAttr() implementation.
|
|
\**************************************************************************/
|
|
|
|
ULONG
|
|
cjBmfdDeviceMetrics (
|
|
PFONTCONTEXT pfc,
|
|
FD_DEVICEMETRICS *pdevm
|
|
)
|
|
{
|
|
PIFIMETRICS pifi;
|
|
UINT xScale = pfc->ptlScale.x;
|
|
UINT yScale = pfc->ptlScale.y;
|
|
|
|
// compute the accelerator flags for this font
|
|
// If this is a bitmap font where some of the glyphs have zero widths,
|
|
// we need to turn off all the accelerator flags
|
|
|
|
if (pfc->pfai->cvtfh.fsFlags & FS_ZERO_WIDTH_GLYPHS)
|
|
{
|
|
pdevm->flRealizedType = 0;
|
|
}
|
|
else
|
|
{
|
|
pdevm->flRealizedType =
|
|
(
|
|
FDM_TYPE_BM_SIDE_CONST | // all char bitmaps have the same cy
|
|
FDM_TYPE_CONST_BEARINGS | // ac spaces for all chars the same, not 0 necessarilly
|
|
FDM_TYPE_MAXEXT_EQUAL_BM_SIDE
|
|
);
|
|
|
|
// the above flags are set regardless of the possible simulation performed on the face
|
|
// the remaining two are only set if italicizing has not been done
|
|
|
|
if ( !(pfc->flFontType & FO_SIM_ITALIC) )
|
|
{
|
|
pdevm->flRealizedType |=
|
|
(FDM_TYPE_ZERO_BEARINGS | FDM_TYPE_CHAR_INC_EQUAL_BM_BASE);
|
|
}
|
|
}
|
|
|
|
pifi = pfc->pfai->pifi;
|
|
|
|
#ifdef FE_SB // ROTATION:cjBmfdDeviceMetric(): set direction unit vectors
|
|
|
|
/**********************************************************************
|
|
Coordinate (0 degree) (90 degree) (180 degree) (270 degree)
|
|
System
|
|
|
|
|(-) A A
|
|
| Side | | Base
|
|
| | | Base Side
|
|
-----+----->X +------> <------+ <------+ +------>
|
|
(-) | (+) Base Side | |
|
|
| Side| | Base
|
|
|(+) V V
|
|
Y
|
|
***********************************************************************/
|
|
|
|
switch( pfc->ulRotate )
|
|
{
|
|
case 0L:
|
|
|
|
// the direction unit vectors for all ANSI bitmap fonts are the
|
|
// same. We do not even have to look to the font context:
|
|
|
|
vLToE(&pdevm->pteBase.x, 1L);
|
|
vLToE(&pdevm->pteBase.y, 0L);
|
|
vLToE(&pdevm->pteSide.x, 0L);
|
|
vLToE(&pdevm->pteSide.y, -1L); // y axis points down
|
|
|
|
pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale);
|
|
pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale );
|
|
|
|
pdevm->ptlUnderline1.x = 0L;
|
|
pdevm->ptlUnderline1.y = -(LONG)pifi->fwdUnderscorePosition * yScale;
|
|
|
|
pdevm->ptlStrikeOut.x =
|
|
(pfc->flFontType & FO_SIM_ITALIC) ? (LONG)pifi->fwdStrikeoutPosition / 2 : 0;
|
|
pdevm->ptlStrikeOut.y = -(LONG)pifi->fwdStrikeoutPosition * yScale;
|
|
|
|
pdevm->ptlULThickness.x = 0;
|
|
pdevm->ptlULThickness.y = (LONG)pifi->fwdUnderscoreSize * yScale;
|
|
|
|
pdevm->ptlSOThickness.x = 0;
|
|
pdevm->ptlSOThickness.y = (LONG)pifi->fwdStrikeoutSize * yScale;
|
|
|
|
break;
|
|
|
|
case 900L:
|
|
|
|
// the direction unit vectors for all ANSI bitmap fonts are the
|
|
// same. We do not even have to look to the font context:
|
|
|
|
vLToE(&pdevm->pteBase.x, 0L);
|
|
vLToE(&pdevm->pteBase.y, -1L);
|
|
vLToE(&pdevm->pteSide.x, -1L);
|
|
vLToE(&pdevm->pteSide.y, 0L);
|
|
|
|
|
|
pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale);
|
|
pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale );
|
|
|
|
pdevm->ptlUnderline1.x = -(LONG)pifi->fwdUnderscorePosition * yScale;
|
|
pdevm->ptlUnderline1.y = 0;
|
|
|
|
pdevm->ptlStrikeOut.x = -(LONG)pifi->fwdStrikeoutPosition * yScale;
|
|
pdevm->ptlStrikeOut.y =
|
|
(pfc->flFontType & FO_SIM_ITALIC) ? -(LONG)pifi->fwdStrikeoutPosition / 2 : 0;
|
|
|
|
pdevm->ptlULThickness.x = (LONG)pifi->fwdUnderscoreSize * yScale;
|
|
pdevm->ptlULThickness.y = 0;
|
|
|
|
pdevm->ptlSOThickness.x = (LONG)pifi->fwdStrikeoutSize * yScale;
|
|
pdevm->ptlSOThickness.y = 0;
|
|
|
|
break;
|
|
|
|
case 1800L:
|
|
|
|
// the direction unit vectors for all ANSI bitmap fonts are the
|
|
// same. We do not even have to look to the font context:
|
|
|
|
vLToE(&pdevm->pteBase.x, -1L);
|
|
vLToE(&pdevm->pteBase.y, 0L);
|
|
vLToE(&pdevm->pteSide.x, 0L);
|
|
vLToE(&pdevm->pteSide.y, 1L);
|
|
|
|
|
|
pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale);
|
|
pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale );
|
|
|
|
pdevm->ptlUnderline1.x = 0L;
|
|
pdevm->ptlUnderline1.y = (LONG)pifi->fwdUnderscorePosition * yScale;
|
|
|
|
pdevm->ptlStrikeOut.x =
|
|
(pfc->flFontType & FO_SIM_ITALIC) ? -(LONG)pifi->fwdStrikeoutPosition / 2 : 0;
|
|
pdevm->ptlStrikeOut.y = pifi->fwdStrikeoutPosition * yScale;
|
|
|
|
pdevm->ptlULThickness.x = 0;
|
|
pdevm->ptlULThickness.y = (LONG)pifi->fwdUnderscoreSize * yScale;
|
|
|
|
pdevm->ptlSOThickness.x = 0;
|
|
pdevm->ptlSOThickness.y = (LONG)pifi->fwdStrikeoutSize * yScale;
|
|
|
|
break;
|
|
|
|
case 2700L:
|
|
|
|
// the direction unit vectors for all ANSI bitmap fonts are the
|
|
// same. We do not even have to look to the font context:
|
|
|
|
vLToE(&pdevm->pteBase.x, 0L);
|
|
vLToE(&pdevm->pteBase.y, 1L);
|
|
vLToE(&pdevm->pteSide.x, 1L);
|
|
vLToE(&pdevm->pteSide.y, 0L);
|
|
|
|
pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale);
|
|
pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale );
|
|
|
|
pdevm->ptlUnderline1.x = (LONG)pifi->fwdUnderscorePosition * yScale;
|
|
pdevm->ptlUnderline1.y = 0L;
|
|
|
|
pdevm->ptlStrikeOut.x = (LONG)pifi->fwdStrikeoutPosition * yScale;
|
|
pdevm->ptlStrikeOut.y =
|
|
(pfc->flFontType & FO_SIM_ITALIC) ? (LONG)pifi->fwdStrikeoutPosition / 2 : 0;
|
|
|
|
pdevm->ptlULThickness.x = (LONG)pifi->fwdUnderscoreSize * yScale;
|
|
pdevm->ptlULThickness.y = 0;
|
|
|
|
pdevm->ptlSOThickness.x = (LONG)pifi->fwdStrikeoutSize * yScale;
|
|
pdevm->ptlSOThickness.y = 0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
}
|
|
|
|
#else
|
|
|
|
// the direction unit vectors for all ANSI bitmap fonts are the
|
|
// same. We do not even have to look to the font context:
|
|
|
|
vLToE(&pdevm->pteBase.x, 1L);
|
|
vLToE(&pdevm->pteBase.y, 0L);
|
|
vLToE(&pdevm->pteSide.x, 0L);
|
|
vLToE(&pdevm->pteSide.y, -1L); // y axis points down
|
|
|
|
#endif // FE_SB
|
|
|
|
// Set the constant increment for a fixed pitch font. Don't forget to
|
|
// take into account a bold simulation!
|
|
|
|
pdevm->lD = 0;
|
|
|
|
if ((pifi->flInfo & FM_INFO_CONSTANT_WIDTH) &&
|
|
!(pfc->pfai->cvtfh.fsFlags & FS_ZERO_WIDTH_GLYPHS))
|
|
{
|
|
pdevm->lD = (LONG) pifi->fwdMaxCharInc * xScale;
|
|
|
|
if (pfc->flFontType & FO_SIM_BOLD)
|
|
pdevm->lD++;
|
|
}
|
|
|
|
#ifndef FE_SB // cjBmfdDeviceMetric():
|
|
|
|
// for a bitmap font there is no difference between notional and device
|
|
// coords, so that the Ascender and Descender can be copied directly
|
|
// from PIFIMETRICS where these two numbers are in notional coords
|
|
|
|
pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale);
|
|
pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale );
|
|
|
|
pdevm->ptlUnderline1.x = 0L;
|
|
pdevm->ptlUnderline1.y = - pifi->fwdUnderscorePosition * yScale;
|
|
|
|
pdevm->ptlStrikeOut.y = - pifi->fwdStrikeoutPosition * yScale;
|
|
|
|
pdevm->ptlStrikeOut.x =
|
|
(pfc->flFontType & FO_SIM_ITALIC) ? (LONG)pifi->fwdStrikeoutPosition / 2 : 0;
|
|
|
|
pdevm->ptlULThickness.x = 0;
|
|
pdevm->ptlULThickness.y = (LONG)pifi->fwdUnderscoreSize * yScale;
|
|
|
|
pdevm->ptlSOThickness.x = 0;
|
|
pdevm->ptlSOThickness.y = (LONG)pifi->fwdStrikeoutSize * yScale;
|
|
|
|
|
|
// for a bitmap font there is no difference between notional and device
|
|
// coords, so that the Ascender and Descender can be copied directly
|
|
// from PIFIMETRICS where these two numbers are in notional coords
|
|
|
|
pdevm->fxMaxAscender = LTOFX((LONG)pifi->fwdWinAscender * yScale);
|
|
pdevm->fxMaxDescender = LTOFX((LONG)pifi->fwdWinDescender * yScale );
|
|
|
|
pdevm->ptlUnderline1.x = 0L;
|
|
pdevm->ptlUnderline1.y = - pifi->fwdUnderscorePosition * yScale;
|
|
|
|
pdevm->ptlStrikeOut.y = - pifi->fwdStrikeoutPosition * yScale;
|
|
|
|
pdevm->ptlStrikeOut.x =
|
|
(pfc->flFontType & FO_SIM_ITALIC) ? (LONG)pifi->fwdStrikeoutPosition / 2 : 0;
|
|
|
|
pdevm->ptlULThickness.x = 0;
|
|
pdevm->ptlULThickness.y = (LONG)pifi->fwdUnderscoreSize * yScale;
|
|
|
|
pdevm->ptlSOThickness.x = 0;
|
|
pdevm->ptlSOThickness.y = (LONG)pifi->fwdStrikeoutSize * yScale;
|
|
|
|
#endif // FE_SB
|
|
|
|
// max glyph bitmap width in pixels in x direction
|
|
// does not need to be multiplied by xScale, this has already been taken into
|
|
// account, see the code in fdfc.c:
|
|
// cjGlyphMax =
|
|
// cjGlyphDataSimulated(
|
|
// pfo,
|
|
// (ULONG)pcvtfh->usMaxWidth * ptlScale.x,
|
|
// (ULONG)pcvtfh->cy * ptlScale.y,
|
|
// &cxMax);
|
|
// [bodind]
|
|
|
|
pdevm->cxMax = pfc->cxMax;
|
|
|
|
// new fields
|
|
|
|
pdevm->cyMax = pfc->cjGlyphMax / ((pfc->cxMax + 7) / 8);
|
|
pdevm->cjGlyphMax = pfc->cjGlyphMax;
|
|
|
|
|
|
return (sizeof(FD_DEVICEMETRICS));
|
|
}
|
|
|
|
|
|
#ifdef FE_SB // vFill_RotateGLYPHDATA()
|
|
|
|
#define CJ_DIB8_SCAN(cx) ((((cx) + 7) & ~7) >> 3)
|
|
|
|
|
|
/*
|
|
BIT macro returns non zero ( if bitmap[x,y] is on) or zero (bitmap[x,y] is off).
|
|
pb : bitmap
|
|
w : byte count per scan line
|
|
x : Xth bit in x direction
|
|
y : scan line
|
|
|
|
x
|
|
-------------------->
|
|
y | *******************************
|
|
| *******************************
|
|
| *******************************
|
|
V
|
|
*/
|
|
|
|
BYTE BitON[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
|
|
BYTE BitOFF[8] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
|
|
#define BIT(pb, w, x, y) (*((PBYTE)(pb) + (w) * (y) + ((x)/8)) & (BitON[(x) & 7]))
|
|
|
|
/******************************************************************************\
|
|
*
|
|
* VOID vFill_RotateGLYPHDATA()
|
|
*
|
|
*
|
|
* History :
|
|
*
|
|
* 11-Feb-1992 (Thu) -by- Hideyuki Nagase [hideyukn]
|
|
* Wrote it.
|
|
*
|
|
\******************************************************************************/
|
|
|
|
VOID
|
|
vFill_RotateGLYPHDATA (
|
|
GLYPHDATA *pDistGlyphData,
|
|
PVOID SrcGLYPHBITS,
|
|
PVOID DistGLYPHBITS,
|
|
UINT RotateDegree
|
|
)
|
|
{
|
|
GLYPHDATA SrcGlyphData;
|
|
ULONG ulSrcBitmapSizeX , ulDistBitmapSizeX;
|
|
ULONG ulSrcBitmapSizeY , ulDistBitmapSizeY;
|
|
GLYPHBITS *pSrcGlyphBits , *pDistGlyphBits;
|
|
PBYTE pbSrcBitmap , pbDistBitmap;
|
|
UINT x , y , k;
|
|
UINT cjScanSrc , cjScanDist;
|
|
PBYTE pb;
|
|
|
|
// Now , in this point *pDistGlyphData contain No rotated GLYPHDATA
|
|
// Copy No rotate GLYPHDATA to Source Area . later we write back changed data to
|
|
// distination area.
|
|
|
|
//
|
|
// these field are defined as:
|
|
//
|
|
// unit vector along the baseline - fxD, fxA, fxAB
|
|
// or
|
|
// unit vector in the ascent direction - fxInkTop, fxInkBottom
|
|
//
|
|
// Because baseline direction and ascent direction are rotated
|
|
// as ulRotate specifies, these fileds should be considered as
|
|
// rotation independent.
|
|
//
|
|
|
|
// Init Local value
|
|
// Set pointer to GLYPHBITS structure
|
|
|
|
pSrcGlyphBits = (GLYPHBITS *)SrcGLYPHBITS;
|
|
pDistGlyphBits = (GLYPHBITS *)DistGLYPHBITS;
|
|
|
|
if( pDistGlyphData != NULL )
|
|
{
|
|
|
|
// Init Source GlyphData
|
|
|
|
SrcGlyphData = *pDistGlyphData;
|
|
|
|
// Record the pointer to GLYPHBITS in GLYPHDATA structure
|
|
|
|
pDistGlyphData->gdf.pgb = pDistGlyphBits;
|
|
}
|
|
|
|
// Check Rotation
|
|
|
|
switch( RotateDegree )
|
|
{
|
|
case 0L :
|
|
|
|
WARNING("BMFD:vFill_RotateGLYPHDATA():Why come here?\n");
|
|
break;
|
|
|
|
case 900L :
|
|
|
|
if( pDistGlyphData != NULL )
|
|
{
|
|
|
|
// Setup GLYPHDATA structure
|
|
|
|
// x = y;
|
|
// y = -x; !!!! HighPart include plus or minus flag
|
|
|
|
pDistGlyphData->ptqD.x = SrcGlyphData.ptqD.y;
|
|
pDistGlyphData->ptqD.y.HighPart = -(SrcGlyphData.ptqD.x.HighPart);
|
|
pDistGlyphData->ptqD.y.LowPart = SrcGlyphData.ptqD.x.LowPart;
|
|
|
|
// top = -rihgt ; bottom = -left ; right = bottom ; left = top
|
|
|
|
pDistGlyphData->rclInk.top = -(SrcGlyphData.rclInk.right);
|
|
pDistGlyphData->rclInk.bottom = -(SrcGlyphData.rclInk.left);
|
|
pDistGlyphData->rclInk.right = SrcGlyphData.rclInk.bottom;
|
|
pDistGlyphData->rclInk.left = SrcGlyphData.rclInk.top;
|
|
|
|
}
|
|
|
|
if( pSrcGlyphBits != NULL && pDistGlyphBits != NULL )
|
|
{
|
|
|
|
// Get Bitmap size
|
|
|
|
ulSrcBitmapSizeX = pSrcGlyphBits->sizlBitmap.cx;
|
|
ulSrcBitmapSizeY = pSrcGlyphBits->sizlBitmap.cy;
|
|
|
|
// Get the pointer to Bitmap images
|
|
|
|
pbSrcBitmap = (PBYTE)pSrcGlyphBits->aj;
|
|
pbDistBitmap = (PBYTE)pDistGlyphBits->aj;
|
|
|
|
// Set Distination Bitmap Size
|
|
|
|
ulDistBitmapSizeX = ulSrcBitmapSizeY;
|
|
ulDistBitmapSizeY = ulSrcBitmapSizeX;
|
|
|
|
// Setup GLYPHBITS stuff
|
|
|
|
pDistGlyphBits->ptlOrigin.x = pSrcGlyphBits->ptlOrigin.y;
|
|
pDistGlyphBits->ptlOrigin.y = -(LONG)(ulSrcBitmapSizeX);
|
|
|
|
pDistGlyphBits->sizlBitmap.cx = pSrcGlyphBits->sizlBitmap.cy;
|
|
pDistGlyphBits->sizlBitmap.cy = pSrcGlyphBits->sizlBitmap.cx;
|
|
|
|
// Rotate bitmap inage
|
|
|
|
cjScanSrc = CJ_DIB8_SCAN( ulSrcBitmapSizeX );
|
|
cjScanDist = CJ_DIB8_SCAN( ulDistBitmapSizeX );
|
|
|
|
// we need to clear the dst buffer because the S3 driver expects
|
|
// extra stuff on the edges to be zeroed out
|
|
|
|
for ( y = 0; y < ulDistBitmapSizeY ; y++ )
|
|
{
|
|
for ( x= 0 , pb = pbDistBitmap + cjScanDist * y ;
|
|
x < ulDistBitmapSizeX ;
|
|
x++ )
|
|
{
|
|
k = x & 7; // k is from 0 to 7;
|
|
|
|
if ( BIT( pbSrcBitmap , cjScanSrc,
|
|
ulDistBitmapSizeY - y - 1 ,
|
|
x
|
|
)
|
|
)
|
|
*pb |= (BitON[ k ] );
|
|
else
|
|
*pb &= (BitOFF[ k ] );
|
|
if ( k == 7 )
|
|
pb++;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case 1800L :
|
|
|
|
if( pDistGlyphData != NULL )
|
|
{
|
|
|
|
// Setup GLYPHDATA structure
|
|
|
|
// x = -x; !!!! HighPart include plus or minus flag
|
|
// y = -y; !!!! HighPart include plus or minus flag
|
|
|
|
pDistGlyphData->ptqD.x.HighPart = -(SrcGlyphData.ptqD.x.HighPart);
|
|
pDistGlyphData->ptqD.x.LowPart = SrcGlyphData.ptqD.x.LowPart;
|
|
pDistGlyphData->ptqD.y.HighPart = -(SrcGlyphData.ptqD.y.HighPart);
|
|
pDistGlyphData->ptqD.y.LowPart = SrcGlyphData.ptqD.y.LowPart;
|
|
|
|
// top = -bottom ; bottom = -top ; right = -left ; left = -right
|
|
|
|
pDistGlyphData->rclInk.top = -(SrcGlyphData.rclInk.bottom);
|
|
pDistGlyphData->rclInk.bottom = -(SrcGlyphData.rclInk.top);
|
|
pDistGlyphData->rclInk.right = -(SrcGlyphData.rclInk.left);
|
|
pDistGlyphData->rclInk.left = -(SrcGlyphData.rclInk.right);
|
|
}
|
|
|
|
if( pSrcGlyphBits != NULL && pDistGlyphBits != NULL )
|
|
{
|
|
|
|
// Get Bitmap size
|
|
|
|
ulSrcBitmapSizeX = pSrcGlyphBits->sizlBitmap.cx;
|
|
ulSrcBitmapSizeY = pSrcGlyphBits->sizlBitmap.cy;
|
|
|
|
// Get the pointer to Bitmap images
|
|
|
|
pbSrcBitmap = (PBYTE)pSrcGlyphBits->aj;
|
|
pbDistBitmap = (PBYTE)pDistGlyphBits->aj;
|
|
|
|
// Set Distination Bitmap Size
|
|
|
|
ulDistBitmapSizeX = ulSrcBitmapSizeX;
|
|
ulDistBitmapSizeY = ulSrcBitmapSizeY;
|
|
|
|
// Setup GLYPHBITS stuff
|
|
|
|
pDistGlyphBits->ptlOrigin.x = -(LONG)(ulSrcBitmapSizeX);
|
|
pDistGlyphBits->ptlOrigin.y = -(LONG)(ulSrcBitmapSizeY + pSrcGlyphBits->ptlOrigin.y);
|
|
|
|
pDistGlyphBits->sizlBitmap.cx = pSrcGlyphBits->sizlBitmap.cx;
|
|
pDistGlyphBits->sizlBitmap.cy = pSrcGlyphBits->sizlBitmap.cy;
|
|
|
|
|
|
// Rotate bitmap inage
|
|
|
|
cjScanSrc = CJ_DIB8_SCAN( ulSrcBitmapSizeX );
|
|
cjScanDist = CJ_DIB8_SCAN( ulDistBitmapSizeX );
|
|
|
|
for ( y = 0; y < ulDistBitmapSizeY ; y++ )
|
|
{
|
|
for ( x = 0 , pb = pbDistBitmap + cjScanDist * y ;
|
|
x < ulDistBitmapSizeX ;
|
|
x++ )
|
|
{
|
|
k = x & 7;
|
|
|
|
if ( BIT( pbSrcBitmap, cjScanSrc,
|
|
ulDistBitmapSizeX - x - 1,
|
|
ulDistBitmapSizeY - y - 1
|
|
)
|
|
)
|
|
*pb |= (BitON[ k ] );
|
|
else
|
|
*pb &= (BitOFF[ k ] );
|
|
if ( k == 7 )
|
|
pb++;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case 2700L :
|
|
|
|
if( pDistGlyphData != NULL )
|
|
{
|
|
|
|
// Setup GLYPHDATA structure
|
|
|
|
// x = -y; !!!! HighPart include plus or minus flag
|
|
// y = x;
|
|
|
|
pDistGlyphData->ptqD.x.HighPart = -(SrcGlyphData.ptqD.y.HighPart);
|
|
pDistGlyphData->ptqD.x.LowPart = SrcGlyphData.ptqD.y.LowPart;
|
|
pDistGlyphData->ptqD.y = SrcGlyphData.ptqD.x;
|
|
|
|
// top = left ; bottom = right ; right = -bottom ; left = -top
|
|
|
|
pDistGlyphData->rclInk.top = SrcGlyphData.rclInk.left;
|
|
pDistGlyphData->rclInk.bottom = SrcGlyphData.rclInk.right;
|
|
pDistGlyphData->rclInk.right = -(SrcGlyphData.rclInk.bottom);
|
|
pDistGlyphData->rclInk.left = -(SrcGlyphData.rclInk.top);
|
|
|
|
}
|
|
|
|
if( pSrcGlyphBits != NULL && pDistGlyphBits != NULL )
|
|
{
|
|
|
|
// Get Bitmap size
|
|
|
|
ulSrcBitmapSizeX = pSrcGlyphBits->sizlBitmap.cx;
|
|
ulSrcBitmapSizeY = pSrcGlyphBits->sizlBitmap.cy;
|
|
|
|
// Get the pointer to Bitmap images
|
|
|
|
pbSrcBitmap = (PBYTE)pSrcGlyphBits->aj;
|
|
pbDistBitmap = (PBYTE)pDistGlyphBits->aj;
|
|
|
|
// Set Distination Bitmap Size
|
|
|
|
ulDistBitmapSizeX = ulSrcBitmapSizeY;
|
|
ulDistBitmapSizeY = ulSrcBitmapSizeX;
|
|
|
|
// Setup GLYPHBITS stuff
|
|
|
|
pDistGlyphBits->ptlOrigin.x = -(LONG)(ulSrcBitmapSizeY + pSrcGlyphBits->ptlOrigin.y);
|
|
pDistGlyphBits->ptlOrigin.y = pSrcGlyphBits->ptlOrigin.x;
|
|
|
|
pDistGlyphBits->sizlBitmap.cx = pSrcGlyphBits->sizlBitmap.cy;
|
|
pDistGlyphBits->sizlBitmap.cy = pSrcGlyphBits->sizlBitmap.cx;
|
|
|
|
// Rotate bitmap inage
|
|
|
|
cjScanSrc = CJ_DIB8_SCAN( ulSrcBitmapSizeX );
|
|
cjScanDist = CJ_DIB8_SCAN( ulDistBitmapSizeX );
|
|
|
|
for ( y = 0; y < ulDistBitmapSizeY ; y++ )
|
|
{
|
|
for ( x = 0 , pb = pbDistBitmap + cjScanDist * y ;
|
|
x < ulDistBitmapSizeX ;
|
|
x++ )
|
|
{
|
|
k = x & 7;
|
|
|
|
if ( BIT( pbSrcBitmap, cjScanSrc,
|
|
y ,
|
|
ulDistBitmapSizeX - x - 1
|
|
)
|
|
)
|
|
*pb |= (BitON[ k ] );
|
|
else
|
|
*pb &= (BitOFF[ k ] );
|
|
if ( k == 7 )
|
|
pb++;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
WARNING("BMFD:vFill_RotateGLYPHDATA():ulRotate is invalid\n");
|
|
break;
|
|
|
|
} // end switch
|
|
}
|
|
|
|
#endif // FE_SB
|