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_textrenderer.h"
8
9 #include <algorithm>
10 #include <vector>
11
12 #include "core/fpdfapi/font/cpdf_font.h"
13 #include "core/fpdfapi/render/charposlist.h"
14 #include "core/fpdfapi/render/cpdf_renderoptions.h"
15 #include "core/fxge/cfx_graphstatedata.h"
16 #include "core/fxge/cfx_pathdata.h"
17 #include "core/fxge/cfx_renderdevice.h"
18 #include "core/fxge/cfx_textrenderoptions.h"
19 #include "core/fxge/fx_font.h"
20 #include "core/fxge/text_char_pos.h"
21
22 namespace {
23
GetFont(CPDF_Font * pFont,int32_t position)24 CFX_Font* GetFont(CPDF_Font* pFont, int32_t position) {
25 return position == -1 ? pFont->GetFont() : pFont->GetFontFallback(position);
26 }
27
GetTextRenderOptionsHelper(const CPDF_Font * pFont,const CPDF_RenderOptions & options)28 CFX_TextRenderOptions GetTextRenderOptionsHelper(
29 const CPDF_Font* pFont,
30 const CPDF_RenderOptions& options) {
31 CFX_TextRenderOptions text_options;
32
33 if (pFont->IsCIDFont())
34 text_options.font_is_cid = true;
35
36 if (options.GetOptions().bNoTextSmooth)
37 text_options.aliasing_type = CFX_TextRenderOptions::kAliasing;
38 else if (options.GetOptions().bClearType)
39 text_options.aliasing_type = CFX_TextRenderOptions::kLcd;
40
41 if (options.GetOptions().bNoNativeText)
42 text_options.native_text = false;
43
44 return text_options;
45 }
46
47 } // namespace
48
49 // static
DrawTextPath(CFX_RenderDevice * pDevice,pdfium::span<const uint32_t> char_codes,pdfium::span<const float> char_pos,CPDF_Font * pFont,float font_size,const CFX_Matrix & mtText2User,const CFX_Matrix * pUser2Device,const CFX_GraphStateData * pGraphState,FX_ARGB fill_argb,FX_ARGB stroke_argb,CFX_PathData * pClippingPath,const CFX_FillRenderOptions & fill_options)50 bool CPDF_TextRenderer::DrawTextPath(
51 CFX_RenderDevice* pDevice,
52 pdfium::span<const uint32_t> char_codes,
53 pdfium::span<const float> char_pos,
54 CPDF_Font* pFont,
55 float font_size,
56 const CFX_Matrix& mtText2User,
57 const CFX_Matrix* pUser2Device,
58 const CFX_GraphStateData* pGraphState,
59 FX_ARGB fill_argb,
60 FX_ARGB stroke_argb,
61 CFX_PathData* pClippingPath,
62 const CFX_FillRenderOptions& fill_options) {
63 std::vector<TextCharPos> pos =
64 GetCharPosList(char_codes, char_pos, pFont, font_size);
65 if (pos.empty())
66 return true;
67
68 bool bDraw = true;
69 int32_t fontPosition = pos[0].m_FallbackFontPosition;
70 size_t startIndex = 0;
71 for (size_t i = 0; i < pos.size(); ++i) {
72 int32_t curFontPosition = pos[i].m_FallbackFontPosition;
73 if (fontPosition == curFontPosition)
74 continue;
75
76 CFX_Font* font = GetFont(pFont, fontPosition);
77 if (!pDevice->DrawTextPath(i - startIndex, &pos[startIndex], font,
78 font_size, mtText2User, pUser2Device,
79 pGraphState, fill_argb, stroke_argb,
80 pClippingPath, fill_options)) {
81 bDraw = false;
82 }
83 fontPosition = curFontPosition;
84 startIndex = i;
85 }
86 CFX_Font* font = GetFont(pFont, fontPosition);
87 if (!pDevice->DrawTextPath(pos.size() - startIndex, &pos[startIndex], font,
88 font_size, mtText2User, pUser2Device, pGraphState,
89 fill_argb, stroke_argb, pClippingPath,
90 fill_options)) {
91 bDraw = false;
92 }
93 return bDraw;
94 }
95
96 // static
DrawTextString(CFX_RenderDevice * pDevice,float origin_x,float origin_y,CPDF_Font * pFont,float font_size,const CFX_Matrix & matrix,const ByteString & str,FX_ARGB fill_argb,const CPDF_RenderOptions & options)97 void CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice,
98 float origin_x,
99 float origin_y,
100 CPDF_Font* pFont,
101 float font_size,
102 const CFX_Matrix& matrix,
103 const ByteString& str,
104 FX_ARGB fill_argb,
105 const CPDF_RenderOptions& options) {
106 if (pFont->IsType3Font())
107 return;
108
109 int nChars = pFont->CountChar(str.AsStringView());
110 if (nChars <= 0)
111 return;
112
113 size_t offset = 0;
114 std::vector<uint32_t> codes;
115 std::vector<float> positions;
116 codes.resize(nChars);
117 positions.resize(nChars - 1);
118 float cur_pos = 0;
119 for (int i = 0; i < nChars; i++) {
120 codes[i] = pFont->GetNextChar(str.AsStringView(), &offset);
121 if (i)
122 positions[i - 1] = cur_pos;
123 cur_pos += pFont->GetCharWidthF(codes[i]) * font_size / 1000;
124 }
125 CFX_Matrix new_matrix = matrix;
126 new_matrix.e = origin_x;
127 new_matrix.f = origin_y;
128 DrawNormalText(pDevice, codes, positions, pFont, font_size, new_matrix,
129 fill_argb, options);
130 }
131
132 // static
DrawNormalText(CFX_RenderDevice * pDevice,pdfium::span<const uint32_t> char_codes,pdfium::span<const float> char_pos,CPDF_Font * pFont,float font_size,const CFX_Matrix & mtText2Device,FX_ARGB fill_argb,const CPDF_RenderOptions & options)133 bool CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice,
134 pdfium::span<const uint32_t> char_codes,
135 pdfium::span<const float> char_pos,
136 CPDF_Font* pFont,
137 float font_size,
138 const CFX_Matrix& mtText2Device,
139 FX_ARGB fill_argb,
140 const CPDF_RenderOptions& options) {
141 std::vector<TextCharPos> pos =
142 GetCharPosList(char_codes, char_pos, pFont, font_size);
143 if (pos.empty())
144 return true;
145
146 CFX_TextRenderOptions text_options =
147 GetTextRenderOptionsHelper(pFont, options);
148 bool bDraw = true;
149 int32_t fontPosition = pos[0].m_FallbackFontPosition;
150 size_t startIndex = 0;
151 for (size_t i = 0; i < pos.size(); ++i) {
152 int32_t curFontPosition = pos[i].m_FallbackFontPosition;
153 if (fontPosition == curFontPosition)
154 continue;
155
156 CFX_Font* font = GetFont(pFont, fontPosition);
157 if (!pDevice->DrawNormalText(i - startIndex, &pos[startIndex], font,
158 font_size, mtText2Device, fill_argb,
159 text_options)) {
160 bDraw = false;
161 }
162 fontPosition = curFontPosition;
163 startIndex = i;
164 }
165 CFX_Font* font = GetFont(pFont, fontPosition);
166 if (!pDevice->DrawNormalText(pos.size() - startIndex, &pos[startIndex], font,
167 font_size, mtText2Device, fill_argb,
168 text_options)) {
169 bDraw = false;
170 }
171 return bDraw;
172 }
173