Sync with trunk head (part 1 or 2)
[reactos.git] / drivers / video / 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 = (PGLYPHENTRY)(pface->pCharTable + hg);
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 if (!pge)
91 {
92 DbgPrint("no glyph handle given!\n");
93 return FD_ERROR;
94 }
95
96 /* Get the bitmap offset depending on file version */
97 if (pface->ulVersion >= 0x300)
98 {
99 cxSrc = GETVAL(pge->ge20.geWidth);
100 ulGlyphOffset = GETVAL(pge->ge30.geOffset);
101 }
102 else
103 {
104 cxSrc = GETVAL(pge->ge30.geWidth);
105 ulGlyphOffset = GETVAL(pge->ge20.geOffset);
106 }
107 cySrc = pface->wPixHeight;
108
109 /* Pointer to the bitmap bits */
110 pvSrc0 = (PBYTE)pface->pFontInfo + ulGlyphOffset;
111 pvDst0 = pgb->aj;
112
113 xScale = pfont->xScale;
114 yScale = pfont->yScale;
115
116 /* Calculate extents of destination bitmap */
117 if (pfont->ulAngle == 90 || pfont->ulAngle == 270)
118 {
119 cxDst = cySrc * xScale;
120 cyDst = cxSrc * yScale;
121 }
122 else
123 {
124 cxDst = cxSrc * yScale;
125 cyDst = cySrc * xScale;
126 }
127 cjDstRow = (cxDst + 7) / 8;
128
129 if (pgd)
130 {
131 /* Fill GLYPHDATA structure */
132 pgd->gdf.pgb = pgb;
133 pgd->hg = hg;
134 pgd->fxD = xScale * (pface->wA + cxDst + pface->wC) << 4;
135 pgd->fxA = xScale * pface->wA << 4;
136 pgd->fxAB = xScale * (pface->wA + cxDst) << 4;
137 pgd->fxInkTop = yScale * pface->wAscent << 4;
138 pgd->fxInkBottom = - yScale * (pface->wDescent << 4);
139 pgd->rclInk.top = - yScale * pface->wAscent;
140 pgd->rclInk.bottom = yScale * pface->wDescent;
141 pgd->rclInk.left = xScale * pface->wA;
142 pgd->rclInk.right = pgd->rclInk.left + cxDst;
143 pgd->ptqD.x.LowPart = 0;
144 pgd->ptqD.x.HighPart = pgd->fxD;
145 pgd->ptqD.y.LowPart = 0;
146 pgd->ptqD.y.HighPart = 0;
147 }
148
149 if (pgb)
150 {
151 /* Verify that the buffer is big enough */
152 if (cjSize < FIELD_OFFSET(GLYPHBITS, aj) + cyDst * cjDstRow)
153 {
154 DbgPrint("Buffer too small (%ld), %ld,%ld\n",
155 cjSize, cxSrc, cySrc);
156 return FD_ERROR;
157 }
158
159 /* Fill GLYPHBITS structure */
160 pgb->ptlOrigin.x = yScale * pface->wA;
161 pgb->ptlOrigin.y = - yScale * pface->wAscent;
162 pgb->sizlBitmap.cx = cxDst;
163 pgb->sizlBitmap.cy = cyDst;
164
165 /* Erase destination surface */
166 memset(pvDst0, 0, cyDst * cjDstRow);
167
168 switch (pfont->ulAngle)
169 {
170 case 90:
171 /* Copy pixels */
172 for (yDst = 0; yDst < cyDst ; yDst++)
173 {
174 xSrc = yDst / yScale;
175 for (xDst = 0; xDst < cxDst; xDst++)
176 {
177 ySrc = (cxDst - xDst) / xScale;
178 color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc);
179 _WritePixel(pvDst0, xDst, yDst, cjDstRow, color);
180 }
181 }
182 break;
183
184 case 180:
185 for (yDst = 0; yDst < cyDst ; yDst++)
186 {
187 ySrc = (cyDst - yDst) / yScale;
188 for (xDst = 0; xDst < cxDst; xDst++)
189 {
190 xSrc = (cxDst - xDst) / xScale;
191 color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc);
192 _WritePixel(pvDst0, xDst, yDst, cjDstRow, color);
193 }
194 }
195 break;
196
197 case 270:
198 for (yDst = 0; yDst < cyDst ; yDst++)
199 {
200 xSrc = (cyDst - yDst) / yScale;
201 for (xDst = 0; xDst < cxDst; xDst++)
202 {
203 ySrc = xDst / xScale;
204 color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc);
205 _WritePixel(pvDst0, xDst, yDst, cjDstRow, color);
206 }
207 }
208 break;
209
210 case 0:
211 default:
212 for (yDst = 0; yDst < cyDst ; yDst++)
213 {
214 ySrc = yDst / yScale;
215 for (xDst = 0; xDst < cxDst; xDst++)
216 {
217 xSrc = xDst / xScale;
218 color = _ReadPixel(pvSrc0, xSrc, ySrc, cySrc);
219 _WritePixel(pvDst0, xDst, yDst, cjDstRow, color);
220 }
221 }
222 }
223 }
224
225 /* Return the size of the GLYPHBITS structure */
226 return FIELD_OFFSET(GLYPHBITS, aj) + cyDst * cjDstRow;
227 }
228
229 ULONG
230 BmfdQueryMaxExtents(
231 PBMFD_FONT pfont,
232 PFD_DEVICEMETRICS pfddm,
233 ULONG cjSize)
234 {
235 ULONG cjMaxWidth, cjMaxBitmapSize;
236 PFONTINFO16 pFontInfo;
237 ULONG xScale, yScale;
238
239 if (pfddm)
240 {
241 if (cjSize < sizeof(FD_DEVICEMETRICS))
242 {
243 /* Not enough space, fail */
244 return FD_ERROR;
245 }
246
247 pFontInfo = pfont->pface->pFontInfo;
248
249 xScale = pfont->xScale;
250 yScale = pfont->yScale;
251
252 /* Fill FD_DEVICEMETRICS */
253 pfddm->flRealizedType = FDM_MASK;
254 pfddm->pteBase.x = FLOATL_1;
255 pfddm->pteBase.y = 0;
256 pfddm->pteSide.x = 0;
257 pfddm->pteSide.y = FLOATL_1;
258 pfddm->ptlUnderline1.x = 0;
259 pfddm->ptlUnderline1.y = 1;
260 pfddm->ptlStrikeout.x = 0;
261 pfddm->ptlStrikeout.y = -4;
262 pfddm->ptlULThickness.x = 0;
263 pfddm->ptlULThickness.y = 1;
264 pfddm->ptlSOThickness.x = 0;
265 pfddm->ptlSOThickness.y = 1;
266 pfddm->lMinA = 0;
267 pfddm->lMinC = 0;
268 pfddm->lMinD = 0;
269
270 if (pfont->ulAngle == 90 || pfont->ulAngle == 270)
271 {
272 pfddm->cxMax = xScale * GETVAL(pFontInfo->dfPixHeight);
273 pfddm->cyMax = yScale * GETVAL(pFontInfo->dfMaxWidth);
274 pfddm->fxMaxAscender = yScale * GETVAL(pFontInfo->dfAscent) << 4;
275 pfddm->fxMaxDescender = (pfddm->cyMax << 4) - pfddm->fxMaxAscender;
276 }
277 else
278 {
279 pfddm->cxMax = xScale * GETVAL(pFontInfo->dfMaxWidth);
280 pfddm->cyMax = yScale * GETVAL(pFontInfo->dfPixHeight);
281 pfddm->fxMaxAscender = yScale * GETVAL(pFontInfo->dfAscent) << 4;
282 pfddm->fxMaxDescender = (pfddm->cyMax << 4) - pfddm->fxMaxAscender;
283 }
284
285 pfddm->lD = pfddm->cxMax;
286
287 /* Calculate Width in bytes */
288 cjMaxWidth = ((pfddm->cxMax + 7) >> 3);
289
290 /* Calculate size of the bitmap, rounded to DWORDs */
291 cjMaxBitmapSize = ((cjMaxWidth * pfddm->cyMax) + 3) & ~3;
292
293 /* cjGlyphMax is the full size of the GLYPHBITS structure */
294 pfddm->cjGlyphMax = FIELD_OFFSET(GLYPHBITS, aj) + cjMaxBitmapSize;
295
296 /* NOTE: fdxQuantized and NonLinear... stay unchanged */
297 }
298
299 /* Return the size of the structure */
300 return sizeof(FD_DEVICEMETRICS);
301 }
302
303
304 /** Public Interface **********************************************************/
305
306 PFD_GLYPHATTR
307 APIENTRY
308 BmfdQueryGlyphAttrs(
309 FONTOBJ *pfo,
310 ULONG iMode)
311 {
312 DbgPrint("BmfdQueryGlyphAttrs()\n");
313 /* We don't support FO_ATTR_MODE_ROTATE */
314 return NULL;
315 }
316
317 LONG
318 APIENTRY
319 BmfdQueryFontData(
320 DHPDEV dhpdev,
321 FONTOBJ *pfo,
322 ULONG iMode,
323 HGLYPH hg,
324 OUT GLYPHDATA *pgd,
325 PVOID pv,
326 ULONG cjSize)
327 {
328 PBMFD_FILE pfile = (PBMFD_FILE)pfo->iFile;
329 PBMFD_FACE pface = &pfile->aface[pfo->iFace - 1];
330 PBMFD_FONT pfont= BmfdGetFontInstance(pfo, pface);
331
332 DbgPrint("BmfdQueryFontData(pfo=%p, iMode=%ld, hg=%p, pgd=%p, pv=%p, cjSize=%ld)\n",
333 pfo, iMode, hg, pgd, pv, cjSize);
334 // __debugbreak();
335
336 switch (iMode)
337 {
338 case QFD_GLYPHANDBITMAP: /* 1 */
339 return BmfdQueryGlyphAndBitmap(pfont, hg, pgd, pv, cjSize);
340
341 case QFD_MAXEXTENTS: /* 3 */
342 return BmfdQueryMaxExtents(pfont, pv, cjSize);
343
344 /* we support nothing else */
345 default:
346 return FD_ERROR;
347
348 }
349
350 return FD_ERROR;
351 }