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/include/fpdfapi/fpdf_resource.h" 8#include "fpdfsdk/include/fxedit/fx_edit.h" 9#include "fpdfsdk/include/fxedit/fxet_edit.h" 10 11CFX_ByteString GetPDFWordString(IFX_Edit_FontMap* pFontMap, 12 int32_t nFontIndex, 13 FX_WORD Word, 14 FX_WORD SubWord) { 15 CFX_ByteString sWord; 16 if (CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex)) { 17 if (SubWord > 0) { 18 Word = SubWord; 19 } else { 20 FX_DWORD dwCharCode = -1; 21 22 if (pPDFFont->IsUnicodeCompatible()) 23 dwCharCode = pPDFFont->CharCodeFromUnicode(Word); 24 else 25 dwCharCode = pFontMap->CharCodeFromUnicode(nFontIndex, Word); 26 27 if (dwCharCode > 0) { 28 pPDFFont->AppendChar(sWord, dwCharCode); 29 return sWord; 30 } 31 } 32 33 pPDFFont->AppendChar(sWord, Word); 34 } 35 36 return sWord; 37} 38 39static CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) { 40 if (strWords.GetLength() > 0) 41 return PDF_EncodeString(strWords) + " Tj\n"; 42 43 return ""; 44} 45 46static CFX_ByteString GetFontSetString(IFX_Edit_FontMap* pFontMap, 47 int32_t nFontIndex, 48 FX_FLOAT fFontSize) { 49 CFX_ByteTextBuf sRet; 50 51 if (pFontMap) { 52 CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); 53 54 if (sFontAlias.GetLength() > 0 && fFontSize > 0) 55 sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n"; 56 } 57 58 return sRet.GetByteString(); 59} 60 61CFX_ByteString IFX_Edit::GetEditAppearanceStream( 62 IFX_Edit* pEdit, 63 const CPDF_Point& ptOffset, 64 const CPVT_WordRange* pRange /* = NULL*/, 65 FX_BOOL bContinuous /* = TRUE*/, 66 FX_WORD SubWord /* = 0*/) { 67 CFX_ByteTextBuf sEditStream, sWords; 68 69 CPDF_Point ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f); 70 int32_t nCurFontIndex = -1; 71 72 if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) { 73 if (pRange) 74 pIterator->SetAt(pRange->BeginPos); 75 else 76 pIterator->SetAt(0); 77 78 CPVT_WordPlace oldplace; 79 80 while (pIterator->NextWord()) { 81 CPVT_WordPlace place = pIterator->GetAt(); 82 83 if (pRange && place.WordCmp(pRange->EndPos) > 0) 84 break; 85 86 if (bContinuous) { 87 if (place.LineCmp(oldplace) != 0) { 88 if (sWords.GetSize() > 0) { 89 sEditStream << GetWordRenderString(sWords.GetByteString()); 90 sWords.Clear(); 91 } 92 93 CPVT_Word word; 94 if (pIterator->GetWord(word)) { 95 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, 96 word.ptWord.y + ptOffset.y); 97 } else { 98 CPVT_Line line; 99 pIterator->GetLine(line); 100 ptNew = CPDF_Point(line.ptLine.x + ptOffset.x, 101 line.ptLine.y + ptOffset.y); 102 } 103 104 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { 105 sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y 106 << " Td\n"; 107 108 ptOld = ptNew; 109 } 110 } 111 112 CPVT_Word word; 113 if (pIterator->GetWord(word)) { 114 if (word.nFontIndex != nCurFontIndex) { 115 if (sWords.GetSize() > 0) { 116 sEditStream << GetWordRenderString(sWords.GetByteString()); 117 sWords.Clear(); 118 } 119 sEditStream << GetFontSetString(pEdit->GetFontMap(), 120 word.nFontIndex, word.fFontSize); 121 nCurFontIndex = word.nFontIndex; 122 } 123 124 sWords << GetPDFWordString(pEdit->GetFontMap(), nCurFontIndex, 125 word.Word, SubWord); 126 } 127 128 oldplace = place; 129 } else { 130 CPVT_Word word; 131 if (pIterator->GetWord(word)) { 132 ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, 133 word.ptWord.y + ptOffset.y); 134 135 if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { 136 sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y 137 << " Td\n"; 138 ptOld = ptNew; 139 } 140 141 if (word.nFontIndex != nCurFontIndex) { 142 sEditStream << GetFontSetString(pEdit->GetFontMap(), 143 word.nFontIndex, word.fFontSize); 144 nCurFontIndex = word.nFontIndex; 145 } 146 147 sEditStream << GetWordRenderString(GetPDFWordString( 148 pEdit->GetFontMap(), nCurFontIndex, word.Word, SubWord)); 149 } 150 } 151 } 152 153 if (sWords.GetSize() > 0) { 154 sEditStream << GetWordRenderString(sWords.GetByteString()); 155 sWords.Clear(); 156 } 157 } 158 159 CFX_ByteTextBuf sAppStream; 160 if (sEditStream.GetSize() > 0) { 161 int32_t nHorzScale = pEdit->GetHorzScale(); 162 if (nHorzScale != 100) { 163 sAppStream << nHorzScale << " Tz\n"; 164 } 165 166 FX_FLOAT fCharSpace = pEdit->GetCharSpace(); 167 if (!FX_EDIT_IsFloatZero(fCharSpace)) { 168 sAppStream << fCharSpace << " Tc\n"; 169 } 170 171 sAppStream << sEditStream; 172 } 173 174 return sAppStream.GetByteString(); 175} 176 177CFX_ByteString IFX_Edit::GetSelectAppearanceStream( 178 IFX_Edit* pEdit, 179 const CPDF_Point& ptOffset, 180 const CPVT_WordRange* pRange) { 181 CFX_ByteTextBuf sRet; 182 183 if (pRange && pRange->IsExist()) { 184 if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) { 185 pIterator->SetAt(pRange->BeginPos); 186 187 while (pIterator->NextWord()) { 188 CPVT_WordPlace place = pIterator->GetAt(); 189 190 if (pRange && place.WordCmp(pRange->EndPos) > 0) 191 break; 192 193 CPVT_Word word; 194 CPVT_Line line; 195 if (pIterator->GetWord(word) && pIterator->GetLine(line)) { 196 sRet << word.ptWord.x + ptOffset.x << " " 197 << line.ptLine.y + line.fLineDescent << " " << word.fWidth << " " 198 << line.fLineAscent - line.fLineDescent << " re\nf\n"; 199 } 200 } 201 } 202 } 203 204 return sRet.GetByteString(); 205} 206