OLD | NEW |
| (Empty) |
1 // Copyright 2014 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/render_int.h" | |
8 | |
9 #include <vector> | |
10 | |
11 #include "core/fpdfapi/font/cpdf_cidfont.h" | |
12 #include "core/fpdfapi/font/cpdf_font.h" | |
13 #include "core/fpdfapi/font/cpdf_type3char.h" | |
14 #include "core/fpdfapi/font/cpdf_type3font.h" | |
15 #include "core/fpdfapi/page/cpdf_docpagedata.h" | |
16 #include "core/fpdfapi/page/cpdf_form.h" | |
17 #include "core/fpdfapi/page/cpdf_imageobject.h" | |
18 #include "core/fpdfapi/page/cpdf_pageobject.h" | |
19 #include "core/fpdfapi/page/cpdf_pathobject.h" | |
20 #include "core/fpdfapi/page/cpdf_textobject.h" | |
21 #include "core/fpdfapi/parser/cpdf_dictionary.h" | |
22 #include "core/fpdfapi/parser/cpdf_document.h" | |
23 #include "core/fpdfapi/render/cpdf_charposlist.h" | |
24 #include "core/fpdfapi/render/cpdf_docrenderdata.h" | |
25 #include "core/fpdfapi/render/cpdf_renderoptions.h" | |
26 #include "core/fpdfapi/render/cpdf_renderstatus.h" | |
27 #include "core/fpdfapi/render/cpdf_textrenderer.h" | |
28 #include "core/fpdfapi/render/cpdf_type3cache.h" | |
29 #include "core/fxge/cfx_facecache.h" | |
30 #include "core/fxge/cfx_fxgedevice.h" | |
31 #include "core/fxge/cfx_gemodule.h" | |
32 #include "core/fxge/cfx_graphstatedata.h" | |
33 #include "core/fxge/cfx_pathdata.h" | |
34 #include "core/fxge/cfx_renderdevice.h" | |
35 #include "third_party/base/numerics/safe_math.h" | |
36 | |
37 // static | |
38 bool CPDF_TextRenderer::DrawTextPath(CFX_RenderDevice* pDevice, | |
39 int nChars, | |
40 uint32_t* pCharCodes, | |
41 FX_FLOAT* pCharPos, | |
42 CPDF_Font* pFont, | |
43 FX_FLOAT font_size, | |
44 const CFX_Matrix* pText2User, | |
45 const CFX_Matrix* pUser2Device, | |
46 const CFX_GraphStateData* pGraphState, | |
47 FX_ARGB fill_argb, | |
48 FX_ARGB stroke_argb, | |
49 CFX_PathData* pClippingPath, | |
50 int nFlag) { | |
51 CPDF_CharPosList CharPosList; | |
52 CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size); | |
53 if (CharPosList.m_nChars == 0) | |
54 return true; | |
55 bool bDraw = true; | |
56 int32_t fontPosition = CharPosList.m_pCharPos[0].m_FallbackFontPosition; | |
57 uint32_t startIndex = 0; | |
58 for (uint32_t i = 0; i < CharPosList.m_nChars; i++) { | |
59 int32_t curFontPosition = CharPosList.m_pCharPos[i].m_FallbackFontPosition; | |
60 if (fontPosition == curFontPosition) | |
61 continue; | |
62 auto* font = fontPosition == -1 | |
63 ? &pFont->m_Font | |
64 : pFont->m_FontFallbacks[fontPosition].get(); | |
65 if (!pDevice->DrawTextPath(i - startIndex, | |
66 CharPosList.m_pCharPos + startIndex, font, | |
67 font_size, pText2User, pUser2Device, pGraphState, | |
68 fill_argb, stroke_argb, pClippingPath, nFlag)) { | |
69 bDraw = false; | |
70 } | |
71 fontPosition = curFontPosition; | |
72 startIndex = i; | |
73 } | |
74 auto* font = fontPosition == -1 ? &pFont->m_Font | |
75 : pFont->m_FontFallbacks[fontPosition].get(); | |
76 if (!pDevice->DrawTextPath(CharPosList.m_nChars - startIndex, | |
77 CharPosList.m_pCharPos + startIndex, font, | |
78 font_size, pText2User, pUser2Device, pGraphState, | |
79 fill_argb, stroke_argb, pClippingPath, nFlag)) { | |
80 bDraw = false; | |
81 } | |
82 return bDraw; | |
83 } | |
84 | |
85 // static | |
86 void CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice, | |
87 FX_FLOAT origin_x, | |
88 FX_FLOAT origin_y, | |
89 CPDF_Font* pFont, | |
90 FX_FLOAT font_size, | |
91 const CFX_Matrix* pMatrix, | |
92 const CFX_ByteString& str, | |
93 FX_ARGB fill_argb, | |
94 FX_ARGB stroke_argb, | |
95 const CFX_GraphStateData* pGraphState, | |
96 const CPDF_RenderOptions* pOptions) { | |
97 if (pFont->IsType3Font()) | |
98 return; | |
99 | |
100 int nChars = pFont->CountChar(str.c_str(), str.GetLength()); | |
101 if (nChars <= 0) | |
102 return; | |
103 | |
104 int offset = 0; | |
105 uint32_t* pCharCodes; | |
106 FX_FLOAT* pCharPos; | |
107 std::vector<uint32_t> codes; | |
108 std::vector<FX_FLOAT> positions; | |
109 if (nChars == 1) { | |
110 pCharCodes = reinterpret_cast<uint32_t*>( | |
111 pFont->GetNextChar(str.c_str(), str.GetLength(), offset)); | |
112 pCharPos = nullptr; | |
113 } else { | |
114 codes.resize(nChars); | |
115 positions.resize(nChars - 1); | |
116 FX_FLOAT cur_pos = 0; | |
117 for (int i = 0; i < nChars; i++) { | |
118 codes[i] = pFont->GetNextChar(str.c_str(), str.GetLength(), offset); | |
119 if (i) | |
120 positions[i - 1] = cur_pos; | |
121 cur_pos += pFont->GetCharWidthF(codes[i]) * font_size / 1000; | |
122 } | |
123 pCharCodes = codes.data(); | |
124 pCharPos = positions.data(); | |
125 } | |
126 CFX_Matrix matrix; | |
127 if (pMatrix) | |
128 matrix = *pMatrix; | |
129 | |
130 matrix.e = origin_x; | |
131 matrix.f = origin_y; | |
132 | |
133 if (stroke_argb == 0) { | |
134 DrawNormalText(pDevice, nChars, pCharCodes, pCharPos, pFont, font_size, | |
135 &matrix, fill_argb, pOptions); | |
136 } else { | |
137 DrawTextPath(pDevice, nChars, pCharCodes, pCharPos, pFont, font_size, | |
138 &matrix, nullptr, pGraphState, fill_argb, stroke_argb, nullptr, | |
139 0); | |
140 } | |
141 } | |
142 | |
143 // static | |
144 bool CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice, | |
145 int nChars, | |
146 uint32_t* pCharCodes, | |
147 FX_FLOAT* pCharPos, | |
148 CPDF_Font* pFont, | |
149 FX_FLOAT font_size, | |
150 const CFX_Matrix* pText2Device, | |
151 FX_ARGB fill_argb, | |
152 const CPDF_RenderOptions* pOptions) { | |
153 CPDF_CharPosList CharPosList; | |
154 CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size); | |
155 if (CharPosList.m_nChars == 0) | |
156 return true; | |
157 int FXGE_flags = 0; | |
158 if (pOptions) { | |
159 uint32_t dwFlags = pOptions->m_Flags; | |
160 if (dwFlags & RENDER_CLEARTYPE) { | |
161 FXGE_flags |= FXTEXT_CLEARTYPE; | |
162 if (dwFlags & RENDER_BGR_STRIPE) { | |
163 FXGE_flags |= FXTEXT_BGR_STRIPE; | |
164 } | |
165 } | |
166 if (dwFlags & RENDER_NOTEXTSMOOTH) { | |
167 FXGE_flags |= FXTEXT_NOSMOOTH; | |
168 } | |
169 if (dwFlags & RENDER_PRINTGRAPHICTEXT) { | |
170 FXGE_flags |= FXTEXT_PRINTGRAPHICTEXT; | |
171 } | |
172 if (dwFlags & RENDER_NO_NATIVETEXT) { | |
173 FXGE_flags |= FXTEXT_NO_NATIVETEXT; | |
174 } | |
175 if (dwFlags & RENDER_PRINTIMAGETEXT) { | |
176 FXGE_flags |= FXTEXT_PRINTIMAGETEXT; | |
177 } | |
178 } else { | |
179 FXGE_flags = FXTEXT_CLEARTYPE; | |
180 } | |
181 if (pFont->IsCIDFont()) { | |
182 FXGE_flags |= FXFONT_CIDFONT; | |
183 } | |
184 bool bDraw = true; | |
185 int32_t fontPosition = CharPosList.m_pCharPos[0].m_FallbackFontPosition; | |
186 uint32_t startIndex = 0; | |
187 for (uint32_t i = 0; i < CharPosList.m_nChars; i++) { | |
188 int32_t curFontPosition = CharPosList.m_pCharPos[i].m_FallbackFontPosition; | |
189 if (fontPosition == curFontPosition) | |
190 continue; | |
191 auto* font = fontPosition == -1 | |
192 ? &pFont->m_Font | |
193 : pFont->m_FontFallbacks[fontPosition].get(); | |
194 if (!pDevice->DrawNormalText( | |
195 i - startIndex, CharPosList.m_pCharPos + startIndex, font, | |
196 font_size, pText2Device, fill_argb, FXGE_flags)) { | |
197 bDraw = false; | |
198 } | |
199 fontPosition = curFontPosition; | |
200 startIndex = i; | |
201 } | |
202 auto* font = fontPosition == -1 ? &pFont->m_Font | |
203 : pFont->m_FontFallbacks[fontPosition].get(); | |
204 if (!pDevice->DrawNormalText(CharPosList.m_nChars - startIndex, | |
205 CharPosList.m_pCharPos + startIndex, font, | |
206 font_size, pText2Device, fill_argb, | |
207 FXGE_flags)) { | |
208 bDraw = false; | |
209 } | |
210 return bDraw; | |
211 } | |
OLD | NEW |