• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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