source: trunk/src/gdi32/text.cpp@ 21628

Last change on this file since 21628 was 21628, checked in by dmik, 14 years ago

gdi32: Fixed broken TextOut API family that would draw text flipped along the base line.

File size: 25.3 KB
Line 
1/* $Id: text.cpp,v 1.45 2004-05-07 10:27:50 sandervl Exp $ */
2
3/*
4 * GDI32 text apis
5 *
6 * Based on Wine/ReWind code (objects\text.c, objects\font.c)
7 *
8 * Copyright 1993, 1994 Alexandre Julliard
9 * 1997 Alex Korobka
10 *
11 * Copyright 1999-2000 Christoph Bratschi
12 * Copyright 2002-2003 Innotek Systemberatung GmbH (sandervl@innotek.de)
13 *
14 * Project Odin Software License can be found in LICENSE.TXT
15 *
16 */
17#include <os2win.h>
18#include <stdlib.h>
19#include <stdio.h>
20#include <misc.h>
21#include <string.h>
22#include <float.h>
23#include "oslibgpi.h"
24#include <dcdata.h>
25#include <unicode.h>
26#include "dibsect.h"
27#include "ft2supp.h"
28#include "font.h"
29#include <math.h>
30
31#define DBG_LOCALLOG DBG_text
32#include "dbglocal.h"
33
34#define ELLIPSIS "..."
35#define ELLIPSISLEN 3
36
37//******************************************************************************
38//******************************************************************************
39CHAR getBrokenDBCS( LPCSTR strA, INT lenA )
40{
41 int i;
42
43 for( i = 0; i < lenA; i++ )
44 if( IsDBCSLeadByte( strA[ i ]))
45 i++;
46
47 if( lenA < i ) // terminated at DBCS lead byte
48 return strA[ lenA ];
49
50 return 0;
51}
52//******************************************************************************
53//******************************************************************************
54UINT WINAPI GetTextCharsetInfo(
55 HDC hdc, /* [in] Handle to device context */
56 LPFONTSIGNATURE fs, /* [out] Pointer to struct to receive data */
57 DWORD flags) /* [in] Reserved - must be 0 */
58{
59 HGDIOBJ hFont;
60 UINT charSet = DEFAULT_CHARSET;
61 LOGFONTW lf;
62 CHARSETINFO csinfo;
63
64 dprintf(("GetTextCharsetInfo %x %x %x", hdc, fs, flags));
65
66 hFont = GetCurrentObject(hdc, OBJ_FONT);
67 if (hFont == 0)
68 return(DEFAULT_CHARSET);
69 if ( GetObjectW(hFont, sizeof(LOGFONTW), &lf) != 0 )
70 charSet = lf.lfCharSet;
71
72 if (fs != NULL) {
73 if (!TranslateCharsetInfo((LPDWORD)charSet, &csinfo, TCI_SRCCHARSET))
74 return (DEFAULT_CHARSET);
75 memcpy(fs, &csinfo.fs, sizeof(FONTSIGNATURE));
76 }
77 return charSet;
78}
79/***********************************************************************
80 * GetTextCharset32 [GDI32.226] Gets character set for font in DC
81 *
82 * NOTES
83 * Should it return a UINT32 instead of an INT32?
84 * => YES, as GetTextCharsetInfo returns UINT32
85 *
86 * RETURNS
87 * Success: Character set identifier
88 * Failure: DEFAULT_CHARSET
89 */
90UINT WINAPI GetTextCharset(HDC hdc) /* [in] Handle to device context */
91{
92 /* MSDN docs say this is equivalent */
93 return GetTextCharsetInfo(hdc, NULL, 0);
94}
95//******************************************************************************
96// todo: metafile support
97//******************************************************************************
98BOOL InternalTextOutAW(HDC hdc,int X,int Y,UINT fuOptions,
99 CONST RECT *lprc, LPCSTR lpszStringA, LPCWSTR lpszStringW,
100 INT cbCount,CONST INT *lpDx,BOOL IsExtTextOut, BOOL fUnicode)
101{
102 pDCData pHps = (pDCData)OSLibGpiQueryDCData(hdc);
103 ULONG flOptions = 0;
104 RECTLOS2 pmRect;
105 POINTLOS2 ptl;
106 LONG hits;
107 RECT rect;
108
109 if (!pHps || (cbCount < 0) || (((lpszStringA == NULL && !fUnicode) || (lpszStringW == NULL && fUnicode)) && (cbCount != 0)))
110 {
111 dprintf(("InternalTextOutA: invalid parameter"));
112 SetLastError(ERROR_INVALID_HANDLE);
113 return FALSE;
114 }
115
116 if(cbCount == -1) {
117 if(fUnicode)
118 cbCount = lstrlenW(lpszStringW);
119 else cbCount = lstrlenA(lpszStringA);
120 }
121
122 if (cbCount > 512)
123 {
124 dprintf(("InternalTextOutA: invalid parameter cbCount"));
125 SetLastError(ERROR_INVALID_PARAMETER);
126 return FALSE;
127 }
128 if (fuOptions & ~((UINT)(ETO_CLIPPED | ETO_OPAQUE | ETO_GLYPH_INDEX)))
129 {
130 dprintf(("InternalTextOutA: invalid fuOptions"));
131 //ETO_GLYPH_INDEX, ETO_RTLLEADING, ETO_NUMERICSLOCAL, ETO_NUMERICSLATIN, ETO_IGNORELANGUAGE, ETO_PDY are ignored
132 return TRUE;
133 }
134
135 // When using font association, the height of DBCS and SBCS chars may be different.
136 // In this case, background color make stair below chars
137 if( IsDBCSEnv() && !lprc && ( GetBkMode( hdc ) & OPAQUE ))
138 {
139 SIZE size;
140 TEXTMETRICA tmA;
141
142 if( fUnicode )
143 GetTextExtentPointW( hdc, lpszStringW, cbCount, &size );
144 else
145 GetTextExtentPointA( hdc, lpszStringA, cbCount, &size );
146
147 GetTextMetricsA( hdc, &tmA );
148
149 rect.left = X;
150 rect.right = X + size.cx;
151 rect.top = Y;
152 rect.bottom = Y + tmA.tmHeight;
153
154 lprc = &rect;
155 fuOptions |= ETO_OPAQUE;
156 }
157
158 //CB: add metafile info
159
160 if (lprc)
161 {
162 if (fuOptions)
163 {
164 MapWin32ToOS2Rect(*lprc,pmRect);
165 if (excludeBottomRightPoint(pHps,(PPOINTLOS2)&pmRect) == 0)
166 {
167 dprintf(("InternalTextOutA: excludeBottomRightPoint returned 0"));
168 return TRUE;
169 }
170
171 if (fuOptions & ETO_CLIPPED) flOptions |= CHSOS_CLIP;
172 if (fuOptions & ETO_OPAQUE) flOptions |= CHSOS_OPAQUE;
173 }
174 }
175 else
176 {
177 if (fuOptions & ~ETO_GLYPH_INDEX)
178 {
179 dprintf(("InternalTextOutA: ERROR_INVALID_PARAMETER"));
180 SetLastError(ERROR_INVALID_PARAMETER);
181 return FALSE;
182 }
183 }
184
185 if((lpszStringA || lpszStringW) && cbCount) {
186 DIBSECTION_CHECK_IF_DIRTY(hdc);
187 }
188
189 if (cbCount == 0)
190 {
191 if (fuOptions & ETO_OPAQUE)
192 {
193//SvL: This doesn't seem to work (anymore). Look at MFC apps for the missing border
194// between menu & button bar (all white). (e.g. odin app & acrobat reader 4.05)
195#if 0
196 lpszString = " ";
197 cbCount = 1;
198 flOptions |= CHSOS_CLIP;
199#else
200 HBRUSH hbrush = CreateSolidBrush(GetBkColor(hdc));
201 HBRUSH oldbrush;
202
203 oldbrush = SelectObject(hdc, hbrush);
204 FillRect(hdc, lprc, hbrush);
205 SelectObject(hdc, oldbrush);
206 DeleteObject(hbrush);
207
208 DIBSECTION_MARK_INVALID(hdc);
209
210 return TRUE;
211#endif
212 }
213 else {
214 dprintf(("InternalTextOutA: cbCount == 0"));
215 return TRUE;
216 }
217 }
218
219 if (lpDx)
220 flOptions |= CHSOS_VECTOR;
221
222 if (!getAlignUpdateCP(pHps))
223 {
224 ptl.x = X;
225 ptl.y = Y;
226
227 flOptions |= CHSOS_LEAVEPOS;
228 }
229 else OSLibGpiQueryCurrentPosition(pHps,&ptl);
230
231 UINT align = GetTextAlign(hdc);
232 LONG pmHAlign,pmVAlign;
233
234#if 0
235 //SvL: This code is broken. TODO: Investigate
236 //CB: TA_RIGHT not supported by PM, only TA_CENTER and TA_LEFT
237 if ((align & 0x6) == TA_RIGHT)
238 {
239 BOOL rc;
240 PPOINTLOS2 pts = (PPOINTLOS2)malloc((cbCount+1)*sizeof(POINTLOS2));
241
242 rc = OSLibGpiQueryCharStringPosAt(pHps,&ptl,flOptions & CHSOS_VECTOR,cbCount,lpszString,lpDx,pts);
243 if(rc) {
244 for(int i=0;i<cbCount+1;i++) {
245 dprintf(("OSLibGpiQueryCharStringPosAt %d (%d,%d)", pts[i].x, pts[i].y));
246 }
247 ptl.x -= pts[cbCount].x-pts[0].x;
248 }
249 free(pts);
250 }
251#endif
252
253 if (lprc && ((align & 0x18) == TA_BASELINE))
254 {
255 //CB: if TA_BASELINE is set, GPI doesn't fill rect
256 // TA_BOTTOM fills rect
257 OSLibGpiQueryTextAlignment(pHps,&pmHAlign,&pmVAlign);
258 OSLibGpiSetTextAlignment(pHps,pmHAlign,(pmVAlign & ~TAOS_BASE) | TAOS_BOTTOM);
259 }
260
261#ifdef INVERT
262 ptl.y += getWorldYDeltaFor1Pixel(pHps);
263#else
264 ptl.y -= getWorldYDeltaFor1Pixel(pHps);
265
266 int vertAdjust = 0;
267 if ((pHps->taMode & 0x18) != TA_TOP)
268 {
269 vertAdjust = OSLibGpiQueryFontMaxHeight(pHps->hps);
270 }
271 ptl.y -= vertAdjust;
272#endif
273
274 if(fUnicode)
275 hits = FT2Module.Ft2CharStringPosAtW(pHps->hps,&ptl,&pmRect,flOptions,cbCount,lpszStringW,lpDx, fuOptions & ETO_GLYPH_INDEX);
276 else
277 {
278 INT *lpDxNew = NULL;
279
280 // KOMH : OS/2 uses width of lead byte for whole DBCS width and is not concerned about
281 // trail byte, while Win can apportion width between lead byte and trail byte
282 if( IsDBCSEnv() && lpDx )
283 {
284 int i;
285
286 lpDxNew = ( INT * )malloc(( cbCount + 1 ) * sizeof( INT )); // 1 for broken DBCS char
287 for( i = 0; i < cbCount; i++ )
288 {
289 lpDxNew[ i ] = lpDx[ i ];
290 if( IsDBCSLeadByte( lpszStringA[ i ] ))
291 {
292 lpDxNew[ i ] += lpDx[ i + 1 ];
293 lpDxNew[ ++i ] = 0; // for the sake of possibility
294 }
295 }
296
297 lpDx = lpDxNew;
298 }
299
300 hits = FT2Module.Ft2CharStringPosAtA(pHps->hps,&ptl,&pmRect,flOptions,cbCount,lpszStringA,lpDx, fuOptions & ETO_GLYPH_INDEX);
301
302 if( lpDxNew )
303 free( lpDxNew );
304 }
305
306 if (lprc && ((align & 0x18) == TA_BASELINE))
307 OSLibGpiSetTextAlignment(pHps,pmHAlign,pmVAlign);
308
309 if(hits == GPIOS_ERROR) {
310 dprintf(("InternalTextOutA: OSLibGpiCharStringPosAt returned GPIOS_ERROR"));
311 return FALSE;
312 }
313
314 if (getAlignUpdateCP(pHps))
315 {
316 OSLibGpiQueryCurrentPosition(pHps,&ptl);
317 ptl.y -= getWorldYDeltaFor1Pixel(pHps);
318#ifndef INVERT
319 ptl.y += vertAdjust;
320#endif
321 OSLibGpiSetCurrentPosition(pHps,&ptl);
322 }
323
324 DIBSECTION_MARK_INVALID(hdc);
325
326 return TRUE;
327}
328//******************************************************************************
329//******************************************************************************
330BOOL WIN32API ExtTextOutA(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCSTR lpszString,UINT cbCount,CONST INT *lpDx)
331{
332 BOOL rc;
333 SIZE size;
334 int newy;
335
336 if(lprc)
337 {
338 dprintf(("GDI32: ExtTextOutA %x %.*s (%d,%d) %x %d %x rect (%d,%d)(%d,%d)", hdc, cbCount, lpszString, X, Y, fuOptions, cbCount, lpDx, lprc->left, lprc->top, lprc->right, lprc->bottom));
339 }
340 else dprintf(("GDI32: ExtTextOutA %x %.*s (%d,%d) %x %d %x", hdc, cbCount, lpszString, X, Y, fuOptions, cbCount, lpDx));
341
342 if(lpDx) {
343 for(int i=0;i<cbCount;i++) {
344 dprintf2(("Inc %d", lpDx[i]));
345 }
346 }
347
348 rc = InternalTextOutAW(hdc, X, Y, fuOptions, lprc, lpszString, NULL, cbCount, lpDx, TRUE, FALSE);
349
350 return(rc);
351}
352//******************************************************************************
353//******************************************************************************
354BOOL WIN32API ExtTextOutW(HDC hdc,int X,int Y,UINT fuOptions,CONST RECT *lprc,LPCWSTR lpszString,UINT cbCount,CONST int *lpDx)
355{
356 if(lprc) {
357 dprintf(("GDI32: ExtTextOutW %x %.*ls (%d,%d) %x %d %x rect (%d,%d)(%d,%d)", hdc, cbCount, lpszString, X, Y, fuOptions, cbCount, lpDx, lprc->left, lprc->top, lprc->right, lprc->bottom));
358 }
359 else dprintf(("GDI32: ExtTextOutW %x %.*ls (%d,%d) %x %d %x", hdc, cbCount, lpszString, X, Y, fuOptions, cbCount, lpDx));
360
361 return InternalTextOutAW(hdc, X, Y, fuOptions, lprc, NULL, lpszString, cbCount, lpDx, TRUE, TRUE);
362}
363//******************************************************************************
364//******************************************************************************
365BOOL WIN32API TextOutA(HDC hdc,int nXStart,int nYStart,LPCSTR lpszString,int cbString)
366{
367 dprintf(("GDI32: TextOutA %x (%d,%d) %d %.*s", hdc, nXStart, nYStart, cbString, cbString, lpszString));
368 return InternalTextOutAW(hdc,nXStart,nYStart,0,NULL,lpszString,NULL,cbString,NULL,FALSE, FALSE);
369}
370//******************************************************************************
371//******************************************************************************
372BOOL WIN32API TextOutW(HDC hdc,int nXStart,int nYStart,LPCWSTR lpszString,int cbString)
373{
374 dprintf(("GDI32: TextOutW %x (%d,%d) %d %.*ls", hdc, nXStart, nYStart, cbString, cbString, lpszString));
375 return InternalTextOutAW(hdc,nXStart,nYStart,0,NULL, NULL, lpszString,cbString,NULL,FALSE, TRUE);
376}
377//******************************************************************************
378//******************************************************************************
379BOOL WIN32API PolyTextOutA(HDC hdc,POLYTEXTA *pptxt,int cStrings)
380{
381 dprintf(("GDI32: PolyTextOutA %x %x %d", hdc, pptxt, cStrings));
382
383 for (INT x = 0;x < cStrings;x++)
384 {
385 BOOL rc;
386
387 rc = ExtTextOutA(hdc,pptxt[x].x,pptxt[x].y,pptxt[x].uiFlags,&pptxt[x].rcl,pptxt[x].lpstr, pptxt[x].n,pptxt[x].pdx);
388 if (!rc) return FALSE;
389 }
390
391 return TRUE;
392}
393//******************************************************************************
394//******************************************************************************
395BOOL WIN32API PolyTextOutW(HDC hdc,POLYTEXTW *pptxt,int cStrings)
396{
397 dprintf(("GDI32: PolyTextOutW %x %x %d", hdc, pptxt, cStrings));
398
399 for (INT x = 0;x < cStrings;x++)
400 {
401 BOOL rc;
402
403 rc = ExtTextOutW(hdc,pptxt[x].x,pptxt[x].y,pptxt[x].uiFlags,&pptxt[x].rcl, pptxt[x].lpstr,pptxt[x].n,pptxt[x].pdx);
404 if (!rc) return FALSE;
405 }
406
407 return TRUE;
408}
409//******************************************************************************
410// Note: GetTextExtentPoint behaves differently under certain circumstances
411// compared to GetTextExtentPoint32 (due to bugs).
412// We are treating both as the same thing which is not entirely correct.
413//
414//******************************************************************************
415BOOL WIN32API GetTextExtentPointA(HDC hdc, LPCTSTR lpsz, int cbString,
416 LPSIZE lpsSize)
417{
418 BOOL ret = FALSE;
419 INT wlen;
420 LPWSTR p;
421 CHAR brokenDBCS = 0;
422
423 if( IsDBCSEnv())
424 brokenDBCS = getBrokenDBCS( lpsz, cbString );
425
426 if( brokenDBCS )
427 cbString--;
428
429 p = FONT_mbtowc(hdc, lpsz, cbString, &wlen, NULL);
430 if (p) {
431 ret = GetTextExtentPointW( hdc, p, wlen, lpsSize );
432 // For broken DBCS. Correct for FIXED WIDTH, but approx. for VARIABLE WIDTH
433 if( brokenDBCS )
434 {
435 TEXTMETRICA tmA;
436
437 GetTextMetricsA( hdc, &tmA );
438 lpsSize->cx += tmA.tmAveCharWidth;
439
440 if( cbString == 0 )
441 lpsSize->cy = tmA.tmHeight;
442 }
443
444 HeapFree( GetProcessHeap(), 0, p );
445 }
446 else DebugInt3();
447 return ret;
448}
449//******************************************************************************
450//******************************************************************************
451BOOL WIN32API GetTextExtentPointW(HDC hdc,
452 LPCWSTR lpString,
453 int cbString,
454 PSIZE lpSize)
455{
456 BOOL rc;
457 POINTLOS2 widthHeight = { 0, 0};
458 pDCData pHps = (pDCData)OSLibGpiQueryDCData((HPS)hdc);
459
460 dprintf(("GDI32: GetTextExtentPointW %.*ls", cbString, lpString));
461 if(pHps == NULL)
462 {
463 SetLastError(ERROR_INVALID_HANDLE);
464 return FALSE;
465 }
466
467 if(lpString == NULL || cbString < 0 || lpSize == NULL)
468 {
469 SetLastError(ERROR_INVALID_PARAMETER);
470 return FALSE;
471 }
472
473 lpSize->cx = 0;
474 lpSize->cy = 0;
475
476 // Verified with NT4, SP6
477 if(cbString == 0)
478 {
479 dprintf(("!WARNING!: GDI32: GetTextExtentPointW invalid parameter!"));
480 SetLastError(ERROR_SUCCESS);
481 return TRUE;
482 }
483
484 if(pHps->isPrinter)
485 ReallySetCharAttrs(pHps);
486
487 if(cbString > 512)
488 {
489 DWORD cbStringNew;
490 SIZE newSize;
491
492 dprintf(("WARNING: string longer than 512 chars; splitting up"));
493 while(cbString) {
494 cbStringNew = min(500, cbString);
495 rc = GetTextExtentPointW(hdc, lpString, cbStringNew, &newSize);
496 if(rc == FALSE) {
497 return FALSE;
498 }
499 lpSize->cx += newSize.cx;
500 lpSize->cy = max(newSize.cy, lpSize->cy);
501 lpString += cbStringNew;
502 cbString -= cbStringNew;
503 }
504 return TRUE;
505 }
506
507 rc = FT2Module.Ft2GetTextExtentW(pHps->hps, cbString, lpString, &widthHeight);
508 if(rc == FALSE)
509 {
510 SetLastError(ERROR_INVALID_PARAMETER); //todo wrong error
511 return FALSE;
512 }
513 lpSize->cx = widthHeight.x;
514 lpSize->cy = widthHeight.y;
515
516 if(pHps && pHps->isPrinter && pHps->hdc)
517 {//scale for printer dcs
518 LONG alArray[2];
519
520 if(OSLibDevQueryCaps(pHps, OSLIB_CAPS_HORIZONTAL_RESOLUTION, 2, &alArray[0]))
521 lpSize->cx = lpSize->cx * alArray[0] / alArray[1];
522 }
523
524 dprintf(("GDI32: GetTextExtentPointW %x %ls %d returned %d (%d,%d)", hdc, lpString, cbString, rc, lpSize->cx, lpSize->cy));
525 SetLastError(ERROR_SUCCESS);
526 return TRUE;
527}
528//******************************************************************************
529//******************************************************************************
530BOOL WIN32API GetTextExtentPoint32A( HDC hdc, LPCSTR lpsz, int cbString, PSIZE lpSize)
531{
532 return GetTextExtentPointA(hdc, lpsz, cbString, lpSize);
533}
534//******************************************************************************
535//******************************************************************************
536BOOL WIN32API GetTextExtentPoint32W(HDC hdc, LPCWSTR lpsz, int cbString, PSIZE lpSize)
537{
538 return GetTextExtentPointW(hdc, lpsz, cbString, lpSize);
539}
540
541typedef BOOL ( WIN32API *PFN_GETTEXTEXTENTPOINT32 )( HDC, PVOID, INT, LPSIZE );
542
543BOOL InternalGetTextExtentExPointAW(HDC hdc,
544 PVOID str,
545 INT count,
546 INT maxExt,
547 LPINT lpnFit,
548 LPINT alpDx,
549 LPSIZE size,
550 BOOL fUnicode)
551{
552 int i, nFit;
553 SIZE tSize;
554 BOOL ret = FALSE;
555
556 PFN_GETTEXTEXTENTPOINT32 pfnGetTextExtentPoint32;
557
558 if( fUnicode )
559 pfnGetTextExtentPoint32 = ( PFN_GETTEXTEXTENTPOINT32 )GetTextExtentPoint32W;
560 else
561 pfnGetTextExtentPoint32 = ( PFN_GETTEXTEXTENTPOINT32 )GetTextExtentPoint32A;
562
563 size->cx = size->cy = nFit = i = 0;
564
565 if( lpnFit || alpDx )
566 {
567 for( i = 1; i <= count; i++ )
568 {
569 if( !pfnGetTextExtentPoint32( hdc, str, i, &tSize )) goto done;
570
571 if( lpnFit && ( maxExt < tSize.cx ))
572 break;
573
574 if( alpDx )
575 alpDx[ nFit ] = tSize.cx;
576
577 nFit++;
578 }
579 }
580
581 if(( count > 0 ) && ( i >= count ))
582 {
583 size->cx = tSize.cx;
584 size->cy = tSize.cy; // The height of a font is constant.
585 }
586 else if( !pfnGetTextExtentPoint32( hdc, str, count, size )) goto done;
587
588 if(lpnFit) *lpnFit = nFit;
589 ret = TRUE;
590
591 dprintf(("returning %d %ld x %ld\n",nFit,size->cx,size->cy));
592
593done:
594 return ret;
595}
596
597//******************************************************************************
598//******************************************************************************
599BOOL WIN32API GetTextExtentExPointA(HDC hdc,
600 LPCSTR str,
601 int count,
602 int maxExt,
603 LPINT lpnFit,
604 LPINT alpDx,
605 LPSIZE size)
606{
607 return InternalGetTextExtentExPointAW( hdc, ( PVOID )str, count, maxExt, lpnFit, alpDx, size, FALSE );
608}
609//******************************************************************************
610//******************************************************************************
611BOOL WIN32API GetTextExtentExPointW(HDC hdc,
612 LPCWSTR str,
613 int count,
614 int maxExt,
615 LPINT lpnFit,
616 LPINT alpDx,
617 LPSIZE size)
618{
619 return InternalGetTextExtentExPointAW( hdc, ( PVOID )str, count, maxExt, lpnFit, alpDx, size, TRUE );
620}
621//******************************************************************************
622//******************************************************************************
623BOOL WIN32API GetCharWidth32A( HDC hdc, UINT iFirstChar, UINT iLastChar, PINT pWidthArray)
624{
625 BOOL ret = FALSE;
626
627 for (int i = iFirstChar; i <= iLastChar; i++)
628 {
629 SIZE size;
630 CHAR c = i;
631
632 if (GetTextExtentPointA(hdc, &c, 1, &size))
633 {
634 pWidthArray[i-iFirstChar] = size.cx;
635 // at least one character was processed
636 ret = TRUE;
637 }
638 else
639 {
640 // default value for unprocessed characters
641 pWidthArray[i-iFirstChar] = 0;
642 }
643
644 dprintf2(("Char 0x%x('%c') -> width %d", i, i<256? i: '.', pWidthArray[i-iFirstChar]));
645 }
646
647 return ret;
648}
649//******************************************************************************
650//******************************************************************************
651BOOL WIN32API GetCharWidth32W(HDC hdc, UINT iFirstChar, UINT iLastChar, PINT pWidthArray)
652{
653 BOOL ret = FALSE;
654
655 for (int i = iFirstChar; i <= iLastChar; i++)
656 {
657 SIZE size;
658 WCHAR wc = i;
659
660 if (GetTextExtentPointW(hdc, &wc, 1, &size))
661 {
662 pWidthArray[i-iFirstChar] = size.cx;
663 // at least one character was processed
664 ret = TRUE;
665 }
666 else
667 {
668 // default value for unprocessed characters
669 pWidthArray[i-iFirstChar] = 0;
670 }
671
672 dprintf2(("Char 0x%x('%c') -> width %d", i, i<256? i: '.', pWidthArray[i-iFirstChar]));
673 }
674
675 return ret;
676}
677//******************************************************************************
678// GetStringWidthW
679//
680// Return the width of each character in the string
681//
682// Parameters:
683// HDC hdc - device context handle
684// LPWSTR lpszString - unicod string pointer
685// UINT cbString - number of valid characters in string
686// PINT pWidthArray - array that receives the character width (must be
687// large enough to contain cbString elements
688//
689// Returns:
690// FALSE - failure
691// TRUE - success
692//
693//******************************************************************************
694BOOL WIN32API GetStringWidthW(HDC hdc, LPWSTR lpszString, UINT cbString, PINT pWidthArray)
695{
696 return FT2Module.Ft2GetStringWidthW(hdc, lpszString, cbString, pWidthArray);
697}
698//******************************************************************************
699//******************************************************************************
700BOOL WIN32API GetCharWidthFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar, PFLOAT pxBUffer)
701{
702 dprintf(("ERROR: GDI32: GetCharWidthFloatA, not implemented\n"));
703 DebugInt3();
704 return(FALSE);
705}
706//******************************************************************************
707//******************************************************************************
708BOOL WIN32API GetCharWidthFloatW(HDC hdc, UINT iFirstChar, UINT iLastChar, PFLOAT pxBUffer)
709{
710 dprintf(("ERROR: GDI32: GetCharWidthFloatW, not implemented\n"));
711 DebugInt3();
712 return(FALSE);
713}
714//******************************************************************************
715//******************************************************************************
716BOOL WIN32API GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar, LPABC abc)
717{
718 if(FT2Module.isEnabled() == FALSE)
719 {//fallback method
720 return O32_GetCharABCWidths(hdc, firstChar, lastChar, abc);
721 }
722
723 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
724 LPSTR str;
725 LPWSTR wstr;
726 BOOL ret = TRUE;
727
728 if(count <= 0) {
729 dprintf(("ERROR: Invalid parameter!!"));
730 SetLastError(ERROR_INVALID_PARAMETER);
731 return FALSE;
732 }
733
734 str = (LPSTR)HeapAlloc(GetProcessHeap(), 0, count);
735 for(i = 0; i < count; i++)
736 str[i] = (BYTE)(firstChar + i);
737
738 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
739
740 for(i = 0; i < wlen; i++)
741 {
742 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
743 {
744 ret = FALSE;
745 break;
746 }
747 abc++;
748 }
749
750 HeapFree(GetProcessHeap(), 0, str);
751 HeapFree(GetProcessHeap(), 0, wstr);
752
753 return ret;
754}
755//******************************************************************************
756//******************************************************************************
757BOOL WIN32API GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar, LPABC abc)
758{
759 if(FT2Module.isEnabled() == FALSE)
760 {//no fallback method (yet)
761 DebugInt3();
762 return FALSE;
763 }
764
765 int i;
766 GLYPHMETRICS gm;
767
768 for (i=firstChar;i<=lastChar;i++)
769 {
770 if(GetGlyphOutlineW(hdc, i, GGO_METRICS, &gm, 0, NULL, NULL) == GDI_ERROR)
771 {
772 dprintf(("ERROR: GetGlyphOutlineW failed!!"));
773 return FALSE;
774 }
775 abc[i-firstChar].abcA = gm.gmptGlyphOrigin.x;
776 abc[i-firstChar].abcB = gm.gmBlackBoxX;
777 abc[i-firstChar].abcC = gm.gmCellIncX - gm.gmptGlyphOrigin.x - gm.gmBlackBoxX;
778 dprintf2(("GetCharABCWidthsW %d (%d,%d,%d)", i, abc[i-firstChar].abcA, abc[i-firstChar].abcB, abc[i-firstChar].abcC));
779 }
780 return TRUE;
781}
782//******************************************************************************
783//******************************************************************************
784BOOL WIN32API GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar, LPABCFLOAT pxBUffer)
785{
786 dprintf(("ERROR: GDI32: GetCharABCWidthsFloatA, not implemented\n"));
787 DebugInt3();
788 return(FALSE);
789}
790//******************************************************************************
791//******************************************************************************
792BOOL WIN32API GetCharABCWidthsFloatW(HDC hdc,
793 UINT iFirstChar,
794 UINT iLastChar,
795 LPABCFLOAT pxBUffer)
796{
797 dprintf(("ERROR: GDI32: GetCharABCWidthsFloatA, not implemented\n"));
798 DebugInt3();
799 return(FALSE);
800}
801//******************************************************************************
802//******************************************************************************
803
Note: See TracBrowser for help on using the repository browser.