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
22 #include "wine/port.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(dibdrv
);
28 /***********************************************************************
31 BOOL
DIBDRV_ExtTextOut( DIBDRVPHYSDEV
*physDev
, INT x
, INT y
, UINT flags
,
32 const RECT
*lprect
, LPCWSTR wstr
, UINT count
,
35 /* FIXME : TODO many, many stuffs... just trivial text support by now */
47 FT_BitmapGlyph bitmapGlyph
;
48 FT_Bitmap
*bitmap
, bitmap8
;
49 double cosEsc
, sinEsc
;
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
));
64 /* DIB section selected in, use DIB Engine */
69 ERR("FreeType face is null\n");
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
)
79 WCHAR
*str
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(WCHAR
)*(count
+1));
80 int delta
= a
- pFT_Get_Char_Index( face
, a
);
82 memcpy(str
, wstr
, sizeof(WCHAR
)*count
);
83 for(i
= 0; str
[i
] && i
< count
; i
++)
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
))
110 memcpy(&clipRec
, r
, sizeof(RECT
));
112 /* if opaque, paint the font background */
113 if(flags
& ETO_OPAQUE
)
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
);
131 ONCE(ERR("Couldn't set char size to (%d,%d), code %d\n", lf
.lfWidth
, lf
.lfHeight
, error
));
133 /* transformation matrix and vector */
136 if(lf
.lfEscapement
!= 0)
138 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
139 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
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 */
153 for ( n
= 0; n
< count
; n
++ )
155 /* retrieve glyph index from character code */
156 if(flags
& ETO_GLYPH_INDEX
)
157 glyph_index
= *wstrPnt
++;
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
);
165 ERR("Couldn't load glyph at index %d\n", glyph_index
);
169 error
= pFT_Get_Glyph(face
->glyph
, &glyph
);
172 FIXME("Couldn't get glyph\n");
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(
189 #ifdef DIBDRV_ANTIALIASED_FONTS
190 physDev
->physBitmap
.bitCount
> 8 ? FT_RENDER_MODE_NORMAL
: FT_RENDER_MODE_MONO
,
194 0, /* no additional translation */
195 1 /* destroy copy in "image" */
201 FIXME("Couldn't render glyph\n");
202 pFT_Done_Glyph(glyph
);
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
);
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 */
233 pFT_Done_Glyph(glyph
);
237 } /* end region rects loop */
241 /* DDB selected in, use X11 driver */
242 res
= _DIBDRV_GetDisplayDriver()->pExtTextOut(physDev
->X11PhysDev
, x
, y
, flags
, lprect
,
249 /***********************************************************************
250 * DIBDRV_GetTextExtentExPoint
252 BOOL
DIBDRV_GetTextExtentExPoint( DIBDRVPHYSDEV
*physDev
, LPCWSTR str
, INT count
,
253 INT maxExt
, LPINT lpnFit
, LPINT alpDx
, LPSIZE size
)
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
));
262 /* DIB section selected in, use DIB Engine */
263 ONCE(FIXME("STUB\n"));
268 /* DDB selected in, use X11 driver */
269 res
= _DIBDRV_GetDisplayDriver()->pGetTextExtentExPoint(physDev
->X11PhysDev
, str
, count
, maxExt
,
270 lpnFit
, alpDx
, size
);