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 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 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 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 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