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/render/cpdf_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/fxge/cfx_substfont.h"
13 #include "core/fxge/text_char_pos.h"
14
CPDF_CharPosList(const std::vector<uint32_t> & charCodes,const std::vector<float> & charPos,CPDF_Font * pFont,float font_size)15 CPDF_CharPosList::CPDF_CharPosList(const std::vector<uint32_t>& charCodes,
16 const std::vector<float>& charPos,
17 CPDF_Font* pFont,
18 float font_size) {
19 m_CharPos.reserve(charCodes.size());
20 CPDF_CIDFont* pCIDFont = pFont->AsCIDFont();
21 bool bVertWriting = pCIDFont && pCIDFont->IsVertWriting();
22 bool bToUnicode = !!pFont->GetFontDict()->GetStreamFor("ToUnicode");
23 for (size_t i = 0; i < charCodes.size(); ++i) {
24 uint32_t CharCode = charCodes[i];
25 if (CharCode == static_cast<uint32_t>(-1))
26 continue;
27
28 bool bVert = false;
29 m_CharPos.emplace_back();
30 TextCharPos& charpos = m_CharPos.back();
31 if (pCIDFont)
32 charpos.m_bFontStyle = true;
33 WideString unicode = pFont->UnicodeFromCharCode(CharCode);
34 charpos.m_Unicode = !unicode.IsEmpty() ? unicode[0] : CharCode;
35 charpos.m_GlyphIndex = pFont->GlyphFromCharCode(CharCode, &bVert);
36 uint32_t GlyphID = charpos.m_GlyphIndex;
37 #if defined(OS_MACOSX)
38 charpos.m_ExtGID = pFont->GlyphFromCharCodeExt(CharCode);
39 GlyphID = charpos.m_ExtGID != static_cast<uint32_t>(-1)
40 ? charpos.m_ExtGID
41 : charpos.m_GlyphIndex;
42 #endif
43 bool bIsInvalidGlyph = GlyphID == static_cast<uint32_t>(-1);
44 bool bIsTrueTypeZeroGlyph = GlyphID == 0 && pFont->IsTrueTypeFont();
45 bool bUseFallbackFont = false;
46 if (bIsInvalidGlyph || bIsTrueTypeZeroGlyph) {
47 charpos.m_FallbackFontPosition =
48 pFont->FallbackFontFromCharcode(CharCode);
49 charpos.m_GlyphIndex = pFont->FallbackGlyphFromCharcode(
50 charpos.m_FallbackFontPosition, CharCode);
51 if (bIsTrueTypeZeroGlyph &&
52 charpos.m_GlyphIndex == static_cast<uint32_t>(-1)) {
53 // For a TrueType font character, when finding the glyph from the
54 // fallback font fails, switch back to using the original font.
55
56 // When keyword "ToUnicode" exists in the PDF file, it indicates
57 // a "ToUnicode" mapping file is used to convert from CIDs (which
58 // begins at decimal 0) to Unicode code. (See ToUnicode Mapping File
59 // Tutorial - Adobe
60 // https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/5411.ToUnicode.pdf
61 // and
62 // https://www.freetype.org/freetype2/docs/tutorial/step1.html#section-6)
63 if (bToUnicode)
64 charpos.m_GlyphIndex = 0;
65 } else {
66 bUseFallbackFont = true;
67 }
68 }
69 CFX_Font* pCurrentFont;
70 if (bUseFallbackFont) {
71 pCurrentFont = pFont->GetFontFallback(charpos.m_FallbackFontPosition);
72 #if defined(OS_MACOSX)
73 charpos.m_ExtGID = charpos.m_GlyphIndex;
74 #endif
75 } else {
76 pCurrentFont = pFont->GetFont();
77 charpos.m_FallbackFontPosition = -1;
78 }
79
80 if (!pFont->IsEmbedded() && !pFont->IsCIDFont())
81 charpos.m_FontCharWidth = pFont->GetCharWidthF(CharCode);
82 else
83 charpos.m_FontCharWidth = 0;
84
85 charpos.m_Origin = CFX_PointF(i > 0 ? charPos[i - 1] : 0, 0);
86 charpos.m_bGlyphAdjust = false;
87
88 float scalingFactor = 1.0f;
89 if (!pFont->IsEmbedded() && pFont->HasFontWidths() && !bVertWriting &&
90 !pCurrentFont->GetSubstFont()->m_bFlagMM) {
91 uint32_t pdfGlyphWidth = pFont->GetCharWidthF(CharCode);
92 uint32_t ftGlyphWidth =
93 pCurrentFont ? pCurrentFont->GetGlyphWidth(charpos.m_GlyphIndex) : 0;
94 if (ftGlyphWidth && pdfGlyphWidth > ftGlyphWidth + 1) {
95 // Move the initial x position by half of the excess (transformed to
96 // text space coordinates).
97 charpos.m_Origin.x +=
98 (pdfGlyphWidth - ftGlyphWidth) * font_size / 2000.0f;
99 } else if (pdfGlyphWidth && ftGlyphWidth &&
100 pdfGlyphWidth < ftGlyphWidth) {
101 scalingFactor = static_cast<float>(pdfGlyphWidth) / ftGlyphWidth;
102 charpos.m_AdjustMatrix[0] = scalingFactor;
103 charpos.m_AdjustMatrix[1] = 0.0f;
104 charpos.m_AdjustMatrix[2] = 0.0f;
105 charpos.m_AdjustMatrix[3] = 1.0f;
106 charpos.m_bGlyphAdjust = true;
107 }
108 }
109 if (!pCIDFont)
110 continue;
111
112 uint16_t CID = pCIDFont->CIDFromCharCode(CharCode);
113 if (bVertWriting) {
114 charpos.m_Origin = CFX_PointF(0, charpos.m_Origin.x);
115
116 short vx;
117 short vy;
118 pCIDFont->GetVertOrigin(CID, vx, vy);
119 charpos.m_Origin.x -= font_size * vx / 1000;
120 charpos.m_Origin.y -= font_size * vy / 1000;
121 }
122
123 const uint8_t* pTransform = pCIDFont->GetCIDTransform(CID);
124 if (pTransform && !bVert) {
125 charpos.m_AdjustMatrix[0] =
126 pCIDFont->CIDTransformToFloat(pTransform[0]) * scalingFactor;
127 charpos.m_AdjustMatrix[1] =
128 pCIDFont->CIDTransformToFloat(pTransform[1]) * scalingFactor;
129 charpos.m_AdjustMatrix[2] = pCIDFont->CIDTransformToFloat(pTransform[2]);
130 charpos.m_AdjustMatrix[3] = pCIDFont->CIDTransformToFloat(pTransform[3]);
131 charpos.m_Origin.x +=
132 pCIDFont->CIDTransformToFloat(pTransform[4]) * font_size;
133 charpos.m_Origin.y +=
134 pCIDFont->CIDTransformToFloat(pTransform[5]) * font_size;
135 charpos.m_bGlyphAdjust = true;
136 }
137 }
138 }
139
140 CPDF_CharPosList::~CPDF_CharPosList() = default;
141