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/fpdfapi/font/cpdf_simplefont.h" 8 9 #include "core/fpdfapi/font/font_int.h" 10 #include "core/fpdfapi/parser/cpdf_array.h" 11 #include "core/fpdfapi/parser/cpdf_dictionary.h" 12 #include "core/fxge/fx_freetype.h" 13 #include "third_party/base/numerics/safe_math.h" 14 15 CPDF_SimpleFont::CPDF_SimpleFont() : m_BaseEncoding(PDFFONT_ENCODING_BUILTIN) { 16 FXSYS_memset(m_CharWidth, 0xff, sizeof(m_CharWidth)); 17 FXSYS_memset(m_GlyphIndex, 0xff, sizeof(m_GlyphIndex)); 18 FXSYS_memset(m_ExtGID, 0xff, sizeof(m_ExtGID)); 19 for (size_t i = 0; i < FX_ArraySize(m_CharBBox); ++i) 20 m_CharBBox[i] = FX_RECT(-1, -1, -1, -1); 21 } 22 23 CPDF_SimpleFont::~CPDF_SimpleFont() {} 24 25 int CPDF_SimpleFont::GlyphFromCharCode(uint32_t charcode, bool* pVertGlyph) { 26 if (pVertGlyph) 27 *pVertGlyph = false; 28 29 if (charcode > 0xff) 30 return -1; 31 32 int index = m_GlyphIndex[(uint8_t)charcode]; 33 return index != 0xffff ? index : -1; 34 } 35 36 void CPDF_SimpleFont::LoadCharMetrics(int charcode) { 37 if (!m_Font.GetFace()) 38 return; 39 40 if (charcode < 0 || charcode > 0xff) { 41 return; 42 } 43 int glyph_index = m_GlyphIndex[charcode]; 44 if (glyph_index == 0xffff) { 45 if (!m_pFontFile && charcode != 32) { 46 LoadCharMetrics(32); 47 m_CharBBox[charcode] = m_CharBBox[32]; 48 if (m_bUseFontWidth) { 49 m_CharWidth[charcode] = m_CharWidth[32]; 50 } 51 } 52 return; 53 } 54 FXFT_Face face = m_Font.GetFace(); 55 int err = FXFT_Load_Glyph( 56 face, glyph_index, 57 FXFT_LOAD_NO_SCALE | FXFT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH); 58 if (err) 59 return; 60 61 int iHoriBearingX = FXFT_Get_Glyph_HoriBearingX(face); 62 int iHoriBearingY = FXFT_Get_Glyph_HoriBearingY(face); 63 m_CharBBox[charcode] = 64 FX_RECT(TT2PDF(iHoriBearingX, face), TT2PDF(iHoriBearingY, face), 65 TT2PDF(iHoriBearingX + FXFT_Get_Glyph_Width(face), face), 66 TT2PDF(iHoriBearingY - FXFT_Get_Glyph_Height(face), face)); 67 68 if (m_bUseFontWidth) { 69 int TT_Width = TT2PDF(FXFT_Get_Glyph_HoriAdvance(face), face); 70 if (m_CharWidth[charcode] == 0xffff) { 71 m_CharWidth[charcode] = TT_Width; 72 } else if (TT_Width && !IsEmbedded()) { 73 m_CharBBox[charcode].right = 74 m_CharBBox[charcode].right * m_CharWidth[charcode] / TT_Width; 75 m_CharBBox[charcode].left = 76 m_CharBBox[charcode].left * m_CharWidth[charcode] / TT_Width; 77 } 78 } 79 } 80 81 int CPDF_SimpleFont::GetCharWidthF(uint32_t charcode) { 82 if (charcode > 0xff) 83 charcode = 0; 84 85 if (m_CharWidth[charcode] == 0xffff) { 86 LoadCharMetrics(charcode); 87 if (m_CharWidth[charcode] == 0xffff) { 88 m_CharWidth[charcode] = 0; 89 } 90 } 91 return m_CharWidth[charcode]; 92 } 93 94 FX_RECT CPDF_SimpleFont::GetCharBBox(uint32_t charcode) { 95 if (charcode > 0xff) 96 charcode = 0; 97 98 if (m_CharBBox[charcode].left == -1) 99 LoadCharMetrics(charcode); 100 101 return m_CharBBox[charcode]; 102 } 103 104 bool CPDF_SimpleFont::LoadCommon() { 105 CPDF_Dictionary* pFontDesc = m_pFontDict->GetDictFor("FontDescriptor"); 106 if (pFontDesc) { 107 LoadFontDescriptor(pFontDesc); 108 } 109 CPDF_Array* pWidthArray = m_pFontDict->GetArrayFor("Widths"); 110 m_bUseFontWidth = !pWidthArray; 111 if (pWidthArray) { 112 if (pFontDesc && pFontDesc->KeyExist("MissingWidth")) { 113 int MissingWidth = pFontDesc->GetIntegerFor("MissingWidth"); 114 for (int i = 0; i < 256; i++) { 115 m_CharWidth[i] = MissingWidth; 116 } 117 } 118 size_t width_start = m_pFontDict->GetIntegerFor("FirstChar", 0); 119 size_t width_end = m_pFontDict->GetIntegerFor("LastChar", 0); 120 if (width_start <= 255) { 121 if (width_end == 0 || width_end >= width_start + pWidthArray->GetCount()) 122 width_end = width_start + pWidthArray->GetCount() - 1; 123 if (width_end > 255) 124 width_end = 255; 125 for (size_t i = width_start; i <= width_end; i++) 126 m_CharWidth[i] = pWidthArray->GetIntegerAt(i - width_start); 127 } 128 } 129 if (m_pFontFile) { 130 if (m_BaseFont.GetLength() > 8 && m_BaseFont[7] == '+') 131 m_BaseFont = m_BaseFont.Mid(8); 132 } else { 133 LoadSubstFont(); 134 } 135 if (!(m_Flags & FXFONT_SYMBOLIC)) 136 m_BaseEncoding = PDFFONT_ENCODING_STANDARD; 137 CPDF_Object* pEncoding = m_pFontDict->GetDirectObjectFor("Encoding"); 138 LoadPDFEncoding(pEncoding, m_BaseEncoding, &m_CharNames, !!m_pFontFile, 139 m_Font.IsTTFont()); 140 LoadGlyphMap(); 141 m_CharNames.clear(); 142 if (!m_Font.GetFace()) 143 return true; 144 145 if (m_Flags & FXFONT_ALLCAP) { 146 unsigned char kLowercases[][2] = {{'a', 'z'}, {0xe0, 0xf6}, {0xf8, 0xfd}}; 147 for (size_t range = 0; range < FX_ArraySize(kLowercases); ++range) { 148 const auto& lower = kLowercases[range]; 149 for (int i = lower[0]; i <= lower[1]; ++i) { 150 if (m_GlyphIndex[i] != 0xffff && m_pFontFile) 151 continue; 152 153 int j = i - 32; 154 m_GlyphIndex[i] = m_GlyphIndex[j]; 155 if (m_CharWidth[j]) { 156 m_CharWidth[i] = m_CharWidth[j]; 157 m_CharBBox[i] = m_CharBBox[j]; 158 } 159 } 160 } 161 } 162 CheckFontMetrics(); 163 return true; 164 } 165 166 void CPDF_SimpleFont::LoadSubstFont() { 167 if (!m_bUseFontWidth && !(m_Flags & FXFONT_FIXED_PITCH)) { 168 int width = 0, i; 169 for (i = 0; i < 256; i++) { 170 if (m_CharWidth[i] == 0 || m_CharWidth[i] == 0xffff) 171 continue; 172 173 if (width == 0) 174 width = m_CharWidth[i]; 175 else if (width != m_CharWidth[i]) 176 break; 177 } 178 if (i == 256 && width) 179 m_Flags |= FXFONT_FIXED_PITCH; 180 } 181 pdfium::base::CheckedNumeric<int> safeStemV(m_StemV); 182 if (m_StemV < 140) 183 safeStemV *= 5; 184 else 185 safeStemV = safeStemV * 4 + 140; 186 m_Font.LoadSubst(m_BaseFont, IsTrueTypeFont(), m_Flags, 187 safeStemV.ValueOrDefault(FXFONT_FW_NORMAL), m_ItalicAngle, 0, 188 false); 189 } 190 191 bool CPDF_SimpleFont::IsUnicodeCompatible() const { 192 return m_BaseEncoding != PDFFONT_ENCODING_BUILTIN && 193 m_BaseEncoding != PDFFONT_ENCODING_ADOBE_SYMBOL && 194 m_BaseEncoding != PDFFONT_ENCODING_ZAPFDINGBATS; 195 } 196 197 CFX_WideString CPDF_SimpleFont::UnicodeFromCharCode(uint32_t charcode) const { 198 CFX_WideString unicode = CPDF_Font::UnicodeFromCharCode(charcode); 199 if (!unicode.IsEmpty()) 200 return unicode; 201 FX_WCHAR ret = m_Encoding.UnicodeFromCharCode((uint8_t)charcode); 202 if (ret == 0) 203 return CFX_WideString(); 204 return ret; 205 } 206 207 uint32_t CPDF_SimpleFont::CharCodeFromUnicode(FX_WCHAR unicode) const { 208 uint32_t ret = CPDF_Font::CharCodeFromUnicode(unicode); 209 if (ret) 210 return ret; 211 return m_Encoding.CharCodeFromUnicode(unicode); 212 } 213