Home | History | Annotate | Download | only in fxedit
      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 
     11 CFX_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 
     39 static CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) {
     40   if (strWords.GetLength() > 0)
     41     return PDF_EncodeString(strWords) + " Tj\n";
     42 
     43   return "";
     44 }
     45 
     46 static 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 
     61 CFX_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 
    177 CFX_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