[BMFD]
[reactos.git] / reactos / win32ss / drivers / font / bmfd / glyph.c
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 ULONG
11 FORCEINLINE
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 VOID
25 FORCEINLINE
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 ULONG 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 * yScale;
122 cyDst = cySrc * xScale;
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 = yScale * 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 }