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
11 #include "core/fpdfapi/font/cpdf_font.h"
12 #include "core/fpdfapi/render/cpdf_charposlist.h"
13 #include "core/fpdfapi/render/cpdf_renderoptions.h"
14 #include "core/fxge/cfx_graphstatedata.h"
15 #include "core/fxge/cfx_pathdata.h"
16 #include "core/fxge/cfx_renderdevice.h"
17
18 // static
DrawTextPath(CFX_RenderDevice * pDevice,const std::vector<uint32_t> & charCodes,const std::vector<FX_FLOAT> & charPos,CPDF_Font * pFont,FX_FLOAT font_size,const CFX_Matrix * pText2User,const CFX_Matrix * pUser2Device,const CFX_GraphStateData * pGraphState,FX_ARGB fill_argb,FX_ARGB stroke_argb,CFX_PathData * pClippingPath,int nFlag)19 bool CPDF_TextRenderer::DrawTextPath(CFX_RenderDevice* pDevice,
20 const std::vector<uint32_t>& charCodes,
21 const std::vector<FX_FLOAT>& charPos,
22 CPDF_Font* pFont,
23 FX_FLOAT font_size,
24 const CFX_Matrix* pText2User,
25 const CFX_Matrix* pUser2Device,
26 const CFX_GraphStateData* pGraphState,
27 FX_ARGB fill_argb,
28 FX_ARGB stroke_argb,
29 CFX_PathData* pClippingPath,
30 int nFlag) {
31 CPDF_CharPosList CharPosList;
32 CharPosList.Load(charCodes, charPos, pFont, font_size);
33 if (CharPosList.m_nChars == 0)
34 return true;
35
36 bool bDraw = true;
37 int32_t fontPosition = CharPosList.m_pCharPos[0].m_FallbackFontPosition;
38 uint32_t startIndex = 0;
39 for (uint32_t i = 0; i < CharPosList.m_nChars; i++) {
40 int32_t curFontPosition = CharPosList.m_pCharPos[i].m_FallbackFontPosition;
41 if (fontPosition == curFontPosition)
42 continue;
43 auto* font = fontPosition == -1
44 ? &pFont->m_Font
45 : pFont->m_FontFallbacks[fontPosition].get();
46 if (!pDevice->DrawTextPath(i - startIndex,
47 CharPosList.m_pCharPos + startIndex, font,
48 font_size, pText2User, pUser2Device, pGraphState,
49 fill_argb, stroke_argb, pClippingPath, nFlag)) {
50 bDraw = false;
51 }
52 fontPosition = curFontPosition;
53 startIndex = i;
54 }
55 auto* font = fontPosition == -1 ? &pFont->m_Font
56 : pFont->m_FontFallbacks[fontPosition].get();
57 if (!pDevice->DrawTextPath(CharPosList.m_nChars - startIndex,
58 CharPosList.m_pCharPos + startIndex, font,
59 font_size, pText2User, pUser2Device, pGraphState,
60 fill_argb, stroke_argb, pClippingPath, nFlag)) {
61 bDraw = false;
62 }
63 return bDraw;
64 }
65
66 // static
DrawTextString(CFX_RenderDevice * pDevice,FX_FLOAT origin_x,FX_FLOAT origin_y,CPDF_Font * pFont,FX_FLOAT font_size,const CFX_Matrix * pMatrix,const CFX_ByteString & str,FX_ARGB fill_argb,const CFX_GraphStateData * pGraphState,const CPDF_RenderOptions * pOptions)67 void CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice,
68 FX_FLOAT origin_x,
69 FX_FLOAT origin_y,
70 CPDF_Font* pFont,
71 FX_FLOAT font_size,
72 const CFX_Matrix* pMatrix,
73 const CFX_ByteString& str,
74 FX_ARGB fill_argb,
75 const CFX_GraphStateData* pGraphState,
76 const CPDF_RenderOptions* pOptions) {
77 if (pFont->IsType3Font())
78 return;
79
80 int nChars = pFont->CountChar(str.c_str(), str.GetLength());
81 if (nChars <= 0)
82 return;
83
84 int offset = 0;
85 std::vector<uint32_t> codes;
86 std::vector<FX_FLOAT> positions;
87 codes.resize(nChars);
88 positions.resize(nChars - 1);
89 FX_FLOAT cur_pos = 0;
90 for (int i = 0; i < nChars; i++) {
91 codes[i] = pFont->GetNextChar(str.c_str(), str.GetLength(), offset);
92 if (i)
93 positions[i - 1] = cur_pos;
94 cur_pos += pFont->GetCharWidthF(codes[i]) * font_size / 1000;
95 }
96 CFX_Matrix matrix;
97 if (pMatrix)
98 matrix = *pMatrix;
99
100 matrix.e = origin_x;
101 matrix.f = origin_y;
102
103 DrawNormalText(pDevice, codes, positions, pFont, font_size, &matrix,
104 fill_argb, pOptions);
105 }
106
107 // static
DrawNormalText(CFX_RenderDevice * pDevice,const std::vector<uint32_t> & charCodes,const std::vector<FX_FLOAT> & charPos,CPDF_Font * pFont,FX_FLOAT font_size,const CFX_Matrix * pText2Device,FX_ARGB fill_argb,const CPDF_RenderOptions * pOptions)108 bool CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice,
109 const std::vector<uint32_t>& charCodes,
110 const std::vector<FX_FLOAT>& charPos,
111 CPDF_Font* pFont,
112 FX_FLOAT font_size,
113 const CFX_Matrix* pText2Device,
114 FX_ARGB fill_argb,
115 const CPDF_RenderOptions* pOptions) {
116 CPDF_CharPosList CharPosList;
117 CharPosList.Load(charCodes, charPos, pFont, font_size);
118 if (CharPosList.m_nChars == 0)
119 return true;
120 int FXGE_flags = 0;
121 if (pOptions) {
122 uint32_t dwFlags = pOptions->m_Flags;
123 if (dwFlags & RENDER_CLEARTYPE) {
124 FXGE_flags |= FXTEXT_CLEARTYPE;
125 if (dwFlags & RENDER_BGR_STRIPE)
126 FXGE_flags |= FXTEXT_BGR_STRIPE;
127 }
128 if (dwFlags & RENDER_NOTEXTSMOOTH)
129 FXGE_flags |= FXTEXT_NOSMOOTH;
130 if (dwFlags & RENDER_PRINTGRAPHICTEXT)
131 FXGE_flags |= FXTEXT_PRINTGRAPHICTEXT;
132 if (dwFlags & RENDER_NO_NATIVETEXT)
133 FXGE_flags |= FXTEXT_NO_NATIVETEXT;
134 if (dwFlags & RENDER_PRINTIMAGETEXT)
135 FXGE_flags |= FXTEXT_PRINTIMAGETEXT;
136 } else {
137 FXGE_flags = FXTEXT_CLEARTYPE;
138 }
139 if (pFont->IsCIDFont())
140 FXGE_flags |= FXFONT_CIDFONT;
141 bool bDraw = true;
142 int32_t fontPosition = CharPosList.m_pCharPos[0].m_FallbackFontPosition;
143 uint32_t startIndex = 0;
144 for (uint32_t i = 0; i < CharPosList.m_nChars; i++) {
145 int32_t curFontPosition = CharPosList.m_pCharPos[i].m_FallbackFontPosition;
146 if (fontPosition == curFontPosition)
147 continue;
148 auto* font = fontPosition == -1
149 ? &pFont->m_Font
150 : pFont->m_FontFallbacks[fontPosition].get();
151 if (!pDevice->DrawNormalText(
152 i - startIndex, CharPosList.m_pCharPos + startIndex, font,
153 font_size, pText2Device, fill_argb, FXGE_flags)) {
154 bDraw = false;
155 }
156 fontPosition = curFontPosition;
157 startIndex = i;
158 }
159 auto* font = fontPosition == -1 ? &pFont->m_Font
160 : pFont->m_FontFallbacks[fontPosition].get();
161 if (!pDevice->DrawNormalText(CharPosList.m_nChars - startIndex,
162 CharPosList.m_pCharPos + startIndex, font,
163 font_size, pText2Device, fill_argb,
164 FXGE_flags)) {
165 bDraw = false;
166 }
167 return bDraw;
168 }
169