1 /* 2 * PROJECT: ReactOS win32 subsystem 3 * LICENSE: GPL - See COPYING in the top level directory 4 * PURPOSE: GDI font driver for bitmap fonts 5 * PROGRAMMER: Timo Kreuzer (timo.kreuzer@reactos.org) 6 */ 7 8 #include "bmfd.h" 9 10 FORCEINLINE 11 ULONG 12 _ReadPixel( 13 CHAR* pjBits, 14 ULONG x, 15 ULONG y, 16 ULONG ulHeight) 17 { 18 CHAR j; 19 j = pjBits[(x/8) * ulHeight + y]; 20 return (j >> (~x & 0x7)) & 1; 21 } 22 23 24 FORCEINLINE 25 VOID 26 _WritePixel( 27 CHAR* pjBits, 28 ULONG x, 29 ULONG y, 30 ULONG cjRow, 31 ULONG color) 32 { 33 pjBits += y * cjRow; 34 pjBits += x / 8; 35 *pjBits |= color << (~x & 0x7); 36 } 37 38 39 PBMFD_FONT 40 BmfdGetFontInstance( 41 FONTOBJ *pfo, 42 PBMFD_FACE pface) 43 { 44 PBMFD_FONT pfont = pfo->pvProducer; 45 XFORMOBJ *pxo; 46 FLOATOBJ_XFORM xfo; 47 48 if (!pfont) 49 { 50 /* Allocate realization info */ 51 pfont = EngAllocMem(0, sizeof(BMFD_FONT), 0); 52 if (!pfont) 53 { 54 return NULL; 55 } 56 57 pxo = FONTOBJ_pxoGetXform(pfo); 58 XFORMOBJ_iGetFloatObjXform(pxo, &xfo); 59 60 pfont->pfo = pfo; 61 pfont->pface = pface; 62 pfont->xScale = FLOATOBJ_GetLong(&xfo.eM11); 63 pfont->yScale = FLOATOBJ_GetLong(&xfo.eM22); 64 pfont->ulAngle = 0; 65 66 /* Set the pvProducer member of the fontobj */ 67 pfo->pvProducer = pfont; 68 } 69 70 return pfont; 71 } 72 73 74 ULONG 75 BmfdQueryGlyphAndBitmap( 76 PBMFD_FONT pfont, 77 HGLYPH hg, 78 GLYPHDATA *pgd, 79 GLYPHBITS *pgb, 80 ULONG cjSize) 81 { 82 PBMFD_FACE pface = pfont->pface; 83 PGLYPHENTRY pge; 84 ULONG xSrc, ySrc, cxSrc, cySrc; 85 ULONG xDst, yDst, cxDst, cyDst; 86 LONG xScale, yScale; 87 ULONG ulGlyphOffset, cjDstRow, color; 88 PVOID pvSrc0, pvDst0; 89 90 /* The glyph handle is the byte offset to the glyph in the table */ 91 pge = (PGLYPHENTRY)(pface->pCharTable + hg); 92 93 /* Get the bitmap offset depending on file version */ 94 if (pface->ulVersion >= 0x300) 95 { 96 cxSrc = GETVAL(pge->ge20.geWidth); 97 ulGlyphOffset = GETVAL(pge->ge30.geOffset); 98 } 99 else 100 { 101 cxSrc = GETVAL(pge->ge30.geWidth); 102 ulGlyphOffset = GETVAL(pge->ge20.geOffset); 103 } 104 cySrc = pface->wPixHeight; 105 106 /* Pointer to the bitmap bits */ 107 pvSrc0 = (PBYTE)pface->pFontInfo + ulGlyphOffset; 108 pvDst0 = pgb->aj; 109 110 xScale = pfont->xScale; 111 yScale = pfont->yScale; 112 113 /* Calculate extents of destination bitmap */ 114 if (pfont->ulAngle == 90 || pfont->ulAngle == 270) 115 { 116 cxDst = cySrc * xScale; 117 cyDst = cxSrc * yScale; 118 } 119 else 120 { 121 cxDst = cxSrc * xScale; 122 cyDst = cySrc * yScale; 123 } 124 cjDstRow = (cxDst + 7) / 8; 125 126 if (pgd) 127 { 128 /* Fill GLYPHDATA structure */ 129 pgd->gdf.pgb = pgb; 130 pgd->hg = hg; 131 pgd->fxD = xScale * (pface->wA + cxDst + pface->wC) << 4; 132 pgd->fxA = xScale * pface->wA << 4; 133 pgd->fxAB = xScale * (pface->wA + cxDst) << 4; 134 pgd->fxInkTop = yScale * pface->wAscent << 4; 135 pgd->fxInkBottom = - yScale * (pface->wDescent << 4); 136 pgd->rclInk.top = - yScale * pface->wAscent; 137 pgd->rclInk.bottom = yScale * pface->wDescent; 138 pgd->rclInk.left = xScale * pface->wA; 139 pgd->rclInk.right = pgd->rclInk.left + cxDst; 140 pgd->ptqD.x.LowPart = 0; 141 pgd->ptqD.x.HighPart = pgd->fxD; 142 pgd->ptqD.y.LowPart = 0; 143 pgd->ptqD.y.HighPart = 0; 144 } 145 146 if (pgb) 147 { 148 /* Verify that the buffer is big enough */ 149 if (cjSize < FIELD_OFFSET(GLYPHBITS, aj) + cyDst * cjDstRow) 150 { 151 DbgPrint("Buffer too small (%ld), %ld,%ld\n", 152 cjSize, cxSrc, cySrc); 153 return FD_ERROR; 154 } 155 156 /* Fill GLYPHBITS structure */ 157 pgb->ptlOrigin.x = xScale * pface->wA; 158 pgb->ptlOrigin.y = - yScale * pface->wAscent; 159 pgb->sizlBitmap.cx = cxDst; 160 pgb->sizlBitmap.cy = cyDst; 161 162 /* Erase destination surface */ 163 memset(pvDst0, 0, cyDst * cjDstRow); 164 165 switch (pfont->ulAngle) 166 { 167 case 90: 168 /* Copy pixels */ 169 for (yDst = 0; yDst < cyDst ; yDst++) 170 { 171 xSrc = yDst / yScale; 172 for (xDst = 0; xDst < cxDst; xDst++) 173 { 174 ySrc = (cxDst - xDst) / xScale; 175 color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc); 176 _WritePixel(pvDst0, xDst, yDst, cjDstRow, color); 177 } 178 } 179 break; 180 181 case 180: 182 for (yDst = 0; yDst < cyDst ; yDst++) 183 { 184 ySrc = (cyDst - yDst) / yScale; 185 for (xDst = 0; xDst < cxDst; xDst++) 186 { 187 xSrc = (cxDst - xDst) / xScale; 188 color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc); 189 _WritePixel(pvDst0, xDst, yDst, cjDstRow, color); 190 } 191 } 192 break; 193 194 case 270: 195 for (yDst = 0; yDst < cyDst ; yDst++) 196 { 197 xSrc = (cyDst - yDst) / yScale; 198 for (xDst = 0; xDst < cxDst; xDst++) 199 { 200 ySrc = xDst / xScale; 201 color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc); 202 _WritePixel(pvDst0, xDst, yDst, cjDstRow, color); 203 } 204 } 205 break; 206 207 case 0: 208 default: 209 for (yDst = 0; yDst < cyDst ; yDst++) 210 { 211 ySrc = yDst / yScale; 212 for (xDst = 0; xDst < cxDst; xDst++) 213 { 214 xSrc = xDst / xScale; 215 color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc); 216 _WritePixel(pvDst0, xDst, yDst, cjDstRow, color); 217 } 218 } 219 } 220 } 221 222 /* Return the size of the GLYPHBITS structure */ 223 return FIELD_OFFSET(GLYPHBITS, aj) + cyDst * cjDstRow; 224 } 225 226 ULONG 227 BmfdQueryMaxExtents( 228 PBMFD_FONT pfont, 229 PFD_DEVICEMETRICS pfddm, 230 ULONG cjSize) 231 { 232 ULONG cjMaxWidth, cjMaxBitmapSize; 233 PFONTINFO16 pFontInfo; 234 ULONG xScale, yScale; 235 236 if (pfddm) 237 { 238 if (cjSize < sizeof(FD_DEVICEMETRICS)) 239 { 240 /* Not enough space, fail */ 241 return FD_ERROR; 242 } 243 244 pFontInfo = pfont->pface->pFontInfo; 245 246 xScale = pfont->xScale; 247 yScale = pfont->yScale; 248 249 /* Fill FD_DEVICEMETRICS */ 250 pfddm->flRealizedType = FDM_MASK; 251 pfddm->pteBase.x = FLOATL_1; 252 pfddm->pteBase.y = 0; 253 pfddm->pteSide.x = 0; 254 pfddm->pteSide.y = FLOATL_1; 255 pfddm->ptlUnderline1.x = 0; 256 pfddm->ptlUnderline1.y = 1; 257 pfddm->ptlStrikeout.x = 0; 258 pfddm->ptlStrikeout.y = -4; 259 pfddm->ptlULThickness.x = 0; 260 pfddm->ptlULThickness.y = 1; 261 pfddm->ptlSOThickness.x = 0; 262 pfddm->ptlSOThickness.y = 1; 263 pfddm->lMinA = 0; 264 pfddm->lMinC = 0; 265 pfddm->lMinD = 0; 266 267 if (pfont->ulAngle == 90 || pfont->ulAngle == 270) 268 { 269 pfddm->cxMax = xScale * GETVAL(pFontInfo->dfPixHeight); 270 pfddm->cyMax = yScale * GETVAL(pFontInfo->dfMaxWidth); 271 pfddm->fxMaxAscender = yScale * GETVAL(pFontInfo->dfAscent) << 4; 272 pfddm->fxMaxDescender = (pfddm->cyMax << 4) - pfddm->fxMaxAscender; 273 } 274 else 275 { 276 pfddm->cxMax = xScale * GETVAL(pFontInfo->dfMaxWidth); 277 pfddm->cyMax = yScale * GETVAL(pFontInfo->dfPixHeight); 278 pfddm->fxMaxAscender = yScale * GETVAL(pFontInfo->dfAscent) << 4; 279 pfddm->fxMaxDescender = (pfddm->cyMax << 4) - pfddm->fxMaxAscender; 280 } 281 282 pfddm->lD = pfddm->cxMax; 283 284 /* Calculate Width in bytes */ 285 cjMaxWidth = ((pfddm->cxMax + 7) >> 3); 286 287 /* Calculate size of the bitmap, rounded to DWORDs */ 288 cjMaxBitmapSize = ((cjMaxWidth * pfddm->cyMax) + 3) & ~3; 289 290 /* cjGlyphMax is the full size of the GLYPHBITS structure */ 291 pfddm->cjGlyphMax = FIELD_OFFSET(GLYPHBITS, aj) + cjMaxBitmapSize; 292 293 /* NOTE: fdxQuantized and NonLinear... stay unchanged */ 294 } 295 296 /* Return the size of the structure */ 297 return sizeof(FD_DEVICEMETRICS); 298 } 299 300 301 /** Public Interface **********************************************************/ 302 303 PFD_GLYPHATTR 304 APIENTRY 305 BmfdQueryGlyphAttrs( 306 FONTOBJ *pfo, 307 ULONG iMode) 308 { 309 DbgPrint("BmfdQueryGlyphAttrs()\n"); 310 /* We don't support FO_ATTR_MODE_ROTATE */ 311 return NULL; 312 } 313 314 LONG 315 APIENTRY 316 BmfdQueryFontData( 317 DHPDEV dhpdev, 318 FONTOBJ *pfo, 319 ULONG iMode, 320 HGLYPH hg, 321 OUT GLYPHDATA *pgd, 322 PVOID pv, 323 ULONG cjSize) 324 { 325 PBMFD_FILE pfile = (PBMFD_FILE)pfo->iFile; 326 PBMFD_FACE pface = &pfile->aface[pfo->iFace - 1]; 327 PBMFD_FONT pfont= BmfdGetFontInstance(pfo, pface); 328 329 DbgPrint("BmfdQueryFontData(pfo=%p, iMode=%ld, hg=%p, pgd=%p, pv=%p, cjSize=%ld)\n", 330 pfo, iMode, hg, pgd, pv, cjSize); 331 // __debugbreak(); 332 333 switch (iMode) 334 { 335 case QFD_GLYPHANDBITMAP: /* 1 */ 336 return BmfdQueryGlyphAndBitmap(pfont, hg, pgd, pv, cjSize); 337 338 case QFD_MAXEXTENTS: /* 3 */ 339 return BmfdQueryMaxExtents(pfont, pv, cjSize); 340 341 /* we support nothing else */ 342 default: 343 return FD_ERROR; 344 345 } 346 347 return FD_ERROR; 348 } 349