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