DIB Engine: introduction of bitmaplist structure
[wine/hacks.git] / dlls / winedib.drv / text.c
blob94c799253cb6a680b0777fe8d4c5c85799135215
1 /*
2 * DIBDRV text functions
4 * Copyright 2009 Massimo Del Fedele
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include "dibdrv.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv);
28 /***********************************************************************
29 * DIBDRV_ExtTextOut
31 BOOL DIBDRV_ExtTextOut( DIBDRVPHYSDEV *physDev, INT x, INT y, UINT flags,
32 const RECT *lprect, LPCWSTR wstr, UINT count,
33 const INT *lpDx )
35 /* FIXME : TODO many, many stuffs... just trivial text support by now */
37 BOOL res;
38 FT_Face face;
39 FT_UInt glyph_index;
40 INT n;
41 INT error;
42 LOGFONTW lf;
43 int w, h;
44 LPCWSTR wstrPnt;
46 FT_Glyph glyph;
47 FT_BitmapGlyph bitmapGlyph;
48 FT_Bitmap *bitmap, bitmap8;
49 double cosEsc, sinEsc;
50 FT_Matrix matrix;
51 FT_Vector start;
52 int dx, dy;
54 RECT *r;
55 int iRec;
56 RECT clipRec;
57 DWORD backPixel;
59 MAYBE(TRACE("physDev:%p, x:%d, y:%d, flags:%x, lprect:%p, wstr:%s, count:%d, lpDx:%p\n",
60 physDev, x, y, flags, lprect, debugstr_w(wstr), count, lpDx));
62 if(physDev->hasDIB)
64 /* DIB section selected in, use DIB Engine */
66 face = physDev->face;
67 if(!face)
69 ERR("FreeType face is null\n");
70 res = FALSE;
71 goto fin;
74 /* outputs the string in case it is given by glyph indexes
75 make locating it in logs much easier */
76 if(TRACE_ON(dibdrv) && flags & ETO_GLYPH_INDEX)
78 WCHAR a = 'A';
79 WCHAR *str = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR)*(count+1));
80 int delta = a - pFT_Get_Char_Index( face, a);
81 int i;
82 memcpy(str, wstr, sizeof(WCHAR)*count);
83 for(i = 0; str[i] && i < count; i++)
84 str[i] += delta;
85 TRACE("String: '%s'\n", debugstr_w(str));
86 HeapFree(GetProcessHeap(), 0, str);
89 /* gets background pixel value for opaque text */
90 backPixel = physDev->backgroundColor;
92 /* gets font data, etc */
93 GetObjectW(GetCurrentObject(physDev->hdc, OBJ_FONT), sizeof(lf), &lf);
95 /* convert sizes to device space */
96 w = abs(lf.lfWidth); h = abs(lf.lfHeight);
97 _DIBDRV_Sizes_ws2ds(physDev, &w, &h);
99 /* loop on all clip region rectangles */
100 r = physDev->regionRects;
101 for(iRec = 0; iRec < physDev->regionRectCount; iRec++, r++)
103 /* if clipped on text rect, intersect with current region */
104 if(flags & ETO_CLIPPED)
106 if(!_DIBDRV_IntersectRect(&clipRec, r, lprect))
107 continue;
109 else
110 memcpy(&clipRec, r, sizeof(RECT));
112 /* if opaque, paint the font background */
113 if(flags & ETO_OPAQUE)
115 int iLine;
116 RECT tr;
118 /* clips text rectangle */
119 if(_DIBDRV_IntersectRect(&tr, r, lprect))
121 /* paints the backgound */
122 for(iLine = tr.top; iLine < tr.bottom; iLine++)
123 physDev->physBitmap->funcs->SolidHLine(physDev->physBitmap,
124 tr.left, tr.right-1, iLine, 0, backPixel);
128 /* sets character pixel size */
129 error = pFT_Set_Pixel_Sizes(face, w, h);
130 if(error)
131 ONCE(ERR("Couldn't set char size to (%d,%d), code %d\n", lf.lfWidth, lf.lfHeight, error));
133 /* transformation matrix and vector */
134 start.x = 0;
135 start.y = 0;
136 if(lf.lfEscapement != 0)
138 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
139 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
141 else
143 cosEsc = 1;
144 sinEsc = 0;
146 matrix.xx = (FT_Fixed)( cosEsc * 0x10000L );
147 matrix.xy = (FT_Fixed)(-sinEsc * 0x10000L );
148 matrix.yx = (FT_Fixed)( sinEsc * 0x10000L );
149 matrix.yy = (FT_Fixed)( cosEsc * 0x10000L );
151 /* outputs characters one by one */
152 wstrPnt = wstr;
153 for ( n = 0; n < count; n++ )
155 /* retrieve glyph index from character code */
156 if(flags & ETO_GLYPH_INDEX)
157 glyph_index = *wstrPnt++;
158 else
159 glyph_index = pFT_Get_Char_Index( face, *wstrPnt++);
161 /* load glyph image into the slot (erase previous one) */
162 error = pFT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
163 if(error)
165 ERR("Couldn't load glyph at index %d\n", glyph_index);
166 /* ignore errors */
167 continue;
169 error = pFT_Get_Glyph(face->glyph, &glyph);
170 if ( error )
172 FIXME("Couldn't get glyph\n");
173 continue;
176 /* apply transformation to glyph */
177 if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )
178 pFT_Glyph_Transform(glyph, &matrix, &start );
180 /* gets advance BEFORE transforming... */
181 dx = glyph->advance.x;
182 dy = glyph->advance.y;
184 /* convert to an anti-aliased bitmap, if needed */
185 if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )
187 error = pFT_Glyph_To_Bitmap(
188 &glyph,
189 #ifdef DIBDRV_ANTIALIASED_FONTS
190 physDev->physBitmap->bitCount > 8 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO,
191 #else
192 FT_RENDER_MODE_MONO,
193 #endif
194 0, /* no additional translation */
195 1 /* destroy copy in "image" */
198 /* ignore errors */
199 if ( error )
201 FIXME("Couldn't render glyph\n");
202 pFT_Done_Glyph(glyph);
203 continue;
206 bitmapGlyph = (FT_BitmapGlyph)glyph;
208 /* convert the bitmap in an 8bpp 1 byte aligned one if needed */
209 bitmap = &bitmapGlyph->bitmap;
210 if(bitmap->pixel_mode != FT_PIXEL_MODE_GRAY)
212 pFT_Bitmap_New(&bitmap8);
213 if(pFT_Bitmap_Convert(glyph->library, bitmap, &bitmap8, 1))
215 FIXME("Couldn't convert bitmap to 8 bit grayscale\n");
216 pFT_Done_Glyph(glyph);
217 continue;
219 bitmap = &bitmap8;
222 /* now, draw to our target surface */
223 physDev->physBitmap->funcs->FreetypeBlit(physDev, x+bitmapGlyph->left, y-bitmapGlyph->top, &clipRec, bitmap);
225 /* frees converted bitmap, if any */
226 if(bitmap != &bitmapGlyph->bitmap)
227 pFT_Bitmap_Done(glyph->library, bitmap);
229 /* increment pen position */
230 x += dx>>16;
231 y -= dy>>16;
233 pFT_Done_Glyph(glyph);
235 res = TRUE;
237 } /* end region rects loop */
239 else
241 /* DDB selected in, use X11 driver */
242 res = _DIBDRV_GetDisplayDriver()->pExtTextOut(physDev->X11PhysDev, x, y, flags, lprect,
243 wstr, count, lpDx);
245 fin:
246 return res;
249 /***********************************************************************
250 * DIBDRV_GetTextExtentExPoint
252 BOOL DIBDRV_GetTextExtentExPoint( DIBDRVPHYSDEV *physDev, LPCWSTR str, INT count,
253 INT maxExt, LPINT lpnFit, LPINT alpDx, LPSIZE size )
255 BOOL res;
257 MAYBE(TRACE("physDev:%p, str:%s, count:%d, maxExt:%d, lpnFit:%p, alpDx:%p, size:%p\n",
258 physDev, debugstr_w(str), count, maxExt, lpnFit, alpDx, size));
260 if(physDev->hasDIB)
262 /* DIB section selected in, use DIB Engine */
263 ONCE(FIXME("STUB\n"));
264 res = TRUE;
266 else
268 /* DDB selected in, use X11 driver */
269 res = _DIBDRV_GetDisplayDriver()->pGetTextExtentExPoint(physDev->X11PhysDev, str, count, maxExt,
270 lpnFit, alpDx, size);
272 return res;