From 7c20ea6571ae5311641a4579de7494a3a5a1f8c3 Mon Sep 17 00:00:00 2001 From: James Tabor Date: Sat, 1 Nov 2008 12:08:07 +0000 Subject: [PATCH] - Update NtGdiGetGlyphOutline and NtGdiGetGlyphIndicesW. svn path=/trunk/; revision=37128 --- .../subsystems/win32/win32k/objects/font.c | 59 ++++++- .../win32/win32k/objects/freetype.c | 145 +++++++++--------- 2 files changed, 126 insertions(+), 78 deletions(-) diff --git a/reactos/subsystems/win32/win32k/objects/font.c b/reactos/subsystems/win32/win32k/objects/font.c index 76e7dfdf57a..713fb99cf95 100644 --- a/reactos/subsystems/win32/win32k/objects/font.c +++ b/reactos/subsystems/win32/win32k/objects/font.c @@ -149,22 +149,75 @@ NtGdiGetGlyphOutline( IN LPMAT2 pmat2, IN BOOL bIgnoreRotation) { - ULONG Ret; + ULONG Ret = GDI_ERROR; PDC dc; + PVOID pvBuf = NULL; + GLYPHMETRICS gm; + NTSTATUS Status = STATUS_SUCCESS; + dc = DC_LockDc(hdc); if (!dc) { SetLastWin32Error(ERROR_INVALID_HANDLE); return GDI_ERROR; } + + if (UnsafeBuf && cjBuf) + { + pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, TAG_GDITEXT); + if (!pvBuf) + { + SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); + goto Exit; + } + } + Ret = ftGdiGetGlyphOutline( dc, wch, iFormat, - pgm, + pgm ? &gm : NULL, cjBuf, - UnsafeBuf, + pvBuf, pmat2, bIgnoreRotation); + + if (pvBuf) + { + _SEH_TRY + { + ProbeForWrite(UnsafeBuf, cjBuf, 1); + RtlCopyMemory(UnsafeBuf, pvBuf, cjBuf); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END + + ExFreePoolWithTag(pvBuf, TAG_GDITEXT); + } + + if (pgm) + { + _SEH_TRY + { + ProbeForWrite(pgm, sizeof(GLYPHMETRICS), 1); + RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS)); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END + } + + if (! NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + Ret = GDI_ERROR; + } + +Exit: DC_UnlockDc(dc); return Ret; } diff --git a/reactos/subsystems/win32/win32k/objects/freetype.c b/reactos/subsystems/win32/win32k/objects/freetype.c index 8bb65454212..a2aef691326 100644 --- a/reactos/subsystems/win32/win32k/objects/freetype.c +++ b/reactos/subsystems/win32/win32k/objects/freetype.c @@ -2377,7 +2377,7 @@ NtGdiGetGlyphIndicesW( OUTLINETEXTMETRICW *potm; INT i; FT_Face face; - WCHAR DefChar = 0; + WCHAR DefChar = 0xffff; PWSTR Buffer = NULL; ULONG Size; @@ -2444,8 +2444,17 @@ NtGdiGetGlyphIndicesW( for (i = 0; i < cwc; i++) { - Buffer[i] = FT_Get_Char_Index(face, UnSafepwc[i]); - if (Buffer[i] == 0) Buffer[i] = DefChar; + Buffer[i] = FT_Get_Char_Index(face, UnSafepwc[i]); + if (Buffer[i] == 0) + { + if (DefChar == 0xffff && FT_IS_SFNT(face)) + { + TT_OS2 *pOS2 = FT_Get_Sfnt_Table(face, ft_sfnt_os2); + Buffer[i] = (pOS2->usDefaultChar ? FT_Get_Char_Index(face, pOS2->usDefaultChar) : 0); + } + else + Buffer[i] = DefChar; + } } IntUnLockFreeType; @@ -2518,7 +2527,7 @@ ftGdiGetGlyphOutline( UINT iFormat, LPGLYPHMETRICS pgm, ULONG cjBuf, - OPTIONAL PVOID UnsafeBuf, + PVOID pvBuf, LPMAT2 pmat2, BOOL bIgnoreRotation) { @@ -2527,7 +2536,6 @@ ftGdiGetGlyphOutline( PTEXTOBJ TextObj; PFONTGDI FontGDI; HFONT hFont = 0; - NTSTATUS Status; GLYPHMETRICS gm; ULONG Size; FT_Face ft_face; @@ -2545,13 +2553,12 @@ ftGdiGetGlyphOutline( LONG aveWidth; INT adv, lsb, bbx; /* These three hold to widths of the unrotated chars */ OUTLINETEXTMETRICW *potm; - PVOID pvBuf = NULL; int n = 0; FT_CharMap found = 0, charmap; XFORM xForm; DPRINT("%d, %08x, %p, %08lx, %p, %p\n", wch, iFormat, pgm, - cjBuf, UnsafeBuf, pmat2); + cjBuf, pvBuf, pmat2); Dc_Attr = dc->pDc_Attr; if(!Dc_Attr) Dc_Attr = &dc->Dc_Attr; @@ -2561,7 +2568,7 @@ ftGdiGetGlyphOutline( hFont = Dc_Attr->hlfntNew; TextObj = TEXTOBJ_LockText(hFont); -// DC_UnlockDc(dc); + if (!TextObj) { SetLastWin32Error(ERROR_INVALID_HANDLE); @@ -2591,8 +2598,6 @@ ftGdiGetGlyphOutline( DPRINT("WARNING: No charmap selected!\n"); DPRINT("This font face has %d charmaps\n", ft_face->num_charmaps); - - for (n = 0; n < ft_face->num_charmaps; n++) { charmap = ft_face->charmaps[n]; @@ -2643,7 +2648,7 @@ ftGdiGetGlyphOutline( { DPRINT1("WARNING: Failed to load and render glyph! [index: %u]\n", glyph_index); IntUnLockFreeType; - if (potm) ExFreePool(potm); + if (potm) ExFreePoolWithTag(potm, TAG_GDITEXT); return GDI_ERROR; } IntUnLockFreeType; @@ -2721,7 +2726,7 @@ ftGdiGetGlyphOutline( needsTransform = TRUE; } - if (potm) ExFreePool(potm); /* It looks like we are finished with potm ATM.*/ + if (potm) ExFreePoolWithTag(potm, TAG_GDITEXT); /* It looks like we are finished with potm ATM.*/ if (!needsTransform) { @@ -2784,16 +2789,7 @@ ftGdiGetGlyphOutline( IntUnLockFreeType; - if (pgm) - { - Status = MmCopyToCaller(pgm, &gm, sizeof(GLYPHMETRICS)); - if (! NT_SUCCESS(Status)) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return GDI_ERROR; - } - DPRINT("Copied GLYPHMETRICS to User!\n"); - } + if (pgm) RtlCopyMemory(pgm, &gm, sizeof(GLYPHMETRICS)); if (iFormat == GGO_METRICS) { @@ -2807,18 +2803,6 @@ ftGdiGetGlyphOutline( return GDI_ERROR; } - if (UnsafeBuf && cjBuf) - { - pvBuf = ExAllocatePoolWithTag(PagedPool, cjBuf, TAG_GDITEXT); - if (pvBuf == NULL) - { - SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY); - return GDI_ERROR; - } - RtlZeroMemory(pvBuf, cjBuf); - } - - switch(iFormat) { case GGO_BITMAP: @@ -2866,7 +2850,6 @@ ftGdiGetGlyphOutline( default: DPRINT1("loaded glyph format %x\n", ft_face->glyph->format); - if(pvBuf) ExFreePool(pvBuf); return GDI_ERROR; } break; @@ -2885,34 +2868,60 @@ ftGdiGetGlyphOutline( if(!pvBuf || !cjBuf) break; - ft_bitmap.width = width; - ft_bitmap.rows = height; - ft_bitmap.pitch = pitch; - ft_bitmap.pixel_mode = ft_pixel_mode_grays; - ft_bitmap.buffer = pvBuf; - - IntLockFreeType; - if(needsTransform) + switch(ft_face->glyph->format) { - FT_Outline_Transform(&ft_face->glyph->outline, &transMat); - } - FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom ); - RtlZeroMemory(ft_bitmap.buffer, cjBuf); - FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); - IntUnLockFreeType; + case ft_glyph_format_bitmap: + { + BYTE *src = ft_face->glyph->bitmap.buffer, *dst = pvBuf; + INT h = ft_face->glyph->bitmap.rows; + INT x; + while(h--) + { + for(x = 0; x < pitch; x++) + { + if(x < ft_face->glyph->bitmap.width) + dst[x] = (src[x / 8] & (1 << ( (7 - (x % 8))))) ? 0xff : 0; + else + dst[x] = 0; + } + src += ft_face->glyph->bitmap.pitch; + dst += pitch; + } + return needed; + } + case ft_glyph_format_outline: + { + ft_bitmap.width = width; + ft_bitmap.rows = height; + ft_bitmap.pitch = pitch; + ft_bitmap.pixel_mode = ft_pixel_mode_grays; + ft_bitmap.buffer = pvBuf; - if(iFormat == GGO_GRAY2_BITMAP) - mult = 4; - else if(iFormat == GGO_GRAY4_BITMAP) - mult = 16; - else if(iFormat == GGO_GRAY8_BITMAP) - mult = 64; - else - { - ASSERT(0); - break; - } + IntLockFreeType; + if (needsTransform) + { + FT_Outline_Transform(&ft_face->glyph->outline, &transMat); + } + FT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom ); + RtlZeroMemory(ft_bitmap.buffer, cjBuf); + FT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); + IntUnLockFreeType; + if (iFormat == GGO_GRAY2_BITMAP) + mult = 4; + else if (iFormat == GGO_GRAY4_BITMAP) + mult = 16; + else if (iFormat == GGO_GRAY8_BITMAP) + mult = 64; + else + { + return GDI_ERROR; + } + } + default: + DPRINT1("loaded glyph format %x\n", ft_face->glyph->format); + return GDI_ERROR; + } start = pvBuf; for(row = 0; row < height; row++) { @@ -3132,24 +3141,10 @@ ftGdiGetGlyphOutline( default: DPRINT1("Unsupported format %d\n", iFormat); - if(pvBuf) ExFreePool(pvBuf); return GDI_ERROR; } - if (pvBuf) - { - Status = MmCopyToCaller(UnsafeBuf, pvBuf, cjBuf); - if (! NT_SUCCESS(Status)) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - ExFreePool(pvBuf); - return GDI_ERROR; - } - DPRINT("NtGdiGetGlyphOutline K -> U worked!\n"); - ExFreePool(pvBuf); - } - - DPRINT("NtGdiGetGlyphOutline END and needed %d\n", needed); + DPRINT("ftGdiGetGlyphOutline END and needed %d\n", needed); return needed; }