Allow external font-path configuration from pdfium_test.
authorTom Sepez <tsepez@chromium.org>
Thu, 13 Aug 2015 18:22:54 +0000 (11:22 -0700)
committerTom Sepez <tsepez@chromium.org>
Thu, 13 Aug 2015 18:22:54 +0000 (11:22 -0700)
R=thestig@chromium.org

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

13 files changed:
core/include/fxge/fx_font.h
core/include/fxge/fx_ge.h
core/src/fxge/apple/fx_mac_imp.cpp
core/src/fxge/ge/fx_ge.cpp
core/src/fxge/ge/fx_ge_fontmap.cpp
core/src/fxge/ge/fx_ge_linux.cpp
core/src/fxge/win32/fx_win32_device.cpp
fpdfsdk/src/fpdf_sysfontinfo.cpp
fpdfsdk/src/fpdfview.cpp
fpdfsdk/src/fpdfview_c_api_test.c
public/fpdfview.h
samples/pdfium_test.cc
testing/tools/run_corpus_tests.py

index aa9286f..5cd1620 100644 (file)
@@ -285,7 +285,7 @@ class CFX_FontMapper {
 };
 class IFX_SystemFontInfo {
  public:
-  static IFX_SystemFontInfo* CreateDefault();
+  static IFX_SystemFontInfo* CreateDefault(const char** pUserPaths);
   virtual void Release() = 0;
 
   virtual FX_BOOL EnumFontList(CFX_FontMapper* pMapper) = 0;
index 0aa3f17..ef3c8f6 100644 (file)
@@ -24,7 +24,7 @@ class IFXG_PaintModuleMgr;
 
 class CFX_GEModule {
  public:
-  static void Create();
+  static void Create(const char** pUserFontPaths);
 
   static void Use(CFX_GEModule* pMgr);
 
@@ -46,7 +46,7 @@ class CFX_GEModule {
   void* GetPlatformData() { return m_pPlatformData; }
 
  protected:
-  CFX_GEModule();
+  explicit CFX_GEModule(const char** pUserFontPaths);
 
   ~CFX_GEModule();
   void InitPlatform();
@@ -58,6 +58,7 @@ class CFX_GEModule {
   CFX_FontMgr* m_pFontMgr;
   CCodec_ModuleMgr* m_pCodecModule;
   void* m_pPlatformData;
+  const char** m_pUserFontPaths;
 };
 typedef struct {
   FX_FLOAT m_PointX;
index 9918ba9..5a4e660 100644 (file)
@@ -93,7 +93,7 @@ void* CFX_MacFontInfo::MapFont(int weight,
   }
   return NULL;
 }
-IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() {
+IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUnused) {
   CFX_MacFontInfo* pInfo = new CFX_MacFontInfo;
   pInfo->AddPath("~/Library/Fonts");
   pInfo->AddPath("/Library/Fonts");
@@ -102,7 +102,7 @@ IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() {
 }
 void CFX_GEModule::InitPlatform() {
   m_pPlatformData = new CApplePlatform;
-  m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault());
+  m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault(nullptr));
 }
 void CFX_GEModule::DestroyPlatform() {
   delete (CApplePlatform*)m_pPlatformData;
index d37ed5c..6dfed88 100644 (file)
@@ -7,12 +7,13 @@
 #include "../../../include/fxge/fx_ge.h"
 #include "text_int.h"
 static CFX_GEModule* g_pGEModule = NULL;
-CFX_GEModule::CFX_GEModule() {
+CFX_GEModule::CFX_GEModule(const char** pUserFontPaths) {
   m_pFontCache = NULL;
   m_pFontMgr = NULL;
   m_FTLibrary = NULL;
   m_pCodecModule = NULL;
   m_pPlatformData = NULL;
+  m_pUserFontPaths = pUserFontPaths;
 }
 CFX_GEModule::~CFX_GEModule() {
   delete m_pFontCache;
@@ -24,8 +25,8 @@ CFX_GEModule::~CFX_GEModule() {
 CFX_GEModule* CFX_GEModule::Get() {
   return g_pGEModule;
 }
-void CFX_GEModule::Create() {
-  g_pGEModule = new CFX_GEModule;
+void CFX_GEModule::Create(const char** userFontPaths) {
+  g_pGEModule = new CFX_GEModule(userFontPaths);
   g_pGEModule->m_pFontMgr = new CFX_FontMgr;
   g_pGEModule->InitPlatform();
   g_pGEModule->SetTextGamma(2.2f);
index 02af775..d4416d9 100644 (file)
@@ -1270,7 +1270,7 @@ extern FX_BOOL _LoadFile(FXFT_Library library,
                          IFX_FileRead* pFile,
                          FXFT_Stream* stream);
 #if _FX_OS_ == _FX_ANDROID_
-IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() {
+IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUnused) {
   return NULL;
 }
 #endif
index 299806c..8ff0a4e 100644 (file)
@@ -34,7 +34,7 @@ class CFX_LinuxFontInfo : public CFX_FolderFontInfo {
                 int pitch_family,
                 const FX_CHAR* family,
                 int& iExact) override;
-  FX_BOOL ParseFontCfg();
+  FX_BOOL ParseFontCfg(const char** pUserPaths);
   void* FindFont(int weight,
                  FX_BOOL bItalic,
                  int charset,
@@ -227,9 +227,9 @@ void* CFX_LinuxFontInfo::FindFont(int weight,
   }
   return pFind;
 }
-IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() {
+IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUserPaths) {
   CFX_LinuxFontInfo* pInfo = new CFX_LinuxFontInfo;
-  if (!pInfo->ParseFontCfg()) {
+  if (!pInfo->ParseFontCfg(pUserPaths)) {
     pInfo->AddPath("/usr/share/fonts");
     pInfo->AddPath("/usr/share/X11/fonts/Type1");
     pInfo->AddPath("/usr/share/X11/fonts/TTF");
@@ -237,11 +237,18 @@ IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() {
   }
   return pInfo;
 }
-FX_BOOL CFX_LinuxFontInfo::ParseFontCfg() {
-  return FALSE;
+FX_BOOL CFX_LinuxFontInfo::ParseFontCfg(const char** pUserPaths) {
+  if (!pUserPaths) {
+    return FALSE;
+  }
+  for (const char** pPath = pUserPaths; *pPath; ++pPath) {
+    AddPath(*pPath);
+  }
+  return TRUE;
 }
 void CFX_GEModule::InitPlatform() {
-  m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault());
+  m_pFontMgr->SetSystemFontInfo(
+      IFX_SystemFontInfo::CreateDefault(m_pUserFontPaths));
 }
 void CFX_GEModule::DestroyPlatform() {}
 #endif  // _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_
index 4cfc6cb..c3325ba 100644 (file)
@@ -401,7 +401,7 @@ FX_BOOL CFX_Win32FontInfo::GetFontCharset(void* hFont, int& charset) {
   charset = tm.tmCharSet;
   return TRUE;
 }
-IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault() {
+IFX_SystemFontInfo* IFX_SystemFontInfo::CreateDefault(const char** pUnused) {
   return new CFX_Win32FontInfo;
 }
 void CFX_GEModule::InitPlatform() {
@@ -412,7 +412,7 @@ void CFX_GEModule::InitPlatform() {
   pPlatformData->m_bHalfTone = ver.dwMajorVersion >= 5;
   pPlatformData->m_GdiplusExt.Load();
   m_pPlatformData = pPlatformData;
-  m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault());
+  m_pFontMgr->SetSystemFontInfo(IFX_SystemFontInfo::CreateDefault(nullptr));
 }
 void CFX_GEModule::DestroyPlatform() {
   delete (CWin32Platform*)m_pPlatformData;
index a0fdb50..804efe3 100644 (file)
@@ -168,7 +168,7 @@ static void DefaultDeleteFont(struct _FPDF_SYSFONTINFO* pThis, void* hFont) {
 }
 
 DLLEXPORT FPDF_SYSFONTINFO* STDCALL FPDF_GetDefaultSystemFontInfo() {
-  IFX_SystemFontInfo* pFontInfo = IFX_SystemFontInfo::CreateDefault();
+  IFX_SystemFontInfo* pFontInfo = IFX_SystemFontInfo::CreateDefault(nullptr);
   if (pFontInfo == NULL)
     return NULL;
 
index 9ad3384..2700aeb 100644 (file)
@@ -91,9 +91,14 @@ CFontMapper* g_pFontMapper = NULL;
 #endif  // #if _FX_OS_ == _FX_LINUX_EMBEDDED_
 
 DLLEXPORT void STDCALL FPDF_InitLibrary() {
+  FPDF_InitLibraryWithConfig(nullptr);
+}
+
+DLLEXPORT void STDCALL FPDF_InitLibraryWithConfig(
+    const FPDF_LIBRARY_CONFIG* cfg) {
   g_pCodecModule = new CCodec_ModuleMgr();
 
-  CFX_GEModule::Create();
+  CFX_GEModule::Create(cfg ? cfg->m_pUserFontPaths : nullptr);
   CFX_GEModule::Get()->SetCodecModule(g_pCodecModule);
 
   CPDF_ModuleMgr::Create();
index 3fd682d..a17f7b6 100644 (file)
@@ -172,6 +172,7 @@ int CheckPDFiumCApi() {
 
     // fpdfview.h
     CHK(FPDF_InitLibrary);
+    CHK(FPDF_InitLibraryWithConfig);
     CHK(FPDF_DestroyLibrary);
     CHK(FPDF_SetSandBoxPolicy);
     CHK(FPDF_LoadDocument);
index 8379226..9d199a1 100644 (file)
@@ -124,9 +124,33 @@ extern "C" {
 // Return value:
 //          None.
 // Comments:
+//          Convenience function to call FPDF_InitLibraryWithConfig() for
+//          backwards comatibility purposes.
+DLLEXPORT void STDCALL FPDF_InitLibrary();
+
+// Process-wide options for initializing library.
+typedef struct FPDF_LIBRARY_CONFIG_ {
+  // Version number of the interface. Currently must be 1.
+  int version;
+
+  // Array of paths to scan in place of the defaults when using built-in
+  // FXGE font loading code. The array is terminated by a NULL pointer.
+  // The Array may be NULL itself to use the default paths. May be ignored
+  // entirely depending upon the platform.
+  const char** m_pUserFontPaths;
+} FPDF_LIBRARY_CONFIG;
+
+// Function: FPDF_InitLibraryWithConfig
+//          Initialize the FPDFSDK library
+// Parameters:
+//          cfg - configuration information as above.
+// Return value:
+//          None.
+// Comments:
 //          You have to call this function before you can call any PDF
 //          processing functions.
-DLLEXPORT void STDCALL FPDF_InitLibrary();
+DLLEXPORT void STDCALL FPDF_InitLibraryWithConfig(
+    const FPDF_LIBRARY_CONFIG* config);
 
 // Function: FPDF_DestroyLibary
 //          Release all resources allocated by the FPDFSDK library.
index 0d76b63..5a171c3 100644 (file)
@@ -46,6 +46,7 @@ struct Options {
   std::string scale_factor_as_string;
   std::string exe_path;
   std::string bin_directory;
+  std::string font_directory;
 };
 
 // Reads the entire contents of a file into a newly malloc'd buffer.
@@ -347,7 +348,15 @@ bool ParseCommandLine(const std::vector<std::string>& args,
         return false;
       }
       options->output_format = OUTPUT_PNG;
+    } else if (cur_arg.size() > 11 &&
+               cur_arg.compare(0, 11, "--font-dir=") == 0) {
+      if (!options->font_directory.empty()) {
+        fprintf(stderr, "Duplicate --font-dir argument\n");
+        return false;
+      }
+      options->font_directory = cur_arg.substr(11);
     }
+
 #ifdef _WIN32
     else if (cur_arg == "--emf") {
       if (options->output_format != OUTPUT_NONE) {
@@ -560,8 +569,9 @@ void RenderPdf(const std::string& name, const char* pBuf, size_t len,
 
 static const char usage_string[] =
     "Usage: pdfium_test [OPTION] [FILE]...\n"
-    "  --bin-dir=<path> - override path to v8 external data\n"
-    "  --scale=<number> - scale output size by number (e.g. 0.5)\n"
+    "  --bin-dir=<path>  - override path to v8 external data\n"
+    "  --font-dir=<path> - override path to external fonts\n"
+    "  --scale=<number>  - scale output size by number (e.g. 0.5)\n"
 #ifdef _WIN32
     "  --bmp - write page images <pdf-name>.<page-number>.bmp\n"
     "  --emf - write page meta files <pdf-name>.<page-number>.emf\n"
@@ -599,7 +609,17 @@ int main(int argc, const char* argv[]) {
   v8::V8::SetSnapshotDataBlob(&snapshot);
 #endif  // V8_USE_EXTERNAL_STARTUP_DATA
 
-  FPDF_InitLibrary();
+  if (!options.font_directory.empty()) {
+    const char* path_array[2];
+    path_array[0] = options.font_directory.c_str();
+    path_array[1] = nullptr;
+    FPDF_LIBRARY_CONFIG config;
+    config.version = 1;
+    config.m_pUserFontPaths = path_array;
+    FPDF_InitLibraryWithConfig(&config);
+  } else {
+    FPDF_InitLibrary();
+  }
 
   UNSUPPORT_INFO unsuppored_info;
   memset(&unsuppored_info, '\0', sizeof(unsuppored_info));
index 28616fb..d33a149 100755 (executable)
@@ -21,13 +21,14 @@ import suppressor
 #   c_dir - "path/to/a/b/c"
 
 def test_one_file(input_filename, source_dir, working_dir,
-                  pdfium_test_path, image_differ):
+                  pdfium_test_path, font_dir, image_differ):
   input_path = os.path.join(source_dir, input_filename)
   pdf_path = os.path.join(working_dir, input_filename)
   try:
     shutil.copyfile(input_path, pdf_path)
     sys.stdout.flush()
-    subprocess.check_call([pdfium_test_path, '--png', pdf_path])
+    subprocess.check_call([pdfium_test_path, '--font-dir=' + font_dir,
+                           '--png', pdf_path])
   except subprocess.CalledProcessError as e:
     print "FAILURE: " + input_filename + "; " + str(e)
     return False
@@ -57,6 +58,7 @@ def main():
   failures = []
   surprises = []
   walk_from_dir = finder.TestingDir('corpus');
+  font_dir = os.path.join(walk_from_dir, 'fonts');
   input_file_re = re.compile('^[a-zA-Z0-9_.]+[.]pdf$')
   for source_dir, _, filename_list in os.walk(walk_from_dir):
     for input_filename in filename_list:
@@ -64,7 +66,7 @@ def main():
          input_path = os.path.join(source_dir, input_filename)
          if os.path.isfile(input_path):
            result = test_one_file(input_filename, source_dir, working_dir,
-                                  pdfium_test_path, image_differ)
+                                  pdfium_test_path, font_dir, image_differ)
            if test_suppressor.IsSuppressed(input_filename):
              if result:
                surprises.append(input_path)