summaryrefslogtreecommitdiff
path: root/core/fpdfdoc
diff options
context:
space:
mode:
authordsinclair <dsinclair@chromium.org>2016-03-31 20:03:08 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-31 20:03:08 -0700
commit777b333109db7fceb5f2ca1fc521ced7f863fa18 (patch)
treef5968b42f43c90bc20af39a845718877cf80e064 /core/fpdfdoc
parent47ca692c8150cb39abef5737e866b91e6a105b80 (diff)
downloadpdfium-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.cpp51
-rw-r--r--core/fpdfdoc/cpvt_color.h38
-rw-r--r--core/fpdfdoc/cpvt_dash.h21
-rw-r--r--core/fpdfdoc/cpvt_fontmap.cpp75
-rw-r--r--core/fpdfdoc/cpvt_fontmap.h45
-rw-r--r--core/fpdfdoc/cpvt_generateap.cpp769
-rw-r--r--core/fpdfdoc/cpvt_generateap.h66
-rw-r--r--core/fpdfdoc/cpvt_provider.h35
-rw-r--r--core/fpdfdoc/doc_annot.cpp1
-rw-r--r--core/fpdfdoc/doc_ap.cpp870
-rw-r--r--core/fpdfdoc/doc_formfield.cpp1
-rw-r--r--core/fpdfdoc/doc_vt.cpp1
-rw-r--r--core/fpdfdoc/include/ipdf_variabletext_provider.h28
-rw-r--r--core/fpdfdoc/ipdf_variabletext_provider.cpp9
-rw-r--r--core/fpdfdoc/ipvt_fontmap.h24
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_