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