⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 text.c

📁 这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
 * ReactOS W32 Subsystem
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
 *
 * Parts based on Wine code
 * Copyright 1993 Alexandre Julliard
 *           1997 Alex Korobka
 * Copyright 2002,2003 Shachar Shemesh
 * Copyright 2001 Huw D M Davies for CodeWeavers.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
/* $Id: text.c 28248 2007-08-08 18:58:06Z jimtabor $ */

#include <w32k.h>

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include <freetype/tttables.h>
#include <freetype/fttrigon.h>
#include <freetype/ftglyph.h>
#include <freetype/ftoutln.h>
#include <freetype/ftwinfnt.h>

#define NDEBUG
#include <debug.h>

FT_Library  library;

typedef struct _FONT_ENTRY {
  LIST_ENTRY ListEntry;
  FONTGDI *Font;
  UNICODE_STRING FaceName;
  BYTE NotEnum;
} FONT_ENTRY, *PFONT_ENTRY;

/* The FreeType library is not thread safe, so we have
   to serialize access to it */
static FAST_MUTEX FreeTypeLock;

static LIST_ENTRY FontListHead;
static FAST_MUTEX FontListLock;
static BOOL RenderingEnabled = TRUE;

#define MAX_FONT_CACHE 256
UINT Hits;
UINT Misses;

typedef struct _FONT_CACHE_ENTRY {
  LIST_ENTRY ListEntry;
  int GlyphIndex;
  FT_Face Face;
  FT_Glyph Glyph;
  int Height;
} FONT_CACHE_ENTRY, *PFONT_CACHE_ENTRY;
static LIST_ENTRY FontCacheListHead;
static UINT FontCacheNumEntries;

static PWCHAR ElfScripts[32] = { /* these are in the order of the fsCsb[0] bits */
  L"Western", /*00*/
  L"Central_European",
  L"Cyrillic",
  L"Greek",
  L"Turkish",
  L"Hebrew",
  L"Arabic",
  L"Baltic",
  L"Vietnamese", /*08*/
  NULL, NULL, NULL, NULL, NULL, NULL, NULL, /*15*/
  L"Thai",
  L"Japanese",
  L"CHINESE_GB2312",
  L"Hangul",
  L"CHINESE_BIG5",
  L"Hangul(Johab)",
  NULL, NULL, /*23*/
  NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  L"Symbol" /*31*/
};

/*
 *  For NtGdiTranslateCharsetInfo
 */
#define FS(x) {{0,0,0,0},{0x1<<(x),0}}
#define MAXTCIINDEX 32
static CHARSETINFO FontTci[MAXTCIINDEX] = {
  /* ANSI */
  { ANSI_CHARSET, 1252, FS(0)},
  { EASTEUROPE_CHARSET, 1250, FS(1)},
  { RUSSIAN_CHARSET, 1251, FS(2)},
  { GREEK_CHARSET, 1253, FS(3)},
  { TURKISH_CHARSET, 1254, FS(4)},
  { HEBREW_CHARSET, 1255, FS(5)},
  { ARABIC_CHARSET, 1256, FS(6)},
  { BALTIC_CHARSET, 1257, FS(7)},
  { VIETNAMESE_CHARSET, 1258, FS(8)},
  /* reserved by ANSI */
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  /* ANSI and OEM */
  { THAI_CHARSET,  874,  FS(16)},
  { SHIFTJIS_CHARSET, 932, FS(17)},
  { GB2312_CHARSET, 936, FS(18)},
  { HANGEUL_CHARSET, 949, FS(19)},
  { CHINESEBIG5_CHARSET, 950, FS(20)},
  { JOHAB_CHARSET, 1361, FS(21)},
  /* reserved for alternate ANSI and OEM */
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  { DEFAULT_CHARSET, 0, FS(0)},
  /* reserved for system */
  { DEFAULT_CHARSET, 0, FS(0)},
  { SYMBOL_CHARSET, 42 /* CP_SYMBOL */, FS(31)},
};

VOID FASTCALL
IntLoadSystemFonts(VOID);

INT FASTCALL
IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics);

BOOL FASTCALL
InitFontSupport(VOID)
{
   ULONG ulError;

   InitializeListHead(&FontListHead);
   InitializeListHead(&FontCacheListHead);
   FontCacheNumEntries = 0;
   ExInitializeFastMutex(&FontListLock);
   ExInitializeFastMutex(&FreeTypeLock);

   ulError = FT_Init_FreeType(&library);
   if (ulError) {
      DPRINT1("FT_Init_FreeType failed with error code 0x%x\n", ulError);
      return FALSE;
   }

   IntLoadSystemFonts();

   return TRUE;
}

/*
 * IntLoadSystemFonts
 *
 * Search the system font directory and adds each font found.
 */

VOID FASTCALL
IntLoadSystemFonts(VOID)
{
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING Directory, SearchPattern, FileName, TempString;
   IO_STATUS_BLOCK Iosb;
   HANDLE hDirectory;
   BYTE *DirInfoBuffer;
   PFILE_DIRECTORY_INFORMATION DirInfo;
   BOOL bRestartScan = TRUE;
   NTSTATUS Status;

   RtlInitUnicodeString(&Directory, L"\\SystemRoot\\media\\fonts\\");
   /* FIXME: Add support for other font types */
   RtlInitUnicodeString(&SearchPattern, L"*.ttf");

   InitializeObjectAttributes(
      &ObjectAttributes,
      &Directory,
      OBJ_CASE_INSENSITIVE,
      NULL,
      NULL);

   Status = ZwOpenFile(
      &hDirectory,
      SYNCHRONIZE | FILE_LIST_DIRECTORY,
      &ObjectAttributes,
      &Iosb,
      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
      FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE);

   if (NT_SUCCESS(Status))
   {
      DirInfoBuffer = ExAllocatePool(PagedPool, 0x4000);
      if (DirInfoBuffer == NULL)
      {
         ZwClose(hDirectory);
         return;
      }

      FileName.Buffer = ExAllocatePool(PagedPool, MAX_PATH * sizeof(WCHAR));
      if (FileName.Buffer == NULL)
      {
         ExFreePool(DirInfoBuffer);
         ZwClose(hDirectory);
         return;
      }
      FileName.Length = 0;
      FileName.MaximumLength = MAX_PATH * sizeof(WCHAR);

      while (1)
      {
         Status = ZwQueryDirectoryFile(
            hDirectory,
            NULL,
            NULL,
            NULL,
            &Iosb,
            DirInfoBuffer,
            0x4000,
            FileDirectoryInformation,
            FALSE,
            &SearchPattern,
            bRestartScan);

         if (!NT_SUCCESS(Status) || Status == STATUS_NO_MORE_FILES)
         {
            break;
         }

         DirInfo = (PFILE_DIRECTORY_INFORMATION)DirInfoBuffer;
         while (1)
         {
            TempString.Buffer = DirInfo->FileName;
            TempString.Length =
            TempString.MaximumLength = DirInfo->FileNameLength;
            RtlCopyUnicodeString(&FileName, &Directory);
            RtlAppendUnicodeStringToString(&FileName, &TempString);
            IntGdiAddFontResource(&FileName, 0);
            if (DirInfo->NextEntryOffset == 0)
               break;
            DirInfo = (PFILE_DIRECTORY_INFORMATION)((ULONG_PTR)DirInfo + DirInfo->NextEntryOffset);
         }

         bRestartScan = FALSE;
      }

      ExFreePool(FileName.Buffer);
      ExFreePool(DirInfoBuffer);
      ZwClose(hDirectory);
   }
}

/*
 * IntGdiAddFontResource
 *
 * Adds the font resource from the specified file to the system.
 */

INT FASTCALL
IntGdiAddFontResource(PUNICODE_STRING FileName, DWORD Characteristics)
{
   FONTGDI *FontGDI;
   NTSTATUS Status;
   HANDLE FileHandle;
   OBJECT_ATTRIBUTES ObjectAttributes;
   PVOID Buffer = NULL;
   IO_STATUS_BLOCK Iosb;
   INT Error;
   FT_Face Face;
   ANSI_STRING AnsiFaceName;
   PFONT_ENTRY Entry;
   PSECTION_OBJECT SectionObject;
   ULONG ViewSize = 0;
   FT_Fixed XScale, YScale;
   UNICODE_STRING FileNameCopy;

   /* Open the font file */

   InitializeObjectAttributes(&ObjectAttributes, FileName, 0, NULL, NULL);
   Status = ZwOpenFile(
      &FileHandle,
      FILE_GENERIC_READ | SYNCHRONIZE,
      &ObjectAttributes,
      &Iosb,
      FILE_SHARE_READ,
      FILE_SYNCHRONOUS_IO_NONALERT);

   if (!NT_SUCCESS(Status))
   {
      DPRINT("Could not font file: %wZ\n", FileName);
      return 0;
   }

   Status = MmCreateSection((PVOID)&SectionObject, SECTION_ALL_ACCESS,
                            NULL, NULL, PAGE_READONLY,
                            0, FileHandle, NULL);
   if (!NT_SUCCESS(Status))
   {
      DPRINT("Could not map file: %wZ\n", FileName);
      ZwClose(FileHandle);
      return 0;
   }

   ZwClose(FileHandle);

   Status = MmMapViewInSystemSpace(SectionObject, &Buffer, &ViewSize);
   if (!NT_SUCCESS(Status))
   {
      DPRINT("Could not map file: %wZ\n", FileName);
      return Status;
   }

   IntLockFreeType;
   Error = FT_New_Memory_Face(
      library,
      Buffer,
      ViewSize,
      0,
      &Face);
   IntUnLockFreeType;

   if (Error)
   {
      if (Error == FT_Err_Unknown_File_Format)
         DPRINT("Unknown font file format\n");
      else
         DPRINT("Error reading font file (error code: %u)\n", Error);
      ObDereferenceObject(SectionObject);
      return 0;
   }

   Entry = ExAllocatePoolWithTag(PagedPool, sizeof(FONT_ENTRY), TAG_FONT);
   if (!Entry)
   {
      FT_Done_Face(Face);
      ObDereferenceObject(SectionObject);
      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
      return 0;
   }

   FontGDI = EngAllocMem(FL_ZERO_MEMORY, sizeof(FONTGDI), TAG_FONTOBJ);
   if(FontGDI == NULL)
   {
      FT_Done_Face(Face);
      ObDereferenceObject(SectionObject);
      ExFreePool(Entry);
      SetLastWin32Error(ERROR_NOT_ENOUGH_MEMORY);
      return 0;
   }

   RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, FileName, &FileNameCopy);
   FontGDI->Filename = FileNameCopy.Buffer;
   FontGDI->face = Face;

   /* FIXME: Complete text metrics */
    XScale = Face->size->metrics.x_scale;
    YScale = Face->size->metrics.y_scale;
#if 1 /* This (Wine) code doesn't seem to work correctly for us */
    FontGDI->TextMetric.tmAscent =  (FT_MulFix(Face->ascender, YScale) + 32) >> 6;
    FontGDI->TextMetric.tmDescent = (FT_MulFix(Face->descender, YScale) + 32) >> 6;
    FontGDI->TextMetric.tmHeight =  (FT_MulFix(Face->ascender, YScale) - 
                                     FT_MulFix(Face->descender, YScale)) >> 6;
#else
    FontGDI->TextMetric.tmAscent  = (Face->size->metrics.ascender + 32) >> 6; /* units above baseline */
    FontGDI->TextMetric.tmDescent = (32 - Face->size->metrics.descender) >> 6; /* units below baseline */
    FontGDI->TextMetric.tmHeight = (Face->size->metrics.ascender - Face->size->metrics.descender) >> 6;
#endif



   DPRINT("Font loaded: %s (%s)\n", Face->family_name, Face->style_name);
   DPRINT("Num glyphs: %u\n", Face->num_glyphs);

   /* Add this font resource to the font table */

   Entry->Font = FontGDI;
   Entry->NotEnum = (Characteristics & FR_NOT_ENUM);
   RtlInitAnsiString(&AnsiFaceName, (LPSTR)Face->family_name);
   RtlAnsiStringToUnicodeString(&Entry->FaceName, &AnsiFaceName, TRUE);

   if (Characteristics & FR_PRIVATE)
   {
      PW32PROCESS Win32Process = PsGetCurrentProcessWin32Process();
      IntLockProcessPrivateFonts(Win32Process);
      InsertTailList(&Win32Process->PrivateFontListHead, &Entry->ListEntry);
      IntUnLockProcessPrivateFonts(Win32Process);
   }
   else
   {
      IntLockGlobalFonts;
      InsertTailList(&FontListHead, &Entry->ListEntry);
      IntUnLockGlobalFonts;
   }

   return 1;
}

BOOL FASTCALL
IntIsFontRenderingEnabled(VOID)
{
   BOOL Ret = RenderingEnabled;
   HDC hDC;

   hDC = IntGetScreenDC();
   if (hDC)
      Ret = (NtGdiGetDeviceCaps(hDC, BITSPIXEL) > 8) && RenderingEnabled;

   return Ret;
}

VOID FASTCALL
IntEnableFontRendering(BOOL Enable)
{
  RenderingEnabled = Enable;
}

FT_Render_Mode FASTCALL
IntGetFontRenderMode(LOGFONTW *logfont)
{
  switch(logfont->lfQuality)
  {
    case NONANTIALIASED_QUALITY:
      return FT_RENDER_MODE_MONO;
    case DRAFT_QUALITY:
      return FT_RENDER_MODE_LIGHT;
/*    case CLEARTYPE_QUALITY:
        return FT_RENDER_MODE_LCD; */
  }
  return FT_RENDER_MODE_NORMAL;
}

int
STDCALL
NtGdiAddFontResource(PUNICODE_STRING Filename, DWORD fl)
{
  UNICODE_STRING SafeFileName;
  PWSTR src;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -