mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
348 lines
9.3 KiB
C
348 lines
9.3 KiB
C
/*
|
|
* PROJECT: ReactOS win32 subsystem
|
|
* LICENSE: GPL - See COPYING in the top level directory
|
|
* PURPOSE: GDI font driver for bitmap fonts
|
|
* PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org)
|
|
*/
|
|
|
|
#include "bmfd.h"
|
|
|
|
FORCEINLINE
|
|
ULONG
|
|
_ReadPixel(
|
|
CHAR* pjBits,
|
|
ULONG x,
|
|
ULONG y,
|
|
ULONG ulHeight)
|
|
{
|
|
CHAR j;
|
|
j = pjBits[(x/8) * ulHeight + y];
|
|
return (j >> (~x & 0x7)) & 1;
|
|
}
|
|
|
|
|
|
FORCEINLINE
|
|
VOID
|
|
_WritePixel(
|
|
CHAR* pjBits,
|
|
ULONG x,
|
|
ULONG y,
|
|
ULONG cjRow,
|
|
ULONG color)
|
|
{
|
|
pjBits += y * cjRow;
|
|
pjBits += x / 8;
|
|
*pjBits |= color << (~x & 0x7);
|
|
}
|
|
|
|
|
|
PBMFD_FONT
|
|
BmfdGetFontInstance(
|
|
FONTOBJ *pfo,
|
|
PBMFD_FACE pface)
|
|
{
|
|
PBMFD_FONT pfont = pfo->pvProducer;
|
|
XFORMOBJ *pxo;
|
|
FLOATOBJ_XFORM xfo;
|
|
|
|
if (!pfont)
|
|
{
|
|
/* Allocate realization info */
|
|
pfont = EngAllocMem(0, sizeof(BMFD_FONT), 0);
|
|
if (!pfont)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
pxo = FONTOBJ_pxoGetXform(pfo);
|
|
XFORMOBJ_iGetFloatObjXform(pxo, &xfo);
|
|
|
|
pfont->pfo = pfo;
|
|
pfont->pface = pface;
|
|
pfont->xScale = FLOATOBJ_GetLong(&xfo.eM11);
|
|
pfont->yScale = FLOATOBJ_GetLong(&xfo.eM22);
|
|
pfont->ulAngle = 0;
|
|
|
|
/* Set the pvProducer member of the fontobj */
|
|
pfo->pvProducer = pfont;
|
|
}
|
|
|
|
return pfont;
|
|
}
|
|
|
|
|
|
ULONG
|
|
BmfdQueryGlyphAndBitmap(
|
|
PBMFD_FONT pfont,
|
|
HGLYPH hg,
|
|
GLYPHDATA *pgd,
|
|
GLYPHBITS *pgb,
|
|
ULONG cjSize)
|
|
{
|
|
PBMFD_FACE pface = pfont->pface;
|
|
PGLYPHENTRY pge;
|
|
ULONG xSrc, ySrc, cxSrc, cySrc;
|
|
ULONG xDst, yDst, cxDst, cyDst;
|
|
LONG xScale, yScale;
|
|
ULONG ulGlyphOffset, cjDstRow, color;
|
|
PVOID pvSrc0, pvDst0;
|
|
|
|
/* The glyph handle is the byte offset to the glyph in the table */
|
|
pge = (PGLYPHENTRY)(pface->pCharTable + hg);
|
|
|
|
/* Get the bitmap offset depending on file version */
|
|
if (pface->ulVersion >= 0x300)
|
|
{
|
|
cxSrc = GETVAL(pge->ge20.geWidth);
|
|
ulGlyphOffset = GETVAL(pge->ge30.geOffset);
|
|
}
|
|
else
|
|
{
|
|
cxSrc = GETVAL(pge->ge30.geWidth);
|
|
ulGlyphOffset = GETVAL(pge->ge20.geOffset);
|
|
}
|
|
cySrc = pface->wPixHeight;
|
|
|
|
/* Pointer to the bitmap bits */
|
|
pvSrc0 = (PBYTE)pface->pFontInfo + ulGlyphOffset;
|
|
pvDst0 = pgb->aj;
|
|
|
|
xScale = pfont->xScale;
|
|
yScale = pfont->yScale;
|
|
|
|
/* Calculate extents of destination bitmap */
|
|
if (pfont->ulAngle == 90 || pfont->ulAngle == 270)
|
|
{
|
|
cxDst = cySrc * xScale;
|
|
cyDst = cxSrc * yScale;
|
|
}
|
|
else
|
|
{
|
|
cxDst = cxSrc * xScale;
|
|
cyDst = cySrc * yScale;
|
|
}
|
|
cjDstRow = (cxDst + 7) / 8;
|
|
|
|
if (pgd)
|
|
{
|
|
/* Fill GLYPHDATA structure */
|
|
pgd->gdf.pgb = pgb;
|
|
pgd->hg = hg;
|
|
pgd->fxD = xScale * (pface->wA + cxDst + pface->wC) << 4;
|
|
pgd->fxA = xScale * pface->wA << 4;
|
|
pgd->fxAB = xScale * (pface->wA + cxDst) << 4;
|
|
pgd->fxInkTop = yScale * pface->wAscent << 4;
|
|
pgd->fxInkBottom = - yScale * (pface->wDescent << 4);
|
|
pgd->rclInk.top = - yScale * pface->wAscent;
|
|
pgd->rclInk.bottom = yScale * pface->wDescent;
|
|
pgd->rclInk.left = xScale * pface->wA;
|
|
pgd->rclInk.right = pgd->rclInk.left + cxDst;
|
|
pgd->ptqD.x.LowPart = 0;
|
|
pgd->ptqD.x.HighPart = pgd->fxD;
|
|
pgd->ptqD.y.LowPart = 0;
|
|
pgd->ptqD.y.HighPart = 0;
|
|
}
|
|
|
|
if (pgb)
|
|
{
|
|
/* Verify that the buffer is big enough */
|
|
if (cjSize < FIELD_OFFSET(GLYPHBITS, aj) + cyDst * cjDstRow)
|
|
{
|
|
DbgPrint("Buffer too small (%ld), %ld,%ld\n",
|
|
cjSize, cxSrc, cySrc);
|
|
return FD_ERROR;
|
|
}
|
|
|
|
/* Fill GLYPHBITS structure */
|
|
pgb->ptlOrigin.x = xScale * pface->wA;
|
|
pgb->ptlOrigin.y = - yScale * pface->wAscent;
|
|
pgb->sizlBitmap.cx = cxDst;
|
|
pgb->sizlBitmap.cy = cyDst;
|
|
|
|
/* Erase destination surface */
|
|
memset(pvDst0, 0, cyDst * cjDstRow);
|
|
|
|
switch (pfont->ulAngle)
|
|
{
|
|
case 90:
|
|
/* Copy pixels */
|
|
for (yDst = 0; yDst < cyDst ; yDst++)
|
|
{
|
|
xSrc = yDst / yScale;
|
|
for (xDst = 0; xDst < cxDst; xDst++)
|
|
{
|
|
ySrc = (cxDst - xDst) / xScale;
|
|
color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc);
|
|
_WritePixel(pvDst0, xDst, yDst, cjDstRow, color);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 180:
|
|
for (yDst = 0; yDst < cyDst ; yDst++)
|
|
{
|
|
ySrc = (cyDst - yDst) / yScale;
|
|
for (xDst = 0; xDst < cxDst; xDst++)
|
|
{
|
|
xSrc = (cxDst - xDst) / xScale;
|
|
color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc);
|
|
_WritePixel(pvDst0, xDst, yDst, cjDstRow, color);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 270:
|
|
for (yDst = 0; yDst < cyDst ; yDst++)
|
|
{
|
|
xSrc = (cyDst - yDst) / yScale;
|
|
for (xDst = 0; xDst < cxDst; xDst++)
|
|
{
|
|
ySrc = xDst / xScale;
|
|
color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc);
|
|
_WritePixel(pvDst0, xDst, yDst, cjDstRow, color);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 0:
|
|
default:
|
|
for (yDst = 0; yDst < cyDst ; yDst++)
|
|
{
|
|
ySrc = yDst / yScale;
|
|
for (xDst = 0; xDst < cxDst; xDst++)
|
|
{
|
|
xSrc = xDst / xScale;
|
|
color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc);
|
|
_WritePixel(pvDst0, xDst, yDst, cjDstRow, color);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Return the size of the GLYPHBITS structure */
|
|
return FIELD_OFFSET(GLYPHBITS, aj) + cyDst * cjDstRow;
|
|
}
|
|
|
|
ULONG
|
|
BmfdQueryMaxExtents(
|
|
PBMFD_FONT pfont,
|
|
PFD_DEVICEMETRICS pfddm,
|
|
ULONG cjSize)
|
|
{
|
|
ULONG cjMaxWidth, cjMaxBitmapSize;
|
|
PFONTINFO16 pFontInfo;
|
|
ULONG xScale, yScale;
|
|
|
|
if (pfddm)
|
|
{
|
|
if (cjSize < sizeof(FD_DEVICEMETRICS))
|
|
{
|
|
/* Not enough space, fail */
|
|
return FD_ERROR;
|
|
}
|
|
|
|
pFontInfo = pfont->pface->pFontInfo;
|
|
|
|
xScale = pfont->xScale;
|
|
yScale = pfont->yScale;
|
|
|
|
/* Fill FD_DEVICEMETRICS */
|
|
pfddm->flRealizedType = FDM_MASK;
|
|
pfddm->pteBase.x = FLOATL_1;
|
|
pfddm->pteBase.y = 0;
|
|
pfddm->pteSide.x = 0;
|
|
pfddm->pteSide.y = FLOATL_1;
|
|
pfddm->ptlUnderline1.x = 0;
|
|
pfddm->ptlUnderline1.y = 1;
|
|
pfddm->ptlStrikeout.x = 0;
|
|
pfddm->ptlStrikeout.y = -4;
|
|
pfddm->ptlULThickness.x = 0;
|
|
pfddm->ptlULThickness.y = 1;
|
|
pfddm->ptlSOThickness.x = 0;
|
|
pfddm->ptlSOThickness.y = 1;
|
|
pfddm->lMinA = 0;
|
|
pfddm->lMinC = 0;
|
|
pfddm->lMinD = 0;
|
|
|
|
if (pfont->ulAngle == 90 || pfont->ulAngle == 270)
|
|
{
|
|
pfddm->cxMax = xScale * GETVAL(pFontInfo->dfPixHeight);
|
|
pfddm->cyMax = yScale * GETVAL(pFontInfo->dfMaxWidth);
|
|
pfddm->fxMaxAscender = yScale * GETVAL(pFontInfo->dfAscent) << 4;
|
|
pfddm->fxMaxDescender = (pfddm->cyMax << 4) - pfddm->fxMaxAscender;
|
|
}
|
|
else
|
|
{
|
|
pfddm->cxMax = xScale * GETVAL(pFontInfo->dfMaxWidth);
|
|
pfddm->cyMax = yScale * GETVAL(pFontInfo->dfPixHeight);
|
|
pfddm->fxMaxAscender = yScale * GETVAL(pFontInfo->dfAscent) << 4;
|
|
pfddm->fxMaxDescender = (pfddm->cyMax << 4) - pfddm->fxMaxAscender;
|
|
}
|
|
|
|
pfddm->lD = pfddm->cxMax;
|
|
|
|
/* Calculate Width in bytes */
|
|
cjMaxWidth = ((pfddm->cxMax + 7) >> 3);
|
|
|
|
/* Calculate size of the bitmap, rounded to DWORDs */
|
|
cjMaxBitmapSize = ((cjMaxWidth * pfddm->cyMax) + 3) & ~3;
|
|
|
|
/* cjGlyphMax is the full size of the GLYPHBITS structure */
|
|
pfddm->cjGlyphMax = FIELD_OFFSET(GLYPHBITS, aj) + cjMaxBitmapSize;
|
|
|
|
/* NOTE: fdxQuantized and NonLinear... stay unchanged */
|
|
}
|
|
|
|
/* Return the size of the structure */
|
|
return sizeof(FD_DEVICEMETRICS);
|
|
}
|
|
|
|
|
|
/** Public Interface **********************************************************/
|
|
|
|
PFD_GLYPHATTR
|
|
APIENTRY
|
|
BmfdQueryGlyphAttrs(
|
|
FONTOBJ *pfo,
|
|
ULONG iMode)
|
|
{
|
|
DbgPrint("BmfdQueryGlyphAttrs()\n");
|
|
/* We don't support FO_ATTR_MODE_ROTATE */
|
|
return NULL;
|
|
}
|
|
|
|
LONG
|
|
APIENTRY
|
|
BmfdQueryFontData(
|
|
DHPDEV dhpdev,
|
|
FONTOBJ *pfo,
|
|
ULONG iMode,
|
|
HGLYPH hg,
|
|
OUT GLYPHDATA *pgd,
|
|
PVOID pv,
|
|
ULONG cjSize)
|
|
{
|
|
PBMFD_FILE pfile = (PBMFD_FILE)pfo->iFile;
|
|
PBMFD_FACE pface = &pfile->aface[pfo->iFace - 1];
|
|
PBMFD_FONT pfont= BmfdGetFontInstance(pfo, pface);
|
|
|
|
DbgPrint("BmfdQueryFontData(pfo=%p, iMode=%ld, hg=%p, pgd=%p, pv=%p, cjSize=%ld)\n",
|
|
pfo, iMode, hg, pgd, pv, cjSize);
|
|
// __debugbreak();
|
|
|
|
switch (iMode)
|
|
{
|
|
case QFD_GLYPHANDBITMAP: /* 1 */
|
|
return BmfdQueryGlyphAndBitmap(pfont, hg, pgd, pv, cjSize);
|
|
|
|
case QFD_MAXEXTENTS: /* 3 */
|
|
return BmfdQueryMaxExtents(pfont, pv, cjSize);
|
|
|
|
/* we support nothing else */
|
|
default:
|
|
return FD_ERROR;
|
|
|
|
}
|
|
|
|
return FD_ERROR;
|
|
}
|