Index: fpdfsdk/fxedit/fxet_edit.cpp |
diff --git a/fpdfsdk/fxedit/fxet_edit.cpp b/fpdfsdk/fxedit/fxet_edit.cpp |
index 550dd1d78fd0e621dd07cc4af4975dba417d80ed..2125eb8f0e09bf3b79e79196a3e9ad069f448c64 100644 |
--- a/fpdfsdk/fxedit/fxet_edit.cpp |
+++ b/fpdfsdk/fxedit/fxet_edit.cpp |
@@ -9,14 +9,183 @@ |
#include <algorithm> |
#include "core/fpdfapi/fpdf_font/include/cpdf_font.h" |
+#include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h" |
+#include "core/fpdfapi/fpdf_page/include/cpdf_pageobjectholder.h" |
+#include "core/fpdfapi/fpdf_page/include/cpdf_pathobject.h" |
+#include "core/fpdfapi/fpdf_page/include/cpdf_textobject.h" |
+#include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h" |
+#include "core/fpdfapi/fpdf_render/include/cpdf_textrenderer.h" |
#include "core/fpdfdoc/include/cpvt_section.h" |
#include "core/fpdfdoc/include/cpvt_word.h" |
#include "core/fpdfdoc/include/ipvt_fontmap.h" |
+#include "core/fxge/include/fx_ge.h" |
+#include "fpdfsdk/cfx_systemhandler.h" |
+#include "fpdfsdk/fxedit/include/fx_edit.h" |
+#include "fpdfsdk/fxedit/include/fxet_edit.h" |
+#include "fpdfsdk/pdfwindow/PWL_Edit.h" |
+#include "fpdfsdk/pdfwindow/PWL_EditCtrl.h" |
+ |
+#define PVTWORD_STYLE_UNDERLINE 0x0002L |
+#define PVTWORD_STYLE_CROSSOUT 0x0004L |
+#define PVTWORD_STYLE_BOLD 0x0020L |
+#define PVTWORD_STYLE_ITALIC 0x0040L |
namespace { |
const int kEditUndoMaxItems = 10000; |
+CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords) { |
+ if (strWords.GetLength() > 0) |
+ return PDF_EncodeString(strWords) + " Tj\n"; |
+ return CFX_ByteString(); |
+} |
+ |
+CFX_ByteString GetFontSetString(IPVT_FontMap* pFontMap, |
+ int32_t nFontIndex, |
+ FX_FLOAT fFontSize) { |
+ if (!pFontMap) |
+ return CFX_ByteString(); |
+ |
+ CFX_ByteString sFontAlias = pFontMap->GetPDFFontAlias(nFontIndex); |
+ if (sFontAlias.GetLength() <= 0 || fFontSize <= 0) |
+ return CFX_ByteString(); |
+ |
+ CFX_ByteTextBuf sRet; |
+ sRet << "/" << sFontAlias << " " << fFontSize << " Tf\n"; |
+ return sRet.MakeString(); |
+} |
+ |
+CFX_FloatRect GetUnderLineRect(const CPVT_Word& word) { |
+ return CFX_FloatRect(word.ptWord.x, word.ptWord.y + word.fDescent * 0.5f, |
+ word.ptWord.x + word.fWidth, |
+ word.ptWord.y + word.fDescent * 0.25f); |
+} |
+ |
+CFX_FloatRect GetCrossoutRect(const CPVT_Word& word) { |
+ return CFX_FloatRect(word.ptWord.x, |
+ word.ptWord.y + (word.fAscent + word.fDescent) * 0.5f + |
+ word.fDescent * 0.25f, |
+ word.ptWord.x + word.fWidth, |
+ word.ptWord.y + (word.fAscent + word.fDescent) * 0.5f); |
+} |
+ |
+void DrawTextString(CFX_RenderDevice* pDevice, |
+ const CFX_FloatPoint& pt, |
+ CPDF_Font* pFont, |
+ FX_FLOAT fFontSize, |
+ CFX_Matrix* pUser2Device, |
+ const CFX_ByteString& str, |
+ FX_ARGB crTextFill, |
+ FX_ARGB crTextStroke, |
+ int32_t nHorzScale) { |
+ FX_FLOAT x = pt.x, y = pt.y; |
+ pUser2Device->Transform(x, y); |
+ |
+ if (pFont) { |
+ if (nHorzScale != 100) { |
+ CFX_Matrix mt(nHorzScale / 100.0f, 0, 0, 1, 0, 0); |
+ mt.Concat(*pUser2Device); |
+ |
+ CPDF_RenderOptions ro; |
+ ro.m_Flags = RENDER_CLEARTYPE; |
+ ro.m_ColorMode = RENDER_COLOR_NORMAL; |
+ |
+ if (crTextStroke != 0) { |
+ CFX_FloatPoint pt1(0, 0), pt2(1, 0); |
+ pUser2Device->Transform(pt1.x, pt1.y); |
+ pUser2Device->Transform(pt2.x, pt2.y); |
+ CFX_GraphStateData gsd; |
+ gsd.m_LineWidth = |
+ (FX_FLOAT)FXSYS_fabs((pt2.x + pt2.y) - (pt1.x + pt1.y)); |
+ |
+ CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize, &mt, |
+ str, crTextFill, crTextStroke, &gsd, |
+ &ro); |
+ } else { |
+ CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize, &mt, |
+ str, crTextFill, 0, nullptr, &ro); |
+ } |
+ } else { |
+ CPDF_RenderOptions ro; |
+ ro.m_Flags = RENDER_CLEARTYPE; |
+ ro.m_ColorMode = RENDER_COLOR_NORMAL; |
+ |
+ if (crTextStroke != 0) { |
+ CFX_FloatPoint pt1(0, 0), pt2(1, 0); |
+ pUser2Device->Transform(pt1.x, pt1.y); |
+ pUser2Device->Transform(pt2.x, pt2.y); |
+ CFX_GraphStateData gsd; |
+ gsd.m_LineWidth = |
+ (FX_FLOAT)FXSYS_fabs((pt2.x + pt2.y) - (pt1.x + pt1.y)); |
+ |
+ CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize, |
+ pUser2Device, str, crTextFill, |
+ crTextStroke, &gsd, &ro); |
+ } else { |
+ CPDF_TextRenderer::DrawTextString(pDevice, x, y, pFont, fFontSize, |
+ pUser2Device, str, crTextFill, 0, |
+ nullptr, &ro); |
+ } |
+ } |
+ } |
+} |
+ |
+void AddRectToPageObjects(CPDF_PageObjectHolder* pObjectHolder, |
+ FX_COLORREF crFill, |
+ const CFX_FloatRect& rcFill) { |
+ std::unique_ptr<CPDF_PathObject> pPathObj(new CPDF_PathObject); |
+ CFX_PathData* pPathData = pPathObj->m_Path.GetModify(); |
+ pPathData->AppendRect(rcFill.left, rcFill.bottom, rcFill.right, rcFill.top); |
+ |
+ FX_FLOAT rgb[3]; |
+ rgb[0] = FXARGB_R(crFill) / 255.0f; |
+ rgb[1] = FXARGB_G(crFill) / 255.0f; |
+ rgb[2] = FXARGB_B(crFill) / 255.0f; |
+ pPathObj->m_ColorState.SetFillColor( |
+ CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); |
+ |
+ pPathObj->m_FillType = FXFILL_ALTERNATE; |
+ pPathObj->m_bStroke = FALSE; |
+ pObjectHolder->GetPageObjectList()->push_back(std::move(pPathObj)); |
+} |
+ |
+CPDF_TextObject* AddTextObjToPageObjects(CPDF_PageObjectHolder* pObjectHolder, |
+ FX_COLORREF crText, |
+ CPDF_Font* pFont, |
+ FX_FLOAT fFontSize, |
+ FX_FLOAT fCharSpace, |
+ int32_t nHorzScale, |
+ const CFX_FloatPoint& point, |
+ const CFX_ByteString& text) { |
+ std::unique_ptr<CPDF_TextObject> pTxtObj(new CPDF_TextObject); |
+ CPDF_TextStateData* pTextStateData = pTxtObj->m_TextState.GetModify(); |
+ pTextStateData->m_pFont = pFont; |
+ pTextStateData->m_FontSize = fFontSize; |
+ pTextStateData->m_CharSpace = fCharSpace; |
+ pTextStateData->m_WordSpace = 0; |
+ pTextStateData->m_TextMode = TextRenderingMode::MODE_FILL; |
+ pTextStateData->m_Matrix[0] = nHorzScale / 100.0f; |
+ pTextStateData->m_Matrix[1] = 0; |
+ pTextStateData->m_Matrix[2] = 0; |
+ pTextStateData->m_Matrix[3] = 1; |
+ |
+ FX_FLOAT rgb[3]; |
+ rgb[0] = FXARGB_R(crText) / 255.0f; |
+ rgb[1] = FXARGB_G(crText) / 255.0f; |
+ rgb[2] = FXARGB_B(crText) / 255.0f; |
+ pTxtObj->m_ColorState.SetFillColor( |
+ CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); |
+ pTxtObj->m_ColorState.SetStrokeColor( |
+ CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); |
+ |
+ pTxtObj->SetPosition(point.x, point.y); |
+ pTxtObj->SetText(text); |
+ |
+ CPDF_TextObject* pRet = pTxtObj.get(); |
+ pObjectHolder->GetPageObjectList()->push_back(std::move(pTxtObj)); |
+ return pRet; |
+} |
+ |
} // namespace |
CFX_Edit_Iterator::CFX_Edit_Iterator(CFX_Edit* pEdit, |
@@ -91,7 +260,7 @@ const CPVT_WordPlace& CFX_Edit_Iterator::GetAt() const { |
return m_pVTIterator->GetAt(); |
} |
-IFX_Edit* CFX_Edit_Iterator::GetEdit() const { |
+CFX_Edit* CFX_Edit_Iterator::GetEdit() const { |
return m_pEdit; |
} |
@@ -645,8 +814,639 @@ void CFXEU_InsertText::Undo() { |
} |
} |
-CFX_Edit::CFX_Edit(CPDF_VariableText* pVT) |
- : m_pVT(pVT), |
+// static |
+CFX_ByteString CFX_Edit::GetEditAppearanceStream(CFX_Edit* pEdit, |
+ const CFX_FloatPoint& ptOffset, |
+ const CPVT_WordRange* pRange, |
+ FX_BOOL bContinuous, |
+ uint16_t SubWord) { |
+ CFX_Edit_Iterator* pIterator = pEdit->GetIterator(); |
+ if (pRange) |
+ pIterator->SetAt(pRange->BeginPos); |
+ else |
+ pIterator->SetAt(0); |
+ |
+ CFX_ByteTextBuf sEditStream; |
+ CFX_ByteTextBuf sWords; |
+ int32_t nCurFontIndex = -1; |
+ CFX_FloatPoint ptOld(0.0f, 0.0f); |
+ CFX_FloatPoint ptNew(0.0f, 0.0f); |
+ 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.MakeString()); |
+ sWords.Clear(); |
+ } |
+ |
+ CPVT_Word word; |
+ if (pIterator->GetWord(word)) { |
+ ptNew = CFX_FloatPoint(word.ptWord.x + ptOffset.x, |
+ word.ptWord.y + ptOffset.y); |
+ } else { |
+ CPVT_Line line; |
+ pIterator->GetLine(line); |
+ ptNew = CFX_FloatPoint(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.MakeString()); |
+ 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 = CFX_FloatPoint(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.MakeString()); |
+ 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.MakeString(); |
+} |
+ |
+// static |
+CFX_ByteString CFX_Edit::GetSelectAppearanceStream( |
+ CFX_Edit* pEdit, |
+ const CFX_FloatPoint& ptOffset, |
+ const CPVT_WordRange* pRange) { |
+ if (!pRange || !pRange->IsExist()) |
+ return CFX_ByteString(); |
+ |
+ CFX_Edit_Iterator* pIterator = pEdit->GetIterator(); |
+ pIterator->SetAt(pRange->BeginPos); |
+ |
+ CFX_ByteTextBuf sRet; |
+ while (pIterator->NextWord()) { |
+ CPVT_WordPlace place = pIterator->GetAt(); |
+ if (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.MakeString(); |
+} |
+ |
+// static |
+void CFX_Edit::DrawUnderline(CFX_RenderDevice* pDevice, |
+ CFX_Matrix* pUser2Device, |
+ CFX_Edit* pEdit, |
+ FX_COLORREF color, |
+ const CFX_FloatRect& rcClip, |
+ const CFX_FloatPoint& ptOffset, |
+ const CPVT_WordRange* pRange) { |
+ pDevice->SaveState(); |
+ |
+ if (!rcClip.IsEmpty()) { |
+ CFX_FloatRect rcTemp = rcClip; |
+ pUser2Device->TransformRect(rcTemp); |
+ pDevice->SetClip_Rect(rcTemp.ToFxRect()); |
+ } |
+ |
+ CFX_Edit_Iterator* pIterator = pEdit->GetIterator(); |
+ if (pEdit->GetFontMap()) { |
+ if (pRange) |
+ pIterator->SetAt(pRange->BeginPos); |
+ else |
+ pIterator->SetAt(0); |
+ |
+ while (pIterator->NextWord()) { |
+ CPVT_WordPlace place = pIterator->GetAt(); |
+ if (pRange && place.WordCmp(pRange->EndPos) > 0) |
+ break; |
+ |
+ CPVT_Word word; |
+ if (pIterator->GetWord(word)) { |
+ CFX_PathData pathUnderline; |
+ CFX_FloatRect rcUnderline = GetUnderLineRect(word); |
+ rcUnderline.left += ptOffset.x; |
+ rcUnderline.right += ptOffset.x; |
+ rcUnderline.top += ptOffset.y; |
+ rcUnderline.bottom += ptOffset.y; |
+ pathUnderline.AppendRect(rcUnderline.left, rcUnderline.bottom, |
+ rcUnderline.right, rcUnderline.top); |
+ |
+ pDevice->DrawPath(&pathUnderline, pUser2Device, nullptr, color, 0, |
+ FXFILL_WINDING); |
+ } |
+ } |
+ } |
+ |
+ pDevice->RestoreState(false); |
+} |
+ |
+// static |
+void CFX_Edit::DrawEdit(CFX_RenderDevice* pDevice, |
+ CFX_Matrix* pUser2Device, |
+ CFX_Edit* pEdit, |
+ FX_COLORREF crTextFill, |
+ FX_COLORREF crTextStroke, |
+ const CFX_FloatRect& rcClip, |
+ const CFX_FloatPoint& ptOffset, |
+ const CPVT_WordRange* pRange, |
+ CFX_SystemHandler* pSystemHandler, |
+ void* pFFLData) { |
+ const bool bContinuous = |
+ pEdit->GetCharArray() == 0 && pEdit->GetCharSpace() <= 0.0f; |
+ uint16_t SubWord = pEdit->GetPasswordChar(); |
+ FX_FLOAT fFontSize = pEdit->GetFontSize(); |
+ CPVT_WordRange wrSelect = pEdit->GetSelectWordRange(); |
+ int32_t nHorzScale = pEdit->GetHorzScale(); |
+ |
+ FX_COLORREF crCurFill = crTextFill; |
+ FX_COLORREF crOldFill = crCurFill; |
+ |
+ FX_BOOL bSelect = FALSE; |
+ const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255); |
+ const FX_COLORREF crSelBK = ArgbEncode(255, 0, 51, 113); |
+ |
+ CFX_ByteTextBuf sTextBuf; |
+ int32_t nFontIndex = -1; |
+ CFX_FloatPoint ptBT(0.0f, 0.0f); |
+ |
+ pDevice->SaveState(); |
+ |
+ if (!rcClip.IsEmpty()) { |
+ CFX_FloatRect rcTemp = rcClip; |
+ pUser2Device->TransformRect(rcTemp); |
+ pDevice->SetClip_Rect(rcTemp.ToFxRect()); |
+ } |
+ |
+ CFX_Edit_Iterator* pIterator = pEdit->GetIterator(); |
+ if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) { |
+ 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 (wrSelect.IsExist()) { |
+ bSelect = place.WordCmp(wrSelect.BeginPos) > 0 && |
+ place.WordCmp(wrSelect.EndPos) <= 0; |
+ crCurFill = bSelect ? crWhite : crTextFill; |
+ } |
+ if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) { |
+ crCurFill = crTextFill; |
+ crOldFill = crCurFill; |
+ } |
+ CPVT_Word word; |
+ if (pIterator->GetWord(word)) { |
+ if (bSelect) { |
+ CPVT_Line line; |
+ pIterator->GetLine(line); |
+ |
+ if (pSystemHandler && pSystemHandler->IsSelectionImplemented()) { |
+ CFX_FloatRect rc(word.ptWord.x, line.ptLine.y + line.fLineDescent, |
+ word.ptWord.x + word.fWidth, |
+ line.ptLine.y + line.fLineAscent); |
+ rc.Intersect(rcClip); |
+ pSystemHandler->OutputSelectedRect(pFFLData, rc); |
+ } else { |
+ CFX_PathData pathSelBK; |
+ pathSelBK.AppendRect( |
+ word.ptWord.x, line.ptLine.y + line.fLineDescent, |
+ word.ptWord.x + word.fWidth, line.ptLine.y + line.fLineAscent); |
+ |
+ pDevice->DrawPath(&pathSelBK, pUser2Device, nullptr, crSelBK, 0, |
+ FXFILL_WINDING); |
+ } |
+ } |
+ |
+ if (bContinuous) { |
+ if (place.LineCmp(oldplace) != 0 || word.nFontIndex != nFontIndex || |
+ crOldFill != crCurFill) { |
+ if (sTextBuf.GetLength() > 0) { |
+ DrawTextString( |
+ pDevice, |
+ CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), |
+ pFontMap->GetPDFFont(nFontIndex), fFontSize, pUser2Device, |
+ sTextBuf.MakeString(), crOldFill, crTextStroke, nHorzScale); |
+ |
+ sTextBuf.Clear(); |
+ } |
+ nFontIndex = word.nFontIndex; |
+ ptBT = word.ptWord; |
+ crOldFill = crCurFill; |
+ } |
+ |
+ sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, |
+ SubWord) |
+ .AsStringC(); |
+ } else { |
+ DrawTextString( |
+ pDevice, CFX_FloatPoint(word.ptWord.x + ptOffset.x, |
+ word.ptWord.y + ptOffset.y), |
+ pFontMap->GetPDFFont(word.nFontIndex), fFontSize, pUser2Device, |
+ GetPDFWordString(pFontMap, word.nFontIndex, word.Word, SubWord), |
+ crCurFill, crTextStroke, nHorzScale); |
+ } |
+ oldplace = place; |
+ } |
+ } |
+ |
+ if (sTextBuf.GetLength() > 0) { |
+ DrawTextString( |
+ pDevice, CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), |
+ pFontMap->GetPDFFont(nFontIndex), fFontSize, pUser2Device, |
+ sTextBuf.MakeString(), crOldFill, crTextStroke, nHorzScale); |
+ } |
+ } |
+ |
+ pDevice->RestoreState(false); |
+} |
+ |
+// static |
+void CFX_Edit::DrawRichEdit(CFX_RenderDevice* pDevice, |
+ CFX_Matrix* pUser2Device, |
+ CFX_Edit* pEdit, |
+ const CFX_FloatRect& rcClip, |
+ const CFX_FloatPoint& ptOffset, |
+ const CPVT_WordRange* pRange) { |
+ CPVT_WordRange wrSelect = pEdit->GetSelectWordRange(); |
+ |
+ FX_COLORREF crCurText = ArgbEncode(255, 0, 0, 0); |
+ FX_COLORREF crOld = crCurText; |
+ FX_BOOL bSelect = FALSE; |
+ const FX_COLORREF crWhite = ArgbEncode(255, 255, 255, 255); |
+ const FX_COLORREF crSelBK = ArgbEncode(255, 0, 51, 113); |
+ |
+ CFX_ByteTextBuf sTextBuf; |
+ CPVT_WordProps wp; |
+ CFX_FloatPoint ptBT(0.0f, 0.0f); |
+ |
+ pDevice->SaveState(); |
+ |
+ if (!rcClip.IsEmpty()) { |
+ CFX_FloatRect rcTemp = rcClip; |
+ pUser2Device->TransformRect(rcTemp); |
+ pDevice->SetClip_Rect(rcTemp.ToFxRect()); |
+ } |
+ |
+ CFX_Edit_Iterator* pIterator = pEdit->GetIterator(); |
+ if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) { |
+ 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; |
+ |
+ CPVT_Word word; |
+ if (pIterator->GetWord(word)) { |
+ word.WordProps.fFontSize = word.fFontSize; |
+ |
+ crCurText = ArgbEncode(255, word.WordProps.dwWordColor); |
+ |
+ if (wrSelect.IsExist()) { |
+ bSelect = place.WordCmp(wrSelect.BeginPos) > 0 && |
+ place.WordCmp(wrSelect.EndPos) <= 0; |
+ if (bSelect) { |
+ crCurText = crWhite; |
+ } |
+ } |
+ |
+ if (bSelect) { |
+ CPVT_Line line; |
+ pIterator->GetLine(line); |
+ |
+ CFX_PathData pathSelBK; |
+ pathSelBK.AppendRect(word.ptWord.x + ptOffset.x, |
+ line.ptLine.y + line.fLineDescent + ptOffset.y, |
+ word.ptWord.x + word.fWidth + ptOffset.x, |
+ line.ptLine.y + line.fLineAscent + ptOffset.y); |
+ |
+ pDevice->DrawPath(&pathSelBK, pUser2Device, nullptr, crSelBK, 0, |
+ FXFILL_WINDING); |
+ } |
+ |
+ if (place.LineCmp(oldplace) != 0 || word.WordProps.fCharSpace > 0.0f || |
+ word.WordProps.nHorzScale != 100 || |
+ FXSYS_memcmp(&word.WordProps, &wp, sizeof(CPVT_WordProps)) != 0 || |
+ crOld != crCurText) { |
+ if (sTextBuf.GetLength() > 0) { |
+ DrawTextString( |
+ pDevice, |
+ CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), |
+ pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize, pUser2Device, |
+ sTextBuf.MakeString(), crOld, 0, wp.nHorzScale); |
+ |
+ sTextBuf.Clear(); |
+ } |
+ wp = word.WordProps; |
+ ptBT = word.ptWord; |
+ crOld = crCurText; |
+ } |
+ |
+ sTextBuf << GetPDFWordString(pFontMap, word.WordProps.nFontIndex, |
+ word.Word, 0) |
+ .AsStringC(); |
+ |
+ if (word.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) { |
+ CFX_PathData pathUnderline; |
+ CFX_FloatRect rcUnderline = GetUnderLineRect(word); |
+ pathUnderline.AppendRect(rcUnderline.left, rcUnderline.bottom, |
+ rcUnderline.right, rcUnderline.top); |
+ |
+ pDevice->DrawPath(&pathUnderline, pUser2Device, nullptr, crCurText, 0, |
+ FXFILL_WINDING); |
+ } |
+ |
+ if (word.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) { |
+ CFX_PathData pathCrossout; |
+ CFX_FloatRect rcCrossout = GetCrossoutRect(word); |
+ pathCrossout.AppendRect(rcCrossout.left, rcCrossout.bottom, |
+ rcCrossout.right, rcCrossout.top); |
+ |
+ pDevice->DrawPath(&pathCrossout, pUser2Device, nullptr, crCurText, 0, |
+ FXFILL_WINDING); |
+ } |
+ |
+ oldplace = place; |
+ } |
+ } |
+ |
+ if (sTextBuf.GetLength() > 0) { |
+ DrawTextString( |
+ pDevice, CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), |
+ pFontMap->GetPDFFont(wp.nFontIndex), wp.fFontSize, pUser2Device, |
+ sTextBuf.MakeString(), crOld, 0, wp.nHorzScale); |
+ } |
+ } |
+ |
+ pDevice->RestoreState(false); |
+} |
+ |
+// static |
+void CFX_Edit::GeneratePageObjects( |
+ CPDF_PageObjectHolder* pObjectHolder, |
+ CFX_Edit* pEdit, |
+ const CFX_FloatPoint& ptOffset, |
+ const CPVT_WordRange* pRange, |
+ FX_COLORREF crText, |
+ CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray) { |
+ FX_FLOAT fFontSize = pEdit->GetFontSize(); |
+ |
+ int32_t nOldFontIndex = -1; |
+ |
+ CFX_ByteTextBuf sTextBuf; |
+ CFX_FloatPoint ptBT(0.0f, 0.0f); |
+ |
+ ObjArray.RemoveAll(); |
+ |
+ CFX_Edit_Iterator* pIterator = pEdit->GetIterator(); |
+ if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) { |
+ 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; |
+ |
+ CPVT_Word word; |
+ if (pIterator->GetWord(word)) { |
+ if (place.LineCmp(oldplace) != 0 || nOldFontIndex != word.nFontIndex) { |
+ if (sTextBuf.GetLength() > 0) { |
+ ObjArray.Add(AddTextObjToPageObjects( |
+ pObjectHolder, crText, pFontMap->GetPDFFont(nOldFontIndex), |
+ fFontSize, 0.0f, 100, |
+ CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), |
+ sTextBuf.MakeString())); |
+ |
+ sTextBuf.Clear(); |
+ } |
+ |
+ ptBT = word.ptWord; |
+ nOldFontIndex = word.nFontIndex; |
+ } |
+ |
+ sTextBuf << GetPDFWordString(pFontMap, word.nFontIndex, word.Word, 0) |
+ .AsStringC(); |
+ oldplace = place; |
+ } |
+ } |
+ |
+ if (sTextBuf.GetLength() > 0) { |
+ ObjArray.Add(AddTextObjToPageObjects( |
+ pObjectHolder, crText, pFontMap->GetPDFFont(nOldFontIndex), fFontSize, |
+ 0.0f, 100, CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), |
+ sTextBuf.MakeString())); |
+ } |
+ } |
+} |
+ |
+// static |
+void CFX_Edit::GenerateRichPageObjects( |
+ CPDF_PageObjectHolder* pObjectHolder, |
+ CFX_Edit* pEdit, |
+ const CFX_FloatPoint& ptOffset, |
+ const CPVT_WordRange* pRange, |
+ CFX_ArrayTemplate<CPDF_TextObject*>& ObjArray) { |
+ FX_COLORREF crCurText = ArgbEncode(255, 0, 0, 0); |
+ FX_COLORREF crOld = crCurText; |
+ |
+ CFX_ByteTextBuf sTextBuf; |
+ CPVT_WordProps wp; |
+ CFX_FloatPoint ptBT(0.0f, 0.0f); |
+ |
+ ObjArray.RemoveAll(); |
+ |
+ CFX_Edit_Iterator* pIterator = pEdit->GetIterator(); |
+ if (IPVT_FontMap* pFontMap = pEdit->GetFontMap()) { |
+ 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; |
+ |
+ CPVT_Word word; |
+ if (pIterator->GetWord(word)) { |
+ word.WordProps.fFontSize = word.fFontSize; |
+ |
+ crCurText = ArgbEncode(255, word.WordProps.dwWordColor); |
+ |
+ if (place.LineCmp(oldplace) != 0 || word.WordProps.fCharSpace > 0.0f || |
+ word.WordProps.nHorzScale != 100 || |
+ FXSYS_memcmp(&word.WordProps, &wp, sizeof(CPVT_WordProps)) != 0 || |
+ crOld != crCurText) { |
+ if (sTextBuf.GetLength() > 0) { |
+ ObjArray.Add(AddTextObjToPageObjects( |
+ pObjectHolder, crOld, pFontMap->GetPDFFont(wp.nFontIndex), |
+ wp.fFontSize, wp.fCharSpace, wp.nHorzScale, |
+ CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), |
+ sTextBuf.MakeString())); |
+ |
+ sTextBuf.Clear(); |
+ } |
+ |
+ wp = word.WordProps; |
+ ptBT = word.ptWord; |
+ crOld = crCurText; |
+ } |
+ |
+ sTextBuf << GetPDFWordString(pFontMap, word.WordProps.nFontIndex, |
+ word.Word, 0) |
+ .AsStringC(); |
+ |
+ if (word.WordProps.nWordStyle & PVTWORD_STYLE_UNDERLINE) { |
+ CFX_FloatRect rcUnderline = GetUnderLineRect(word); |
+ rcUnderline.left += ptOffset.x; |
+ rcUnderline.right += ptOffset.x; |
+ rcUnderline.top += ptOffset.y; |
+ rcUnderline.bottom += ptOffset.y; |
+ |
+ AddRectToPageObjects(pObjectHolder, crCurText, rcUnderline); |
+ } |
+ |
+ if (word.WordProps.nWordStyle & PVTWORD_STYLE_CROSSOUT) { |
+ CFX_FloatRect rcCrossout = GetCrossoutRect(word); |
+ rcCrossout.left += ptOffset.x; |
+ rcCrossout.right += ptOffset.x; |
+ rcCrossout.top += ptOffset.y; |
+ rcCrossout.bottom += ptOffset.y; |
+ |
+ AddRectToPageObjects(pObjectHolder, crCurText, rcCrossout); |
+ } |
+ |
+ oldplace = place; |
+ } |
+ } |
+ |
+ if (sTextBuf.GetLength() > 0) { |
+ ObjArray.Add(AddTextObjToPageObjects( |
+ pObjectHolder, crOld, pFontMap->GetPDFFont(wp.nFontIndex), |
+ wp.fFontSize, wp.fCharSpace, wp.nHorzScale, |
+ CFX_FloatPoint(ptBT.x + ptOffset.x, ptBT.y + ptOffset.y), |
+ sTextBuf.MakeString())); |
+ } |
+ } |
+} |
+ |
+// static |
+void CFX_Edit::GenerateUnderlineObjects(CPDF_PageObjectHolder* pObjectHolder, |
+ CFX_Edit* pEdit, |
+ const CFX_FloatPoint& ptOffset, |
+ const CPVT_WordRange* pRange, |
+ FX_COLORREF color) { |
+ CFX_Edit_Iterator* pIterator = pEdit->GetIterator(); |
+ if (pEdit->GetFontMap()) { |
+ 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; |
+ |
+ CPVT_Word word; |
+ if (pIterator->GetWord(word)) { |
+ CFX_FloatRect rcUnderline = GetUnderLineRect(word); |
+ rcUnderline.left += ptOffset.x; |
+ rcUnderline.right += ptOffset.x; |
+ rcUnderline.top += ptOffset.y; |
+ rcUnderline.bottom += ptOffset.y; |
+ AddRectToPageObjects(pObjectHolder, color, rcUnderline); |
+ } |
+ } |
+ } |
+} |
+ |
+CFX_Edit::CFX_Edit() |
+ : m_pVT(new CPDF_VariableText), |
m_pNotify(nullptr), |
m_pOprNotify(nullptr), |
m_wpCaret(-1, -1, -1), |
@@ -664,9 +1464,7 @@ CFX_Edit::CFX_Edit(CPDF_VariableText* pVT) |
m_rcOldContent(0.0f, 0.0f, 0.0f, 0.0f), |
m_bEnableUndo(TRUE), |
m_bOprNotify(FALSE), |
- m_pGroupUndoItem(nullptr) { |
- ASSERT(pVT); |
-} |
+ m_pGroupUndoItem(nullptr) {} |
CFX_Edit::~CFX_Edit() { |
ASSERT(!m_pGroupUndoItem); |
@@ -683,22 +1481,22 @@ void CFX_Edit::SetFontMap(IPVT_FontMap* pFontMap) { |
m_pVT->SetProvider(m_pVTProvider.get()); |
} |
-void CFX_Edit::SetNotify(IFX_Edit_Notify* pNotify) { |
+void CFX_Edit::SetNotify(CPWL_EditCtrl* pNotify) { |
m_pNotify = pNotify; |
} |
-void CFX_Edit::SetOprNotify(IFX_Edit_OprNotify* pOprNotify) { |
+void CFX_Edit::SetOprNotify(CPWL_Edit* pOprNotify) { |
m_pOprNotify = pOprNotify; |
} |
-IFX_Edit_Iterator* CFX_Edit::GetIterator() { |
+CFX_Edit_Iterator* CFX_Edit::GetIterator() { |
if (!m_pIterator) |
m_pIterator.reset(new CFX_Edit_Iterator(this, m_pVT->GetIterator())); |
return m_pIterator.get(); |
} |
CPDF_VariableText* CFX_Edit::GetVariableText() { |
- return m_pVT; |
+ return m_pVT.get(); |
} |
IPVT_FontMap* CFX_Edit::GetFontMap() { |
@@ -1202,10 +2000,6 @@ void CFX_Edit::SetScrollInfo() { |
if (!m_bNotifyFlag) { |
m_bNotifyFlag = TRUE; |
- m_pNotify->IOnSetScrollInfoX(rcPlate.left, rcPlate.right, rcContent.left, |
- rcContent.right, rcPlate.Width() / 3, |
- rcPlate.Width()); |
- |
m_pNotify->IOnSetScrollInfoY(rcPlate.bottom, rcPlate.top, |
rcContent.bottom, rcContent.top, |
rcPlate.Height() / 3, rcPlate.Height()); |
@@ -1222,14 +2016,6 @@ void CFX_Edit::SetScrollPosX(FX_FLOAT fx) { |
if (!FX_EDIT_IsFloatEqual(m_ptScrollPos.x, fx)) { |
m_ptScrollPos.x = fx; |
Refresh(RP_NOANALYSE); |
- |
- if (m_pNotify) { |
- if (!m_bNotifyFlag) { |
- m_bNotifyFlag = TRUE; |
- m_pNotify->IOnSetScrollPosX(fx); |
- m_bNotifyFlag = FALSE; |
- } |
- } |
} |
} |
} |
@@ -1810,8 +2596,6 @@ void CFX_Edit::SetText(const FX_WCHAR* text, |
DoInsertText(CPVT_WordPlace(0, 0, -1), text, charset, pSecProps, pWordProps); |
if (bPaint) |
Paint(); |
- if (m_bOprNotify && m_pOprNotify) |
- m_pOprNotify->OnSetText(m_wpCaret, m_wpOldCaret); |
} |
FX_BOOL CFX_Edit::InsertWord(uint16_t word, |