DIB Engine: implement most engine functions
[wine/hacks.git] / dlls / winedib.drv / text.c
blobe2cea0c1c9c36bfe7fab7e500a6bc3b5b11a44dc
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 /* converts font sizes from Word space to Device space */
29 static void FontSizes_ws2ds(DIBDRVPHYSDEV *physDev, int *w, int *h)
31 POINT pts[2];
32 pts[0].x = 0;
33 pts[0].y = 0;
34 pts[1].x = abs(*w);
35 pts[1].y = abs(*h);
36 LPtoDP(physDev->hdc, pts, 2);
37 *w = pts[1].x - pts[0].x;
38 *h = pts[1].y - pts[0].y;
41 /***********************************************************************
42 * DIBDRV_ExtTextOut
44 BOOL DIBDRV_ExtTextOut( DIBDRVPHYSDEV *physDev, INT x, INT y, UINT flags,
45 const RECT *lprect, LPCWSTR wstr, UINT count,
46 const INT *lpDx )
48 /* FIXME : TODO many, many stuffs... just trivial text support by now */
50 BOOL res;
51 FT_Face face;
52 FT_UInt glyph_index;
53 INT n;
54 INT error;
55 LOGFONTW lf;
56 int w, h;
57 LPCWSTR wstrPnt;
59 FT_Glyph glyph;
60 FT_BitmapGlyph bitmap;
61 double cosEsc, sinEsc;
62 FT_Matrix matrix;
63 FT_Vector start;
64 int dx, dy;
67 MAYBE(TRACE("physDev:%p, x:%d, y:%d, flags:%x, lprect:%p, wstr:%s, count:%d, lpDx:%p\n",
68 physDev, x, y, flags, lprect, debugstr_w(wstr), count, lpDx));
70 if(physDev->hasDIB)
72 /* DIB section selected in, use DIB Engine */
74 face = physDev->face;
75 if(!face)
77 ERR("FreeType face is null\n");
78 res = FALSE;
79 goto fin;
82 /* outputs the string in case it is given by glyph indexes
83 make locating it in logs much easier */
84 if(TRACE_ON(dibdrv) && flags & ETO_GLYPH_INDEX)
86 WCHAR a = 'A';
87 WCHAR *str = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WCHAR)*(count+1));
88 int delta = a - pFT_Get_Char_Index( face, a);
89 int i;
90 memcpy(str, wstr, sizeof(WCHAR)*count);
91 for(i = 0; str[i] && i < count; i++)
92 str[i] += delta;
93 TRACE("String: '%s'\n", debugstr_w(str));
94 HeapFree(GetProcessHeap(), 0, str);
97 /* gets font data, etc */
98 GetObjectW(GetCurrentObject(physDev->hdc, OBJ_FONT), sizeof(lf), &lf);
100 /* convert sizes to device space */
101 w = lf.lfWidth; h = lf.lfHeight;
102 FontSizes_ws2ds(physDev, &w, &h);
104 /* if opaque, paint the font background */
106 if(flags | ETO_OPAQUE)
108 int iLine;
109 for(iLine = lprect->top; iLine < lprect->bottom; iLine++)
110 physDev->physBitmap.funcs->SolidHLine(&physDev->physBitmap,
111 lprect->left, lprect->right-1, iLine, 0, physDev->backgroundColor);
114 /* sets character pixel size */
115 error = pFT_Set_Pixel_Sizes(
116 face,
117 MulDiv(w, 96, DIBDRV_GetDeviceCaps(physDev, LOGPIXELSX)),
118 MulDiv(h, 96, DIBDRV_GetDeviceCaps(physDev, LOGPIXELSY))
120 if(error)
121 ERR("Couldn't set char size to (%d,%d)\n", lf.lfWidth, lf.lfHeight);
123 /* transformation matrix and vector */
124 start.x = 0;
125 start.y = 0;
126 if(lf.lfEscapement != 0)
128 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
129 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
131 else
133 cosEsc = 1;
134 sinEsc = 0;
136 matrix.xx = (FT_Fixed)( cosEsc * 0x10000L );
137 matrix.xy = (FT_Fixed)(-sinEsc * 0x10000L );
138 matrix.yx = (FT_Fixed)( sinEsc * 0x10000L );
139 matrix.yy = (FT_Fixed)( cosEsc * 0x10000L );
141 /* outputs characters one by one */
142 wstrPnt = wstr;
143 for ( n = 0; n < count; n++ )
145 /* retrieve glyph index from character code */
146 if(flags & ETO_GLYPH_INDEX)
147 glyph_index = *wstrPnt++;
148 else
149 glyph_index = pFT_Get_Char_Index( face, *wstrPnt++);
151 /* load glyph image into the slot (erase previous one) */
152 error = pFT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
153 if(error)
155 ERR("Couldn't load glyph at index %d\n", glyph_index);
156 /* ignore errors */
157 continue;
159 error = pFT_Get_Glyph(face->glyph, &glyph);
160 if ( error )
162 FIXME("Couldn't get glyph\n");
163 continue;
166 /* apply transformation to glyph */
167 if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )
168 pFT_Glyph_Transform(glyph, &matrix, &start );
170 /* gets advance BEFORE transforming... */
171 dx = glyph->advance.x;
172 dy = glyph->advance.y;
174 /* convert to an anti-aliased bitmap, if needed */
175 if ( glyph->format != FT_GLYPH_FORMAT_BITMAP )
177 error = pFT_Glyph_To_Bitmap(
178 &glyph,
179 FT_RENDER_MODE_NORMAL,
180 0, /* no additional translation */
181 1 /* destroy copy in "image" */
184 /* ignore errors */
185 if ( error )
187 FIXME("Couldn't render glyph\n");
188 pFT_Done_Glyph(glyph);
189 continue;
193 /* now, draw to our target surface */
194 bitmap = (FT_BitmapGlyph)glyph;
195 physDev->physBitmap.funcs->FreetypeBlit(physDev, x+bitmap->left, y-bitmap->top, &bitmap->bitmap);
197 /* increment pen position */
198 x += dx>>16;
199 y -= dy>>16;
201 pFT_Done_Glyph(glyph);
203 res = TRUE;
206 else
208 /* DDB selected in, use X11 driver */
209 res = _DIBDRV_GetDisplayDriver()->pExtTextOut(physDev->X11PhysDev, x, y, flags, lprect,
210 wstr, count, lpDx);
212 fin:
213 return res;
216 /***********************************************************************
217 * DIBDRV_GetTextExtentExPoint
219 BOOL DIBDRV_GetTextExtentExPoint( DIBDRVPHYSDEV *physDev, LPCWSTR str, INT count,
220 INT maxExt, LPINT lpnFit, LPINT alpDx, LPSIZE size )
222 BOOL res;
224 MAYBE(TRACE("physDev:%p, str:%s, count:%d, maxExt:%d, lpnFit:%p, alpDx:%p, size:%p\n",
225 physDev, debugstr_w(str), count, maxExt, lpnFit, alpDx, size));
227 if(physDev->hasDIB)
229 /* DIB section selected in, use DIB Engine */
230 ONCE(FIXME("STUB\n"));
231 res = TRUE;
233 else
235 /* DDB selected in, use X11 driver */
236 res = _DIBDRV_GetDisplayDriver()->pGetTextExtentExPoint(physDev->X11PhysDev, str, count, maxExt,
237 lpnFit, alpDx, size);
239 return res;