Original patch by forshaw.
authorTom Sepez <tsepez@chromium.org>
Mon, 5 Oct 2015 19:57:17 +0000 (12:57 -0700)
committerTom Sepez <tsepez@chromium.org>
Mon, 5 Oct 2015 19:57:17 +0000 (12:57 -0700)
Added a fallback Win32 font information class for win32k lockdown.
This is to support running PDFIUM within the Win32k lockdown by
removing dependancies on USER32/GDI for the font information code.
It falls back to using a freetype/directory enumeration implementation
if it detects the win32k system calls have been disabled by policy.

BUG=523278
R=tsepez@chromium.org

Review URL: https://codereview.chromium.org/1306883002 .

core/include/fxge/fx_font.h
core/src/fxge/ge/fx_ge_fontmap.cpp
core/src/fxge/ge/fx_ge_linux.cpp
core/src/fxge/win32/fx_win32_device.cpp

index 8f6db1e..bdaeff7 100644 (file)
@@ -338,6 +338,13 @@ class CFX_FolderFontInfo : public IFX_SystemFontInfo {
                   FXSYS_FILE* pFile,
                   FX_DWORD filesize,
                   FX_DWORD offset);
+  void* GetSubstFont(const CFX_ByteString& face);
+  void* FindFont(int weight,
+                 FX_BOOL bItalic,
+                 int charset,
+                 int pitch_family,
+                 const FX_CHAR* family,
+                 FX_BOOL bMatchName);
 };
 class CFX_CountedFaceCache {
  public:
index 90b3c52..826caa0 100644 (file)
@@ -1407,6 +1407,105 @@ void CFX_FolderFontInfo::ReportFace(CFX_ByteString& path,
   }
   m_FontList[facename] = pInfo;
 }
+static const struct {
+  const FX_CHAR* m_pName;
+  const FX_CHAR* m_pSubstName;
+} Base14Substs[] = {
+    {"Courier", "Courier New"},
+    {"Courier-Bold", "Courier New Bold"},
+    {"Courier-BoldOblique", "Courier New Bold Italic"},
+    {"Courier-Oblique", "Courier New Italic"},
+    {"Helvetica", "Arial"},
+    {"Helvetica-Bold", "Arial Bold"},
+    {"Helvetica-BoldOblique", "Arial Bold Italic"},
+    {"Helvetica-Oblique", "Arial Italic"},
+    {"Times-Roman", "Times New Roman"},
+    {"Times-Bold", "Times New Roman Bold"},
+    {"Times-BoldItalic", "Times New Roman Bold Italic"},
+    {"Times-Italic", "Times New Roman Italic"},
+};
+void* CFX_FolderFontInfo::GetSubstFont(const CFX_ByteString& face) {
+  for (size_t iBaseFont = 0; iBaseFont < FX_ArraySize(Base14Substs);
+       iBaseFont++) {
+    if (face == Base14Substs[iBaseFont].m_pName) {
+      return GetFont(Base14Substs[iBaseFont].m_pSubstName);
+    }
+  }
+  return nullptr;
+}
+static FX_DWORD _GetCharset(int charset) {
+  switch (charset) {
+    case FXFONT_SHIFTJIS_CHARSET:
+      return CHARSET_FLAG_SHIFTJIS;
+    case FXFONT_GB2312_CHARSET:
+      return CHARSET_FLAG_GB;
+    case FXFONT_CHINESEBIG5_CHARSET:
+      return CHARSET_FLAG_BIG5;
+    case FXFONT_HANGEUL_CHARSET:
+      return CHARSET_FLAG_KOREAN;
+    case FXFONT_SYMBOL_CHARSET:
+      return CHARSET_FLAG_SYMBOL;
+    case FXFONT_ANSI_CHARSET:
+      return CHARSET_FLAG_ANSI;
+    default:
+      break;
+  }
+  return 0;
+}
+static int32_t _GetSimilarValue(int weight,
+                                FX_BOOL bItalic,
+                                int pitch_family,
+                                FX_DWORD style) {
+  int32_t iSimilarValue = 0;
+  if ((style & FXFONT_BOLD) == (weight > 400)) {
+    iSimilarValue += 16;
+  }
+  if ((style & FXFONT_ITALIC) == bItalic) {
+    iSimilarValue += 16;
+  }
+  if ((style & FXFONT_SERIF) == (pitch_family & FXFONT_FF_ROMAN)) {
+    iSimilarValue += 16;
+  }
+  if ((style & FXFONT_SCRIPT) == (pitch_family & FXFONT_FF_SCRIPT)) {
+    iSimilarValue += 8;
+  }
+  if ((style & FXFONT_FIXED_PITCH) == (pitch_family & FXFONT_FF_FIXEDPITCH)) {
+    iSimilarValue += 8;
+  }
+  return iSimilarValue;
+}
+void* CFX_FolderFontInfo::FindFont(int weight,
+                                   FX_BOOL bItalic,
+                                   int charset,
+                                   int pitch_family,
+                                   const FX_CHAR* family,
+                                   FX_BOOL bMatchName) {
+  CFX_FontFaceInfo* pFind = nullptr;
+  if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) {
+    return GetFont("Courier New");
+  }
+  FX_DWORD charset_flag = _GetCharset(charset);
+  int32_t iBestSimilar = 0;
+  for (const auto& it : m_FontList) {
+    const CFX_ByteString& bsName = it.first;
+    CFX_FontFaceInfo* pFont = it.second;
+    if (!(pFont->m_Charsets & charset_flag) &&
+        charset != FXFONT_DEFAULT_CHARSET) {
+      continue;
+    }
+    int32_t index = bsName.Find(family);
+    if (bMatchName && index < 0) {
+      continue;
+    }
+    int32_t iSimilarValue =
+        _GetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles);
+    if (iSimilarValue > iBestSimilar) {
+      iBestSimilar = iSimilarValue;
+      pFind = pFont;
+    }
+  }
+  return pFind;
+}
 void* CFX_FolderFontInfo::MapFont(int weight,
                                   FX_BOOL bItalic,
                                   int charset,
index 065fd12..609777f 100644 (file)
@@ -9,23 +9,6 @@
 #include "text_int.h"
 
 #if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
-static const struct {
-  const FX_CHAR* m_pName;
-  const FX_CHAR* m_pSubstName;
-} Base14Substs[] = {
-    {"Courier", "Courier New"},
-    {"Courier-Bold", "Courier New Bold"},
-    {"Courier-BoldOblique", "Courier New Bold Italic"},
-    {"Courier-Oblique", "Courier New Italic"},
-    {"Helvetica", "Arial"},
-    {"Helvetica-Bold", "Arial Bold"},
-    {"Helvetica-BoldOblique", "Arial Bold Italic"},
-    {"Helvetica-Oblique", "Arial Italic"},
-    {"Times-Roman", "Times New Roman"},
-    {"Times-Bold", "Times New Roman Bold"},
-    {"Times-BoldItalic", "Times New Roman Bold Italic"},
-    {"Times-Italic", "Times New Roman Italic"},
-};
 class CFX_LinuxFontInfo : public CFX_FolderFontInfo {
  public:
   void* MapFont(int weight,
@@ -35,12 +18,6 @@ class CFX_LinuxFontInfo : public CFX_FolderFontInfo {
                 const FX_CHAR* family,
                 int& iExact) override;
   FX_BOOL ParseFontCfg(const char** pUserPaths);
-  void* FindFont(int weight,
-                 FX_BOOL bItalic,
-                 int charset,
-                 int pitch_family,
-                 const FX_CHAR* family,
-                 FX_BOOL bMatchName);
 };
 #define LINUX_GPNAMESIZE 6
 static const struct {
@@ -94,16 +71,10 @@ void* CFX_LinuxFontInfo::MapFont(int weight,
                                  int pitch_family,
                                  const FX_CHAR* cstr_face,
                                  int& iExact) {
-  CFX_ByteString face = cstr_face;
-  int iBaseFont;
-  for (iBaseFont = 0; iBaseFont < 12; iBaseFont++)
-    if (face == CFX_ByteStringC(Base14Substs[iBaseFont].m_pName)) {
-      face = Base14Substs[iBaseFont].m_pSubstName;
-      iExact = 1;
-      break;
-    }
-  if (iBaseFont < 12) {
-    return GetFont(face);
+  void* font = GetSubstFont(cstr_face);
+  if (font) {
+    iExact = 1;
+    return font;
   }
   FX_BOOL bCJK = TRUE;
   switch (charset) {
@@ -147,85 +118,8 @@ void* CFX_LinuxFontInfo::MapFont(int weight,
       bCJK = FALSE;
       break;
   }
-  if (charset == FXFONT_ANSI_CHARSET && (pitch_family & FXFONT_FF_FIXEDPITCH)) {
-    return GetFont("Courier New");
-  }
   return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK);
 }
-static FX_DWORD _LinuxGetCharset(int charset) {
-  switch (charset) {
-    case FXFONT_SHIFTJIS_CHARSET:
-      return CHARSET_FLAG_SHIFTJIS;
-    case FXFONT_GB2312_CHARSET:
-      return CHARSET_FLAG_GB;
-    case FXFONT_CHINESEBIG5_CHARSET:
-      return CHARSET_FLAG_BIG5;
-    case FXFONT_HANGEUL_CHARSET:
-      return CHARSET_FLAG_KOREAN;
-    case FXFONT_SYMBOL_CHARSET:
-      return CHARSET_FLAG_SYMBOL;
-    case FXFONT_ANSI_CHARSET:
-      return CHARSET_FLAG_ANSI;
-    default:
-      break;
-  }
-  return 0;
-}
-static int32_t _LinuxGetSimilarValue(int weight,
-                                     FX_BOOL bItalic,
-                                     int pitch_family,
-                                     FX_DWORD style) {
-  int32_t iSimilarValue = 0;
-  if ((style & FXFONT_BOLD) == (weight > 400)) {
-    iSimilarValue += 16;
-  }
-  if ((style & FXFONT_ITALIC) == bItalic) {
-    iSimilarValue += 16;
-  }
-  if ((style & FXFONT_SERIF) == (pitch_family & FXFONT_FF_ROMAN)) {
-    iSimilarValue += 16;
-  }
-  if ((style & FXFONT_SCRIPT) == (pitch_family & FXFONT_FF_SCRIPT)) {
-    iSimilarValue += 8;
-  }
-  if ((style & FXFONT_FIXED_PITCH) == (pitch_family & FXFONT_FF_FIXEDPITCH)) {
-    iSimilarValue += 8;
-  }
-  return iSimilarValue;
-}
-void* CFX_LinuxFontInfo::FindFont(int weight,
-                                  FX_BOOL bItalic,
-                                  int charset,
-                                  int pitch_family,
-                                  const FX_CHAR* family,
-                                  FX_BOOL bMatchName) {
-  CFX_FontFaceInfo* pFind = NULL;
-  FX_DWORD charset_flag = _LinuxGetCharset(charset);
-  int32_t iBestSimilar = 0;
-  for (const auto& it : m_FontList) {
-    const CFX_ByteString& bsName = it.first;
-    CFX_FontFaceInfo* pFont = it.second;
-    if (!(pFont->m_Charsets & charset_flag) &&
-        charset != FXFONT_DEFAULT_CHARSET) {
-      continue;
-    }
-    int32_t iSimilarValue = 0;
-    int32_t index = bsName.Find(family);
-    if (bMatchName && index < 0) {
-      continue;
-    }
-    if (!bMatchName && index > 0) {
-      iSimilarValue += 64;
-    }
-    iSimilarValue =
-        _LinuxGetSimilarValue(weight, bItalic, pitch_family, pFont->m_Styles);
-    if (iSimilarValue > iBestSimilar) {
-      iBestSimilar = iSimilarValue;
-      pFind = pFont;
-    }
-  }
-  return pFind;
-}
 IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUserPaths) {
   CFX_LinuxFontInfo* pInfo = new CFX_LinuxFontInfo;
   if (!pInfo->ParseFontCfg(pUserPaths)) {
index 2db35f7..a40e79b 100644 (file)
 #include "dwrite_int.h"
 #include "win32_int.h"
 
+class CFX_Win32FallbackFontInfo final : public CFX_FolderFontInfo {
+ public:
+  void* MapFont(int weight,
+                FX_BOOL bItalic,
+                int charset,
+                int pitch_family,
+                const FX_CHAR* family,
+                int& iExact) override;
+};
 class CFX_Win32FontInfo final : public IFX_SystemFontInfo {
  public:
   CFX_Win32FontInfo();
@@ -199,6 +208,29 @@ CFX_ByteString CFX_Win32FontInfo::FindFont(const CFX_ByteString& name) {
   }
   return CFX_ByteString();
 }
+void* CFX_Win32FallbackFontInfo::MapFont(int weight,
+                                         FX_BOOL bItalic,
+                                         int charset,
+                                         int pitch_family,
+                                         const FX_CHAR* cstr_face,
+                                         int& iExact) {
+  void* font = GetSubstFont(cstr_face);
+  if (font) {
+    iExact = 1;
+    return font;
+  }
+  FX_BOOL bCJK = TRUE;
+  switch (charset) {
+    case FXFONT_SHIFTJIS_CHARSET:
+    case FXFONT_GB2312_CHARSET:
+    case FXFONT_CHINESEBIG5_CHARSET:
+    case FXFONT_HANGEUL_CHARSET:
+    default:
+      bCJK = FALSE;
+      break;
+  }
+  return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK);
+}
 struct _FontNameMap {
   const FX_CHAR* m_pSubFontName;
   const FX_CHAR* m_pSrcFontName;
@@ -406,7 +438,24 @@ FX_BOOL CFX_Win32FontInfo::GetFontCharset(void* hFont, int& charset) {
   return TRUE;
 }
 IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUnused) {
-  return new CFX_Win32FontInfo;
+  HDC hdc = ::GetDC(NULL);
+  if (hdc) {
+    ::ReleaseDC(NULL, hdc);
+    return new CFX_Win32FontInfo;
+  }
+  // If GDI is disabled then GetDC for the desktop will fail. Select the
+  // fallback font information class if GDI is disabled.
+  CFX_Win32FallbackFontInfo* pInfoFallback = new CFX_Win32FallbackFontInfo;
+  // Construct the font path manually, SHGetKnownFolderPath won't work under
+  // a restrictive sandbox.
+  CHAR windows_path[MAX_PATH] = {};
+  DWORD path_len = ::GetWindowsDirectoryA(windows_path, MAX_PATH);
+  if (path_len > 0 && path_len < MAX_PATH) {
+    CFX_ByteString fonts_path(windows_path);
+    fonts_path += "\\Fonts";
+    pInfoFallback->AddPath(fonts_path);
+  }
+  return pInfoFallback;
 }
 void CFX_GEModule::InitPlatform() {
   CWin32Platform* pPlatformData = new CWin32Platform;