text.c
来自「一个类似windows」· C语言 代码 · 共 2,305 行 · 第 1/5 页
C
2,305 行
*/
HSourceGlyph = EngCreateBitmap(bitSize, glyph->bitmap.pitch,
(glyph->bitmap.pixel_mode == ft_pixel_mode_grays) ?
BMF_8BPP : BMF_1BPP, BMF_TOPDOWN,
glyph->bitmap.buffer);
if ( !HSourceGlyph )
{
DPRINT1("WARNING: EngLockSurface() failed!\n");
IntUnLockFreeType;
goto fail;
}
SourceGlyphSurf = EngLockSurface((HSURF)HSourceGlyph);
if ( !SourceGlyphSurf )
{
EngDeleteSurface((HSURF)HSourceGlyph);
DPRINT1("WARNING: EngLockSurface() failed!\n");
IntUnLockFreeType;
goto fail;
}
/*
* Use the font data as a mask to paint onto the DCs surface using a
* brush.
*/
if (lprc &&
(fuOptions & ETO_CLIPPED) &&
DestRect.right >= SpecifiedDestRect.right + dc->w.DCOrgX)
{
// We do the check '>=' instead of '>' to possibly save an iteration
// through this loop, since it's breaking after the drawing is done,
// and x is always incremented.
DestRect.right = SpecifiedDestRect.right + dc->w.DCOrgX;
DoBreak = TRUE;
}
IntEngMaskBlt(
SurfObj,
SourceGlyphSurf,
dc->CombinedClip,
XlateObj,
XlateObj2,
&DestRect,
&SourcePoint,
(PPOINTL)&MaskRect,
&BrushFgInst.BrushObject,
&BrushOrigin);
EngUnlockSurface(SourceGlyphSurf);
EngDeleteSurface((HSURF)HSourceGlyph);
if (DoBreak)
{
break;
}
if (NULL == Dx)
{
TextLeft += glyph->advance.x;
}
else
{
TextLeft += Dx[i] << 6;
}
previous = glyph_index;
String++;
}
IntUnLockFreeType;
EngDeleteXlate(XlateObj);
EngDeleteXlate(XlateObj2);
BITMAPOBJ_UnlockBitmap(BitmapObj);
if(TextObj != NULL)
TEXTOBJ_UnlockText(TextObj);
if (hBrushBg != NULL)
{
BRUSHOBJ_UnlockBrush(BrushBg);
NtGdiDeleteObject(hBrushBg);
}
BRUSHOBJ_UnlockBrush(BrushFg);
NtGdiDeleteObject(hBrushFg);
if (NULL != Dx)
{
ExFreePool(Dx);
}
DC_UnlockDc( dc );
return TRUE;
fail:
if ( XlateObj2 != NULL )
EngDeleteXlate(XlateObj2);
if ( XlateObj != NULL )
EngDeleteXlate(XlateObj);
if(TextObj != NULL)
TEXTOBJ_UnlockText(TextObj);
BITMAPOBJ_UnlockBitmap(BitmapObj);
if (hBrushBg != NULL)
{
BRUSHOBJ_UnlockBrush(BrushBg);
NtGdiDeleteObject(hBrushBg);
}
if (hBrushFg != NULL)
{
BRUSHOBJ_UnlockBrush(BrushFg);
NtGdiDeleteObject(hBrushFg);
}
if (NULL != Dx)
{
ExFreePool(Dx);
}
DC_UnlockDc(dc);
return FALSE;
}
BOOL
STDCALL
NtGdiGetAspectRatioFilterEx(HDC hDC,
LPSIZE AspectRatio)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL
STDCALL
NtGdiGetCharABCWidths(HDC hDC,
UINT FirstChar,
UINT LastChar,
LPABC abc)
{
LPABC SafeBuffer;
PDC dc;
PTEXTOBJ TextObj;
PFONTGDI FontGDI;
FT_Face face;
FT_CharMap charmap, found = NULL;
UINT i, glyph_index, BufferSize;
HFONT hFont = 0;
NTSTATUS Status;
if (LastChar < FirstChar)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
BufferSize = (LastChar - FirstChar + 1) * sizeof(ABC);
SafeBuffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT);
if (SafeBuffer == NULL)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
dc = DC_LockDc(hDC);
if (dc == NULL)
{
ExFreePool(SafeBuffer);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
hFont = dc->w.hFont;
TextObj = TEXTOBJ_LockText(hFont);
DC_UnlockDc(dc);
if (TextObj == NULL)
{
ExFreePool(SafeBuffer);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
FontGDI = ObjToGDI(TextObj->Font, FONT);
face = FontGDI->face;
if (face->charmap == NULL)
{
for (i = 0; i < face->num_charmaps; i++)
{
charmap = face->charmaps[i];
if (charmap->encoding != 0)
{
found = charmap;
break;
}
}
if (!found)
{
DPRINT1("WARNING: Could not find desired charmap!\n");
ExFreePool(SafeBuffer);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
IntLockFreeType;
FT_Set_Charmap(face, found);
IntUnLockFreeType;
}
IntLockFreeType;
FT_Set_Pixel_Sizes(face,
TextObj->logfont.lfWidth,
/* FIXME should set character height if neg */
(TextObj->logfont.lfHeight < 0 ? - TextObj->logfont.lfHeight :
TextObj->logfont.lfHeight == 0 ? 11 : TextObj->logfont.lfHeight));
for (i = FirstChar; i <= LastChar; i++)
{
int adv, lsb, bbx, left, right;
glyph_index = FT_Get_Char_Index(face, i);
FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
left = (INT)face->glyph->metrics.horiBearingX & -64;
right = (INT)((face->glyph->metrics.horiBearingX + face->glyph->metrics.width) + 63) & -64;
adv = (face->glyph->advance.x + 32) >> 6;
// int test = (INT)(face->glyph->metrics.horiAdvance + 63) >> 6;
// DPRINT1("Advance Wine %d and Advance Ros %d\n",test, adv ); /* It's the same!*/
lsb = left >> 6;
bbx = (right - left) >> 6;
/*
DPRINT1("lsb %d and bbx %d\n", lsb, bbx );
*/
SafeBuffer[i - FirstChar].abcA = lsb;
SafeBuffer[i - FirstChar].abcB = bbx;
SafeBuffer[i - FirstChar].abcC = adv - lsb - bbx;
}
IntUnLockFreeType;
TEXTOBJ_UnlockText(TextObj);
Status = MmCopyToCaller(abc, SafeBuffer, BufferSize);
if (! NT_SUCCESS(Status))
{
SetLastNtError(Status);
ExFreePool(SafeBuffer);
return FALSE;
}
ExFreePool(SafeBuffer);
DPRINT("NtGdiGetCharABCWidths Worked!\n");
return TRUE;
}
BOOL
STDCALL
NtGdiGetCharABCWidthsFloat(HDC hDC,
UINT FirstChar,
UINT LastChar,
LPABCFLOAT abcF)
{
UNIMPLEMENTED;
return FALSE;
}
DWORD
STDCALL
NtGdiGetCharacterPlacement(HDC hDC,
LPCWSTR String,
int Count,
int MaxExtent,
LPGCP_RESULTSW Results,
DWORD Flags)
{
UNIMPLEMENTED;
return 0;
}
BOOL
STDCALL
NtGdiGetCharWidth32(HDC hDC,
UINT FirstChar,
UINT LastChar,
LPINT Buffer)
{
LPINT SafeBuffer;
PDC dc;
PTEXTOBJ TextObj;
PFONTGDI FontGDI;
FT_Face face;
FT_CharMap charmap, found = NULL;
UINT i, glyph_index, BufferSize;
HFONT hFont = 0;
if (LastChar < FirstChar)
{
SetLastWin32Error(ERROR_INVALID_PARAMETER);
return FALSE;
}
BufferSize = (LastChar - FirstChar + 1) * sizeof(INT);
SafeBuffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_GDITEXT);
if (SafeBuffer == NULL)
{
SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
return FALSE;
}
dc = DC_LockDc(hDC);
if (dc == NULL)
{
ExFreePool(SafeBuffer);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
hFont = dc->w.hFont;
TextObj = TEXTOBJ_LockText(hFont);
DC_UnlockDc(dc);
if (TextObj == NULL)
{
ExFreePool(SafeBuffer);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
FontGDI = ObjToGDI(TextObj->Font, FONT);
face = FontGDI->face;
if (face->charmap == NULL)
{
for (i = 0; i < face->num_charmaps; i++)
{
charmap = face->charmaps[i];
if (charmap->encoding != 0)
{
found = charmap;
break;
}
}
if (!found)
{
DPRINT1("WARNING: Could not find desired charmap!\n");
ExFreePool(SafeBuffer);
SetLastWin32Error(ERROR_INVALID_HANDLE);
return FALSE;
}
IntLockFreeType;
FT_Set_Charmap(face, found);
IntUnLockFreeType;
}
IntLockFreeType;
FT_Set_Pixel_Sizes(face,
TextObj->logfont.lfWidth,
/* FIXME should set character height if neg */
(TextObj->logfont.lfHeight < 0 ?
- TextObj->logfont.lfHeight :
TextObj->logfont.lfHeight == 0 ? 11 : TextObj->logfont.lfHeight));
for (i = FirstChar; i <= LastChar; i++)
{
glyph_index = FT_Get_Char_Index(face, i);
FT_Load_Glyph(face, glyph_index, FT_LOAD_DEFAULT);
SafeBuffer[i - FirstChar] = (face->glyph->advance.x + 32) >> 6;
}
IntUnLockFreeType;
TEXTOBJ_UnlockText(TextObj);
MmCopyToCaller(Buffer, SafeBuffer, BufferSize);
ExFreePool(SafeBuffer);
return TRUE;
}
BOOL
STDCALL
NtGdiGetCharWidthFloat(HDC hDC,
UINT FirstChar,
UINT LastChar,
PFLOAT Buffer)
{
UNIMPLEMENTED;
return FALSE;
}
DWORD
STDCALL
NtGdiGetFontLanguageInfo(HDC hDC)
{
UNIMPLEMENTED;
return 0;
}
static
void
FTVectorToPOINTFX(FT_Vector *vec, POINTFX *pt)
{
pt->x.value = vec->x >> 6;
pt->x.fract = (vec->x & 0x3f) << 10;
pt->x.fract |= ((pt->x.fract >> 6) | (pt->x.fract >> 12));
pt->y.value = vec->y >> 6;
pt->y.fract = (vec->y & 0x3f) << 10;
pt->y.fract |= ((pt->y.fract >> 6) | (pt->y.fract >> 12));
return;
}
/*
This function builds an FT_Fixed from a float. It puts the integer part
in the highest 16 bits and the decimal part in the lowest 16 bits of the FT_Fixed.
It fails if the integer part of the float number is greater than SHORT_MAX.
*/
static inline FT_Fixed FT_FixedFromFloat(float f)
{
short value = f;
unsigned short fract = (f - value) * 0xFFFF;
return (FT_Fixed)((long)value << 16 | (unsigned long)fract);
}
/*
This function builds an FT_Fixed from a FIXED. It simply put f.value
in the highest 16 bits and f.fract in the lowest 16 bits of the FT_Fixed.
*/
static inline FT_Fixed FT_FixedFromFIXED(FIXED f)
{
return (FT_Fixed)((long)f.value << 16 | (unsigned long)f.fract);
}
/*
* Based on WineEngGetGlyphOutline
*
*/
ULONG
APIENTRY
NtGdiGetGlyphOutline(
IN HDC hdc,
IN WCHAR wch,
IN UINT iFormat,
OUT LPGLYPHMETRICS pgm,
IN ULONG cjBuf,
OUT OPTIONAL PVOID UnsafeBuf,
IN LPMAT2 pmat2,
IN BOOL bIgnoreRotation)
{
static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)};
PDC dc;
PTEXTOBJ TextObj;
PFONTGDI FontGDI;
HFONT hFont = 0;
NTSTATUS Status;
GLYPHMETRICS gm;
ULONG Size;
FT_Face ft_face;
FT_UInt glyph_index;
DWORD width, height, pitch, needed = 0;
FT_Bitmap ft_bitmap;
FT_Error error;
INT left, right, top = 0, bottom = 0;
FT_Angle angle = 0;
FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
FLOAT eM11, widthRatio = 1.0;
FT_Matrix transMat = identityMat;
BOOL needsTransform = FALSE;
INT orientation;
LONG aveWidth;
INT adv, lsb, bbx; /* These three hold to widths
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?