| // Copyright 2016 The PDFium Authors |
| // 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 <algorithm> |
| #include <array> |
| #include <limits> |
| |
| namespace { |
| |
| constexpr auto kWeightPow = std::to_array<const uint8_t>({ |
| 0, 6, 12, 14, 16, 18, 22, 24, 28, 30, 32, 34, 36, 38, 40, |
| 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, |
| 70, 72, 72, 74, 74, 74, 76, 76, 76, 78, 78, 78, 80, 80, 80, |
| 82, 82, 82, 84, 84, 84, 84, 86, 86, 86, 88, 88, 88, 88, 90, |
| 90, 90, 90, 92, 92, 92, 92, 94, 94, 94, 94, 96, 96, 96, 96, |
| 96, 98, 98, 98, 98, 100, 100, 100, 100, 100, 102, 102, 102, 102, 102, |
| 104, 104, 104, 104, 104, 106, 106, 106, 106, 106, |
| }); |
| |
| constexpr auto kWeightPow11 = std::to_array<const uint8_t>({ |
| 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, |
| }); |
| |
| constexpr auto kWeightPowShiftJis = std::to_array<const uint8_t>({ |
| 0, 0, 2, 4, 6, 8, 10, 14, 16, 20, 22, 26, 28, 32, 34, |
| 38, 42, 44, 48, 52, 56, 60, 64, 66, 70, 74, 78, 82, 86, 90, |
| 96, 96, 96, 96, 98, 98, 98, 100, 100, 100, 100, 102, 102, 102, 102, |
| 104, 104, 104, 104, 104, 106, 106, 106, 106, 106, 108, 108, 108, 108, 108, |
| 110, 110, 110, 110, 110, 112, 112, 112, 112, 112, 112, 114, 114, 114, 114, |
| 114, 114, 114, 116, 116, 116, 116, 116, 116, 116, 118, 118, 118, 118, 118, |
| 118, 118, 120, 120, 120, 120, 120, 120, 120, 120, |
| }); |
| |
| constexpr size_t kWeightPowArraySize = 100; |
| static_assert(kWeightPowArraySize == std::size(kWeightPow), "Wrong size"); |
| static_assert(kWeightPowArraySize == std::size(kWeightPow11), "Wrong size"); |
| static_assert(kWeightPowArraySize == std::size(kWeightPowShiftJis), |
| "Wrong size"); |
| |
| constexpr auto kAngleSkew = std::to_array<const int8_t>({ |
| -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, |
| }); |
| |
| int GetSkewFromAngle(int angle) { |
| // |angle| is non-positive so |-angle| is used as the index. Need to make sure |
| // |angle| != INT_MIN since -INT_MIN is undefined. |
| if (angle > 0 || angle == std::numeric_limits<int>::min() || |
| static_cast<size_t>(-angle) >= std::size(kAngleSkew)) { |
| return -58; |
| } |
| return kAngleSkew[-angle]; |
| } |
| |
| } // namespace |
| |
| CFX_SubstFont::CFX_SubstFont() = default; |
| |
| CFX_SubstFont::~CFX_SubstFont() = default; |
| |
| #if defined(PDF_USE_SKIA) |
| int CFX_SubstFont::GetOriginalWeight() const { |
| int weight = weight_; |
| |
| // Perform the inverse weight adjustment of UseChromeSerif() to get the |
| // original font weight. |
| if (family_ == "Chrome Serif") { |
| weight = weight * 5 / 4; |
| } |
| return weight; |
| } |
| #endif |
| |
| void CFX_SubstFont::UseChromeSerif() { |
| weight_ = weight_ * 4 / 5; |
| family_ = "Chrome Serif"; |
| } |
| |
| // The following is not a perfect solution and can be further improved. |
| // For example, if `this` is "Book" and the `base_font_name` is "Bookman", |
| // this function will return "true" even though the actual font "Bookman" |
| // is not loaded. |
| // An exact string match is not possible here, because `subst_font_name` |
| // will be the same value for different postscript names. |
| // For example: "Times New Roman" as `subst_font_name` for all of these |
| // `base_font_name` values: "TimesNewRoman,Bold", "TimesNewRomanPS-Bold", |
| // "TimesNewRomanBold" and "TimesNewRoman-Bold". |
| bool CFX_SubstFont::IsActualFontLoaded(const ByteString& base_font_name) const { |
| // Skip if we loaded the actual font. |
| // example: TimesNewRoman,Bold -> Times New Roman |
| ByteString subst_font_name = family_; |
| subst_font_name.Remove(' '); |
| subst_font_name.MakeLower(); |
| |
| std::optional<size_t> find = |
| base_font_name.Find(subst_font_name.AsStringView()); |
| return find.has_value() && find.value() == 0; |
| } |
| |
| int CFX_SubstFont::GetWeightLevel(size_t index) const { |
| if (index >= kWeightPowArraySize) { |
| return -1; |
| } |
| if (charset_ == FX_Charset::kShiftJIS) { |
| return kWeightPowShiftJis[index]; |
| } |
| return kWeightPow11[index]; |
| } |
| |
| int CFX_SubstFont::GetWeightLevelForLoad(size_t index) const { |
| index = std::min(index, kWeightPowArraySize - 1); |
| if (charset_ == FX_Charset::kShiftJIS) { |
| return kWeightPowShiftJis[index] * 65536 / 36655; |
| } |
| return kWeightPow[index]; |
| } |
| |
| int CFX_SubstFont::GetSkew() const { |
| return GetSkewFromAngle(italic_angle_); |
| } |
| |
| int CFX_SubstFont::GetSkewCJK() const { |
| return GetSkewFromAngle(italic_cjk_ ? -15 : 0); |
| } |