|  | // Copyright 2014 PDFium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 
|  |  | 
|  | #include "../../include/fxedit/fxet_stub.h" | 
|  | #include "../../include/fxedit/fx_edit.h" | 
|  | #include "../../include/fxedit/fxet_edit.h" | 
|  |  | 
|  | CFX_ByteString GetPDFWordString(IFX_Edit_FontMap* pFontMap, | 
|  | int32_t nFontIndex, | 
|  | FX_WORD Word, | 
|  | FX_WORD SubWord) { | 
|  | ASSERT(pFontMap != NULL); | 
|  |  | 
|  | CFX_ByteString sWord; | 
|  |  | 
|  | if (CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex)) { | 
|  | if (SubWord > 0) { | 
|  | Word = SubWord; | 
|  | } else { | 
|  | FX_DWORD dwCharCode = -1; | 
|  |  | 
|  | if (pPDFFont->IsUnicodeCompatible()) | 
|  | dwCharCode = pPDFFont->CharCodeFromUnicode(Word); | 
|  | else | 
|  | dwCharCode = pFontMap->CharCodeFromUnicode(nFontIndex, Word); | 
|  |  | 
|  | if (dwCharCode > 0) { | 
|  | pPDFFont->AppendChar(sWord, dwCharCode); | 
|  | return sWord; | 
|  | } | 
|  | } | 
|  |  | 
|  | pPDFFont->AppendChar(sWord, Word); | 
|  | } | 
|  |  | 
|  | return sWord; | 
|  | } | 
|  |  | 
|  | static CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) { | 
|  | if (strWords.GetLength() > 0) | 
|  | return PDF_EncodeString(strWords) + " Tj\n"; | 
|  |  | 
|  | return ""; | 
|  | } | 
|  |  | 
|  | static CFX_ByteString GetFontSetString(IFX_Edit_FontMap* pFontMap, | 
|  | int32_t nFontIndex, | 
|  | FX_FLOAT fFontSize) { | 
|  | CFX_ByteTextBuf sRet; | 
|  |  | 
|  | if (pFontMap) { | 
|  | CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); | 
|  |  | 
|  | if (sFontAlias.GetLength() > 0 && fFontSize > 0) | 
|  | sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n"; | 
|  | } | 
|  |  | 
|  | return sRet.GetByteString(); | 
|  | } | 
|  |  | 
|  | CFX_ByteString IFX_Edit::GetEditAppearanceStream( | 
|  | IFX_Edit* pEdit, | 
|  | const CPDF_Point& ptOffset, | 
|  | const CPVT_WordRange* pRange /* = NULL*/, | 
|  | FX_BOOL bContinuous /* = TRUE*/, | 
|  | FX_WORD SubWord /* = 0*/) { | 
|  | CFX_ByteTextBuf sEditStream, sWords; | 
|  |  | 
|  | CPDF_Point ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f); | 
|  | int32_t nCurFontIndex = -1; | 
|  |  | 
|  | if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) { | 
|  | if (pRange) | 
|  | pIterator->SetAt(pRange->BeginPos); | 
|  | else | 
|  | pIterator->SetAt(0); | 
|  |  | 
|  | CPVT_WordPlace oldplace; | 
|  |  | 
|  | while (pIterator->NextWord()) { | 
|  | CPVT_WordPlace place = pIterator->GetAt(); | 
|  |  | 
|  | if (pRange && place.WordCmp(pRange->EndPos) > 0) | 
|  | break; | 
|  |  | 
|  | if (bContinuous) { | 
|  | if (place.LineCmp(oldplace) != 0) { | 
|  | if (sWords.GetSize() > 0) { | 
|  | sEditStream << GetWordRenderString(sWords.GetByteString()); | 
|  | sWords.Clear(); | 
|  | } | 
|  |  | 
|  | CPVT_Word word; | 
|  | if (pIterator->GetWord(word)) { | 
|  | ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, | 
|  | word.ptWord.y + ptOffset.y); | 
|  | } else { | 
|  | CPVT_Line line; | 
|  | pIterator->GetLine(line); | 
|  | ptNew = CPDF_Point(line.ptLine.x + ptOffset.x, | 
|  | line.ptLine.y + ptOffset.y); | 
|  | } | 
|  |  | 
|  | if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { | 
|  | sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y | 
|  | << " Td\n"; | 
|  |  | 
|  | ptOld = ptNew; | 
|  | } | 
|  | } | 
|  |  | 
|  | CPVT_Word word; | 
|  | if (pIterator->GetWord(word)) { | 
|  | if (word.nFontIndex != nCurFontIndex) { | 
|  | if (sWords.GetSize() > 0) { | 
|  | sEditStream << GetWordRenderString(sWords.GetByteString()); | 
|  | sWords.Clear(); | 
|  | } | 
|  | sEditStream << GetFontSetString(pEdit->GetFontMap(), | 
|  | word.nFontIndex, word.fFontSize); | 
|  | nCurFontIndex = word.nFontIndex; | 
|  | } | 
|  |  | 
|  | sWords << GetPDFWordString(pEdit->GetFontMap(), nCurFontIndex, | 
|  | word.Word, SubWord); | 
|  | } | 
|  |  | 
|  | oldplace = place; | 
|  | } else { | 
|  | CPVT_Word word; | 
|  | if (pIterator->GetWord(word)) { | 
|  | ptNew = CPDF_Point(word.ptWord.x + ptOffset.x, | 
|  | word.ptWord.y + ptOffset.y); | 
|  |  | 
|  | if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) { | 
|  | sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y | 
|  | << " Td\n"; | 
|  | ptOld = ptNew; | 
|  | } | 
|  |  | 
|  | if (word.nFontIndex != nCurFontIndex) { | 
|  | sEditStream << GetFontSetString(pEdit->GetFontMap(), | 
|  | word.nFontIndex, word.fFontSize); | 
|  | nCurFontIndex = word.nFontIndex; | 
|  | } | 
|  |  | 
|  | sEditStream << GetWordRenderString(GetPDFWordString( | 
|  | pEdit->GetFontMap(), nCurFontIndex, word.Word, SubWord)); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | if (sWords.GetSize() > 0) { | 
|  | sEditStream << GetWordRenderString(sWords.GetByteString()); | 
|  | sWords.Clear(); | 
|  | } | 
|  | } | 
|  |  | 
|  | CFX_ByteTextBuf sAppStream; | 
|  | if (sEditStream.GetSize() > 0) { | 
|  | int32_t nHorzScale = pEdit->GetHorzScale(); | 
|  | if (nHorzScale != 100) { | 
|  | sAppStream << nHorzScale << " Tz\n"; | 
|  | } | 
|  |  | 
|  | FX_FLOAT fCharSpace = pEdit->GetCharSpace(); | 
|  | if (!FX_EDIT_IsFloatZero(fCharSpace)) { | 
|  | sAppStream << fCharSpace << " Tc\n"; | 
|  | } | 
|  |  | 
|  | sAppStream << sEditStream; | 
|  | } | 
|  |  | 
|  | return sAppStream.GetByteString(); | 
|  | } | 
|  |  | 
|  | CFX_ByteString IFX_Edit::GetSelectAppearanceStream( | 
|  | IFX_Edit* pEdit, | 
|  | const CPDF_Point& ptOffset, | 
|  | const CPVT_WordRange* pRange /*= NULL*/) { | 
|  | CFX_ByteTextBuf sRet; | 
|  |  | 
|  | if (pRange && pRange->IsExist()) { | 
|  | if (IFX_Edit_Iterator* pIterator = pEdit->GetIterator()) { | 
|  | pIterator->SetAt(pRange->BeginPos); | 
|  |  | 
|  | while (pIterator->NextWord()) { | 
|  | CPVT_WordPlace place = pIterator->GetAt(); | 
|  |  | 
|  | if (pRange && place.WordCmp(pRange->EndPos) > 0) | 
|  | break; | 
|  |  | 
|  | CPVT_Word word; | 
|  | CPVT_Line line; | 
|  | if (pIterator->GetWord(word) && pIterator->GetLine(line)) { | 
|  | sRet << word.ptWord.x + ptOffset.x << " " | 
|  | << line.ptLine.y + line.fLineDescent << " " << word.fWidth << " " | 
|  | << line.fLineAscent - line.fLineDescent << " re\nf\n"; | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | return sRet.GetByteString(); | 
|  | } |