diff options
author | dsinclair <dsinclair@chromium.org> | 2016-03-31 20:03:08 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-03-31 20:03:08 -0700 |
commit | 777b333109db7fceb5f2ca1fc521ced7f863fa18 (patch) | |
tree | f5968b42f43c90bc20af39a845718877cf80e064 /core/fpdfdoc | |
parent | 47ca692c8150cb39abef5737e866b91e6a105b80 (diff) | |
download | pdfium-777b333109db7fceb5f2ca1fc521ced7f863fa18.tar.xz |
Split core/include/fpdfdoc/fpdf_ap.h
This CL splits the fpdf_ap.h file apart into individual pieces and moves the
implementations to their own CPP files.
Review URL: https://codereview.chromium.org/1840413002
Diffstat (limited to 'core/fpdfdoc')
-rw-r--r-- | core/fpdfdoc/cpvt_color.cpp | 51 | ||||
-rw-r--r-- | core/fpdfdoc/cpvt_color.h | 38 | ||||
-rw-r--r-- | core/fpdfdoc/cpvt_dash.h | 21 | ||||
-rw-r--r-- | core/fpdfdoc/cpvt_fontmap.cpp | 75 | ||||
-rw-r--r-- | core/fpdfdoc/cpvt_fontmap.h | 45 | ||||
-rw-r--r-- | core/fpdfdoc/cpvt_generateap.cpp | 769 | ||||
-rw-r--r-- | core/fpdfdoc/cpvt_generateap.h | 66 | ||||
-rw-r--r-- | core/fpdfdoc/cpvt_provider.h | 35 | ||||
-rw-r--r-- | core/fpdfdoc/doc_annot.cpp | 1 | ||||
-rw-r--r-- | core/fpdfdoc/doc_ap.cpp | 870 | ||||
-rw-r--r-- | core/fpdfdoc/doc_formfield.cpp | 1 | ||||
-rw-r--r-- | core/fpdfdoc/doc_vt.cpp | 1 | ||||
-rw-r--r-- | core/fpdfdoc/include/ipdf_variabletext_provider.h | 28 | ||||
-rw-r--r-- | core/fpdfdoc/ipdf_variabletext_provider.cpp | 9 | ||||
-rw-r--r-- | core/fpdfdoc/ipvt_fontmap.h | 24 |
15 files changed, 1165 insertions, 869 deletions
diff --git a/core/fpdfdoc/cpvt_color.cpp b/core/fpdfdoc/cpvt_color.cpp new file mode 100644 index 0000000000..afeff23e15 --- /dev/null +++ b/core/fpdfdoc/cpvt_color.cpp @@ -0,0 +1,51 @@ +// Copyright 2016 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 "core/fpdfdoc/cpvt_color.h" + +#include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h" + +// Static. +CPVT_Color CPVT_Color::ParseColor(const CFX_ByteString& str) { + CPDF_SimpleParser syntax(str); + if (syntax.FindTagParamFromStart("g", 1)) + return CPVT_Color(CPVT_Color::kGray, FX_atof(syntax.GetWord())); + + if (syntax.FindTagParamFromStart("rg", 3)) { + FX_FLOAT f1 = FX_atof(syntax.GetWord()); + FX_FLOAT f2 = FX_atof(syntax.GetWord()); + FX_FLOAT f3 = FX_atof(syntax.GetWord()); + return CPVT_Color(CPVT_Color::kRGB, f1, f2, f3); + } + if (syntax.FindTagParamFromStart("k", 4)) { + FX_FLOAT f1 = FX_atof(syntax.GetWord()); + FX_FLOAT f2 = FX_atof(syntax.GetWord()); + FX_FLOAT f3 = FX_atof(syntax.GetWord()); + FX_FLOAT f4 = FX_atof(syntax.GetWord()); + return CPVT_Color(CPVT_Color::kCMYK, f1, f2, f3, f4); + } + return CPVT_Color(CPVT_Color::kTransparent); +} + +// Static. +CPVT_Color CPVT_Color::ParseColor(const CPDF_Array& array) { + CPVT_Color rt; + switch (array.GetCount()) { + case 1: + rt = CPVT_Color(CPVT_Color::kGray, array.GetFloatAt(0)); + break; + case 3: + rt = CPVT_Color(CPVT_Color::kRGB, array.GetFloatAt(0), + array.GetFloatAt(1), array.GetFloatAt(2)); + break; + case 4: + rt = CPVT_Color(CPVT_Color::kCMYK, array.GetFloatAt(0), + array.GetFloatAt(1), array.GetFloatAt(2), + array.GetFloatAt(3)); + break; + } + return rt; +} diff --git a/core/fpdfdoc/cpvt_color.h b/core/fpdfdoc/cpvt_color.h new file mode 100644 index 0000000000..da23ce4bb9 --- /dev/null +++ b/core/fpdfdoc/cpvt_color.h @@ -0,0 +1,38 @@ +// Copyright 2016 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 + +#ifndef CORE_FPDFDOC_CPVT_COLOR_H_ +#define CORE_FPDFDOC_CPVT_COLOR_H_ + +#include "core/fpdfapi/fpdf_parser/include/cpdf_array.h" +#include "core/fxcrt/include/fx_string.h" +#include "core/fxcrt/include/fx_system.h" + +struct CPVT_Color { + enum Type { kTransparent = 0, kGray, kRGB, kCMYK }; + + CPVT_Color(Type type = kTransparent, + FX_FLOAT color1 = 0.0f, + FX_FLOAT color2 = 0.0f, + FX_FLOAT color3 = 0.0f, + FX_FLOAT color4 = 0.0f) + : nColorType(type), + fColor1(color1), + fColor2(color2), + fColor3(color3), + fColor4(color4) {} + + Type nColorType; + FX_FLOAT fColor1; + FX_FLOAT fColor2; + FX_FLOAT fColor3; + FX_FLOAT fColor4; + + static CPVT_Color ParseColor(const CFX_ByteString& str); + static CPVT_Color ParseColor(const CPDF_Array& array); +}; + +#endif // CORE_FPDFDOC_CPVT_COLOR_H_ diff --git a/core/fpdfdoc/cpvt_dash.h b/core/fpdfdoc/cpvt_dash.h new file mode 100644 index 0000000000..f80d104c96 --- /dev/null +++ b/core/fpdfdoc/cpvt_dash.h @@ -0,0 +1,21 @@ +// Copyright 2016 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 + +#ifndef CORE_FPDFDOC_CPVT_DASH_H_ +#define CORE_FPDFDOC_CPVT_DASH_H_ + +#include <stdint.h> + +struct CPVT_Dash { + CPVT_Dash(int32_t dash, int32_t gap, int32_t phase) + : nDash(dash), nGap(gap), nPhase(phase) {} + + int32_t nDash; + int32_t nGap; + int32_t nPhase; +}; + +#endif // CORE_FPDFDOC_CPVT_DASH_H_ diff --git a/core/fpdfdoc/cpvt_fontmap.cpp b/core/fpdfdoc/cpvt_fontmap.cpp new file mode 100644 index 0000000000..529f85169e --- /dev/null +++ b/core/fpdfdoc/cpvt_fontmap.cpp @@ -0,0 +1,75 @@ +// Copyright 2016 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 "core/fpdfdoc/cpvt_fontmap.h" + +#include "core/fpdfapi/fpdf_font/include/cpdf_font.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" +#include "core/fpdfdoc/doc_utils.h" + +CPVT_FontMap::CPVT_FontMap(CPDF_Document* pDoc, + CPDF_Dictionary* pResDict, + CPDF_Font* pDefFont, + const CFX_ByteString& sDefFontAlias) + : m_pDocument(pDoc), + m_pResDict(pResDict), + m_pDefFont(pDefFont), + m_sDefFontAlias(sDefFontAlias), + m_pSysFont(nullptr), + m_sSysFontAlias() {} + +CPVT_FontMap::~CPVT_FontMap() {} + +void CPVT_FontMap::GetAnnotSysPDFFont(CPDF_Document* pDoc, + const CPDF_Dictionary* pResDict, + CPDF_Font*& pSysFont, + CFX_ByteString& sSysFontAlias) { + if (!pDoc || !pResDict) + return; + + CFX_ByteString sFontAlias; + CPDF_Dictionary* pFormDict = pDoc->GetRoot()->GetDictBy("AcroForm"); + CPDF_Font* pPDFFont = AddNativeInterFormFont(pFormDict, pDoc, sSysFontAlias); + if (!pPDFFont) + return; + + if (CPDF_Dictionary* pFontList = pResDict->GetDictBy("Font")) { + if (!pFontList->KeyExist(sSysFontAlias)) + pFontList->SetAtReference(sSysFontAlias, pDoc, pPDFFont->GetFontDict()); + } + pSysFont = pPDFFont; +} + +CPDF_Font* CPVT_FontMap::GetPDFFont(int32_t nFontIndex) { + switch (nFontIndex) { + case 0: + return m_pDefFont; + case 1: + if (!m_pSysFont) { + GetAnnotSysPDFFont(m_pDocument, m_pResDict, m_pSysFont, + m_sSysFontAlias); + } + return m_pSysFont; + default: + return nullptr; + } +} + +CFX_ByteString CPVT_FontMap::GetPDFFontAlias(int32_t nFontIndex) { + switch (nFontIndex) { + case 0: + return m_sDefFontAlias; + case 1: + if (!m_pSysFont) { + GetAnnotSysPDFFont(m_pDocument, m_pResDict, m_pSysFont, + m_sSysFontAlias); + } + return m_sSysFontAlias; + default: + return ""; + } +} diff --git a/core/fpdfdoc/cpvt_fontmap.h b/core/fpdfdoc/cpvt_fontmap.h new file mode 100644 index 0000000000..d6f931aeb7 --- /dev/null +++ b/core/fpdfdoc/cpvt_fontmap.h @@ -0,0 +1,45 @@ +// Copyright 2016 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 + +#ifndef CORE_FPDFDOC_CPVT_FONTMAP_H_ +#define CORE_FPDFDOC_CPVT_FONTMAP_H_ + +#include <stdint.h> + +#include "core/fpdfdoc/ipvt_fontmap.h" +#include "core/fxcrt/include/fx_string.h" + +class CPDF_Document; +class CPDF_Dictionary; +class CPDF_Font; + +class CPVT_FontMap : public IPVT_FontMap { + public: + CPVT_FontMap(CPDF_Document* pDoc, + CPDF_Dictionary* pResDict, + CPDF_Font* pDefFont, + const CFX_ByteString& sDefFontAlias); + ~CPVT_FontMap() override; + + // IPVT_FontMap: + CPDF_Font* GetPDFFont(int32_t nFontIndex) override; + CFX_ByteString GetPDFFontAlias(int32_t nFontIndex) override; + + static void GetAnnotSysPDFFont(CPDF_Document* pDoc, + const CPDF_Dictionary* pResDict, + CPDF_Font*& pSysFont, + CFX_ByteString& sSysFontAlias); + + private: + CPDF_Document* const m_pDocument; + const CPDF_Dictionary* const m_pResDict; + CPDF_Font* const m_pDefFont; + const CFX_ByteString m_sDefFontAlias; + CPDF_Font* m_pSysFont; + CFX_ByteString m_sSysFontAlias; +}; + +#endif // CORE_FPDFDOC_CPVT_FONTMAP_H_ diff --git a/core/fpdfdoc/cpvt_generateap.cpp b/core/fpdfdoc/cpvt_generateap.cpp new file mode 100644 index 0000000000..f9d6e9630b --- /dev/null +++ b/core/fpdfdoc/cpvt_generateap.cpp @@ -0,0 +1,769 @@ +// Copyright 2016 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 "core/fpdfdoc/cpvt_generateap.h" + +#include "core/fpdfapi/fpdf_font/include/cpdf_font.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h" +#include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h" +#include "core/fpdfdoc/cpvt_color.h" +#include "core/fpdfdoc/cpvt_fontmap.h" +#include "core/fpdfdoc/cpvt_provider.h" +#include "core/fpdfdoc/pdf_vt.h" +#include "core/include/fpdfdoc/fpdf_doc.h" + +namespace { + +FX_BOOL GenerateWidgetAP(CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict, + const int32_t& nWidgetType) { + CPDF_Dictionary* pFormDict = nullptr; + if (CPDF_Dictionary* pRootDict = pDoc->GetRoot()) + pFormDict = pRootDict->GetDictBy("AcroForm"); + if (!pFormDict) + return FALSE; + + CFX_ByteString DA; + if (CPDF_Object* pDAObj = FPDF_GetFieldAttr(pAnnotDict, "DA")) + DA = pDAObj->GetString(); + if (DA.IsEmpty()) + DA = pFormDict->GetStringBy("DA"); + if (DA.IsEmpty()) + return FALSE; + + CPDF_SimpleParser syntax(DA); + syntax.FindTagParamFromStart("Tf", 2); + CFX_ByteString sFontName = syntax.GetWord(); + sFontName = PDF_NameDecode(sFontName); + if (sFontName.IsEmpty()) + return FALSE; + + FX_FLOAT fFontSize = FX_atof(syntax.GetWord()); + CPVT_Color crText = CPVT_Color::ParseColor(DA); + FX_BOOL bUseFormRes = FALSE; + CPDF_Dictionary* pFontDict = nullptr; + CPDF_Dictionary* pDRDict = pAnnotDict->GetDictBy("DR"); + if (!pDRDict) { + pDRDict = pFormDict->GetDictBy("DR"); + bUseFormRes = TRUE; + } + CPDF_Dictionary* pDRFontDict = pDRDict ? pDRDict->GetDictBy("Font") : nullptr; + if (pDRFontDict) { + pFontDict = pDRFontDict->GetDictBy(sFontName.Mid(1)); + if (!pFontDict && !bUseFormRes) { + pDRDict = pFormDict->GetDictBy("DR"); + pDRFontDict = pDRDict->GetDictBy("Font"); + if (pDRFontDict) + pFontDict = pDRFontDict->GetDictBy(sFontName.Mid(1)); + } + } + if (!pDRFontDict) + return FALSE; + + if (!pFontDict) { + pFontDict = new CPDF_Dictionary; + pFontDict->SetAtName("Type", "Font"); + pFontDict->SetAtName("Subtype", "Type1"); + pFontDict->SetAtName("BaseFont", "Helvetica"); + pFontDict->SetAtName("Encoding", "WinAnsiEncoding"); + pDoc->AddIndirectObject(pFontDict); + pDRFontDict->SetAtReference(sFontName.Mid(1), pDoc, pFontDict); + } + CPDF_Font* pDefFont = pDoc->LoadFont(pFontDict); + if (!pDefFont) + return FALSE; + + CFX_FloatRect rcAnnot = pAnnotDict->GetRectBy("Rect"); + int32_t nRotate = 0; + if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDictBy("MK")) + nRotate = pMKDict->GetIntegerBy("R"); + + CFX_FloatRect rcBBox; + CFX_Matrix matrix; + switch (nRotate % 360) { + case 0: + rcBBox = CFX_FloatRect(0, 0, rcAnnot.right - rcAnnot.left, + rcAnnot.top - rcAnnot.bottom); + break; + case 90: + matrix = CFX_Matrix(0, 1, -1, 0, rcAnnot.right - rcAnnot.left, 0); + rcBBox = CFX_FloatRect(0, 0, rcAnnot.top - rcAnnot.bottom, + rcAnnot.right - rcAnnot.left); + break; + case 180: + matrix = CFX_Matrix(-1, 0, 0, -1, rcAnnot.right - rcAnnot.left, + rcAnnot.top - rcAnnot.bottom); + rcBBox = CFX_FloatRect(0, 0, rcAnnot.right - rcAnnot.left, + rcAnnot.top - rcAnnot.bottom); + break; + case 270: + matrix = CFX_Matrix(0, -1, 1, 0, 0, rcAnnot.top - rcAnnot.bottom); + rcBBox = CFX_FloatRect(0, 0, rcAnnot.top - rcAnnot.bottom, + rcAnnot.right - rcAnnot.left); + break; + } + int32_t nBorderStyle = PBS_SOLID; + FX_FLOAT fBorderWidth = 1; + CPVT_Dash dsBorder(3, 0, 0); + CPVT_Color crLeftTop, crRightBottom; + if (CPDF_Dictionary* pBSDict = pAnnotDict->GetDictBy("BS")) { + if (pBSDict->KeyExist("W")) + fBorderWidth = pBSDict->GetNumberBy("W"); + + if (CPDF_Array* pArray = pBSDict->GetArrayBy("D")) { + dsBorder = CPVT_Dash(pArray->GetIntegerAt(0), pArray->GetIntegerAt(1), + pArray->GetIntegerAt(2)); + } + switch (pBSDict->GetStringBy("S").GetAt(0)) { + case 'S': + nBorderStyle = PBS_SOLID; + break; + case 'D': + nBorderStyle = PBS_DASH; + break; + case 'B': + nBorderStyle = PBS_BEVELED; + fBorderWidth *= 2; + crLeftTop = CPVT_Color(CPVT_Color::kGray, 1); + crRightBottom = CPVT_Color(CPVT_Color::kGray, 0.5); + break; + case 'I': + nBorderStyle = PBS_INSET; + fBorderWidth *= 2; + crLeftTop = CPVT_Color(CPVT_Color::kGray, 0.5); + crRightBottom = CPVT_Color(CPVT_Color::kGray, 0.75); + break; + case 'U': + nBorderStyle = PBS_UNDERLINED; + break; + } + } + CPVT_Color crBorder, crBG; + if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDictBy("MK")) { + if (CPDF_Array* pArray = pMKDict->GetArrayBy("BC")) + crBorder = CPVT_Color::ParseColor(*pArray); + if (CPDF_Array* pArray = pMKDict->GetArrayBy("BG")) + crBG = CPVT_Color::ParseColor(*pArray); + } + CFX_ByteTextBuf sAppStream; + CFX_ByteString sBG = CPVT_GenerateAP::GenerateColorAP(crBG, TRUE); + if (sBG.GetLength() > 0) { + sAppStream << "q\n" << sBG << rcBBox.left << " " << rcBBox.bottom << " " + << rcBBox.Width() << " " << rcBBox.Height() << " re f\n" + << "Q\n"; + } + CFX_ByteString sBorderStream = CPVT_GenerateAP::GenerateBorderAP( + rcBBox, fBorderWidth, crBorder, crLeftTop, crRightBottom, nBorderStyle, + dsBorder); + if (sBorderStream.GetLength() > 0) + sAppStream << "q\n" << sBorderStream << "Q\n"; + + CFX_FloatRect rcBody = + CFX_FloatRect(rcBBox.left + fBorderWidth, rcBBox.bottom + fBorderWidth, + rcBBox.right - fBorderWidth, rcBBox.top - fBorderWidth); + rcBody.Normalize(); + CPDF_Dictionary* pAPDict = pAnnotDict->GetDictBy("AP"); + if (!pAPDict) { + pAPDict = new CPDF_Dictionary; + pAnnotDict->SetAt("AP", pAPDict); + } + CPDF_Stream* pNormalStream = pAPDict->GetStreamBy("N"); + if (!pNormalStream) { + pNormalStream = new CPDF_Stream(nullptr, 0, nullptr); + int32_t objnum = pDoc->AddIndirectObject(pNormalStream); + pAnnotDict->GetDictBy("AP")->SetAtReference("N", pDoc, objnum); + } + CPDF_Dictionary* pStreamDict = pNormalStream->GetDict(); + if (pStreamDict) { + pStreamDict->SetAtMatrix("Matrix", matrix); + pStreamDict->SetAtRect("BBox", rcBBox); + CPDF_Dictionary* pStreamResList = pStreamDict->GetDictBy("Resources"); + if (pStreamResList) { + CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDictBy("Font"); + if (!pStreamResFontList) { + pStreamResFontList = new CPDF_Dictionary; + pStreamResList->SetAt("Font", pStreamResFontList); + } + if (!pStreamResFontList->KeyExist(sFontName)) + pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict); + } else { + pStreamDict->SetAt("Resources", pFormDict->GetDictBy("DR")->Clone()); + pStreamResList = pStreamDict->GetDictBy("Resources"); + } + } + switch (nWidgetType) { + case 0: { + CFX_WideString swValue = + FPDF_GetFieldAttr(pAnnotDict, "V") + ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() + : CFX_WideString(); + int32_t nAlign = FPDF_GetFieldAttr(pAnnotDict, "Q") + ? FPDF_GetFieldAttr(pAnnotDict, "Q")->GetInteger() + : 0; + uint32_t dwFlags = FPDF_GetFieldAttr(pAnnotDict, "Ff") + ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() + : 0; + uint32_t dwMaxLen = + FPDF_GetFieldAttr(pAnnotDict, "MaxLen") + ? FPDF_GetFieldAttr(pAnnotDict, "MaxLen")->GetInteger() + : 0; + CPVT_FontMap map( + pDoc, pStreamDict ? pStreamDict->GetDictBy("Resources") : nullptr, + pDefFont, sFontName.Right(sFontName.GetLength() - 1)); + CPVT_Provider prd(&map); + CPDF_VariableText vt; + vt.SetProvider(&prd); + vt.SetPlateRect(rcBody); + vt.SetAlignment(nAlign); + if (IsFloatZero(fFontSize)) + vt.SetAutoFontSize(TRUE); + else + vt.SetFontSize(fFontSize); + + FX_BOOL bMultiLine = (dwFlags >> 12) & 1; + if (bMultiLine) { + vt.SetMultiLine(TRUE); + vt.SetAutoReturn(TRUE); + } + uint16_t subWord = 0; + if ((dwFlags >> 13) & 1) { + subWord = '*'; + vt.SetPasswordChar(subWord); + } + FX_BOOL bCharArray = (dwFlags >> 24) & 1; + if (bCharArray) + vt.SetCharArray(dwMaxLen); + else + vt.SetLimitChar(dwMaxLen); + + vt.Initialize(); + vt.SetText(swValue.c_str()); + vt.RearrangeAll(); + CFX_FloatRect rcContent = vt.GetContentRect(); + CFX_FloatPoint ptOffset(0.0f, 0.0f); + if (!bMultiLine) { + ptOffset = + CFX_FloatPoint(0.0f, (rcContent.Height() - rcBody.Height()) / 2.0f); + } + CFX_ByteString sBody = CPVT_GenerateAP::GenerateEditAP( + &map, vt.GetIterator(), ptOffset, !bCharArray, subWord); + if (sBody.GetLength() > 0) { + sAppStream << "/Tx BMC\n" + << "q\n"; + if (rcContent.Width() > rcBody.Width() || + rcContent.Height() > rcBody.Height()) { + sAppStream << rcBody.left << " " << rcBody.bottom << " " + << rcBody.Width() << " " << rcBody.Height() + << " re\nW\nn\n"; + } + sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) + << sBody << "ET\n" + << "Q\nEMC\n"; + } + } break; + case 1: { + CFX_WideString swValue = + FPDF_GetFieldAttr(pAnnotDict, "V") + ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() + : CFX_WideString(); + CPVT_FontMap map( + pDoc, pStreamDict ? pStreamDict->GetDictBy("Resources") : nullptr, + pDefFont, sFontName.Right(sFontName.GetLength() - 1)); + CPVT_Provider prd(&map); + CPDF_VariableText vt; + vt.SetProvider(&prd); + CFX_FloatRect rcButton = rcBody; + rcButton.left = rcButton.right - 13; + rcButton.Normalize(); + CFX_FloatRect rcEdit = rcBody; + rcEdit.right = rcButton.left; + rcEdit.Normalize(); + vt.SetPlateRect(rcEdit); + if (IsFloatZero(fFontSize)) + vt.SetAutoFontSize(TRUE); + else + vt.SetFontSize(fFontSize); + + vt.Initialize(); + vt.SetText(swValue.c_str()); + vt.RearrangeAll(); + CFX_FloatRect rcContent = vt.GetContentRect(); + CFX_FloatPoint ptOffset = + CFX_FloatPoint(0.0f, (rcContent.Height() - rcEdit.Height()) / 2.0f); + CFX_ByteString sEdit = CPVT_GenerateAP::GenerateEditAP( + &map, vt.GetIterator(), ptOffset, TRUE, 0); + if (sEdit.GetLength() > 0) { + sAppStream << "/Tx BMC\n" + << "q\n"; + sAppStream << rcEdit.left << " " << rcEdit.bottom << " " + << rcEdit.Width() << " " << rcEdit.Height() << " re\nW\nn\n"; + sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) + << sEdit << "ET\n" + << "Q\nEMC\n"; + } + CFX_ByteString sButton = CPVT_GenerateAP::GenerateColorAP( + CPVT_Color(CPVT_Color::kRGB, 220.0f / 255.0f, 220.0f / 255.0f, + 220.0f / 255.0f), + TRUE); + if (sButton.GetLength() > 0 && !rcButton.IsEmpty()) { + sAppStream << "q\n" << sButton; + sAppStream << rcButton.left << " " << rcButton.bottom << " " + << rcButton.Width() << " " << rcButton.Height() << " re f\n"; + sAppStream << "Q\n"; + CFX_ByteString sButtonBorder = CPVT_GenerateAP::GenerateBorderAP( + rcButton, 2, CPVT_Color(CPVT_Color::kGray, 0), + CPVT_Color(CPVT_Color::kGray, 1), + CPVT_Color(CPVT_Color::kGray, 0.5), PBS_BEVELED, + CPVT_Dash(3, 0, 0)); + if (sButtonBorder.GetLength() > 0) + sAppStream << "q\n" << sButtonBorder << "Q\n"; + + CFX_FloatPoint ptCenter = + CFX_FloatPoint((rcButton.left + rcButton.right) / 2, + (rcButton.top + rcButton.bottom) / 2); + if (IsFloatBigger(rcButton.Width(), 6) && + IsFloatBigger(rcButton.Height(), 6)) { + sAppStream << "q\n" + << " 0 g\n"; + sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n"; + sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n"; + sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n"; + sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n"; + sAppStream << sButton << "Q\n"; + } + } + } break; + case 2: { + CPVT_FontMap map( + pDoc, pStreamDict ? pStreamDict->GetDictBy("Resources") : nullptr, + pDefFont, sFontName.Right(sFontName.GetLength() - 1)); + CPVT_Provider prd(&map); + CPDF_Array* pOpts = FPDF_GetFieldAttr(pAnnotDict, "Opt") + ? FPDF_GetFieldAttr(pAnnotDict, "Opt")->GetArray() + : nullptr; + CPDF_Array* pSels = FPDF_GetFieldAttr(pAnnotDict, "I") + ? FPDF_GetFieldAttr(pAnnotDict, "I")->GetArray() + : nullptr; + int32_t nTop = FPDF_GetFieldAttr(pAnnotDict, "TI") + ? FPDF_GetFieldAttr(pAnnotDict, "TI")->GetInteger() + : 0; + CFX_ByteTextBuf sBody; + if (pOpts) { + FX_FLOAT fy = rcBody.top; + for (int32_t i = nTop, sz = pOpts->GetCount(); i < sz; i++) { + if (IsFloatSmaller(fy, rcBody.bottom)) + break; + + if (CPDF_Object* pOpt = pOpts->GetDirectObjectAt(i)) { + CFX_WideString swItem; + if (pOpt->IsString()) + swItem = pOpt->GetUnicodeText(); + else if (CPDF_Array* pArray = pOpt->AsArray()) + swItem = pArray->GetDirectObjectAt(1)->GetUnicodeText(); + + FX_BOOL bSelected = FALSE; + if (pSels) { + for (uint32_t s = 0, ssz = pSels->GetCount(); s < ssz; s++) { + if (i == pSels->GetIntegerAt(s)) { + bSelected = TRUE; + break; + } + } + } + CPDF_VariableText vt; + vt.SetProvider(&prd); + vt.SetPlateRect( + CFX_FloatRect(rcBody.left, 0.0f, rcBody.right, 0.0f)); + vt.SetFontSize(IsFloatZero(fFontSize) ? 12.0f : fFontSize); + + vt.Initialize(); + vt.SetText(swItem.c_str()); + vt.RearrangeAll(); + FX_FLOAT fItemHeight = vt.GetContentRect().Height(); + if (bSelected) { + CFX_FloatRect rcItem = CFX_FloatRect( + rcBody.left, fy - fItemHeight, rcBody.right, fy); + sBody << "q\n" << CPVT_GenerateAP::GenerateColorAP( + CPVT_Color(CPVT_Color::kRGB, 0, + 51.0f / 255.0f, 113.0f / 255.0f), + TRUE) + << rcItem.left << " " << rcItem.bottom << " " + << rcItem.Width() << " " << rcItem.Height() << " re f\n" + << "Q\n"; + sBody << "BT\n" << CPVT_GenerateAP::GenerateColorAP( + CPVT_Color(CPVT_Color::kGray, 1), TRUE) + << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), + CFX_FloatPoint(0.0f, fy), + TRUE, 0) + << "ET\n"; + } else { + sBody << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) + << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), + CFX_FloatPoint(0.0f, fy), + TRUE, 0) + << "ET\n"; + } + fy -= fItemHeight; + } + } + } + if (sBody.GetSize() > 0) { + sAppStream << "/Tx BMC\n" + << "q\n"; + sAppStream << rcBody.left << " " << rcBody.bottom << " " + << rcBody.Width() << " " << rcBody.Height() << " re\nW\nn\n"; + sAppStream << sBody.GetByteString() << "Q\nEMC\n"; + } + } break; + } + if (pNormalStream) { + pNormalStream->SetData((uint8_t*)sAppStream.GetBuffer(), + sAppStream.GetSize(), FALSE, FALSE); + pStreamDict = pNormalStream->GetDict(); + if (pStreamDict) { + pStreamDict->SetAtMatrix("Matrix", matrix); + pStreamDict->SetAtRect("BBox", rcBBox); + CPDF_Dictionary* pStreamResList = pStreamDict->GetDictBy("Resources"); + if (pStreamResList) { + CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDictBy("Font"); + if (!pStreamResFontList) { + pStreamResFontList = new CPDF_Dictionary; + pStreamResList->SetAt("Font", pStreamResFontList); + } + if (!pStreamResFontList->KeyExist(sFontName)) + pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict); + } else { + pStreamDict->SetAt("Resources", pFormDict->GetDictBy("DR")->Clone()); + pStreamResList = pStreamDict->GetDictBy("Resources"); + } + } + } + return TRUE; +} + +} // namespace + +FX_BOOL FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { + if (!pAnnotDict || pAnnotDict->GetConstStringBy("Subtype") != "Widget") { + return FALSE; + } + CFX_ByteString field_type = FPDF_GetFieldAttr(pAnnotDict, "FT")->GetString(); + uint32_t flags = FPDF_GetFieldAttr(pAnnotDict, "Ff") + ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() + : 0; + if (field_type == "Tx") { + return CPVT_GenerateAP::GenerateTextFieldAP(pDoc, pAnnotDict); + } + if (field_type == "Ch") { + return (flags & (1 << 17)) + ? CPVT_GenerateAP::GenerateComboBoxAP(pDoc, pAnnotDict) + : CPVT_GenerateAP::GenerateListBoxAP(pDoc, pAnnotDict); + } + if (field_type == "Btn") { + if (!(flags & (1 << 16))) { + if (!pAnnotDict->KeyExist("AS")) { + if (CPDF_Dictionary* pParentDict = pAnnotDict->GetDictBy("Parent")) { + if (pParentDict->KeyExist("AS")) { + pAnnotDict->SetAtString("AS", pParentDict->GetStringBy("AS")); + } + } + } + } + } + return FALSE; +} + +// Static. +FX_BOOL CPVT_GenerateAP::GenerateTextFieldAP(CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict) { + return GenerateWidgetAP(pDoc, pAnnotDict, 0); +} + +// Static. +FX_BOOL CPVT_GenerateAP::GenerateComboBoxAP(CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict) { + return GenerateWidgetAP(pDoc, pAnnotDict, 1); +} + +// Static. +FX_BOOL CPVT_GenerateAP::GenerateListBoxAP(CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict) { + return GenerateWidgetAP(pDoc, pAnnotDict, 2); +} + +// Static. +CFX_ByteString CPVT_GenerateAP::GenerateEditAP( + IPVT_FontMap* pFontMap, + IPDF_VariableText_Iterator* pIterator, + const CFX_FloatPoint& ptOffset, + FX_BOOL bContinuous, + uint16_t SubWord, + const CPVT_WordRange* pVisible) { + CFX_ByteTextBuf sEditStream, sLineStream, sWords; + CFX_FloatPoint ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f); + int32_t nCurFontIndex = -1; + if (pIterator) { + if (pVisible) + pIterator->SetAt(pVisible->BeginPos); + else + pIterator->SetAt(0); + + CPVT_WordPlace oldplace; + while (pIterator->NextWord()) { + CPVT_WordPlace place = pIterator->GetAt(); + if (pVisible && place.WordCmp(pVisible->EndPos) > 0) + break; + + if (bContinuous) { + if (place.LineCmp(oldplace) != 0) { + if (sWords.GetSize() > 0) { + sLineStream << GetWordRenderString(sWords.GetByteString()); + sEditStream << sLineStream; + sLineStream.Clear(); + 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) { + sLineStream << 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) { + sLineStream << GetWordRenderString(sWords.GetByteString()); + sWords.Clear(); + } + sLineStream << GetFontSetString(pFontMap, word.nFontIndex, + word.fFontSize); + nCurFontIndex = word.nFontIndex; + } + sWords << GetPDFWordString(pFontMap, 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(pFontMap, word.nFontIndex, + word.fFontSize); + nCurFontIndex = word.nFontIndex; + } + sEditStream << GetWordRenderString( + GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord)); + } + } + } + if (sWords.GetSize() > 0) { + sLineStream << GetWordRenderString(sWords.GetByteString()); + sEditStream << sLineStream; + sWords.Clear(); + } + } + return sEditStream.GetByteString(); +} + +// Static. +CFX_ByteString CPVT_GenerateAP::GenerateBorderAP( + const CFX_FloatRect& rect, + FX_FLOAT fWidth, + const CPVT_Color& color, + const CPVT_Color& crLeftTop, + const CPVT_Color& crRightBottom, + int32_t nStyle, + const CPVT_Dash& dash) { + CFX_ByteTextBuf sAppStream; + CFX_ByteString sColor; + FX_FLOAT fLeft = rect.left; + FX_FLOAT fRight = rect.right; + FX_FLOAT fTop = rect.top; + FX_FLOAT fBottom = rect.bottom; + if (fWidth > 0.0f) { + FX_FLOAT fHalfWidth = fWidth / 2.0f; + switch (nStyle) { + default: + case PBS_SOLID: + sColor = GenerateColorAP(color, TRUE); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " + << fTop - fBottom << " re\n"; + sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " " + << fRight - fLeft - fWidth * 2 << " " + << fTop - fBottom - fWidth * 2 << " re\n"; + sAppStream << "f*\n"; + } + break; + case PBS_DASH: + sColor = GenerateColorAP(color, FALSE); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fWidth << " w" + << " [" << dash.nDash << " " << dash.nGap << "] " + << dash.nPhase << " d\n"; + sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 + << " m\n"; + sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 + << " l\n"; + sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 + << " l\n"; + sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2 + << " l\n"; + sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 + << " l S\n"; + } + break; + case PBS_BEVELED: + case PBS_INSET: + sColor = GenerateColorAP(crLeftTop, TRUE); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth + << " m\n"; + sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth + << " l\n"; + sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth + << " l\n"; + sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 + << " l\n"; + sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 + << " l\n"; + sAppStream << fLeft + fHalfWidth * 2 << " " + << fBottom + fHalfWidth * 2 << " l f\n"; + } + sColor = GenerateColorAP(crRightBottom, TRUE); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth + << " m\n"; + sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth + << " l\n"; + sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth + << " l\n"; + sAppStream << fLeft + fHalfWidth * 2 << " " + << fBottom + fHalfWidth * 2 << " l\n"; + sAppStream << fRight - fHalfWidth * 2 << " " + << fBottom + fHalfWidth * 2 << " l\n"; + sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 + << " l f\n"; + } + sColor = GenerateColorAP(color, TRUE); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " + << fTop - fBottom << " re\n"; + sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " " + << fRight - fLeft - fHalfWidth * 2 << " " + << fTop - fBottom - fHalfWidth * 2 << " re f*\n"; + } + break; + case PBS_UNDERLINED: + sColor = GenerateColorAP(color, FALSE); + if (sColor.GetLength() > 0) { + sAppStream << sColor; + sAppStream << fWidth << " w\n"; + sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n"; + sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n"; + } + break; + } + } + return sAppStream.GetByteString(); +} + +// Static. +CFX_ByteString CPVT_GenerateAP::GenerateColorAP(const CPVT_Color& color, + const FX_BOOL& bFillOrStroke) { + CFX_ByteTextBuf sColorStream; + switch (color.nColorType) { + case CPVT_Color::kRGB: + sColorStream << color.fColor1 << " " << color.fColor2 << " " + << color.fColor3 << " " << (bFillOrStroke ? "rg" : "RG") + << "\n"; + break; + case CPVT_Color::kGray: + sColorStream << color.fColor1 << " " << (bFillOrStroke ? "g" : "G") + << "\n"; + break; + case CPVT_Color::kCMYK: + sColorStream << color.fColor1 << " " << color.fColor2 << " " + << color.fColor3 << " " << color.fColor4 << " " + << (bFillOrStroke ? "k" : "K") << "\n"; + break; + case CPVT_Color::kTransparent: + break; + } + return sColorStream.GetByteString(); +} + +// Static. +CFX_ByteString CPVT_GenerateAP::GetPDFWordString(IPVT_FontMap* pFontMap, + int32_t nFontIndex, + uint16_t Word, + uint16_t SubWord) { + CFX_ByteString sWord; + if (SubWord > 0) { + sWord.Format("%c", SubWord); + return sWord; + } + + if (!pFontMap) + return sWord; + + if (CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex)) { + if (pPDFFont->GetBaseFont().Compare("Symbol") == 0 || + pPDFFont->GetBaseFont().Compare("ZapfDingbats") == 0) { + sWord.Format("%c", Word); + } else { + uint32_t dwCharCode = pPDFFont->CharCodeFromUnicode(Word); + if (dwCharCode != CPDF_Font::kInvalidCharCode) + pPDFFont->AppendChar(sWord, dwCharCode); + } + } + return sWord; +} + +// Static. +CFX_ByteString CPVT_GenerateAP::GetWordRenderString( + const CFX_ByteString& strWords) { + if (strWords.GetLength() > 0) + return PDF_EncodeString(strWords) + " Tj\n"; + return ""; +} + +// Static. +CFX_ByteString CPVT_GenerateAP::GetFontSetString(IPVT_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(); +} diff --git a/core/fpdfdoc/cpvt_generateap.h b/core/fpdfdoc/cpvt_generateap.h new file mode 100644 index 0000000000..b97b38ad6b --- /dev/null +++ b/core/fpdfdoc/cpvt_generateap.h @@ -0,0 +1,66 @@ +// Copyright 2016 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 + +#ifndef CORE_FPDFDOC_CPVT_GENERATEAP_H_ +#define CORE_FPDFDOC_CPVT_GENERATEAP_H_ + +#include "core/fpdfdoc/cpvt_color.h" +#include "core/fpdfdoc/cpvt_dash.h" +#include "core/fxcrt/include/fx_coordinates.h" +#include "core/fxcrt/include/fx_string.h" +#include "core/fxcrt/include/fx_system.h" + +// border style +#define PBS_SOLID 0 +#define PBS_DASH 1 +#define PBS_BEVELED 2 +#define PBS_INSET 3 +#define PBS_UNDERLINED 4 +#define PBS_SHADOW 5 + +class CPDF_Dictionary; +class CPDF_Document; +class IPDF_VariableText_Iterator; +class IPVT_FontMap; +struct CPVT_WordRange; + +FX_BOOL FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict); + +class CPVT_GenerateAP { + public: + static FX_BOOL GenerateTextFieldAP(CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict); + static FX_BOOL GenerateComboBoxAP(CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict); + static FX_BOOL GenerateListBoxAP(CPDF_Document* pDoc, + CPDF_Dictionary* pAnnotDict); + static CFX_ByteString GenerateEditAP(IPVT_FontMap* pFontMap, + IPDF_VariableText_Iterator* pIterator, + const CFX_FloatPoint& ptOffset, + FX_BOOL bContinuous, + uint16_t SubWord = 0, + const CPVT_WordRange* pVisible = NULL); + static CFX_ByteString GenerateBorderAP(const CFX_FloatRect& rect, + FX_FLOAT fWidth, + const CPVT_Color& color, + const CPVT_Color& crLeftTop, + const CPVT_Color& crRightBottom, + int32_t nStyle, + const CPVT_Dash& dash); + static CFX_ByteString GenerateColorAP(const CPVT_Color& color, + const FX_BOOL& bFillOrStroke); + + static CFX_ByteString GetPDFWordString(IPVT_FontMap* pFontMap, + int32_t nFontIndex, + uint16_t Word, + uint16_t SubWord); + static CFX_ByteString GetWordRenderString(const CFX_ByteString& strWords); + static CFX_ByteString GetFontSetString(IPVT_FontMap* pFontMap, + int32_t nFontIndex, + FX_FLOAT fFontSize); +}; + +#endif // CORE_FPDFDOC_CPVT_GENERATEAP_H_ diff --git a/core/fpdfdoc/cpvt_provider.h b/core/fpdfdoc/cpvt_provider.h new file mode 100644 index 0000000000..e7edd538e5 --- /dev/null +++ b/core/fpdfdoc/cpvt_provider.h @@ -0,0 +1,35 @@ +// Copyright 2016 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 + +#ifndef CORE_FPDFDOC_CPVT_PROVIDER_H_ +#define CORE_FPDFDOC_CPVT_PROVIDER_H_ + +#include "core/fpdfdoc/include/ipdf_variabletext_provider.h" +#include "core/fpdfdoc/ipvt_fontmap.h" +#include "core/fxcrt/include/fx_system.h" + +class CPVT_Provider : public IPDF_VariableText_Provider { + public: + CPVT_Provider(IPVT_FontMap* pFontMap); + ~CPVT_Provider() override; + + // IPDF_VariableText_Provider + int32_t GetCharWidth(int32_t nFontIndex, + uint16_t word, + int32_t nWordStyle) override; + int32_t GetTypeAscent(int32_t nFontIndex) override; + int32_t GetTypeDescent(int32_t nFontIndex) override; + int32_t GetWordFontIndex(uint16_t word, + int32_t charset, + int32_t nFontIndex) override; + FX_BOOL IsLatinWord(uint16_t word) override; + int32_t GetDefaultFontIndex() override; + + private: + IPVT_FontMap* m_pFontMap; +}; + +#endif // CORE_FPDFDOC_CPVT_PROVIDER_H_ diff --git a/core/fpdfdoc/doc_annot.cpp b/core/fpdfdoc/doc_annot.cpp index 1ea6c8b5a8..276516589a 100644 --- a/core/fpdfdoc/doc_annot.cpp +++ b/core/fpdfdoc/doc_annot.cpp @@ -12,6 +12,7 @@ #include "core/fpdfapi/fpdf_parser/ipdf_occontext.h" #include "core/fpdfapi/fpdf_render/include/cpdf_rendercontext.h" #include "core/fpdfapi/fpdf_render/include/cpdf_renderoptions.h" +#include "core/fpdfdoc/cpvt_generateap.h" #include "core/include/fpdfdoc/fpdf_doc.h" #include "core/include/fxge/fx_ge.h" diff --git a/core/fpdfdoc/doc_ap.cpp b/core/fpdfdoc/doc_ap.cpp index e87b21b8ec..440979e229 100644 --- a/core/fpdfdoc/doc_ap.cpp +++ b/core/fpdfdoc/doc_ap.cpp @@ -9,130 +9,12 @@ #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_stream.h" +#include "core/fpdfdoc/cpvt_provider.h" #include "core/fpdfdoc/doc_utils.h" #include "core/fpdfdoc/pdf_vt.h" -#include "core/include/fpdfdoc/fpdf_ap.h" #include "core/include/fpdfdoc/fpdf_doc.h" #include "core/include/fpdfdoc/fpdf_vt.h" -#define PBS_SOLID 0 -#define PBS_DASH 1 -#define PBS_BEVELED 2 -#define PBS_INSET 3 -#define PBS_UNDERLINED 4 - -FX_BOOL FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict) { - if (!pAnnotDict || pAnnotDict->GetConstStringBy("Subtype") != "Widget") { - return FALSE; - } - CFX_ByteString field_type = FPDF_GetFieldAttr(pAnnotDict, "FT")->GetString(); - uint32_t flags = FPDF_GetFieldAttr(pAnnotDict, "Ff") - ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() - : 0; - if (field_type == "Tx") { - return CPVT_GenerateAP::GenerateTextFieldAP(pDoc, pAnnotDict); - } - if (field_type == "Ch") { - return (flags & (1 << 17)) - ? CPVT_GenerateAP::GenerateComboBoxAP(pDoc, pAnnotDict) - : CPVT_GenerateAP::GenerateListBoxAP(pDoc, pAnnotDict); - } - if (field_type == "Btn") { - if (!(flags & (1 << 16))) { - if (!pAnnotDict->KeyExist("AS")) { - if (CPDF_Dictionary* pParentDict = pAnnotDict->GetDictBy("Parent")) { - if (pParentDict->KeyExist("AS")) { - pAnnotDict->SetAtString("AS", pParentDict->GetStringBy("AS")); - } - } - } - } - } - return FALSE; -} - -class CPVT_FontMap : public IPVT_FontMap { - public: - CPVT_FontMap(CPDF_Document* pDoc, - CPDF_Dictionary* pResDict, - CPDF_Font* pDefFont, - const CFX_ByteString& sDefFontAlias); - ~CPVT_FontMap() override; - - // IPVT_FontMap - CPDF_Font* GetPDFFont(int32_t nFontIndex) override; - CFX_ByteString GetPDFFontAlias(int32_t nFontIndex) override; - - static void GetAnnotSysPDFFont(CPDF_Document* pDoc, - CPDF_Dictionary* pResDict, - CPDF_Font*& pSysFont, - CFX_ByteString& sSysFontAlias); - - private: - CPDF_Document* m_pDocument; - CPDF_Dictionary* m_pResDict; - CPDF_Font* m_pDefFont; - CFX_ByteString m_sDefFontAlias; - CPDF_Font* m_pSysFont; - CFX_ByteString m_sSysFontAlias; -}; - -CPVT_FontMap::CPVT_FontMap(CPDF_Document* pDoc, - CPDF_Dictionary* pResDict, - CPDF_Font* pDefFont, - const CFX_ByteString& sDefFontAlias) - : m_pDocument(pDoc), - m_pResDict(pResDict), - m_pDefFont(pDefFont), - m_sDefFontAlias(sDefFontAlias), - m_pSysFont(NULL), - m_sSysFontAlias() {} -CPVT_FontMap::~CPVT_FontMap() {} -void CPVT_FontMap::GetAnnotSysPDFFont(CPDF_Document* pDoc, - CPDF_Dictionary* pResDict, - CPDF_Font*& pSysFont, - CFX_ByteString& sSysFontAlias) { - if (pDoc && pResDict) { - CFX_ByteString sFontAlias; - CPDF_Dictionary* pFormDict = pDoc->GetRoot()->GetDictBy("AcroForm"); - if (CPDF_Font* pPDFFont = - AddNativeInterFormFont(pFormDict, pDoc, sSysFontAlias)) { - if (CPDF_Dictionary* pFontList = pResDict->GetDictBy("Font")) { - if (!pFontList->KeyExist(sSysFontAlias)) { - pFontList->SetAtReference(sSysFontAlias, pDoc, - pPDFFont->GetFontDict()); - } - } - pSysFont = pPDFFont; - } - } -} -CPDF_Font* CPVT_FontMap::GetPDFFont(int32_t nFontIndex) { - switch (nFontIndex) { - case 0: - return m_pDefFont; - case 1: - if (!m_pSysFont) { - GetAnnotSysPDFFont(m_pDocument, m_pResDict, m_pSysFont, - m_sSysFontAlias); - } - return m_pSysFont; - } - return NULL; -} -CFX_ByteString CPVT_FontMap::GetPDFFontAlias(int32_t nFontIndex) { - switch (nFontIndex) { - case 0: - return m_sDefFontAlias; - case 1: - if (!m_pSysFont) { - GetAnnotSysPDFFont(m_pDocument, m_pResDict, m_pSysFont, - m_sSysFontAlias); - } - return m_sSysFontAlias; - } - return ""; -} CPVT_Provider::CPVT_Provider(IPVT_FontMap* pFontMap) : m_pFontMap(pFontMap) { ASSERT(m_pFontMap); } @@ -186,753 +68,3 @@ int32_t CPVT_Provider::GetDefaultFontIndex() { return 0; } -static CFX_ByteString GetPDFWordString(IPVT_FontMap* pFontMap, - int32_t nFontIndex, - uint16_t Word, - uint16_t SubWord) { - CFX_ByteString sWord; - if (SubWord > 0) { - sWord.Format("%c", SubWord); - return sWord; - } - - if (!pFontMap) - return sWord; - - if (CPDF_Font* pPDFFont = pFontMap->GetPDFFont(nFontIndex)) { - if (pPDFFont->GetBaseFont().Compare("Symbol") == 0 || - pPDFFont->GetBaseFont().Compare("ZapfDingbats") == 0) { - sWord.Format("%c", Word); - } else { - uint32_t dwCharCode = pPDFFont->CharCodeFromUnicode(Word); - if (dwCharCode != CPDF_Font::kInvalidCharCode) { - pPDFFont->AppendChar(sWord, dwCharCode); - } - } - } - 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(IPVT_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(); -} -static CPVT_Color ParseColor(const CFX_ByteString& str) { - CPDF_SimpleParser syntax(str); - if (syntax.FindTagParamFromStart("g", 1)) { - return CPVT_Color(CPVT_Color::kGray, FX_atof(syntax.GetWord())); - } - if (syntax.FindTagParamFromStart("rg", 3)) { - FX_FLOAT f1 = FX_atof(syntax.GetWord()); - FX_FLOAT f2 = FX_atof(syntax.GetWord()); - FX_FLOAT f3 = FX_atof(syntax.GetWord()); - return CPVT_Color(CPVT_Color::kRGB, f1, f2, f3); - } - if (syntax.FindTagParamFromStart("k", 4)) { - FX_FLOAT f1 = FX_atof(syntax.GetWord()); - FX_FLOAT f2 = FX_atof(syntax.GetWord()); - FX_FLOAT f3 = FX_atof(syntax.GetWord()); - FX_FLOAT f4 = FX_atof(syntax.GetWord()); - return CPVT_Color(CPVT_Color::kCMYK, f1, f2, f3, f4); - } - return CPVT_Color(CPVT_Color::kTransparent); -} -static CPVT_Color ParseColor(const CPDF_Array& array) { - CPVT_Color rt; - switch (array.GetCount()) { - case 1: - rt = CPVT_Color(CPVT_Color::kGray, array.GetFloatAt(0)); - break; - case 3: - rt = CPVT_Color(CPVT_Color::kRGB, array.GetFloatAt(0), - array.GetFloatAt(1), array.GetFloatAt(2)); - break; - case 4: - rt = CPVT_Color(CPVT_Color::kCMYK, array.GetFloatAt(0), - array.GetFloatAt(1), array.GetFloatAt(2), - array.GetFloatAt(3)); - break; - } - return rt; -} -static FX_BOOL GenerateWidgetAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict, - const int32_t& nWidgetType) { - CPDF_Dictionary* pFormDict = NULL; - if (CPDF_Dictionary* pRootDict = pDoc->GetRoot()) { - pFormDict = pRootDict->GetDictBy("AcroForm"); - } - if (!pFormDict) { - return FALSE; - } - CFX_ByteString DA; - if (CPDF_Object* pDAObj = FPDF_GetFieldAttr(pAnnotDict, "DA")) { - DA = pDAObj->GetString(); - } - if (DA.IsEmpty()) { - DA = pFormDict->GetStringBy("DA"); - } - if (DA.IsEmpty()) { - return FALSE; - } - CPDF_SimpleParser syntax(DA); - syntax.FindTagParamFromStart("Tf", 2); - CFX_ByteString sFontName = syntax.GetWord(); - sFontName = PDF_NameDecode(sFontName); - if (sFontName.IsEmpty()) { - return FALSE; - } - FX_FLOAT fFontSize = FX_atof(syntax.GetWord()); - CPVT_Color crText = ParseColor(DA); - FX_BOOL bUseFormRes = FALSE; - CPDF_Dictionary* pFontDict = NULL; - CPDF_Dictionary* pDRDict = pAnnotDict->GetDictBy("DR"); - if (!pDRDict) { - pDRDict = pFormDict->GetDictBy("DR"); - bUseFormRes = TRUE; - } - CPDF_Dictionary* pDRFontDict = pDRDict ? pDRDict->GetDictBy("Font") : nullptr; - if (pDRFontDict) { - pFontDict = pDRFontDict->GetDictBy(sFontName.Mid(1)); - if (!pFontDict && !bUseFormRes) { - pDRDict = pFormDict->GetDictBy("DR"); - pDRFontDict = pDRDict->GetDictBy("Font"); - if (pDRFontDict) { - pFontDict = pDRFontDict->GetDictBy(sFontName.Mid(1)); - } - } - } - if (!pDRFontDict) { - return FALSE; - } - if (!pFontDict) { - pFontDict = new CPDF_Dictionary; - pFontDict->SetAtName("Type", "Font"); - pFontDict->SetAtName("Subtype", "Type1"); - pFontDict->SetAtName("BaseFont", "Helvetica"); - pFontDict->SetAtName("Encoding", "WinAnsiEncoding"); - pDoc->AddIndirectObject(pFontDict); - pDRFontDict->SetAtReference(sFontName.Mid(1), pDoc, pFontDict); - } - CPDF_Font* pDefFont = pDoc->LoadFont(pFontDict); - if (!pDefFont) { - return FALSE; - } - CFX_FloatRect rcAnnot = pAnnotDict->GetRectBy("Rect"); - int32_t nRotate = 0; - if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDictBy("MK")) { - nRotate = pMKDict->GetIntegerBy("R"); - } - CFX_FloatRect rcBBox; - CFX_Matrix matrix; - switch (nRotate % 360) { - case 0: - rcBBox = CFX_FloatRect(0, 0, rcAnnot.right - rcAnnot.left, - rcAnnot.top - rcAnnot.bottom); - break; - case 90: - matrix = CFX_Matrix(0, 1, -1, 0, rcAnnot.right - rcAnnot.left, 0); - rcBBox = CFX_FloatRect(0, 0, rcAnnot.top - rcAnnot.bottom, - rcAnnot.right - rcAnnot.left); - break; - case 180: - matrix = CFX_Matrix(-1, 0, 0, -1, rcAnnot.right - rcAnnot.left, - rcAnnot.top - rcAnnot.bottom); - rcBBox = CFX_FloatRect(0, 0, rcAnnot.right - rcAnnot.left, - rcAnnot.top - rcAnnot.bottom); - break; - case 270: - matrix = CFX_Matrix(0, -1, 1, 0, 0, rcAnnot.top - rcAnnot.bottom); - rcBBox = CFX_FloatRect(0, 0, rcAnnot.top - rcAnnot.bottom, - rcAnnot.right - rcAnnot.left); - break; - } - int32_t nBorderStyle = PBS_SOLID; - FX_FLOAT fBorderWidth = 1; - CPVT_Dash dsBorder(3, 0, 0); - CPVT_Color crLeftTop, crRightBottom; - if (CPDF_Dictionary* pBSDict = pAnnotDict->GetDictBy("BS")) { - if (pBSDict->KeyExist("W")) { - fBorderWidth = pBSDict->GetNumberBy("W"); - } - if (CPDF_Array* pArray = pBSDict->GetArrayBy("D")) { - dsBorder = CPVT_Dash(pArray->GetIntegerAt(0), pArray->GetIntegerAt(1), - pArray->GetIntegerAt(2)); - } - switch (pBSDict->GetStringBy("S").GetAt(0)) { - case 'S': - nBorderStyle = PBS_SOLID; - break; - case 'D': - nBorderStyle = PBS_DASH; - break; - case 'B': - nBorderStyle = PBS_BEVELED; - fBorderWidth *= 2; - crLeftTop = CPVT_Color(CPVT_Color::kGray, 1); - crRightBottom = CPVT_Color(CPVT_Color::kGray, 0.5); - break; - case 'I': - nBorderStyle = PBS_INSET; - fBorderWidth *= 2; - crLeftTop = CPVT_Color(CPVT_Color::kGray, 0.5); - crRightBottom = CPVT_Color(CPVT_Color::kGray, 0.75); - break; - case 'U': - nBorderStyle = PBS_UNDERLINED; - break; - } - } - CPVT_Color crBorder, crBG; - if (CPDF_Dictionary* pMKDict = pAnnotDict->GetDictBy("MK")) { - if (CPDF_Array* pArray = pMKDict->GetArrayBy("BC")) { - crBorder = ParseColor(*pArray); - } - if (CPDF_Array* pArray = pMKDict->GetArrayBy("BG")) { - crBG = ParseColor(*pArray); - } - } - CFX_ByteTextBuf sAppStream; - CFX_ByteString sBG = CPVT_GenerateAP::GenerateColorAP(crBG, TRUE); - if (sBG.GetLength() > 0) { - sAppStream << "q\n" << sBG << rcBBox.left << " " << rcBBox.bottom << " " - << rcBBox.Width() << " " << rcBBox.Height() << " re f\n" - << "Q\n"; - } - CFX_ByteString sBorderStream = CPVT_GenerateAP::GenerateBorderAP( - rcBBox, fBorderWidth, crBorder, crLeftTop, crRightBottom, nBorderStyle, - dsBorder); - if (sBorderStream.GetLength() > 0) { - sAppStream << "q\n" << sBorderStream << "Q\n"; - } - CFX_FloatRect rcBody = - CFX_FloatRect(rcBBox.left + fBorderWidth, rcBBox.bottom + fBorderWidth, - rcBBox.right - fBorderWidth, rcBBox.top - fBorderWidth); - rcBody.Normalize(); - CPDF_Dictionary* pAPDict = pAnnotDict->GetDictBy("AP"); - if (!pAPDict) { - pAPDict = new CPDF_Dictionary; - pAnnotDict->SetAt("AP", pAPDict); - } - CPDF_Stream* pNormalStream = pAPDict->GetStreamBy("N"); - if (!pNormalStream) { - pNormalStream = new CPDF_Stream(nullptr, 0, nullptr); - int32_t objnum = pDoc->AddIndirectObject(pNormalStream); - pAnnotDict->GetDictBy("AP")->SetAtReference("N", pDoc, objnum); - } - CPDF_Dictionary* pStreamDict = pNormalStream->GetDict(); - if (pStreamDict) { - pStreamDict->SetAtMatrix("Matrix", matrix); - pStreamDict->SetAtRect("BBox", rcBBox); - CPDF_Dictionary* pStreamResList = pStreamDict->GetDictBy("Resources"); - if (pStreamResList) { - CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDictBy("Font"); - if (!pStreamResFontList) { - pStreamResFontList = new CPDF_Dictionary; - pStreamResList->SetAt("Font", pStreamResFontList); - } - if (!pStreamResFontList->KeyExist(sFontName)) { - pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict); - } - } else { - pStreamDict->SetAt("Resources", pFormDict->GetDictBy("DR")->Clone()); - pStreamResList = pStreamDict->GetDictBy("Resources"); - } - } - switch (nWidgetType) { - case 0: { - CFX_WideString swValue = - FPDF_GetFieldAttr(pAnnotDict, "V") - ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() - : CFX_WideString(); - int32_t nAlign = FPDF_GetFieldAttr(pAnnotDict, "Q") - ? FPDF_GetFieldAttr(pAnnotDict, "Q")->GetInteger() - : 0; - uint32_t dwFlags = FPDF_GetFieldAttr(pAnnotDict, "Ff") - ? FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger() - : 0; - uint32_t dwMaxLen = - FPDF_GetFieldAttr(pAnnotDict, "MaxLen") - ? FPDF_GetFieldAttr(pAnnotDict, "MaxLen")->GetInteger() - : 0; - CPVT_FontMap map(pDoc, - pStreamDict ? pStreamDict->GetDictBy("Resources") : NULL, - pDefFont, sFontName.Right(sFontName.GetLength() - 1)); - CPVT_Provider prd(&map); - CPDF_VariableText vt; - vt.SetProvider(&prd); - vt.SetPlateRect(rcBody); - vt.SetAlignment(nAlign); - if (IsFloatZero(fFontSize)) { - vt.SetAutoFontSize(TRUE); - } else { - vt.SetFontSize(fFontSize); - } - FX_BOOL bMultiLine = (dwFlags >> 12) & 1; - if (bMultiLine) { - vt.SetMultiLine(TRUE); - vt.SetAutoReturn(TRUE); - } - uint16_t subWord = 0; - if ((dwFlags >> 13) & 1) { - subWord = '*'; - vt.SetPasswordChar(subWord); - } - FX_BOOL bCharArray = (dwFlags >> 24) & 1; - if (bCharArray) { - vt.SetCharArray(dwMaxLen); - } else { - vt.SetLimitChar(dwMaxLen); - } - vt.Initialize(); - vt.SetText(swValue.c_str()); - vt.RearrangeAll(); - CFX_FloatRect rcContent = vt.GetContentRect(); - CFX_FloatPoint ptOffset(0.0f, 0.0f); - if (!bMultiLine) { - ptOffset = - CFX_FloatPoint(0.0f, (rcContent.Height() - rcBody.Height()) / 2.0f); - } - CFX_ByteString sBody = CPVT_GenerateAP::GenerateEditAP( - &map, vt.GetIterator(), ptOffset, !bCharArray, subWord); - if (sBody.GetLength() > 0) { - sAppStream << "/Tx BMC\n" - << "q\n"; - if (rcContent.Width() > rcBody.Width() || - rcContent.Height() > rcBody.Height()) { - sAppStream << rcBody.left << " " << rcBody.bottom << " " - << rcBody.Width() << " " << rcBody.Height() - << " re\nW\nn\n"; - } - sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) - << sBody << "ET\n" - << "Q\nEMC\n"; - } - } break; - case 1: { - CFX_WideString swValue = - FPDF_GetFieldAttr(pAnnotDict, "V") - ? FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText() - : CFX_WideString(); - CPVT_FontMap map(pDoc, - pStreamDict ? pStreamDict->GetDictBy("Resources") : NULL, - pDefFont, sFontName.Right(sFontName.GetLength() - 1)); - CPVT_Provider prd(&map); - CPDF_VariableText vt; - vt.SetProvider(&prd); - CFX_FloatRect rcButton = rcBody; - rcButton.left = rcButton.right - 13; - rcButton.Normalize(); - CFX_FloatRect rcEdit = rcBody; - rcEdit.right = rcButton.left; - rcEdit.Normalize(); - vt.SetPlateRect(rcEdit); - if (IsFloatZero(fFontSize)) { - vt.SetAutoFontSize(TRUE); - } else { - vt.SetFontSize(fFontSize); - } - vt.Initialize(); - vt.SetText(swValue.c_str()); - vt.RearrangeAll(); - CFX_FloatRect rcContent = vt.GetContentRect(); - CFX_FloatPoint ptOffset = - CFX_FloatPoint(0.0f, (rcContent.Height() - rcEdit.Height()) / 2.0f); - CFX_ByteString sEdit = CPVT_GenerateAP::GenerateEditAP( - &map, vt.GetIterator(), ptOffset, TRUE, 0); - if (sEdit.GetLength() > 0) { - sAppStream << "/Tx BMC\n" - << "q\n"; - sAppStream << rcEdit.left << " " << rcEdit.bottom << " " - << rcEdit.Width() << " " << rcEdit.Height() << " re\nW\nn\n"; - sAppStream << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) - << sEdit << "ET\n" - << "Q\nEMC\n"; - } - CFX_ByteString sButton = CPVT_GenerateAP::GenerateColorAP( - CPVT_Color(CPVT_Color::kRGB, 220.0f / 255.0f, 220.0f / 255.0f, - 220.0f / 255.0f), - TRUE); - if (sButton.GetLength() > 0 && !rcButton.IsEmpty()) { - sAppStream << "q\n" << sButton; - sAppStream << rcButton.left << " " << rcButton.bottom << " " - << rcButton.Width() << " " << rcButton.Height() << " re f\n"; - sAppStream << "Q\n"; - CFX_ByteString sButtonBorder = CPVT_GenerateAP::GenerateBorderAP( - rcButton, 2, CPVT_Color(CPVT_Color::kGray, 0), - CPVT_Color(CPVT_Color::kGray, 1), - CPVT_Color(CPVT_Color::kGray, 0.5), PBS_BEVELED, - CPVT_Dash(3, 0, 0)); - if (sButtonBorder.GetLength() > 0) { - sAppStream << "q\n" << sButtonBorder << "Q\n"; - } - CFX_FloatPoint ptCenter = - CFX_FloatPoint((rcButton.left + rcButton.right) / 2, - (rcButton.top + rcButton.bottom) / 2); - if (IsFloatBigger(rcButton.Width(), 6) && - IsFloatBigger(rcButton.Height(), 6)) { - sAppStream << "q\n" - << " 0 g\n"; - sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " m\n"; - sAppStream << ptCenter.x + 3 << " " << ptCenter.y + 1.5f << " l\n"; - sAppStream << ptCenter.x << " " << ptCenter.y - 1.5f << " l\n"; - sAppStream << ptCenter.x - 3 << " " << ptCenter.y + 1.5f << " l f\n"; - sAppStream << sButton << "Q\n"; - } - } - } break; - case 2: { - CPVT_FontMap map(pDoc, - pStreamDict ? pStreamDict->GetDictBy("Resources") : NULL, - pDefFont, sFontName.Right(sFontName.GetLength() - 1)); - CPVT_Provider prd(&map); - CPDF_Array* pOpts = FPDF_GetFieldAttr(pAnnotDict, "Opt") - ? FPDF_GetFieldAttr(pAnnotDict, "Opt")->GetArray() - : NULL; - CPDF_Array* pSels = FPDF_GetFieldAttr(pAnnotDict, "I") - ? FPDF_GetFieldAttr(pAnnotDict, "I")->GetArray() - : NULL; - int32_t nTop = FPDF_GetFieldAttr(pAnnotDict, "TI") - ? FPDF_GetFieldAttr(pAnnotDict, "TI")->GetInteger() - : 0; - CFX_ByteTextBuf sBody; - if (pOpts) { - FX_FLOAT fy = rcBody.top; - for (int32_t i = nTop, sz = pOpts->GetCount(); i < sz; i++) { - if (IsFloatSmaller(fy, rcBody.bottom)) { - break; - } - if (CPDF_Object* pOpt = pOpts->GetDirectObjectAt(i)) { - CFX_WideString swItem; - if (pOpt->IsString()) - swItem = pOpt->GetUnicodeText(); - else if (CPDF_Array* pArray = pOpt->AsArray()) - swItem = pArray->GetDirectObjectAt(1)->GetUnicodeText(); - - FX_BOOL bSelected = FALSE; - if (pSels) { - for (uint32_t s = 0, ssz = pSels->GetCount(); s < ssz; s++) { - if (i == pSels->GetIntegerAt(s)) { - bSelected = TRUE; - break; - } - } - } - CPDF_VariableText vt; - vt.SetProvider(&prd); - vt.SetPlateRect( - CFX_FloatRect(rcBody.left, 0.0f, rcBody.right, 0.0f)); - if (IsFloatZero(fFontSize)) { - vt.SetFontSize(12.0f); - } else { - vt.SetFontSize(fFontSize); - } - vt.Initialize(); - vt.SetText(swItem.c_str()); - vt.RearrangeAll(); - FX_FLOAT fItemHeight = vt.GetContentRect().Height(); - if (bSelected) { - CFX_FloatRect rcItem = CFX_FloatRect( - rcBody.left, fy - fItemHeight, rcBody.right, fy); - sBody << "q\n" << CPVT_GenerateAP::GenerateColorAP( - CPVT_Color(CPVT_Color::kRGB, 0, - 51.0f / 255.0f, 113.0f / 255.0f), - TRUE) - << rcItem.left << " " << rcItem.bottom << " " - << rcItem.Width() << " " << rcItem.Height() << " re f\n" - << "Q\n"; - sBody << "BT\n" << CPVT_GenerateAP::GenerateColorAP( - CPVT_Color(CPVT_Color::kGray, 1), TRUE) - << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), - CFX_FloatPoint(0.0f, fy), - TRUE, 0) - << "ET\n"; - } else { - sBody << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) - << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), - CFX_FloatPoint(0.0f, fy), - TRUE, 0) - << "ET\n"; - } - fy -= fItemHeight; - } - } - } - if (sBody.GetSize() > 0) { - sAppStream << "/Tx BMC\n" - << "q\n"; - sAppStream << rcBody.left << " " << rcBody.bottom << " " - << rcBody.Width() << " " << rcBody.Height() << " re\nW\nn\n"; - sAppStream << sBody.GetByteString() << "Q\nEMC\n"; - } - } break; - } - if (pNormalStream) { - pNormalStream->SetData((uint8_t*)sAppStream.GetBuffer(), - sAppStream.GetSize(), FALSE, FALSE); - pStreamDict = pNormalStream->GetDict(); - if (pStreamDict) { - pStreamDict->SetAtMatrix("Matrix", matrix); - pStreamDict->SetAtRect("BBox", rcBBox); - CPDF_Dictionary* pStreamResList = pStreamDict->GetDictBy("Resources"); - if (pStreamResList) { - CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDictBy("Font"); - if (!pStreamResFontList) { - pStreamResFontList = new CPDF_Dictionary; - pStreamResList->SetAt("Font", pStreamResFontList); - } - if (!pStreamResFontList->KeyExist(sFontName)) { - pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict); - } - } else { - pStreamDict->SetAt("Resources", pFormDict->GetDictBy("DR")->Clone()); - pStreamResList = pStreamDict->GetDictBy("Resources"); - } - } - } - return TRUE; -} -FX_BOOL CPVT_GenerateAP::GenerateTextFieldAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - return GenerateWidgetAP(pDoc, pAnnotDict, 0); -} -FX_BOOL CPVT_GenerateAP::GenerateComboBoxAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - return GenerateWidgetAP(pDoc, pAnnotDict, 1); -} -FX_BOOL CPVT_GenerateAP::GenerateListBoxAP(CPDF_Document* pDoc, - CPDF_Dictionary* pAnnotDict) { - return GenerateWidgetAP(pDoc, pAnnotDict, 2); -} -CFX_ByteString CPVT_GenerateAP::GenerateEditAP( - IPVT_FontMap* pFontMap, - IPDF_VariableText_Iterator* pIterator, - const CFX_FloatPoint& ptOffset, - FX_BOOL bContinuous, - uint16_t SubWord, - const CPVT_WordRange* pVisible) { - CFX_ByteTextBuf sEditStream, sLineStream, sWords; - CFX_FloatPoint ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f); - int32_t nCurFontIndex = -1; - if (pIterator) { - if (pVisible) { - pIterator->SetAt(pVisible->BeginPos); - } else { - pIterator->SetAt(0); - } - CPVT_WordPlace oldplace; - while (pIterator->NextWord()) { - CPVT_WordPlace place = pIterator->GetAt(); - if (pVisible && place.WordCmp(pVisible->EndPos) > 0) { - break; - } - if (bContinuous) { - if (place.LineCmp(oldplace) != 0) { - if (sWords.GetSize() > 0) { - sLineStream << GetWordRenderString(sWords.GetByteString()); - sEditStream << sLineStream; - sLineStream.Clear(); - 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) { - sLineStream << 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) { - sLineStream << GetWordRenderString(sWords.GetByteString()); - sWords.Clear(); - } - sLineStream << GetFontSetString(pFontMap, word.nFontIndex, - word.fFontSize); - nCurFontIndex = word.nFontIndex; - } - sWords << GetPDFWordString(pFontMap, 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(pFontMap, word.nFontIndex, - word.fFontSize); - nCurFontIndex = word.nFontIndex; - } - sEditStream << GetWordRenderString( - GetPDFWordString(pFontMap, nCurFontIndex, word.Word, SubWord)); - } - } - } - if (sWords.GetSize() > 0) { - sLineStream << GetWordRenderString(sWords.GetByteString()); - sEditStream << sLineStream; - sWords.Clear(); - } - } - return sEditStream.GetByteString(); -} -CFX_ByteString CPVT_GenerateAP::GenerateBorderAP( - const CFX_FloatRect& rect, - FX_FLOAT fWidth, - const CPVT_Color& color, - const CPVT_Color& crLeftTop, - const CPVT_Color& crRightBottom, - int32_t nStyle, - const CPVT_Dash& dash) { - CFX_ByteTextBuf sAppStream; - CFX_ByteString sColor; - FX_FLOAT fLeft = rect.left; - FX_FLOAT fRight = rect.right; - FX_FLOAT fTop = rect.top; - FX_FLOAT fBottom = rect.bottom; - if (fWidth > 0.0f) { - FX_FLOAT fHalfWidth = fWidth / 2.0f; - switch (nStyle) { - default: - case PBS_SOLID: - sColor = GenerateColorAP(color, TRUE); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " - << fTop - fBottom << " re\n"; - sAppStream << fLeft + fWidth << " " << fBottom + fWidth << " " - << fRight - fLeft - fWidth * 2 << " " - << fTop - fBottom - fWidth * 2 << " re\n"; - sAppStream << "f*\n"; - } - break; - case PBS_DASH: - sColor = GenerateColorAP(color, FALSE); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fWidth << " w" - << " [" << dash.nDash << " " << dash.nGap << "] " - << dash.nPhase << " d\n"; - sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 - << " m\n"; - sAppStream << fLeft + fWidth / 2 << " " << fTop - fWidth / 2 - << " l\n"; - sAppStream << fRight - fWidth / 2 << " " << fTop - fWidth / 2 - << " l\n"; - sAppStream << fRight - fWidth / 2 << " " << fBottom + fWidth / 2 - << " l\n"; - sAppStream << fLeft + fWidth / 2 << " " << fBottom + fWidth / 2 - << " l S\n"; - } - break; - case PBS_BEVELED: - case PBS_INSET: - sColor = GenerateColorAP(crLeftTop, TRUE); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth - << " m\n"; - sAppStream << fLeft + fHalfWidth << " " << fTop - fHalfWidth - << " l\n"; - sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth - << " l\n"; - sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 - << " l\n"; - sAppStream << fLeft + fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 - << " l\n"; - sAppStream << fLeft + fHalfWidth * 2 << " " - << fBottom + fHalfWidth * 2 << " l f\n"; - } - sColor = GenerateColorAP(crRightBottom, TRUE); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fRight - fHalfWidth << " " << fTop - fHalfWidth - << " m\n"; - sAppStream << fRight - fHalfWidth << " " << fBottom + fHalfWidth - << " l\n"; - sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth - << " l\n"; - sAppStream << fLeft + fHalfWidth * 2 << " " - << fBottom + fHalfWidth * 2 << " l\n"; - sAppStream << fRight - fHalfWidth * 2 << " " - << fBottom + fHalfWidth * 2 << " l\n"; - sAppStream << fRight - fHalfWidth * 2 << " " << fTop - fHalfWidth * 2 - << " l f\n"; - } - sColor = GenerateColorAP(color, TRUE); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fLeft << " " << fBottom << " " << fRight - fLeft << " " - << fTop - fBottom << " re\n"; - sAppStream << fLeft + fHalfWidth << " " << fBottom + fHalfWidth << " " - << fRight - fLeft - fHalfWidth * 2 << " " - << fTop - fBottom - fHalfWidth * 2 << " re f*\n"; - } - break; - case PBS_UNDERLINED: - sColor = GenerateColorAP(color, FALSE); - if (sColor.GetLength() > 0) { - sAppStream << sColor; - sAppStream << fWidth << " w\n"; - sAppStream << fLeft << " " << fBottom + fWidth / 2 << " m\n"; - sAppStream << fRight << " " << fBottom + fWidth / 2 << " l S\n"; - } - break; - } - } - return sAppStream.GetByteString(); -} -CFX_ByteString CPVT_GenerateAP::GenerateColorAP(const CPVT_Color& color, - const FX_BOOL& bFillOrStroke) { - CFX_ByteTextBuf sColorStream; - switch (color.nColorType) { - case CPVT_Color::kRGB: - sColorStream << color.fColor1 << " " << color.fColor2 << " " - << color.fColor3 << " " << (bFillOrStroke ? "rg" : "RG") - << "\n"; - break; - case CPVT_Color::kGray: - sColorStream << color.fColor1 << " " << (bFillOrStroke ? "g" : "G") - << "\n"; - break; - case CPVT_Color::kCMYK: - sColorStream << color.fColor1 << " " << color.fColor2 << " " - << color.fColor3 << " " << color.fColor4 << " " - << (bFillOrStroke ? "k" : "K") << "\n"; - break; - case CPVT_Color::kTransparent: - break; - } - return sColorStream.GetByteString(); -} diff --git a/core/fpdfdoc/doc_formfield.cpp b/core/fpdfdoc/doc_formfield.cpp index 4ebf2d3020..0f8b3dd5ea 100644 --- a/core/fpdfdoc/doc_formfield.cpp +++ b/core/fpdfdoc/doc_formfield.cpp @@ -10,6 +10,7 @@ #include "core/fpdfapi/fpdf_parser/include/cpdf_number.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_simple_parser.h" #include "core/fpdfapi/fpdf_parser/include/cpdf_string.h" +#include "core/fpdfdoc/cpvt_generateap.h" #include "core/fpdfdoc/doc_utils.h" #include "core/include/fpdfdoc/fpdf_doc.h" diff --git a/core/fpdfdoc/doc_vt.cpp b/core/fpdfdoc/doc_vt.cpp index 028a2204c5..5977288d54 100644 --- a/core/fpdfdoc/doc_vt.cpp +++ b/core/fpdfdoc/doc_vt.cpp @@ -6,6 +6,7 @@ #include <algorithm> +#include "core/fpdfdoc/include/ipdf_variabletext_provider.h" #include "core/fpdfdoc/pdf_vt.h" #include "core/include/fpdfdoc/fpdf_doc.h" #include "core/include/fpdfdoc/fpdf_vt.h" diff --git a/core/fpdfdoc/include/ipdf_variabletext_provider.h b/core/fpdfdoc/include/ipdf_variabletext_provider.h new file mode 100644 index 0000000000..592c7da9d2 --- /dev/null +++ b/core/fpdfdoc/include/ipdf_variabletext_provider.h @@ -0,0 +1,28 @@ +// Copyright 2016 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 + +#ifndef CORE_FPDFDOC_INCLUDE_IPDF_VARIABLETEXT_PROVIDER_H_ +#define CORE_FPDFDOC_INCLUDE_IPDF_VARIABLETEXT_PROVIDER_H_ + +#include "core/fxcrt/include/fx_system.h" + +class IPDF_VariableText_Provider { + public: + virtual ~IPDF_VariableText_Provider(); + + virtual int32_t GetCharWidth(int32_t nFontIndex, + uint16_t word, + int32_t nWordStyle) = 0; + virtual int32_t GetTypeAscent(int32_t nFontIndex) = 0; + virtual int32_t GetTypeDescent(int32_t nFontIndex) = 0; + virtual int32_t GetWordFontIndex(uint16_t word, + int32_t charset, + int32_t nFontIndex) = 0; + virtual int32_t GetDefaultFontIndex() = 0; + virtual FX_BOOL IsLatinWord(uint16_t word) = 0; +}; + +#endif // CORE_FPDFDOC_INCLUDE_IPDF_VARIABLETEXT_PROVIDER_H_ diff --git a/core/fpdfdoc/ipdf_variabletext_provider.cpp b/core/fpdfdoc/ipdf_variabletext_provider.cpp new file mode 100644 index 0000000000..82937f745a --- /dev/null +++ b/core/fpdfdoc/ipdf_variabletext_provider.cpp @@ -0,0 +1,9 @@ +// Copyright 2016 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 "core/fpdfdoc/include/ipdf_variabletext_provider.h" + +IPDF_VariableText_Provider::~IPDF_VariableText_Provider() {} diff --git a/core/fpdfdoc/ipvt_fontmap.h b/core/fpdfdoc/ipvt_fontmap.h new file mode 100644 index 0000000000..eec414d617 --- /dev/null +++ b/core/fpdfdoc/ipvt_fontmap.h @@ -0,0 +1,24 @@ +// Copyright 2016 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 + +#ifndef CORE_FPDFDOC_IPVT_FONTMAP_H_ +#define CORE_FPDFDOC_IPVT_FONTMAP_H_ + +#include <stdint.h> + +#include "core/fxcrt/include/fx_string.h" + +class CPDF_Font; + +class IPVT_FontMap { + public: + virtual ~IPVT_FontMap() {} + + virtual CPDF_Font* GetPDFFont(int32_t nFontIndex) = 0; + virtual CFX_ByteString GetPDFFontAlias(int32_t nFontIndex) = 0; +}; + +#endif // CORE_FPDFDOC_IPVT_FONTMAP_H_ |