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