From 92e2276a8be492fd2be8e44a5d62e8a5879644d8 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Mon, 10 Jul 2017 15:14:26 -0400 Subject: Move core/fxge/ge to core/fxge. This brings the cpp and h files together and removes the redundant ge/ path. Change-Id: I36594b8ae719d362768ba4c2e4ce173e287363eb Reviewed-on: https://pdfium-review.googlesource.com/7452 Commit-Queue: dsinclair Reviewed-by: Tom Sepez --- BUILD.gn | 48 +- core/fxge/agg/fx_agg_driver.cpp | 2 +- core/fxge/apple/fx_apple_platform.cpp | 4 +- core/fxge/apple/fx_mac_imp.cpp | 2 +- core/fxge/apple/fx_quartz_device.cpp | 2 +- core/fxge/cfx_cliprgn.cpp | 106 +++ core/fxge/cfx_cliprgn.h | 42 ++ core/fxge/cfx_facecache.cpp | 401 +++++++++++ core/fxge/cfx_folderfontinfo.cpp | 379 ++++++++++ core/fxge/cfx_folderfontinfo.h | 69 ++ core/fxge/cfx_font.cpp | 657 +++++++++++++++++ core/fxge/cfx_fontcache.cpp | 70 ++ core/fxge/cfx_fontmapper.cpp | 817 +++++++++++++++++++++ core/fxge/cfx_fontmgr.cpp | 259 +++++++ core/fxge/cfx_gemodule.cpp | 54 ++ core/fxge/cfx_graphstate.cpp | 61 ++ core/fxge/cfx_graphstatedata.cpp | 52 ++ core/fxge/cfx_pathdata.cpp | 487 +++++++++++++ core/fxge/cfx_renderdevice.cpp | 1135 ++++++++++++++++++++++++++++++ core/fxge/cfx_substfont.cpp | 19 + core/fxge/cfx_unicodeencoding.cpp | 34 + core/fxge/cfx_unicodeencodingex.cpp | 103 +++ core/fxge/cttfontdesc.cpp | 38 + core/fxge/cttfontdesc.h | 40 ++ core/fxge/dib/cfx_bitmapcomposer.cpp | 2 +- core/fxge/dib/cfx_dibitmap.cpp | 2 +- core/fxge/dib/cfx_dibsource.cpp | 2 +- core/fxge/dib/cfx_imagerenderer.cpp | 2 +- core/fxge/fx_ge_fontmap.cpp | 93 +++ core/fxge/fx_ge_linux.cpp | 166 +++++ core/fxge/fx_ge_text.cpp | 121 ++++ core/fxge/fx_ge_text_embeddertest.cpp | 18 + core/fxge/fx_text_int.h | 31 + core/fxge/ge/cfx_cliprgn.cpp | 106 --- core/fxge/ge/cfx_cliprgn.h | 42 -- core/fxge/ge/cfx_facecache.cpp | 402 ----------- core/fxge/ge/cfx_folderfontinfo.cpp | 379 ---------- core/fxge/ge/cfx_folderfontinfo.h | 69 -- core/fxge/ge/cfx_font.cpp | 658 ----------------- core/fxge/ge/cfx_fontcache.cpp | 70 -- core/fxge/ge/cfx_fontmapper.cpp | 817 --------------------- core/fxge/ge/cfx_fontmgr.cpp | 259 ------- core/fxge/ge/cfx_gemodule.cpp | 54 -- core/fxge/ge/cfx_graphstate.cpp | 61 -- core/fxge/ge/cfx_graphstatedata.cpp | 52 -- core/fxge/ge/cfx_pathdata.cpp | 487 ------------- core/fxge/ge/cfx_renderdevice.cpp | 1135 ------------------------------ core/fxge/ge/cfx_substfont.cpp | 19 - core/fxge/ge/cfx_unicodeencoding.cpp | 34 - core/fxge/ge/cfx_unicodeencodingex.cpp | 103 --- core/fxge/ge/cttfontdesc.cpp | 38 - core/fxge/ge/cttfontdesc.h | 40 -- core/fxge/ge/fx_ge_fontmap.cpp | 93 --- core/fxge/ge/fx_ge_linux.cpp | 166 ----- core/fxge/ge/fx_ge_text.cpp | 121 ---- core/fxge/ge/fx_ge_text_embeddertest.cpp | 18 - core/fxge/ge/fx_text_int.h | 31 - core/fxge/skia/fx_skia_device.cpp | 2 +- core/fxge/win32/cfx_psrenderer.cpp | 2 +- core/fxge/win32/fx_win32_device.cpp | 4 +- core/fxge/win32/fx_win32_dwrite.cpp | 2 +- core/fxge/win32/fx_win32_print.cpp | 2 +- 62 files changed, 5291 insertions(+), 5293 deletions(-) create mode 100644 core/fxge/cfx_cliprgn.cpp create mode 100644 core/fxge/cfx_cliprgn.h create mode 100644 core/fxge/cfx_facecache.cpp create mode 100644 core/fxge/cfx_folderfontinfo.cpp create mode 100644 core/fxge/cfx_folderfontinfo.h create mode 100644 core/fxge/cfx_font.cpp create mode 100644 core/fxge/cfx_fontcache.cpp create mode 100644 core/fxge/cfx_fontmapper.cpp create mode 100644 core/fxge/cfx_fontmgr.cpp create mode 100644 core/fxge/cfx_gemodule.cpp create mode 100644 core/fxge/cfx_graphstate.cpp create mode 100644 core/fxge/cfx_graphstatedata.cpp create mode 100644 core/fxge/cfx_pathdata.cpp create mode 100644 core/fxge/cfx_renderdevice.cpp create mode 100644 core/fxge/cfx_substfont.cpp create mode 100644 core/fxge/cfx_unicodeencoding.cpp create mode 100644 core/fxge/cfx_unicodeencodingex.cpp create mode 100644 core/fxge/cttfontdesc.cpp create mode 100644 core/fxge/cttfontdesc.h create mode 100644 core/fxge/fx_ge_fontmap.cpp create mode 100644 core/fxge/fx_ge_linux.cpp create mode 100644 core/fxge/fx_ge_text.cpp create mode 100644 core/fxge/fx_ge_text_embeddertest.cpp create mode 100644 core/fxge/fx_text_int.h delete mode 100644 core/fxge/ge/cfx_cliprgn.cpp delete mode 100644 core/fxge/ge/cfx_cliprgn.h delete mode 100644 core/fxge/ge/cfx_facecache.cpp delete mode 100644 core/fxge/ge/cfx_folderfontinfo.cpp delete mode 100644 core/fxge/ge/cfx_folderfontinfo.h delete mode 100644 core/fxge/ge/cfx_font.cpp delete mode 100644 core/fxge/ge/cfx_fontcache.cpp delete mode 100644 core/fxge/ge/cfx_fontmapper.cpp delete mode 100644 core/fxge/ge/cfx_fontmgr.cpp delete mode 100644 core/fxge/ge/cfx_gemodule.cpp delete mode 100644 core/fxge/ge/cfx_graphstate.cpp delete mode 100644 core/fxge/ge/cfx_graphstatedata.cpp delete mode 100644 core/fxge/ge/cfx_pathdata.cpp delete mode 100644 core/fxge/ge/cfx_renderdevice.cpp delete mode 100644 core/fxge/ge/cfx_substfont.cpp delete mode 100644 core/fxge/ge/cfx_unicodeencoding.cpp delete mode 100644 core/fxge/ge/cfx_unicodeencodingex.cpp delete mode 100644 core/fxge/ge/cttfontdesc.cpp delete mode 100644 core/fxge/ge/cttfontdesc.h delete mode 100644 core/fxge/ge/fx_ge_fontmap.cpp delete mode 100644 core/fxge/ge/fx_ge_linux.cpp delete mode 100644 core/fxge/ge/fx_ge_text.cpp delete mode 100644 core/fxge/ge/fx_ge_text_embeddertest.cpp delete mode 100644 core/fxge/ge/fx_text_int.h diff --git a/BUILD.gn b/BUILD.gn index e99cc86841..fff58b3afd 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -930,19 +930,37 @@ static_library("fxge") { "core/fxge/android/cfx_androidfontinfo.cpp", "core/fxge/android/cfx_androidfontinfo.h", "core/fxge/android/fx_android_imp.cpp", + "core/fxge/cfx_cliprgn.cpp", + "core/fxge/cfx_cliprgn.h", "core/fxge/cfx_defaultrenderdevice.h", + "core/fxge/cfx_facecache.cpp", "core/fxge/cfx_facecache.h", + "core/fxge/cfx_folderfontinfo.cpp", + "core/fxge/cfx_folderfontinfo.h", + "core/fxge/cfx_font.cpp", + "core/fxge/cfx_fontcache.cpp", "core/fxge/cfx_fontcache.h", + "core/fxge/cfx_fontmapper.cpp", "core/fxge/cfx_fontmapper.h", + "core/fxge/cfx_fontmgr.cpp", "core/fxge/cfx_fontmgr.h", + "core/fxge/cfx_gemodule.cpp", "core/fxge/cfx_gemodule.h", + "core/fxge/cfx_graphstate.cpp", "core/fxge/cfx_graphstate.h", + "core/fxge/cfx_graphstatedata.cpp", "core/fxge/cfx_graphstatedata.h", + "core/fxge/cfx_pathdata.cpp", "core/fxge/cfx_pathdata.h", + "core/fxge/cfx_renderdevice.cpp", "core/fxge/cfx_renderdevice.h", + "core/fxge/cfx_substfont.cpp", "core/fxge/cfx_substfont.h", + "core/fxge/cfx_unicodeencoding.cpp", "core/fxge/cfx_unicodeencoding.h", "core/fxge/cfx_windowsrenderdevice.h", + "core/fxge/cttfontdesc.cpp", + "core/fxge/cttfontdesc.h", "core/fxge/dib/cfx_bitmapcomposer.cpp", "core/fxge/dib/cfx_bitmapcomposer.h", "core/fxge/dib/cfx_bitmapstorer.cpp", @@ -988,28 +1006,10 @@ static_library("fxge") { "core/fxge/fx_dib.h", "core/fxge/fx_font.h", "core/fxge/fx_freetype.h", - "core/fxge/ge/cfx_cliprgn.cpp", - "core/fxge/ge/cfx_cliprgn.h", - "core/fxge/ge/cfx_facecache.cpp", - "core/fxge/ge/cfx_folderfontinfo.cpp", - "core/fxge/ge/cfx_folderfontinfo.h", - "core/fxge/ge/cfx_font.cpp", - "core/fxge/ge/cfx_fontcache.cpp", - "core/fxge/ge/cfx_fontmapper.cpp", - "core/fxge/ge/cfx_fontmgr.cpp", - "core/fxge/ge/cfx_gemodule.cpp", - "core/fxge/ge/cfx_graphstate.cpp", - "core/fxge/ge/cfx_graphstatedata.cpp", - "core/fxge/ge/cfx_pathdata.cpp", - "core/fxge/ge/cfx_renderdevice.cpp", - "core/fxge/ge/cfx_substfont.cpp", - "core/fxge/ge/cfx_unicodeencoding.cpp", - "core/fxge/ge/cttfontdesc.cpp", - "core/fxge/ge/cttfontdesc.h", - "core/fxge/ge/fx_ge_fontmap.cpp", - "core/fxge/ge/fx_ge_linux.cpp", - "core/fxge/ge/fx_ge_text.cpp", - "core/fxge/ge/fx_text_int.h", + "core/fxge/fx_ge_fontmap.cpp", + "core/fxge/fx_ge_linux.cpp", + "core/fxge/fx_ge_text.cpp", + "core/fxge/fx_text_int.h", "core/fxge/ifx_renderdevicedriver.cpp", "core/fxge/ifx_renderdevicedriver.h", "core/fxge/ifx_systemfontinfo.h", @@ -1029,8 +1029,8 @@ static_library("fxge") { if (pdf_enable_xfa) { sources += [ + "core/fxge/cfx_unicodeencodingex.cpp", "core/fxge/cfx_unicodeencodingex.h", - "core/fxge/ge/cfx_unicodeencodingex.cpp", ] } @@ -2000,7 +2000,7 @@ test("pdfium_embeddertests") { "core/fpdfapi/render/fpdf_render_loadimage_embeddertest.cpp", "core/fpdfapi/render/fpdf_render_pattern_embeddertest.cpp", "core/fxcodec/codec/fx_codec_embeddertest.cpp", - "core/fxge/ge/fx_ge_text_embeddertest.cpp", + "core/fxge/fx_ge_text_embeddertest.cpp", "fpdfsdk/fpdf_dataavail_embeddertest.cpp", "fpdfsdk/fpdf_flatten_embeddertest.cpp", "fpdfsdk/fpdf_structtree_embeddertest.cpp", diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp index 855ea2a04c..846920240e 100644 --- a/core/fxge/agg/fx_agg_driver.cpp +++ b/core/fxge/agg/fx_agg_driver.cpp @@ -10,12 +10,12 @@ #include #include "core/fxcodec/fx_codec.h" +#include "core/fxge/cfx_cliprgn.h" #include "core/fxge/cfx_defaultrenderdevice.h" #include "core/fxge/cfx_graphstatedata.h" #include "core/fxge/cfx_pathdata.h" #include "core/fxge/dib/cfx_imagerenderer.h" #include "core/fxge/dib/cfx_imagestretcher.h" -#include "core/fxge/ge/cfx_cliprgn.h" #include "third_party/agg23/agg_conv_dash.h" #include "third_party/agg23/agg_conv_stroke.h" #include "third_party/agg23/agg_curves.h" diff --git a/core/fxge/apple/fx_apple_platform.cpp b/core/fxge/apple/fx_apple_platform.cpp index 1a56b183cf..56b15b35d0 100644 --- a/core/fxge/apple/fx_apple_platform.cpp +++ b/core/fxge/apple/fx_apple_platform.cpp @@ -13,12 +13,12 @@ #endif #include "core/fxge/apple/apple_int.h" +#include "core/fxge/cfx_cliprgn.h" #include "core/fxge/cfx_facecache.h" #include "core/fxge/cfx_gemodule.h" #include "core/fxge/cfx_renderdevice.h" #include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/cfx_cliprgn.h" -#include "core/fxge/ge/fx_text_int.h" +#include "core/fxge/fx_text_int.h" #ifndef _SKIA_SUPPORT_ diff --git a/core/fxge/apple/fx_mac_imp.cpp b/core/fxge/apple/fx_mac_imp.cpp index ced08d2776..78fe16459c 100644 --- a/core/fxge/apple/fx_mac_imp.cpp +++ b/core/fxge/apple/fx_mac_imp.cpp @@ -9,8 +9,8 @@ #include "core/fxcrt/fx_codepage.h" #include "core/fxge/apple/apple_int.h" +#include "core/fxge/cfx_folderfontinfo.h" #include "core/fxge/cfx_gemodule.h" -#include "core/fxge/ge/cfx_folderfontinfo.h" #include "core/fxge/ifx_systemfontinfo.h" #include "third_party/base/ptr_util.h" diff --git a/core/fxge/apple/fx_quartz_device.cpp b/core/fxge/apple/fx_quartz_device.cpp index ad09f91f61..f92db2b30b 100644 --- a/core/fxge/apple/fx_quartz_device.cpp +++ b/core/fxge/apple/fx_quartz_device.cpp @@ -15,7 +15,7 @@ #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_renderdevice.h" #include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/fx_text_int.h" +#include "core/fxge/fx_text_int.h" #include "third_party/base/ptr_util.h" #include "core/fxge/apple/apple_int.h" diff --git a/core/fxge/cfx_cliprgn.cpp b/core/fxge/cfx_cliprgn.cpp new file mode 100644 index 0000000000..087c11089a --- /dev/null +++ b/core/fxge/cfx_cliprgn.cpp @@ -0,0 +1,106 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_cliprgn.h" + +#include + +#include "core/fxge/dib/cfx_dibitmap.h" +#include "third_party/base/logging.h" + +CFX_ClipRgn::CFX_ClipRgn(int width, int height) + : m_Type(RectI), m_Box(0, 0, width, height) {} + +CFX_ClipRgn::CFX_ClipRgn(const CFX_ClipRgn& src) { + m_Type = src.m_Type; + m_Box = src.m_Box; + m_Mask = src.m_Mask; +} + +CFX_ClipRgn::~CFX_ClipRgn() {} + +void CFX_ClipRgn::Reset(const FX_RECT& rect) { + m_Type = RectI; + m_Box = rect; + m_Mask = nullptr; +} + +void CFX_ClipRgn::IntersectRect(const FX_RECT& rect) { + if (m_Type == RectI) { + m_Box.Intersect(rect); + return; + } + if (m_Type == MaskF) { + IntersectMaskRect(rect, m_Box, m_Mask); + return; + } +} + +void CFX_ClipRgn::IntersectMaskRect(FX_RECT rect, + FX_RECT mask_rect, + const CFX_RetainPtr& pMask) { + m_Type = MaskF; + m_Box = rect; + m_Box.Intersect(mask_rect); + if (m_Box.IsEmpty()) { + m_Type = RectI; + return; + } + if (m_Box == mask_rect) { + m_Mask = pMask; + return; + } + CFX_RetainPtr pOldMask(pMask); + m_Mask = pdfium::MakeRetain(); + m_Mask->Create(m_Box.Width(), m_Box.Height(), FXDIB_8bppMask); + for (int row = m_Box.top; row < m_Box.bottom; row++) { + uint8_t* dest_scan = + m_Mask->GetBuffer() + m_Mask->GetPitch() * (row - m_Box.top); + uint8_t* src_scan = + pOldMask->GetBuffer() + pOldMask->GetPitch() * (row - mask_rect.top); + for (int col = m_Box.left; col < m_Box.right; col++) + dest_scan[col - m_Box.left] = src_scan[col - mask_rect.left]; + } +} + +void CFX_ClipRgn::IntersectMaskF(int left, + int top, + const CFX_RetainPtr& pMask) { + ASSERT(pMask->GetFormat() == FXDIB_8bppMask); + FX_RECT mask_box(left, top, left + pMask->GetWidth(), + top + pMask->GetHeight()); + if (m_Type == RectI) { + IntersectMaskRect(m_Box, mask_box, pMask); + return; + } + if (m_Type == MaskF) { + FX_RECT new_box = m_Box; + new_box.Intersect(mask_box); + if (new_box.IsEmpty()) { + m_Type = RectI; + m_Mask = nullptr; + m_Box = new_box; + return; + } + auto new_dib = pdfium::MakeRetain(); + new_dib->Create(new_box.Width(), new_box.Height(), FXDIB_8bppMask); + for (int row = new_box.top; row < new_box.bottom; row++) { + uint8_t* old_scan = + m_Mask->GetBuffer() + (row - m_Box.top) * m_Mask->GetPitch(); + uint8_t* mask_scan = pMask->GetBuffer() + (row - top) * pMask->GetPitch(); + uint8_t* new_scan = + new_dib->GetBuffer() + (row - new_box.top) * new_dib->GetPitch(); + for (int col = new_box.left; col < new_box.right; col++) { + new_scan[col - new_box.left] = + old_scan[col - m_Box.left] * mask_scan[col - left] / 255; + } + } + m_Box = new_box; + m_Mask = std::move(new_dib); + return; + } + NOTREACHED(); +} diff --git a/core/fxge/cfx_cliprgn.h b/core/fxge/cfx_cliprgn.h new file mode 100644 index 0000000000..866af9b205 --- /dev/null +++ b/core/fxge/cfx_cliprgn.h @@ -0,0 +1,42 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_CFX_CLIPRGN_H_ +#define CORE_FXGE_CFX_CLIPRGN_H_ + +#include "core/fxcrt/fx_coordinates.h" + +class CFX_DIBitmap; + +class CFX_ClipRgn { + public: + enum ClipType { RectI, MaskF }; + + CFX_ClipRgn(int device_width, int device_height); + CFX_ClipRgn(const CFX_ClipRgn& src); + ~CFX_ClipRgn(); + + ClipType GetType() const { return m_Type; } + const FX_RECT& GetBox() const { return m_Box; } + CFX_RetainPtr GetMask() const { return m_Mask; } + + void Reset(const FX_RECT& rect); + void IntersectRect(const FX_RECT& rect); + void IntersectMaskF(int left, + int top, + const CFX_RetainPtr& Mask); + + private: + void IntersectMaskRect(FX_RECT rect, + FX_RECT mask_box, + const CFX_RetainPtr& Mask); + + ClipType m_Type; + FX_RECT m_Box; + CFX_RetainPtr m_Mask; +}; + +#endif // CORE_FXGE_CFX_CLIPRGN_H_ diff --git a/core/fxge/cfx_facecache.cpp b/core/fxge/cfx_facecache.cpp new file mode 100644 index 0000000000..eac28074fc --- /dev/null +++ b/core/fxge/cfx_facecache.cpp @@ -0,0 +1,401 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_facecache.h" + +#include +#include +#include +#include + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_fontmgr.h" +#include "core/fxge/cfx_gemodule.h" +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/cfx_substfont.h" +#include "core/fxge/fx_freetype.h" +#include "core/fxge/fx_text_int.h" +#include "third_party/base/numerics/safe_math.h" +#include "third_party/base/ptr_util.h" + +#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ +#include "third_party/skia/include/core/SkStream.h" +#include "third_party/skia/include/core/SkTypeface.h" + +#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ +#include "third_party/skia/include/ports/SkFontMgr.h" +#include "third_party/skia/include/ports/SkFontMgr_empty.h" +#endif +#endif + +namespace { + +constexpr uint32_t kInvalidGlyphIndex = static_cast(-1); + +constexpr int kMinPixel = 0; +constexpr int kMaxPixel = 255; + +constexpr int kMaxGlyphDimension = 2048; + +void ContrastAdjust(uint8_t* pDataIn, + uint8_t* pDataOut, + int nWidth, + int nHeight, + int nSrcRowBytes, + int nDstRowBytes) { + int max = kMinPixel; + int min = kMaxPixel; + for (int row = 0; row < nHeight; row++) { + uint8_t* pRow = pDataIn + row * nSrcRowBytes; + for (int col = 0; col < nWidth; col++) { + int val = pRow[col]; + max = std::max(val, max); + min = std::min(val, min); + } + } + int diff = max - min; + if (diff == kMinPixel || diff == kMaxPixel) { + int rowbytes = std::min(abs(nSrcRowBytes), nDstRowBytes); + for (int row = 0; row < nHeight; row++) { + memcpy(pDataOut + row * nDstRowBytes, pDataIn + row * nSrcRowBytes, + rowbytes); + } + return; + } + float rate = 255.f / diff; + for (int row = 0; row < nHeight; row++) { + uint8_t* pSrcRow = pDataIn + row * nSrcRowBytes; + uint8_t* pDstRow = pDataOut + row * nDstRowBytes; + for (int col = 0; col < nWidth; col++) { + int val = static_cast((pSrcRow[col] - min) * rate + 0.5); + pDstRow[col] = + static_cast(pdfium::clamp(val, kMinPixel, kMaxPixel)); + } + } +} + +} // namespace + +CFX_FaceCache::CFX_FaceCache(FXFT_Face face) + : m_Face(face) +#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ + , + m_pTypeface(nullptr) +#endif +{ +} + +CFX_FaceCache::~CFX_FaceCache() {} + +std::unique_ptr CFX_FaceCache::RenderGlyph( + const CFX_Font* pFont, + uint32_t glyph_index, + bool bFontStyle, + const CFX_Matrix* pMatrix, + int dest_width, + int anti_alias) { + if (!m_Face) + return nullptr; + + FXFT_Matrix ft_matrix; + ft_matrix.xx = (signed long)(pMatrix->a / 64 * 65536); + ft_matrix.xy = (signed long)(pMatrix->c / 64 * 65536); + ft_matrix.yx = (signed long)(pMatrix->b / 64 * 65536); + ft_matrix.yy = (signed long)(pMatrix->d / 64 * 65536); + bool bUseCJKSubFont = false; + const CFX_SubstFont* pSubstFont = pFont->GetSubstFont(); + if (pSubstFont) { + bUseCJKSubFont = pSubstFont->m_bSubstCJK && bFontStyle; + int skew = 0; + if (bUseCJKSubFont) + skew = pSubstFont->m_bItalicCJK ? -15 : 0; + else + skew = pSubstFont->m_ItalicAngle; + if (skew) { + // |skew| is nonpositive so |-skew| is used as the index. We need to make + // sure |skew| != INT_MIN since -INT_MIN is undefined. + if (skew <= 0 && skew != std::numeric_limits::min() && + static_cast(-skew) < CFX_Font::kAngleSkewArraySize) { + skew = -CFX_Font::s_AngleSkew[-skew]; + } else { + skew = -58; + } + if (pFont->IsVertical()) + ft_matrix.yx += ft_matrix.yy * skew / 100; + else + ft_matrix.xy -= ft_matrix.xx * skew / 100; + } + if (pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { + pFont->AdjustMMParams(glyph_index, dest_width, + pFont->GetSubstFont()->m_Weight); + } + } + ScopedFontTransform scoped_transform(m_Face, &ft_matrix); + int load_flags = (m_Face->face_flags & FT_FACE_FLAG_SFNT) + ? FXFT_LOAD_NO_BITMAP + : (FXFT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); + int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); + if (error) { + // if an error is returned, try to reload glyphs without hinting. + if (load_flags & FT_LOAD_NO_HINTING || load_flags & FT_LOAD_NO_SCALE) + return nullptr; + + load_flags |= FT_LOAD_NO_HINTING; + error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); + + if (error) + return nullptr; + } + int weight = 0; + if (bUseCJKSubFont) + weight = pSubstFont->m_WeightCJK; + else + weight = pSubstFont ? pSubstFont->m_Weight : 0; + if (pSubstFont && !(pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && + weight > 400) { + uint32_t index = (weight - 400) / 10; + if (index >= CFX_Font::kWeightPowArraySize) + return nullptr; + pdfium::base::CheckedNumeric level = 0; + if (pSubstFont->m_Charset == FX_CHARSET_ShiftJIS) + level = CFX_Font::s_WeightPow_SHIFTJIS[index] * 2; + else + level = CFX_Font::s_WeightPow_11[index]; + + level = level * + (abs(static_cast(ft_matrix.xx)) + + abs(static_cast(ft_matrix.xy))) / + 36655; + FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), + level.ValueOrDefault(0)); + } + FXFT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(), + FT_LCD_FILTER_DEFAULT); + error = FXFT_Render_Glyph(m_Face, anti_alias); + if (error) + return nullptr; + int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(m_Face)); + int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(m_Face)); + if (bmwidth > kMaxGlyphDimension || bmheight > kMaxGlyphDimension) + return nullptr; + int dib_width = bmwidth; + auto pGlyphBitmap = pdfium::MakeUnique(); + pGlyphBitmap->m_pBitmap->Create( + dib_width, bmheight, + anti_alias == FXFT_RENDER_MODE_MONO ? FXDIB_1bppMask : FXDIB_8bppMask); + pGlyphBitmap->m_Left = FXFT_Get_Glyph_BitmapLeft(m_Face); + pGlyphBitmap->m_Top = FXFT_Get_Glyph_BitmapTop(m_Face); + int dest_pitch = pGlyphBitmap->m_pBitmap->GetPitch(); + int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(m_Face)); + uint8_t* pDestBuf = pGlyphBitmap->m_pBitmap->GetBuffer(); + uint8_t* pSrcBuf = + (uint8_t*)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(m_Face)); + if (anti_alias != FXFT_RENDER_MODE_MONO && + FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == + FXFT_PIXEL_MODE_MONO) { + int bytes = anti_alias == FXFT_RENDER_MODE_LCD ? 3 : 1; + for (int i = 0; i < bmheight; i++) { + for (int n = 0; n < bmwidth; n++) { + uint8_t data = + (pSrcBuf[i * src_pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0; + for (int b = 0; b < bytes; b++) + pDestBuf[i * dest_pitch + n * bytes + b] = data; + } + } + } else { + memset(pDestBuf, 0, dest_pitch * bmheight); + if (anti_alias == FXFT_RENDER_MODE_MONO && + FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == + FXFT_PIXEL_MODE_MONO) { + int rowbytes = abs(src_pitch) > dest_pitch ? dest_pitch : abs(src_pitch); + for (int row = 0; row < bmheight; row++) { + memcpy(pDestBuf + row * dest_pitch, pSrcBuf + row * src_pitch, + rowbytes); + } + } else { + ContrastAdjust(pSrcBuf, pDestBuf, bmwidth, bmheight, src_pitch, + dest_pitch); + } + } + return pGlyphBitmap; +} + +const CFX_PathData* CFX_FaceCache::LoadGlyphPath(const CFX_Font* pFont, + uint32_t glyph_index, + int dest_width) { + if (!m_Face || glyph_index == kInvalidGlyphIndex || dest_width < 0) + return nullptr; + + uint32_t key = glyph_index; + auto* pSubstFont = pFont->GetSubstFont(); + if (pSubstFont) { + if (pSubstFont->m_Weight < 0 || pSubstFont->m_ItalicAngle < 0) + return nullptr; + uint32_t weight = static_cast(pSubstFont->m_Weight); + uint32_t angle = static_cast(pSubstFont->m_ItalicAngle); + uint32_t key_modifier = (weight / 16) << 15; + key_modifier += (angle / 2) << 21; + key_modifier += (static_cast(dest_width) / 16) << 25; + if (pFont->IsVertical()) + key_modifier += 1U << 31; + key += key_modifier; + } + auto it = m_PathMap.find(key); + if (it != m_PathMap.end()) + return it->second.get(); + + CFX_PathData* pGlyphPath = pFont->LoadGlyphPathImpl(glyph_index, dest_width); + m_PathMap[key] = std::unique_ptr(pGlyphPath); + return pGlyphPath; +} + +const CFX_GlyphBitmap* CFX_FaceCache::LoadGlyphBitmap(const CFX_Font* pFont, + uint32_t glyph_index, + bool bFontStyle, + const CFX_Matrix* pMatrix, + int dest_width, + int anti_alias, + int& text_flags) { + if (glyph_index == kInvalidGlyphIndex) + return nullptr; + + CFX_UniqueKeyGen keygen; + int nMatrixA = static_cast(pMatrix->a * 10000); + int nMatrixB = static_cast(pMatrix->b * 10000); + int nMatrixC = static_cast(pMatrix->c * 10000); + int nMatrixD = static_cast(pMatrix->d * 10000); +#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ + if (pFont->GetSubstFont()) { + keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); + } else { + keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias); + } +#else + if (text_flags & FXTEXT_NO_NATIVETEXT) { + if (pFont->GetSubstFont()) { + keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, + pFont->IsVertical()); + } else { + keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias); + } + } else { + if (pFont->GetSubstFont()) { + keygen.Generate(10, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical(), + 3); + } else { + keygen.Generate(7, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias, 3); + } + } +#endif + CFX_ByteString FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); +#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_ || \ + defined _SKIA_SUPPORT_PATHS_ + return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, + bFontStyle, dest_width, anti_alias); +#else + if (text_flags & FXTEXT_NO_NATIVETEXT) { + return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, + bFontStyle, dest_width, anti_alias); + } + std::unique_ptr pGlyphBitmap; + auto it = m_SizeMap.find(FaceGlyphsKey); + if (it != m_SizeMap.end()) { + CFX_SizeGlyphCache* pSizeCache = it->second.get(); + auto it2 = pSizeCache->m_GlyphMap.find(glyph_index); + if (it2 != pSizeCache->m_GlyphMap.end()) + return it2->second.get(); + + pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, + dest_width, anti_alias); + if (pGlyphBitmap) { + CFX_GlyphBitmap* pResult = pGlyphBitmap.get(); + pSizeCache->m_GlyphMap[glyph_index] = std::move(pGlyphBitmap); + return pResult; + } + } else { + pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, + dest_width, anti_alias); + if (pGlyphBitmap) { + auto pNewCache = pdfium::MakeUnique(); + CFX_SizeGlyphCache* pSizeCache = pNewCache.get(); + m_SizeMap[FaceGlyphsKey] = std::move(pNewCache); + CFX_GlyphBitmap* pResult = pGlyphBitmap.get(); + pSizeCache->m_GlyphMap[glyph_index] = std::move(pGlyphBitmap); + return pResult; + } + } + if (pFont->GetSubstFont()) { + keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias, pFont->GetSubstFont()->m_Weight, + pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); + } else { + keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, + anti_alias); + } + CFX_ByteString FaceGlyphsKey2(keygen.m_Key, keygen.m_KeyLen); + text_flags |= FXTEXT_NO_NATIVETEXT; + return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey2, glyph_index, + bFontStyle, dest_width, anti_alias); +#endif +} + +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ +CFX_TypeFace* CFX_FaceCache::GetDeviceCache(const CFX_Font* pFont) { + if (!m_pTypeface) { + m_pTypeface = SkTypeface::MakeFromStream( + new SkMemoryStream(pFont->GetFontData(), pFont->GetSize())); + } +#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ + if (!m_pTypeface) { + sk_sp customMgr(SkFontMgr_New_Custom_Empty()); + m_pTypeface.reset(customMgr->createFromStream( + new SkMemoryStream(pFont->GetFontData(), pFont->GetSize()))); + } +#endif + return m_pTypeface.get(); +} +#endif + +#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ +void CFX_FaceCache::InitPlatform() {} +#endif + +CFX_GlyphBitmap* CFX_FaceCache::LookUpGlyphBitmap( + const CFX_Font* pFont, + const CFX_Matrix* pMatrix, + const CFX_ByteString& FaceGlyphsKey, + uint32_t glyph_index, + bool bFontStyle, + int dest_width, + int anti_alias) { + CFX_SizeGlyphCache* pSizeCache; + auto it = m_SizeMap.find(FaceGlyphsKey); + if (it == m_SizeMap.end()) { + auto pNewCache = pdfium::MakeUnique(); + pSizeCache = pNewCache.get(); + m_SizeMap[FaceGlyphsKey] = std::move(pNewCache); + } else { + pSizeCache = it->second.get(); + } + auto it2 = pSizeCache->m_GlyphMap.find(glyph_index); + if (it2 != pSizeCache->m_GlyphMap.end()) + return it2->second.get(); + + std::unique_ptr pGlyphBitmap = RenderGlyph( + pFont, glyph_index, bFontStyle, pMatrix, dest_width, anti_alias); + CFX_GlyphBitmap* pResult = pGlyphBitmap.get(); + pSizeCache->m_GlyphMap[glyph_index] = std::move(pGlyphBitmap); + return pResult; +} diff --git a/core/fxge/cfx_folderfontinfo.cpp b/core/fxge/cfx_folderfontinfo.cpp new file mode 100644 index 0000000000..12e7dd25fc --- /dev/null +++ b/core/fxge/cfx_folderfontinfo.cpp @@ -0,0 +1,379 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_folderfontinfo.h" + +#include +#include + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_fontmapper.h" +#include "core/fxge/fx_font.h" +#include "third_party/base/ptr_util.h" +#include "third_party/base/stl_util.h" + +namespace { + +const struct { + const char* m_pName; + const 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"}, +}; + +CFX_ByteString FPDF_ReadStringFromFile(FILE* pFile, uint32_t size) { + CFX_ByteString buffer; + if (!fread(buffer.GetBuffer(size), size, 1, pFile)) + return CFX_ByteString(); + buffer.ReleaseBuffer(size); + return buffer; +} + +CFX_ByteString FPDF_LoadTableFromTT(FILE* pFile, + const uint8_t* pTables, + uint32_t nTables, + uint32_t tag) { + for (uint32_t i = 0; i < nTables; i++) { + const uint8_t* p = pTables + i * 16; + if (GET_TT_LONG(p) == tag) { + uint32_t offset = GET_TT_LONG(p + 8); + uint32_t size = GET_TT_LONG(p + 12); + fseek(pFile, offset, SEEK_SET); + return FPDF_ReadStringFromFile(pFile, size); + } + } + return CFX_ByteString(); +} + +uint32_t GetCharset(int charset) { + switch (charset) { + case FX_CHARSET_ShiftJIS: + return CHARSET_FLAG_SHIFTJIS; + case FX_CHARSET_ChineseSimplified: + return CHARSET_FLAG_GB; + case FX_CHARSET_ChineseTraditional: + return CHARSET_FLAG_BIG5; + case FX_CHARSET_Hangul: + return CHARSET_FLAG_KOREAN; + case FX_CHARSET_Symbol: + return CHARSET_FLAG_SYMBOL; + case FX_CHARSET_ANSI: + return CHARSET_FLAG_ANSI; + default: + break; + } + return 0; +} + +int32_t GetSimilarValue(int weight, + bool bItalic, + int pitch_family, + uint32_t 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; +} + +} // namespace + +CFX_FolderFontInfo::CFX_FolderFontInfo() {} + +CFX_FolderFontInfo::~CFX_FolderFontInfo() {} + +void CFX_FolderFontInfo::AddPath(const CFX_ByteString& path) { + m_PathList.push_back(path); +} + +bool CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) { + m_pMapper = pMapper; + for (const auto& path : m_PathList) + ScanPath(path); + return true; +} + +void CFX_FolderFontInfo::ScanPath(const CFX_ByteString& path) { + FX_FileHandle* handle = FX_OpenFolder(path.c_str()); + if (!handle) + return; + + CFX_ByteString filename; + bool bFolder; + while (FX_GetNextFile(handle, &filename, &bFolder)) { + if (bFolder) { + if (filename == "." || filename == "..") + continue; + } else { + CFX_ByteString ext = filename.Right(4); + ext.MakeUpper(); + if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") + continue; + } + + CFX_ByteString fullpath = path; +#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ + fullpath += "\\"; +#else + fullpath += "/"; +#endif + + fullpath += filename; + bFolder ? ScanPath(fullpath) : ScanFile(fullpath); + } + FX_CloseFolder(handle); +} + +void CFX_FolderFontInfo::ScanFile(const CFX_ByteString& path) { + FILE* pFile = fopen(path.c_str(), "rb"); + if (!pFile) + return; + + fseek(pFile, 0, SEEK_END); + + uint32_t filesize = ftell(pFile); + uint8_t buffer[16]; + fseek(pFile, 0, SEEK_SET); + + size_t readCnt = fread(buffer, 12, 1, pFile); + if (readCnt != 1) { + fclose(pFile); + return; + } + + if (GET_TT_LONG(buffer) == kTableTTCF) { + uint32_t nFaces = GET_TT_LONG(buffer + 8); + if (nFaces > std::numeric_limits::max() / 4) { + fclose(pFile); + return; + } + uint32_t face_bytes = nFaces * 4; + uint8_t* offsets = FX_Alloc(uint8_t, face_bytes); + readCnt = fread(offsets, 1, face_bytes, pFile); + if (readCnt != face_bytes) { + FX_Free(offsets); + fclose(pFile); + return; + } + for (uint32_t i = 0; i < nFaces; i++) { + uint8_t* p = offsets + i * 4; + ReportFace(path, pFile, filesize, GET_TT_LONG(p)); + } + FX_Free(offsets); + } else { + ReportFace(path, pFile, filesize, 0); + } + fclose(pFile); +} + +void CFX_FolderFontInfo::ReportFace(const CFX_ByteString& path, + FILE* pFile, + uint32_t filesize, + uint32_t offset) { + fseek(pFile, offset, SEEK_SET); + char buffer[16]; + if (!fread(buffer, 12, 1, pFile)) + return; + + uint32_t nTables = GET_TT_SHORT(buffer + 4); + CFX_ByteString tables = FPDF_ReadStringFromFile(pFile, nTables * 16); + if (tables.IsEmpty()) + return; + + CFX_ByteString names = + FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x6e616d65); + if (names.IsEmpty()) + return; + + CFX_ByteString facename = + GetNameFromTT(names.raw_str(), names.GetLength(), 1); + if (facename.IsEmpty()) + return; + + CFX_ByteString style = GetNameFromTT(names.raw_str(), names.GetLength(), 2); + if (style != "Regular") + facename += " " + style; + + if (pdfium::ContainsKey(m_FontList, facename)) + return; + + auto pInfo = pdfium::MakeUnique(path, facename, tables, + offset, filesize); + CFX_ByteString os2 = + FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x4f532f32); + if (os2.GetLength() >= 86) { + const uint8_t* p = os2.raw_str() + 78; + uint32_t codepages = GET_TT_LONG(p); + if (codepages & (1 << 17)) { + m_pMapper->AddInstalledFont(facename, FX_CHARSET_ShiftJIS); + pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS; + } + if (codepages & (1 << 18)) { + m_pMapper->AddInstalledFont(facename, FX_CHARSET_ChineseSimplified); + pInfo->m_Charsets |= CHARSET_FLAG_GB; + } + if (codepages & (1 << 20)) { + m_pMapper->AddInstalledFont(facename, FX_CHARSET_ChineseTraditional); + pInfo->m_Charsets |= CHARSET_FLAG_BIG5; + } + if ((codepages & (1 << 19)) || (codepages & (1 << 21))) { + m_pMapper->AddInstalledFont(facename, FX_CHARSET_Hangul); + pInfo->m_Charsets |= CHARSET_FLAG_KOREAN; + } + if (codepages & (1 << 31)) { + m_pMapper->AddInstalledFont(facename, FX_CHARSET_Symbol); + pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL; + } + } + m_pMapper->AddInstalledFont(facename, FX_CHARSET_ANSI); + pInfo->m_Charsets |= CHARSET_FLAG_ANSI; + pInfo->m_Styles = 0; + if (style.Find("Bold") > -1) + pInfo->m_Styles |= FXFONT_BOLD; + if (style.Find("Italic") > -1 || style.Find("Oblique") > -1) + pInfo->m_Styles |= FXFONT_ITALIC; + if (facename.Find("Serif") > -1) + pInfo->m_Styles |= FXFONT_SERIF; + + m_FontList[facename] = std::move(pInfo); +} + +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; +} + +void* CFX_FolderFontInfo::FindFont(int weight, + bool bItalic, + int charset, + int pitch_family, + const char* family, + bool bMatchName) { + CFX_FontFaceInfo* pFind = nullptr; + if (charset == FX_CHARSET_ANSI && (pitch_family & FXFONT_FF_FIXEDPITCH)) + return GetFont("Courier New"); + + uint32_t 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.get(); + if (!(pFont->m_Charsets & charset_flag) && charset != FX_CHARSET_Default) + 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, + bool bItalic, + int charset, + int pitch_family, + const char* family, + int& iExact) { + return nullptr; +} + +#ifdef PDF_ENABLE_XFA +void* CFX_FolderFontInfo::MapFontByUnicode(uint32_t dwUnicode, + int weight, + bool bItalic, + int pitch_family) { + return nullptr; +} +#endif // PDF_ENABLE_XFA + +void* CFX_FolderFontInfo::GetFont(const char* face) { + auto it = m_FontList.find(face); + return it != m_FontList.end() ? it->second.get() : nullptr; +} + +uint32_t CFX_FolderFontInfo::GetFontData(void* hFont, + uint32_t table, + uint8_t* buffer, + uint32_t size) { + if (!hFont) + return 0; + + const CFX_FontFaceInfo* pFont = static_cast(hFont); + uint32_t datasize = 0; + uint32_t offset = 0; + if (table == 0) { + datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize; + } else if (table == kTableTTCF) { + datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0; + } else { + uint32_t nTables = pFont->m_FontTables.GetLength() / 16; + for (uint32_t i = 0; i < nTables; i++) { + const uint8_t* p = pFont->m_FontTables.raw_str() + i * 16; + if (GET_TT_LONG(p) == table) { + offset = GET_TT_LONG(p + 8); + datasize = GET_TT_LONG(p + 12); + } + } + } + + if (!datasize || size < datasize) + return datasize; + + FILE* pFile = fopen(pFont->m_FilePath.c_str(), "rb"); + if (!pFile) + return 0; + + if (fseek(pFile, offset, SEEK_SET) < 0 || + fread(buffer, datasize, 1, pFile) != 1) { + datasize = 0; + } + fclose(pFile); + return datasize; +} + +void CFX_FolderFontInfo::DeleteFont(void* hFont) {} + +bool CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString* name) { + if (!hFont) + return false; + *name = static_cast(hFont)->m_FaceName; + return true; +} + +bool CFX_FolderFontInfo::GetFontCharset(void* hFont, int* charset) { + return false; +} diff --git a/core/fxge/cfx_folderfontinfo.h b/core/fxge/cfx_folderfontinfo.h new file mode 100644 index 0000000000..82ed902b22 --- /dev/null +++ b/core/fxge/cfx_folderfontinfo.h @@ -0,0 +1,69 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_CFX_FOLDERFONTINFO_H_ +#define CORE_FXGE_CFX_FOLDERFONTINFO_H_ + +#include +#include +#include + +#include "core/fxcrt/cfx_unowned_ptr.h" +#include "core/fxge/cfx_fontmapper.h" +#include "core/fxge/fx_font.h" +#include "core/fxge/ifx_systemfontinfo.h" + +class CFX_FolderFontInfo : public IFX_SystemFontInfo { + public: + CFX_FolderFontInfo(); + ~CFX_FolderFontInfo() override; + + void AddPath(const CFX_ByteString& path); + + // IFX_SytemFontInfo: + bool EnumFontList(CFX_FontMapper* pMapper) override; + void* MapFont(int weight, + bool bItalic, + int charset, + int pitch_family, + const char* face, + int& bExact) override; +#ifdef PDF_ENABLE_XFA + void* MapFontByUnicode(uint32_t dwUnicode, + int weight, + bool bItalic, + int pitch_family) override; +#endif // PDF_ENABLE_XFA + void* GetFont(const char* face) override; + uint32_t GetFontData(void* hFont, + uint32_t table, + uint8_t* buffer, + uint32_t size) override; + void DeleteFont(void* hFont) override; + bool GetFaceName(void* hFont, CFX_ByteString* name) override; + bool GetFontCharset(void* hFont, int* charset) override; + + protected: + void ScanPath(const CFX_ByteString& path); + void ScanFile(const CFX_ByteString& path); + void ReportFace(const CFX_ByteString& path, + FILE* pFile, + uint32_t filesize, + uint32_t offset); + void* GetSubstFont(const CFX_ByteString& face); + void* FindFont(int weight, + bool bItalic, + int charset, + int pitch_family, + const char* family, + bool bMatchName); + + std::map> m_FontList; + std::vector m_PathList; + CFX_UnownedPtr m_pMapper; +}; + +#endif // CORE_FXGE_CFX_FOLDERFONTINFO_H_ diff --git a/core/fxge/cfx_font.cpp b/core/fxge/cfx_font.cpp new file mode 100644 index 0000000000..a8e271dd9a --- /dev/null +++ b/core/fxge/cfx_font.cpp @@ -0,0 +1,657 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/fx_font.h" + +#include +#include +#include +#include +#include + +#include "core/fpdfapi/font/cpdf_font.h" +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_facecache.h" +#include "core/fxge/cfx_fontcache.h" +#include "core/fxge/cfx_fontmgr.h" +#include "core/fxge/cfx_gemodule.h" +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/cfx_substfont.h" +#include "core/fxge/fx_freetype.h" +#include "core/fxge/fx_text_int.h" +#include "third_party/base/ptr_util.h" + +#define EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em) + +namespace { + +struct OUTLINE_PARAMS { + CFX_PathData* m_pPath; + int m_CurX; + int m_CurY; + float m_CoordUnit; +}; + +#ifdef PDF_ENABLE_XFA + +unsigned long FTStreamRead(FXFT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count) { + if (count == 0) + return 0; + + IFX_SeekableReadStream* pFile = + static_cast(stream->descriptor.pointer); + return pFile && pFile->ReadBlock(buffer, offset, count) ? count : 0; +} + +void FTStreamClose(FXFT_Stream stream) {} + +bool LoadFileImp(FXFT_Library library, + FXFT_Face* Face, + const CFX_RetainPtr& pFile, + int32_t faceIndex, + std::unique_ptr* stream) { + auto stream1 = pdfium::MakeUnique(); + stream1->base = nullptr; + stream1->size = static_cast(pFile->GetSize()); + stream1->pos = 0; + stream1->descriptor.pointer = static_cast(pFile.Get()); + stream1->close = FTStreamClose; + stream1->read = FTStreamRead; + FXFT_Open_Args args; + args.flags = FT_OPEN_STREAM; + args.stream = stream1.get(); + if (FXFT_Open_Face(library, &args, faceIndex, Face)) + return false; + if (stream) + *stream = std::move(stream1); + return true; +} +#endif // PDF_ENABLE_XFA + +FXFT_Face FT_LoadFont(const uint8_t* pData, int size) { + return CFX_GEModule::Get()->GetFontMgr()->GetFixedFace(pData, size, 0); +} + +void Outline_CheckEmptyContour(OUTLINE_PARAMS* param) { + std::vector& points = param->m_pPath->GetPoints(); + size_t size = points.size(); + + if (size >= 2 && points[size - 2].IsTypeAndOpen(FXPT_TYPE::MoveTo) && + points[size - 2].m_Point == points[size - 1].m_Point) { + size -= 2; + } + if (size >= 4 && points[size - 4].IsTypeAndOpen(FXPT_TYPE::MoveTo) && + points[size - 3].IsTypeAndOpen(FXPT_TYPE::BezierTo) && + points[size - 3].m_Point == points[size - 4].m_Point && + points[size - 2].m_Point == points[size - 4].m_Point && + points[size - 1].m_Point == points[size - 4].m_Point) { + size -= 4; + } + points.resize(size); +} + +int Outline_MoveTo(const FXFT_Vector* to, void* user) { + OUTLINE_PARAMS* param = static_cast(user); + + Outline_CheckEmptyContour(param); + + param->m_pPath->ClosePath(); + param->m_pPath->AppendPoint( + CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), + FXPT_TYPE::MoveTo, false); + + param->m_CurX = to->x; + param->m_CurY = to->y; + return 0; +} + +int Outline_LineTo(const FXFT_Vector* to, void* user) { + OUTLINE_PARAMS* param = static_cast(user); + + param->m_pPath->AppendPoint( + CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), + FXPT_TYPE::LineTo, false); + + param->m_CurX = to->x; + param->m_CurY = to->y; + return 0; +} + +int Outline_ConicTo(const FXFT_Vector* control, + const FXFT_Vector* to, + void* user) { + OUTLINE_PARAMS* param = static_cast(user); + + param->m_pPath->AppendPoint( + CFX_PointF((param->m_CurX + (control->x - param->m_CurX) * 2 / 3) / + param->m_CoordUnit, + (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) / + param->m_CoordUnit), + FXPT_TYPE::BezierTo, false); + + param->m_pPath->AppendPoint( + CFX_PointF((control->x + (to->x - control->x) / 3) / param->m_CoordUnit, + (control->y + (to->y - control->y) / 3) / param->m_CoordUnit), + FXPT_TYPE::BezierTo, false); + + param->m_pPath->AppendPoint( + CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), + FXPT_TYPE::BezierTo, false); + + param->m_CurX = to->x; + param->m_CurY = to->y; + return 0; +} + +int Outline_CubicTo(const FXFT_Vector* control1, + const FXFT_Vector* control2, + const FXFT_Vector* to, + void* user) { + OUTLINE_PARAMS* param = static_cast(user); + + param->m_pPath->AppendPoint(CFX_PointF(control1->x / param->m_CoordUnit, + control1->y / param->m_CoordUnit), + FXPT_TYPE::BezierTo, false); + + param->m_pPath->AppendPoint(CFX_PointF(control2->x / param->m_CoordUnit, + control2->y / param->m_CoordUnit), + FXPT_TYPE::BezierTo, false); + + param->m_pPath->AppendPoint( + CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), + FXPT_TYPE::BezierTo, false); + + param->m_CurX = to->x; + param->m_CurY = to->y; + return 0; +} + +} // namespace + +const char CFX_Font::s_AngleSkew[] = { + 0, 2, 3, 5, 7, 9, 11, 12, 14, 16, 18, 19, 21, 23, 25, + 27, 29, 31, 32, 34, 36, 38, 40, 42, 45, 47, 49, 51, 53, 55, +}; + +const uint8_t CFX_Font::s_WeightPow[] = { + 0, 3, 6, 7, 8, 9, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 36, 36, 37, + 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, + 42, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, + 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 50, + 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, +}; + +const uint8_t CFX_Font::s_WeightPow_11[] = { + 0, 4, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, 41, + 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, + 46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52, + 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55, + 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, +}; + +const uint8_t CFX_Font::s_WeightPow_SHIFTJIS[] = { + 0, 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 21, + 22, 24, 26, 28, 30, 32, 33, 35, 37, 39, 41, 43, 45, 48, 48, 48, 48, + 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, + 53, 53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, + 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58, + 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, +}; + +CFX_Font::CFX_Font() + : +#ifdef PDF_ENABLE_XFA + m_bShallowCopy(false), + m_pOwnedStream(nullptr), +#endif // PDF_ENABLE_XFA + m_Face(nullptr), + m_FaceCache(nullptr), + m_pFontData(nullptr), + m_pGsubData(nullptr), + m_dwSize(0), +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + m_pPlatformFont(nullptr), +#endif + m_bEmbedded(false), + m_bVertical(false) { +} + +#ifdef PDF_ENABLE_XFA +bool CFX_Font::LoadClone(const CFX_Font* pFont) { + if (!pFont) + return false; + + m_bShallowCopy = true; + if (pFont->m_pSubstFont) { + m_pSubstFont = pdfium::MakeUnique(); + m_pSubstFont->m_Charset = pFont->m_pSubstFont->m_Charset; + m_pSubstFont->m_SubstFlags = pFont->m_pSubstFont->m_SubstFlags; + m_pSubstFont->m_Weight = pFont->m_pSubstFont->m_Weight; + m_pSubstFont->m_Family = pFont->m_pSubstFont->m_Family; + m_pSubstFont->m_ItalicAngle = pFont->m_pSubstFont->m_ItalicAngle; + } + m_Face = pFont->m_Face; + m_bEmbedded = pFont->m_bEmbedded; + m_bVertical = pFont->m_bVertical; + m_dwSize = pFont->m_dwSize; + m_pFontData = pFont->m_pFontData; + m_pGsubData = pFont->m_pGsubData; +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + m_pPlatformFont = pFont->m_pPlatformFont; +#endif + m_pOwnedStream = pFont->m_pOwnedStream; + m_FaceCache = pFont->GetFaceCache(); + return true; +} + +void CFX_Font::SetFace(FXFT_Face face) { + ClearFaceCache(); + m_Face = face; +} + +#endif // PDF_ENABLE_XFA + +CFX_Font::~CFX_Font() { +#ifdef PDF_ENABLE_XFA + if (m_bShallowCopy) + return; +#endif // PDF_ENABLE_XFA + if (m_Face) { +#ifndef PDF_ENABLE_XFA + if (FXFT_Get_Face_External_Stream(m_Face)) { + FXFT_Clear_Face_External_Stream(m_Face); + } +#endif // PDF_ENABLE_XFA + DeleteFace(); + } +#ifdef PDF_ENABLE_XFA + delete m_pOwnedStream; +#endif // PDF_ENABLE_XFA + FX_Free(m_pGsubData); +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ && !defined _SKIA_SUPPORT_ + ReleasePlatformResource(); +#endif +} + +void CFX_Font::DeleteFace() { + ClearFaceCache(); + if (m_bEmbedded) + FXFT_Done_Face(m_Face); + else + CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face); + m_Face = nullptr; +} + +void CFX_Font::LoadSubst(const CFX_ByteString& face_name, + bool bTrueType, + uint32_t flags, + int weight, + int italic_angle, + int CharsetCP, + bool bVertical) { + m_bEmbedded = false; + m_bVertical = bVertical; + m_pSubstFont = pdfium::MakeUnique(); + m_Face = CFX_GEModule::Get()->GetFontMgr()->FindSubstFont( + face_name, bTrueType, flags, weight, italic_angle, CharsetCP, + m_pSubstFont.get()); + if (m_Face) { + m_pFontData = FXFT_Get_Face_Stream_Base(m_Face); + m_dwSize = FXFT_Get_Face_Stream_Size(m_Face); + } +} + +#ifdef PDF_ENABLE_XFA +bool CFX_Font::LoadFile(const CFX_RetainPtr& pFile, + int nFaceIndex) { + m_bEmbedded = false; + + CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr(); + pFontMgr->InitFTLibrary(); + + FXFT_Library library = pFontMgr->GetFTLibrary(); + std::unique_ptr stream; + if (!LoadFileImp(library, &m_Face, pFile, nFaceIndex, &stream)) + return false; + + m_pOwnedStream = stream.release(); + FXFT_Set_Pixel_Sizes(m_Face, 0, 64); + return true; +} +#endif // PDF_ENABLE_XFA + +int CFX_Font::GetGlyphWidth(uint32_t glyph_index) { + if (!m_Face) + return 0; + if (m_pSubstFont && (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM)) + AdjustMMParams(glyph_index, 0, 0); + int err = FXFT_Load_Glyph( + m_Face, glyph_index, + FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + if (err) + return 0; + + int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), + FXFT_Get_Glyph_HoriAdvance(m_Face)); + return width; +} + +bool CFX_Font::LoadEmbedded(const uint8_t* data, uint32_t size) { + std::vector temp(data, data + size); + m_pFontDataAllocation.swap(temp); + m_Face = FT_LoadFont(m_pFontDataAllocation.data(), size); + m_pFontData = m_pFontDataAllocation.data(); + m_bEmbedded = true; + m_dwSize = size; + return !!m_Face; +} + +bool CFX_Font::IsTTFont() const { + return m_Face && FXFT_Is_Face_TT_OT(m_Face) == FXFT_FACE_FLAG_SFNT; +} + +int CFX_Font::GetAscent() const { + if (!m_Face) + return 0; + + return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), + FXFT_Get_Face_Ascender(m_Face)); +} + +int CFX_Font::GetDescent() const { + if (!m_Face) + return 0; + + return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), + FXFT_Get_Face_Descender(m_Face)); +} + +bool CFX_Font::GetGlyphBBox(uint32_t glyph_index, FX_RECT& bbox) { + if (!m_Face) + return false; + + if (FXFT_Is_Face_Tricky(m_Face)) { + int error = FXFT_Set_Char_Size(m_Face, 0, 1000 * 64, 72, 72); + if (error) + return false; + + error = FXFT_Load_Glyph(m_Face, glyph_index, + FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + if (error) + return false; + + FXFT_BBox cbox; + FT_Glyph glyph; + error = FXFT_Get_Glyph(m_Face->glyph, &glyph); + if (error) + return false; + + FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox); + int pixel_size_x = m_Face->size->metrics.x_ppem, + pixel_size_y = m_Face->size->metrics.y_ppem; + if (pixel_size_x == 0 || pixel_size_y == 0) { + bbox.left = cbox.xMin; + bbox.right = cbox.xMax; + bbox.top = cbox.yMax; + bbox.bottom = cbox.yMin; + } else { + bbox.left = cbox.xMin * 1000 / pixel_size_x; + bbox.right = cbox.xMax * 1000 / pixel_size_x; + bbox.top = cbox.yMax * 1000 / pixel_size_y; + bbox.bottom = cbox.yMin * 1000 / pixel_size_y; + } + bbox.top = std::min(bbox.top, + static_cast(FXFT_Get_Face_Ascender(m_Face))); + bbox.bottom = std::max( + bbox.bottom, static_cast(FXFT_Get_Face_Descender(m_Face))); + FT_Done_Glyph(glyph); + return FXFT_Set_Pixel_Sizes(m_Face, 0, 64) == 0; + } + if (FXFT_Load_Glyph( + m_Face, glyph_index, + FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) { + return false; + } + int em = FXFT_Get_Face_UnitsPerEM(m_Face); + if (em == 0) { + bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face); + bbox.bottom = FXFT_Get_Glyph_HoriBearingY(m_Face); + bbox.top = bbox.bottom - FXFT_Get_Glyph_Height(m_Face); + bbox.right = bbox.left + FXFT_Get_Glyph_Width(m_Face); + } else { + bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face) * 1000 / em; + bbox.top = + (FXFT_Get_Glyph_HoriBearingY(m_Face) - FXFT_Get_Glyph_Height(m_Face)) * + 1000 / em; + bbox.right = + (FXFT_Get_Glyph_HoriBearingX(m_Face) + FXFT_Get_Glyph_Width(m_Face)) * + 1000 / em; + bbox.bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face)) * 1000 / em; + } + return true; +} + +bool CFX_Font::IsItalic() const { + if (!m_Face) + return false; + if (FXFT_Is_Face_Italic(m_Face) == FXFT_STYLE_FLAG_ITALIC) + return true; + + CFX_ByteString str(FXFT_Get_Face_Style_Name(m_Face)); + str.MakeLower(); + return str.Find("italic") != -1; +} + +bool CFX_Font::IsBold() const { + return m_Face && FXFT_Is_Face_Bold(m_Face) == FXFT_STYLE_FLAG_BOLD; +} + +bool CFX_Font::IsFixedWidth() const { + return m_Face && FXFT_Is_Face_fixedwidth(m_Face) != 0; +} + +CFX_ByteString CFX_Font::GetPsName() const { + if (!m_Face) + return CFX_ByteString(); + + CFX_ByteString psName = FXFT_Get_Postscript_Name(m_Face); + if (psName.IsEmpty()) + psName = "Untitled"; + return psName; +} + +CFX_ByteString CFX_Font::GetFamilyName() const { + if (!m_Face && !m_pSubstFont) + return CFX_ByteString(); + if (m_Face) + return CFX_ByteString(FXFT_Get_Face_Family_Name(m_Face)); + + return m_pSubstFont->m_Family; +} + +CFX_ByteString CFX_Font::GetFaceName() const { + if (!m_Face && !m_pSubstFont) + return CFX_ByteString(); + if (m_Face) { + CFX_ByteString style = CFX_ByteString(FXFT_Get_Face_Style_Name(m_Face)); + CFX_ByteString facename = GetFamilyName(); + if (facename.IsEmpty()) + facename = "Untitled"; + if (!style.IsEmpty() && style != "Regular") + facename += " " + style; + return facename; + } + return m_pSubstFont->m_Family; +} + +bool CFX_Font::GetBBox(FX_RECT& bbox) { + if (!m_Face) + return false; + + int em = FXFT_Get_Face_UnitsPerEM(m_Face); + if (em == 0) { + bbox.left = FXFT_Get_Face_xMin(m_Face); + bbox.bottom = FXFT_Get_Face_yMax(m_Face); + bbox.top = FXFT_Get_Face_yMin(m_Face); + bbox.right = FXFT_Get_Face_xMax(m_Face); + } else { + bbox.left = FXFT_Get_Face_xMin(m_Face) * 1000 / em; + bbox.top = FXFT_Get_Face_yMin(m_Face) * 1000 / em; + bbox.right = FXFT_Get_Face_xMax(m_Face) * 1000 / em; + bbox.bottom = FXFT_Get_Face_yMax(m_Face) * 1000 / em; + } + return true; +} + +CFX_FaceCache* CFX_Font::GetFaceCache() const { + if (!m_FaceCache) + m_FaceCache = CFX_GEModule::Get()->GetFontCache()->GetCachedFace(this); + return m_FaceCache.Get(); +} + +void CFX_Font::ClearFaceCache() { + if (!m_FaceCache) + return; + + m_FaceCache = nullptr; + CFX_GEModule::Get()->GetFontCache()->ReleaseCachedFace(this); +} + +void CFX_Font::AdjustMMParams(int glyph_index, + int dest_width, + int weight) const { + FXFT_MM_Var pMasters = nullptr; + FXFT_Get_MM_Var(m_Face, &pMasters); + if (!pMasters) + return; + + long coords[2]; + if (weight == 0) + coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536; + else + coords[0] = weight; + + if (dest_width == 0) { + coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; + } else { + int min_param = FXFT_Get_MM_Axis_Min(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; + int max_param = FXFT_Get_MM_Axis_Max(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; + coords[1] = min_param; + FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); + FXFT_Load_Glyph(m_Face, glyph_index, + FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + int min_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / + FXFT_Get_Face_UnitsPerEM(m_Face); + coords[1] = max_param; + FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); + FXFT_Load_Glyph(m_Face, glyph_index, + FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); + int max_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / + FXFT_Get_Face_UnitsPerEM(m_Face); + if (max_width == min_width) { + FXFT_Free(m_Face, pMasters); + return; + } + int param = min_param + (max_param - min_param) * (dest_width - min_width) / + (max_width - min_width); + coords[1] = param; + } + FXFT_Free(m_Face, pMasters); + FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); +} + +CFX_PathData* CFX_Font::LoadGlyphPathImpl(uint32_t glyph_index, + int dest_width) const { + if (!m_Face) + return nullptr; + FXFT_Set_Pixel_Sizes(m_Face, 0, 64); + FXFT_Matrix ft_matrix = {65536, 0, 0, 65536}; + if (m_pSubstFont) { + if (m_pSubstFont->m_ItalicAngle) { + int skew = m_pSubstFont->m_ItalicAngle; + // |skew| is nonpositive so |-skew| is used as the index. We need to make + // sure |skew| != INT_MIN since -INT_MIN is undefined. + if (skew <= 0 && skew != std::numeric_limits::min() && + static_cast(-skew) < kAngleSkewArraySize) { + skew = -s_AngleSkew[-skew]; + } else { + skew = -58; + } + if (m_bVertical) + ft_matrix.yx += ft_matrix.yy * skew / 100; + else + ft_matrix.xy -= ft_matrix.xx * skew / 100; + } + if (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) + AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight); + } + ScopedFontTransform scoped_transform(m_Face, &ft_matrix); + int load_flags = FXFT_LOAD_NO_BITMAP; + if (!(m_Face->face_flags & FT_FACE_FLAG_SFNT) || !FT_IS_TRICKY(m_Face)) + load_flags |= FT_LOAD_NO_HINTING; + if (FXFT_Load_Glyph(m_Face, glyph_index, load_flags)) + return nullptr; + if (m_pSubstFont && !(m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && + m_pSubstFont->m_Weight > 400) { + uint32_t index = (m_pSubstFont->m_Weight - 400) / 10; + index = std::min(index, static_cast(kWeightPowArraySize - 1)); + int level = 0; + if (m_pSubstFont->m_Charset == FX_CHARSET_ShiftJIS) + level = s_WeightPow_SHIFTJIS[index] * 2 * 65536 / 36655; + else + level = s_WeightPow[index] * 2; + FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level); + } + + FXFT_Outline_Funcs funcs; + funcs.move_to = Outline_MoveTo; + funcs.line_to = Outline_LineTo; + funcs.conic_to = Outline_ConicTo; + funcs.cubic_to = Outline_CubicTo; + funcs.shift = 0; + funcs.delta = 0; + + OUTLINE_PARAMS params; + auto pPath = pdfium::MakeUnique(); + params.m_pPath = pPath.get(); + params.m_CurX = params.m_CurY = 0; + params.m_CoordUnit = 64 * 64.0; + + FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms); + if (pPath->GetPoints().empty()) + return nullptr; + + Outline_CheckEmptyContour(¶ms); + pPath->ClosePath(); + + return pPath.release(); +} + +const CFX_GlyphBitmap* CFX_Font::LoadGlyphBitmap(uint32_t glyph_index, + bool bFontStyle, + const CFX_Matrix* pMatrix, + int dest_width, + int anti_alias, + int& text_flags) const { + return GetFaceCache()->LoadGlyphBitmap(this, glyph_index, bFontStyle, pMatrix, + dest_width, anti_alias, text_flags); +} + +const CFX_PathData* CFX_Font::LoadGlyphPath(uint32_t glyph_index, + int dest_width) const { + return GetFaceCache()->LoadGlyphPath(this, glyph_index, dest_width); +} + +#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ +CFX_TypeFace* CFX_Font::GetDeviceCache() const { + return GetFaceCache()->GetDeviceCache(this); +} +#endif diff --git a/core/fxge/cfx_fontcache.cpp b/core/fxge/cfx_fontcache.cpp new file mode 100644 index 0000000000..5ccac8cfbc --- /dev/null +++ b/core/fxge/cfx_fontcache.cpp @@ -0,0 +1,70 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_fontcache.h" + +#include +#include + +#include "core/fxge/cfx_facecache.h" +#include "core/fxge/fx_font.h" +#include "core/fxge/fx_freetype.h" +#include "third_party/base/ptr_util.h" + +CFX_FontCache::CountedFaceCache::CountedFaceCache() {} + +CFX_FontCache::CountedFaceCache::~CountedFaceCache() {} + +CFX_FontCache::CFX_FontCache() {} + +CFX_FontCache::~CFX_FontCache() { + ASSERT(m_ExtFaceMap.empty()); + ASSERT(m_FTFaceMap.empty()); +} + +CFX_FaceCache* CFX_FontCache::GetCachedFace(const CFX_Font* pFont) { + FXFT_Face face = pFont->GetFace(); + const bool bExternal = !face; + CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; + auto it = map.find(face); + if (it != map.end()) { + CountedFaceCache* counted_face_cache = it->second.get(); + counted_face_cache->m_nCount++; + return counted_face_cache->m_Obj.get(); + } + + auto counted_face_cache = pdfium::MakeUnique(); + counted_face_cache->m_nCount = 2; + auto new_cache = + pdfium::MakeUnique(bExternal ? nullptr : face); + CFX_FaceCache* face_cache = new_cache.get(); + counted_face_cache->m_Obj = std::move(new_cache); + map[face] = std::move(counted_face_cache); + return face_cache; +} + +#ifdef _SKIA_SUPPORT_ +CFX_TypeFace* CFX_FontCache::GetDeviceCache(const CFX_Font* pFont) { + return GetCachedFace(pFont)->GetDeviceCache(pFont); +} +#endif + +void CFX_FontCache::ReleaseCachedFace(const CFX_Font* pFont) { + FXFT_Face face = pFont->GetFace(); + const bool bExternal = !face; + CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; + + auto it = map.find(face); + if (it == map.end()) + return; + + CountedFaceCache* counted_face_cache = it->second.get(); + if (counted_face_cache->m_nCount > 2) { + counted_face_cache->m_nCount--; + } else { + map.erase(it); + } +} diff --git a/core/fxge/cfx_fontmapper.cpp b/core/fxge/cfx_fontmapper.cpp new file mode 100644 index 0000000000..5b4ceaac59 --- /dev/null +++ b/core/fxge/cfx_fontmapper.cpp @@ -0,0 +1,817 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_fontmapper.h" + +#include +#include +#include +#include +#include + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_substfont.h" +#include "core/fxge/fx_font.h" +#include "core/fxge/ifx_systemfontinfo.h" + +#include "third_party/base/stl_util.h" + +#define FX_FONT_STYLE_None 0x00 +#define FX_FONT_STYLE_Bold 0x01 +#define FX_FONT_STYLE_Italic 0x02 +#define FX_FONT_STYLE_BoldBold 0x04 + +namespace { + +const int kNumStandardFonts = 14; + +const char* const g_Base14FontNames[kNumStandardFonts] = { + "Courier", + "Courier-Bold", + "Courier-BoldOblique", + "Courier-Oblique", + "Helvetica", + "Helvetica-Bold", + "Helvetica-BoldOblique", + "Helvetica-Oblique", + "Times-Roman", + "Times-Bold", + "Times-BoldItalic", + "Times-Italic", + "Symbol", + "ZapfDingbats", +}; + +const struct AltFontName { + const char* m_pName; + int m_Index; +} g_AltFontNames[] = { + {"Arial", 4}, + {"Arial,Bold", 5}, + {"Arial,BoldItalic", 6}, + {"Arial,Italic", 7}, + {"Arial-Bold", 5}, + {"Arial-BoldItalic", 6}, + {"Arial-BoldItalicMT", 6}, + {"Arial-BoldMT", 5}, + {"Arial-Italic", 7}, + {"Arial-ItalicMT", 7}, + {"ArialBold", 5}, + {"ArialBoldItalic", 6}, + {"ArialItalic", 7}, + {"ArialMT", 4}, + {"ArialMT,Bold", 5}, + {"ArialMT,BoldItalic", 6}, + {"ArialMT,Italic", 7}, + {"ArialRoundedMTBold", 5}, + {"Courier", 0}, + {"Courier,Bold", 1}, + {"Courier,BoldItalic", 2}, + {"Courier,Italic", 3}, + {"Courier-Bold", 1}, + {"Courier-BoldOblique", 2}, + {"Courier-Oblique", 3}, + {"CourierBold", 1}, + {"CourierBoldItalic", 2}, + {"CourierItalic", 3}, + {"CourierNew", 0}, + {"CourierNew,Bold", 1}, + {"CourierNew,BoldItalic", 2}, + {"CourierNew,Italic", 3}, + {"CourierNew-Bold", 1}, + {"CourierNew-BoldItalic", 2}, + {"CourierNew-Italic", 3}, + {"CourierNewBold", 1}, + {"CourierNewBoldItalic", 2}, + {"CourierNewItalic", 3}, + {"CourierNewPS-BoldItalicMT", 2}, + {"CourierNewPS-BoldMT", 1}, + {"CourierNewPS-ItalicMT", 3}, + {"CourierNewPSMT", 0}, + {"CourierStd", 0}, + {"CourierStd-Bold", 1}, + {"CourierStd-BoldOblique", 2}, + {"CourierStd-Oblique", 3}, + {"Helvetica", 4}, + {"Helvetica,Bold", 5}, + {"Helvetica,BoldItalic", 6}, + {"Helvetica,Italic", 7}, + {"Helvetica-Bold", 5}, + {"Helvetica-BoldItalic", 6}, + {"Helvetica-BoldOblique", 6}, + {"Helvetica-Italic", 7}, + {"Helvetica-Oblique", 7}, + {"HelveticaBold", 5}, + {"HelveticaBoldItalic", 6}, + {"HelveticaItalic", 7}, + {"Symbol", 12}, + {"SymbolMT", 12}, + {"Times-Bold", 9}, + {"Times-BoldItalic", 10}, + {"Times-Italic", 11}, + {"Times-Roman", 8}, + {"TimesBold", 9}, + {"TimesBoldItalic", 10}, + {"TimesItalic", 11}, + {"TimesNewRoman", 8}, + {"TimesNewRoman,Bold", 9}, + {"TimesNewRoman,BoldItalic", 10}, + {"TimesNewRoman,Italic", 11}, + {"TimesNewRoman-Bold", 9}, + {"TimesNewRoman-BoldItalic", 10}, + {"TimesNewRoman-Italic", 11}, + {"TimesNewRomanBold", 9}, + {"TimesNewRomanBoldItalic", 10}, + {"TimesNewRomanItalic", 11}, + {"TimesNewRomanPS", 8}, + {"TimesNewRomanPS-Bold", 9}, + {"TimesNewRomanPS-BoldItalic", 10}, + {"TimesNewRomanPS-BoldItalicMT", 10}, + {"TimesNewRomanPS-BoldMT", 9}, + {"TimesNewRomanPS-Italic", 11}, + {"TimesNewRomanPS-ItalicMT", 11}, + {"TimesNewRomanPSMT", 8}, + {"TimesNewRomanPSMT,Bold", 9}, + {"TimesNewRomanPSMT,BoldItalic", 10}, + {"TimesNewRomanPSMT,Italic", 11}, + {"ZapfDingbats", 13}, +}; + +const struct AltFontFamily { + const char* m_pFontName; + const char* m_pFontFamily; +} g_AltFontFamilies[] = { + {"AGaramondPro", "Adobe Garamond Pro"}, + {"BankGothicBT-Medium", "BankGothic Md BT"}, + {"ForteMT", "Forte"}, +}; + +const struct FX_FontStyle { + const char* style; + int32_t len; +} g_FontStyles[] = { + {"Bold", 4}, {"Italic", 6}, {"BoldItalic", 10}, {"Reg", 3}, {"Regular", 7}, +}; + +const struct CODEPAGE_MAP { + uint16_t codepage; + uint8_t charset; +} g_Codepage2CharsetTable[] = { + {0, 1}, {42, 2}, {437, 254}, {850, 255}, {874, 222}, + {932, 128}, {936, 134}, {949, 129}, {950, 136}, {1250, 238}, + {1251, 204}, {1252, 0}, {1253, 161}, {1254, 162}, {1255, 177}, + {1256, 178}, {1257, 186}, {1258, 163}, {1361, 130}, {10000, 77}, + {10001, 78}, {10002, 81}, {10003, 79}, {10004, 84}, {10005, 83}, + {10006, 85}, {10007, 89}, {10008, 80}, {10021, 87}, {10029, 88}, + {10081, 86}, +}; + +int CompareFontFamilyString(const void* key, const void* element) { + CFX_ByteString str_key((const char*)key); + const AltFontFamily* family = reinterpret_cast(element); + if (str_key.Find(family->m_pFontName) != -1) + return 0; + return FXSYS_stricmp(reinterpret_cast(key), family->m_pFontName); +} + +int CompareString(const void* key, const void* element) { + return FXSYS_stricmp(reinterpret_cast(key), + reinterpret_cast(element)->m_pName); +} + +CFX_ByteString TT_NormalizeName(const char* family) { + CFX_ByteString norm(family); + norm.Remove(' '); + norm.Remove('-'); + norm.Remove(','); + int pos = norm.Find('+'); + if (pos > 0) + norm = norm.Left(pos); + norm.MakeLower(); + return norm; +} + +uint8_t GetCharsetFromCodePage(uint16_t codepage) { + const CODEPAGE_MAP* pEnd = + g_Codepage2CharsetTable + FX_ArraySize(g_Codepage2CharsetTable); + const CODEPAGE_MAP* pCharmap = + std::lower_bound(g_Codepage2CharsetTable, pEnd, codepage, + [](const CODEPAGE_MAP& charset, uint16_t page) { + return charset.codepage < page; + }); + if (pCharmap < pEnd && codepage == pCharmap->codepage) + return pCharmap->charset; + return FX_CHARSET_Default; +} + +CFX_ByteString GetFontFamily(CFX_ByteString fontName, int nStyle) { + if (fontName.Find("Script") >= 0) { + if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) + fontName = "ScriptMTBold"; + else if (fontName.Find("Palace") >= 0) + fontName = "PalaceScriptMT"; + else if (fontName.Find("French") >= 0) + fontName = "FrenchScriptMT"; + else if (fontName.Find("FreeStyle") >= 0) + fontName = "FreeStyleScript"; + return fontName; + } + AltFontFamily* found = reinterpret_cast(bsearch( + fontName.c_str(), g_AltFontFamilies, FX_ArraySize(g_AltFontFamilies), + sizeof(AltFontFamily), CompareFontFamilyString)); + return found ? CFX_ByteString(found->m_pFontFamily) : fontName; +} + +CFX_ByteString ParseStyle(const char* pStyle, int iLen, int iIndex) { + std::ostringstream buf; + if (!iLen || iLen <= iIndex) + return CFX_ByteString(buf); + while (iIndex < iLen) { + if (pStyle[iIndex] == ',') + break; + buf << pStyle[iIndex]; + ++iIndex; + } + return CFX_ByteString(buf); +} + +int32_t GetStyleType(const CFX_ByteString& bsStyle, bool bReverse) { + int32_t iLen = bsStyle.GetLength(); + if (!iLen) + return -1; + int iSize = FX_ArraySize(g_FontStyles); + const FX_FontStyle* pStyle = nullptr; + for (int i = iSize - 1; i >= 0; --i) { + pStyle = g_FontStyles + i; + if (!pStyle || pStyle->len > iLen) + continue; + + if (bReverse) { + if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) + return i; + } else { + if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) + return i; + } + } + return -1; +} + +bool CheckSupportThirdPartFont(CFX_ByteString name, int& PitchFamily) { + if (name == "MyriadPro") { + PitchFamily &= ~FXFONT_FF_ROMAN; + return true; + } + return false; +} + +void UpdatePitchFamily(uint32_t flags, int& PitchFamily) { + if (flags & FXFONT_SERIF) + PitchFamily |= FXFONT_FF_ROMAN; + if (flags & FXFONT_SCRIPT) + PitchFamily |= FXFONT_FF_SCRIPT; + if (flags & FXFONT_FIXED_PITCH) + PitchFamily |= FXFONT_FF_FIXEDPITCH; +} + +} // namespace + +CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) + : m_bListLoaded(false), m_pFontMgr(mgr) { + m_MMFaces[0] = nullptr; + m_MMFaces[1] = nullptr; + memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces)); +} + +CFX_FontMapper::~CFX_FontMapper() { + for (size_t i = 0; i < FX_ArraySize(m_FoxitFaces); ++i) { + if (m_FoxitFaces[i]) + FXFT_Done_Face(m_FoxitFaces[i]); + } + if (m_MMFaces[0]) + FXFT_Done_Face(m_MMFaces[0]); + if (m_MMFaces[1]) + FXFT_Done_Face(m_MMFaces[1]); +} + +void CFX_FontMapper::SetSystemFontInfo( + std::unique_ptr pFontInfo) { + if (!pFontInfo) + return; + + m_pFontInfo = std::move(pFontInfo); +} + +CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) { + if (!m_pFontInfo) + return CFX_ByteString(); + + uint32_t size = m_pFontInfo->GetFontData(hFont, kTableNAME, nullptr, 0); + if (!size) + return CFX_ByteString(); + + std::vector buffer(size); + uint8_t* buffer_ptr = buffer.data(); + uint32_t bytes_read = + m_pFontInfo->GetFontData(hFont, kTableNAME, buffer_ptr, size); + return bytes_read == size ? GetNameFromTT(buffer_ptr, bytes_read, 6) + : CFX_ByteString(); +} + +void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) { + if (!m_pFontInfo) + return; + + m_FaceArray.push_back({name, static_cast(charset)}); + if (name == m_LastFamily) + return; + + bool bLocalized = std::any_of(name.begin(), name.end(), [](const char& c) { + return static_cast(c) > 0x80; + }); + + if (bLocalized) { + void* hFont = m_pFontInfo->GetFont(name.c_str()); + if (!hFont) { + int iExact; + hFont = m_pFontInfo->MapFont(0, 0, FX_CHARSET_Default, 0, name.c_str(), + iExact); + if (!hFont) + return; + } + + CFX_ByteString new_name = GetPSNameFromTT(hFont); + if (!new_name.IsEmpty()) + m_LocalizedTTFonts.push_back(std::make_pair(new_name, name)); + m_pFontInfo->DeleteFont(hFont); + } + m_InstalledTTFonts.push_back(name); + m_LastFamily = name; +} + +void CFX_FontMapper::LoadInstalledFonts() { + if (!m_pFontInfo || m_bListLoaded) + return; + + m_pFontInfo->EnumFontList(this); + m_bListLoaded = true; +} + +CFX_ByteString CFX_FontMapper::MatchInstalledFonts( + const CFX_ByteString& norm_name) { + LoadInstalledFonts(); + int i; + for (i = pdfium::CollectionSize(m_InstalledTTFonts) - 1; i >= 0; i--) { + CFX_ByteString norm1 = TT_NormalizeName(m_InstalledTTFonts[i].c_str()); + if (norm1 == norm_name) + return m_InstalledTTFonts[i]; + } + for (i = pdfium::CollectionSize(m_LocalizedTTFonts) - 1; i >= 0; i--) { + CFX_ByteString norm1 = + TT_NormalizeName(m_LocalizedTTFonts[i].first.c_str()); + if (norm1 == norm_name) + return m_LocalizedTTFonts[i].second; + } + return CFX_ByteString(); +} + +FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, + int iBaseFont, + int italic_angle, + int weight, + int picthfamily) { + if (iBaseFont < kNumStandardFonts) { + if (m_FoxitFaces[iBaseFont]) + return m_FoxitFaces[iBaseFont]; + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + if (m_pFontMgr->GetBuiltinFont(iBaseFont, &pFontData, &size)) { + m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_FoxitFaces[iBaseFont]; + } + } + pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM; + pSubstFont->m_ItalicAngle = italic_angle; + if (weight) + pSubstFont->m_Weight = weight; + if (picthfamily & FXFONT_FF_ROMAN) { + pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5; + pSubstFont->m_Family = "Chrome Serif"; + if (m_MMFaces[1]) + return m_MMFaces[1]; + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + m_pFontMgr->GetBuiltinFont(14, &pFontData, &size); + m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_MMFaces[1]; + } + pSubstFont->m_Family = "Chrome Sans"; + if (m_MMFaces[0]) + return m_MMFaces[0]; + const uint8_t* pFontData = nullptr; + uint32_t size = 0; + m_pFontMgr->GetBuiltinFont(15, &pFontData, &size); + m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0); + return m_MMFaces[0]; +} + +FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name, + bool bTrueType, + uint32_t flags, + int weight, + int italic_angle, + int WindowCP, + CFX_SubstFont* pSubstFont) { + if (!(flags & FXFONT_USEEXTERNATTR)) { + weight = FXFONT_FW_NORMAL; + italic_angle = 0; + } + CFX_ByteString SubstName = name; + SubstName.Remove(' '); + if (bTrueType && name[0] == '@') + SubstName = name.Mid(1); + PDF_GetStandardFontName(&SubstName); + if (SubstName == "Symbol" && !bTrueType) { + pSubstFont->m_Family = "Chrome Symbol"; + pSubstFont->m_Charset = FX_CHARSET_Symbol; + return UseInternalSubst(pSubstFont, 12, italic_angle, weight, 0); + } + if (SubstName == "ZapfDingbats") { + pSubstFont->m_Family = "Chrome Dingbats"; + pSubstFont->m_Charset = FX_CHARSET_Symbol; + return UseInternalSubst(pSubstFont, 13, italic_angle, weight, 0); + } + int iBaseFont = 0; + CFX_ByteString family; + CFX_ByteString style; + bool bHasComma = false; + bool bHasHyphen = false; + int find = SubstName.Find(",", 0); + if (find >= 0) { + family = SubstName.Left(find); + PDF_GetStandardFontName(&family); + style = SubstName.Mid(find + 1); + bHasComma = true; + } else { + family = SubstName; + } + for (; iBaseFont < 12; iBaseFont++) { + if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) + break; + } + int PitchFamily = 0; + bool bItalic = false; + uint32_t nStyle = 0; + bool bStyleAvail = false; + if (iBaseFont < 12) { + if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) + nStyle |= FX_FONT_STYLE_Bold; + if ((iBaseFont % 4) / 2) + nStyle |= FX_FONT_STYLE_Italic; + if (iBaseFont < 4) + PitchFamily |= FXFONT_FF_FIXEDPITCH; + if (iBaseFont >= 8) + PitchFamily |= FXFONT_FF_ROMAN; + } else { + iBaseFont = kNumStandardFonts; + if (!bHasComma) { + find = family.ReverseFind('-'); + if (find >= 0) { + style = family.Mid(find + 1); + family = family.Left(find); + bHasHyphen = true; + } + } + if (!bHasHyphen) { + int nLen = family.GetLength(); + int32_t nRet = GetStyleType(family, true); + if (nRet > -1) { + family = family.Left(nLen - g_FontStyles[nRet].len); + if (nRet == 0) + nStyle |= FX_FONT_STYLE_Bold; + else if (nRet == 1) + nStyle |= FX_FONT_STYLE_Italic; + else if (nRet == 2) + nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic); + } + } + UpdatePitchFamily(flags, PitchFamily); + } + if (!style.IsEmpty()) { + int nLen = style.GetLength(); + const char* pStyle = style.c_str(); + int i = 0; + bool bFirstItem = true; + CFX_ByteString buf; + while (i < nLen) { + buf = ParseStyle(pStyle, nLen, i); + int32_t nRet = GetStyleType(buf, false); + if ((i && !bStyleAvail) || (!i && nRet < 0)) { + family = SubstName; + iBaseFont = kNumStandardFonts; + break; + } + if (nRet >= 0) { + bStyleAvail = true; + } + if (nRet == 1) { + if (bFirstItem) { + nStyle |= FX_FONT_STYLE_Italic; + } else { + family = SubstName; + iBaseFont = kNumStandardFonts; + } + break; + } + if (nRet == 0) { + if (nStyle & FX_FONT_STYLE_Bold) + nStyle |= FX_FONT_STYLE_BoldBold; + else + nStyle |= FX_FONT_STYLE_Bold; + bFirstItem = false; + } else if (nRet == 2) { + nStyle |= FX_FONT_STYLE_Italic; + if (nStyle & FX_FONT_STYLE_Bold) + nStyle |= FX_FONT_STYLE_BoldBold; + else + nStyle |= FX_FONT_STYLE_Bold; + bFirstItem = false; + } + i += buf.GetLength() + 1; + } + } + weight = weight ? weight : FXFONT_FW_NORMAL; + int old_weight = weight; + if (nStyle) { + weight = + nStyle & FX_FONT_STYLE_BoldBold + ? 900 + : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); + } + if (nStyle & FX_FONT_STYLE_Italic) + bItalic = true; + int iExact = 0; + int Charset = FX_CHARSET_ANSI; + if (WindowCP) + Charset = GetCharsetFromCodePage(WindowCP); + else if (iBaseFont == kNumStandardFonts && (flags & FXFONT_SYMBOLIC)) + Charset = FX_CHARSET_Symbol; + bool bCJK = (Charset == FX_CHARSET_ShiftJIS || + Charset == FX_CHARSET_ChineseSimplified || + Charset == FX_CHARSET_Hangul || + Charset == FX_CHARSET_ChineseTraditional); + if (!m_pFontInfo) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + family = GetFontFamily(family, nStyle); + CFX_ByteString match = MatchInstalledFonts(TT_NormalizeName(family.c_str())); + if (match.IsEmpty() && family != SubstName && + (!bHasComma && (!bHasHyphen || (bHasHyphen && !bStyleAvail)))) { + match = MatchInstalledFonts(TT_NormalizeName(SubstName.c_str())); + } + if (match.IsEmpty() && iBaseFont >= kNumStandardFonts) { + if (!bCJK) { + if (!CheckSupportThirdPartFont(family, PitchFamily)) { + bItalic = italic_angle != 0; + weight = old_weight; + } +#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ + if (SubstName.Find("Narrow") > 0 || SubstName.Find("Condensed") > 0) + family = "LiberationSansNarrow"; +#elif _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ + if (family.Find("Narrow") > 0 || family.Find("Condensed") > 0) + family = "RobotoCondensed"; +#else + if (family.Find("Narrow") > 0 || family.Find("Condensed") > 0) + family = "ArialNarrow"; +#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ + } else { + pSubstFont->m_bSubstCJK = true; + if (nStyle) + pSubstFont->m_WeightCJK = nStyle ? weight : FXFONT_FW_NORMAL; + if (nStyle & FX_FONT_STYLE_Italic) + pSubstFont->m_bItalicCJK = true; + } + } else { + italic_angle = 0; + weight = + nStyle & FX_FONT_STYLE_BoldBold + ? 900 + : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); + } + if (!match.IsEmpty() || iBaseFont < kNumStandardFonts) { + if (!match.IsEmpty()) + family = match; + if (iBaseFont < kNumStandardFonts) { + if (nStyle && !(iBaseFont % 4)) { + if ((nStyle & 0x3) == 1) + iBaseFont += 1; + if ((nStyle & 0x3) == 2) + iBaseFont += 3; + if ((nStyle & 0x3) == 3) + iBaseFont += 2; + } + family = g_Base14FontNames[iBaseFont]; + } + } else { + if (flags & FXFONT_ITALIC) + bItalic = true; + } + iExact = !match.IsEmpty(); + void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, + family.c_str(), iExact); + if (iExact) + pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT; + if (!hFont) { +#ifdef PDF_ENABLE_XFA + if (flags & FXFONT_EXACTMATCH) + return nullptr; +#endif // PDF_ENABLE_XFA + if (bCJK) { + bItalic = italic_angle != 0; + weight = old_weight; + } + if (!match.IsEmpty()) { + hFont = m_pFontInfo->GetFont(match.c_str()); + if (!hFont) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + } else { + if (Charset == FX_CHARSET_Symbol) { +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \ + _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ + if (SubstName == "Symbol") { + pSubstFont->m_Family = "Chrome Symbol"; + pSubstFont->m_Charset = FX_CHARSET_Symbol; + return UseInternalSubst(pSubstFont, 12, italic_angle, old_weight, + PitchFamily); + } +#endif + return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, + weight, italic_angle, 0, pSubstFont); + } + if (Charset == FX_CHARSET_ANSI) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + + auto it = + std::find_if(m_FaceArray.begin(), m_FaceArray.end(), + [Charset](const FaceData& face) { + return face.charset == static_cast(Charset); + }); + if (it == m_FaceArray.end()) { + return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, + PitchFamily); + } + hFont = m_pFontInfo->GetFont(it->name.c_str()); + } + } + if (!hFont) + return nullptr; + + m_pFontInfo->GetFaceName(hFont, &SubstName); + if (Charset == FX_CHARSET_Default) + m_pFontInfo->GetFontCharset(hFont, &Charset); + uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, kTableTTCF, nullptr, 0); + uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); + if (font_size == 0 && ttc_size == 0) { + m_pFontInfo->DeleteFont(hFont); + return nullptr; + } + FXFT_Face face = nullptr; + if (ttc_size) + face = GetCachedTTCFace(hFont, kTableTTCF, ttc_size, font_size); + else + face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size); + if (!face) { + m_pFontInfo->DeleteFont(hFont); + return nullptr; + } + pSubstFont->m_Family = SubstName; + pSubstFont->m_Charset = Charset; + bool bNeedUpdateWeight = false; + if (FXFT_Is_Face_Bold(face)) + bNeedUpdateWeight = weight != FXFONT_FW_BOLD; + else + bNeedUpdateWeight = weight != FXFONT_FW_NORMAL; + if (bNeedUpdateWeight) + pSubstFont->m_Weight = weight; + if (bItalic && !FXFT_Is_Face_Italic(face)) { + if (italic_angle == 0) + italic_angle = -12; + else if (abs(italic_angle) < 5) + italic_angle = 0; + pSubstFont->m_ItalicAngle = italic_angle; + } + m_pFontInfo->DeleteFont(hFont); + return face; +} + +#ifdef PDF_ENABLE_XFA +FXFT_Face CFX_FontMapper::FindSubstFontByUnicode(uint32_t dwUnicode, + uint32_t flags, + int weight, + int italic_angle) { + if (!m_pFontInfo) + return nullptr; + + bool bItalic = (flags & FXFONT_ITALIC) != 0; + int PitchFamily = 0; + UpdatePitchFamily(flags, PitchFamily); + void* hFont = + m_pFontInfo->MapFontByUnicode(dwUnicode, weight, bItalic, PitchFamily); + if (!hFont) + return nullptr; + + uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, nullptr, 0); + uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); + if (font_size == 0 && ttc_size == 0) { + m_pFontInfo->DeleteFont(hFont); + return nullptr; + } + FXFT_Face face = nullptr; + if (ttc_size) { + face = GetCachedTTCFace(hFont, 0x74746366, ttc_size, font_size); + } else { + CFX_ByteString SubstName; + m_pFontInfo->GetFaceName(hFont, &SubstName); + face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size); + } + m_pFontInfo->DeleteFont(hFont); + return face; +} +#endif // PDF_ENABLE_XFA + +int CFX_FontMapper::GetFaceSize() const { + return pdfium::CollectionSize(m_FaceArray); +} + +bool CFX_FontMapper::IsBuiltinFace(const FXFT_Face face) const { + for (size_t i = 0; i < MM_FACE_COUNT; ++i) { + if (m_MMFaces[i] == face) + return true; + } + for (size_t i = 0; i < FOXIT_FACE_COUNT; ++i) { + if (m_FoxitFaces[i] == face) + return true; + } + return false; +} + +FXFT_Face CFX_FontMapper::GetCachedTTCFace(void* hFont, + const uint32_t tableTTCF, + uint32_t ttc_size, + uint32_t font_size) { + FXFT_Face face; + uint8_t buffer[1024]; + m_pFontInfo->GetFontData(hFont, tableTTCF, buffer, FX_ArraySize(buffer)); + uint32_t* pBuffer = reinterpret_cast(buffer); + uint32_t checksum = 0; + for (int i = 0; i < 256; i++) + checksum += pBuffer[i]; + uint8_t* pFontData; + face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, ttc_size - font_size, + pFontData); + if (!face) { + pFontData = FX_Alloc(uint8_t, ttc_size); + m_pFontInfo->GetFontData(hFont, tableTTCF, pFontData, ttc_size); + face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size, + ttc_size - font_size); + } + return face; +} + +FXFT_Face CFX_FontMapper::GetCachedFace(void* hFont, + CFX_ByteString SubstName, + int weight, + bool bItalic, + uint32_t font_size) { + FXFT_Face face; + uint8_t* pFontData; + face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData); + if (!face) { + pFontData = FX_Alloc(uint8_t, font_size); + m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size); + face = + m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, + font_size, m_pFontInfo->GetFaceIndex(hFont)); + } + return face; +} + +int PDF_GetStandardFontName(CFX_ByteString* name) { + AltFontName* found = static_cast( + bsearch(name->c_str(), g_AltFontNames, FX_ArraySize(g_AltFontNames), + sizeof(AltFontName), CompareString)); + if (!found) + return -1; + + *name = g_Base14FontNames[found->m_Index]; + return found->m_Index; +} diff --git a/core/fxge/cfx_fontmgr.cpp b/core/fxge/cfx_fontmgr.cpp new file mode 100644 index 0000000000..c8beb515f0 --- /dev/null +++ b/core/fxge/cfx_fontmgr.cpp @@ -0,0 +1,259 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_fontmgr.h" + +#include +#include + +#include "core/fxge/cfx_fontmapper.h" +#include "core/fxge/cfx_substfont.h" +#include "core/fxge/cttfontdesc.h" +#include "core/fxge/fontdata/chromefontdata/chromefontdata.h" +#include "core/fxge/fx_font.h" +#include "core/fxge/ifx_systemfontinfo.h" +#include "third_party/base/ptr_util.h" + +namespace { + +struct BuiltinFont { + const uint8_t* m_pFontData; + uint32_t m_dwSize; +}; + +const BuiltinFont g_FoxitFonts[14] = { + {g_FoxitFixedFontData, 17597}, + {g_FoxitFixedBoldFontData, 18055}, + {g_FoxitFixedBoldItalicFontData, 19151}, + {g_FoxitFixedItalicFontData, 18746}, + {g_FoxitSansFontData, 15025}, + {g_FoxitSansBoldFontData, 16344}, + {g_FoxitSansBoldItalicFontData, 16418}, + {g_FoxitSansItalicFontData, 16339}, + {g_FoxitSerifFontData, 19469}, + {g_FoxitSerifBoldFontData, 19395}, + {g_FoxitSerifBoldItalicFontData, 20733}, + {g_FoxitSerifItalicFontData, 21227}, + {g_FoxitSymbolFontData, 16729}, + {g_FoxitDingbatsFontData, 29513}, +}; + +const BuiltinFont g_MMFonts[2] = { + {g_FoxitSerifMMFontData, 113417}, + {g_FoxitSansMMFontData, 66919}, +}; + +CFX_ByteString KeyNameFromFace(const CFX_ByteString& face_name, + int weight, + bool bItalic) { + CFX_ByteString key(face_name); + key += ','; + key += CFX_ByteString::FormatInteger(weight); + key += bItalic ? 'I' : 'N'; + return key; +} + +CFX_ByteString KeyNameFromSize(int ttc_size, uint32_t checksum) { + CFX_ByteString key; + key.Format("%d:%d", ttc_size, checksum); + return key; +} + +int GetTTCIndex(const uint8_t* pFontData, + uint32_t ttc_size, + uint32_t font_offset) { + int face_index = 0; + const uint8_t* p = pFontData + 8; + uint32_t nfont = GET_TT_LONG(p); + uint32_t index; + for (index = 0; index < nfont; index++) { + p = pFontData + 12 + index * 4; + if (GET_TT_LONG(p) == font_offset) + break; + } + if (index >= nfont) + face_index = 0; + else + face_index = index; + return face_index; +} + +} // namespace + +CFX_FontMgr::CFX_FontMgr() + : m_FTLibrary(nullptr), m_FTLibrarySupportsHinting(false) { + m_pBuiltinMapper = pdfium::MakeUnique(this); +} + +CFX_FontMgr::~CFX_FontMgr() { + // |m_FaceMap| and |m_pBuiltinMapper| reference |m_FTLibrary|, so they must + // be destroyed first. + m_FaceMap.clear(); + m_pBuiltinMapper.reset(); + FXFT_Done_FreeType(m_FTLibrary); +} + +void CFX_FontMgr::InitFTLibrary() { + if (m_FTLibrary) + return; + FXFT_Init_FreeType(&m_FTLibrary); + m_FTLibrarySupportsHinting = + FXFT_Library_SetLcdFilter(m_FTLibrary, FT_LCD_FILTER_DEFAULT) != + FT_Err_Unimplemented_Feature; +} + +void CFX_FontMgr::SetSystemFontInfo( + std::unique_ptr pFontInfo) { + m_pBuiltinMapper->SetSystemFontInfo(std::move(pFontInfo)); +} + +FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name, + bool bTrueType, + uint32_t flags, + int weight, + int italic_angle, + int CharsetCP, + CFX_SubstFont* pSubstFont) { + InitFTLibrary(); + return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, + italic_angle, CharsetCP, pSubstFont); +} + +FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name, + int weight, + bool bItalic, + uint8_t*& pFontData) { + auto it = m_FaceMap.find(KeyNameFromFace(face_name, weight, bItalic)); + if (it == m_FaceMap.end()) + return nullptr; + + CTTFontDesc* pFontDesc = it->second.get(); + pFontData = pFontDesc->m_pFontData; + pFontDesc->m_RefCount++; + return pFontDesc->m_SingleFace; +} + +FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name, + int weight, + bool bItalic, + uint8_t* pData, + uint32_t size, + int face_index) { + auto pFontDesc = pdfium::MakeUnique(); + pFontDesc->m_Type = 1; + pFontDesc->m_SingleFace = nullptr; + pFontDesc->m_pFontData = pData; + pFontDesc->m_RefCount = 1; + + InitFTLibrary(); + FXFT_Library library = m_FTLibrary; + int ret = FXFT_New_Memory_Face(library, pData, size, face_index, + &pFontDesc->m_SingleFace); + if (ret) + return nullptr; + + ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace, 64, 64); + if (ret) + return nullptr; + + CTTFontDesc* pResult = pFontDesc.get(); + m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = std::move(pFontDesc); + return pResult->m_SingleFace; +} + +FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, + uint32_t checksum, + int font_offset, + uint8_t*& pFontData) { + auto it = m_FaceMap.find(KeyNameFromSize(ttc_size, checksum)); + if (it == m_FaceMap.end()) + return nullptr; + + CTTFontDesc* pFontDesc = it->second.get(); + pFontData = pFontDesc->m_pFontData; + pFontDesc->m_RefCount++; + int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); + if (!pFontDesc->m_TTCFaces[face_index]) { + pFontDesc->m_TTCFaces[face_index] = + GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); + } + return pFontDesc->m_TTCFaces[face_index]; +} + +FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, + uint32_t checksum, + uint8_t* pData, + uint32_t size, + int font_offset) { + auto pFontDesc = pdfium::MakeUnique(); + pFontDesc->m_Type = 2; + pFontDesc->m_pFontData = pData; + for (int i = 0; i < 16; i++) + pFontDesc->m_TTCFaces[i] = nullptr; + pFontDesc->m_RefCount++; + CTTFontDesc* pResult = pFontDesc.get(); + m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = std::move(pFontDesc); + int face_index = GetTTCIndex(pResult->m_pFontData, ttc_size, font_offset); + pResult->m_TTCFaces[face_index] = + GetFixedFace(pResult->m_pFontData, ttc_size, face_index); + return pResult->m_TTCFaces[face_index]; +} + +FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData, + uint32_t size, + int face_index) { + InitFTLibrary(); + FXFT_Library library = m_FTLibrary; + FXFT_Face face = nullptr; + if (FXFT_New_Memory_Face(library, pData, size, face_index, &face)) + return nullptr; + return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; +} + +FXFT_Face CFX_FontMgr::GetFileFace(const char* filename, int face_index) { + InitFTLibrary(); + FXFT_Library library = m_FTLibrary; + FXFT_Face face = nullptr; + if (FXFT_New_Face(library, filename, face_index, &face)) + return nullptr; + return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; +} + +void CFX_FontMgr::ReleaseFace(FXFT_Face face) { + if (!face) + return; + bool bNeedFaceDone = true; + auto it = m_FaceMap.begin(); + while (it != m_FaceMap.end()) { + auto temp = it++; + int nRet = temp->second->ReleaseFace(face); + if (nRet == -1) + continue; + bNeedFaceDone = false; + if (nRet == 0) + m_FaceMap.erase(temp); + break; + } + if (bNeedFaceDone && !m_pBuiltinMapper->IsBuiltinFace(face)) + FXFT_Done_Face(face); +} + +bool CFX_FontMgr::GetBuiltinFont(size_t index, + const uint8_t** pFontData, + uint32_t* size) { + if (index < FX_ArraySize(g_FoxitFonts)) { + *pFontData = g_FoxitFonts[index].m_pFontData; + *size = g_FoxitFonts[index].m_dwSize; + return true; + } + index -= FX_ArraySize(g_FoxitFonts); + if (index < FX_ArraySize(g_MMFonts)) { + *pFontData = g_MMFonts[index].m_pFontData; + *size = g_MMFonts[index].m_dwSize; + return true; + } + return false; +} diff --git a/core/fxge/cfx_gemodule.cpp b/core/fxge/cfx_gemodule.cpp new file mode 100644 index 0000000000..a28a88243a --- /dev/null +++ b/core/fxge/cfx_gemodule.cpp @@ -0,0 +1,54 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_gemodule.h" + +#include "core/fxge/cfx_folderfontinfo.h" +#include "core/fxge/cfx_fontcache.h" +#include "core/fxge/cfx_fontmgr.h" +#include "core/fxge/fx_text_int.h" +#include "third_party/base/ptr_util.h" + +namespace { + +CFX_GEModule* g_pGEModule = nullptr; + +} // namespace + +CFX_GEModule::CFX_GEModule() + : m_pFontMgr(pdfium::MakeUnique()), + m_pPlatformData(nullptr), + m_pUserFontPaths(nullptr) {} + +CFX_GEModule::~CFX_GEModule() { + DestroyPlatform(); +} + +// static +CFX_GEModule* CFX_GEModule::Get() { + if (!g_pGEModule) + g_pGEModule = new CFX_GEModule(); + return g_pGEModule; +} + +// static +void CFX_GEModule::Destroy() { + ASSERT(g_pGEModule); + delete g_pGEModule; + g_pGEModule = nullptr; +} + +void CFX_GEModule::Init(const char** userFontPaths) { + ASSERT(g_pGEModule); + m_pUserFontPaths = userFontPaths; + InitPlatform(); +} + +CFX_FontCache* CFX_GEModule::GetFontCache() { + if (!m_pFontCache) + m_pFontCache = pdfium::MakeUnique(); + return m_pFontCache.get(); +} diff --git a/core/fxge/cfx_graphstate.cpp b/core/fxge/cfx_graphstate.cpp new file mode 100644 index 0000000000..ad6b5fc6c7 --- /dev/null +++ b/core/fxge/cfx_graphstate.cpp @@ -0,0 +1,61 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_graphstate.h" + +#include "core/fpdfapi/parser/cpdf_array.h" + +CFX_GraphState::CFX_GraphState() {} + +CFX_GraphState::CFX_GraphState(const CFX_GraphState& that) + : m_Ref(that.m_Ref) {} + +CFX_GraphState::~CFX_GraphState() {} + +void CFX_GraphState::Emplace() { + m_Ref.Emplace(); +} + +void CFX_GraphState::SetLineDash(CPDF_Array* pArray, float phase, float scale) { + CFX_GraphStateData* pData = m_Ref.GetPrivateCopy(); + pData->m_DashPhase = phase * scale; + pData->SetDashCount(static_cast(pArray->GetCount())); + for (size_t i = 0; i < pArray->GetCount(); i++) + pData->m_DashArray[i] = pArray->GetNumberAt(i) * scale; +} + +float CFX_GraphState::GetLineWidth() const { + return m_Ref.GetObject() ? m_Ref.GetObject()->m_LineWidth : 1.f; +} + +void CFX_GraphState::SetLineWidth(float width) { + m_Ref.GetPrivateCopy()->m_LineWidth = width; +} + +CFX_GraphStateData::LineCap CFX_GraphState::GetLineCap() const { + return m_Ref.GetObject() ? m_Ref.GetObject()->m_LineCap + : CFX_GraphStateData::LineCapButt; +} +void CFX_GraphState::SetLineCap(CFX_GraphStateData::LineCap cap) { + m_Ref.GetPrivateCopy()->m_LineCap = cap; +} + +CFX_GraphStateData::LineJoin CFX_GraphState::GetLineJoin() const { + return m_Ref.GetObject() ? m_Ref.GetObject()->m_LineJoin + : CFX_GraphStateData::LineJoinMiter; +} + +void CFX_GraphState::SetLineJoin(CFX_GraphStateData::LineJoin join) { + m_Ref.GetPrivateCopy()->m_LineJoin = join; +} + +float CFX_GraphState::GetMiterLimit() const { + return m_Ref.GetObject() ? m_Ref.GetObject()->m_MiterLimit : 10.f; +} + +void CFX_GraphState::SetMiterLimit(float limit) { + m_Ref.GetPrivateCopy()->m_MiterLimit = limit; +} diff --git a/core/fxge/cfx_graphstatedata.cpp b/core/fxge/cfx_graphstatedata.cpp new file mode 100644 index 0000000000..82fede176a --- /dev/null +++ b/core/fxge/cfx_graphstatedata.cpp @@ -0,0 +1,52 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_graphstatedata.h" + +#include "core/fxcrt/fx_memory.h" +#include "core/fxcrt/fx_system.h" + +CFX_GraphStateData::CFX_GraphStateData() + : m_LineCap(LineCapButt), + m_DashCount(0), + m_DashArray(nullptr), + m_DashPhase(0), + m_LineJoin(LineJoinMiter), + m_MiterLimit(10 * 1.0f), + m_LineWidth(1.0f) {} + +CFX_GraphStateData::CFX_GraphStateData(const CFX_GraphStateData& src) { + m_DashArray = nullptr; + Copy(src); +} + +void CFX_GraphStateData::Copy(const CFX_GraphStateData& src) { + m_LineCap = src.m_LineCap; + m_DashCount = src.m_DashCount; + FX_Free(m_DashArray); + m_DashArray = nullptr; + m_DashPhase = src.m_DashPhase; + m_LineJoin = src.m_LineJoin; + m_MiterLimit = src.m_MiterLimit; + m_LineWidth = src.m_LineWidth; + if (m_DashCount) { + m_DashArray = FX_Alloc(float, m_DashCount); + memcpy(m_DashArray, src.m_DashArray, m_DashCount * sizeof(float)); + } +} + +CFX_GraphStateData::~CFX_GraphStateData() { + FX_Free(m_DashArray); +} + +void CFX_GraphStateData::SetDashCount(int count) { + FX_Free(m_DashArray); + m_DashArray = nullptr; + m_DashCount = count; + if (count == 0) + return; + m_DashArray = FX_Alloc(float, count); +} diff --git a/core/fxge/cfx_pathdata.cpp b/core/fxge/cfx_pathdata.cpp new file mode 100644 index 0000000000..fe3c6778d5 --- /dev/null +++ b/core/fxge/cfx_pathdata.cpp @@ -0,0 +1,487 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_pathdata.h" + +#include "core/fxcrt/fx_system.h" +#include "third_party/base/numerics/safe_math.h" + +namespace { + +void UpdateLineEndPoints(CFX_FloatRect* rect, + const CFX_PointF& start_pos, + const CFX_PointF& end_pos, + float hw) { + if (start_pos.x == end_pos.x) { + if (start_pos.y == end_pos.y) { + rect->UpdateRect(end_pos.x + hw, end_pos.y + hw); + rect->UpdateRect(end_pos.x - hw, end_pos.y - hw); + return; + } + + float point_y; + if (end_pos.y < start_pos.y) + point_y = end_pos.y - hw; + else + point_y = end_pos.y + hw; + + rect->UpdateRect(end_pos.x + hw, point_y); + rect->UpdateRect(end_pos.x - hw, point_y); + return; + } + + if (start_pos.y == end_pos.y) { + float point_x; + if (end_pos.x < start_pos.x) + point_x = end_pos.x - hw; + else + point_x = end_pos.x + hw; + + rect->UpdateRect(point_x, end_pos.y + hw); + rect->UpdateRect(point_x, end_pos.y - hw); + return; + } + + CFX_PointF diff = end_pos - start_pos; + float ll = FXSYS_sqrt2(diff.x, diff.y); + float mx = end_pos.x + hw * diff.x / ll; + float my = end_pos.y + hw * diff.y / ll; + float dx1 = hw * diff.y / ll; + float dy1 = hw * diff.x / ll; + rect->UpdateRect(mx - dx1, my + dy1); + rect->UpdateRect(mx + dx1, my - dy1); +} + +void UpdateLineJoinPoints(CFX_FloatRect* rect, + const CFX_PointF& start_pos, + const CFX_PointF& mid_pos, + const CFX_PointF& end_pos, + float half_width, + float miter_limit) { + float start_k = 0; + float start_c = 0; + float end_k = 0; + float end_c = 0; + float start_len = 0; + float start_dc = 0; + float end_len = 0; + float end_dc = 0; + float one_twentieth = 1.0f / 20; + + bool bStartVert = fabs(start_pos.x - mid_pos.x) < one_twentieth; + bool bEndVert = fabs(mid_pos.x - end_pos.x) < one_twentieth; + if (bStartVert && bEndVert) { + int start_dir = mid_pos.y > start_pos.y ? 1 : -1; + float point_y = mid_pos.y + half_width * start_dir; + rect->UpdateRect(mid_pos.x + half_width, point_y); + rect->UpdateRect(mid_pos.x - half_width, point_y); + return; + } + + if (!bStartVert) { + CFX_PointF start_to_mid = start_pos - mid_pos; + start_k = (mid_pos.y - start_pos.y) / (mid_pos.x - start_pos.x); + start_c = mid_pos.y - (start_k * mid_pos.x); + start_len = FXSYS_sqrt2(start_to_mid.x, start_to_mid.y); + start_dc = + static_cast(fabs(half_width * start_len / start_to_mid.x)); + } + if (!bEndVert) { + CFX_PointF end_to_mid = end_pos - mid_pos; + end_k = end_to_mid.y / end_to_mid.x; + end_c = mid_pos.y - (end_k * mid_pos.x); + end_len = FXSYS_sqrt2(end_to_mid.x, end_to_mid.y); + end_dc = static_cast(fabs(half_width * end_len / end_to_mid.x)); + } + if (bStartVert) { + CFX_PointF outside(start_pos.x, 0); + if (end_pos.x < start_pos.x) + outside.x += half_width; + else + outside.x -= half_width; + + if (start_pos.y < (end_k * start_pos.x) + end_c) + outside.y = (end_k * outside.x) + end_c + end_dc; + else + outside.y = (end_k * outside.x) + end_c - end_dc; + + rect->UpdateRect(outside.x, outside.y); + return; + } + + if (bEndVert) { + CFX_PointF outside(end_pos.x, 0); + if (start_pos.x < end_pos.x) + outside.x += half_width; + else + outside.x -= half_width; + + if (end_pos.y < (start_k * end_pos.x) + start_c) + outside.y = (start_k * outside.x) + start_c + start_dc; + else + outside.y = (start_k * outside.x) + start_c - start_dc; + + rect->UpdateRect(outside.x, outside.y); + return; + } + + if (fabs(start_k - end_k) < one_twentieth) { + int start_dir = mid_pos.x > start_pos.x ? 1 : -1; + int end_dir = end_pos.x > mid_pos.x ? 1 : -1; + if (start_dir == end_dir) + UpdateLineEndPoints(rect, mid_pos, end_pos, half_width); + else + UpdateLineEndPoints(rect, start_pos, mid_pos, half_width); + return; + } + + float start_outside_c = start_c; + if (end_pos.y < (start_k * end_pos.x) + start_c) + start_outside_c += start_dc; + else + start_outside_c -= start_dc; + + float end_outside_c = end_c; + if (start_pos.y < (end_k * start_pos.x) + end_c) + end_outside_c += end_dc; + else + end_outside_c -= end_dc; + + float join_x = (end_outside_c - start_outside_c) / (start_k - end_k); + float join_y = start_k * join_x + start_outside_c; + rect->UpdateRect(join_x, join_y); +} + +} // namespace + +FX_PATHPOINT::FX_PATHPOINT() = default; + +FX_PATHPOINT::FX_PATHPOINT(const CFX_PointF& point, FXPT_TYPE type, bool close) + : m_Point(point), m_Type(type), m_CloseFigure(close) {} + +FX_PATHPOINT::FX_PATHPOINT(const FX_PATHPOINT& other) = default; + +FX_PATHPOINT::~FX_PATHPOINT() = default; + +CFX_PathData::CFX_PathData() {} + +CFX_PathData::~CFX_PathData() {} + +CFX_PathData::CFX_PathData(const CFX_PathData& src) : m_Points(src.m_Points) {} + +void CFX_PathData::Clear() { + m_Points.clear(); +} + +void CFX_PathData::ClosePath() { + if (m_Points.empty()) + return; + m_Points.back().m_CloseFigure = true; +} + +void CFX_PathData::Append(const CFX_PathData* pSrc, const CFX_Matrix* pMatrix) { + if (pSrc->m_Points.empty()) + return; + + size_t cur_size = m_Points.size(); + m_Points.insert(m_Points.end(), pSrc->m_Points.begin(), pSrc->m_Points.end()); + + if (!pMatrix) + return; + + for (size_t i = cur_size; i < m_Points.size(); i++) + m_Points[i].m_Point = pMatrix->Transform(m_Points[i].m_Point); +} + +void CFX_PathData::AppendPoint(const CFX_PointF& point, + FXPT_TYPE type, + bool closeFigure) { + m_Points.push_back(FX_PATHPOINT(point, type, closeFigure)); +} + +void CFX_PathData::AppendRect(float left, + float bottom, + float right, + float top) { + m_Points.push_back( + FX_PATHPOINT(CFX_PointF(left, bottom), FXPT_TYPE::MoveTo, false)); + m_Points.push_back( + FX_PATHPOINT(CFX_PointF(left, top), FXPT_TYPE::LineTo, false)); + m_Points.push_back( + FX_PATHPOINT(CFX_PointF(right, top), FXPT_TYPE::LineTo, false)); + m_Points.push_back( + FX_PATHPOINT(CFX_PointF(right, bottom), FXPT_TYPE::LineTo, false)); + m_Points.push_back( + FX_PATHPOINT(CFX_PointF(left, bottom), FXPT_TYPE::LineTo, true)); +} + +CFX_FloatRect CFX_PathData::GetBoundingBox() const { + if (m_Points.empty()) + return CFX_FloatRect(); + + CFX_FloatRect rect; + rect.InitRect(m_Points[0].m_Point.x, m_Points[0].m_Point.y); + for (size_t i = 1; i < m_Points.size(); i++) + rect.UpdateRect(m_Points[i].m_Point.x, m_Points[i].m_Point.y); + return rect; +} + +CFX_FloatRect CFX_PathData::GetBoundingBox(float line_width, + float miter_limit) const { + CFX_FloatRect rect(100000.0f, 100000.0f, -100000.0f, -100000.0f); + size_t iPoint = 0; + float half_width = line_width; + int iStartPoint = 0; + int iEndPoint = 0; + int iMiddlePoint = 0; + bool bJoin; + while (iPoint < m_Points.size()) { + if (m_Points[iPoint].IsTypeAndOpen(FXPT_TYPE::MoveTo)) { + if (iPoint + 1 == m_Points.size()) + break; + + iStartPoint = iPoint + 1; + iEndPoint = iPoint; + bJoin = false; + } else { + if (m_Points[iPoint].IsTypeAndOpen(FXPT_TYPE::BezierTo)) { + rect.UpdateRect(m_Points[iPoint].m_Point.x, m_Points[iPoint].m_Point.y); + rect.UpdateRect(m_Points[iPoint + 1].m_Point.x, + m_Points[iPoint + 1].m_Point.y); + iPoint += 2; + } + if (iPoint == m_Points.size() - 1 || + m_Points[iPoint + 1].IsTypeAndOpen(FXPT_TYPE::MoveTo)) { + iStartPoint = iPoint - 1; + iEndPoint = iPoint; + bJoin = false; + } else { + iStartPoint = iPoint - 1; + iMiddlePoint = iPoint; + iEndPoint = iPoint + 1; + bJoin = true; + } + } + + CFX_PointF start_pos = m_Points[iStartPoint].m_Point; + CFX_PointF end_pos = m_Points[iEndPoint].m_Point; + if (bJoin) { + CFX_PointF mid_pos = m_Points[iMiddlePoint].m_Point; + UpdateLineJoinPoints(&rect, start_pos, mid_pos, end_pos, half_width, + miter_limit); + } else { + UpdateLineEndPoints(&rect, start_pos, end_pos, half_width); + } + iPoint++; + } + return rect; +} + +void CFX_PathData::Transform(const CFX_Matrix* pMatrix) { + if (!pMatrix) + return; + for (auto& point : m_Points) + point.m_Point = pMatrix->Transform(point.m_Point); +} + +bool CFX_PathData::GetZeroAreaPath(const CFX_Matrix* pMatrix, + bool bAdjust, + CFX_PathData* NewPath, + bool* bThin, + bool* setIdentity) const { + *setIdentity = false; + if (m_Points.size() < 3) + return false; + + if (m_Points.size() == 3 && m_Points[0].m_Type == FXPT_TYPE::MoveTo && + m_Points[1].m_Type == FXPT_TYPE::LineTo && + m_Points[2].m_Type == FXPT_TYPE::LineTo && + m_Points[0].m_Point == m_Points[2].m_Point) { + for (size_t i = 0; i < 2; i++) { + CFX_PointF point = m_Points[i].m_Point; + if (bAdjust) { + if (pMatrix) + point = pMatrix->Transform(point); + + point = CFX_PointF(static_cast(point.x) + 0.5f, + static_cast(point.y) + 0.5f); + } + NewPath->AppendPoint( + point, i == 0 ? FXPT_TYPE::MoveTo : FXPT_TYPE::LineTo, false); + } + if (bAdjust && pMatrix) + *setIdentity = true; + + // Note, they both have to be not equal. + if (m_Points[0].m_Point.x != m_Points[1].m_Point.x && + m_Points[0].m_Point.y != m_Points[1].m_Point.y) { + *bThin = true; + } + return true; + } + + if (((m_Points.size() > 3) && (m_Points.size() % 2))) { + int mid = m_Points.size() / 2; + bool bZeroArea = false; + CFX_PathData t_path; + for (int i = 0; i < mid; i++) { + if (!(m_Points[mid - i - 1].m_Point == m_Points[mid + i + 1].m_Point && + m_Points[mid - i - 1].m_Type != FXPT_TYPE::BezierTo && + m_Points[mid + i + 1].m_Type != FXPT_TYPE::BezierTo)) { + bZeroArea = true; + break; + } + + t_path.AppendPoint(m_Points[mid - i].m_Point, FXPT_TYPE::MoveTo, false); + t_path.AppendPoint(m_Points[mid - i - 1].m_Point, FXPT_TYPE::LineTo, + false); + } + if (!bZeroArea) { + NewPath->Append(&t_path, nullptr); + *bThin = true; + return true; + } + } + + int startPoint = 0; + int next = 0; + for (size_t i = 0; i < m_Points.size(); i++) { + FXPT_TYPE point_type = m_Points[i].m_Type; + if (point_type == FXPT_TYPE::MoveTo) { + startPoint = i; + } else if (point_type == FXPT_TYPE::LineTo) { + next = (i + 1 - startPoint) % (m_Points.size() - startPoint) + startPoint; + if (m_Points[next].m_Type != FXPT_TYPE::BezierTo && + m_Points[next].m_Type != FXPT_TYPE::MoveTo) { + if ((m_Points[i - 1].m_Point.x == m_Points[i].m_Point.x && + m_Points[i].m_Point.x == m_Points[next].m_Point.x) && + ((m_Points[i].m_Point.y - m_Points[i - 1].m_Point.y) * + (m_Points[i].m_Point.y - m_Points[next].m_Point.y) > + 0)) { + int pre = i; + if (fabs(m_Points[i].m_Point.y - m_Points[i - 1].m_Point.y) < + fabs(m_Points[i].m_Point.y - m_Points[next].m_Point.y)) { + pre--; + next--; + } + + NewPath->AppendPoint(m_Points[pre].m_Point, FXPT_TYPE::MoveTo, false); + NewPath->AppendPoint(m_Points[next].m_Point, FXPT_TYPE::LineTo, + false); + } else if ((m_Points[i - 1].m_Point.y == m_Points[i].m_Point.y && + m_Points[i].m_Point.y == m_Points[next].m_Point.y) && + ((m_Points[i].m_Point.x - m_Points[i - 1].m_Point.x) * + (m_Points[i].m_Point.x - m_Points[next].m_Point.x) > + 0)) { + int pre = i; + if (fabs(m_Points[i].m_Point.x - m_Points[i - 1].m_Point.x) < + fabs(m_Points[i].m_Point.x - m_Points[next].m_Point.x)) { + pre--; + next--; + } + + NewPath->AppendPoint(m_Points[pre].m_Point, FXPT_TYPE::MoveTo, false); + NewPath->AppendPoint(m_Points[next].m_Point, FXPT_TYPE::LineTo, + false); + } else if (m_Points[i - 1].m_Type == FXPT_TYPE::MoveTo && + m_Points[next].m_Type == FXPT_TYPE::LineTo && + m_Points[i - 1].m_Point == m_Points[next].m_Point && + m_Points[next].m_CloseFigure) { + NewPath->AppendPoint(m_Points[i - 1].m_Point, FXPT_TYPE::MoveTo, + false); + NewPath->AppendPoint(m_Points[i].m_Point, FXPT_TYPE::LineTo, false); + *bThin = true; + } + } + } else if (point_type == FXPT_TYPE::BezierTo) { + i += 2; + continue; + } + } + + size_t new_path_size = NewPath->GetPoints().size(); + if (m_Points.size() > 3 && new_path_size > 0) + *bThin = true; + return new_path_size != 0; +} + +bool CFX_PathData::IsRect() const { + if (m_Points.size() != 5 && m_Points.size() != 4) + return false; + + if ((m_Points.size() == 5 && m_Points[0].m_Point != m_Points[4].m_Point) || + m_Points[0].m_Point == m_Points[2].m_Point || + m_Points[1].m_Point == m_Points[3].m_Point) { + return false; + } + // Note, both x,y have to not equal. + if (m_Points[0].m_Point.x != m_Points[3].m_Point.x && + m_Points[0].m_Point.y != m_Points[3].m_Point.y) { + return false; + } + + for (int i = 1; i < 4; i++) { + if (m_Points[i].m_Type != FXPT_TYPE::LineTo) + return false; + // Note, both x,y have to not equal. + if (m_Points[i].m_Point.x != m_Points[i - 1].m_Point.x && + m_Points[i].m_Point.y != m_Points[i - 1].m_Point.y) { + return false; + } + } + return m_Points.size() == 5 || m_Points[3].m_CloseFigure; +} + +bool CFX_PathData::IsRect(const CFX_Matrix* pMatrix, + CFX_FloatRect* pRect) const { + if (!pMatrix) { + if (!IsRect()) + return false; + + if (pRect) { + pRect->left = m_Points[0].m_Point.x; + pRect->right = m_Points[2].m_Point.x; + pRect->bottom = m_Points[0].m_Point.y; + pRect->top = m_Points[2].m_Point.y; + pRect->Normalize(); + } + return true; + } + + if (m_Points.size() != 5 && m_Points.size() != 4) + return false; + + if ((m_Points.size() == 5 && m_Points[0].m_Point != m_Points[4].m_Point) || + m_Points[1].m_Point == m_Points[3].m_Point) { + return false; + } + // Note, both x,y not equal. + if (m_Points.size() == 4 && m_Points[0].m_Point.x != m_Points[3].m_Point.x && + m_Points[0].m_Point.y != m_Points[3].m_Point.y) { + return false; + } + + CFX_PointF points[5]; + for (size_t i = 0; i < m_Points.size(); i++) { + points[i] = pMatrix->Transform(m_Points[i].m_Point); + + if (i == 0) + continue; + if (m_Points[i].m_Type != FXPT_TYPE::LineTo) + return false; + if (points[i].x != points[i - 1].x && points[i].y != points[i - 1].y) + return false; + } + + if (pRect) { + pRect->left = points[0].x; + pRect->right = points[2].x; + pRect->bottom = points[0].y; + pRect->top = points[2].y; + pRect->Normalize(); + } + return true; +} diff --git a/core/fxge/cfx_renderdevice.cpp b/core/fxge/cfx_renderdevice.cpp new file mode 100644 index 0000000000..266ae50e78 --- /dev/null +++ b/core/fxge/cfx_renderdevice.cpp @@ -0,0 +1,1135 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_renderdevice.h" + +#include +#include +#include +#include + +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxge/cfx_defaultrenderdevice.h" +#include "core/fxge/cfx_facecache.h" +#include "core/fxge/cfx_gemodule.h" +#include "core/fxge/cfx_graphstatedata.h" +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/dib/cfx_imagerenderer.h" +#include "core/fxge/ifx_renderdevicedriver.h" + +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ +#include "third_party/skia/include/core/SkTypes.h" +#endif + +namespace { + +void AdjustGlyphSpace(std::vector* pGlyphAndPos) { + ASSERT(pGlyphAndPos->size() > 1); + std::vector& glyphs = *pGlyphAndPos; + bool bVertical = glyphs.back().m_Origin.x == glyphs.front().m_Origin.x; + if (!bVertical && (glyphs.back().m_Origin.y != glyphs.front().m_Origin.y)) + return; + + for (size_t i = glyphs.size() - 1; i > 1; --i) { + FXTEXT_GLYPHPOS& next = glyphs[i]; + int next_origin = bVertical ? next.m_Origin.y : next.m_Origin.x; + float next_origin_f = bVertical ? next.m_fOrigin.y : next.m_fOrigin.x; + + FXTEXT_GLYPHPOS& current = glyphs[i - 1]; + int& current_origin = bVertical ? current.m_Origin.y : current.m_Origin.x; + float current_origin_f = + bVertical ? current.m_fOrigin.y : current.m_fOrigin.x; + + int space = next_origin - current_origin; + float space_f = next_origin_f - current_origin_f; + float error = fabs(space_f) - fabs(static_cast(space)); + if (error > 0.5f) + current_origin += space > 0 ? -1 : 1; + } +} + +const uint8_t g_TextGammaAdjust[256] = { + 0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, + 19, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, + 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, + 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, + 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, + 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, + 129, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, + 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 156, + 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, + 172, 173, 174, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, + 200, 201, 202, 203, 204, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, + 214, 215, 216, 217, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, + 228, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 239, 240, + 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 250, 251, 252, 253, 254, + 255, +}; + +int TextGammaAdjust(int value) { + ASSERT(value >= 0); + ASSERT(value <= 255); + return g_TextGammaAdjust[value]; +} + +int CalcAlpha(int src, int alpha) { + return src * alpha / 255; +} + +void Merge(uint8_t src, int channel, int alpha, uint8_t* dest) { + *dest = FXDIB_ALPHA_MERGE(*dest, channel, CalcAlpha(src, alpha)); +} + +void MergeGammaAdjust(uint8_t src, int channel, int alpha, uint8_t* dest) { + *dest = + FXDIB_ALPHA_MERGE(*dest, channel, CalcAlpha(TextGammaAdjust(src), alpha)); +} + +void MergeGammaAdjustBgr(const uint8_t* src, + int r, + int g, + int b, + int a, + uint8_t* dest) { + MergeGammaAdjust(src[0], b, a, &dest[0]); + MergeGammaAdjust(src[1], g, a, &dest[1]); + MergeGammaAdjust(src[2], r, a, &dest[2]); +} + +void MergeGammaAdjustRgb(const uint8_t* src, + int r, + int g, + int b, + int a, + uint8_t* dest) { + MergeGammaAdjust(src[2], b, a, &dest[0]); + MergeGammaAdjust(src[1], g, a, &dest[1]); + MergeGammaAdjust(src[0], r, a, &dest[2]); +} + +int AverageRgb(const uint8_t* src) { + return (src[0] + src[1] + src[2]) / 3; +} + +uint8_t CalculateDestAlpha(uint8_t back_alpha, int src_alpha) { + return back_alpha + src_alpha - back_alpha * src_alpha / 255; +} + +void ApplyDestAlpha(uint8_t back_alpha, + int src_alpha, + int r, + int g, + int b, + uint8_t* dest) { + uint8_t dest_alpha = CalculateDestAlpha(back_alpha, src_alpha); + int alpha_ratio = src_alpha * 255 / dest_alpha; + dest[0] = FXDIB_ALPHA_MERGE(dest[0], b, alpha_ratio); + dest[1] = FXDIB_ALPHA_MERGE(dest[1], g, alpha_ratio); + dest[2] = FXDIB_ALPHA_MERGE(dest[2], r, alpha_ratio); + dest[3] = dest_alpha; +} + +void NormalizeRgbDst(int src_value, int r, int g, int b, int a, uint8_t* dest) { + int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); + dest[0] = FXDIB_ALPHA_MERGE(dest[0], b, src_alpha); + dest[1] = FXDIB_ALPHA_MERGE(dest[1], g, src_alpha); + dest[2] = FXDIB_ALPHA_MERGE(dest[2], r, src_alpha); +} + +void NormalizeRgbSrc(int src_value, int r, int g, int b, int a, uint8_t* dest) { + int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); + if (src_alpha == 0) + return; + + dest[0] = FXDIB_ALPHA_MERGE(dest[0], b, src_alpha); + dest[1] = FXDIB_ALPHA_MERGE(dest[1], g, src_alpha); + dest[2] = FXDIB_ALPHA_MERGE(dest[2], r, src_alpha); +} + +void NormalizeArgbDest(int src_value, + int r, + int g, + int b, + int a, + uint8_t* dest) { + int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); + uint8_t back_alpha = dest[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest, FXARGB_MAKE(src_alpha, r, g, b)); + } else if (src_alpha != 0) { + ApplyDestAlpha(back_alpha, src_alpha, r, g, b, dest); + } +} + +void NormalizeArgbSrc(int src_value, + int r, + int g, + int b, + int a, + uint8_t* dest) { + int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); + if (src_alpha == 0) + return; + + uint8_t back_alpha = dest[3]; + if (back_alpha == 0) { + FXARGB_SETDIB(dest, FXARGB_MAKE(src_alpha, r, g, b)); + } else { + ApplyDestAlpha(back_alpha, src_alpha, r, g, b, dest); + } +} + +void NextPixel(uint8_t** src_scan, uint8_t** dst_scan, int bpp) { + *src_scan += 3; + *dst_scan += bpp; +} + +void SetAlpha(uint8_t* alpha) { + alpha[3] = 255; +} + +void SetAlphaDoNothing(uint8_t* alpha) {} + +void DrawNormalTextHelper(const CFX_RetainPtr& bitmap, + const CFX_RetainPtr& pGlyph, + int nrows, + int left, + int top, + int start_col, + int end_col, + bool bNormal, + bool bBGRStripe, + int x_subpixel, + int a, + int r, + int g, + int b) { + const bool has_alpha = bitmap->GetFormat() == FXDIB_Argb; + uint8_t* src_buf = pGlyph->GetBuffer(); + int src_pitch = pGlyph->GetPitch(); + uint8_t* dest_buf = bitmap->GetBuffer(); + int dest_pitch = bitmap->GetPitch(); + const int Bpp = has_alpha ? 4 : bitmap->GetBPP() / 8; + auto* pNormalizeSrcFunc = has_alpha ? &NormalizeArgbSrc : &NormalizeRgbDst; + auto* pNormalizeDstFunc = has_alpha ? &NormalizeArgbDest : &NormalizeRgbSrc; + auto* pSetAlpha = has_alpha ? &SetAlpha : &SetAlphaDoNothing; + + for (int row = 0; row < nrows; row++) { + int dest_row = row + top; + if (dest_row < 0 || dest_row >= bitmap->GetHeight()) + continue; + + uint8_t* src_scan = src_buf + row * src_pitch + (start_col - left) * 3; + uint8_t* dest_scan = dest_buf + dest_row * dest_pitch + start_col * Bpp; + if (bBGRStripe) { + if (x_subpixel == 0) { + for (int col = start_col; col < end_col; col++) { + if (has_alpha) { + Merge(src_scan[2], r, a, &dest_scan[2]); + Merge(src_scan[1], g, a, &dest_scan[1]); + Merge(src_scan[0], b, a, &dest_scan[0]); + } else { + MergeGammaAdjustBgr(&src_scan[0], r, g, b, a, &dest_scan[0]); + } + pSetAlpha(dest_scan); + NextPixel(&src_scan, &dest_scan, Bpp); + } + } else if (x_subpixel == 1) { + MergeGammaAdjust(src_scan[1], r, a, &dest_scan[2]); + MergeGammaAdjust(src_scan[0], g, a, &dest_scan[1]); + if (start_col > left) + MergeGammaAdjust(src_scan[-1], b, a, &dest_scan[0]); + pSetAlpha(dest_scan); + NextPixel(&src_scan, &dest_scan, Bpp); + for (int col = start_col + 1; col < end_col - 1; col++) { + MergeGammaAdjustBgr(&src_scan[-1], r, g, b, a, &dest_scan[0]); + pSetAlpha(dest_scan); + NextPixel(&src_scan, &dest_scan, Bpp); + } + } else { + MergeGammaAdjust(src_scan[0], r, a, &dest_scan[2]); + if (start_col > left) { + MergeGammaAdjust(src_scan[-1], g, a, &dest_scan[1]); + MergeGammaAdjust(src_scan[-2], b, a, &dest_scan[0]); + } + pSetAlpha(dest_scan); + NextPixel(&src_scan, &dest_scan, Bpp); + for (int col = start_col + 1; col < end_col - 1; col++) { + MergeGammaAdjustBgr(&src_scan[-2], r, g, b, a, &dest_scan[0]); + pSetAlpha(dest_scan); + NextPixel(&src_scan, &dest_scan, Bpp); + } + } + } else { + if (x_subpixel == 0) { + for (int col = start_col; col < end_col; col++) { + if (bNormal) { + int src_value = AverageRgb(&src_scan[0]); + pNormalizeDstFunc(src_value, r, g, b, a, dest_scan); + } else { + MergeGammaAdjustRgb(&src_scan[0], r, g, b, a, &dest_scan[0]); + pSetAlpha(dest_scan); + } + NextPixel(&src_scan, &dest_scan, Bpp); + } + } else if (x_subpixel == 1) { + if (bNormal) { + int src_value = start_col > left ? AverageRgb(&src_scan[-1]) + : (src_scan[0] + src_scan[1]) / 3; + pNormalizeSrcFunc(src_value, r, g, b, a, dest_scan); + } else { + if (start_col > left) + MergeGammaAdjust(src_scan[-1], r, a, &dest_scan[2]); + MergeGammaAdjust(src_scan[0], g, a, &dest_scan[1]); + MergeGammaAdjust(src_scan[1], b, a, &dest_scan[0]); + pSetAlpha(dest_scan); + } + NextPixel(&src_scan, &dest_scan, Bpp); + for (int col = start_col + 1; col < end_col; col++) { + if (bNormal) { + int src_value = AverageRgb(&src_scan[-1]); + pNormalizeDstFunc(src_value, r, g, b, a, dest_scan); + } else { + MergeGammaAdjustRgb(&src_scan[-1], r, g, b, a, &dest_scan[0]); + pSetAlpha(dest_scan); + } + NextPixel(&src_scan, &dest_scan, Bpp); + } + } else { + if (bNormal) { + int src_value = + start_col > left ? AverageRgb(&src_scan[-2]) : src_scan[0] / 3; + pNormalizeSrcFunc(src_value, r, g, b, a, dest_scan); + } else { + if (start_col > left) { + MergeGammaAdjust(src_scan[-2], r, a, &dest_scan[2]); + MergeGammaAdjust(src_scan[-1], g, a, &dest_scan[1]); + } + MergeGammaAdjust(src_scan[0], b, a, &dest_scan[0]); + pSetAlpha(dest_scan); + } + NextPixel(&src_scan, &dest_scan, Bpp); + for (int col = start_col + 1; col < end_col; col++) { + if (bNormal) { + int src_value = AverageRgb(&src_scan[-2]); + pNormalizeDstFunc(src_value, r, g, b, a, dest_scan); + } else { + MergeGammaAdjustRgb(&src_scan[-2], r, g, b, a, &dest_scan[0]); + pSetAlpha(dest_scan); + } + NextPixel(&src_scan, &dest_scan, Bpp); + } + } + } + } +} + +bool ShouldDrawDeviceText(const CFX_Font* pFont, uint32_t text_flags) { +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + if (text_flags & FXFONT_CIDFONT) + return false; + + const CFX_ByteString bsPsName = pFont->GetPsName(); + if (bsPsName.Find("+ZJHL") != -1) + return false; + + if (bsPsName == "CNAAJI+cmex10") + return false; +#endif + return true; +} + +} // namespace + +FXTEXT_CHARPOS::FXTEXT_CHARPOS() + : m_GlyphIndex(0), + m_FontCharWidth(0), +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ + m_ExtGID(0), +#endif + m_FallbackFontPosition(0), + m_bGlyphAdjust(false), + m_bFontStyle(false) { +} + +FXTEXT_CHARPOS::FXTEXT_CHARPOS(const FXTEXT_CHARPOS&) = default; + +FXTEXT_CHARPOS::~FXTEXT_CHARPOS(){}; + +CFX_RenderDevice::CFX_RenderDevice() + : m_pBitmap(nullptr), + m_Width(0), + m_Height(0), + m_bpp(0), + m_RenderCaps(0), + m_DeviceClass(0) {} + +CFX_RenderDevice::~CFX_RenderDevice() { + RestoreState(false); +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ + Flush(); +#endif +} + +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ +void CFX_RenderDevice::Flush() { + m_pDeviceDriver.reset(); +} +#endif + +void CFX_RenderDevice::SetDeviceDriver( + std::unique_ptr pDriver) { + m_pDeviceDriver = std::move(pDriver); + InitDeviceInfo(); +} + +void CFX_RenderDevice::InitDeviceInfo() { + m_Width = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_WIDTH); + m_Height = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_HEIGHT); + m_bpp = m_pDeviceDriver->GetDeviceCaps(FXDC_BITS_PIXEL); + m_RenderCaps = m_pDeviceDriver->GetDeviceCaps(FXDC_RENDER_CAPS); + m_DeviceClass = m_pDeviceDriver->GetDeviceCaps(FXDC_DEVICE_CLASS); + if (!m_pDeviceDriver->GetClipBox(&m_ClipBox)) { + m_ClipBox.left = 0; + m_ClipBox.top = 0; + m_ClipBox.right = m_Width; + m_ClipBox.bottom = m_Height; + } +} + +void CFX_RenderDevice::SaveState() { + m_pDeviceDriver->SaveState(); +} + +void CFX_RenderDevice::RestoreState(bool bKeepSaved) { + if (m_pDeviceDriver) { + m_pDeviceDriver->RestoreState(bKeepSaved); + UpdateClipBox(); + } +} + +int CFX_RenderDevice::GetDeviceCaps(int caps_id) const { + return m_pDeviceDriver->GetDeviceCaps(caps_id); +} + +CFX_Matrix CFX_RenderDevice::GetCTM() const { + return m_pDeviceDriver->GetCTM(); +} + +bool CFX_RenderDevice::CreateCompatibleBitmap( + const CFX_RetainPtr& pDIB, + int width, + int height) const { + if (m_RenderCaps & FXRC_CMYK_OUTPUT) { + return pDIB->Create( + width, height, + m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Cmyka : FXDIB_Cmyk); + } + if (m_RenderCaps & FXRC_BYTEMASK_OUTPUT) + return pDIB->Create(width, height, FXDIB_8bppMask); +#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_PATHS_ + return pDIB->Create( + width, height, + m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Argb : FXDIB_Rgb32); +#else + return pDIB->Create( + width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Argb : FXDIB_Rgb); +#endif +} + +bool CFX_RenderDevice::SetClip_PathFill(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + int fill_mode) { + if (!m_pDeviceDriver->SetClip_PathFill(pPathData, pObject2Device, + fill_mode)) { + return false; + } + UpdateClipBox(); + return true; +} + +bool CFX_RenderDevice::SetClip_PathStroke( + const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState) { + if (!m_pDeviceDriver->SetClip_PathStroke(pPathData, pObject2Device, + pGraphState)) { + return false; + } + UpdateClipBox(); + return true; +} + +bool CFX_RenderDevice::SetClip_Rect(const FX_RECT& rect) { + CFX_PathData path; + path.AppendRect(rect.left, rect.bottom, rect.right, rect.top); + if (!SetClip_PathFill(&path, nullptr, FXFILL_WINDING)) + return false; + + UpdateClipBox(); + return true; +} + +void CFX_RenderDevice::UpdateClipBox() { + if (m_pDeviceDriver->GetClipBox(&m_ClipBox)) + return; + m_ClipBox.left = 0; + m_ClipBox.top = 0; + m_ClipBox.right = m_Width; + m_ClipBox.bottom = m_Height; +} + +bool CFX_RenderDevice::DrawPathWithBlend(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState, + uint32_t fill_color, + uint32_t stroke_color, + int fill_mode, + int blend_type) { + uint8_t stroke_alpha = pGraphState ? FXARGB_A(stroke_color) : 0; + uint8_t fill_alpha = (fill_mode & 3) ? FXARGB_A(fill_color) : 0; + const std::vector& pPoints = pPathData->GetPoints(); + if (stroke_alpha == 0 && pPoints.size() == 2) { + CFX_PointF pos1 = pPoints[0].m_Point; + CFX_PointF pos2 = pPoints[1].m_Point; + if (pObject2Device) { + pos1 = pObject2Device->Transform(pos1); + pos2 = pObject2Device->Transform(pos2); + } + DrawCosmeticLine(pos1.x, pos1.y, pos2.x, pos2.y, fill_color, fill_mode, + blend_type); + return true; + } + + if ((pPoints.size() == 5 || pPoints.size() == 4) && stroke_alpha == 0) { + CFX_FloatRect rect_f; + if (!(fill_mode & FXFILL_RECT_AA) && + pPathData->IsRect(pObject2Device, &rect_f)) { + FX_RECT rect_i = rect_f.GetOuterRect(); + + // Depending on the top/bottom, left/right values of the rect it's + // possible to overflow the Width() and Height() calculations. Check that + // the rect will have valid dimension before continuing. + if (!rect_i.Valid()) + return false; + + int width = (int)ceil(rect_f.right - rect_f.left); + if (width < 1) { + width = 1; + if (rect_i.left == rect_i.right) + rect_i.right++; + } + int height = (int)ceil(rect_f.top - rect_f.bottom); + if (height < 1) { + height = 1; + if (rect_i.bottom == rect_i.top) + rect_i.bottom++; + } + if (rect_i.Width() >= width + 1) { + if (rect_f.left - (float)(rect_i.left) > + (float)(rect_i.right) - rect_f.right) { + rect_i.left++; + } else { + rect_i.right--; + } + } + if (rect_i.Height() >= height + 1) { + if (rect_f.top - (float)(rect_i.top) > + (float)(rect_i.bottom) - rect_f.bottom) { + rect_i.top++; + } else { + rect_i.bottom--; + } + } + if (FillRectWithBlend(&rect_i, fill_color, blend_type)) + return true; + } + } + if ((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) && + !(fill_mode & FX_FILL_TEXT_MODE)) { + CFX_PathData newPath; + bool bThin = false; + bool setIdentity = false; + if (pPathData->GetZeroAreaPath(pObject2Device, + !!m_pDeviceDriver->GetDriverType(), &newPath, + &bThin, &setIdentity)) { + CFX_GraphStateData graphState; + graphState.m_LineWidth = 0.0f; + + uint32_t strokecolor = fill_color; + if (bThin) + strokecolor = (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff)); + + const CFX_Matrix* pMatrix = nullptr; + if (pObject2Device && !pObject2Device->IsIdentity() && !setIdentity) + pMatrix = pObject2Device; + + int smooth_path = FX_ZEROAREA_FILL; + if (fill_mode & FXFILL_NOPATHSMOOTH) + smooth_path |= FXFILL_NOPATHSMOOTH; + + m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor, + smooth_path, blend_type); + } + } + if ((fill_mode & 3) && fill_alpha && stroke_alpha < 0xff && + (fill_mode & FX_FILL_STROKE)) { + if (m_RenderCaps & FXRC_FILLSTROKE_PATH) { + return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState, + fill_color, stroke_color, fill_mode, + blend_type); + } + return DrawFillStrokePath(pPathData, pObject2Device, pGraphState, + fill_color, stroke_color, fill_mode, blend_type); + } + return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState, + fill_color, stroke_color, fill_mode, + blend_type); +} + +// This can be removed once PDFium entirely relies on Skia +bool CFX_RenderDevice::DrawFillStrokePath(const CFX_PathData* pPathData, + const CFX_Matrix* pObject2Device, + const CFX_GraphStateData* pGraphState, + uint32_t fill_color, + uint32_t stroke_color, + int fill_mode, + int blend_type) { + if (!(m_RenderCaps & FXRC_GET_BITS)) + return false; + CFX_FloatRect bbox; + if (pGraphState) { + bbox = pPathData->GetBoundingBox(pGraphState->m_LineWidth, + pGraphState->m_MiterLimit); + } else { + bbox = pPathData->GetBoundingBox(); + } + if (pObject2Device) + pObject2Device->TransformRect(bbox); + + CFX_Matrix ctm = GetCTM(); + float fScaleX = fabs(ctm.a); + float fScaleY = fabs(ctm.d); + FX_RECT rect = bbox.GetOuterRect(); + auto bitmap = pdfium::MakeRetain(); + auto Backdrop = pdfium::MakeRetain(); + if (!CreateCompatibleBitmap(bitmap, FXSYS_round(rect.Width() * fScaleX), + FXSYS_round(rect.Height() * fScaleY))) { + return false; + } + if (bitmap->HasAlpha()) { + bitmap->Clear(0); + Backdrop->Copy(bitmap); + } else { + if (!m_pDeviceDriver->GetDIBits(bitmap, rect.left, rect.top)) + return false; + Backdrop->Copy(bitmap); + } + CFX_DefaultRenderDevice bitmap_device; + bitmap_device.Attach(bitmap, false, Backdrop, true); + + CFX_Matrix matrix; + if (pObject2Device) + matrix = *pObject2Device; + matrix.Translate(-rect.left, -rect.top); + matrix.Concat(CFX_Matrix(fScaleX, 0, 0, fScaleY, 0, 0)); + if (!bitmap_device.GetDeviceDriver()->DrawPath( + pPathData, &matrix, pGraphState, fill_color, stroke_color, fill_mode, + blend_type)) { + return false; + } +#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ + bitmap_device.GetDeviceDriver()->Flush(); +#endif + FX_RECT src_rect(0, 0, FXSYS_round(rect.Width() * fScaleX), + FXSYS_round(rect.Height() * fScaleY)); + return m_pDeviceDriver->SetDIBits(bitmap, 0, &src_rect, rect.left, rect.top, + FXDIB_BLEND_NORMAL); +} + +bool CFX_RenderDevice::SetPixel(int x, int y, uint32_t color) { + if (m_pDeviceDriver->SetPixel(x, y, color)) + return true; + + FX_RECT rect(x, y, x + 1, y + 1); + return FillRectWithBlend(&rect, color, FXDIB_BLEND_NORMAL); +} + +bool CFX_RenderDevice::FillRectWithBlend(const FX_RECT* pRect, + uint32_t fill_color, + int blend_type) { + if (m_pDeviceDriver->FillRectWithBlend(pRect, fill_color, blend_type)) + return true; + + if (!(m_RenderCaps & FXRC_GET_BITS)) + return false; + + auto bitmap = pdfium::MakeRetain(); + if (!CreateCompatibleBitmap(bitmap, pRect->Width(), pRect->Height())) + return false; + + if (!m_pDeviceDriver->GetDIBits(bitmap, pRect->left, pRect->top)) + return false; + + if (!bitmap->CompositeRect(0, 0, pRect->Width(), pRect->Height(), fill_color, + 0)) { + return false; + } + FX_RECT src_rect(0, 0, pRect->Width(), pRect->Height()); + m_pDeviceDriver->SetDIBits(bitmap, 0, &src_rect, pRect->left, pRect->top, + FXDIB_BLEND_NORMAL); + return true; +} + +bool CFX_RenderDevice::DrawCosmeticLine(float x1, + float y1, + float x2, + float y2, + uint32_t color, + int fill_mode, + int blend_type) { + if ((color >= 0xff000000) && + m_pDeviceDriver->DrawCosmeticLine(x1, y1, x2, y2, color, blend_type)) { + return true; + } + CFX_GraphStateData graph_state; + CFX_PathData path; + path.AppendPoint(CFX_PointF(x1, y1), FXPT_TYPE::MoveTo, false); + path.AppendPoint(CFX_PointF(x2, y2), FXPT_TYPE::LineTo, false); + return m_pDeviceDriver->DrawPath(&path, nullptr, &graph_state, 0, color, + fill_mode, blend_type); +} + +bool CFX_RenderDevice::GetDIBits(const CFX_RetainPtr& pBitmap, + int left, + int top) { + if (!(m_RenderCaps & FXRC_GET_BITS)) + return false; + return m_pDeviceDriver->GetDIBits(pBitmap, left, top); +} + +CFX_RetainPtr CFX_RenderDevice::GetBackDrop() { + return m_pDeviceDriver->GetBackDrop(); +} + +bool CFX_RenderDevice::SetDIBitsWithBlend( + const CFX_RetainPtr& pBitmap, + int left, + int top, + int blend_mode) { + ASSERT(!pBitmap->IsAlphaMask()); + CFX_Matrix ctm = GetCTM(); + float fScaleX = fabs(ctm.a); + float fScaleY = fabs(ctm.d); + FX_RECT dest_rect(left, top, + FXSYS_round(left + pBitmap->GetWidth() / fScaleX), + FXSYS_round(top + pBitmap->GetHeight() / fScaleY)); + dest_rect.Intersect(m_ClipBox); + if (dest_rect.IsEmpty()) + return true; + + FX_RECT src_rect(dest_rect.left - left, dest_rect.top - top, + dest_rect.left - left + dest_rect.Width(), + dest_rect.top - top + dest_rect.Height()); + src_rect.left = FXSYS_round(src_rect.left * fScaleX); + src_rect.top = FXSYS_round(src_rect.top * fScaleY); + src_rect.right = FXSYS_round(src_rect.right * fScaleX); + src_rect.bottom = FXSYS_round(src_rect.bottom * fScaleY); + if ((blend_mode != FXDIB_BLEND_NORMAL && !(m_RenderCaps & FXRC_BLEND_MODE)) || + (pBitmap->HasAlpha() && !(m_RenderCaps & FXRC_ALPHA_IMAGE))) { + if (!(m_RenderCaps & FXRC_GET_BITS)) + return false; + + int bg_pixel_width = FXSYS_round(dest_rect.Width() * fScaleX); + int bg_pixel_height = FXSYS_round(dest_rect.Height() * fScaleY); + auto background = pdfium::MakeRetain(); + if (!background->Create( + bg_pixel_width, bg_pixel_height, + (m_RenderCaps & FXRC_CMYK_OUTPUT) ? FXDIB_Cmyk : FXDIB_Rgb32)) { + return false; + } + if (!m_pDeviceDriver->GetDIBits(background, dest_rect.left, + dest_rect.top)) { + return false; + } + if (!background->CompositeBitmap(0, 0, bg_pixel_width, bg_pixel_height, + pBitmap, src_rect.left, src_rect.top, + blend_mode, nullptr, false)) { + return false; + } + FX_RECT rect(0, 0, bg_pixel_width, bg_pixel_height); + return m_pDeviceDriver->SetDIBits(background, 0, &rect, dest_rect.left, + dest_rect.top, FXDIB_BLEND_NORMAL); + } + return m_pDeviceDriver->SetDIBits(pBitmap, 0, &src_rect, dest_rect.left, + dest_rect.top, blend_mode); +} + +bool CFX_RenderDevice::StretchDIBitsWithFlagsAndBlend( + const CFX_RetainPtr& pBitmap, + int left, + int top, + int dest_width, + int dest_height, + uint32_t flags, + int blend_mode) { + FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); + FX_RECT clip_box = m_ClipBox; + clip_box.Intersect(dest_rect); + if (clip_box.IsEmpty()) + return true; + return m_pDeviceDriver->StretchDIBits(pBitmap, 0, left, top, dest_width, + dest_height, &clip_box, flags, + blend_mode); +} + +bool CFX_RenderDevice::SetBitMask(const CFX_RetainPtr& pBitmap, + int left, + int top, + uint32_t argb) { + FX_RECT src_rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); + return m_pDeviceDriver->SetDIBits(pBitmap, argb, &src_rect, left, top, + FXDIB_BLEND_NORMAL); +} + +bool CFX_RenderDevice::StretchBitMask( + const CFX_RetainPtr& pBitmap, + int left, + int top, + int dest_width, + int dest_height, + uint32_t color) { + return StretchBitMaskWithFlags(pBitmap, left, top, dest_width, dest_height, + color, 0); +} + +bool CFX_RenderDevice::StretchBitMaskWithFlags( + const CFX_RetainPtr& pBitmap, + int left, + int top, + int dest_width, + int dest_height, + uint32_t argb, + uint32_t flags) { + FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); + FX_RECT clip_box = m_ClipBox; + clip_box.Intersect(dest_rect); + return m_pDeviceDriver->StretchDIBits(pBitmap, argb, left, top, dest_width, + dest_height, &clip_box, flags, + FXDIB_BLEND_NORMAL); +} + +bool CFX_RenderDevice::StartDIBitsWithBlend( + const CFX_RetainPtr& pBitmap, + int bitmap_alpha, + uint32_t argb, + const CFX_Matrix* pMatrix, + uint32_t flags, + std::unique_ptr* handle, + int blend_mode) { + return m_pDeviceDriver->StartDIBits(pBitmap, bitmap_alpha, argb, pMatrix, + flags, handle, blend_mode); +} + +bool CFX_RenderDevice::ContinueDIBits(CFX_ImageRenderer* handle, + IFX_Pause* pPause) { + return m_pDeviceDriver->ContinueDIBits(handle, pPause); +} + +#ifdef _SKIA_SUPPORT_ +void CFX_RenderDevice::DebugVerifyBitmapIsPreMultiplied() const { + SkASSERT(0); +} + +bool CFX_RenderDevice::SetBitsWithMask( + const CFX_RetainPtr& pBitmap, + const CFX_RetainPtr& pMask, + int left, + int top, + int bitmap_alpha, + int blend_type) { + return m_pDeviceDriver->SetBitsWithMask(pBitmap, pMask, left, top, + bitmap_alpha, blend_type); +} +#endif + +bool CFX_RenderDevice::DrawNormalText(int nChars, + const FXTEXT_CHARPOS* pCharPos, + CFX_Font* pFont, + float font_size, + const CFX_Matrix* pText2Device, + uint32_t fill_color, + uint32_t text_flags) { + int nativetext_flags = text_flags; + if (m_DeviceClass != FXDC_DISPLAY) { + if (!(text_flags & FXTEXT_PRINTGRAPHICTEXT)) { + if (ShouldDrawDeviceText(pFont, text_flags) && + m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pText2Device, + font_size, fill_color)) { + return true; + } + } + if (FXARGB_A(fill_color) < 255) + return false; + } else if (!(text_flags & FXTEXT_NO_NATIVETEXT)) { + if (ShouldDrawDeviceText(pFont, text_flags) && + m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pText2Device, + font_size, fill_color)) { + return true; + } + } + CFX_Matrix char2device; + CFX_Matrix text2Device; + if (pText2Device) { + char2device = *pText2Device; + text2Device = *pText2Device; + } + + char2device.Scale(font_size, -font_size); + if (fabs(char2device.a) + fabs(char2device.b) > 50 * 1.0f || + ((m_DeviceClass == FXDC_PRINTER) && + !(text_flags & FXTEXT_PRINTIMAGETEXT))) { + if (pFont->GetFace()) { + int nPathFlags = + (text_flags & FXTEXT_NOSMOOTH) == 0 ? 0 : FXFILL_NOPATHSMOOTH; + return DrawTextPath(nChars, pCharPos, pFont, font_size, pText2Device, + nullptr, nullptr, fill_color, 0, nullptr, nPathFlags); + } + } + int anti_alias = FXFT_RENDER_MODE_MONO; + bool bNormal = false; + if ((text_flags & FXTEXT_NOSMOOTH) == 0) { + if (m_DeviceClass == FXDC_DISPLAY && m_bpp > 1) { + if (!CFX_GEModule::Get()->GetFontMgr()->FTLibrarySupportsHinting()) { + // Some Freetype implementations (like the one packaged with Fedora) do + // not support hinting due to patents 6219025, 6239783, 6307566, + // 6225973, 6243070, 6393145, 6421054, 6282327, and 6624828; the latest + // one expires 10/7/19. This makes LCD antialiasing very ugly, so we + // instead fall back on NORMAL antialiasing. + anti_alias = FXFT_RENDER_MODE_NORMAL; + } else if ((m_RenderCaps & (FXRC_ALPHA_OUTPUT | FXRC_CMYK_OUTPUT))) { + anti_alias = FXFT_RENDER_MODE_LCD; + bNormal = true; + } else if (m_bpp < 16) { + anti_alias = FXFT_RENDER_MODE_NORMAL; + } else { + anti_alias = FXFT_RENDER_MODE_LCD; + + bool bClearType = false; + if (pFont->GetFace()) + bClearType = !!(text_flags & FXTEXT_CLEARTYPE); + bNormal = !bClearType; + } + } + } + std::vector glyphs(nChars); + CFX_Matrix matrixCTM = GetCTM(); + float scale_x = fabs(matrixCTM.a); + float scale_y = fabs(matrixCTM.d); + CFX_Matrix deviceCtm = char2device; + CFX_Matrix m(scale_x, 0, 0, scale_y, 0, 0); + deviceCtm.Concat(m); + text2Device.Concat(m); + + for (size_t i = 0; i < glyphs.size(); ++i) { + FXTEXT_GLYPHPOS& glyph = glyphs[i]; + const FXTEXT_CHARPOS& charpos = pCharPos[i]; + + glyph.m_fOrigin = text2Device.Transform(charpos.m_Origin); + if (anti_alias < FXFT_RENDER_MODE_LCD) + glyph.m_Origin.x = FXSYS_round(glyph.m_fOrigin.x); + else + glyph.m_Origin.x = static_cast(floor(glyph.m_fOrigin.x)); + glyph.m_Origin.y = FXSYS_round(glyph.m_fOrigin.y); + + if (charpos.m_bGlyphAdjust) { + CFX_Matrix new_matrix( + charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], + charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); + new_matrix.Concat(deviceCtm); + glyph.m_pGlyph = pFont->LoadGlyphBitmap( + charpos.m_GlyphIndex, charpos.m_bFontStyle, &new_matrix, + charpos.m_FontCharWidth, anti_alias, nativetext_flags); + } else { + glyph.m_pGlyph = pFont->LoadGlyphBitmap( + charpos.m_GlyphIndex, charpos.m_bFontStyle, &deviceCtm, + charpos.m_FontCharWidth, anti_alias, nativetext_flags); + } + } + if (anti_alias < FXFT_RENDER_MODE_LCD && glyphs.size() > 1) + AdjustGlyphSpace(&glyphs); + + FX_RECT bmp_rect1 = FXGE_GetGlyphsBBox(glyphs, anti_alias, 1.0f, 1.0f); + if (scale_x > 1 && scale_y > 1) { + bmp_rect1.left--; + bmp_rect1.top--; + bmp_rect1.right++; + bmp_rect1.bottom++; + } + FX_RECT bmp_rect(FXSYS_round((float)(bmp_rect1.left) / scale_x), + FXSYS_round((float)(bmp_rect1.top) / scale_y), + FXSYS_round((float)bmp_rect1.right / scale_x), + FXSYS_round((float)bmp_rect1.bottom / scale_y)); + bmp_rect.Intersect(m_ClipBox); + if (bmp_rect.IsEmpty()) + return true; + + int pixel_width = FXSYS_round(bmp_rect.Width() * scale_x); + int pixel_height = FXSYS_round(bmp_rect.Height() * scale_y); + int pixel_left = FXSYS_round(bmp_rect.left * scale_x); + int pixel_top = FXSYS_round(bmp_rect.top * scale_y); + if (anti_alias == FXFT_RENDER_MODE_MONO) { + auto bitmap = pdfium::MakeRetain(); + if (!bitmap->Create(pixel_width, pixel_height, FXDIB_1bppMask)) + return false; + bitmap->Clear(0); + for (const FXTEXT_GLYPHPOS& glyph : glyphs) { + if (!glyph.m_pGlyph) + continue; + CFX_RetainPtr pGlyph = glyph.m_pGlyph->m_pBitmap; + bitmap->TransferBitmap( + glyph.m_Origin.x + glyph.m_pGlyph->m_Left - pixel_left, + glyph.m_Origin.y - glyph.m_pGlyph->m_Top - pixel_top, + pGlyph->GetWidth(), pGlyph->GetHeight(), pGlyph, 0, 0); + } + return SetBitMask(bitmap, bmp_rect.left, bmp_rect.top, fill_color); + } + auto bitmap = pdfium::MakeRetain(); + if (m_bpp == 8) { + if (!bitmap->Create(pixel_width, pixel_height, FXDIB_8bppMask)) + return false; + } else { + if (!CreateCompatibleBitmap(bitmap, pixel_width, pixel_height)) + return false; + } + if (!bitmap->HasAlpha() && !bitmap->IsAlphaMask()) { + bitmap->Clear(0xFFFFFFFF); + if (!GetDIBits(bitmap, bmp_rect.left, bmp_rect.top)) + return false; + } else { + bitmap->Clear(0); + if (bitmap->m_pAlphaMask) + bitmap->m_pAlphaMask->Clear(0); + } + int dest_width = pixel_width; + int a = 0; + int r = 0; + int g = 0; + int b = 0; + if (anti_alias == FXFT_RENDER_MODE_LCD) + std::tie(a, r, g, b) = ArgbDecode(fill_color); + + for (const FXTEXT_GLYPHPOS& glyph : glyphs) { + if (!glyph.m_pGlyph) + continue; + + pdfium::base::CheckedNumeric left = glyph.m_Origin.x; + left += glyph.m_pGlyph->m_Left; + left -= pixel_left; + if (!left.IsValid()) + return false; + + pdfium::base::CheckedNumeric top = glyph.m_Origin.y; + top -= glyph.m_pGlyph->m_Top; + top -= pixel_top; + if (!top.IsValid()) + return false; + + CFX_RetainPtr pGlyph = glyph.m_pGlyph->m_pBitmap; + int ncols = pGlyph->GetWidth(); + int nrows = pGlyph->GetHeight(); + if (anti_alias == FXFT_RENDER_MODE_NORMAL) { + if (!bitmap->CompositeMask(left.ValueOrDie(), top.ValueOrDie(), ncols, + nrows, pGlyph, fill_color, 0, 0, + FXDIB_BLEND_NORMAL, nullptr, false, 0)) { + return false; + } + continue; + } + bool bBGRStripe = !!(text_flags & FXTEXT_BGR_STRIPE); + ncols /= 3; + int x_subpixel = static_cast(glyph.m_fOrigin.x * 3) % 3; + int start_col = + pdfium::base::ValueOrDieForType(pdfium::base::CheckMax(left, 0)); + pdfium::base::CheckedNumeric end_col_safe = left; + end_col_safe += ncols; + if (!end_col_safe.IsValid()) + return false; + + int end_col = + std::min(static_cast(end_col_safe.ValueOrDie()), dest_width); + if (start_col >= end_col) + continue; + + DrawNormalTextHelper(bitmap, pGlyph, nrows, left.ValueOrDie(), + top.ValueOrDie(), start_col, end_col, bNormal, + bBGRStripe, x_subpixel, a, r, g, b); + } + if (bitmap->IsAlphaMask()) + SetBitMask(bitmap, bmp_rect.left, bmp_rect.top, fill_color); + else + SetDIBits(bitmap, bmp_rect.left, bmp_rect.top); + return true; +} + +bool CFX_RenderDevice::DrawTextPath(int nChars, + const FXTEXT_CHARPOS* pCharPos, + CFX_Font* pFont, + float font_size, + const CFX_Matrix* pText2User, + const CFX_Matrix* pUser2Device, + const CFX_GraphStateData* pGraphState, + uint32_t fill_color, + FX_ARGB stroke_color, + CFX_PathData* pClippingPath, + int nFlag) { + for (int iChar = 0; iChar < nChars; iChar++) { + const FXTEXT_CHARPOS& charpos = pCharPos[iChar]; + CFX_Matrix matrix; + if (charpos.m_bGlyphAdjust) { + matrix = CFX_Matrix(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], + charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], + 0, 0); + } + matrix.Concat(CFX_Matrix(font_size, 0, 0, font_size, charpos.m_Origin.x, + charpos.m_Origin.y)); + const CFX_PathData* pPath = + pFont->LoadGlyphPath(charpos.m_GlyphIndex, charpos.m_FontCharWidth); + if (!pPath) + continue; + + matrix.Concat(*pText2User); + + CFX_PathData TransformedPath(*pPath); + TransformedPath.Transform(&matrix); + if (fill_color || stroke_color) { + int fill_mode = nFlag; + if (fill_color) + fill_mode |= FXFILL_WINDING; + fill_mode |= FX_FILL_TEXT_MODE; + if (!DrawPathWithBlend(&TransformedPath, pUser2Device, pGraphState, + fill_color, stroke_color, fill_mode, + FXDIB_BLEND_NORMAL)) { + return false; + } + } + if (pClippingPath) + pClippingPath->Append(&TransformedPath, pUser2Device); + } + return true; +} + +CFX_RenderDevice::StateRestorer::StateRestorer(CFX_RenderDevice* pDevice) + : m_pDevice(pDevice) { + m_pDevice->SaveState(); +} + +CFX_RenderDevice::StateRestorer::~StateRestorer() { + m_pDevice->RestoreState(false); +} diff --git a/core/fxge/cfx_substfont.cpp b/core/fxge/cfx_substfont.cpp new file mode 100644 index 0000000000..27d3bc3059 --- /dev/null +++ b/core/fxge/cfx_substfont.cpp @@ -0,0 +1,19 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_substfont.h" + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/fx_font.h" + +CFX_SubstFont::CFX_SubstFont() + : m_Charset(FX_CHARSET_ANSI), + m_SubstFlags(0), + m_Weight(0), + m_ItalicAngle(0), + m_bSubstCJK(false), + m_WeightCJK(0), + m_bItalicCJK(false) {} diff --git a/core/fxge/cfx_unicodeencoding.cpp b/core/fxge/cfx_unicodeencoding.cpp new file mode 100644 index 0000000000..494ae33bb0 --- /dev/null +++ b/core/fxge/cfx_unicodeencoding.cpp @@ -0,0 +1,34 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_unicodeencoding.h" + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/fx_font.h" +#include "core/fxge/fx_freetype.h" + +CFX_UnicodeEncoding::CFX_UnicodeEncoding(CFX_Font* pFont) : m_pFont(pFont) {} + +CFX_UnicodeEncoding::~CFX_UnicodeEncoding() {} + +uint32_t CFX_UnicodeEncoding::GlyphFromCharCode(uint32_t charcode) { + FXFT_Face face = m_pFont->GetFace(); + if (!face) + return charcode; + + if (FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE) == 0) + return FXFT_Get_Char_Index(face, charcode); + + if (m_pFont->GetSubstFont() && + m_pFont->GetSubstFont()->m_Charset == FX_CHARSET_Symbol) { + uint32_t index = 0; + if (FXFT_Select_Charmap(face, FXFT_ENCODING_MS_SYMBOL) == 0) + index = FXFT_Get_Char_Index(face, charcode); + if (!index && !FXFT_Select_Charmap(face, FXFT_ENCODING_APPLE_ROMAN)) + return FXFT_Get_Char_Index(face, charcode); + } + return charcode; +} diff --git a/core/fxge/cfx_unicodeencodingex.cpp b/core/fxge/cfx_unicodeencodingex.cpp new file mode 100644 index 0000000000..3f28d4295e --- /dev/null +++ b/core/fxge/cfx_unicodeencodingex.cpp @@ -0,0 +1,103 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cfx_unicodeencodingex.h" + +#include + +#include "core/fpdfapi/font/cpdf_font.h" +#include "core/fxge/fx_font.h" +#include "core/fxge/fx_freetype.h" +#include "third_party/base/ptr_util.h" + +namespace { + +const uint32_t g_EncodingID[] = { + FXFM_ENCODING_MS_SYMBOL, FXFM_ENCODING_UNICODE, + FXFM_ENCODING_MS_SJIS, FXFM_ENCODING_MS_GB2312, + FXFM_ENCODING_MS_BIG5, FXFM_ENCODING_MS_WANSUNG, + FXFM_ENCODING_MS_JOHAB, FXFM_ENCODING_ADOBE_STANDARD, + FXFM_ENCODING_ADOBE_EXPERT, FXFM_ENCODING_ADOBE_CUSTOM, + FXFM_ENCODING_ADOBE_LATIN_1, FXFM_ENCODING_OLD_LATIN_2, + FXFM_ENCODING_APPLE_ROMAN, +}; + +std::unique_ptr FXFM_CreateFontEncoding( + CFX_Font* pFont, + uint32_t nEncodingID) { + if (FXFT_Select_Charmap(pFont->GetFace(), nEncodingID)) + return nullptr; + return pdfium::MakeUnique(pFont, nEncodingID); +} + +} // namespace + +CFX_UnicodeEncodingEx::CFX_UnicodeEncodingEx(CFX_Font* pFont, + uint32_t EncodingID) + : CFX_UnicodeEncoding(pFont), m_nEncodingID(EncodingID) {} + +CFX_UnicodeEncodingEx::~CFX_UnicodeEncodingEx() {} + +uint32_t CFX_UnicodeEncodingEx::GlyphFromCharCode(uint32_t charcode) { + FXFT_Face face = m_pFont->GetFace(); + FT_UInt nIndex = FXFT_Get_Char_Index(face, charcode); + if (nIndex > 0) + return nIndex; + int nmaps = FXFT_Get_Face_CharmapCount(face); + int m = 0; + while (m < nmaps) { + uint32_t nEncodingID = + FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[m++]); + if (m_nEncodingID == nEncodingID) + continue; + int error = FXFT_Select_Charmap(face, nEncodingID); + if (error) + continue; + nIndex = FXFT_Get_Char_Index(face, charcode); + if (nIndex > 0) { + m_nEncodingID = nEncodingID; + return nIndex; + } + } + FXFT_Select_Charmap(face, m_nEncodingID); + return 0; +} + +uint32_t CFX_UnicodeEncodingEx::CharCodeFromUnicode(wchar_t Unicode) const { + if (m_nEncodingID == FXFM_ENCODING_UNICODE || + m_nEncodingID == FXFM_ENCODING_MS_SYMBOL) { + return Unicode; + } + FXFT_Face face = m_pFont->GetFace(); + int nmaps = FXFT_Get_Face_CharmapCount(face); + for (int i = 0; i < nmaps; i++) { + int nEncodingID = + FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[i]); + if (nEncodingID == FXFM_ENCODING_UNICODE || + nEncodingID == FXFM_ENCODING_MS_SYMBOL) { + return Unicode; + } + } + return CPDF_Font::kInvalidCharCode; +} + +std::unique_ptr FX_CreateFontEncodingEx( + CFX_Font* pFont, + uint32_t nEncodingID) { + if (!pFont || !pFont->GetFace()) + return nullptr; + + if (nEncodingID != FXFM_ENCODING_NONE) + return FXFM_CreateFontEncoding(pFont, nEncodingID); + + for (size_t i = 0; i < FX_ArraySize(g_EncodingID); ++i) { + std::unique_ptr pFontEncoding = + FXFM_CreateFontEncoding(pFont, g_EncodingID[i]); + if (pFontEncoding) + return pFontEncoding; + } + return nullptr; +} diff --git a/core/fxge/cttfontdesc.cpp b/core/fxge/cttfontdesc.cpp new file mode 100644 index 0000000000..cf900a8b95 --- /dev/null +++ b/core/fxge/cttfontdesc.cpp @@ -0,0 +1,38 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include "core/fxge/cttfontdesc.h" + +#include "core/fxge/fx_freetype.h" + +CTTFontDesc::~CTTFontDesc() { + if (m_Type == 1) { + if (m_SingleFace) + FXFT_Done_Face(m_SingleFace); + } else if (m_Type == 2) { + for (int i = 0; i < 16; i++) { + if (m_TTCFaces[i]) + FXFT_Done_Face(m_TTCFaces[i]); + } + } + FX_Free(m_pFontData); +} + +int CTTFontDesc::ReleaseFace(FXFT_Face face) { + if (m_Type == 1) { + if (m_SingleFace != face) + return -1; + } else if (m_Type == 2) { + int i; + for (i = 0; i < 16; i++) { + if (m_TTCFaces[i] == face) + break; + } + if (i == 16) + return -1; + } + return --m_RefCount; +} diff --git a/core/fxge/cttfontdesc.h b/core/fxge/cttfontdesc.h new file mode 100644 index 0000000000..6eb36360c0 --- /dev/null +++ b/core/fxge/cttfontdesc.h @@ -0,0 +1,40 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_CTTFONTDESC_H_ +#define CORE_FXGE_CTTFONTDESC_H_ + +#include "core/fxcrt/fx_system.h" +#include "core/fxge/fx_font.h" + +#define FX_FONT_FLAG_SERIF 0x01 +#define FX_FONT_FLAG_FIXEDPITCH 0x02 +#define FX_FONT_FLAG_ITALIC 0x04 +#define FX_FONT_FLAG_BOLD 0x08 +#define FX_FONT_FLAG_SYMBOLIC_SYMBOL 0x10 +#define FX_FONT_FLAG_SYMBOLIC_DINGBATS 0x20 +#define FX_FONT_FLAG_MULTIPLEMASTER 0x40 + +class CTTFontDesc { + public: + CTTFontDesc() : m_Type(0), m_pFontData(nullptr), m_RefCount(0) {} + ~CTTFontDesc(); + // ret < 0, releaseface not appropriate for this object. + // ret == 0, object released + // ret > 0, object still alive, other referrers. + int ReleaseFace(FXFT_Face face); + + int m_Type; + + union { + FXFT_Face m_SingleFace; + FXFT_Face m_TTCFaces[16]; + }; + uint8_t* m_pFontData; + int m_RefCount; +}; + +#endif // CORE_FXGE_CTTFONTDESC_H_ diff --git a/core/fxge/dib/cfx_bitmapcomposer.cpp b/core/fxge/dib/cfx_bitmapcomposer.cpp index 3f75fae1b6..8664606645 100644 --- a/core/fxge/dib/cfx_bitmapcomposer.cpp +++ b/core/fxge/dib/cfx_bitmapcomposer.cpp @@ -7,8 +7,8 @@ #include "core/fxge/dib/cfx_bitmapcomposer.h" #include "core/fxcodec/fx_codec.h" +#include "core/fxge/cfx_cliprgn.h" #include "core/fxge/dib/cfx_dibitmap.h" -#include "core/fxge/ge/cfx_cliprgn.h" CFX_BitmapComposer::CFX_BitmapComposer() : m_bRgbByteOrder(false), m_BlendType(FXDIB_BLEND_NORMAL) {} diff --git a/core/fxge/dib/cfx_dibitmap.cpp b/core/fxge/dib/cfx_dibitmap.cpp index 43b0da0edf..02c3543c85 100644 --- a/core/fxge/dib/cfx_dibitmap.cpp +++ b/core/fxge/dib/cfx_dibitmap.cpp @@ -11,8 +11,8 @@ #include #include "core/fxcodec/fx_codec.h" +#include "core/fxge/cfx_cliprgn.h" #include "core/fxge/dib/cfx_scanlinecompositor.h" -#include "core/fxge/ge/cfx_cliprgn.h" #include "third_party/base/ptr_util.h" #define MAX_OOM_LIMIT 12000000 diff --git a/core/fxge/dib/cfx_dibsource.cpp b/core/fxge/dib/cfx_dibsource.cpp index 458baa56ca..e19619df1d 100644 --- a/core/fxge/dib/cfx_dibsource.cpp +++ b/core/fxge/dib/cfx_dibsource.cpp @@ -12,11 +12,11 @@ #include #include "core/fxcodec/fx_codec.h" +#include "core/fxge/cfx_cliprgn.h" #include "core/fxge/dib/cfx_bitmapstorer.h" #include "core/fxge/dib/cfx_dibitmap.h" #include "core/fxge/dib/cfx_imagestretcher.h" #include "core/fxge/dib/cfx_imagetransformer.h" -#include "core/fxge/ge/cfx_cliprgn.h" #include "third_party/base/logging.h" #include "third_party/base/ptr_util.h" diff --git a/core/fxge/dib/cfx_imagerenderer.cpp b/core/fxge/dib/cfx_imagerenderer.cpp index db3fe02bd5..6448014ba5 100644 --- a/core/fxge/dib/cfx_imagerenderer.cpp +++ b/core/fxge/dib/cfx_imagerenderer.cpp @@ -8,9 +8,9 @@ #include +#include "core/fxge/cfx_cliprgn.h" #include "core/fxge/dib/cfx_imagestretcher.h" #include "core/fxge/dib/cfx_imagetransformer.h" -#include "core/fxge/ge/cfx_cliprgn.h" #include "third_party/base/ptr_util.h" CFX_ImageRenderer::CFX_ImageRenderer( diff --git a/core/fxge/fx_ge_fontmap.cpp b/core/fxge/fx_ge_fontmap.cpp new file mode 100644 index 0000000000..7ac4fada5c --- /dev/null +++ b/core/fxge/fx_ge_fontmap.cpp @@ -0,0 +1,93 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include + +#include "core/fxge/cfx_fontmapper.h" +#include "core/fxge/ifx_systemfontinfo.h" + +static CFX_ByteString GetStringFromTable(const uint8_t* string_ptr, + uint32_t string_ptr_length, + uint16_t offset, + uint16_t length) { + if (string_ptr_length < static_cast(offset + length)) { + return CFX_ByteString(); + } + return CFX_ByteString(string_ptr + offset, length); +} + +CFX_ByteString GetNameFromTT(const uint8_t* name_table, + uint32_t name_table_size, + uint32_t name_id) { + if (!name_table || name_table_size < 6) { + return CFX_ByteString(); + } + uint32_t name_count = GET_TT_SHORT(name_table + 2); + uint32_t string_offset = GET_TT_SHORT(name_table + 4); + // We will ignore the possibility of overlap of structures and + // string table as if it's all corrupt there's not a lot we can do. + if (name_table_size < string_offset) { + return CFX_ByteString(); + } + + const uint8_t* string_ptr = name_table + string_offset; + uint32_t string_ptr_size = name_table_size - string_offset; + name_table += 6; + name_table_size -= 6; + if (name_table_size < name_count * 12) { + return CFX_ByteString(); + } + + for (uint32_t i = 0; i < name_count; i++, name_table += 12) { + if (GET_TT_SHORT(name_table + 6) == name_id && + GET_TT_SHORT(name_table) == 1 && GET_TT_SHORT(name_table + 2) == 0) { + return GetStringFromTable(string_ptr, string_ptr_size, + GET_TT_SHORT(name_table + 10), + GET_TT_SHORT(name_table + 8)); + } + } + return CFX_ByteString(); +} +#ifdef PDF_ENABLE_XFA +void* IFX_SystemFontInfo::MapFontByUnicode(uint32_t dwUnicode, + int weight, + bool bItalic, + int pitch_family) { + return nullptr; +} +#endif // PDF_ENABLE_XFA + +int IFX_SystemFontInfo::GetFaceIndex(void* hFont) { + return 0; +} + +extern "C" { +unsigned long _FTStreamRead(FXFT_Stream stream, + unsigned long offset, + unsigned char* buffer, + unsigned long count); +void _FTStreamClose(FXFT_Stream stream); +}; + +#if _FX_OS_ == _FX_ANDROID_ +std::unique_ptr IFX_SystemFontInfo::CreateDefault( + const char** pUnused) { + return nullptr; +} +#endif + +CFX_FontFaceInfo::CFX_FontFaceInfo(CFX_ByteString filePath, + CFX_ByteString faceName, + CFX_ByteString fontTables, + uint32_t fontOffset, + uint32_t fileSize) + : m_FilePath(filePath), + m_FaceName(faceName), + m_FontTables(fontTables), + m_FontOffset(fontOffset), + m_FileSize(fileSize), + m_Styles(0), + m_Charsets(0) {} diff --git a/core/fxge/fx_ge_linux.cpp b/core/fxge/fx_ge_linux.cpp new file mode 100644 index 0000000000..d9fac3f54c --- /dev/null +++ b/core/fxge/fx_ge_linux.cpp @@ -0,0 +1,166 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include +#include + +#include "core/fxcrt/fx_codepage.h" +#include "core/fxge/cfx_folderfontinfo.h" +#include "core/fxge/cfx_gemodule.h" +#include "core/fxge/ifx_systemfontinfo.h" +#include "third_party/base/ptr_util.h" + +#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ +namespace { + +const size_t kLinuxGpNameSize = 6; + +const char* const g_LinuxGpFontList[][kLinuxGpNameSize] = { + {"TakaoPGothic", "VL PGothic", "IPAPGothic", "VL Gothic", "Kochi Gothic", + "VL Gothic regular"}, + {"TakaoGothic", "VL Gothic", "IPAGothic", "Kochi Gothic", nullptr, + "VL Gothic regular"}, + {"TakaoPMincho", "IPAPMincho", "VL Gothic", "Kochi Mincho", nullptr, + "VL Gothic regular"}, + {"TakaoMincho", "IPAMincho", "VL Gothic", "Kochi Mincho", nullptr, + "VL Gothic regular"}, +}; + +const char* const g_LinuxGbFontList[] = { + "AR PL UMing CN Light", "WenQuanYi Micro Hei", "AR PL UKai CN", +}; + +const char* const g_LinuxB5FontList[] = { + "AR PL UMing TW Light", "WenQuanYi Micro Hei", "AR PL UKai TW", +}; + +const char* const g_LinuxHGFontList[] = { + "UnDotum", +}; + +size_t GetJapanesePreference(const char* facearr, + int weight, + int pitch_family) { + CFX_ByteString face = facearr; + if (face.Find("Gothic") >= 0 || + face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { + if (face.Find("PGothic") >= 0 || + face.Find("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { + return 0; + } + return 1; + } + if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) { + if (face.Find("PMincho") >= 0 || + face.Find("\x82\x6f\x96\xbe\x92\xa9") >= 0) { + return 2; + } + return 3; + } + if (!(pitch_family & FXFONT_FF_ROMAN) && weight > 400) + return 0; + + return 2; +} + +class CFX_LinuxFontInfo : public CFX_FolderFontInfo { + public: + CFX_LinuxFontInfo() {} + ~CFX_LinuxFontInfo() override {} + + void* MapFont(int weight, + bool bItalic, + int charset, + int pitch_family, + const char* family, + int& iExact) override; + bool ParseFontCfg(const char** pUserPaths); +}; + +void* CFX_LinuxFontInfo::MapFont(int weight, + bool bItalic, + int charset, + int pitch_family, + const char* cstr_face, + int& iExact) { + void* font = GetSubstFont(cstr_face); + if (font) { + iExact = 1; + return font; + } + bool bCJK = true; + switch (charset) { + case FX_CHARSET_ShiftJIS: { + size_t index = GetJapanesePreference(cstr_face, weight, pitch_family); + ASSERT(index < FX_ArraySize(g_LinuxGpFontList)); + for (size_t i = 0; i < kLinuxGpNameSize; i++) { + auto it = m_FontList.find(g_LinuxGpFontList[index][i]); + if (it != m_FontList.end()) + return it->second.get(); + } + break; + } + case FX_CHARSET_ChineseSimplified: { + for (size_t i = 0; i < FX_ArraySize(g_LinuxGbFontList); ++i) { + auto it = m_FontList.find(g_LinuxGbFontList[i]); + if (it != m_FontList.end()) + return it->second.get(); + } + break; + } + case FX_CHARSET_ChineseTraditional: { + for (size_t i = 0; i < FX_ArraySize(g_LinuxB5FontList); ++i) { + auto it = m_FontList.find(g_LinuxB5FontList[i]); + if (it != m_FontList.end()) + return it->second.get(); + } + break; + } + case FX_CHARSET_Hangul: { + for (size_t i = 0; i < FX_ArraySize(g_LinuxHGFontList); ++i) { + auto it = m_FontList.find(g_LinuxHGFontList[i]); + if (it != m_FontList.end()) + return it->second.get(); + } + break; + } + default: + bCJK = false; + break; + } + return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK); +} + +bool CFX_LinuxFontInfo::ParseFontCfg(const char** pUserPaths) { + if (!pUserPaths) + return false; + + for (const char** pPath = pUserPaths; *pPath; ++pPath) + AddPath(*pPath); + return true; +} + +} // namespace + +std::unique_ptr IFX_SystemFontInfo::CreateDefault( + const char** pUserPaths) { + auto pInfo = pdfium::MakeUnique(); + if (!pInfo->ParseFontCfg(pUserPaths)) { + pInfo->AddPath("/usr/share/fonts"); + pInfo->AddPath("/usr/share/X11/fonts/Type1"); + pInfo->AddPath("/usr/share/X11/fonts/TTF"); + pInfo->AddPath("/usr/local/share/fonts"); + } + return std::move(pInfo); +} + +void CFX_GEModule::InitPlatform() { + m_pFontMgr->SetSystemFontInfo( + IFX_SystemFontInfo::CreateDefault(m_pUserFontPaths)); +} + +void CFX_GEModule::DestroyPlatform() {} +#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ diff --git a/core/fxge/fx_ge_text.cpp b/core/fxge/fx_ge_text.cpp new file mode 100644 index 0000000000..0832f7a020 --- /dev/null +++ b/core/fxge/fx_ge_text.cpp @@ -0,0 +1,121 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#include +#include +#include + +#include "core/fxcodec/fx_codec.h" +#include "core/fxcrt/fx_safe_types.h" +#include "core/fxge/cfx_pathdata.h" +#include "core/fxge/fx_freetype.h" +#include "core/fxge/fx_text_int.h" +#include "core/fxge/ifx_renderdevicedriver.h" + +namespace { + +void ResetTransform(FT_Face face) { + FXFT_Matrix matrix; + matrix.xx = 0x10000L; + matrix.xy = 0; + matrix.yx = 0; + matrix.yy = 0x10000L; + FXFT_Set_Transform(face, &matrix, 0); +} + +} // namespace + +FXTEXT_GLYPHPOS::FXTEXT_GLYPHPOS() : m_pGlyph(nullptr) {} + +FXTEXT_GLYPHPOS::FXTEXT_GLYPHPOS(const FXTEXT_GLYPHPOS&) = default; + +FXTEXT_GLYPHPOS::~FXTEXT_GLYPHPOS(){}; + +ScopedFontTransform::ScopedFontTransform(FT_Face face, FXFT_Matrix* matrix) + : m_Face(face) { + FXFT_Set_Transform(m_Face, matrix, 0); +} + +ScopedFontTransform::~ScopedFontTransform() { + ResetTransform(m_Face); +} + +FX_RECT FXGE_GetGlyphsBBox(const std::vector& glyphs, + int anti_alias, + float retinaScaleX, + float retinaScaleY) { + FX_RECT rect(0, 0, 0, 0); + bool bStarted = false; + for (const FXTEXT_GLYPHPOS& glyph : glyphs) { + const CFX_GlyphBitmap* pGlyph = glyph.m_pGlyph; + if (!pGlyph) + continue; + + FX_SAFE_INT32 char_left = glyph.m_Origin.x; + char_left += pGlyph->m_Left; + if (!char_left.IsValid()) + continue; + + FX_SAFE_INT32 char_width = pGlyph->m_pBitmap->GetWidth(); + char_width /= retinaScaleX; + if (anti_alias == FXFT_RENDER_MODE_LCD) + char_width /= 3; + if (!char_width.IsValid()) + continue; + + FX_SAFE_INT32 char_right = char_left + char_width; + if (!char_right.IsValid()) + continue; + + FX_SAFE_INT32 char_top = glyph.m_Origin.y; + char_top -= pGlyph->m_Top; + if (!char_top.IsValid()) + continue; + + FX_SAFE_INT32 char_height = pGlyph->m_pBitmap->GetHeight(); + char_height /= retinaScaleY; + if (!char_height.IsValid()) + continue; + + FX_SAFE_INT32 char_bottom = char_top + char_height; + if (!char_bottom.IsValid()) + continue; + + if (bStarted) { + rect.left = pdfium::base::ValueOrDieForType( + pdfium::base::CheckMin(rect.left, char_left)); + rect.right = pdfium::base::ValueOrDieForType( + pdfium::base::CheckMax(rect.right, char_right)); + rect.top = pdfium::base::ValueOrDieForType( + pdfium::base::CheckMin(rect.top, char_top)); + rect.bottom = pdfium::base::ValueOrDieForType( + pdfium::base::CheckMax(rect.bottom, char_bottom)); + continue; + } + + rect.left = char_left.ValueOrDie(); + rect.right = char_right.ValueOrDie(); + rect.top = char_top.ValueOrDie(); + rect.bottom = char_bottom.ValueOrDie(); + bStarted = true; + } + return rect; +} + +CFX_SizeGlyphCache::CFX_SizeGlyphCache() {} + +CFX_SizeGlyphCache::~CFX_SizeGlyphCache() {} + +void CFX_UniqueKeyGen::Generate(int count, ...) { + va_list argList; + va_start(argList, count); + for (int i = 0; i < count; i++) { + int p = va_arg(argList, int); + ((uint32_t*)m_Key)[i] = p; + } + va_end(argList); + m_KeyLen = count * sizeof(uint32_t); +} diff --git a/core/fxge/fx_ge_text_embeddertest.cpp b/core/fxge/fx_ge_text_embeddertest.cpp new file mode 100644 index 0000000000..045b6dc869 --- /dev/null +++ b/core/fxge/fx_ge_text_embeddertest.cpp @@ -0,0 +1,18 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/embedder_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +class FXGETextEmbedderTest : public EmbedderTest {}; + +TEST_F(FXGETextEmbedderTest, BadItalic) { + // Shouldn't crash. + EXPECT_TRUE(OpenDocument("bug_601362.pdf")); + FPDF_PAGE page = LoadPage(0); + EXPECT_NE(nullptr, page); + FPDF_BITMAP bitmap = RenderPage(page); + FPDFBitmap_Destroy(bitmap); + UnloadPage(page); +} diff --git a/core/fxge/fx_text_int.h b/core/fxge/fx_text_int.h new file mode 100644 index 0000000000..6af8eb9165 --- /dev/null +++ b/core/fxge/fx_text_int.h @@ -0,0 +1,31 @@ +// Copyright 2014 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com + +#ifndef CORE_FXGE_FX_TEXT_INT_H_ +#define CORE_FXGE_FX_TEXT_INT_H_ + +#include +#include + +#include "core/fxge/fx_font.h" +#include "core/fxge/fx_freetype.h" + +struct CFX_UniqueKeyGen { + void Generate(int count, ...); + + char m_Key[128]; + int m_KeyLen; +}; + +class CFX_SizeGlyphCache { + public: + CFX_SizeGlyphCache(); + ~CFX_SizeGlyphCache(); + + std::map> m_GlyphMap; +}; + +#endif // CORE_FXGE_FX_TEXT_INT_H_ diff --git a/core/fxge/ge/cfx_cliprgn.cpp b/core/fxge/ge/cfx_cliprgn.cpp deleted file mode 100644 index e00cb7c3ad..0000000000 --- a/core/fxge/ge/cfx_cliprgn.cpp +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/ge/cfx_cliprgn.h" - -#include - -#include "core/fxge/dib/cfx_dibitmap.h" -#include "third_party/base/logging.h" - -CFX_ClipRgn::CFX_ClipRgn(int width, int height) - : m_Type(RectI), m_Box(0, 0, width, height) {} - -CFX_ClipRgn::CFX_ClipRgn(const CFX_ClipRgn& src) { - m_Type = src.m_Type; - m_Box = src.m_Box; - m_Mask = src.m_Mask; -} - -CFX_ClipRgn::~CFX_ClipRgn() {} - -void CFX_ClipRgn::Reset(const FX_RECT& rect) { - m_Type = RectI; - m_Box = rect; - m_Mask = nullptr; -} - -void CFX_ClipRgn::IntersectRect(const FX_RECT& rect) { - if (m_Type == RectI) { - m_Box.Intersect(rect); - return; - } - if (m_Type == MaskF) { - IntersectMaskRect(rect, m_Box, m_Mask); - return; - } -} - -void CFX_ClipRgn::IntersectMaskRect(FX_RECT rect, - FX_RECT mask_rect, - const CFX_RetainPtr& pMask) { - m_Type = MaskF; - m_Box = rect; - m_Box.Intersect(mask_rect); - if (m_Box.IsEmpty()) { - m_Type = RectI; - return; - } - if (m_Box == mask_rect) { - m_Mask = pMask; - return; - } - CFX_RetainPtr pOldMask(pMask); - m_Mask = pdfium::MakeRetain(); - m_Mask->Create(m_Box.Width(), m_Box.Height(), FXDIB_8bppMask); - for (int row = m_Box.top; row < m_Box.bottom; row++) { - uint8_t* dest_scan = - m_Mask->GetBuffer() + m_Mask->GetPitch() * (row - m_Box.top); - uint8_t* src_scan = - pOldMask->GetBuffer() + pOldMask->GetPitch() * (row - mask_rect.top); - for (int col = m_Box.left; col < m_Box.right; col++) - dest_scan[col - m_Box.left] = src_scan[col - mask_rect.left]; - } -} - -void CFX_ClipRgn::IntersectMaskF(int left, - int top, - const CFX_RetainPtr& pMask) { - ASSERT(pMask->GetFormat() == FXDIB_8bppMask); - FX_RECT mask_box(left, top, left + pMask->GetWidth(), - top + pMask->GetHeight()); - if (m_Type == RectI) { - IntersectMaskRect(m_Box, mask_box, pMask); - return; - } - if (m_Type == MaskF) { - FX_RECT new_box = m_Box; - new_box.Intersect(mask_box); - if (new_box.IsEmpty()) { - m_Type = RectI; - m_Mask = nullptr; - m_Box = new_box; - return; - } - auto new_dib = pdfium::MakeRetain(); - new_dib->Create(new_box.Width(), new_box.Height(), FXDIB_8bppMask); - for (int row = new_box.top; row < new_box.bottom; row++) { - uint8_t* old_scan = - m_Mask->GetBuffer() + (row - m_Box.top) * m_Mask->GetPitch(); - uint8_t* mask_scan = pMask->GetBuffer() + (row - top) * pMask->GetPitch(); - uint8_t* new_scan = - new_dib->GetBuffer() + (row - new_box.top) * new_dib->GetPitch(); - for (int col = new_box.left; col < new_box.right; col++) { - new_scan[col - new_box.left] = - old_scan[col - m_Box.left] * mask_scan[col - left] / 255; - } - } - m_Box = new_box; - m_Mask = std::move(new_dib); - return; - } - NOTREACHED(); -} diff --git a/core/fxge/ge/cfx_cliprgn.h b/core/fxge/ge/cfx_cliprgn.h deleted file mode 100644 index 800e6ddbee..0000000000 --- a/core/fxge/ge/cfx_cliprgn.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXGE_GE_CFX_CLIPRGN_H_ -#define CORE_FXGE_GE_CFX_CLIPRGN_H_ - -#include "core/fxcrt/fx_coordinates.h" - -class CFX_DIBitmap; - -class CFX_ClipRgn { - public: - enum ClipType { RectI, MaskF }; - - CFX_ClipRgn(int device_width, int device_height); - CFX_ClipRgn(const CFX_ClipRgn& src); - ~CFX_ClipRgn(); - - ClipType GetType() const { return m_Type; } - const FX_RECT& GetBox() const { return m_Box; } - CFX_RetainPtr GetMask() const { return m_Mask; } - - void Reset(const FX_RECT& rect); - void IntersectRect(const FX_RECT& rect); - void IntersectMaskF(int left, - int top, - const CFX_RetainPtr& Mask); - - private: - void IntersectMaskRect(FX_RECT rect, - FX_RECT mask_box, - const CFX_RetainPtr& Mask); - - ClipType m_Type; - FX_RECT m_Box; - CFX_RetainPtr m_Mask; -}; - -#endif // CORE_FXGE_GE_CFX_CLIPRGN_H_ diff --git a/core/fxge/ge/cfx_facecache.cpp b/core/fxge/ge/cfx_facecache.cpp deleted file mode 100644 index e675e11510..0000000000 --- a/core/fxge/ge/cfx_facecache.cpp +++ /dev/null @@ -1,402 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_facecache.h" - -#include -#include -#include -#include - -#include "core/fxcrt/fx_codepage.h" -#include "core/fxge/cfx_fontmgr.h" -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_substfont.h" -#include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/fx_text_int.h" -#include "third_party/base/numerics/safe_math.h" -#include "third_party/base/ptr_util.h" - -#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ -#include "third_party/skia/include/core/SkStream.h" -#include "third_party/skia/include/core/SkTypeface.h" - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ -#include "third_party/skia/include/ports/SkFontMgr.h" -#include "third_party/skia/include/ports/SkFontMgr_empty.h" -#endif -#endif - -namespace { - -constexpr uint32_t kInvalidGlyphIndex = static_cast(-1); - -constexpr int kMinPixel = 0; -constexpr int kMaxPixel = 255; - -constexpr int kMaxGlyphDimension = 2048; - -void ContrastAdjust(uint8_t* pDataIn, - uint8_t* pDataOut, - int nWidth, - int nHeight, - int nSrcRowBytes, - int nDstRowBytes) { - int max = kMinPixel; - int min = kMaxPixel; - for (int row = 0; row < nHeight; row++) { - uint8_t* pRow = pDataIn + row * nSrcRowBytes; - for (int col = 0; col < nWidth; col++) { - int val = pRow[col]; - max = std::max(val, max); - min = std::min(val, min); - } - } - int diff = max - min; - if (diff == kMinPixel || diff == kMaxPixel) { - int rowbytes = std::min(abs(nSrcRowBytes), nDstRowBytes); - for (int row = 0; row < nHeight; row++) { - memcpy(pDataOut + row * nDstRowBytes, pDataIn + row * nSrcRowBytes, - rowbytes); - } - return; - } - float rate = 255.f / diff; - for (int row = 0; row < nHeight; row++) { - uint8_t* pSrcRow = pDataIn + row * nSrcRowBytes; - uint8_t* pDstRow = pDataOut + row * nDstRowBytes; - for (int col = 0; col < nWidth; col++) { - int val = static_cast((pSrcRow[col] - min) * rate + 0.5); - pDstRow[col] = - static_cast(pdfium::clamp(val, kMinPixel, kMaxPixel)); - } - } -} - -} // namespace - -CFX_FaceCache::CFX_FaceCache(FXFT_Face face) - : m_Face(face) -#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ - , - m_pTypeface(nullptr) -#endif -{ -} - -CFX_FaceCache::~CFX_FaceCache() { -} - -std::unique_ptr CFX_FaceCache::RenderGlyph( - const CFX_Font* pFont, - uint32_t glyph_index, - bool bFontStyle, - const CFX_Matrix* pMatrix, - int dest_width, - int anti_alias) { - if (!m_Face) - return nullptr; - - FXFT_Matrix ft_matrix; - ft_matrix.xx = (signed long)(pMatrix->a / 64 * 65536); - ft_matrix.xy = (signed long)(pMatrix->c / 64 * 65536); - ft_matrix.yx = (signed long)(pMatrix->b / 64 * 65536); - ft_matrix.yy = (signed long)(pMatrix->d / 64 * 65536); - bool bUseCJKSubFont = false; - const CFX_SubstFont* pSubstFont = pFont->GetSubstFont(); - if (pSubstFont) { - bUseCJKSubFont = pSubstFont->m_bSubstCJK && bFontStyle; - int skew = 0; - if (bUseCJKSubFont) - skew = pSubstFont->m_bItalicCJK ? -15 : 0; - else - skew = pSubstFont->m_ItalicAngle; - if (skew) { - // |skew| is nonpositive so |-skew| is used as the index. We need to make - // sure |skew| != INT_MIN since -INT_MIN is undefined. - if (skew <= 0 && skew != std::numeric_limits::min() && - static_cast(-skew) < CFX_Font::kAngleSkewArraySize) { - skew = -CFX_Font::s_AngleSkew[-skew]; - } else { - skew = -58; - } - if (pFont->IsVertical()) - ft_matrix.yx += ft_matrix.yy * skew / 100; - else - ft_matrix.xy -= ft_matrix.xx * skew / 100; - } - if (pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) { - pFont->AdjustMMParams(glyph_index, dest_width, - pFont->GetSubstFont()->m_Weight); - } - } - ScopedFontTransform scoped_transform(m_Face, &ft_matrix); - int load_flags = (m_Face->face_flags & FT_FACE_FLAG_SFNT) - ? FXFT_LOAD_NO_BITMAP - : (FXFT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); - int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); - if (error) { - // if an error is returned, try to reload glyphs without hinting. - if (load_flags & FT_LOAD_NO_HINTING || load_flags & FT_LOAD_NO_SCALE) - return nullptr; - - load_flags |= FT_LOAD_NO_HINTING; - error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags); - - if (error) - return nullptr; - } - int weight = 0; - if (bUseCJKSubFont) - weight = pSubstFont->m_WeightCJK; - else - weight = pSubstFont ? pSubstFont->m_Weight : 0; - if (pSubstFont && !(pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && - weight > 400) { - uint32_t index = (weight - 400) / 10; - if (index >= CFX_Font::kWeightPowArraySize) - return nullptr; - pdfium::base::CheckedNumeric level = 0; - if (pSubstFont->m_Charset == FX_CHARSET_ShiftJIS) - level = CFX_Font::s_WeightPow_SHIFTJIS[index] * 2; - else - level = CFX_Font::s_WeightPow_11[index]; - - level = level * - (abs(static_cast(ft_matrix.xx)) + - abs(static_cast(ft_matrix.xy))) / - 36655; - FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), - level.ValueOrDefault(0)); - } - FXFT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(), - FT_LCD_FILTER_DEFAULT); - error = FXFT_Render_Glyph(m_Face, anti_alias); - if (error) - return nullptr; - int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(m_Face)); - int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(m_Face)); - if (bmwidth > kMaxGlyphDimension || bmheight > kMaxGlyphDimension) - return nullptr; - int dib_width = bmwidth; - auto pGlyphBitmap = pdfium::MakeUnique(); - pGlyphBitmap->m_pBitmap->Create( - dib_width, bmheight, - anti_alias == FXFT_RENDER_MODE_MONO ? FXDIB_1bppMask : FXDIB_8bppMask); - pGlyphBitmap->m_Left = FXFT_Get_Glyph_BitmapLeft(m_Face); - pGlyphBitmap->m_Top = FXFT_Get_Glyph_BitmapTop(m_Face); - int dest_pitch = pGlyphBitmap->m_pBitmap->GetPitch(); - int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(m_Face)); - uint8_t* pDestBuf = pGlyphBitmap->m_pBitmap->GetBuffer(); - uint8_t* pSrcBuf = - (uint8_t*)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(m_Face)); - if (anti_alias != FXFT_RENDER_MODE_MONO && - FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == - FXFT_PIXEL_MODE_MONO) { - int bytes = anti_alias == FXFT_RENDER_MODE_LCD ? 3 : 1; - for (int i = 0; i < bmheight; i++) { - for (int n = 0; n < bmwidth; n++) { - uint8_t data = - (pSrcBuf[i * src_pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0; - for (int b = 0; b < bytes; b++) - pDestBuf[i * dest_pitch + n * bytes + b] = data; - } - } - } else { - memset(pDestBuf, 0, dest_pitch * bmheight); - if (anti_alias == FXFT_RENDER_MODE_MONO && - FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) == - FXFT_PIXEL_MODE_MONO) { - int rowbytes = abs(src_pitch) > dest_pitch ? dest_pitch : abs(src_pitch); - for (int row = 0; row < bmheight; row++) { - memcpy(pDestBuf + row * dest_pitch, pSrcBuf + row * src_pitch, - rowbytes); - } - } else { - ContrastAdjust(pSrcBuf, pDestBuf, bmwidth, bmheight, src_pitch, - dest_pitch); - } - } - return pGlyphBitmap; -} - -const CFX_PathData* CFX_FaceCache::LoadGlyphPath(const CFX_Font* pFont, - uint32_t glyph_index, - int dest_width) { - if (!m_Face || glyph_index == kInvalidGlyphIndex || dest_width < 0) - return nullptr; - - uint32_t key = glyph_index; - auto* pSubstFont = pFont->GetSubstFont(); - if (pSubstFont) { - if (pSubstFont->m_Weight < 0 || pSubstFont->m_ItalicAngle < 0) - return nullptr; - uint32_t weight = static_cast(pSubstFont->m_Weight); - uint32_t angle = static_cast(pSubstFont->m_ItalicAngle); - uint32_t key_modifier = (weight / 16) << 15; - key_modifier += (angle / 2) << 21; - key_modifier += (static_cast(dest_width) / 16) << 25; - if (pFont->IsVertical()) - key_modifier += 1U << 31; - key += key_modifier; - } - auto it = m_PathMap.find(key); - if (it != m_PathMap.end()) - return it->second.get(); - - CFX_PathData* pGlyphPath = pFont->LoadGlyphPathImpl(glyph_index, dest_width); - m_PathMap[key] = std::unique_ptr(pGlyphPath); - return pGlyphPath; -} - -const CFX_GlyphBitmap* CFX_FaceCache::LoadGlyphBitmap(const CFX_Font* pFont, - uint32_t glyph_index, - bool bFontStyle, - const CFX_Matrix* pMatrix, - int dest_width, - int anti_alias, - int& text_flags) { - if (glyph_index == kInvalidGlyphIndex) - return nullptr; - - CFX_UniqueKeyGen keygen; - int nMatrixA = static_cast(pMatrix->a * 10000); - int nMatrixB = static_cast(pMatrix->b * 10000); - int nMatrixC = static_cast(pMatrix->c * 10000); - int nMatrixD = static_cast(pMatrix->d * 10000); -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ - if (pFont->GetSubstFont()) { - keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias, pFont->GetSubstFont()->m_Weight, - pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); - } else { - keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias); - } -#else - if (text_flags & FXTEXT_NO_NATIVETEXT) { - if (pFont->GetSubstFont()) { - keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias, pFont->GetSubstFont()->m_Weight, - pFont->GetSubstFont()->m_ItalicAngle, - pFont->IsVertical()); - } else { - keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias); - } - } else { - if (pFont->GetSubstFont()) { - keygen.Generate(10, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias, pFont->GetSubstFont()->m_Weight, - pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical(), - 3); - } else { - keygen.Generate(7, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias, 3); - } - } -#endif - CFX_ByteString FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_ || \ - defined _SKIA_SUPPORT_PATHS_ - return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, - bFontStyle, dest_width, anti_alias); -#else - if (text_flags & FXTEXT_NO_NATIVETEXT) { - return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index, - bFontStyle, dest_width, anti_alias); - } - std::unique_ptr pGlyphBitmap; - auto it = m_SizeMap.find(FaceGlyphsKey); - if (it != m_SizeMap.end()) { - CFX_SizeGlyphCache* pSizeCache = it->second.get(); - auto it2 = pSizeCache->m_GlyphMap.find(glyph_index); - if (it2 != pSizeCache->m_GlyphMap.end()) - return it2->second.get(); - - pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, - dest_width, anti_alias); - if (pGlyphBitmap) { - CFX_GlyphBitmap* pResult = pGlyphBitmap.get(); - pSizeCache->m_GlyphMap[glyph_index] = std::move(pGlyphBitmap); - return pResult; - } - } else { - pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix, - dest_width, anti_alias); - if (pGlyphBitmap) { - auto pNewCache = pdfium::MakeUnique(); - CFX_SizeGlyphCache* pSizeCache = pNewCache.get(); - m_SizeMap[FaceGlyphsKey] = std::move(pNewCache); - CFX_GlyphBitmap* pResult = pGlyphBitmap.get(); - pSizeCache->m_GlyphMap[glyph_index] = std::move(pGlyphBitmap); - return pResult; - } - } - if (pFont->GetSubstFont()) { - keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias, pFont->GetSubstFont()->m_Weight, - pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical()); - } else { - keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width, - anti_alias); - } - CFX_ByteString FaceGlyphsKey2(keygen.m_Key, keygen.m_KeyLen); - text_flags |= FXTEXT_NO_NATIVETEXT; - return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey2, glyph_index, - bFontStyle, dest_width, anti_alias); -#endif -} - -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ -CFX_TypeFace* CFX_FaceCache::GetDeviceCache(const CFX_Font* pFont) { - if (!m_pTypeface) { - m_pTypeface = SkTypeface::MakeFromStream( - new SkMemoryStream(pFont->GetFontData(), pFont->GetSize())); - } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - if (!m_pTypeface) { - sk_sp customMgr(SkFontMgr_New_Custom_Empty()); - m_pTypeface.reset(customMgr->createFromStream( - new SkMemoryStream(pFont->GetFontData(), pFont->GetSize()))); - } -#endif - return m_pTypeface.get(); -} -#endif - -#if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ -void CFX_FaceCache::InitPlatform() {} -#endif - -CFX_GlyphBitmap* CFX_FaceCache::LookUpGlyphBitmap( - const CFX_Font* pFont, - const CFX_Matrix* pMatrix, - const CFX_ByteString& FaceGlyphsKey, - uint32_t glyph_index, - bool bFontStyle, - int dest_width, - int anti_alias) { - CFX_SizeGlyphCache* pSizeCache; - auto it = m_SizeMap.find(FaceGlyphsKey); - if (it == m_SizeMap.end()) { - auto pNewCache = pdfium::MakeUnique(); - pSizeCache = pNewCache.get(); - m_SizeMap[FaceGlyphsKey] = std::move(pNewCache); - } else { - pSizeCache = it->second.get(); - } - auto it2 = pSizeCache->m_GlyphMap.find(glyph_index); - if (it2 != pSizeCache->m_GlyphMap.end()) - return it2->second.get(); - - std::unique_ptr pGlyphBitmap = RenderGlyph( - pFont, glyph_index, bFontStyle, pMatrix, dest_width, anti_alias); - CFX_GlyphBitmap* pResult = pGlyphBitmap.get(); - pSizeCache->m_GlyphMap[glyph_index] = std::move(pGlyphBitmap); - return pResult; -} diff --git a/core/fxge/ge/cfx_folderfontinfo.cpp b/core/fxge/ge/cfx_folderfontinfo.cpp deleted file mode 100644 index a13af068e8..0000000000 --- a/core/fxge/ge/cfx_folderfontinfo.cpp +++ /dev/null @@ -1,379 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/ge/cfx_folderfontinfo.h" - -#include -#include - -#include "core/fxcrt/fx_codepage.h" -#include "core/fxge/cfx_fontmapper.h" -#include "core/fxge/fx_font.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" - -namespace { - -const struct { - const char* m_pName; - const 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"}, -}; - -CFX_ByteString FPDF_ReadStringFromFile(FILE* pFile, uint32_t size) { - CFX_ByteString buffer; - if (!fread(buffer.GetBuffer(size), size, 1, pFile)) - return CFX_ByteString(); - buffer.ReleaseBuffer(size); - return buffer; -} - -CFX_ByteString FPDF_LoadTableFromTT(FILE* pFile, - const uint8_t* pTables, - uint32_t nTables, - uint32_t tag) { - for (uint32_t i = 0; i < nTables; i++) { - const uint8_t* p = pTables + i * 16; - if (GET_TT_LONG(p) == tag) { - uint32_t offset = GET_TT_LONG(p + 8); - uint32_t size = GET_TT_LONG(p + 12); - fseek(pFile, offset, SEEK_SET); - return FPDF_ReadStringFromFile(pFile, size); - } - } - return CFX_ByteString(); -} - -uint32_t GetCharset(int charset) { - switch (charset) { - case FX_CHARSET_ShiftJIS: - return CHARSET_FLAG_SHIFTJIS; - case FX_CHARSET_ChineseSimplified: - return CHARSET_FLAG_GB; - case FX_CHARSET_ChineseTraditional: - return CHARSET_FLAG_BIG5; - case FX_CHARSET_Hangul: - return CHARSET_FLAG_KOREAN; - case FX_CHARSET_Symbol: - return CHARSET_FLAG_SYMBOL; - case FX_CHARSET_ANSI: - return CHARSET_FLAG_ANSI; - default: - break; - } - return 0; -} - -int32_t GetSimilarValue(int weight, - bool bItalic, - int pitch_family, - uint32_t 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; -} - -} // namespace - -CFX_FolderFontInfo::CFX_FolderFontInfo() {} - -CFX_FolderFontInfo::~CFX_FolderFontInfo() {} - -void CFX_FolderFontInfo::AddPath(const CFX_ByteString& path) { - m_PathList.push_back(path); -} - -bool CFX_FolderFontInfo::EnumFontList(CFX_FontMapper* pMapper) { - m_pMapper = pMapper; - for (const auto& path : m_PathList) - ScanPath(path); - return true; -} - -void CFX_FolderFontInfo::ScanPath(const CFX_ByteString& path) { - FX_FileHandle* handle = FX_OpenFolder(path.c_str()); - if (!handle) - return; - - CFX_ByteString filename; - bool bFolder; - while (FX_GetNextFile(handle, &filename, &bFolder)) { - if (bFolder) { - if (filename == "." || filename == "..") - continue; - } else { - CFX_ByteString ext = filename.Right(4); - ext.MakeUpper(); - if (ext != ".TTF" && ext != ".OTF" && ext != ".TTC") - continue; - } - - CFX_ByteString fullpath = path; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ - fullpath += "\\"; -#else - fullpath += "/"; -#endif - - fullpath += filename; - bFolder ? ScanPath(fullpath) : ScanFile(fullpath); - } - FX_CloseFolder(handle); -} - -void CFX_FolderFontInfo::ScanFile(const CFX_ByteString& path) { - FILE* pFile = fopen(path.c_str(), "rb"); - if (!pFile) - return; - - fseek(pFile, 0, SEEK_END); - - uint32_t filesize = ftell(pFile); - uint8_t buffer[16]; - fseek(pFile, 0, SEEK_SET); - - size_t readCnt = fread(buffer, 12, 1, pFile); - if (readCnt != 1) { - fclose(pFile); - return; - } - - if (GET_TT_LONG(buffer) == kTableTTCF) { - uint32_t nFaces = GET_TT_LONG(buffer + 8); - if (nFaces > std::numeric_limits::max() / 4) { - fclose(pFile); - return; - } - uint32_t face_bytes = nFaces * 4; - uint8_t* offsets = FX_Alloc(uint8_t, face_bytes); - readCnt = fread(offsets, 1, face_bytes, pFile); - if (readCnt != face_bytes) { - FX_Free(offsets); - fclose(pFile); - return; - } - for (uint32_t i = 0; i < nFaces; i++) { - uint8_t* p = offsets + i * 4; - ReportFace(path, pFile, filesize, GET_TT_LONG(p)); - } - FX_Free(offsets); - } else { - ReportFace(path, pFile, filesize, 0); - } - fclose(pFile); -} - -void CFX_FolderFontInfo::ReportFace(const CFX_ByteString& path, - FILE* pFile, - uint32_t filesize, - uint32_t offset) { - fseek(pFile, offset, SEEK_SET); - char buffer[16]; - if (!fread(buffer, 12, 1, pFile)) - return; - - uint32_t nTables = GET_TT_SHORT(buffer + 4); - CFX_ByteString tables = FPDF_ReadStringFromFile(pFile, nTables * 16); - if (tables.IsEmpty()) - return; - - CFX_ByteString names = - FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x6e616d65); - if (names.IsEmpty()) - return; - - CFX_ByteString facename = - GetNameFromTT(names.raw_str(), names.GetLength(), 1); - if (facename.IsEmpty()) - return; - - CFX_ByteString style = GetNameFromTT(names.raw_str(), names.GetLength(), 2); - if (style != "Regular") - facename += " " + style; - - if (pdfium::ContainsKey(m_FontList, facename)) - return; - - auto pInfo = pdfium::MakeUnique(path, facename, tables, - offset, filesize); - CFX_ByteString os2 = - FPDF_LoadTableFromTT(pFile, tables.raw_str(), nTables, 0x4f532f32); - if (os2.GetLength() >= 86) { - const uint8_t* p = os2.raw_str() + 78; - uint32_t codepages = GET_TT_LONG(p); - if (codepages & (1 << 17)) { - m_pMapper->AddInstalledFont(facename, FX_CHARSET_ShiftJIS); - pInfo->m_Charsets |= CHARSET_FLAG_SHIFTJIS; - } - if (codepages & (1 << 18)) { - m_pMapper->AddInstalledFont(facename, FX_CHARSET_ChineseSimplified); - pInfo->m_Charsets |= CHARSET_FLAG_GB; - } - if (codepages & (1 << 20)) { - m_pMapper->AddInstalledFont(facename, FX_CHARSET_ChineseTraditional); - pInfo->m_Charsets |= CHARSET_FLAG_BIG5; - } - if ((codepages & (1 << 19)) || (codepages & (1 << 21))) { - m_pMapper->AddInstalledFont(facename, FX_CHARSET_Hangul); - pInfo->m_Charsets |= CHARSET_FLAG_KOREAN; - } - if (codepages & (1 << 31)) { - m_pMapper->AddInstalledFont(facename, FX_CHARSET_Symbol); - pInfo->m_Charsets |= CHARSET_FLAG_SYMBOL; - } - } - m_pMapper->AddInstalledFont(facename, FX_CHARSET_ANSI); - pInfo->m_Charsets |= CHARSET_FLAG_ANSI; - pInfo->m_Styles = 0; - if (style.Find("Bold") > -1) - pInfo->m_Styles |= FXFONT_BOLD; - if (style.Find("Italic") > -1 || style.Find("Oblique") > -1) - pInfo->m_Styles |= FXFONT_ITALIC; - if (facename.Find("Serif") > -1) - pInfo->m_Styles |= FXFONT_SERIF; - - m_FontList[facename] = std::move(pInfo); -} - -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; -} - -void* CFX_FolderFontInfo::FindFont(int weight, - bool bItalic, - int charset, - int pitch_family, - const char* family, - bool bMatchName) { - CFX_FontFaceInfo* pFind = nullptr; - if (charset == FX_CHARSET_ANSI && (pitch_family & FXFONT_FF_FIXEDPITCH)) - return GetFont("Courier New"); - - uint32_t 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.get(); - if (!(pFont->m_Charsets & charset_flag) && charset != FX_CHARSET_Default) - 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, - bool bItalic, - int charset, - int pitch_family, - const char* family, - int& iExact) { - return nullptr; -} - -#ifdef PDF_ENABLE_XFA -void* CFX_FolderFontInfo::MapFontByUnicode(uint32_t dwUnicode, - int weight, - bool bItalic, - int pitch_family) { - return nullptr; -} -#endif // PDF_ENABLE_XFA - -void* CFX_FolderFontInfo::GetFont(const char* face) { - auto it = m_FontList.find(face); - return it != m_FontList.end() ? it->second.get() : nullptr; -} - -uint32_t CFX_FolderFontInfo::GetFontData(void* hFont, - uint32_t table, - uint8_t* buffer, - uint32_t size) { - if (!hFont) - return 0; - - const CFX_FontFaceInfo* pFont = static_cast(hFont); - uint32_t datasize = 0; - uint32_t offset = 0; - if (table == 0) { - datasize = pFont->m_FontOffset ? 0 : pFont->m_FileSize; - } else if (table == kTableTTCF) { - datasize = pFont->m_FontOffset ? pFont->m_FileSize : 0; - } else { - uint32_t nTables = pFont->m_FontTables.GetLength() / 16; - for (uint32_t i = 0; i < nTables; i++) { - const uint8_t* p = pFont->m_FontTables.raw_str() + i * 16; - if (GET_TT_LONG(p) == table) { - offset = GET_TT_LONG(p + 8); - datasize = GET_TT_LONG(p + 12); - } - } - } - - if (!datasize || size < datasize) - return datasize; - - FILE* pFile = fopen(pFont->m_FilePath.c_str(), "rb"); - if (!pFile) - return 0; - - if (fseek(pFile, offset, SEEK_SET) < 0 || - fread(buffer, datasize, 1, pFile) != 1) { - datasize = 0; - } - fclose(pFile); - return datasize; -} - -void CFX_FolderFontInfo::DeleteFont(void* hFont) {} - -bool CFX_FolderFontInfo::GetFaceName(void* hFont, CFX_ByteString* name) { - if (!hFont) - return false; - *name = static_cast(hFont)->m_FaceName; - return true; -} - -bool CFX_FolderFontInfo::GetFontCharset(void* hFont, int* charset) { - return false; -} diff --git a/core/fxge/ge/cfx_folderfontinfo.h b/core/fxge/ge/cfx_folderfontinfo.h deleted file mode 100644 index ad363b5f0d..0000000000 --- a/core/fxge/ge/cfx_folderfontinfo.h +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXGE_GE_CFX_FOLDERFONTINFO_H_ -#define CORE_FXGE_GE_CFX_FOLDERFONTINFO_H_ - -#include -#include -#include - -#include "core/fxcrt/cfx_unowned_ptr.h" -#include "core/fxge/cfx_fontmapper.h" -#include "core/fxge/fx_font.h" -#include "core/fxge/ifx_systemfontinfo.h" - -class CFX_FolderFontInfo : public IFX_SystemFontInfo { - public: - CFX_FolderFontInfo(); - ~CFX_FolderFontInfo() override; - - void AddPath(const CFX_ByteString& path); - - // IFX_SytemFontInfo: - bool EnumFontList(CFX_FontMapper* pMapper) override; - void* MapFont(int weight, - bool bItalic, - int charset, - int pitch_family, - const char* face, - int& bExact) override; -#ifdef PDF_ENABLE_XFA - void* MapFontByUnicode(uint32_t dwUnicode, - int weight, - bool bItalic, - int pitch_family) override; -#endif // PDF_ENABLE_XFA - void* GetFont(const char* face) override; - uint32_t GetFontData(void* hFont, - uint32_t table, - uint8_t* buffer, - uint32_t size) override; - void DeleteFont(void* hFont) override; - bool GetFaceName(void* hFont, CFX_ByteString* name) override; - bool GetFontCharset(void* hFont, int* charset) override; - - protected: - void ScanPath(const CFX_ByteString& path); - void ScanFile(const CFX_ByteString& path); - void ReportFace(const CFX_ByteString& path, - FILE* pFile, - uint32_t filesize, - uint32_t offset); - void* GetSubstFont(const CFX_ByteString& face); - void* FindFont(int weight, - bool bItalic, - int charset, - int pitch_family, - const char* family, - bool bMatchName); - - std::map> m_FontList; - std::vector m_PathList; - CFX_UnownedPtr m_pMapper; -}; - -#endif // CORE_FXGE_GE_CFX_FOLDERFONTINFO_H_ diff --git a/core/fxge/ge/cfx_font.cpp b/core/fxge/ge/cfx_font.cpp deleted file mode 100644 index 144675cdbd..0000000000 --- a/core/fxge/ge/cfx_font.cpp +++ /dev/null @@ -1,658 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/fx_font.h" - -#include -#include -#include -#include -#include - -#include "core/fpdfapi/font/cpdf_font.h" -#include "core/fxcrt/fx_codepage.h" -#include "core/fxge/cfx_facecache.h" -#include "core/fxge/cfx_fontcache.h" -#include "core/fxge/cfx_fontmgr.h" -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/cfx_substfont.h" -#include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/fx_text_int.h" -#include "third_party/base/ptr_util.h" - -#define EM_ADJUST(em, a) (em == 0 ? (a) : (a)*1000 / em) - -namespace { - -struct OUTLINE_PARAMS { - CFX_PathData* m_pPath; - int m_CurX; - int m_CurY; - float m_CoordUnit; -}; - -#ifdef PDF_ENABLE_XFA - -unsigned long FTStreamRead(FXFT_Stream stream, - unsigned long offset, - unsigned char* buffer, - unsigned long count) { - if (count == 0) - return 0; - - IFX_SeekableReadStream* pFile = - static_cast(stream->descriptor.pointer); - return pFile && pFile->ReadBlock(buffer, offset, count) ? count : 0; -} - -void FTStreamClose(FXFT_Stream stream) {} - -bool LoadFileImp(FXFT_Library library, - FXFT_Face* Face, - const CFX_RetainPtr& pFile, - int32_t faceIndex, - std::unique_ptr* stream) { - auto stream1 = pdfium::MakeUnique(); - stream1->base = nullptr; - stream1->size = static_cast(pFile->GetSize()); - stream1->pos = 0; - stream1->descriptor.pointer = static_cast(pFile.Get()); - stream1->close = FTStreamClose; - stream1->read = FTStreamRead; - FXFT_Open_Args args; - args.flags = FT_OPEN_STREAM; - args.stream = stream1.get(); - if (FXFT_Open_Face(library, &args, faceIndex, Face)) - return false; - if (stream) - *stream = std::move(stream1); - return true; -} -#endif // PDF_ENABLE_XFA - -FXFT_Face FT_LoadFont(const uint8_t* pData, int size) { - return CFX_GEModule::Get()->GetFontMgr()->GetFixedFace(pData, size, 0); -} - -void Outline_CheckEmptyContour(OUTLINE_PARAMS* param) { - std::vector& points = param->m_pPath->GetPoints(); - size_t size = points.size(); - - if (size >= 2 && points[size - 2].IsTypeAndOpen(FXPT_TYPE::MoveTo) && - points[size - 2].m_Point == points[size - 1].m_Point) { - size -= 2; - } - if (size >= 4 && points[size - 4].IsTypeAndOpen(FXPT_TYPE::MoveTo) && - points[size - 3].IsTypeAndOpen(FXPT_TYPE::BezierTo) && - points[size - 3].m_Point == points[size - 4].m_Point && - points[size - 2].m_Point == points[size - 4].m_Point && - points[size - 1].m_Point == points[size - 4].m_Point) { - size -= 4; - } - points.resize(size); -} - -int Outline_MoveTo(const FXFT_Vector* to, void* user) { - OUTLINE_PARAMS* param = static_cast(user); - - Outline_CheckEmptyContour(param); - - param->m_pPath->ClosePath(); - param->m_pPath->AppendPoint( - CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), - FXPT_TYPE::MoveTo, false); - - param->m_CurX = to->x; - param->m_CurY = to->y; - return 0; -} - -int Outline_LineTo(const FXFT_Vector* to, void* user) { - OUTLINE_PARAMS* param = static_cast(user); - - param->m_pPath->AppendPoint( - CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), - FXPT_TYPE::LineTo, false); - - param->m_CurX = to->x; - param->m_CurY = to->y; - return 0; -} - -int Outline_ConicTo(const FXFT_Vector* control, - const FXFT_Vector* to, - void* user) { - OUTLINE_PARAMS* param = static_cast(user); - - param->m_pPath->AppendPoint( - CFX_PointF((param->m_CurX + (control->x - param->m_CurX) * 2 / 3) / - param->m_CoordUnit, - (param->m_CurY + (control->y - param->m_CurY) * 2 / 3) / - param->m_CoordUnit), - FXPT_TYPE::BezierTo, false); - - param->m_pPath->AppendPoint( - CFX_PointF((control->x + (to->x - control->x) / 3) / param->m_CoordUnit, - (control->y + (to->y - control->y) / 3) / param->m_CoordUnit), - FXPT_TYPE::BezierTo, false); - - param->m_pPath->AppendPoint( - CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), - FXPT_TYPE::BezierTo, false); - - param->m_CurX = to->x; - param->m_CurY = to->y; - return 0; -} - -int Outline_CubicTo(const FXFT_Vector* control1, - const FXFT_Vector* control2, - const FXFT_Vector* to, - void* user) { - OUTLINE_PARAMS* param = static_cast(user); - - param->m_pPath->AppendPoint(CFX_PointF(control1->x / param->m_CoordUnit, - control1->y / param->m_CoordUnit), - FXPT_TYPE::BezierTo, false); - - param->m_pPath->AppendPoint(CFX_PointF(control2->x / param->m_CoordUnit, - control2->y / param->m_CoordUnit), - FXPT_TYPE::BezierTo, false); - - param->m_pPath->AppendPoint( - CFX_PointF(to->x / param->m_CoordUnit, to->y / param->m_CoordUnit), - FXPT_TYPE::BezierTo, false); - - param->m_CurX = to->x; - param->m_CurY = to->y; - return 0; -} - -} // namespace - -const char CFX_Font::s_AngleSkew[] = { - 0, 2, 3, 5, 7, 9, 11, 12, 14, 16, 18, 19, 21, 23, 25, - 27, 29, 31, 32, 34, 36, 38, 40, 42, 45, 47, 49, 51, 53, 55, -}; - -const uint8_t CFX_Font::s_WeightPow[] = { - 0, 3, 6, 7, 8, 9, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 35, 36, 36, 37, - 37, 37, 38, 38, 38, 39, 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, - 42, 43, 43, 43, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, - 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 50, - 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, -}; - -const uint8_t CFX_Font::s_WeightPow_11[] = { - 0, 4, 7, 8, 9, 10, 12, 13, 15, 17, 18, 19, 20, 21, 22, 23, 24, - 25, 26, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 39, 40, 40, 41, - 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, 45, 45, 45, 46, 46, 46, - 46, 43, 47, 47, 48, 48, 48, 48, 45, 50, 50, 50, 46, 51, 51, 51, 52, - 52, 52, 52, 53, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55, 55, - 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, -}; - -const uint8_t CFX_Font::s_WeightPow_SHIFTJIS[] = { - 0, 0, 1, 2, 3, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 21, - 22, 24, 26, 28, 30, 32, 33, 35, 37, 39, 41, 43, 45, 48, 48, 48, 48, - 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, - 53, 53, 53, 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 56, 56, 56, - 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 58, 58, 58, 58, 58, 58, 58, - 59, 59, 59, 59, 59, 59, 59, 60, 60, 60, 60, 60, 60, 60, 60, -}; - -CFX_Font::CFX_Font() - : -#ifdef PDF_ENABLE_XFA - m_bShallowCopy(false), - m_pOwnedStream(nullptr), -#endif // PDF_ENABLE_XFA - m_Face(nullptr), - m_FaceCache(nullptr), - m_pFontData(nullptr), - m_pGsubData(nullptr), - m_dwSize(0), -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - m_pPlatformFont(nullptr), -#endif - m_bEmbedded(false), - m_bVertical(false) { -} - -#ifdef PDF_ENABLE_XFA -bool CFX_Font::LoadClone(const CFX_Font* pFont) { - if (!pFont) - return false; - - m_bShallowCopy = true; - if (pFont->m_pSubstFont) { - m_pSubstFont = pdfium::MakeUnique(); - m_pSubstFont->m_Charset = pFont->m_pSubstFont->m_Charset; - m_pSubstFont->m_SubstFlags = pFont->m_pSubstFont->m_SubstFlags; - m_pSubstFont->m_Weight = pFont->m_pSubstFont->m_Weight; - m_pSubstFont->m_Family = pFont->m_pSubstFont->m_Family; - m_pSubstFont->m_ItalicAngle = pFont->m_pSubstFont->m_ItalicAngle; - } - m_Face = pFont->m_Face; - m_bEmbedded = pFont->m_bEmbedded; - m_bVertical = pFont->m_bVertical; - m_dwSize = pFont->m_dwSize; - m_pFontData = pFont->m_pFontData; - m_pGsubData = pFont->m_pGsubData; -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - m_pPlatformFont = pFont->m_pPlatformFont; -#endif - m_pOwnedStream = pFont->m_pOwnedStream; - m_FaceCache = pFont->GetFaceCache(); - return true; -} - -void CFX_Font::SetFace(FXFT_Face face) { - ClearFaceCache(); - m_Face = face; -} - -#endif // PDF_ENABLE_XFA - -CFX_Font::~CFX_Font() { -#ifdef PDF_ENABLE_XFA - if (m_bShallowCopy) - return; -#endif // PDF_ENABLE_XFA - if (m_Face) { -#ifndef PDF_ENABLE_XFA - if (FXFT_Get_Face_External_Stream(m_Face)) { - FXFT_Clear_Face_External_Stream(m_Face); - } -#endif // PDF_ENABLE_XFA - DeleteFace(); - } -#ifdef PDF_ENABLE_XFA - delete m_pOwnedStream; -#endif // PDF_ENABLE_XFA - FX_Free(m_pGsubData); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ && !defined _SKIA_SUPPORT_ - ReleasePlatformResource(); -#endif -} - -void CFX_Font::DeleteFace() { - ClearFaceCache(); - if (m_bEmbedded) - FXFT_Done_Face(m_Face); - else - CFX_GEModule::Get()->GetFontMgr()->ReleaseFace(m_Face); - m_Face = nullptr; -} - -void CFX_Font::LoadSubst(const CFX_ByteString& face_name, - bool bTrueType, - uint32_t flags, - int weight, - int italic_angle, - int CharsetCP, - bool bVertical) { - m_bEmbedded = false; - m_bVertical = bVertical; - m_pSubstFont = pdfium::MakeUnique(); - m_Face = CFX_GEModule::Get()->GetFontMgr()->FindSubstFont( - face_name, bTrueType, flags, weight, italic_angle, CharsetCP, - m_pSubstFont.get()); - if (m_Face) { - m_pFontData = FXFT_Get_Face_Stream_Base(m_Face); - m_dwSize = FXFT_Get_Face_Stream_Size(m_Face); - } -} - -#ifdef PDF_ENABLE_XFA -bool CFX_Font::LoadFile(const CFX_RetainPtr& pFile, - int nFaceIndex) { - m_bEmbedded = false; - - CFX_FontMgr* pFontMgr = CFX_GEModule::Get()->GetFontMgr(); - pFontMgr->InitFTLibrary(); - - FXFT_Library library = pFontMgr->GetFTLibrary(); - std::unique_ptr stream; - if (!LoadFileImp(library, &m_Face, pFile, nFaceIndex, &stream)) - return false; - - m_pOwnedStream = stream.release(); - FXFT_Set_Pixel_Sizes(m_Face, 0, 64); - return true; -} -#endif // PDF_ENABLE_XFA - -int CFX_Font::GetGlyphWidth(uint32_t glyph_index) { - if (!m_Face) - return 0; - if (m_pSubstFont && (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM)) - AdjustMMParams(glyph_index, 0, 0); - int err = FXFT_Load_Glyph( - m_Face, glyph_index, - FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); - if (err) - return 0; - - int width = EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), - FXFT_Get_Glyph_HoriAdvance(m_Face)); - return width; -} - -bool CFX_Font::LoadEmbedded(const uint8_t* data, uint32_t size) { - std::vector temp(data, data + size); - m_pFontDataAllocation.swap(temp); - m_Face = FT_LoadFont(m_pFontDataAllocation.data(), size); - m_pFontData = m_pFontDataAllocation.data(); - m_bEmbedded = true; - m_dwSize = size; - return !!m_Face; -} - -bool CFX_Font::IsTTFont() const { - return m_Face && FXFT_Is_Face_TT_OT(m_Face) == FXFT_FACE_FLAG_SFNT; -} - -int CFX_Font::GetAscent() const { - if (!m_Face) - return 0; - - return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), - FXFT_Get_Face_Ascender(m_Face)); -} - -int CFX_Font::GetDescent() const { - if (!m_Face) - return 0; - - return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face), - FXFT_Get_Face_Descender(m_Face)); -} - -bool CFX_Font::GetGlyphBBox(uint32_t glyph_index, FX_RECT& bbox) { - if (!m_Face) - return false; - - if (FXFT_Is_Face_Tricky(m_Face)) { - int error = FXFT_Set_Char_Size(m_Face, 0, 1000 * 64, 72, 72); - if (error) - return false; - - error = FXFT_Load_Glyph(m_Face, glyph_index, - FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); - if (error) - return false; - - FXFT_BBox cbox; - FT_Glyph glyph; - error = FXFT_Get_Glyph(m_Face->glyph, &glyph); - if (error) - return false; - - FXFT_Glyph_Get_CBox(glyph, FXFT_GLYPH_BBOX_PIXELS, &cbox); - int pixel_size_x = m_Face->size->metrics.x_ppem, - pixel_size_y = m_Face->size->metrics.y_ppem; - if (pixel_size_x == 0 || pixel_size_y == 0) { - bbox.left = cbox.xMin; - bbox.right = cbox.xMax; - bbox.top = cbox.yMax; - bbox.bottom = cbox.yMin; - } else { - bbox.left = cbox.xMin * 1000 / pixel_size_x; - bbox.right = cbox.xMax * 1000 / pixel_size_x; - bbox.top = cbox.yMax * 1000 / pixel_size_y; - bbox.bottom = cbox.yMin * 1000 / pixel_size_y; - } - bbox.top = std::min(bbox.top, - static_cast(FXFT_Get_Face_Ascender(m_Face))); - bbox.bottom = std::max( - bbox.bottom, static_cast(FXFT_Get_Face_Descender(m_Face))); - FT_Done_Glyph(glyph); - return FXFT_Set_Pixel_Sizes(m_Face, 0, 64) == 0; - } - if (FXFT_Load_Glyph( - m_Face, glyph_index, - FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) { - return false; - } - int em = FXFT_Get_Face_UnitsPerEM(m_Face); - if (em == 0) { - bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face); - bbox.bottom = FXFT_Get_Glyph_HoriBearingY(m_Face); - bbox.top = bbox.bottom - FXFT_Get_Glyph_Height(m_Face); - bbox.right = bbox.left + FXFT_Get_Glyph_Width(m_Face); - } else { - bbox.left = FXFT_Get_Glyph_HoriBearingX(m_Face) * 1000 / em; - bbox.top = - (FXFT_Get_Glyph_HoriBearingY(m_Face) - FXFT_Get_Glyph_Height(m_Face)) * - 1000 / em; - bbox.right = - (FXFT_Get_Glyph_HoriBearingX(m_Face) + FXFT_Get_Glyph_Width(m_Face)) * - 1000 / em; - bbox.bottom = (FXFT_Get_Glyph_HoriBearingY(m_Face)) * 1000 / em; - } - return true; -} - -bool CFX_Font::IsItalic() const { - if (!m_Face) - return false; - if (FXFT_Is_Face_Italic(m_Face) == FXFT_STYLE_FLAG_ITALIC) - return true; - - CFX_ByteString str(FXFT_Get_Face_Style_Name(m_Face)); - str.MakeLower(); - return str.Find("italic") != -1; -} - -bool CFX_Font::IsBold() const { - return m_Face && FXFT_Is_Face_Bold(m_Face) == FXFT_STYLE_FLAG_BOLD; -} - -bool CFX_Font::IsFixedWidth() const { - return m_Face && FXFT_Is_Face_fixedwidth(m_Face) != 0; -} - -CFX_ByteString CFX_Font::GetPsName() const { - if (!m_Face) - return CFX_ByteString(); - - CFX_ByteString psName = FXFT_Get_Postscript_Name(m_Face); - if (psName.IsEmpty()) - psName = "Untitled"; - return psName; -} - -CFX_ByteString CFX_Font::GetFamilyName() const { - if (!m_Face && !m_pSubstFont) - return CFX_ByteString(); - if (m_Face) - return CFX_ByteString(FXFT_Get_Face_Family_Name(m_Face)); - - return m_pSubstFont->m_Family; -} - -CFX_ByteString CFX_Font::GetFaceName() const { - if (!m_Face && !m_pSubstFont) - return CFX_ByteString(); - if (m_Face) { - CFX_ByteString style = CFX_ByteString(FXFT_Get_Face_Style_Name(m_Face)); - CFX_ByteString facename = GetFamilyName(); - if (facename.IsEmpty()) - facename = "Untitled"; - if (!style.IsEmpty() && style != "Regular") - facename += " " + style; - return facename; - } - return m_pSubstFont->m_Family; -} - -bool CFX_Font::GetBBox(FX_RECT& bbox) { - if (!m_Face) - return false; - - int em = FXFT_Get_Face_UnitsPerEM(m_Face); - if (em == 0) { - bbox.left = FXFT_Get_Face_xMin(m_Face); - bbox.bottom = FXFT_Get_Face_yMax(m_Face); - bbox.top = FXFT_Get_Face_yMin(m_Face); - bbox.right = FXFT_Get_Face_xMax(m_Face); - } else { - bbox.left = FXFT_Get_Face_xMin(m_Face) * 1000 / em; - bbox.top = FXFT_Get_Face_yMin(m_Face) * 1000 / em; - bbox.right = FXFT_Get_Face_xMax(m_Face) * 1000 / em; - bbox.bottom = FXFT_Get_Face_yMax(m_Face) * 1000 / em; - } - return true; -} - -CFX_FaceCache* CFX_Font::GetFaceCache() const { - if (!m_FaceCache) - m_FaceCache = CFX_GEModule::Get()->GetFontCache()->GetCachedFace(this); - return m_FaceCache.Get(); -} - -void CFX_Font::ClearFaceCache() { - if (!m_FaceCache) - return; - - m_FaceCache = nullptr; - CFX_GEModule::Get()->GetFontCache()->ReleaseCachedFace(this); -} - -void CFX_Font::AdjustMMParams(int glyph_index, - int dest_width, - int weight) const { - FXFT_MM_Var pMasters = nullptr; - FXFT_Get_MM_Var(m_Face, &pMasters); - if (!pMasters) - return; - - long coords[2]; - if (weight == 0) - coords[0] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 0)) / 65536; - else - coords[0] = weight; - - if (dest_width == 0) { - coords[1] = FXFT_Get_MM_Axis_Def(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; - } else { - int min_param = FXFT_Get_MM_Axis_Min(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; - int max_param = FXFT_Get_MM_Axis_Max(FXFT_Get_MM_Axis(pMasters, 1)) / 65536; - coords[1] = min_param; - FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); - FXFT_Load_Glyph(m_Face, glyph_index, - FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); - int min_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / - FXFT_Get_Face_UnitsPerEM(m_Face); - coords[1] = max_param; - FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); - FXFT_Load_Glyph(m_Face, glyph_index, - FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); - int max_width = FXFT_Get_Glyph_HoriAdvance(m_Face) * 1000 / - FXFT_Get_Face_UnitsPerEM(m_Face); - if (max_width == min_width) { - FXFT_Free(m_Face, pMasters); - return; - } - int param = min_param + - (max_param - min_param) * (dest_width - min_width) / - (max_width - min_width); - coords[1] = param; - } - FXFT_Free(m_Face, pMasters); - FXFT_Set_MM_Design_Coordinates(m_Face, 2, coords); -} - -CFX_PathData* CFX_Font::LoadGlyphPathImpl(uint32_t glyph_index, - int dest_width) const { - if (!m_Face) - return nullptr; - FXFT_Set_Pixel_Sizes(m_Face, 0, 64); - FXFT_Matrix ft_matrix = {65536, 0, 0, 65536}; - if (m_pSubstFont) { - if (m_pSubstFont->m_ItalicAngle) { - int skew = m_pSubstFont->m_ItalicAngle; - // |skew| is nonpositive so |-skew| is used as the index. We need to make - // sure |skew| != INT_MIN since -INT_MIN is undefined. - if (skew <= 0 && skew != std::numeric_limits::min() && - static_cast(-skew) < kAngleSkewArraySize) { - skew = -s_AngleSkew[-skew]; - } else { - skew = -58; - } - if (m_bVertical) - ft_matrix.yx += ft_matrix.yy * skew / 100; - else - ft_matrix.xy -= ft_matrix.xx * skew / 100; - } - if (m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) - AdjustMMParams(glyph_index, dest_width, m_pSubstFont->m_Weight); - } - ScopedFontTransform scoped_transform(m_Face, &ft_matrix); - int load_flags = FXFT_LOAD_NO_BITMAP; - if (!(m_Face->face_flags & FT_FACE_FLAG_SFNT) || !FT_IS_TRICKY(m_Face)) - load_flags |= FT_LOAD_NO_HINTING; - if (FXFT_Load_Glyph(m_Face, glyph_index, load_flags)) - return nullptr; - if (m_pSubstFont && !(m_pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) && - m_pSubstFont->m_Weight > 400) { - uint32_t index = (m_pSubstFont->m_Weight - 400) / 10; - index = std::min(index, static_cast(kWeightPowArraySize - 1)); - int level = 0; - if (m_pSubstFont->m_Charset == FX_CHARSET_ShiftJIS) - level = s_WeightPow_SHIFTJIS[index] * 2 * 65536 / 36655; - else - level = s_WeightPow[index] * 2; - FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face), level); - } - - FXFT_Outline_Funcs funcs; - funcs.move_to = Outline_MoveTo; - funcs.line_to = Outline_LineTo; - funcs.conic_to = Outline_ConicTo; - funcs.cubic_to = Outline_CubicTo; - funcs.shift = 0; - funcs.delta = 0; - - OUTLINE_PARAMS params; - auto pPath = pdfium::MakeUnique(); - params.m_pPath = pPath.get(); - params.m_CurX = params.m_CurY = 0; - params.m_CoordUnit = 64 * 64.0; - - FXFT_Outline_Decompose(FXFT_Get_Glyph_Outline(m_Face), &funcs, ¶ms); - if (pPath->GetPoints().empty()) - return nullptr; - - Outline_CheckEmptyContour(¶ms); - pPath->ClosePath(); - - return pPath.release(); -} - -const CFX_GlyphBitmap* CFX_Font::LoadGlyphBitmap(uint32_t glyph_index, - bool bFontStyle, - const CFX_Matrix* pMatrix, - int dest_width, - int anti_alias, - int& text_flags) const { - return GetFaceCache()->LoadGlyphBitmap(this, glyph_index, bFontStyle, pMatrix, - dest_width, anti_alias, text_flags); -} - -const CFX_PathData* CFX_Font::LoadGlyphPath(uint32_t glyph_index, - int dest_width) const { - return GetFaceCache()->LoadGlyphPath(this, glyph_index, dest_width); -} - -#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_ -CFX_TypeFace* CFX_Font::GetDeviceCache() const { - return GetFaceCache()->GetDeviceCache(this); -} -#endif diff --git a/core/fxge/ge/cfx_fontcache.cpp b/core/fxge/ge/cfx_fontcache.cpp deleted file mode 100644 index 5ccac8cfbc..0000000000 --- a/core/fxge/ge/cfx_fontcache.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_fontcache.h" - -#include -#include - -#include "core/fxge/cfx_facecache.h" -#include "core/fxge/fx_font.h" -#include "core/fxge/fx_freetype.h" -#include "third_party/base/ptr_util.h" - -CFX_FontCache::CountedFaceCache::CountedFaceCache() {} - -CFX_FontCache::CountedFaceCache::~CountedFaceCache() {} - -CFX_FontCache::CFX_FontCache() {} - -CFX_FontCache::~CFX_FontCache() { - ASSERT(m_ExtFaceMap.empty()); - ASSERT(m_FTFaceMap.empty()); -} - -CFX_FaceCache* CFX_FontCache::GetCachedFace(const CFX_Font* pFont) { - FXFT_Face face = pFont->GetFace(); - const bool bExternal = !face; - CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; - auto it = map.find(face); - if (it != map.end()) { - CountedFaceCache* counted_face_cache = it->second.get(); - counted_face_cache->m_nCount++; - return counted_face_cache->m_Obj.get(); - } - - auto counted_face_cache = pdfium::MakeUnique(); - counted_face_cache->m_nCount = 2; - auto new_cache = - pdfium::MakeUnique(bExternal ? nullptr : face); - CFX_FaceCache* face_cache = new_cache.get(); - counted_face_cache->m_Obj = std::move(new_cache); - map[face] = std::move(counted_face_cache); - return face_cache; -} - -#ifdef _SKIA_SUPPORT_ -CFX_TypeFace* CFX_FontCache::GetDeviceCache(const CFX_Font* pFont) { - return GetCachedFace(pFont)->GetDeviceCache(pFont); -} -#endif - -void CFX_FontCache::ReleaseCachedFace(const CFX_Font* pFont) { - FXFT_Face face = pFont->GetFace(); - const bool bExternal = !face; - CFX_FTCacheMap& map = bExternal ? m_ExtFaceMap : m_FTFaceMap; - - auto it = map.find(face); - if (it == map.end()) - return; - - CountedFaceCache* counted_face_cache = it->second.get(); - if (counted_face_cache->m_nCount > 2) { - counted_face_cache->m_nCount--; - } else { - map.erase(it); - } -} diff --git a/core/fxge/ge/cfx_fontmapper.cpp b/core/fxge/ge/cfx_fontmapper.cpp deleted file mode 100644 index 5b4ceaac59..0000000000 --- a/core/fxge/ge/cfx_fontmapper.cpp +++ /dev/null @@ -1,817 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_fontmapper.h" - -#include -#include -#include -#include -#include - -#include "core/fxcrt/fx_codepage.h" -#include "core/fxge/cfx_substfont.h" -#include "core/fxge/fx_font.h" -#include "core/fxge/ifx_systemfontinfo.h" - -#include "third_party/base/stl_util.h" - -#define FX_FONT_STYLE_None 0x00 -#define FX_FONT_STYLE_Bold 0x01 -#define FX_FONT_STYLE_Italic 0x02 -#define FX_FONT_STYLE_BoldBold 0x04 - -namespace { - -const int kNumStandardFonts = 14; - -const char* const g_Base14FontNames[kNumStandardFonts] = { - "Courier", - "Courier-Bold", - "Courier-BoldOblique", - "Courier-Oblique", - "Helvetica", - "Helvetica-Bold", - "Helvetica-BoldOblique", - "Helvetica-Oblique", - "Times-Roman", - "Times-Bold", - "Times-BoldItalic", - "Times-Italic", - "Symbol", - "ZapfDingbats", -}; - -const struct AltFontName { - const char* m_pName; - int m_Index; -} g_AltFontNames[] = { - {"Arial", 4}, - {"Arial,Bold", 5}, - {"Arial,BoldItalic", 6}, - {"Arial,Italic", 7}, - {"Arial-Bold", 5}, - {"Arial-BoldItalic", 6}, - {"Arial-BoldItalicMT", 6}, - {"Arial-BoldMT", 5}, - {"Arial-Italic", 7}, - {"Arial-ItalicMT", 7}, - {"ArialBold", 5}, - {"ArialBoldItalic", 6}, - {"ArialItalic", 7}, - {"ArialMT", 4}, - {"ArialMT,Bold", 5}, - {"ArialMT,BoldItalic", 6}, - {"ArialMT,Italic", 7}, - {"ArialRoundedMTBold", 5}, - {"Courier", 0}, - {"Courier,Bold", 1}, - {"Courier,BoldItalic", 2}, - {"Courier,Italic", 3}, - {"Courier-Bold", 1}, - {"Courier-BoldOblique", 2}, - {"Courier-Oblique", 3}, - {"CourierBold", 1}, - {"CourierBoldItalic", 2}, - {"CourierItalic", 3}, - {"CourierNew", 0}, - {"CourierNew,Bold", 1}, - {"CourierNew,BoldItalic", 2}, - {"CourierNew,Italic", 3}, - {"CourierNew-Bold", 1}, - {"CourierNew-BoldItalic", 2}, - {"CourierNew-Italic", 3}, - {"CourierNewBold", 1}, - {"CourierNewBoldItalic", 2}, - {"CourierNewItalic", 3}, - {"CourierNewPS-BoldItalicMT", 2}, - {"CourierNewPS-BoldMT", 1}, - {"CourierNewPS-ItalicMT", 3}, - {"CourierNewPSMT", 0}, - {"CourierStd", 0}, - {"CourierStd-Bold", 1}, - {"CourierStd-BoldOblique", 2}, - {"CourierStd-Oblique", 3}, - {"Helvetica", 4}, - {"Helvetica,Bold", 5}, - {"Helvetica,BoldItalic", 6}, - {"Helvetica,Italic", 7}, - {"Helvetica-Bold", 5}, - {"Helvetica-BoldItalic", 6}, - {"Helvetica-BoldOblique", 6}, - {"Helvetica-Italic", 7}, - {"Helvetica-Oblique", 7}, - {"HelveticaBold", 5}, - {"HelveticaBoldItalic", 6}, - {"HelveticaItalic", 7}, - {"Symbol", 12}, - {"SymbolMT", 12}, - {"Times-Bold", 9}, - {"Times-BoldItalic", 10}, - {"Times-Italic", 11}, - {"Times-Roman", 8}, - {"TimesBold", 9}, - {"TimesBoldItalic", 10}, - {"TimesItalic", 11}, - {"TimesNewRoman", 8}, - {"TimesNewRoman,Bold", 9}, - {"TimesNewRoman,BoldItalic", 10}, - {"TimesNewRoman,Italic", 11}, - {"TimesNewRoman-Bold", 9}, - {"TimesNewRoman-BoldItalic", 10}, - {"TimesNewRoman-Italic", 11}, - {"TimesNewRomanBold", 9}, - {"TimesNewRomanBoldItalic", 10}, - {"TimesNewRomanItalic", 11}, - {"TimesNewRomanPS", 8}, - {"TimesNewRomanPS-Bold", 9}, - {"TimesNewRomanPS-BoldItalic", 10}, - {"TimesNewRomanPS-BoldItalicMT", 10}, - {"TimesNewRomanPS-BoldMT", 9}, - {"TimesNewRomanPS-Italic", 11}, - {"TimesNewRomanPS-ItalicMT", 11}, - {"TimesNewRomanPSMT", 8}, - {"TimesNewRomanPSMT,Bold", 9}, - {"TimesNewRomanPSMT,BoldItalic", 10}, - {"TimesNewRomanPSMT,Italic", 11}, - {"ZapfDingbats", 13}, -}; - -const struct AltFontFamily { - const char* m_pFontName; - const char* m_pFontFamily; -} g_AltFontFamilies[] = { - {"AGaramondPro", "Adobe Garamond Pro"}, - {"BankGothicBT-Medium", "BankGothic Md BT"}, - {"ForteMT", "Forte"}, -}; - -const struct FX_FontStyle { - const char* style; - int32_t len; -} g_FontStyles[] = { - {"Bold", 4}, {"Italic", 6}, {"BoldItalic", 10}, {"Reg", 3}, {"Regular", 7}, -}; - -const struct CODEPAGE_MAP { - uint16_t codepage; - uint8_t charset; -} g_Codepage2CharsetTable[] = { - {0, 1}, {42, 2}, {437, 254}, {850, 255}, {874, 222}, - {932, 128}, {936, 134}, {949, 129}, {950, 136}, {1250, 238}, - {1251, 204}, {1252, 0}, {1253, 161}, {1254, 162}, {1255, 177}, - {1256, 178}, {1257, 186}, {1258, 163}, {1361, 130}, {10000, 77}, - {10001, 78}, {10002, 81}, {10003, 79}, {10004, 84}, {10005, 83}, - {10006, 85}, {10007, 89}, {10008, 80}, {10021, 87}, {10029, 88}, - {10081, 86}, -}; - -int CompareFontFamilyString(const void* key, const void* element) { - CFX_ByteString str_key((const char*)key); - const AltFontFamily* family = reinterpret_cast(element); - if (str_key.Find(family->m_pFontName) != -1) - return 0; - return FXSYS_stricmp(reinterpret_cast(key), family->m_pFontName); -} - -int CompareString(const void* key, const void* element) { - return FXSYS_stricmp(reinterpret_cast(key), - reinterpret_cast(element)->m_pName); -} - -CFX_ByteString TT_NormalizeName(const char* family) { - CFX_ByteString norm(family); - norm.Remove(' '); - norm.Remove('-'); - norm.Remove(','); - int pos = norm.Find('+'); - if (pos > 0) - norm = norm.Left(pos); - norm.MakeLower(); - return norm; -} - -uint8_t GetCharsetFromCodePage(uint16_t codepage) { - const CODEPAGE_MAP* pEnd = - g_Codepage2CharsetTable + FX_ArraySize(g_Codepage2CharsetTable); - const CODEPAGE_MAP* pCharmap = - std::lower_bound(g_Codepage2CharsetTable, pEnd, codepage, - [](const CODEPAGE_MAP& charset, uint16_t page) { - return charset.codepage < page; - }); - if (pCharmap < pEnd && codepage == pCharmap->codepage) - return pCharmap->charset; - return FX_CHARSET_Default; -} - -CFX_ByteString GetFontFamily(CFX_ByteString fontName, int nStyle) { - if (fontName.Find("Script") >= 0) { - if ((nStyle & FX_FONT_STYLE_Bold) == FX_FONT_STYLE_Bold) - fontName = "ScriptMTBold"; - else if (fontName.Find("Palace") >= 0) - fontName = "PalaceScriptMT"; - else if (fontName.Find("French") >= 0) - fontName = "FrenchScriptMT"; - else if (fontName.Find("FreeStyle") >= 0) - fontName = "FreeStyleScript"; - return fontName; - } - AltFontFamily* found = reinterpret_cast(bsearch( - fontName.c_str(), g_AltFontFamilies, FX_ArraySize(g_AltFontFamilies), - sizeof(AltFontFamily), CompareFontFamilyString)); - return found ? CFX_ByteString(found->m_pFontFamily) : fontName; -} - -CFX_ByteString ParseStyle(const char* pStyle, int iLen, int iIndex) { - std::ostringstream buf; - if (!iLen || iLen <= iIndex) - return CFX_ByteString(buf); - while (iIndex < iLen) { - if (pStyle[iIndex] == ',') - break; - buf << pStyle[iIndex]; - ++iIndex; - } - return CFX_ByteString(buf); -} - -int32_t GetStyleType(const CFX_ByteString& bsStyle, bool bReverse) { - int32_t iLen = bsStyle.GetLength(); - if (!iLen) - return -1; - int iSize = FX_ArraySize(g_FontStyles); - const FX_FontStyle* pStyle = nullptr; - for (int i = iSize - 1; i >= 0; --i) { - pStyle = g_FontStyles + i; - if (!pStyle || pStyle->len > iLen) - continue; - - if (bReverse) { - if (bsStyle.Right(pStyle->len).Compare(pStyle->style) == 0) - return i; - } else { - if (bsStyle.Left(pStyle->len).Compare(pStyle->style) == 0) - return i; - } - } - return -1; -} - -bool CheckSupportThirdPartFont(CFX_ByteString name, int& PitchFamily) { - if (name == "MyriadPro") { - PitchFamily &= ~FXFONT_FF_ROMAN; - return true; - } - return false; -} - -void UpdatePitchFamily(uint32_t flags, int& PitchFamily) { - if (flags & FXFONT_SERIF) - PitchFamily |= FXFONT_FF_ROMAN; - if (flags & FXFONT_SCRIPT) - PitchFamily |= FXFONT_FF_SCRIPT; - if (flags & FXFONT_FIXED_PITCH) - PitchFamily |= FXFONT_FF_FIXEDPITCH; -} - -} // namespace - -CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) - : m_bListLoaded(false), m_pFontMgr(mgr) { - m_MMFaces[0] = nullptr; - m_MMFaces[1] = nullptr; - memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces)); -} - -CFX_FontMapper::~CFX_FontMapper() { - for (size_t i = 0; i < FX_ArraySize(m_FoxitFaces); ++i) { - if (m_FoxitFaces[i]) - FXFT_Done_Face(m_FoxitFaces[i]); - } - if (m_MMFaces[0]) - FXFT_Done_Face(m_MMFaces[0]); - if (m_MMFaces[1]) - FXFT_Done_Face(m_MMFaces[1]); -} - -void CFX_FontMapper::SetSystemFontInfo( - std::unique_ptr pFontInfo) { - if (!pFontInfo) - return; - - m_pFontInfo = std::move(pFontInfo); -} - -CFX_ByteString CFX_FontMapper::GetPSNameFromTT(void* hFont) { - if (!m_pFontInfo) - return CFX_ByteString(); - - uint32_t size = m_pFontInfo->GetFontData(hFont, kTableNAME, nullptr, 0); - if (!size) - return CFX_ByteString(); - - std::vector buffer(size); - uint8_t* buffer_ptr = buffer.data(); - uint32_t bytes_read = - m_pFontInfo->GetFontData(hFont, kTableNAME, buffer_ptr, size); - return bytes_read == size ? GetNameFromTT(buffer_ptr, bytes_read, 6) - : CFX_ByteString(); -} - -void CFX_FontMapper::AddInstalledFont(const CFX_ByteString& name, int charset) { - if (!m_pFontInfo) - return; - - m_FaceArray.push_back({name, static_cast(charset)}); - if (name == m_LastFamily) - return; - - bool bLocalized = std::any_of(name.begin(), name.end(), [](const char& c) { - return static_cast(c) > 0x80; - }); - - if (bLocalized) { - void* hFont = m_pFontInfo->GetFont(name.c_str()); - if (!hFont) { - int iExact; - hFont = m_pFontInfo->MapFont(0, 0, FX_CHARSET_Default, 0, name.c_str(), - iExact); - if (!hFont) - return; - } - - CFX_ByteString new_name = GetPSNameFromTT(hFont); - if (!new_name.IsEmpty()) - m_LocalizedTTFonts.push_back(std::make_pair(new_name, name)); - m_pFontInfo->DeleteFont(hFont); - } - m_InstalledTTFonts.push_back(name); - m_LastFamily = name; -} - -void CFX_FontMapper::LoadInstalledFonts() { - if (!m_pFontInfo || m_bListLoaded) - return; - - m_pFontInfo->EnumFontList(this); - m_bListLoaded = true; -} - -CFX_ByteString CFX_FontMapper::MatchInstalledFonts( - const CFX_ByteString& norm_name) { - LoadInstalledFonts(); - int i; - for (i = pdfium::CollectionSize(m_InstalledTTFonts) - 1; i >= 0; i--) { - CFX_ByteString norm1 = TT_NormalizeName(m_InstalledTTFonts[i].c_str()); - if (norm1 == norm_name) - return m_InstalledTTFonts[i]; - } - for (i = pdfium::CollectionSize(m_LocalizedTTFonts) - 1; i >= 0; i--) { - CFX_ByteString norm1 = - TT_NormalizeName(m_LocalizedTTFonts[i].first.c_str()); - if (norm1 == norm_name) - return m_LocalizedTTFonts[i].second; - } - return CFX_ByteString(); -} - -FXFT_Face CFX_FontMapper::UseInternalSubst(CFX_SubstFont* pSubstFont, - int iBaseFont, - int italic_angle, - int weight, - int picthfamily) { - if (iBaseFont < kNumStandardFonts) { - if (m_FoxitFaces[iBaseFont]) - return m_FoxitFaces[iBaseFont]; - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - if (m_pFontMgr->GetBuiltinFont(iBaseFont, &pFontData, &size)) { - m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_FoxitFaces[iBaseFont]; - } - } - pSubstFont->m_SubstFlags |= FXFONT_SUBST_MM; - pSubstFont->m_ItalicAngle = italic_angle; - if (weight) - pSubstFont->m_Weight = weight; - if (picthfamily & FXFONT_FF_ROMAN) { - pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5; - pSubstFont->m_Family = "Chrome Serif"; - if (m_MMFaces[1]) - return m_MMFaces[1]; - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - m_pFontMgr->GetBuiltinFont(14, &pFontData, &size); - m_MMFaces[1] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_MMFaces[1]; - } - pSubstFont->m_Family = "Chrome Sans"; - if (m_MMFaces[0]) - return m_MMFaces[0]; - const uint8_t* pFontData = nullptr; - uint32_t size = 0; - m_pFontMgr->GetBuiltinFont(15, &pFontData, &size); - m_MMFaces[0] = m_pFontMgr->GetFixedFace(pFontData, size, 0); - return m_MMFaces[0]; -} - -FXFT_Face CFX_FontMapper::FindSubstFont(const CFX_ByteString& name, - bool bTrueType, - uint32_t flags, - int weight, - int italic_angle, - int WindowCP, - CFX_SubstFont* pSubstFont) { - if (!(flags & FXFONT_USEEXTERNATTR)) { - weight = FXFONT_FW_NORMAL; - italic_angle = 0; - } - CFX_ByteString SubstName = name; - SubstName.Remove(' '); - if (bTrueType && name[0] == '@') - SubstName = name.Mid(1); - PDF_GetStandardFontName(&SubstName); - if (SubstName == "Symbol" && !bTrueType) { - pSubstFont->m_Family = "Chrome Symbol"; - pSubstFont->m_Charset = FX_CHARSET_Symbol; - return UseInternalSubst(pSubstFont, 12, italic_angle, weight, 0); - } - if (SubstName == "ZapfDingbats") { - pSubstFont->m_Family = "Chrome Dingbats"; - pSubstFont->m_Charset = FX_CHARSET_Symbol; - return UseInternalSubst(pSubstFont, 13, italic_angle, weight, 0); - } - int iBaseFont = 0; - CFX_ByteString family; - CFX_ByteString style; - bool bHasComma = false; - bool bHasHyphen = false; - int find = SubstName.Find(",", 0); - if (find >= 0) { - family = SubstName.Left(find); - PDF_GetStandardFontName(&family); - style = SubstName.Mid(find + 1); - bHasComma = true; - } else { - family = SubstName; - } - for (; iBaseFont < 12; iBaseFont++) { - if (family == CFX_ByteStringC(g_Base14FontNames[iBaseFont])) - break; - } - int PitchFamily = 0; - bool bItalic = false; - uint32_t nStyle = 0; - bool bStyleAvail = false; - if (iBaseFont < 12) { - if ((iBaseFont % 4) == 1 || (iBaseFont % 4) == 2) - nStyle |= FX_FONT_STYLE_Bold; - if ((iBaseFont % 4) / 2) - nStyle |= FX_FONT_STYLE_Italic; - if (iBaseFont < 4) - PitchFamily |= FXFONT_FF_FIXEDPITCH; - if (iBaseFont >= 8) - PitchFamily |= FXFONT_FF_ROMAN; - } else { - iBaseFont = kNumStandardFonts; - if (!bHasComma) { - find = family.ReverseFind('-'); - if (find >= 0) { - style = family.Mid(find + 1); - family = family.Left(find); - bHasHyphen = true; - } - } - if (!bHasHyphen) { - int nLen = family.GetLength(); - int32_t nRet = GetStyleType(family, true); - if (nRet > -1) { - family = family.Left(nLen - g_FontStyles[nRet].len); - if (nRet == 0) - nStyle |= FX_FONT_STYLE_Bold; - else if (nRet == 1) - nStyle |= FX_FONT_STYLE_Italic; - else if (nRet == 2) - nStyle |= (FX_FONT_STYLE_Bold | FX_FONT_STYLE_Italic); - } - } - UpdatePitchFamily(flags, PitchFamily); - } - if (!style.IsEmpty()) { - int nLen = style.GetLength(); - const char* pStyle = style.c_str(); - int i = 0; - bool bFirstItem = true; - CFX_ByteString buf; - while (i < nLen) { - buf = ParseStyle(pStyle, nLen, i); - int32_t nRet = GetStyleType(buf, false); - if ((i && !bStyleAvail) || (!i && nRet < 0)) { - family = SubstName; - iBaseFont = kNumStandardFonts; - break; - } - if (nRet >= 0) { - bStyleAvail = true; - } - if (nRet == 1) { - if (bFirstItem) { - nStyle |= FX_FONT_STYLE_Italic; - } else { - family = SubstName; - iBaseFont = kNumStandardFonts; - } - break; - } - if (nRet == 0) { - if (nStyle & FX_FONT_STYLE_Bold) - nStyle |= FX_FONT_STYLE_BoldBold; - else - nStyle |= FX_FONT_STYLE_Bold; - bFirstItem = false; - } else if (nRet == 2) { - nStyle |= FX_FONT_STYLE_Italic; - if (nStyle & FX_FONT_STYLE_Bold) - nStyle |= FX_FONT_STYLE_BoldBold; - else - nStyle |= FX_FONT_STYLE_Bold; - bFirstItem = false; - } - i += buf.GetLength() + 1; - } - } - weight = weight ? weight : FXFONT_FW_NORMAL; - int old_weight = weight; - if (nStyle) { - weight = - nStyle & FX_FONT_STYLE_BoldBold - ? 900 - : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); - } - if (nStyle & FX_FONT_STYLE_Italic) - bItalic = true; - int iExact = 0; - int Charset = FX_CHARSET_ANSI; - if (WindowCP) - Charset = GetCharsetFromCodePage(WindowCP); - else if (iBaseFont == kNumStandardFonts && (flags & FXFONT_SYMBOLIC)) - Charset = FX_CHARSET_Symbol; - bool bCJK = (Charset == FX_CHARSET_ShiftJIS || - Charset == FX_CHARSET_ChineseSimplified || - Charset == FX_CHARSET_Hangul || - Charset == FX_CHARSET_ChineseTraditional); - if (!m_pFontInfo) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - family = GetFontFamily(family, nStyle); - CFX_ByteString match = MatchInstalledFonts(TT_NormalizeName(family.c_str())); - if (match.IsEmpty() && family != SubstName && - (!bHasComma && (!bHasHyphen || (bHasHyphen && !bStyleAvail)))) { - match = MatchInstalledFonts(TT_NormalizeName(SubstName.c_str())); - } - if (match.IsEmpty() && iBaseFont >= kNumStandardFonts) { - if (!bCJK) { - if (!CheckSupportThirdPartFont(family, PitchFamily)) { - bItalic = italic_angle != 0; - weight = old_weight; - } -#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ - if (SubstName.Find("Narrow") > 0 || SubstName.Find("Condensed") > 0) - family = "LiberationSansNarrow"; -#elif _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ - if (family.Find("Narrow") > 0 || family.Find("Condensed") > 0) - family = "RobotoCondensed"; -#else - if (family.Find("Narrow") > 0 || family.Find("Condensed") > 0) - family = "ArialNarrow"; -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ - } else { - pSubstFont->m_bSubstCJK = true; - if (nStyle) - pSubstFont->m_WeightCJK = nStyle ? weight : FXFONT_FW_NORMAL; - if (nStyle & FX_FONT_STYLE_Italic) - pSubstFont->m_bItalicCJK = true; - } - } else { - italic_angle = 0; - weight = - nStyle & FX_FONT_STYLE_BoldBold - ? 900 - : (nStyle & FX_FONT_STYLE_Bold ? FXFONT_FW_BOLD : FXFONT_FW_NORMAL); - } - if (!match.IsEmpty() || iBaseFont < kNumStandardFonts) { - if (!match.IsEmpty()) - family = match; - if (iBaseFont < kNumStandardFonts) { - if (nStyle && !(iBaseFont % 4)) { - if ((nStyle & 0x3) == 1) - iBaseFont += 1; - if ((nStyle & 0x3) == 2) - iBaseFont += 3; - if ((nStyle & 0x3) == 3) - iBaseFont += 2; - } - family = g_Base14FontNames[iBaseFont]; - } - } else { - if (flags & FXFONT_ITALIC) - bItalic = true; - } - iExact = !match.IsEmpty(); - void* hFont = m_pFontInfo->MapFont(weight, bItalic, Charset, PitchFamily, - family.c_str(), iExact); - if (iExact) - pSubstFont->m_SubstFlags |= FXFONT_SUBST_EXACT; - if (!hFont) { -#ifdef PDF_ENABLE_XFA - if (flags & FXFONT_EXACTMATCH) - return nullptr; -#endif // PDF_ENABLE_XFA - if (bCJK) { - bItalic = italic_angle != 0; - weight = old_weight; - } - if (!match.IsEmpty()) { - hFont = m_pFontInfo->GetFont(match.c_str()); - if (!hFont) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - } else { - if (Charset == FX_CHARSET_Symbol) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || \ - _FXM_PLATFORM_ == _FXM_PLATFORM_ANDROID_ - if (SubstName == "Symbol") { - pSubstFont->m_Family = "Chrome Symbol"; - pSubstFont->m_Charset = FX_CHARSET_Symbol; - return UseInternalSubst(pSubstFont, 12, italic_angle, old_weight, - PitchFamily); - } -#endif - return FindSubstFont(family, bTrueType, flags & ~FXFONT_SYMBOLIC, - weight, italic_angle, 0, pSubstFont); - } - if (Charset == FX_CHARSET_ANSI) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - - auto it = - std::find_if(m_FaceArray.begin(), m_FaceArray.end(), - [Charset](const FaceData& face) { - return face.charset == static_cast(Charset); - }); - if (it == m_FaceArray.end()) { - return UseInternalSubst(pSubstFont, iBaseFont, italic_angle, old_weight, - PitchFamily); - } - hFont = m_pFontInfo->GetFont(it->name.c_str()); - } - } - if (!hFont) - return nullptr; - - m_pFontInfo->GetFaceName(hFont, &SubstName); - if (Charset == FX_CHARSET_Default) - m_pFontInfo->GetFontCharset(hFont, &Charset); - uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, kTableTTCF, nullptr, 0); - uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); - if (font_size == 0 && ttc_size == 0) { - m_pFontInfo->DeleteFont(hFont); - return nullptr; - } - FXFT_Face face = nullptr; - if (ttc_size) - face = GetCachedTTCFace(hFont, kTableTTCF, ttc_size, font_size); - else - face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size); - if (!face) { - m_pFontInfo->DeleteFont(hFont); - return nullptr; - } - pSubstFont->m_Family = SubstName; - pSubstFont->m_Charset = Charset; - bool bNeedUpdateWeight = false; - if (FXFT_Is_Face_Bold(face)) - bNeedUpdateWeight = weight != FXFONT_FW_BOLD; - else - bNeedUpdateWeight = weight != FXFONT_FW_NORMAL; - if (bNeedUpdateWeight) - pSubstFont->m_Weight = weight; - if (bItalic && !FXFT_Is_Face_Italic(face)) { - if (italic_angle == 0) - italic_angle = -12; - else if (abs(italic_angle) < 5) - italic_angle = 0; - pSubstFont->m_ItalicAngle = italic_angle; - } - m_pFontInfo->DeleteFont(hFont); - return face; -} - -#ifdef PDF_ENABLE_XFA -FXFT_Face CFX_FontMapper::FindSubstFontByUnicode(uint32_t dwUnicode, - uint32_t flags, - int weight, - int italic_angle) { - if (!m_pFontInfo) - return nullptr; - - bool bItalic = (flags & FXFONT_ITALIC) != 0; - int PitchFamily = 0; - UpdatePitchFamily(flags, PitchFamily); - void* hFont = - m_pFontInfo->MapFontByUnicode(dwUnicode, weight, bItalic, PitchFamily); - if (!hFont) - return nullptr; - - uint32_t ttc_size = m_pFontInfo->GetFontData(hFont, 0x74746366, nullptr, 0); - uint32_t font_size = m_pFontInfo->GetFontData(hFont, 0, nullptr, 0); - if (font_size == 0 && ttc_size == 0) { - m_pFontInfo->DeleteFont(hFont); - return nullptr; - } - FXFT_Face face = nullptr; - if (ttc_size) { - face = GetCachedTTCFace(hFont, 0x74746366, ttc_size, font_size); - } else { - CFX_ByteString SubstName; - m_pFontInfo->GetFaceName(hFont, &SubstName); - face = GetCachedFace(hFont, SubstName, weight, bItalic, font_size); - } - m_pFontInfo->DeleteFont(hFont); - return face; -} -#endif // PDF_ENABLE_XFA - -int CFX_FontMapper::GetFaceSize() const { - return pdfium::CollectionSize(m_FaceArray); -} - -bool CFX_FontMapper::IsBuiltinFace(const FXFT_Face face) const { - for (size_t i = 0; i < MM_FACE_COUNT; ++i) { - if (m_MMFaces[i] == face) - return true; - } - for (size_t i = 0; i < FOXIT_FACE_COUNT; ++i) { - if (m_FoxitFaces[i] == face) - return true; - } - return false; -} - -FXFT_Face CFX_FontMapper::GetCachedTTCFace(void* hFont, - const uint32_t tableTTCF, - uint32_t ttc_size, - uint32_t font_size) { - FXFT_Face face; - uint8_t buffer[1024]; - m_pFontInfo->GetFontData(hFont, tableTTCF, buffer, FX_ArraySize(buffer)); - uint32_t* pBuffer = reinterpret_cast(buffer); - uint32_t checksum = 0; - for (int i = 0; i < 256; i++) - checksum += pBuffer[i]; - uint8_t* pFontData; - face = m_pFontMgr->GetCachedTTCFace(ttc_size, checksum, ttc_size - font_size, - pFontData); - if (!face) { - pFontData = FX_Alloc(uint8_t, ttc_size); - m_pFontInfo->GetFontData(hFont, tableTTCF, pFontData, ttc_size); - face = m_pFontMgr->AddCachedTTCFace(ttc_size, checksum, pFontData, ttc_size, - ttc_size - font_size); - } - return face; -} - -FXFT_Face CFX_FontMapper::GetCachedFace(void* hFont, - CFX_ByteString SubstName, - int weight, - bool bItalic, - uint32_t font_size) { - FXFT_Face face; - uint8_t* pFontData; - face = m_pFontMgr->GetCachedFace(SubstName, weight, bItalic, pFontData); - if (!face) { - pFontData = FX_Alloc(uint8_t, font_size); - m_pFontInfo->GetFontData(hFont, 0, pFontData, font_size); - face = - m_pFontMgr->AddCachedFace(SubstName, weight, bItalic, pFontData, - font_size, m_pFontInfo->GetFaceIndex(hFont)); - } - return face; -} - -int PDF_GetStandardFontName(CFX_ByteString* name) { - AltFontName* found = static_cast( - bsearch(name->c_str(), g_AltFontNames, FX_ArraySize(g_AltFontNames), - sizeof(AltFontName), CompareString)); - if (!found) - return -1; - - *name = g_Base14FontNames[found->m_Index]; - return found->m_Index; -} diff --git a/core/fxge/ge/cfx_fontmgr.cpp b/core/fxge/ge/cfx_fontmgr.cpp deleted file mode 100644 index ec184ae266..0000000000 --- a/core/fxge/ge/cfx_fontmgr.cpp +++ /dev/null @@ -1,259 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_fontmgr.h" - -#include -#include - -#include "core/fxge/cfx_fontmapper.h" -#include "core/fxge/cfx_substfont.h" -#include "core/fxge/fontdata/chromefontdata/chromefontdata.h" -#include "core/fxge/fx_font.h" -#include "core/fxge/ge/cttfontdesc.h" -#include "core/fxge/ifx_systemfontinfo.h" -#include "third_party/base/ptr_util.h" - -namespace { - -struct BuiltinFont { - const uint8_t* m_pFontData; - uint32_t m_dwSize; -}; - -const BuiltinFont g_FoxitFonts[14] = { - {g_FoxitFixedFontData, 17597}, - {g_FoxitFixedBoldFontData, 18055}, - {g_FoxitFixedBoldItalicFontData, 19151}, - {g_FoxitFixedItalicFontData, 18746}, - {g_FoxitSansFontData, 15025}, - {g_FoxitSansBoldFontData, 16344}, - {g_FoxitSansBoldItalicFontData, 16418}, - {g_FoxitSansItalicFontData, 16339}, - {g_FoxitSerifFontData, 19469}, - {g_FoxitSerifBoldFontData, 19395}, - {g_FoxitSerifBoldItalicFontData, 20733}, - {g_FoxitSerifItalicFontData, 21227}, - {g_FoxitSymbolFontData, 16729}, - {g_FoxitDingbatsFontData, 29513}, -}; - -const BuiltinFont g_MMFonts[2] = { - {g_FoxitSerifMMFontData, 113417}, - {g_FoxitSansMMFontData, 66919}, -}; - -CFX_ByteString KeyNameFromFace(const CFX_ByteString& face_name, - int weight, - bool bItalic) { - CFX_ByteString key(face_name); - key += ','; - key += CFX_ByteString::FormatInteger(weight); - key += bItalic ? 'I' : 'N'; - return key; -} - -CFX_ByteString KeyNameFromSize(int ttc_size, uint32_t checksum) { - CFX_ByteString key; - key.Format("%d:%d", ttc_size, checksum); - return key; -} - -int GetTTCIndex(const uint8_t* pFontData, - uint32_t ttc_size, - uint32_t font_offset) { - int face_index = 0; - const uint8_t* p = pFontData + 8; - uint32_t nfont = GET_TT_LONG(p); - uint32_t index; - for (index = 0; index < nfont; index++) { - p = pFontData + 12 + index * 4; - if (GET_TT_LONG(p) == font_offset) - break; - } - if (index >= nfont) - face_index = 0; - else - face_index = index; - return face_index; -} - -} // namespace - -CFX_FontMgr::CFX_FontMgr() - : m_FTLibrary(nullptr), m_FTLibrarySupportsHinting(false) { - m_pBuiltinMapper = pdfium::MakeUnique(this); -} - -CFX_FontMgr::~CFX_FontMgr() { - // |m_FaceMap| and |m_pBuiltinMapper| reference |m_FTLibrary|, so they must - // be destroyed first. - m_FaceMap.clear(); - m_pBuiltinMapper.reset(); - FXFT_Done_FreeType(m_FTLibrary); -} - -void CFX_FontMgr::InitFTLibrary() { - if (m_FTLibrary) - return; - FXFT_Init_FreeType(&m_FTLibrary); - m_FTLibrarySupportsHinting = - FXFT_Library_SetLcdFilter(m_FTLibrary, FT_LCD_FILTER_DEFAULT) != - FT_Err_Unimplemented_Feature; -} - -void CFX_FontMgr::SetSystemFontInfo( - std::unique_ptr pFontInfo) { - m_pBuiltinMapper->SetSystemFontInfo(std::move(pFontInfo)); -} - -FXFT_Face CFX_FontMgr::FindSubstFont(const CFX_ByteString& face_name, - bool bTrueType, - uint32_t flags, - int weight, - int italic_angle, - int CharsetCP, - CFX_SubstFont* pSubstFont) { - InitFTLibrary(); - return m_pBuiltinMapper->FindSubstFont(face_name, bTrueType, flags, weight, - italic_angle, CharsetCP, pSubstFont); -} - -FXFT_Face CFX_FontMgr::GetCachedFace(const CFX_ByteString& face_name, - int weight, - bool bItalic, - uint8_t*& pFontData) { - auto it = m_FaceMap.find(KeyNameFromFace(face_name, weight, bItalic)); - if (it == m_FaceMap.end()) - return nullptr; - - CTTFontDesc* pFontDesc = it->second.get(); - pFontData = pFontDesc->m_pFontData; - pFontDesc->m_RefCount++; - return pFontDesc->m_SingleFace; -} - -FXFT_Face CFX_FontMgr::AddCachedFace(const CFX_ByteString& face_name, - int weight, - bool bItalic, - uint8_t* pData, - uint32_t size, - int face_index) { - auto pFontDesc = pdfium::MakeUnique(); - pFontDesc->m_Type = 1; - pFontDesc->m_SingleFace = nullptr; - pFontDesc->m_pFontData = pData; - pFontDesc->m_RefCount = 1; - - InitFTLibrary(); - FXFT_Library library = m_FTLibrary; - int ret = FXFT_New_Memory_Face(library, pData, size, face_index, - &pFontDesc->m_SingleFace); - if (ret) - return nullptr; - - ret = FXFT_Set_Pixel_Sizes(pFontDesc->m_SingleFace, 64, 64); - if (ret) - return nullptr; - - CTTFontDesc* pResult = pFontDesc.get(); - m_FaceMap[KeyNameFromFace(face_name, weight, bItalic)] = std::move(pFontDesc); - return pResult->m_SingleFace; -} - -FXFT_Face CFX_FontMgr::GetCachedTTCFace(int ttc_size, - uint32_t checksum, - int font_offset, - uint8_t*& pFontData) { - auto it = m_FaceMap.find(KeyNameFromSize(ttc_size, checksum)); - if (it == m_FaceMap.end()) - return nullptr; - - CTTFontDesc* pFontDesc = it->second.get(); - pFontData = pFontDesc->m_pFontData; - pFontDesc->m_RefCount++; - int face_index = GetTTCIndex(pFontDesc->m_pFontData, ttc_size, font_offset); - if (!pFontDesc->m_TTCFaces[face_index]) { - pFontDesc->m_TTCFaces[face_index] = - GetFixedFace(pFontDesc->m_pFontData, ttc_size, face_index); - } - return pFontDesc->m_TTCFaces[face_index]; -} - -FXFT_Face CFX_FontMgr::AddCachedTTCFace(int ttc_size, - uint32_t checksum, - uint8_t* pData, - uint32_t size, - int font_offset) { - auto pFontDesc = pdfium::MakeUnique(); - pFontDesc->m_Type = 2; - pFontDesc->m_pFontData = pData; - for (int i = 0; i < 16; i++) - pFontDesc->m_TTCFaces[i] = nullptr; - pFontDesc->m_RefCount++; - CTTFontDesc* pResult = pFontDesc.get(); - m_FaceMap[KeyNameFromSize(ttc_size, checksum)] = std::move(pFontDesc); - int face_index = GetTTCIndex(pResult->m_pFontData, ttc_size, font_offset); - pResult->m_TTCFaces[face_index] = - GetFixedFace(pResult->m_pFontData, ttc_size, face_index); - return pResult->m_TTCFaces[face_index]; -} - -FXFT_Face CFX_FontMgr::GetFixedFace(const uint8_t* pData, - uint32_t size, - int face_index) { - InitFTLibrary(); - FXFT_Library library = m_FTLibrary; - FXFT_Face face = nullptr; - if (FXFT_New_Memory_Face(library, pData, size, face_index, &face)) - return nullptr; - return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; -} - -FXFT_Face CFX_FontMgr::GetFileFace(const char* filename, int face_index) { - InitFTLibrary(); - FXFT_Library library = m_FTLibrary; - FXFT_Face face = nullptr; - if (FXFT_New_Face(library, filename, face_index, &face)) - return nullptr; - return FXFT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face; -} - -void CFX_FontMgr::ReleaseFace(FXFT_Face face) { - if (!face) - return; - bool bNeedFaceDone = true; - auto it = m_FaceMap.begin(); - while (it != m_FaceMap.end()) { - auto temp = it++; - int nRet = temp->second->ReleaseFace(face); - if (nRet == -1) - continue; - bNeedFaceDone = false; - if (nRet == 0) - m_FaceMap.erase(temp); - break; - } - if (bNeedFaceDone && !m_pBuiltinMapper->IsBuiltinFace(face)) - FXFT_Done_Face(face); -} - -bool CFX_FontMgr::GetBuiltinFont(size_t index, - const uint8_t** pFontData, - uint32_t* size) { - if (index < FX_ArraySize(g_FoxitFonts)) { - *pFontData = g_FoxitFonts[index].m_pFontData; - *size = g_FoxitFonts[index].m_dwSize; - return true; - } - index -= FX_ArraySize(g_FoxitFonts); - if (index < FX_ArraySize(g_MMFonts)) { - *pFontData = g_MMFonts[index].m_pFontData; - *size = g_MMFonts[index].m_dwSize; - return true; - } - return false; -} diff --git a/core/fxge/ge/cfx_gemodule.cpp b/core/fxge/ge/cfx_gemodule.cpp deleted file mode 100644 index 4516d61e27..0000000000 --- a/core/fxge/ge/cfx_gemodule.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_gemodule.h" - -#include "core/fxge/cfx_fontcache.h" -#include "core/fxge/cfx_fontmgr.h" -#include "core/fxge/ge/cfx_folderfontinfo.h" -#include "core/fxge/ge/fx_text_int.h" -#include "third_party/base/ptr_util.h" - -namespace { - -CFX_GEModule* g_pGEModule = nullptr; - -} // namespace - -CFX_GEModule::CFX_GEModule() - : m_pFontMgr(pdfium::MakeUnique()), - m_pPlatformData(nullptr), - m_pUserFontPaths(nullptr) {} - -CFX_GEModule::~CFX_GEModule() { - DestroyPlatform(); -} - -// static -CFX_GEModule* CFX_GEModule::Get() { - if (!g_pGEModule) - g_pGEModule = new CFX_GEModule(); - return g_pGEModule; -} - -// static -void CFX_GEModule::Destroy() { - ASSERT(g_pGEModule); - delete g_pGEModule; - g_pGEModule = nullptr; -} - -void CFX_GEModule::Init(const char** userFontPaths) { - ASSERT(g_pGEModule); - m_pUserFontPaths = userFontPaths; - InitPlatform(); -} - -CFX_FontCache* CFX_GEModule::GetFontCache() { - if (!m_pFontCache) - m_pFontCache = pdfium::MakeUnique(); - return m_pFontCache.get(); -} diff --git a/core/fxge/ge/cfx_graphstate.cpp b/core/fxge/ge/cfx_graphstate.cpp deleted file mode 100644 index ad6b5fc6c7..0000000000 --- a/core/fxge/ge/cfx_graphstate.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_graphstate.h" - -#include "core/fpdfapi/parser/cpdf_array.h" - -CFX_GraphState::CFX_GraphState() {} - -CFX_GraphState::CFX_GraphState(const CFX_GraphState& that) - : m_Ref(that.m_Ref) {} - -CFX_GraphState::~CFX_GraphState() {} - -void CFX_GraphState::Emplace() { - m_Ref.Emplace(); -} - -void CFX_GraphState::SetLineDash(CPDF_Array* pArray, float phase, float scale) { - CFX_GraphStateData* pData = m_Ref.GetPrivateCopy(); - pData->m_DashPhase = phase * scale; - pData->SetDashCount(static_cast(pArray->GetCount())); - for (size_t i = 0; i < pArray->GetCount(); i++) - pData->m_DashArray[i] = pArray->GetNumberAt(i) * scale; -} - -float CFX_GraphState::GetLineWidth() const { - return m_Ref.GetObject() ? m_Ref.GetObject()->m_LineWidth : 1.f; -} - -void CFX_GraphState::SetLineWidth(float width) { - m_Ref.GetPrivateCopy()->m_LineWidth = width; -} - -CFX_GraphStateData::LineCap CFX_GraphState::GetLineCap() const { - return m_Ref.GetObject() ? m_Ref.GetObject()->m_LineCap - : CFX_GraphStateData::LineCapButt; -} -void CFX_GraphState::SetLineCap(CFX_GraphStateData::LineCap cap) { - m_Ref.GetPrivateCopy()->m_LineCap = cap; -} - -CFX_GraphStateData::LineJoin CFX_GraphState::GetLineJoin() const { - return m_Ref.GetObject() ? m_Ref.GetObject()->m_LineJoin - : CFX_GraphStateData::LineJoinMiter; -} - -void CFX_GraphState::SetLineJoin(CFX_GraphStateData::LineJoin join) { - m_Ref.GetPrivateCopy()->m_LineJoin = join; -} - -float CFX_GraphState::GetMiterLimit() const { - return m_Ref.GetObject() ? m_Ref.GetObject()->m_MiterLimit : 10.f; -} - -void CFX_GraphState::SetMiterLimit(float limit) { - m_Ref.GetPrivateCopy()->m_MiterLimit = limit; -} diff --git a/core/fxge/ge/cfx_graphstatedata.cpp b/core/fxge/ge/cfx_graphstatedata.cpp deleted file mode 100644 index 82fede176a..0000000000 --- a/core/fxge/ge/cfx_graphstatedata.cpp +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_graphstatedata.h" - -#include "core/fxcrt/fx_memory.h" -#include "core/fxcrt/fx_system.h" - -CFX_GraphStateData::CFX_GraphStateData() - : m_LineCap(LineCapButt), - m_DashCount(0), - m_DashArray(nullptr), - m_DashPhase(0), - m_LineJoin(LineJoinMiter), - m_MiterLimit(10 * 1.0f), - m_LineWidth(1.0f) {} - -CFX_GraphStateData::CFX_GraphStateData(const CFX_GraphStateData& src) { - m_DashArray = nullptr; - Copy(src); -} - -void CFX_GraphStateData::Copy(const CFX_GraphStateData& src) { - m_LineCap = src.m_LineCap; - m_DashCount = src.m_DashCount; - FX_Free(m_DashArray); - m_DashArray = nullptr; - m_DashPhase = src.m_DashPhase; - m_LineJoin = src.m_LineJoin; - m_MiterLimit = src.m_MiterLimit; - m_LineWidth = src.m_LineWidth; - if (m_DashCount) { - m_DashArray = FX_Alloc(float, m_DashCount); - memcpy(m_DashArray, src.m_DashArray, m_DashCount * sizeof(float)); - } -} - -CFX_GraphStateData::~CFX_GraphStateData() { - FX_Free(m_DashArray); -} - -void CFX_GraphStateData::SetDashCount(int count) { - FX_Free(m_DashArray); - m_DashArray = nullptr; - m_DashCount = count; - if (count == 0) - return; - m_DashArray = FX_Alloc(float, count); -} diff --git a/core/fxge/ge/cfx_pathdata.cpp b/core/fxge/ge/cfx_pathdata.cpp deleted file mode 100644 index fe3c6778d5..0000000000 --- a/core/fxge/ge/cfx_pathdata.cpp +++ /dev/null @@ -1,487 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_pathdata.h" - -#include "core/fxcrt/fx_system.h" -#include "third_party/base/numerics/safe_math.h" - -namespace { - -void UpdateLineEndPoints(CFX_FloatRect* rect, - const CFX_PointF& start_pos, - const CFX_PointF& end_pos, - float hw) { - if (start_pos.x == end_pos.x) { - if (start_pos.y == end_pos.y) { - rect->UpdateRect(end_pos.x + hw, end_pos.y + hw); - rect->UpdateRect(end_pos.x - hw, end_pos.y - hw); - return; - } - - float point_y; - if (end_pos.y < start_pos.y) - point_y = end_pos.y - hw; - else - point_y = end_pos.y + hw; - - rect->UpdateRect(end_pos.x + hw, point_y); - rect->UpdateRect(end_pos.x - hw, point_y); - return; - } - - if (start_pos.y == end_pos.y) { - float point_x; - if (end_pos.x < start_pos.x) - point_x = end_pos.x - hw; - else - point_x = end_pos.x + hw; - - rect->UpdateRect(point_x, end_pos.y + hw); - rect->UpdateRect(point_x, end_pos.y - hw); - return; - } - - CFX_PointF diff = end_pos - start_pos; - float ll = FXSYS_sqrt2(diff.x, diff.y); - float mx = end_pos.x + hw * diff.x / ll; - float my = end_pos.y + hw * diff.y / ll; - float dx1 = hw * diff.y / ll; - float dy1 = hw * diff.x / ll; - rect->UpdateRect(mx - dx1, my + dy1); - rect->UpdateRect(mx + dx1, my - dy1); -} - -void UpdateLineJoinPoints(CFX_FloatRect* rect, - const CFX_PointF& start_pos, - const CFX_PointF& mid_pos, - const CFX_PointF& end_pos, - float half_width, - float miter_limit) { - float start_k = 0; - float start_c = 0; - float end_k = 0; - float end_c = 0; - float start_len = 0; - float start_dc = 0; - float end_len = 0; - float end_dc = 0; - float one_twentieth = 1.0f / 20; - - bool bStartVert = fabs(start_pos.x - mid_pos.x) < one_twentieth; - bool bEndVert = fabs(mid_pos.x - end_pos.x) < one_twentieth; - if (bStartVert && bEndVert) { - int start_dir = mid_pos.y > start_pos.y ? 1 : -1; - float point_y = mid_pos.y + half_width * start_dir; - rect->UpdateRect(mid_pos.x + half_width, point_y); - rect->UpdateRect(mid_pos.x - half_width, point_y); - return; - } - - if (!bStartVert) { - CFX_PointF start_to_mid = start_pos - mid_pos; - start_k = (mid_pos.y - start_pos.y) / (mid_pos.x - start_pos.x); - start_c = mid_pos.y - (start_k * mid_pos.x); - start_len = FXSYS_sqrt2(start_to_mid.x, start_to_mid.y); - start_dc = - static_cast(fabs(half_width * start_len / start_to_mid.x)); - } - if (!bEndVert) { - CFX_PointF end_to_mid = end_pos - mid_pos; - end_k = end_to_mid.y / end_to_mid.x; - end_c = mid_pos.y - (end_k * mid_pos.x); - end_len = FXSYS_sqrt2(end_to_mid.x, end_to_mid.y); - end_dc = static_cast(fabs(half_width * end_len / end_to_mid.x)); - } - if (bStartVert) { - CFX_PointF outside(start_pos.x, 0); - if (end_pos.x < start_pos.x) - outside.x += half_width; - else - outside.x -= half_width; - - if (start_pos.y < (end_k * start_pos.x) + end_c) - outside.y = (end_k * outside.x) + end_c + end_dc; - else - outside.y = (end_k * outside.x) + end_c - end_dc; - - rect->UpdateRect(outside.x, outside.y); - return; - } - - if (bEndVert) { - CFX_PointF outside(end_pos.x, 0); - if (start_pos.x < end_pos.x) - outside.x += half_width; - else - outside.x -= half_width; - - if (end_pos.y < (start_k * end_pos.x) + start_c) - outside.y = (start_k * outside.x) + start_c + start_dc; - else - outside.y = (start_k * outside.x) + start_c - start_dc; - - rect->UpdateRect(outside.x, outside.y); - return; - } - - if (fabs(start_k - end_k) < one_twentieth) { - int start_dir = mid_pos.x > start_pos.x ? 1 : -1; - int end_dir = end_pos.x > mid_pos.x ? 1 : -1; - if (start_dir == end_dir) - UpdateLineEndPoints(rect, mid_pos, end_pos, half_width); - else - UpdateLineEndPoints(rect, start_pos, mid_pos, half_width); - return; - } - - float start_outside_c = start_c; - if (end_pos.y < (start_k * end_pos.x) + start_c) - start_outside_c += start_dc; - else - start_outside_c -= start_dc; - - float end_outside_c = end_c; - if (start_pos.y < (end_k * start_pos.x) + end_c) - end_outside_c += end_dc; - else - end_outside_c -= end_dc; - - float join_x = (end_outside_c - start_outside_c) / (start_k - end_k); - float join_y = start_k * join_x + start_outside_c; - rect->UpdateRect(join_x, join_y); -} - -} // namespace - -FX_PATHPOINT::FX_PATHPOINT() = default; - -FX_PATHPOINT::FX_PATHPOINT(const CFX_PointF& point, FXPT_TYPE type, bool close) - : m_Point(point), m_Type(type), m_CloseFigure(close) {} - -FX_PATHPOINT::FX_PATHPOINT(const FX_PATHPOINT& other) = default; - -FX_PATHPOINT::~FX_PATHPOINT() = default; - -CFX_PathData::CFX_PathData() {} - -CFX_PathData::~CFX_PathData() {} - -CFX_PathData::CFX_PathData(const CFX_PathData& src) : m_Points(src.m_Points) {} - -void CFX_PathData::Clear() { - m_Points.clear(); -} - -void CFX_PathData::ClosePath() { - if (m_Points.empty()) - return; - m_Points.back().m_CloseFigure = true; -} - -void CFX_PathData::Append(const CFX_PathData* pSrc, const CFX_Matrix* pMatrix) { - if (pSrc->m_Points.empty()) - return; - - size_t cur_size = m_Points.size(); - m_Points.insert(m_Points.end(), pSrc->m_Points.begin(), pSrc->m_Points.end()); - - if (!pMatrix) - return; - - for (size_t i = cur_size; i < m_Points.size(); i++) - m_Points[i].m_Point = pMatrix->Transform(m_Points[i].m_Point); -} - -void CFX_PathData::AppendPoint(const CFX_PointF& point, - FXPT_TYPE type, - bool closeFigure) { - m_Points.push_back(FX_PATHPOINT(point, type, closeFigure)); -} - -void CFX_PathData::AppendRect(float left, - float bottom, - float right, - float top) { - m_Points.push_back( - FX_PATHPOINT(CFX_PointF(left, bottom), FXPT_TYPE::MoveTo, false)); - m_Points.push_back( - FX_PATHPOINT(CFX_PointF(left, top), FXPT_TYPE::LineTo, false)); - m_Points.push_back( - FX_PATHPOINT(CFX_PointF(right, top), FXPT_TYPE::LineTo, false)); - m_Points.push_back( - FX_PATHPOINT(CFX_PointF(right, bottom), FXPT_TYPE::LineTo, false)); - m_Points.push_back( - FX_PATHPOINT(CFX_PointF(left, bottom), FXPT_TYPE::LineTo, true)); -} - -CFX_FloatRect CFX_PathData::GetBoundingBox() const { - if (m_Points.empty()) - return CFX_FloatRect(); - - CFX_FloatRect rect; - rect.InitRect(m_Points[0].m_Point.x, m_Points[0].m_Point.y); - for (size_t i = 1; i < m_Points.size(); i++) - rect.UpdateRect(m_Points[i].m_Point.x, m_Points[i].m_Point.y); - return rect; -} - -CFX_FloatRect CFX_PathData::GetBoundingBox(float line_width, - float miter_limit) const { - CFX_FloatRect rect(100000.0f, 100000.0f, -100000.0f, -100000.0f); - size_t iPoint = 0; - float half_width = line_width; - int iStartPoint = 0; - int iEndPoint = 0; - int iMiddlePoint = 0; - bool bJoin; - while (iPoint < m_Points.size()) { - if (m_Points[iPoint].IsTypeAndOpen(FXPT_TYPE::MoveTo)) { - if (iPoint + 1 == m_Points.size()) - break; - - iStartPoint = iPoint + 1; - iEndPoint = iPoint; - bJoin = false; - } else { - if (m_Points[iPoint].IsTypeAndOpen(FXPT_TYPE::BezierTo)) { - rect.UpdateRect(m_Points[iPoint].m_Point.x, m_Points[iPoint].m_Point.y); - rect.UpdateRect(m_Points[iPoint + 1].m_Point.x, - m_Points[iPoint + 1].m_Point.y); - iPoint += 2; - } - if (iPoint == m_Points.size() - 1 || - m_Points[iPoint + 1].IsTypeAndOpen(FXPT_TYPE::MoveTo)) { - iStartPoint = iPoint - 1; - iEndPoint = iPoint; - bJoin = false; - } else { - iStartPoint = iPoint - 1; - iMiddlePoint = iPoint; - iEndPoint = iPoint + 1; - bJoin = true; - } - } - - CFX_PointF start_pos = m_Points[iStartPoint].m_Point; - CFX_PointF end_pos = m_Points[iEndPoint].m_Point; - if (bJoin) { - CFX_PointF mid_pos = m_Points[iMiddlePoint].m_Point; - UpdateLineJoinPoints(&rect, start_pos, mid_pos, end_pos, half_width, - miter_limit); - } else { - UpdateLineEndPoints(&rect, start_pos, end_pos, half_width); - } - iPoint++; - } - return rect; -} - -void CFX_PathData::Transform(const CFX_Matrix* pMatrix) { - if (!pMatrix) - return; - for (auto& point : m_Points) - point.m_Point = pMatrix->Transform(point.m_Point); -} - -bool CFX_PathData::GetZeroAreaPath(const CFX_Matrix* pMatrix, - bool bAdjust, - CFX_PathData* NewPath, - bool* bThin, - bool* setIdentity) const { - *setIdentity = false; - if (m_Points.size() < 3) - return false; - - if (m_Points.size() == 3 && m_Points[0].m_Type == FXPT_TYPE::MoveTo && - m_Points[1].m_Type == FXPT_TYPE::LineTo && - m_Points[2].m_Type == FXPT_TYPE::LineTo && - m_Points[0].m_Point == m_Points[2].m_Point) { - for (size_t i = 0; i < 2; i++) { - CFX_PointF point = m_Points[i].m_Point; - if (bAdjust) { - if (pMatrix) - point = pMatrix->Transform(point); - - point = CFX_PointF(static_cast(point.x) + 0.5f, - static_cast(point.y) + 0.5f); - } - NewPath->AppendPoint( - point, i == 0 ? FXPT_TYPE::MoveTo : FXPT_TYPE::LineTo, false); - } - if (bAdjust && pMatrix) - *setIdentity = true; - - // Note, they both have to be not equal. - if (m_Points[0].m_Point.x != m_Points[1].m_Point.x && - m_Points[0].m_Point.y != m_Points[1].m_Point.y) { - *bThin = true; - } - return true; - } - - if (((m_Points.size() > 3) && (m_Points.size() % 2))) { - int mid = m_Points.size() / 2; - bool bZeroArea = false; - CFX_PathData t_path; - for (int i = 0; i < mid; i++) { - if (!(m_Points[mid - i - 1].m_Point == m_Points[mid + i + 1].m_Point && - m_Points[mid - i - 1].m_Type != FXPT_TYPE::BezierTo && - m_Points[mid + i + 1].m_Type != FXPT_TYPE::BezierTo)) { - bZeroArea = true; - break; - } - - t_path.AppendPoint(m_Points[mid - i].m_Point, FXPT_TYPE::MoveTo, false); - t_path.AppendPoint(m_Points[mid - i - 1].m_Point, FXPT_TYPE::LineTo, - false); - } - if (!bZeroArea) { - NewPath->Append(&t_path, nullptr); - *bThin = true; - return true; - } - } - - int startPoint = 0; - int next = 0; - for (size_t i = 0; i < m_Points.size(); i++) { - FXPT_TYPE point_type = m_Points[i].m_Type; - if (point_type == FXPT_TYPE::MoveTo) { - startPoint = i; - } else if (point_type == FXPT_TYPE::LineTo) { - next = (i + 1 - startPoint) % (m_Points.size() - startPoint) + startPoint; - if (m_Points[next].m_Type != FXPT_TYPE::BezierTo && - m_Points[next].m_Type != FXPT_TYPE::MoveTo) { - if ((m_Points[i - 1].m_Point.x == m_Points[i].m_Point.x && - m_Points[i].m_Point.x == m_Points[next].m_Point.x) && - ((m_Points[i].m_Point.y - m_Points[i - 1].m_Point.y) * - (m_Points[i].m_Point.y - m_Points[next].m_Point.y) > - 0)) { - int pre = i; - if (fabs(m_Points[i].m_Point.y - m_Points[i - 1].m_Point.y) < - fabs(m_Points[i].m_Point.y - m_Points[next].m_Point.y)) { - pre--; - next--; - } - - NewPath->AppendPoint(m_Points[pre].m_Point, FXPT_TYPE::MoveTo, false); - NewPath->AppendPoint(m_Points[next].m_Point, FXPT_TYPE::LineTo, - false); - } else if ((m_Points[i - 1].m_Point.y == m_Points[i].m_Point.y && - m_Points[i].m_Point.y == m_Points[next].m_Point.y) && - ((m_Points[i].m_Point.x - m_Points[i - 1].m_Point.x) * - (m_Points[i].m_Point.x - m_Points[next].m_Point.x) > - 0)) { - int pre = i; - if (fabs(m_Points[i].m_Point.x - m_Points[i - 1].m_Point.x) < - fabs(m_Points[i].m_Point.x - m_Points[next].m_Point.x)) { - pre--; - next--; - } - - NewPath->AppendPoint(m_Points[pre].m_Point, FXPT_TYPE::MoveTo, false); - NewPath->AppendPoint(m_Points[next].m_Point, FXPT_TYPE::LineTo, - false); - } else if (m_Points[i - 1].m_Type == FXPT_TYPE::MoveTo && - m_Points[next].m_Type == FXPT_TYPE::LineTo && - m_Points[i - 1].m_Point == m_Points[next].m_Point && - m_Points[next].m_CloseFigure) { - NewPath->AppendPoint(m_Points[i - 1].m_Point, FXPT_TYPE::MoveTo, - false); - NewPath->AppendPoint(m_Points[i].m_Point, FXPT_TYPE::LineTo, false); - *bThin = true; - } - } - } else if (point_type == FXPT_TYPE::BezierTo) { - i += 2; - continue; - } - } - - size_t new_path_size = NewPath->GetPoints().size(); - if (m_Points.size() > 3 && new_path_size > 0) - *bThin = true; - return new_path_size != 0; -} - -bool CFX_PathData::IsRect() const { - if (m_Points.size() != 5 && m_Points.size() != 4) - return false; - - if ((m_Points.size() == 5 && m_Points[0].m_Point != m_Points[4].m_Point) || - m_Points[0].m_Point == m_Points[2].m_Point || - m_Points[1].m_Point == m_Points[3].m_Point) { - return false; - } - // Note, both x,y have to not equal. - if (m_Points[0].m_Point.x != m_Points[3].m_Point.x && - m_Points[0].m_Point.y != m_Points[3].m_Point.y) { - return false; - } - - for (int i = 1; i < 4; i++) { - if (m_Points[i].m_Type != FXPT_TYPE::LineTo) - return false; - // Note, both x,y have to not equal. - if (m_Points[i].m_Point.x != m_Points[i - 1].m_Point.x && - m_Points[i].m_Point.y != m_Points[i - 1].m_Point.y) { - return false; - } - } - return m_Points.size() == 5 || m_Points[3].m_CloseFigure; -} - -bool CFX_PathData::IsRect(const CFX_Matrix* pMatrix, - CFX_FloatRect* pRect) const { - if (!pMatrix) { - if (!IsRect()) - return false; - - if (pRect) { - pRect->left = m_Points[0].m_Point.x; - pRect->right = m_Points[2].m_Point.x; - pRect->bottom = m_Points[0].m_Point.y; - pRect->top = m_Points[2].m_Point.y; - pRect->Normalize(); - } - return true; - } - - if (m_Points.size() != 5 && m_Points.size() != 4) - return false; - - if ((m_Points.size() == 5 && m_Points[0].m_Point != m_Points[4].m_Point) || - m_Points[1].m_Point == m_Points[3].m_Point) { - return false; - } - // Note, both x,y not equal. - if (m_Points.size() == 4 && m_Points[0].m_Point.x != m_Points[3].m_Point.x && - m_Points[0].m_Point.y != m_Points[3].m_Point.y) { - return false; - } - - CFX_PointF points[5]; - for (size_t i = 0; i < m_Points.size(); i++) { - points[i] = pMatrix->Transform(m_Points[i].m_Point); - - if (i == 0) - continue; - if (m_Points[i].m_Type != FXPT_TYPE::LineTo) - return false; - if (points[i].x != points[i - 1].x && points[i].y != points[i - 1].y) - return false; - } - - if (pRect) { - pRect->left = points[0].x; - pRect->right = points[2].x; - pRect->bottom = points[0].y; - pRect->top = points[2].y; - pRect->Normalize(); - } - return true; -} diff --git a/core/fxge/ge/cfx_renderdevice.cpp b/core/fxge/ge/cfx_renderdevice.cpp deleted file mode 100644 index 34c974439a..0000000000 --- a/core/fxge/ge/cfx_renderdevice.cpp +++ /dev/null @@ -1,1135 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_renderdevice.h" - -#include -#include -#include -#include - -#include "core/fxcrt/fx_safe_types.h" -#include "core/fxge/cfx_defaultrenderdevice.h" -#include "core/fxge/cfx_facecache.h" -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/dib/cfx_imagerenderer.h" -#include "core/fxge/ifx_renderdevicedriver.h" - -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ -#include "third_party/skia/include/core/SkTypes.h" -#endif - -namespace { - -void AdjustGlyphSpace(std::vector* pGlyphAndPos) { - ASSERT(pGlyphAndPos->size() > 1); - std::vector& glyphs = *pGlyphAndPos; - bool bVertical = glyphs.back().m_Origin.x == glyphs.front().m_Origin.x; - if (!bVertical && (glyphs.back().m_Origin.y != glyphs.front().m_Origin.y)) - return; - - for (size_t i = glyphs.size() - 1; i > 1; --i) { - FXTEXT_GLYPHPOS& next = glyphs[i]; - int next_origin = bVertical ? next.m_Origin.y : next.m_Origin.x; - float next_origin_f = bVertical ? next.m_fOrigin.y : next.m_fOrigin.x; - - FXTEXT_GLYPHPOS& current = glyphs[i - 1]; - int& current_origin = bVertical ? current.m_Origin.y : current.m_Origin.x; - float current_origin_f = - bVertical ? current.m_fOrigin.y : current.m_fOrigin.x; - - int space = next_origin - current_origin; - float space_f = next_origin_f - current_origin_f; - float error = fabs(space_f) - fabs(static_cast(space)); - if (error > 0.5f) - current_origin += space > 0 ? -1 : 1; - } -} - -const uint8_t g_TextGammaAdjust[256] = { - 0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, 15, 16, 17, 18, - 19, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, - 36, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, - 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, - 68, 69, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, - 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, - 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, - 129, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, - 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 156, - 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, - 172, 173, 174, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, 187, 188, 189, 190, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, - 200, 201, 202, 203, 204, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, - 228, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 239, 240, - 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 250, 251, 252, 253, 254, - 255, -}; - -int TextGammaAdjust(int value) { - ASSERT(value >= 0); - ASSERT(value <= 255); - return g_TextGammaAdjust[value]; -} - -int CalcAlpha(int src, int alpha) { - return src * alpha / 255; -} - -void Merge(uint8_t src, int channel, int alpha, uint8_t* dest) { - *dest = FXDIB_ALPHA_MERGE(*dest, channel, CalcAlpha(src, alpha)); -} - -void MergeGammaAdjust(uint8_t src, int channel, int alpha, uint8_t* dest) { - *dest = - FXDIB_ALPHA_MERGE(*dest, channel, CalcAlpha(TextGammaAdjust(src), alpha)); -} - -void MergeGammaAdjustBgr(const uint8_t* src, - int r, - int g, - int b, - int a, - uint8_t* dest) { - MergeGammaAdjust(src[0], b, a, &dest[0]); - MergeGammaAdjust(src[1], g, a, &dest[1]); - MergeGammaAdjust(src[2], r, a, &dest[2]); -} - -void MergeGammaAdjustRgb(const uint8_t* src, - int r, - int g, - int b, - int a, - uint8_t* dest) { - MergeGammaAdjust(src[2], b, a, &dest[0]); - MergeGammaAdjust(src[1], g, a, &dest[1]); - MergeGammaAdjust(src[0], r, a, &dest[2]); -} - -int AverageRgb(const uint8_t* src) { - return (src[0] + src[1] + src[2]) / 3; -} - -uint8_t CalculateDestAlpha(uint8_t back_alpha, int src_alpha) { - return back_alpha + src_alpha - back_alpha * src_alpha / 255; -} - -void ApplyDestAlpha(uint8_t back_alpha, - int src_alpha, - int r, - int g, - int b, - uint8_t* dest) { - uint8_t dest_alpha = CalculateDestAlpha(back_alpha, src_alpha); - int alpha_ratio = src_alpha * 255 / dest_alpha; - dest[0] = FXDIB_ALPHA_MERGE(dest[0], b, alpha_ratio); - dest[1] = FXDIB_ALPHA_MERGE(dest[1], g, alpha_ratio); - dest[2] = FXDIB_ALPHA_MERGE(dest[2], r, alpha_ratio); - dest[3] = dest_alpha; -} - -void NormalizeRgbDst(int src_value, int r, int g, int b, int a, uint8_t* dest) { - int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); - dest[0] = FXDIB_ALPHA_MERGE(dest[0], b, src_alpha); - dest[1] = FXDIB_ALPHA_MERGE(dest[1], g, src_alpha); - dest[2] = FXDIB_ALPHA_MERGE(dest[2], r, src_alpha); -} - -void NormalizeRgbSrc(int src_value, int r, int g, int b, int a, uint8_t* dest) { - int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); - if (src_alpha == 0) - return; - - dest[0] = FXDIB_ALPHA_MERGE(dest[0], b, src_alpha); - dest[1] = FXDIB_ALPHA_MERGE(dest[1], g, src_alpha); - dest[2] = FXDIB_ALPHA_MERGE(dest[2], r, src_alpha); -} - -void NormalizeArgbDest(int src_value, - int r, - int g, - int b, - int a, - uint8_t* dest) { - int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); - uint8_t back_alpha = dest[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest, FXARGB_MAKE(src_alpha, r, g, b)); - } else if (src_alpha != 0) { - ApplyDestAlpha(back_alpha, src_alpha, r, g, b, dest); - } -} - -void NormalizeArgbSrc(int src_value, - int r, - int g, - int b, - int a, - uint8_t* dest) { - int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a); - if (src_alpha == 0) - return; - - uint8_t back_alpha = dest[3]; - if (back_alpha == 0) { - FXARGB_SETDIB(dest, FXARGB_MAKE(src_alpha, r, g, b)); - } else { - ApplyDestAlpha(back_alpha, src_alpha, r, g, b, dest); - } -} - -void NextPixel(uint8_t** src_scan, uint8_t** dst_scan, int bpp) { - *src_scan += 3; - *dst_scan += bpp; -} - -void SetAlpha(uint8_t* alpha) { - alpha[3] = 255; -} - -void SetAlphaDoNothing(uint8_t* alpha) {} - -void DrawNormalTextHelper(const CFX_RetainPtr& bitmap, - const CFX_RetainPtr& pGlyph, - int nrows, - int left, - int top, - int start_col, - int end_col, - bool bNormal, - bool bBGRStripe, - int x_subpixel, - int a, - int r, - int g, - int b) { - const bool has_alpha = bitmap->GetFormat() == FXDIB_Argb; - uint8_t* src_buf = pGlyph->GetBuffer(); - int src_pitch = pGlyph->GetPitch(); - uint8_t* dest_buf = bitmap->GetBuffer(); - int dest_pitch = bitmap->GetPitch(); - const int Bpp = has_alpha ? 4 : bitmap->GetBPP() / 8; - auto* pNormalizeSrcFunc = has_alpha ? &NormalizeArgbSrc : &NormalizeRgbDst; - auto* pNormalizeDstFunc = has_alpha ? &NormalizeArgbDest : &NormalizeRgbSrc; - auto* pSetAlpha = has_alpha ? &SetAlpha : &SetAlphaDoNothing; - - for (int row = 0; row < nrows; row++) { - int dest_row = row + top; - if (dest_row < 0 || dest_row >= bitmap->GetHeight()) - continue; - - uint8_t* src_scan = src_buf + row * src_pitch + (start_col - left) * 3; - uint8_t* dest_scan = dest_buf + dest_row * dest_pitch + start_col * Bpp; - if (bBGRStripe) { - if (x_subpixel == 0) { - for (int col = start_col; col < end_col; col++) { - if (has_alpha) { - Merge(src_scan[2], r, a, &dest_scan[2]); - Merge(src_scan[1], g, a, &dest_scan[1]); - Merge(src_scan[0], b, a, &dest_scan[0]); - } else { - MergeGammaAdjustBgr(&src_scan[0], r, g, b, a, &dest_scan[0]); - } - pSetAlpha(dest_scan); - NextPixel(&src_scan, &dest_scan, Bpp); - } - } else if (x_subpixel == 1) { - MergeGammaAdjust(src_scan[1], r, a, &dest_scan[2]); - MergeGammaAdjust(src_scan[0], g, a, &dest_scan[1]); - if (start_col > left) - MergeGammaAdjust(src_scan[-1], b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - NextPixel(&src_scan, &dest_scan, Bpp); - for (int col = start_col + 1; col < end_col - 1; col++) { - MergeGammaAdjustBgr(&src_scan[-1], r, g, b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - NextPixel(&src_scan, &dest_scan, Bpp); - } - } else { - MergeGammaAdjust(src_scan[0], r, a, &dest_scan[2]); - if (start_col > left) { - MergeGammaAdjust(src_scan[-1], g, a, &dest_scan[1]); - MergeGammaAdjust(src_scan[-2], b, a, &dest_scan[0]); - } - pSetAlpha(dest_scan); - NextPixel(&src_scan, &dest_scan, Bpp); - for (int col = start_col + 1; col < end_col - 1; col++) { - MergeGammaAdjustBgr(&src_scan[-2], r, g, b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - NextPixel(&src_scan, &dest_scan, Bpp); - } - } - } else { - if (x_subpixel == 0) { - for (int col = start_col; col < end_col; col++) { - if (bNormal) { - int src_value = AverageRgb(&src_scan[0]); - pNormalizeDstFunc(src_value, r, g, b, a, dest_scan); - } else { - MergeGammaAdjustRgb(&src_scan[0], r, g, b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - } - NextPixel(&src_scan, &dest_scan, Bpp); - } - } else if (x_subpixel == 1) { - if (bNormal) { - int src_value = start_col > left ? AverageRgb(&src_scan[-1]) - : (src_scan[0] + src_scan[1]) / 3; - pNormalizeSrcFunc(src_value, r, g, b, a, dest_scan); - } else { - if (start_col > left) - MergeGammaAdjust(src_scan[-1], r, a, &dest_scan[2]); - MergeGammaAdjust(src_scan[0], g, a, &dest_scan[1]); - MergeGammaAdjust(src_scan[1], b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - } - NextPixel(&src_scan, &dest_scan, Bpp); - for (int col = start_col + 1; col < end_col; col++) { - if (bNormal) { - int src_value = AverageRgb(&src_scan[-1]); - pNormalizeDstFunc(src_value, r, g, b, a, dest_scan); - } else { - MergeGammaAdjustRgb(&src_scan[-1], r, g, b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - } - NextPixel(&src_scan, &dest_scan, Bpp); - } - } else { - if (bNormal) { - int src_value = - start_col > left ? AverageRgb(&src_scan[-2]) : src_scan[0] / 3; - pNormalizeSrcFunc(src_value, r, g, b, a, dest_scan); - } else { - if (start_col > left) { - MergeGammaAdjust(src_scan[-2], r, a, &dest_scan[2]); - MergeGammaAdjust(src_scan[-1], g, a, &dest_scan[1]); - } - MergeGammaAdjust(src_scan[0], b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - } - NextPixel(&src_scan, &dest_scan, Bpp); - for (int col = start_col + 1; col < end_col; col++) { - if (bNormal) { - int src_value = AverageRgb(&src_scan[-2]); - pNormalizeDstFunc(src_value, r, g, b, a, dest_scan); - } else { - MergeGammaAdjustRgb(&src_scan[-2], r, g, b, a, &dest_scan[0]); - pSetAlpha(dest_scan); - } - NextPixel(&src_scan, &dest_scan, Bpp); - } - } - } - } -} - -bool ShouldDrawDeviceText(const CFX_Font* pFont, uint32_t text_flags) { -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - if (text_flags & FXFONT_CIDFONT) - return false; - - const CFX_ByteString bsPsName = pFont->GetPsName(); - if (bsPsName.Find("+ZJHL") != -1) - return false; - - if (bsPsName == "CNAAJI+cmex10") - return false; -#endif - return true; -} - -} // namespace - -FXTEXT_CHARPOS::FXTEXT_CHARPOS() - : m_GlyphIndex(0), - m_FontCharWidth(0), -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ - m_ExtGID(0), -#endif - m_FallbackFontPosition(0), - m_bGlyphAdjust(false), - m_bFontStyle(false) { -} - -FXTEXT_CHARPOS::FXTEXT_CHARPOS(const FXTEXT_CHARPOS&) = default; - -FXTEXT_CHARPOS::~FXTEXT_CHARPOS(){}; - -CFX_RenderDevice::CFX_RenderDevice() - : m_pBitmap(nullptr), - m_Width(0), - m_Height(0), - m_bpp(0), - m_RenderCaps(0), - m_DeviceClass(0) {} - -CFX_RenderDevice::~CFX_RenderDevice() { - RestoreState(false); -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ - Flush(); -#endif -} - -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ -void CFX_RenderDevice::Flush() { - m_pDeviceDriver.reset(); -} -#endif - -void CFX_RenderDevice::SetDeviceDriver( - std::unique_ptr pDriver) { - m_pDeviceDriver = std::move(pDriver); - InitDeviceInfo(); -} - -void CFX_RenderDevice::InitDeviceInfo() { - m_Width = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_WIDTH); - m_Height = m_pDeviceDriver->GetDeviceCaps(FXDC_PIXEL_HEIGHT); - m_bpp = m_pDeviceDriver->GetDeviceCaps(FXDC_BITS_PIXEL); - m_RenderCaps = m_pDeviceDriver->GetDeviceCaps(FXDC_RENDER_CAPS); - m_DeviceClass = m_pDeviceDriver->GetDeviceCaps(FXDC_DEVICE_CLASS); - if (!m_pDeviceDriver->GetClipBox(&m_ClipBox)) { - m_ClipBox.left = 0; - m_ClipBox.top = 0; - m_ClipBox.right = m_Width; - m_ClipBox.bottom = m_Height; - } -} - -void CFX_RenderDevice::SaveState() { - m_pDeviceDriver->SaveState(); -} - -void CFX_RenderDevice::RestoreState(bool bKeepSaved) { - if (m_pDeviceDriver) { - m_pDeviceDriver->RestoreState(bKeepSaved); - UpdateClipBox(); - } -} - -int CFX_RenderDevice::GetDeviceCaps(int caps_id) const { - return m_pDeviceDriver->GetDeviceCaps(caps_id); -} - -CFX_Matrix CFX_RenderDevice::GetCTM() const { - return m_pDeviceDriver->GetCTM(); -} - -bool CFX_RenderDevice::CreateCompatibleBitmap( - const CFX_RetainPtr& pDIB, - int width, - int height) const { - if (m_RenderCaps & FXRC_CMYK_OUTPUT) { - return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT - ? FXDIB_Cmyka - : FXDIB_Cmyk); - } - if (m_RenderCaps & FXRC_BYTEMASK_OUTPUT) - return pDIB->Create(width, height, FXDIB_8bppMask); -#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_PATHS_ - return pDIB->Create(width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT - ? FXDIB_Argb - : FXDIB_Rgb32); -#else - return pDIB->Create( - width, height, m_RenderCaps & FXRC_ALPHA_OUTPUT ? FXDIB_Argb : FXDIB_Rgb); -#endif -} - -bool CFX_RenderDevice::SetClip_PathFill(const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - int fill_mode) { - if (!m_pDeviceDriver->SetClip_PathFill(pPathData, pObject2Device, - fill_mode)) { - return false; - } - UpdateClipBox(); - return true; -} - -bool CFX_RenderDevice::SetClip_PathStroke( - const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - const CFX_GraphStateData* pGraphState) { - if (!m_pDeviceDriver->SetClip_PathStroke(pPathData, pObject2Device, - pGraphState)) { - return false; - } - UpdateClipBox(); - return true; -} - -bool CFX_RenderDevice::SetClip_Rect(const FX_RECT& rect) { - CFX_PathData path; - path.AppendRect(rect.left, rect.bottom, rect.right, rect.top); - if (!SetClip_PathFill(&path, nullptr, FXFILL_WINDING)) - return false; - - UpdateClipBox(); - return true; -} - -void CFX_RenderDevice::UpdateClipBox() { - if (m_pDeviceDriver->GetClipBox(&m_ClipBox)) - return; - m_ClipBox.left = 0; - m_ClipBox.top = 0; - m_ClipBox.right = m_Width; - m_ClipBox.bottom = m_Height; -} - -bool CFX_RenderDevice::DrawPathWithBlend(const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - const CFX_GraphStateData* pGraphState, - uint32_t fill_color, - uint32_t stroke_color, - int fill_mode, - int blend_type) { - uint8_t stroke_alpha = pGraphState ? FXARGB_A(stroke_color) : 0; - uint8_t fill_alpha = (fill_mode & 3) ? FXARGB_A(fill_color) : 0; - const std::vector& pPoints = pPathData->GetPoints(); - if (stroke_alpha == 0 && pPoints.size() == 2) { - CFX_PointF pos1 = pPoints[0].m_Point; - CFX_PointF pos2 = pPoints[1].m_Point; - if (pObject2Device) { - pos1 = pObject2Device->Transform(pos1); - pos2 = pObject2Device->Transform(pos2); - } - DrawCosmeticLine(pos1.x, pos1.y, pos2.x, pos2.y, fill_color, fill_mode, - blend_type); - return true; - } - - if ((pPoints.size() == 5 || pPoints.size() == 4) && stroke_alpha == 0) { - CFX_FloatRect rect_f; - if (!(fill_mode & FXFILL_RECT_AA) && - pPathData->IsRect(pObject2Device, &rect_f)) { - FX_RECT rect_i = rect_f.GetOuterRect(); - - // Depending on the top/bottom, left/right values of the rect it's - // possible to overflow the Width() and Height() calculations. Check that - // the rect will have valid dimension before continuing. - if (!rect_i.Valid()) - return false; - - int width = (int)ceil(rect_f.right - rect_f.left); - if (width < 1) { - width = 1; - if (rect_i.left == rect_i.right) - rect_i.right++; - } - int height = (int)ceil(rect_f.top - rect_f.bottom); - if (height < 1) { - height = 1; - if (rect_i.bottom == rect_i.top) - rect_i.bottom++; - } - if (rect_i.Width() >= width + 1) { - if (rect_f.left - (float)(rect_i.left) > - (float)(rect_i.right) - rect_f.right) { - rect_i.left++; - } else { - rect_i.right--; - } - } - if (rect_i.Height() >= height + 1) { - if (rect_f.top - (float)(rect_i.top) > - (float)(rect_i.bottom) - rect_f.bottom) { - rect_i.top++; - } else { - rect_i.bottom--; - } - } - if (FillRectWithBlend(&rect_i, fill_color, blend_type)) - return true; - } - } - if ((fill_mode & 3) && stroke_alpha == 0 && !(fill_mode & FX_FILL_STROKE) && - !(fill_mode & FX_FILL_TEXT_MODE)) { - CFX_PathData newPath; - bool bThin = false; - bool setIdentity = false; - if (pPathData->GetZeroAreaPath(pObject2Device, - !!m_pDeviceDriver->GetDriverType(), &newPath, - &bThin, &setIdentity)) { - CFX_GraphStateData graphState; - graphState.m_LineWidth = 0.0f; - - uint32_t strokecolor = fill_color; - if (bThin) - strokecolor = (((fill_alpha >> 2) << 24) | (strokecolor & 0x00ffffff)); - - const CFX_Matrix* pMatrix = nullptr; - if (pObject2Device && !pObject2Device->IsIdentity() && !setIdentity) - pMatrix = pObject2Device; - - int smooth_path = FX_ZEROAREA_FILL; - if (fill_mode & FXFILL_NOPATHSMOOTH) - smooth_path |= FXFILL_NOPATHSMOOTH; - - m_pDeviceDriver->DrawPath(&newPath, pMatrix, &graphState, 0, strokecolor, - smooth_path, blend_type); - } - } - if ((fill_mode & 3) && fill_alpha && stroke_alpha < 0xff && - (fill_mode & FX_FILL_STROKE)) { - if (m_RenderCaps & FXRC_FILLSTROKE_PATH) { - return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState, - fill_color, stroke_color, fill_mode, - blend_type); - } - return DrawFillStrokePath(pPathData, pObject2Device, pGraphState, - fill_color, stroke_color, fill_mode, blend_type); - } - return m_pDeviceDriver->DrawPath(pPathData, pObject2Device, pGraphState, - fill_color, stroke_color, fill_mode, - blend_type); -} - -// This can be removed once PDFium entirely relies on Skia -bool CFX_RenderDevice::DrawFillStrokePath(const CFX_PathData* pPathData, - const CFX_Matrix* pObject2Device, - const CFX_GraphStateData* pGraphState, - uint32_t fill_color, - uint32_t stroke_color, - int fill_mode, - int blend_type) { - if (!(m_RenderCaps & FXRC_GET_BITS)) - return false; - CFX_FloatRect bbox; - if (pGraphState) { - bbox = pPathData->GetBoundingBox(pGraphState->m_LineWidth, - pGraphState->m_MiterLimit); - } else { - bbox = pPathData->GetBoundingBox(); - } - if (pObject2Device) - pObject2Device->TransformRect(bbox); - - CFX_Matrix ctm = GetCTM(); - float fScaleX = fabs(ctm.a); - float fScaleY = fabs(ctm.d); - FX_RECT rect = bbox.GetOuterRect(); - auto bitmap = pdfium::MakeRetain(); - auto Backdrop = pdfium::MakeRetain(); - if (!CreateCompatibleBitmap(bitmap, FXSYS_round(rect.Width() * fScaleX), - FXSYS_round(rect.Height() * fScaleY))) { - return false; - } - if (bitmap->HasAlpha()) { - bitmap->Clear(0); - Backdrop->Copy(bitmap); - } else { - if (!m_pDeviceDriver->GetDIBits(bitmap, rect.left, rect.top)) - return false; - Backdrop->Copy(bitmap); - } - CFX_DefaultRenderDevice bitmap_device; - bitmap_device.Attach(bitmap, false, Backdrop, true); - - CFX_Matrix matrix; - if (pObject2Device) - matrix = *pObject2Device; - matrix.Translate(-rect.left, -rect.top); - matrix.Concat(CFX_Matrix(fScaleX, 0, 0, fScaleY, 0, 0)); - if (!bitmap_device.GetDeviceDriver()->DrawPath( - pPathData, &matrix, pGraphState, fill_color, stroke_color, fill_mode, - blend_type)) { - return false; - } -#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_ - bitmap_device.GetDeviceDriver()->Flush(); -#endif - FX_RECT src_rect(0, 0, FXSYS_round(rect.Width() * fScaleX), - FXSYS_round(rect.Height() * fScaleY)); - return m_pDeviceDriver->SetDIBits(bitmap, 0, &src_rect, rect.left, rect.top, - FXDIB_BLEND_NORMAL); -} - -bool CFX_RenderDevice::SetPixel(int x, int y, uint32_t color) { - if (m_pDeviceDriver->SetPixel(x, y, color)) - return true; - - FX_RECT rect(x, y, x + 1, y + 1); - return FillRectWithBlend(&rect, color, FXDIB_BLEND_NORMAL); -} - -bool CFX_RenderDevice::FillRectWithBlend(const FX_RECT* pRect, - uint32_t fill_color, - int blend_type) { - if (m_pDeviceDriver->FillRectWithBlend(pRect, fill_color, blend_type)) - return true; - - if (!(m_RenderCaps & FXRC_GET_BITS)) - return false; - - auto bitmap = pdfium::MakeRetain(); - if (!CreateCompatibleBitmap(bitmap, pRect->Width(), pRect->Height())) - return false; - - if (!m_pDeviceDriver->GetDIBits(bitmap, pRect->left, pRect->top)) - return false; - - if (!bitmap->CompositeRect(0, 0, pRect->Width(), pRect->Height(), fill_color, - 0)) { - return false; - } - FX_RECT src_rect(0, 0, pRect->Width(), pRect->Height()); - m_pDeviceDriver->SetDIBits(bitmap, 0, &src_rect, pRect->left, pRect->top, - FXDIB_BLEND_NORMAL); - return true; -} - -bool CFX_RenderDevice::DrawCosmeticLine(float x1, - float y1, - float x2, - float y2, - uint32_t color, - int fill_mode, - int blend_type) { - if ((color >= 0xff000000) && - m_pDeviceDriver->DrawCosmeticLine(x1, y1, x2, y2, color, blend_type)) { - return true; - } - CFX_GraphStateData graph_state; - CFX_PathData path; - path.AppendPoint(CFX_PointF(x1, y1), FXPT_TYPE::MoveTo, false); - path.AppendPoint(CFX_PointF(x2, y2), FXPT_TYPE::LineTo, false); - return m_pDeviceDriver->DrawPath(&path, nullptr, &graph_state, 0, color, - fill_mode, blend_type); -} - -bool CFX_RenderDevice::GetDIBits(const CFX_RetainPtr& pBitmap, - int left, - int top) { - if (!(m_RenderCaps & FXRC_GET_BITS)) - return false; - return m_pDeviceDriver->GetDIBits(pBitmap, left, top); -} - -CFX_RetainPtr CFX_RenderDevice::GetBackDrop() { - return m_pDeviceDriver->GetBackDrop(); -} - -bool CFX_RenderDevice::SetDIBitsWithBlend( - const CFX_RetainPtr& pBitmap, - int left, - int top, - int blend_mode) { - ASSERT(!pBitmap->IsAlphaMask()); - CFX_Matrix ctm = GetCTM(); - float fScaleX = fabs(ctm.a); - float fScaleY = fabs(ctm.d); - FX_RECT dest_rect(left, top, - FXSYS_round(left + pBitmap->GetWidth() / fScaleX), - FXSYS_round(top + pBitmap->GetHeight() / fScaleY)); - dest_rect.Intersect(m_ClipBox); - if (dest_rect.IsEmpty()) - return true; - - FX_RECT src_rect(dest_rect.left - left, dest_rect.top - top, - dest_rect.left - left + dest_rect.Width(), - dest_rect.top - top + dest_rect.Height()); - src_rect.left = FXSYS_round(src_rect.left * fScaleX); - src_rect.top = FXSYS_round(src_rect.top * fScaleY); - src_rect.right = FXSYS_round(src_rect.right * fScaleX); - src_rect.bottom = FXSYS_round(src_rect.bottom * fScaleY); - if ((blend_mode != FXDIB_BLEND_NORMAL && !(m_RenderCaps & FXRC_BLEND_MODE)) || - (pBitmap->HasAlpha() && !(m_RenderCaps & FXRC_ALPHA_IMAGE))) { - if (!(m_RenderCaps & FXRC_GET_BITS)) - return false; - - int bg_pixel_width = FXSYS_round(dest_rect.Width() * fScaleX); - int bg_pixel_height = FXSYS_round(dest_rect.Height() * fScaleY); - auto background = pdfium::MakeRetain(); - if (!background->Create( - bg_pixel_width, bg_pixel_height, - (m_RenderCaps & FXRC_CMYK_OUTPUT) ? FXDIB_Cmyk : FXDIB_Rgb32)) { - return false; - } - if (!m_pDeviceDriver->GetDIBits(background, dest_rect.left, - dest_rect.top)) { - return false; - } - if (!background->CompositeBitmap(0, 0, bg_pixel_width, bg_pixel_height, - pBitmap, src_rect.left, src_rect.top, - blend_mode, nullptr, false)) { - return false; - } - FX_RECT rect(0, 0, bg_pixel_width, bg_pixel_height); - return m_pDeviceDriver->SetDIBits(background, 0, &rect, dest_rect.left, - dest_rect.top, FXDIB_BLEND_NORMAL); - } - return m_pDeviceDriver->SetDIBits(pBitmap, 0, &src_rect, dest_rect.left, - dest_rect.top, blend_mode); -} - -bool CFX_RenderDevice::StretchDIBitsWithFlagsAndBlend( - const CFX_RetainPtr& pBitmap, - int left, - int top, - int dest_width, - int dest_height, - uint32_t flags, - int blend_mode) { - FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); - FX_RECT clip_box = m_ClipBox; - clip_box.Intersect(dest_rect); - if (clip_box.IsEmpty()) - return true; - return m_pDeviceDriver->StretchDIBits(pBitmap, 0, left, top, dest_width, - dest_height, &clip_box, flags, - blend_mode); -} - -bool CFX_RenderDevice::SetBitMask(const CFX_RetainPtr& pBitmap, - int left, - int top, - uint32_t argb) { - FX_RECT src_rect(0, 0, pBitmap->GetWidth(), pBitmap->GetHeight()); - return m_pDeviceDriver->SetDIBits(pBitmap, argb, &src_rect, left, top, - FXDIB_BLEND_NORMAL); -} - -bool CFX_RenderDevice::StretchBitMask( - const CFX_RetainPtr& pBitmap, - int left, - int top, - int dest_width, - int dest_height, - uint32_t color) { - return StretchBitMaskWithFlags(pBitmap, left, top, dest_width, dest_height, - color, 0); -} - -bool CFX_RenderDevice::StretchBitMaskWithFlags( - const CFX_RetainPtr& pBitmap, - int left, - int top, - int dest_width, - int dest_height, - uint32_t argb, - uint32_t flags) { - FX_RECT dest_rect(left, top, left + dest_width, top + dest_height); - FX_RECT clip_box = m_ClipBox; - clip_box.Intersect(dest_rect); - return m_pDeviceDriver->StretchDIBits(pBitmap, argb, left, top, dest_width, - dest_height, &clip_box, flags, - FXDIB_BLEND_NORMAL); -} - -bool CFX_RenderDevice::StartDIBitsWithBlend( - const CFX_RetainPtr& pBitmap, - int bitmap_alpha, - uint32_t argb, - const CFX_Matrix* pMatrix, - uint32_t flags, - std::unique_ptr* handle, - int blend_mode) { - return m_pDeviceDriver->StartDIBits(pBitmap, bitmap_alpha, argb, pMatrix, - flags, handle, blend_mode); -} - -bool CFX_RenderDevice::ContinueDIBits(CFX_ImageRenderer* handle, - IFX_Pause* pPause) { - return m_pDeviceDriver->ContinueDIBits(handle, pPause); -} - -#ifdef _SKIA_SUPPORT_ -void CFX_RenderDevice::DebugVerifyBitmapIsPreMultiplied() const { - SkASSERT(0); -} - -bool CFX_RenderDevice::SetBitsWithMask( - const CFX_RetainPtr& pBitmap, - const CFX_RetainPtr& pMask, - int left, - int top, - int bitmap_alpha, - int blend_type) { - return m_pDeviceDriver->SetBitsWithMask(pBitmap, pMask, left, top, - bitmap_alpha, blend_type); -} -#endif - -bool CFX_RenderDevice::DrawNormalText(int nChars, - const FXTEXT_CHARPOS* pCharPos, - CFX_Font* pFont, - float font_size, - const CFX_Matrix* pText2Device, - uint32_t fill_color, - uint32_t text_flags) { - int nativetext_flags = text_flags; - if (m_DeviceClass != FXDC_DISPLAY) { - if (!(text_flags & FXTEXT_PRINTGRAPHICTEXT)) { - if (ShouldDrawDeviceText(pFont, text_flags) && - m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pText2Device, - font_size, fill_color)) { - return true; - } - } - if (FXARGB_A(fill_color) < 255) - return false; - } else if (!(text_flags & FXTEXT_NO_NATIVETEXT)) { - if (ShouldDrawDeviceText(pFont, text_flags) && - m_pDeviceDriver->DrawDeviceText(nChars, pCharPos, pFont, pText2Device, - font_size, fill_color)) { - return true; - } - } - CFX_Matrix char2device; - CFX_Matrix text2Device; - if (pText2Device) { - char2device = *pText2Device; - text2Device = *pText2Device; - } - - char2device.Scale(font_size, -font_size); - if (fabs(char2device.a) + fabs(char2device.b) > 50 * 1.0f || - ((m_DeviceClass == FXDC_PRINTER) && - !(text_flags & FXTEXT_PRINTIMAGETEXT))) { - if (pFont->GetFace()) { - int nPathFlags = - (text_flags & FXTEXT_NOSMOOTH) == 0 ? 0 : FXFILL_NOPATHSMOOTH; - return DrawTextPath(nChars, pCharPos, pFont, font_size, pText2Device, - nullptr, nullptr, fill_color, 0, nullptr, nPathFlags); - } - } - int anti_alias = FXFT_RENDER_MODE_MONO; - bool bNormal = false; - if ((text_flags & FXTEXT_NOSMOOTH) == 0) { - if (m_DeviceClass == FXDC_DISPLAY && m_bpp > 1) { - if (!CFX_GEModule::Get()->GetFontMgr()->FTLibrarySupportsHinting()) { - // Some Freetype implementations (like the one packaged with Fedora) do - // not support hinting due to patents 6219025, 6239783, 6307566, - // 6225973, 6243070, 6393145, 6421054, 6282327, and 6624828; the latest - // one expires 10/7/19. This makes LCD antialiasing very ugly, so we - // instead fall back on NORMAL antialiasing. - anti_alias = FXFT_RENDER_MODE_NORMAL; - } else if ((m_RenderCaps & (FXRC_ALPHA_OUTPUT | FXRC_CMYK_OUTPUT))) { - anti_alias = FXFT_RENDER_MODE_LCD; - bNormal = true; - } else if (m_bpp < 16) { - anti_alias = FXFT_RENDER_MODE_NORMAL; - } else { - anti_alias = FXFT_RENDER_MODE_LCD; - - bool bClearType = false; - if (pFont->GetFace()) - bClearType = !!(text_flags & FXTEXT_CLEARTYPE); - bNormal = !bClearType; - } - } - } - std::vector glyphs(nChars); - CFX_Matrix matrixCTM = GetCTM(); - float scale_x = fabs(matrixCTM.a); - float scale_y = fabs(matrixCTM.d); - CFX_Matrix deviceCtm = char2device; - CFX_Matrix m(scale_x, 0, 0, scale_y, 0, 0); - deviceCtm.Concat(m); - text2Device.Concat(m); - - for (size_t i = 0; i < glyphs.size(); ++i) { - FXTEXT_GLYPHPOS& glyph = glyphs[i]; - const FXTEXT_CHARPOS& charpos = pCharPos[i]; - - glyph.m_fOrigin = text2Device.Transform(charpos.m_Origin); - if (anti_alias < FXFT_RENDER_MODE_LCD) - glyph.m_Origin.x = FXSYS_round(glyph.m_fOrigin.x); - else - glyph.m_Origin.x = static_cast(floor(glyph.m_fOrigin.x)); - glyph.m_Origin.y = FXSYS_round(glyph.m_fOrigin.y); - - if (charpos.m_bGlyphAdjust) { - CFX_Matrix new_matrix( - charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], - charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); - new_matrix.Concat(deviceCtm); - glyph.m_pGlyph = pFont->LoadGlyphBitmap( - charpos.m_GlyphIndex, charpos.m_bFontStyle, &new_matrix, - charpos.m_FontCharWidth, anti_alias, nativetext_flags); - } else { - glyph.m_pGlyph = pFont->LoadGlyphBitmap( - charpos.m_GlyphIndex, charpos.m_bFontStyle, &deviceCtm, - charpos.m_FontCharWidth, anti_alias, nativetext_flags); - } - } - if (anti_alias < FXFT_RENDER_MODE_LCD && glyphs.size() > 1) - AdjustGlyphSpace(&glyphs); - - FX_RECT bmp_rect1 = FXGE_GetGlyphsBBox(glyphs, anti_alias, 1.0f, 1.0f); - if (scale_x > 1 && scale_y > 1) { - bmp_rect1.left--; - bmp_rect1.top--; - bmp_rect1.right++; - bmp_rect1.bottom++; - } - FX_RECT bmp_rect(FXSYS_round((float)(bmp_rect1.left) / scale_x), - FXSYS_round((float)(bmp_rect1.top) / scale_y), - FXSYS_round((float)bmp_rect1.right / scale_x), - FXSYS_round((float)bmp_rect1.bottom / scale_y)); - bmp_rect.Intersect(m_ClipBox); - if (bmp_rect.IsEmpty()) - return true; - - int pixel_width = FXSYS_round(bmp_rect.Width() * scale_x); - int pixel_height = FXSYS_round(bmp_rect.Height() * scale_y); - int pixel_left = FXSYS_round(bmp_rect.left * scale_x); - int pixel_top = FXSYS_round(bmp_rect.top * scale_y); - if (anti_alias == FXFT_RENDER_MODE_MONO) { - auto bitmap = pdfium::MakeRetain(); - if (!bitmap->Create(pixel_width, pixel_height, FXDIB_1bppMask)) - return false; - bitmap->Clear(0); - for (const FXTEXT_GLYPHPOS& glyph : glyphs) { - if (!glyph.m_pGlyph) - continue; - CFX_RetainPtr pGlyph = glyph.m_pGlyph->m_pBitmap; - bitmap->TransferBitmap( - glyph.m_Origin.x + glyph.m_pGlyph->m_Left - pixel_left, - glyph.m_Origin.y - glyph.m_pGlyph->m_Top - pixel_top, - pGlyph->GetWidth(), pGlyph->GetHeight(), pGlyph, 0, 0); - } - return SetBitMask(bitmap, bmp_rect.left, bmp_rect.top, fill_color); - } - auto bitmap = pdfium::MakeRetain(); - if (m_bpp == 8) { - if (!bitmap->Create(pixel_width, pixel_height, FXDIB_8bppMask)) - return false; - } else { - if (!CreateCompatibleBitmap(bitmap, pixel_width, pixel_height)) - return false; - } - if (!bitmap->HasAlpha() && !bitmap->IsAlphaMask()) { - bitmap->Clear(0xFFFFFFFF); - if (!GetDIBits(bitmap, bmp_rect.left, bmp_rect.top)) - return false; - } else { - bitmap->Clear(0); - if (bitmap->m_pAlphaMask) - bitmap->m_pAlphaMask->Clear(0); - } - int dest_width = pixel_width; - int a = 0; - int r = 0; - int g = 0; - int b = 0; - if (anti_alias == FXFT_RENDER_MODE_LCD) - std::tie(a, r, g, b) = ArgbDecode(fill_color); - - for (const FXTEXT_GLYPHPOS& glyph : glyphs) { - if (!glyph.m_pGlyph) - continue; - - pdfium::base::CheckedNumeric left = glyph.m_Origin.x; - left += glyph.m_pGlyph->m_Left; - left -= pixel_left; - if (!left.IsValid()) - return false; - - pdfium::base::CheckedNumeric top = glyph.m_Origin.y; - top -= glyph.m_pGlyph->m_Top; - top -= pixel_top; - if (!top.IsValid()) - return false; - - CFX_RetainPtr pGlyph = glyph.m_pGlyph->m_pBitmap; - int ncols = pGlyph->GetWidth(); - int nrows = pGlyph->GetHeight(); - if (anti_alias == FXFT_RENDER_MODE_NORMAL) { - if (!bitmap->CompositeMask(left.ValueOrDie(), top.ValueOrDie(), ncols, - nrows, pGlyph, fill_color, 0, 0, - FXDIB_BLEND_NORMAL, nullptr, false, 0)) { - return false; - } - continue; - } - bool bBGRStripe = !!(text_flags & FXTEXT_BGR_STRIPE); - ncols /= 3; - int x_subpixel = static_cast(glyph.m_fOrigin.x * 3) % 3; - int start_col = - pdfium::base::ValueOrDieForType(pdfium::base::CheckMax(left, 0)); - pdfium::base::CheckedNumeric end_col_safe = left; - end_col_safe += ncols; - if (!end_col_safe.IsValid()) - return false; - - int end_col = - std::min(static_cast(end_col_safe.ValueOrDie()), dest_width); - if (start_col >= end_col) - continue; - - DrawNormalTextHelper(bitmap, pGlyph, nrows, left.ValueOrDie(), - top.ValueOrDie(), start_col, end_col, bNormal, - bBGRStripe, x_subpixel, a, r, g, b); - } - if (bitmap->IsAlphaMask()) - SetBitMask(bitmap, bmp_rect.left, bmp_rect.top, fill_color); - else - SetDIBits(bitmap, bmp_rect.left, bmp_rect.top); - return true; -} - -bool CFX_RenderDevice::DrawTextPath(int nChars, - const FXTEXT_CHARPOS* pCharPos, - CFX_Font* pFont, - float font_size, - const CFX_Matrix* pText2User, - const CFX_Matrix* pUser2Device, - const CFX_GraphStateData* pGraphState, - uint32_t fill_color, - FX_ARGB stroke_color, - CFX_PathData* pClippingPath, - int nFlag) { - for (int iChar = 0; iChar < nChars; iChar++) { - const FXTEXT_CHARPOS& charpos = pCharPos[iChar]; - CFX_Matrix matrix; - if (charpos.m_bGlyphAdjust) { - matrix = CFX_Matrix(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], - charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], - 0, 0); - } - matrix.Concat(CFX_Matrix(font_size, 0, 0, font_size, charpos.m_Origin.x, - charpos.m_Origin.y)); - const CFX_PathData* pPath = - pFont->LoadGlyphPath(charpos.m_GlyphIndex, charpos.m_FontCharWidth); - if (!pPath) - continue; - - matrix.Concat(*pText2User); - - CFX_PathData TransformedPath(*pPath); - TransformedPath.Transform(&matrix); - if (fill_color || stroke_color) { - int fill_mode = nFlag; - if (fill_color) - fill_mode |= FXFILL_WINDING; - fill_mode |= FX_FILL_TEXT_MODE; - if (!DrawPathWithBlend(&TransformedPath, pUser2Device, pGraphState, - fill_color, stroke_color, fill_mode, - FXDIB_BLEND_NORMAL)) { - return false; - } - } - if (pClippingPath) - pClippingPath->Append(&TransformedPath, pUser2Device); - } - return true; -} - -CFX_RenderDevice::StateRestorer::StateRestorer(CFX_RenderDevice* pDevice) - : m_pDevice(pDevice) { - m_pDevice->SaveState(); -} - -CFX_RenderDevice::StateRestorer::~StateRestorer() { - m_pDevice->RestoreState(false); -} diff --git a/core/fxge/ge/cfx_substfont.cpp b/core/fxge/ge/cfx_substfont.cpp deleted file mode 100644 index 27d3bc3059..0000000000 --- a/core/fxge/ge/cfx_substfont.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_substfont.h" - -#include "core/fxcrt/fx_codepage.h" -#include "core/fxge/fx_font.h" - -CFX_SubstFont::CFX_SubstFont() - : m_Charset(FX_CHARSET_ANSI), - m_SubstFlags(0), - m_Weight(0), - m_ItalicAngle(0), - m_bSubstCJK(false), - m_WeightCJK(0), - m_bItalicCJK(false) {} diff --git a/core/fxge/ge/cfx_unicodeencoding.cpp b/core/fxge/ge/cfx_unicodeencoding.cpp deleted file mode 100644 index 494ae33bb0..0000000000 --- a/core/fxge/ge/cfx_unicodeencoding.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_unicodeencoding.h" - -#include "core/fxcrt/fx_codepage.h" -#include "core/fxge/fx_font.h" -#include "core/fxge/fx_freetype.h" - -CFX_UnicodeEncoding::CFX_UnicodeEncoding(CFX_Font* pFont) : m_pFont(pFont) {} - -CFX_UnicodeEncoding::~CFX_UnicodeEncoding() {} - -uint32_t CFX_UnicodeEncoding::GlyphFromCharCode(uint32_t charcode) { - FXFT_Face face = m_pFont->GetFace(); - if (!face) - return charcode; - - if (FXFT_Select_Charmap(face, FXFT_ENCODING_UNICODE) == 0) - return FXFT_Get_Char_Index(face, charcode); - - if (m_pFont->GetSubstFont() && - m_pFont->GetSubstFont()->m_Charset == FX_CHARSET_Symbol) { - uint32_t index = 0; - if (FXFT_Select_Charmap(face, FXFT_ENCODING_MS_SYMBOL) == 0) - index = FXFT_Get_Char_Index(face, charcode); - if (!index && !FXFT_Select_Charmap(face, FXFT_ENCODING_APPLE_ROMAN)) - return FXFT_Get_Char_Index(face, charcode); - } - return charcode; -} diff --git a/core/fxge/ge/cfx_unicodeencodingex.cpp b/core/fxge/ge/cfx_unicodeencodingex.cpp deleted file mode 100644 index 3f28d4295e..0000000000 --- a/core/fxge/ge/cfx_unicodeencodingex.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/cfx_unicodeencodingex.h" - -#include - -#include "core/fpdfapi/font/cpdf_font.h" -#include "core/fxge/fx_font.h" -#include "core/fxge/fx_freetype.h" -#include "third_party/base/ptr_util.h" - -namespace { - -const uint32_t g_EncodingID[] = { - FXFM_ENCODING_MS_SYMBOL, FXFM_ENCODING_UNICODE, - FXFM_ENCODING_MS_SJIS, FXFM_ENCODING_MS_GB2312, - FXFM_ENCODING_MS_BIG5, FXFM_ENCODING_MS_WANSUNG, - FXFM_ENCODING_MS_JOHAB, FXFM_ENCODING_ADOBE_STANDARD, - FXFM_ENCODING_ADOBE_EXPERT, FXFM_ENCODING_ADOBE_CUSTOM, - FXFM_ENCODING_ADOBE_LATIN_1, FXFM_ENCODING_OLD_LATIN_2, - FXFM_ENCODING_APPLE_ROMAN, -}; - -std::unique_ptr FXFM_CreateFontEncoding( - CFX_Font* pFont, - uint32_t nEncodingID) { - if (FXFT_Select_Charmap(pFont->GetFace(), nEncodingID)) - return nullptr; - return pdfium::MakeUnique(pFont, nEncodingID); -} - -} // namespace - -CFX_UnicodeEncodingEx::CFX_UnicodeEncodingEx(CFX_Font* pFont, - uint32_t EncodingID) - : CFX_UnicodeEncoding(pFont), m_nEncodingID(EncodingID) {} - -CFX_UnicodeEncodingEx::~CFX_UnicodeEncodingEx() {} - -uint32_t CFX_UnicodeEncodingEx::GlyphFromCharCode(uint32_t charcode) { - FXFT_Face face = m_pFont->GetFace(); - FT_UInt nIndex = FXFT_Get_Char_Index(face, charcode); - if (nIndex > 0) - return nIndex; - int nmaps = FXFT_Get_Face_CharmapCount(face); - int m = 0; - while (m < nmaps) { - uint32_t nEncodingID = - FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[m++]); - if (m_nEncodingID == nEncodingID) - continue; - int error = FXFT_Select_Charmap(face, nEncodingID); - if (error) - continue; - nIndex = FXFT_Get_Char_Index(face, charcode); - if (nIndex > 0) { - m_nEncodingID = nEncodingID; - return nIndex; - } - } - FXFT_Select_Charmap(face, m_nEncodingID); - return 0; -} - -uint32_t CFX_UnicodeEncodingEx::CharCodeFromUnicode(wchar_t Unicode) const { - if (m_nEncodingID == FXFM_ENCODING_UNICODE || - m_nEncodingID == FXFM_ENCODING_MS_SYMBOL) { - return Unicode; - } - FXFT_Face face = m_pFont->GetFace(); - int nmaps = FXFT_Get_Face_CharmapCount(face); - for (int i = 0; i < nmaps; i++) { - int nEncodingID = - FXFT_Get_Charmap_Encoding(FXFT_Get_Face_Charmaps(face)[i]); - if (nEncodingID == FXFM_ENCODING_UNICODE || - nEncodingID == FXFM_ENCODING_MS_SYMBOL) { - return Unicode; - } - } - return CPDF_Font::kInvalidCharCode; -} - -std::unique_ptr FX_CreateFontEncodingEx( - CFX_Font* pFont, - uint32_t nEncodingID) { - if (!pFont || !pFont->GetFace()) - return nullptr; - - if (nEncodingID != FXFM_ENCODING_NONE) - return FXFM_CreateFontEncoding(pFont, nEncodingID); - - for (size_t i = 0; i < FX_ArraySize(g_EncodingID); ++i) { - std::unique_ptr pFontEncoding = - FXFM_CreateFontEncoding(pFont, g_EncodingID[i]); - if (pFontEncoding) - return pFontEncoding; - } - return nullptr; -} diff --git a/core/fxge/ge/cttfontdesc.cpp b/core/fxge/ge/cttfontdesc.cpp deleted file mode 100644 index f75039567f..0000000000 --- a/core/fxge/ge/cttfontdesc.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include "core/fxge/ge/cttfontdesc.h" - -#include "core/fxge/fx_freetype.h" - -CTTFontDesc::~CTTFontDesc() { - if (m_Type == 1) { - if (m_SingleFace) - FXFT_Done_Face(m_SingleFace); - } else if (m_Type == 2) { - for (int i = 0; i < 16; i++) { - if (m_TTCFaces[i]) - FXFT_Done_Face(m_TTCFaces[i]); - } - } - FX_Free(m_pFontData); -} - -int CTTFontDesc::ReleaseFace(FXFT_Face face) { - if (m_Type == 1) { - if (m_SingleFace != face) - return -1; - } else if (m_Type == 2) { - int i; - for (i = 0; i < 16; i++) { - if (m_TTCFaces[i] == face) - break; - } - if (i == 16) - return -1; - } - return --m_RefCount; -} diff --git a/core/fxge/ge/cttfontdesc.h b/core/fxge/ge/cttfontdesc.h deleted file mode 100644 index d756cb947a..0000000000 --- a/core/fxge/ge/cttfontdesc.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXGE_GE_CTTFONTDESC_H_ -#define CORE_FXGE_GE_CTTFONTDESC_H_ - -#include "core/fxcrt/fx_system.h" -#include "core/fxge/fx_font.h" - -#define FX_FONT_FLAG_SERIF 0x01 -#define FX_FONT_FLAG_FIXEDPITCH 0x02 -#define FX_FONT_FLAG_ITALIC 0x04 -#define FX_FONT_FLAG_BOLD 0x08 -#define FX_FONT_FLAG_SYMBOLIC_SYMBOL 0x10 -#define FX_FONT_FLAG_SYMBOLIC_DINGBATS 0x20 -#define FX_FONT_FLAG_MULTIPLEMASTER 0x40 - -class CTTFontDesc { - public: - CTTFontDesc() : m_Type(0), m_pFontData(nullptr), m_RefCount(0) {} - ~CTTFontDesc(); - // ret < 0, releaseface not appropriate for this object. - // ret == 0, object released - // ret > 0, object still alive, other referrers. - int ReleaseFace(FXFT_Face face); - - int m_Type; - - union { - FXFT_Face m_SingleFace; - FXFT_Face m_TTCFaces[16]; - }; - uint8_t* m_pFontData; - int m_RefCount; -}; - -#endif // CORE_FXGE_GE_CTTFONTDESC_H_ diff --git a/core/fxge/ge/fx_ge_fontmap.cpp b/core/fxge/ge/fx_ge_fontmap.cpp deleted file mode 100644 index 7ac4fada5c..0000000000 --- a/core/fxge/ge/fx_ge_fontmap.cpp +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include - -#include "core/fxge/cfx_fontmapper.h" -#include "core/fxge/ifx_systemfontinfo.h" - -static CFX_ByteString GetStringFromTable(const uint8_t* string_ptr, - uint32_t string_ptr_length, - uint16_t offset, - uint16_t length) { - if (string_ptr_length < static_cast(offset + length)) { - return CFX_ByteString(); - } - return CFX_ByteString(string_ptr + offset, length); -} - -CFX_ByteString GetNameFromTT(const uint8_t* name_table, - uint32_t name_table_size, - uint32_t name_id) { - if (!name_table || name_table_size < 6) { - return CFX_ByteString(); - } - uint32_t name_count = GET_TT_SHORT(name_table + 2); - uint32_t string_offset = GET_TT_SHORT(name_table + 4); - // We will ignore the possibility of overlap of structures and - // string table as if it's all corrupt there's not a lot we can do. - if (name_table_size < string_offset) { - return CFX_ByteString(); - } - - const uint8_t* string_ptr = name_table + string_offset; - uint32_t string_ptr_size = name_table_size - string_offset; - name_table += 6; - name_table_size -= 6; - if (name_table_size < name_count * 12) { - return CFX_ByteString(); - } - - for (uint32_t i = 0; i < name_count; i++, name_table += 12) { - if (GET_TT_SHORT(name_table + 6) == name_id && - GET_TT_SHORT(name_table) == 1 && GET_TT_SHORT(name_table + 2) == 0) { - return GetStringFromTable(string_ptr, string_ptr_size, - GET_TT_SHORT(name_table + 10), - GET_TT_SHORT(name_table + 8)); - } - } - return CFX_ByteString(); -} -#ifdef PDF_ENABLE_XFA -void* IFX_SystemFontInfo::MapFontByUnicode(uint32_t dwUnicode, - int weight, - bool bItalic, - int pitch_family) { - return nullptr; -} -#endif // PDF_ENABLE_XFA - -int IFX_SystemFontInfo::GetFaceIndex(void* hFont) { - return 0; -} - -extern "C" { -unsigned long _FTStreamRead(FXFT_Stream stream, - unsigned long offset, - unsigned char* buffer, - unsigned long count); -void _FTStreamClose(FXFT_Stream stream); -}; - -#if _FX_OS_ == _FX_ANDROID_ -std::unique_ptr IFX_SystemFontInfo::CreateDefault( - const char** pUnused) { - return nullptr; -} -#endif - -CFX_FontFaceInfo::CFX_FontFaceInfo(CFX_ByteString filePath, - CFX_ByteString faceName, - CFX_ByteString fontTables, - uint32_t fontOffset, - uint32_t fileSize) - : m_FilePath(filePath), - m_FaceName(faceName), - m_FontTables(fontTables), - m_FontOffset(fontOffset), - m_FileSize(fileSize), - m_Styles(0), - m_Charsets(0) {} diff --git a/core/fxge/ge/fx_ge_linux.cpp b/core/fxge/ge/fx_ge_linux.cpp deleted file mode 100644 index 4e4b2050e9..0000000000 --- a/core/fxge/ge/fx_ge_linux.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include -#include - -#include "core/fxcrt/fx_codepage.h" -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/ge/cfx_folderfontinfo.h" -#include "core/fxge/ifx_systemfontinfo.h" -#include "third_party/base/ptr_util.h" - -#if _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ -namespace { - -const size_t kLinuxGpNameSize = 6; - -const char* const g_LinuxGpFontList[][kLinuxGpNameSize] = { - {"TakaoPGothic", "VL PGothic", "IPAPGothic", "VL Gothic", "Kochi Gothic", - "VL Gothic regular"}, - {"TakaoGothic", "VL Gothic", "IPAGothic", "Kochi Gothic", nullptr, - "VL Gothic regular"}, - {"TakaoPMincho", "IPAPMincho", "VL Gothic", "Kochi Mincho", nullptr, - "VL Gothic regular"}, - {"TakaoMincho", "IPAMincho", "VL Gothic", "Kochi Mincho", nullptr, - "VL Gothic regular"}, -}; - -const char* const g_LinuxGbFontList[] = { - "AR PL UMing CN Light", "WenQuanYi Micro Hei", "AR PL UKai CN", -}; - -const char* const g_LinuxB5FontList[] = { - "AR PL UMing TW Light", "WenQuanYi Micro Hei", "AR PL UKai TW", -}; - -const char* const g_LinuxHGFontList[] = { - "UnDotum", -}; - -size_t GetJapanesePreference(const char* facearr, - int weight, - int pitch_family) { - CFX_ByteString face = facearr; - if (face.Find("Gothic") >= 0 || - face.Find("\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { - if (face.Find("PGothic") >= 0 || - face.Find("\x82\x6f\x83\x53\x83\x56\x83\x62\x83\x4e") >= 0) { - return 0; - } - return 1; - } - if (face.Find("Mincho") >= 0 || face.Find("\x96\xbe\x92\xa9") >= 0) { - if (face.Find("PMincho") >= 0 || - face.Find("\x82\x6f\x96\xbe\x92\xa9") >= 0) { - return 2; - } - return 3; - } - if (!(pitch_family & FXFONT_FF_ROMAN) && weight > 400) - return 0; - - return 2; -} - -class CFX_LinuxFontInfo : public CFX_FolderFontInfo { - public: - CFX_LinuxFontInfo() {} - ~CFX_LinuxFontInfo() override {} - - void* MapFont(int weight, - bool bItalic, - int charset, - int pitch_family, - const char* family, - int& iExact) override; - bool ParseFontCfg(const char** pUserPaths); -}; - -void* CFX_LinuxFontInfo::MapFont(int weight, - bool bItalic, - int charset, - int pitch_family, - const char* cstr_face, - int& iExact) { - void* font = GetSubstFont(cstr_face); - if (font) { - iExact = 1; - return font; - } - bool bCJK = true; - switch (charset) { - case FX_CHARSET_ShiftJIS: { - size_t index = GetJapanesePreference(cstr_face, weight, pitch_family); - ASSERT(index < FX_ArraySize(g_LinuxGpFontList)); - for (size_t i = 0; i < kLinuxGpNameSize; i++) { - auto it = m_FontList.find(g_LinuxGpFontList[index][i]); - if (it != m_FontList.end()) - return it->second.get(); - } - break; - } - case FX_CHARSET_ChineseSimplified: { - for (size_t i = 0; i < FX_ArraySize(g_LinuxGbFontList); ++i) { - auto it = m_FontList.find(g_LinuxGbFontList[i]); - if (it != m_FontList.end()) - return it->second.get(); - } - break; - } - case FX_CHARSET_ChineseTraditional: { - for (size_t i = 0; i < FX_ArraySize(g_LinuxB5FontList); ++i) { - auto it = m_FontList.find(g_LinuxB5FontList[i]); - if (it != m_FontList.end()) - return it->second.get(); - } - break; - } - case FX_CHARSET_Hangul: { - for (size_t i = 0; i < FX_ArraySize(g_LinuxHGFontList); ++i) { - auto it = m_FontList.find(g_LinuxHGFontList[i]); - if (it != m_FontList.end()) - return it->second.get(); - } - break; - } - default: - bCJK = false; - break; - } - return FindFont(weight, bItalic, charset, pitch_family, cstr_face, !bCJK); -} - -bool CFX_LinuxFontInfo::ParseFontCfg(const char** pUserPaths) { - if (!pUserPaths) - return false; - - for (const char** pPath = pUserPaths; *pPath; ++pPath) - AddPath(*pPath); - return true; -} - -} // namespace - -std::unique_ptr IFX_SystemFontInfo::CreateDefault( - const char** pUserPaths) { - auto pInfo = pdfium::MakeUnique(); - if (!pInfo->ParseFontCfg(pUserPaths)) { - pInfo->AddPath("/usr/share/fonts"); - pInfo->AddPath("/usr/share/X11/fonts/Type1"); - pInfo->AddPath("/usr/share/X11/fonts/TTF"); - pInfo->AddPath("/usr/local/share/fonts"); - } - return std::move(pInfo); -} - -void CFX_GEModule::InitPlatform() { - m_pFontMgr->SetSystemFontInfo( - IFX_SystemFontInfo::CreateDefault(m_pUserFontPaths)); -} - -void CFX_GEModule::DestroyPlatform() {} -#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_LINUX_ diff --git a/core/fxge/ge/fx_ge_text.cpp b/core/fxge/ge/fx_ge_text.cpp deleted file mode 100644 index 8024452265..0000000000 --- a/core/fxge/ge/fx_ge_text.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#include -#include -#include - -#include "core/fxcodec/fx_codec.h" -#include "core/fxcrt/fx_safe_types.h" -#include "core/fxge/cfx_pathdata.h" -#include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/fx_text_int.h" -#include "core/fxge/ifx_renderdevicedriver.h" - -namespace { - -void ResetTransform(FT_Face face) { - FXFT_Matrix matrix; - matrix.xx = 0x10000L; - matrix.xy = 0; - matrix.yx = 0; - matrix.yy = 0x10000L; - FXFT_Set_Transform(face, &matrix, 0); -} - -} // namespace - -FXTEXT_GLYPHPOS::FXTEXT_GLYPHPOS() : m_pGlyph(nullptr) {} - -FXTEXT_GLYPHPOS::FXTEXT_GLYPHPOS(const FXTEXT_GLYPHPOS&) = default; - -FXTEXT_GLYPHPOS::~FXTEXT_GLYPHPOS(){}; - -ScopedFontTransform::ScopedFontTransform(FT_Face face, FXFT_Matrix* matrix) - : m_Face(face) { - FXFT_Set_Transform(m_Face, matrix, 0); -} - -ScopedFontTransform::~ScopedFontTransform() { - ResetTransform(m_Face); -} - -FX_RECT FXGE_GetGlyphsBBox(const std::vector& glyphs, - int anti_alias, - float retinaScaleX, - float retinaScaleY) { - FX_RECT rect(0, 0, 0, 0); - bool bStarted = false; - for (const FXTEXT_GLYPHPOS& glyph : glyphs) { - const CFX_GlyphBitmap* pGlyph = glyph.m_pGlyph; - if (!pGlyph) - continue; - - FX_SAFE_INT32 char_left = glyph.m_Origin.x; - char_left += pGlyph->m_Left; - if (!char_left.IsValid()) - continue; - - FX_SAFE_INT32 char_width = pGlyph->m_pBitmap->GetWidth(); - char_width /= retinaScaleX; - if (anti_alias == FXFT_RENDER_MODE_LCD) - char_width /= 3; - if (!char_width.IsValid()) - continue; - - FX_SAFE_INT32 char_right = char_left + char_width; - if (!char_right.IsValid()) - continue; - - FX_SAFE_INT32 char_top = glyph.m_Origin.y; - char_top -= pGlyph->m_Top; - if (!char_top.IsValid()) - continue; - - FX_SAFE_INT32 char_height = pGlyph->m_pBitmap->GetHeight(); - char_height /= retinaScaleY; - if (!char_height.IsValid()) - continue; - - FX_SAFE_INT32 char_bottom = char_top + char_height; - if (!char_bottom.IsValid()) - continue; - - if (bStarted) { - rect.left = pdfium::base::ValueOrDieForType( - pdfium::base::CheckMin(rect.left, char_left)); - rect.right = pdfium::base::ValueOrDieForType( - pdfium::base::CheckMax(rect.right, char_right)); - rect.top = pdfium::base::ValueOrDieForType( - pdfium::base::CheckMin(rect.top, char_top)); - rect.bottom = pdfium::base::ValueOrDieForType( - pdfium::base::CheckMax(rect.bottom, char_bottom)); - continue; - } - - rect.left = char_left.ValueOrDie(); - rect.right = char_right.ValueOrDie(); - rect.top = char_top.ValueOrDie(); - rect.bottom = char_bottom.ValueOrDie(); - bStarted = true; - } - return rect; -} - -CFX_SizeGlyphCache::CFX_SizeGlyphCache() {} - -CFX_SizeGlyphCache::~CFX_SizeGlyphCache() {} - -void CFX_UniqueKeyGen::Generate(int count, ...) { - va_list argList; - va_start(argList, count); - for (int i = 0; i < count; i++) { - int p = va_arg(argList, int); - ((uint32_t*)m_Key)[i] = p; - } - va_end(argList); - m_KeyLen = count * sizeof(uint32_t); -} diff --git a/core/fxge/ge/fx_ge_text_embeddertest.cpp b/core/fxge/ge/fx_ge_text_embeddertest.cpp deleted file mode 100644 index 045b6dc869..0000000000 --- a/core/fxge/ge/fx_ge_text_embeddertest.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2016 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "testing/embedder_test.h" -#include "testing/gtest/include/gtest/gtest.h" - -class FXGETextEmbedderTest : public EmbedderTest {}; - -TEST_F(FXGETextEmbedderTest, BadItalic) { - // Shouldn't crash. - EXPECT_TRUE(OpenDocument("bug_601362.pdf")); - FPDF_PAGE page = LoadPage(0); - EXPECT_NE(nullptr, page); - FPDF_BITMAP bitmap = RenderPage(page); - FPDFBitmap_Destroy(bitmap); - UnloadPage(page); -} diff --git a/core/fxge/ge/fx_text_int.h b/core/fxge/ge/fx_text_int.h deleted file mode 100644 index dcd54cead0..0000000000 --- a/core/fxge/ge/fx_text_int.h +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2014 PDFium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com - -#ifndef CORE_FXGE_GE_FX_TEXT_INT_H_ -#define CORE_FXGE_GE_FX_TEXT_INT_H_ - -#include -#include - -#include "core/fxge/fx_font.h" -#include "core/fxge/fx_freetype.h" - -struct CFX_UniqueKeyGen { - void Generate(int count, ...); - - char m_Key[128]; - int m_KeyLen; -}; - -class CFX_SizeGlyphCache { - public: - CFX_SizeGlyphCache(); - ~CFX_SizeGlyphCache(); - - std::map> m_GlyphMap; -}; - -#endif // CORE_FXGE_GE_FX_TEXT_INT_H_ diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp index d56ac113b9..40b1ccb665 100644 --- a/core/fxge/skia/fx_skia_device.cpp +++ b/core/fxge/skia/fx_skia_device.cpp @@ -40,7 +40,7 @@ #include "third_party/skia/include/pathops/SkPathOps.h" #ifdef _SKIA_SUPPORT_PATHS_ -#include "core/fxge/ge/cfx_cliprgn.h" +#include "core/fxge/cfx_cliprgn.h" #endif // _SKIA_SUPPORT_PATHS_ #ifdef _SKIA_SUPPORT_ diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp index b5260c1073..c936553598 100644 --- a/core/fxge/win32/cfx_psrenderer.cpp +++ b/core/fxge/win32/cfx_psrenderer.cpp @@ -17,7 +17,7 @@ #include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_renderdevice.h" #include "core/fxge/dib/cfx_dibextractor.h" -#include "core/fxge/ge/fx_text_int.h" +#include "core/fxge/fx_text_int.h" #include "core/fxge/win32/cpsoutput.h" #include "third_party/base/ptr_util.h" diff --git a/core/fxge/win32/fx_win32_device.cpp b/core/fxge/win32/fx_win32_device.cpp index f6481187b3..ef3a7f2f8e 100644 --- a/core/fxge/win32/fx_win32_device.cpp +++ b/core/fxge/win32/fx_win32_device.cpp @@ -15,6 +15,7 @@ #include "core/fxcrt/fx_codepage.h" #include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_system.h" +#include "core/fxge/cfx_folderfontinfo.h" #include "core/fxge/cfx_gemodule.h" #include "core/fxge/cfx_windowsrenderdevice.h" #include "core/fxge/dib/cfx_dibextractor.h" @@ -22,8 +23,7 @@ #include "core/fxge/dib/cstretchengine.h" #include "core/fxge/fx_font.h" #include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/cfx_folderfontinfo.h" -#include "core/fxge/ge/fx_text_int.h" +#include "core/fxge/fx_text_int.h" #include "core/fxge/ifx_systemfontinfo.h" #include "core/fxge/win32/cfx_windowsdib.h" #include "core/fxge/win32/dwrite_int.h" diff --git a/core/fxge/win32/fx_win32_dwrite.cpp b/core/fxge/win32/fx_win32_dwrite.cpp index 91fb465af4..8b1786a088 100644 --- a/core/fxge/win32/fx_win32_dwrite.cpp +++ b/core/fxge/win32/fx_win32_dwrite.cpp @@ -7,7 +7,7 @@ #include #include "core/fxcrt/fx_system.h" -#include "core/fxge/ge/cfx_cliprgn.h" +#include "core/fxge/cfx_cliprgn.h" #include "core/fxge/win32/dwrite_int.h" typedef HRESULT(__stdcall* FuncType_DWriteCreateFactory)( diff --git a/core/fxge/win32/fx_win32_print.cpp b/core/fxge/win32/fx_win32_print.cpp index 8f7cbf5be0..d7444f43a1 100644 --- a/core/fxge/win32/fx_win32_print.cpp +++ b/core/fxge/win32/fx_win32_print.cpp @@ -16,7 +16,7 @@ #include "core/fxge/dib/cfx_imagerenderer.h" #include "core/fxge/dib/cstretchengine.h" #include "core/fxge/fx_freetype.h" -#include "core/fxge/ge/fx_text_int.h" +#include "core/fxge/fx_text_int.h" #include "core/fxge/win32/cpsoutput.h" #include "core/fxge/win32/win32_int.h" #include "third_party/base/ptr_util.h" -- cgit v1.2.3