Home | History | Annotate | Download | only in ge
      1 // Copyright 2016 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "core/fxge/cfx_facecache.h"
      8 
      9 #include <algorithm>
     10 #include <limits>
     11 #include <memory>
     12 
     13 #include "core/fxge/cfx_fontmgr.h"
     14 #include "core/fxge/cfx_gemodule.h"
     15 #include "core/fxge/cfx_pathdata.h"
     16 #include "core/fxge/cfx_substfont.h"
     17 #include "core/fxge/fx_freetype.h"
     18 #include "core/fxge/ge/fx_text_int.h"
     19 #include "third_party/base/numerics/safe_math.h"
     20 
     21 #if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_
     22 #include "third_party/skia/include/core/SkStream.h"
     23 #include "third_party/skia/include/core/SkTypeface.h"
     24 #endif
     25 
     26 namespace {
     27 
     28 constexpr uint32_t kInvalidGlyphIndex = static_cast<uint32_t>(-1);
     29 
     30 void GammaAdjust(uint8_t* pData,
     31                  int nHeight,
     32                  int src_pitch,
     33                  const uint8_t* gammaTable) {
     34   int count = nHeight * src_pitch;
     35   for (int i = 0; i < count; i++)
     36     pData[i] = gammaTable[pData[i]];
     37 }
     38 
     39 void ContrastAdjust(uint8_t* pDataIn,
     40                     uint8_t* pDataOut,
     41                     int nWidth,
     42                     int nHeight,
     43                     int nSrcRowBytes,
     44                     int nDstRowBytes) {
     45   int col, row, temp;
     46   int max = 0, min = 255;
     47   FX_FLOAT rate;
     48   for (row = 0; row < nHeight; row++) {
     49     uint8_t* pRow = pDataIn + row * nSrcRowBytes;
     50     for (col = 0; col < nWidth; col++) {
     51       temp = *pRow++;
     52       max = std::max(temp, max);
     53       min = std::min(temp, min);
     54     }
     55   }
     56   temp = max - min;
     57   if (temp == 0 || temp == 255) {
     58     int rowbytes = std::min(FXSYS_abs(nSrcRowBytes), nDstRowBytes);
     59     for (row = 0; row < nHeight; row++) {
     60       FXSYS_memcpy(pDataOut + row * nDstRowBytes, pDataIn + row * nSrcRowBytes,
     61                    rowbytes);
     62     }
     63     return;
     64   }
     65   rate = 255.f / temp;
     66   for (row = 0; row < nHeight; row++) {
     67     uint8_t* pSrcRow = pDataIn + row * nSrcRowBytes;
     68     uint8_t* pDstRow = pDataOut + row * nDstRowBytes;
     69     for (col = 0; col < nWidth; col++) {
     70       temp = static_cast<int>((*(pSrcRow++) - min) * rate + 0.5);
     71       temp = std::min(temp, 255);
     72       temp = std::max(temp, 0);
     73       *pDstRow++ = (uint8_t)temp;
     74     }
     75   }
     76 }
     77 }  // namespace
     78 
     79 CFX_FaceCache::CFX_FaceCache(FXFT_Face face)
     80     : m_Face(face)
     81 #if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_
     82       ,
     83       m_pTypeface(nullptr)
     84 #endif
     85 {
     86 }
     87 
     88 CFX_FaceCache::~CFX_FaceCache() {
     89 #if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_
     90   SkSafeUnref(m_pTypeface);
     91 #endif
     92 }
     93 
     94 CFX_GlyphBitmap* CFX_FaceCache::RenderGlyph(const CFX_Font* pFont,
     95                                             uint32_t glyph_index,
     96                                             bool bFontStyle,
     97                                             const CFX_Matrix* pMatrix,
     98                                             int dest_width,
     99                                             int anti_alias) {
    100   if (!m_Face)
    101     return nullptr;
    102 
    103   FXFT_Matrix ft_matrix;
    104   ft_matrix.xx = (signed long)(pMatrix->a / 64 * 65536);
    105   ft_matrix.xy = (signed long)(pMatrix->c / 64 * 65536);
    106   ft_matrix.yx = (signed long)(pMatrix->b / 64 * 65536);
    107   ft_matrix.yy = (signed long)(pMatrix->d / 64 * 65536);
    108   bool bUseCJKSubFont = false;
    109   const CFX_SubstFont* pSubstFont = pFont->GetSubstFont();
    110   if (pSubstFont) {
    111     bUseCJKSubFont = pSubstFont->m_bSubstCJK && bFontStyle;
    112     int skew = 0;
    113     if (bUseCJKSubFont)
    114       skew = pSubstFont->m_bItalicCJK ? -15 : 0;
    115     else
    116       skew = pSubstFont->m_ItalicAngle;
    117     if (skew) {
    118       // |skew| is nonpositive so |-skew| is used as the index. We need to make
    119       // sure |skew| != INT_MIN since -INT_MIN is undefined.
    120       if (skew <= 0 && skew != std::numeric_limits<int>::min() &&
    121           static_cast<size_t>(-skew) < CFX_Font::kAngleSkewArraySize) {
    122         skew = -CFX_Font::s_AngleSkew[-skew];
    123       } else {
    124         skew = -58;
    125       }
    126       if (pFont->IsVertical())
    127         ft_matrix.yx += ft_matrix.yy * skew / 100;
    128       else
    129         ft_matrix.xy -= ft_matrix.xx * skew / 100;
    130     }
    131     if (pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) {
    132       pFont->AdjustMMParams(glyph_index, dest_width,
    133                             pFont->GetSubstFont()->m_Weight);
    134     }
    135   }
    136   ScopedFontTransform scoped_transform(m_Face, &ft_matrix);
    137   int load_flags = (m_Face->face_flags & FT_FACE_FLAG_SFNT)
    138                        ? FXFT_LOAD_NO_BITMAP
    139                        : (FXFT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING);
    140   int error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags);
    141   if (error) {
    142     // if an error is returned, try to reload glyphs without hinting.
    143     if (load_flags & FT_LOAD_NO_HINTING || load_flags & FT_LOAD_NO_SCALE)
    144       return nullptr;
    145 
    146     load_flags |= FT_LOAD_NO_HINTING;
    147     error = FXFT_Load_Glyph(m_Face, glyph_index, load_flags);
    148 
    149     if (error)
    150       return nullptr;
    151   }
    152   int weight = 0;
    153   if (bUseCJKSubFont)
    154     weight = pSubstFont->m_WeightCJK;
    155   else
    156     weight = pSubstFont ? pSubstFont->m_Weight : 0;
    157   if (pSubstFont && !(pSubstFont->m_SubstFlags & FXFONT_SUBST_MM) &&
    158       weight > 400) {
    159     uint32_t index = (weight - 400) / 10;
    160     if (index >= CFX_Font::kWeightPowArraySize)
    161       return nullptr;
    162     pdfium::base::CheckedNumeric<signed long> level = 0;
    163     if (pSubstFont->m_Charset == FXFONT_SHIFTJIS_CHARSET)
    164       level = CFX_Font::s_WeightPow_SHIFTJIS[index] * 2;
    165     else
    166       level = CFX_Font::s_WeightPow_11[index];
    167 
    168     level = level * (FXSYS_abs(static_cast<int>(ft_matrix.xx)) +
    169                      FXSYS_abs(static_cast<int>(ft_matrix.xy))) /
    170             36655;
    171     FXFT_Outline_Embolden(FXFT_Get_Glyph_Outline(m_Face),
    172                           level.ValueOrDefault(0));
    173   }
    174   FXFT_Library_SetLcdFilter(CFX_GEModule::Get()->GetFontMgr()->GetFTLibrary(),
    175                             FT_LCD_FILTER_DEFAULT);
    176   error = FXFT_Render_Glyph(m_Face, anti_alias);
    177   if (error)
    178     return nullptr;
    179   int bmwidth = FXFT_Get_Bitmap_Width(FXFT_Get_Glyph_Bitmap(m_Face));
    180   int bmheight = FXFT_Get_Bitmap_Rows(FXFT_Get_Glyph_Bitmap(m_Face));
    181   if (bmwidth > 2048 || bmheight > 2048)
    182     return nullptr;
    183   int dib_width = bmwidth;
    184   CFX_GlyphBitmap* pGlyphBitmap = new CFX_GlyphBitmap;
    185   pGlyphBitmap->m_Bitmap.Create(
    186       dib_width, bmheight,
    187       anti_alias == FXFT_RENDER_MODE_MONO ? FXDIB_1bppMask : FXDIB_8bppMask);
    188   pGlyphBitmap->m_Left = FXFT_Get_Glyph_BitmapLeft(m_Face);
    189   pGlyphBitmap->m_Top = FXFT_Get_Glyph_BitmapTop(m_Face);
    190   int dest_pitch = pGlyphBitmap->m_Bitmap.GetPitch();
    191   int src_pitch = FXFT_Get_Bitmap_Pitch(FXFT_Get_Glyph_Bitmap(m_Face));
    192   uint8_t* pDestBuf = pGlyphBitmap->m_Bitmap.GetBuffer();
    193   uint8_t* pSrcBuf =
    194       (uint8_t*)FXFT_Get_Bitmap_Buffer(FXFT_Get_Glyph_Bitmap(m_Face));
    195   if (anti_alias != FXFT_RENDER_MODE_MONO &&
    196       FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) ==
    197           FXFT_PIXEL_MODE_MONO) {
    198     int bytes = anti_alias == FXFT_RENDER_MODE_LCD ? 3 : 1;
    199     for (int i = 0; i < bmheight; i++) {
    200       for (int n = 0; n < bmwidth; n++) {
    201         uint8_t data =
    202             (pSrcBuf[i * src_pitch + n / 8] & (0x80 >> (n % 8))) ? 255 : 0;
    203         for (int b = 0; b < bytes; b++)
    204           pDestBuf[i * dest_pitch + n * bytes + b] = data;
    205       }
    206     }
    207   } else {
    208     FXSYS_memset(pDestBuf, 0, dest_pitch * bmheight);
    209     if (anti_alias == FXFT_RENDER_MODE_MONO &&
    210         FXFT_Get_Bitmap_PixelMode(FXFT_Get_Glyph_Bitmap(m_Face)) ==
    211             FXFT_PIXEL_MODE_MONO) {
    212       int rowbytes =
    213           FXSYS_abs(src_pitch) > dest_pitch ? dest_pitch : FXSYS_abs(src_pitch);
    214       for (int row = 0; row < bmheight; row++) {
    215         FXSYS_memcpy(pDestBuf + row * dest_pitch, pSrcBuf + row * src_pitch,
    216                      rowbytes);
    217       }
    218     } else {
    219       ContrastAdjust(pSrcBuf, pDestBuf, bmwidth, bmheight, src_pitch,
    220                      dest_pitch);
    221       GammaAdjust(pDestBuf, bmheight, dest_pitch,
    222                   CFX_GEModule::Get()->GetTextGammaTable());
    223     }
    224   }
    225   return pGlyphBitmap;
    226 }
    227 
    228 const CFX_PathData* CFX_FaceCache::LoadGlyphPath(const CFX_Font* pFont,
    229                                                  uint32_t glyph_index,
    230                                                  int dest_width) {
    231   if (!m_Face || glyph_index == kInvalidGlyphIndex || dest_width < 0)
    232     return nullptr;
    233 
    234   uint32_t key = glyph_index;
    235   auto* pSubstFont = pFont->GetSubstFont();
    236   if (pSubstFont) {
    237     if (pSubstFont->m_Weight < 0 || pSubstFont->m_ItalicAngle < 0)
    238       return nullptr;
    239     uint32_t weight = static_cast<uint32_t>(pSubstFont->m_Weight);
    240     uint32_t angle = static_cast<uint32_t>(pSubstFont->m_ItalicAngle);
    241     uint32_t key_modifier = (weight / 16) << 15;
    242     key_modifier += (angle / 2) << 21;
    243     key_modifier += (static_cast<uint32_t>(dest_width) / 16) << 25;
    244     if (pFont->IsVertical())
    245       key_modifier += 1U << 31;
    246     key += key_modifier;
    247   }
    248   auto it = m_PathMap.find(key);
    249   if (it != m_PathMap.end())
    250     return it->second.get();
    251 
    252   CFX_PathData* pGlyphPath = pFont->LoadGlyphPathImpl(glyph_index, dest_width);
    253   m_PathMap[key] = std::unique_ptr<CFX_PathData>(pGlyphPath);
    254   return pGlyphPath;
    255 }
    256 
    257 const CFX_GlyphBitmap* CFX_FaceCache::LoadGlyphBitmap(const CFX_Font* pFont,
    258                                                       uint32_t glyph_index,
    259                                                       bool bFontStyle,
    260                                                       const CFX_Matrix* pMatrix,
    261                                                       int dest_width,
    262                                                       int anti_alias,
    263                                                       int& text_flags) {
    264   if (glyph_index == kInvalidGlyphIndex)
    265     return nullptr;
    266 
    267   _CFX_UniqueKeyGen keygen;
    268   int nMatrixA = static_cast<int>(pMatrix->a * 10000);
    269   int nMatrixB = static_cast<int>(pMatrix->b * 10000);
    270   int nMatrixC = static_cast<int>(pMatrix->c * 10000);
    271   int nMatrixD = static_cast<int>(pMatrix->d * 10000);
    272 #if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
    273   if (pFont->GetSubstFont()) {
    274     keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
    275                     anti_alias, pFont->GetSubstFont()->m_Weight,
    276                     pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical());
    277   } else {
    278     keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
    279                     anti_alias);
    280   }
    281 #else
    282   if (text_flags & FXTEXT_NO_NATIVETEXT) {
    283     if (pFont->GetSubstFont()) {
    284       keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
    285                       anti_alias, pFont->GetSubstFont()->m_Weight,
    286                       pFont->GetSubstFont()->m_ItalicAngle,
    287                       pFont->IsVertical());
    288     } else {
    289       keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
    290                       anti_alias);
    291     }
    292   } else {
    293     if (pFont->GetSubstFont()) {
    294       keygen.Generate(10, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
    295                       anti_alias, pFont->GetSubstFont()->m_Weight,
    296                       pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical(),
    297                       3);
    298     } else {
    299       keygen.Generate(7, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
    300                       anti_alias, 3);
    301     }
    302   }
    303 #endif
    304   CFX_ByteString FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen);
    305 #if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_ || defined _SKIA_SUPPORT_ || \
    306     defined _SKIA_SUPPORT_PATHS_
    307   return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index,
    308                            bFontStyle, dest_width, anti_alias);
    309 #else
    310   if (text_flags & FXTEXT_NO_NATIVETEXT) {
    311     return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey, glyph_index,
    312                              bFontStyle, dest_width, anti_alias);
    313   }
    314   CFX_GlyphBitmap* pGlyphBitmap;
    315   auto it = m_SizeMap.find(FaceGlyphsKey);
    316   if (it != m_SizeMap.end()) {
    317     CFX_SizeGlyphCache* pSizeCache = it->second.get();
    318     auto it2 = pSizeCache->m_GlyphMap.find(glyph_index);
    319     if (it2 != pSizeCache->m_GlyphMap.end())
    320       return it2->second;
    321 
    322     pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix,
    323                                           dest_width, anti_alias);
    324     if (pGlyphBitmap) {
    325       pSizeCache->m_GlyphMap[glyph_index] = pGlyphBitmap;
    326       return pGlyphBitmap;
    327     }
    328   } else {
    329     pGlyphBitmap = RenderGlyph_Nativetext(pFont, glyph_index, pMatrix,
    330                                           dest_width, anti_alias);
    331     if (pGlyphBitmap) {
    332       CFX_SizeGlyphCache* pSizeCache = new CFX_SizeGlyphCache;
    333       m_SizeMap[FaceGlyphsKey] =
    334           std::unique_ptr<CFX_SizeGlyphCache>(pSizeCache);
    335       pSizeCache->m_GlyphMap[glyph_index] = pGlyphBitmap;
    336       return pGlyphBitmap;
    337     }
    338   }
    339   if (pFont->GetSubstFont()) {
    340     keygen.Generate(9, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
    341                     anti_alias, pFont->GetSubstFont()->m_Weight,
    342                     pFont->GetSubstFont()->m_ItalicAngle, pFont->IsVertical());
    343   } else {
    344     keygen.Generate(6, nMatrixA, nMatrixB, nMatrixC, nMatrixD, dest_width,
    345                     anti_alias);
    346   }
    347   CFX_ByteString FaceGlyphsKey2(keygen.m_Key, keygen.m_KeyLen);
    348   text_flags |= FXTEXT_NO_NATIVETEXT;
    349   return LookUpGlyphBitmap(pFont, pMatrix, FaceGlyphsKey2, glyph_index,
    350                            bFontStyle, dest_width, anti_alias);
    351 #endif
    352 }
    353 
    354 #if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_
    355 CFX_TypeFace* CFX_FaceCache::GetDeviceCache(const CFX_Font* pFont) {
    356   if (!m_pTypeface) {
    357     m_pTypeface =
    358         SkTypeface::MakeFromStream(
    359             new SkMemoryStream(pFont->GetFontData(), pFont->GetSize()))
    360             .release();
    361   }
    362   return m_pTypeface;
    363 }
    364 #endif
    365 
    366 #if _FXM_PLATFORM_ != _FXM_PLATFORM_APPLE_
    367 void CFX_FaceCache::InitPlatform() {}
    368 #endif
    369 
    370 CFX_GlyphBitmap* CFX_FaceCache::LookUpGlyphBitmap(
    371     const CFX_Font* pFont,
    372     const CFX_Matrix* pMatrix,
    373     const CFX_ByteString& FaceGlyphsKey,
    374     uint32_t glyph_index,
    375     bool bFontStyle,
    376     int dest_width,
    377     int anti_alias) {
    378   CFX_SizeGlyphCache* pSizeCache;
    379   auto it = m_SizeMap.find(FaceGlyphsKey);
    380   if (it == m_SizeMap.end()) {
    381     pSizeCache = new CFX_SizeGlyphCache;
    382     m_SizeMap[FaceGlyphsKey] = std::unique_ptr<CFX_SizeGlyphCache>(pSizeCache);
    383   } else {
    384     pSizeCache = it->second.get();
    385   }
    386   auto it2 = pSizeCache->m_GlyphMap.find(glyph_index);
    387   if (it2 != pSizeCache->m_GlyphMap.end())
    388     return it2->second;
    389 
    390   CFX_GlyphBitmap* pGlyphBitmap = RenderGlyph(pFont, glyph_index, bFontStyle,
    391                                               pMatrix, dest_width, anti_alias);
    392   pSizeCache->m_GlyphMap[glyph_index] = pGlyphBitmap;
    393   return pGlyphBitmap;
    394 }
    395