Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
charposlist.cpp
Go to the documentation of this file.
1// Copyright 2016 The PDFium Authors
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/render/charposlist.h"
8
9#include "build/build_config.h"
10#include "core/fpdfapi/font/cpdf_cidfont.h"
11#include "core/fpdfapi/font/cpdf_font.h"
12#include "core/fpdfapi/parser/cpdf_stream.h"
13#include "core/fxge/cfx_fontmapper.h"
14#include "core/fxge/cfx_substfont.h"
15#include "core/fxge/text_char_pos.h"
16
17namespace {
18
19bool ShouldUseExistingFont(const CPDF_Font* font,
20 uint32_t glyph_id,
21 bool has_to_unicode) {
22 // Check for invalid glyph ID.
23 if (glyph_id == static_cast<uint32_t>(-1)) {
24 return false;
25 }
26
27 if (font->IsEmbedded()) {
28 return true;
29 }
30
31 if (!font->IsTrueTypeFont()) {
32 return true;
33 }
34
35 // For non-embedded TrueType fonts, a glyph ID of 0 may be invalid.
36 //
37 // When a "ToUnicode" entry exists in the font dictionary, it indicates
38 // a "ToUnicode" mapping file is used to convert from CIDs (which
39 // begins at decimal 0) to Unicode code. (See ToUnicode Mapping File
40 // Tutorial - Adobe
41 // https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/5411.ToUnicode.pdf
42 // and
43 // https://www.freetype.org/freetype2/docs/tutorial/step1.html#section-6)
44 return glyph_id != 0 || has_to_unicode;
45}
46
47// The following is not a perfect solution and can be further improved.
48// For example, if `subst_font` is "Book" and the `base_font_name` is "Bookman",
49// this function will return "true" even though the actual font "Bookman"
50// is not loaded.
51// An exact string match is not possible here, because `subst_font_name`
52// will be the same value for different postscript names.
53// For example: "Times New Roman" as `subst_font_name` for all of these
54// `base_font_name` values: "TimesNewRoman,Bold", "TimesNewRomanPS-Bold",
55// "TimesNewRomanBold" and "TimesNewRoman-Bold".
56bool IsActualFontLoaded(const CFX_SubstFont* subst_font,
57 const ByteString& base_font_name) {
58 // Skip if we loaded the actual font.
59 // example: TimesNewRoman,Bold -> Times New Roman
60 ByteString subst_font_name = subst_font->m_Family;
61 subst_font_name.Remove(' ');
62 subst_font_name.MakeLower();
63
64 std::optional<size_t> find =
65 base_font_name.Find(subst_font_name.AsStringView());
66 return find.has_value() && find.value() == 0;
67}
68
69bool ApplyGlyphSpacingHeuristic(const CPDF_Font* font,
70 const CFX_Font* current_font,
71 bool is_vertical_writing) {
72 if (is_vertical_writing || font->IsEmbedded() || !font->HasFontWidths()) {
73 return false;
74 }
75
76 // Skip if we loaded a standard alternate font.
77 // example: Helvetica -> Arial
78 ByteString base_font_name = font->GetBaseFontName();
79 base_font_name.MakeLower();
80
81 auto standard_font_name =
83 if (standard_font_name.has_value()) {
84 return false;
85 }
86
87 CFX_SubstFont* subst_font = current_font->GetSubstFont();
88 if (subst_font->IsBuiltInGenericFont()) {
89 return false;
90 }
91
92 return !IsActualFontLoaded(subst_font, base_font_name);
93}
94
95} // namespace
96
97std::vector<TextCharPos> GetCharPosList(pdfium::span<const uint32_t> char_codes,
98 pdfium::span<const float> char_pos,
99 CPDF_Font* font,
100 float font_size) {
101 std::vector<TextCharPos> results;
102 results.reserve(char_codes.size());
103
104 CPDF_CIDFont* cid_font = font->AsCIDFont();
105 bool is_vertical_writing = cid_font && cid_font->IsVertWriting();
106 bool has_to_unicode = !!font->GetFontDict()->GetStreamFor("ToUnicode");
107 for (size_t i = 0; i < char_codes.size(); ++i) {
108 uint32_t char_code = char_codes[i];
109 if (char_code == static_cast<uint32_t>(-1))
110 continue;
111
112 bool is_vertical_glyph = false;
113 results.emplace_back();
114 TextCharPos& text_char_pos = results.back();
115 if (cid_font)
116 text_char_pos.m_bFontStyle = true;
117 WideString unicode = font->UnicodeFromCharCode(char_code);
118 text_char_pos.m_Unicode = !unicode.IsEmpty() ? unicode[0] : char_code;
119 text_char_pos.m_GlyphIndex =
120 font->GlyphFromCharCode(char_code, &is_vertical_glyph);
121 uint32_t glyph_id = text_char_pos.m_GlyphIndex;
122#if BUILDFLAG(IS_APPLE)
123 text_char_pos.m_ExtGID = font->GlyphFromCharCodeExt(char_code);
124 glyph_id = text_char_pos.m_ExtGID != static_cast<uint32_t>(-1)
125 ? text_char_pos.m_ExtGID
126 : text_char_pos.m_GlyphIndex;
127#endif
128 CFX_Font* current_font;
129 if (ShouldUseExistingFont(font, glyph_id, has_to_unicode)) {
130 current_font = font->GetFont();
131 text_char_pos.m_FallbackFontPosition = -1;
132 } else {
133 int32_t fallback_position = font->FallbackFontFromCharcode(char_code);
134 current_font = font->GetFontFallback(fallback_position);
135 text_char_pos.m_FallbackFontPosition = fallback_position;
136 text_char_pos.m_GlyphIndex =
137 font->FallbackGlyphFromCharcode(fallback_position, char_code);
138#if BUILDFLAG(IS_APPLE)
139 text_char_pos.m_ExtGID = text_char_pos.m_GlyphIndex;
140#endif
141 }
142
143 if (!font->IsEmbedded() && !font->IsCIDFont())
144 text_char_pos.m_FontCharWidth = font->GetCharWidthF(char_code);
145 else
146 text_char_pos.m_FontCharWidth = 0;
147
148 text_char_pos.m_Origin = CFX_PointF(i > 0 ? char_pos[i - 1] : 0, 0);
149 text_char_pos.m_bGlyphAdjust = false;
150
151 float scaling_factor = 1.0f;
152 if (ApplyGlyphSpacingHeuristic(font, current_font, is_vertical_writing)) {
153 int pdf_glyph_width = font->GetCharWidthF(char_code);
154 int font_glyph_width =
155 current_font->GetGlyphWidth(text_char_pos.m_GlyphIndex);
156 if (font_glyph_width && pdf_glyph_width > font_glyph_width + 1) {
157 // Move the initial x position by half of the excess (transformed to
158 // text space coordinates).
159 text_char_pos.m_Origin.x +=
160 (pdf_glyph_width - font_glyph_width) * font_size / 2000.0f;
161 } else if (pdf_glyph_width && font_glyph_width &&
162 pdf_glyph_width < font_glyph_width) {
163 scaling_factor = static_cast<float>(pdf_glyph_width) / font_glyph_width;
164 text_char_pos.m_AdjustMatrix[0] = scaling_factor;
165 text_char_pos.m_AdjustMatrix[1] = 0.0f;
166 text_char_pos.m_AdjustMatrix[2] = 0.0f;
167 text_char_pos.m_AdjustMatrix[3] = 1.0f;
168 text_char_pos.m_bGlyphAdjust = true;
169 }
170 }
171 if (!cid_font)
172 continue;
173
174 uint16_t cid = cid_font->CIDFromCharCode(char_code);
175 if (is_vertical_writing) {
176 text_char_pos.m_Origin = CFX_PointF(0, text_char_pos.m_Origin.x);
177
178 CFX_Point16 vertical_origin = cid_font->GetVertOrigin(cid);
179 text_char_pos.m_Origin.x -= font_size * vertical_origin.x / 1000;
180 text_char_pos.m_Origin.y -= font_size * vertical_origin.y / 1000;
181 }
182
183 const CIDTransform* cid_transform = cid_font->GetCIDTransform(cid);
184 if (cid_transform && !is_vertical_glyph) {
185 text_char_pos.m_AdjustMatrix[0] =
186 cid_font->CIDTransformToFloat(cid_transform->a) * scaling_factor;
187 text_char_pos.m_AdjustMatrix[1] =
188 cid_font->CIDTransformToFloat(cid_transform->b) * scaling_factor;
189 text_char_pos.m_AdjustMatrix[2] =
190 cid_font->CIDTransformToFloat(cid_transform->c);
191 text_char_pos.m_AdjustMatrix[3] =
192 cid_font->CIDTransformToFloat(cid_transform->d);
193 text_char_pos.m_Origin.x +=
194 cid_font->CIDTransformToFloat(cid_transform->e) * font_size;
195 text_char_pos.m_Origin.y +=
196 cid_font->CIDTransformToFloat(cid_transform->f) * font_size;
197 text_char_pos.m_bGlyphAdjust = true;
198 }
199 }
200
201 return results;
202}
fxcrt::ByteString ByteString
Definition bytestring.h:180
std::vector< TextCharPos > GetCharPosList(pdfium::span< const uint32_t > char_codes, pdfium::span< const float > char_pos, CPDF_Font *font, float font_size)
static std::optional< StandardFont > GetStandardFontName(ByteString *name)
int GetGlyphWidth(uint32_t glyph_index) const
Definition cfx_font.cpp:251
CFX_SubstFont * GetSubstFont() const
Definition cfx_font.h:79
bool IsBuiltInGenericFont() const
uint16_t CIDFromCharCode(uint32_t charcode) const
const CIDTransform * GetCIDTransform(uint16_t cid) const
static float CIDTransformToFloat(uint8_t ch)
bool IsVertWriting() const override
virtual bool IsTrueTypeFont() const
Definition cpdf_font.cpp:66
virtual int GetCharWidthF(uint32_t charcode)=0
int FallbackGlyphFromCharcode(int fallbackFont, uint32_t charcode)
virtual CPDF_CIDFont * AsCIDFont()
virtual int GlyphFromCharCode(uint32_t charcode, bool *pVertGlyph)=0
virtual bool IsCIDFont() const
Definition cpdf_font.cpp:74
virtual WideString UnicodeFromCharCode(uint32_t charcode) const
CFX_Font * GetFont()
Definition cpdf_font.h:128
ByteString GetBaseFontName() const
Definition cpdf_font.h:98
virtual bool HasFontWidths() const
uint32_t FallbackFontFromCharcode(uint32_t charcode)
bool IsEmbedded() const
Definition cpdf_font.h:100
CFX_Font * GetFontFallback(int position)
uint32_t m_GlyphIndex
int32_t m_FallbackFontPosition
bool m_bGlyphAdjust
CFX_PTemplate< int16_t > CFX_Point16
CFX_PTemplate< float > CFX_PointF
fxcrt::WideString WideString
Definition widestring.h:207