diff options
author | John Abd-El-Malek <jabdelmalek@google.com> | 2014-05-17 22:33:34 -0700 |
---|---|---|
committer | John Abd-El-Malek <jabdelmalek@google.com> | 2014-05-17 22:33:34 -0700 |
commit | 5110c4743751145c4ae1934cd1d83bc6c55bb43f (patch) | |
tree | b141608096b73163182764c25b895d3df4b2c182 /core/src/fpdfdoc | |
parent | 76b563d2feed92ed328afb1f15e3466a9536b11b (diff) | |
download | pdfium-5110c4743751145c4ae1934cd1d83bc6c55bb43f.tar.xz |
Initial commit.
Diffstat (limited to 'core/src/fpdfdoc')
-rw-r--r-- | core/src/fpdfdoc/doc_action.cpp | 362 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_annot.cpp | 519 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_ap.cpp | 808 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_basic.cpp | 567 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_bookmark.cpp | 91 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_form.cpp | 1664 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_formcontrol.cpp | 461 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_formfield.cpp | 1095 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_link.cpp | 105 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_metadata.cpp | 152 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_ocg.cpp | 300 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_tagged.cpp | 448 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_utils.cpp | 749 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_viewerPreferences.cpp | 31 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_vt.cpp | 1864 | ||||
-rw-r--r-- | core/src/fpdfdoc/doc_vtmodule.cpp | 17 | ||||
-rw-r--r-- | core/src/fpdfdoc/pdf_vt.h | 642 | ||||
-rw-r--r-- | core/src/fpdfdoc/tagged_int.h | 91 |
18 files changed, 9966 insertions, 0 deletions
diff --git a/core/src/fpdfdoc/doc_action.cpp b/core/src/fpdfdoc/doc_action.cpp new file mode 100644 index 0000000000..f13bd27cbe --- /dev/null +++ b/core/src/fpdfdoc/doc_action.cpp @@ -0,0 +1,362 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+CPDF_Dest CPDF_Action::GetDest(CPDF_Document* pDoc) const
+{
+ if (m_pDict == NULL) {
+ return NULL;
+ }
+ CFX_ByteString type = m_pDict->GetString("S");
+ if (type != "GoTo" && type != "GoToR") {
+ return NULL;
+ }
+ CPDF_Object* pDest = m_pDict->GetElementValue("D");
+ if (pDest == NULL) {
+ return NULL;
+ }
+ if (pDest->GetType() == PDFOBJ_STRING || pDest->GetType() == PDFOBJ_NAME) {
+ CPDF_NameTree name_tree(pDoc, FX_BSTRC("Dests"));
+ CFX_ByteStringC name = pDest->GetString();
+ return name_tree.LookupNamedDest(pDoc, name);
+ } else if (pDest->GetType() == PDFOBJ_ARRAY) {
+ return (CPDF_Array*)pDest;
+ }
+ return NULL;
+}
+const FX_CHAR* g_sATypes[] = {"Unknown", "GoTo", "GoToR", "GoToE", "Launch", "Thread", "URI", "Sound", "Movie",
+ "Hide", "Named", "SubmitForm", "ResetForm", "ImportData", "JavaScript", "SetOCGState",
+ "Rendition", "Trans", "GoTo3DView", ""
+ };
+CPDF_Action::ActionType CPDF_Action::GetType() const
+{
+ ActionType eType = Unknown;
+ if (m_pDict != NULL) {
+ CFX_ByteString csType = m_pDict->GetString("S");
+ if (!csType.IsEmpty()) {
+ int i = 0;
+ while (g_sATypes[i][0] != '\0') {
+ if (csType == g_sATypes[i]) {
+ return (ActionType)i;
+ }
+ i ++;
+ }
+ }
+ }
+ return eType;
+}
+CFX_WideString CPDF_Action::GetFilePath() const
+{
+ CFX_ByteString type = m_pDict->GetString("S");
+ if (type != "GoToR" && type != "Launch" &&
+ type != "SubmitForm" && type != "ImportData") {
+ return CFX_WideString();
+ }
+ CPDF_Object* pFile = m_pDict->GetElementValue("F");
+ CFX_WideString path;
+ if (pFile == NULL) {
+ if (type == "Launch") {
+ CPDF_Dictionary* pWinDict = m_pDict->GetDict(FX_BSTRC("Win"));
+ if (pWinDict) {
+ return CFX_WideString::FromLocal(pWinDict->GetString(FX_BSTRC("F")));
+ }
+ }
+ return path;
+ }
+ CPDF_FileSpec filespec(pFile);
+ filespec.GetFileName(path);
+ return path;
+}
+CFX_ByteString CPDF_Action::GetURI(CPDF_Document* pDoc) const
+{
+ CFX_ByteString csURI;
+ if (m_pDict == NULL) {
+ return csURI;
+ }
+ if (m_pDict->GetString("S") != "URI") {
+ return csURI;
+ }
+ csURI = m_pDict->GetString("URI");
+ CPDF_Dictionary* pRoot = pDoc->GetRoot();
+ CPDF_Dictionary* pURI = pRoot->GetDict("URI");
+ if (pURI != NULL) {
+ if (csURI.Find(FX_BSTRC(":"), 0) < 1) {
+ csURI = pURI->GetString("Base") + csURI;
+ }
+ }
+ return csURI;
+}
+FX_DWORD CPDF_ActionFields::GetFieldsCount() const
+{
+ if (m_pAction == NULL) {
+ return 0;
+ }
+ CPDF_Dictionary* pDict = (CPDF_Dictionary*)(*m_pAction);
+ if (pDict == NULL) {
+ return 0;
+ }
+ CFX_ByteString csType = pDict->GetString("S");
+ CPDF_Object* pFields = NULL;
+ if (csType == "Hide") {
+ pFields = pDict->GetElementValue("T");
+ } else {
+ pFields = pDict->GetArray("Fields");
+ }
+ if (pFields == NULL) {
+ return 0;
+ }
+ int iType = pFields->GetType();
+ if (iType == PDFOBJ_DICTIONARY) {
+ return 1;
+ } else if (iType == PDFOBJ_STRING) {
+ return 1;
+ } else if (iType == PDFOBJ_ARRAY) {
+ return ((CPDF_Array*)pFields)->GetCount();
+ }
+ return 0;
+}
+void CPDF_ActionFields::GetAllFields(CFX_PtrArray& fieldObjects) const
+{
+ fieldObjects.RemoveAll();
+ if (m_pAction == NULL) {
+ return;
+ }
+ CPDF_Dictionary* pDict = (CPDF_Dictionary*)(*m_pAction);
+ if (pDict == NULL) {
+ return;
+ }
+ CFX_ByteString csType = pDict->GetString("S");
+ CPDF_Object* pFields = NULL;
+ if (csType == "Hide") {
+ pFields = pDict->GetElementValue("T");
+ } else {
+ pFields = pDict->GetArray("Fields");
+ }
+ if (pFields == NULL) {
+ return;
+ }
+ int iType = pFields->GetType();
+ if (iType == PDFOBJ_DICTIONARY || iType == PDFOBJ_STRING) {
+ fieldObjects.Add(pFields);
+ } else if (iType == PDFOBJ_ARRAY) {
+ CPDF_Array* pArray = (CPDF_Array*)pFields;
+ FX_DWORD iCount = pArray->GetCount();
+ for (FX_DWORD i = 0; i < iCount; i ++) {
+ CPDF_Object* pObj = pArray->GetElementValue(i);
+ if (pObj != NULL) {
+ fieldObjects.Add(pObj);
+ }
+ }
+ }
+}
+CPDF_Object* CPDF_ActionFields::GetField(FX_DWORD iIndex) const
+{
+ if (m_pAction == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pDict = (CPDF_Dictionary*)(*m_pAction);
+ if (pDict == NULL) {
+ return NULL;
+ }
+ CFX_ByteString csType = pDict->GetString("S");
+ CPDF_Object* pFields = NULL;
+ if (csType == "Hide") {
+ pFields = pDict->GetElementValue("T");
+ } else {
+ pFields = pDict->GetArray("Fields");
+ }
+ if (pFields == NULL) {
+ return NULL;
+ }
+ CPDF_Object* pFindObj = NULL;
+ int iType = pFields->GetType();
+ if (iType == PDFOBJ_DICTIONARY || iType == PDFOBJ_STRING) {
+ if (iIndex == 0) {
+ pFindObj = pFields;
+ }
+ } else if (iType == PDFOBJ_ARRAY) {
+ pFindObj = ((CPDF_Array*)pFields)->GetElementValue(iIndex);
+ }
+ return pFindObj;
+}
+CPDF_LWinParam CPDF_Action::GetWinParam() const
+{
+ if (m_pDict == NULL) {
+ return NULL;
+ }
+ if (m_pDict->GetString("S") != "Launch") {
+ return NULL;
+ }
+ return m_pDict->GetDict("Win");
+}
+CFX_WideString CPDF_Action::GetJavaScript() const
+{
+ CFX_WideString csJS;
+ if (m_pDict == NULL) {
+ return csJS;
+ }
+ CPDF_Object* pJS = m_pDict->GetElementValue("JS");
+ if (pJS != NULL) {
+ return pJS->GetUnicodeText();
+ }
+ return csJS;
+}
+CPDF_Dictionary* CPDF_Action::GetAnnot() const
+{
+ if (m_pDict == NULL) {
+ return NULL;
+ }
+ CFX_ByteString csType = m_pDict->GetString("S");
+ if (csType == FX_BSTRC("Rendition")) {
+ return m_pDict->GetDict("AN");
+ } else if (csType == FX_BSTRC("Movie")) {
+ return m_pDict->GetDict("Annotation");
+ }
+ return NULL;
+}
+FX_INT32 CPDF_Action::GetOperationType() const
+{
+ if (m_pDict == NULL) {
+ return 0;
+ }
+ CFX_ByteString csType = m_pDict->GetString("S");
+ if (csType == FX_BSTRC("Rendition")) {
+ return m_pDict->GetInteger("OP");
+ } else if (csType == FX_BSTRC("Movie")) {
+ CFX_ByteString csOP = m_pDict->GetString("Operation");
+ if (csOP == FX_BSTRC("Play")) {
+ return 0;
+ } else if (csOP == FX_BSTRC("Stop")) {
+ return 1;
+ } else if (csOP == FX_BSTRC("Pause")) {
+ return 2;
+ } else if (csOP == FX_BSTRC("Resume")) {
+ return 3;
+ }
+ }
+ return 0;
+}
+FX_DWORD CPDF_Action::GetSubActionsCount() const
+{
+ if (m_pDict == NULL || !m_pDict->KeyExist("Next")) {
+ return 0;
+ }
+ CPDF_Object* pNext = m_pDict->GetElementValue("Next");
+ if (!pNext) {
+ return 0;
+ }
+ int iObjType = pNext->GetType();
+ if (iObjType == PDFOBJ_DICTIONARY) {
+ return 1;
+ }
+ if (iObjType == PDFOBJ_ARRAY) {
+ return ((CPDF_Array*)pNext)->GetCount();
+ }
+ return 0;
+}
+CPDF_Action CPDF_Action::GetSubAction(FX_DWORD iIndex) const
+{
+ if (m_pDict == NULL || !m_pDict->KeyExist("Next")) {
+ return NULL;
+ }
+ CPDF_Object* pNext = m_pDict->GetElementValue("Next");
+ int iObjType = pNext->GetType();
+ if (iObjType == PDFOBJ_DICTIONARY) {
+ if (iIndex == 0) {
+ return (CPDF_Dictionary*)pNext;
+ }
+ }
+ if (iObjType == PDFOBJ_ARRAY) {
+ return ((CPDF_Array*)pNext)->GetDict(iIndex);
+ }
+ return NULL;
+}
+const FX_CHAR* g_sAATypes[] = {"E", "X", "D", "U", "Fo", "Bl", "PO", "PC", "PV", "PI",
+ "O", "C",
+ "K", "F", "V", "C",
+ "WC", "WS", "DS", "WP", "DP",
+ ""
+ };
+FX_BOOL CPDF_AAction::ActionExist(AActionType eType) const
+{
+ if (m_pDict == NULL) {
+ return FALSE;
+ }
+ return m_pDict->KeyExist(g_sAATypes[(int)eType]);
+}
+CPDF_Action CPDF_AAction::GetAction(AActionType eType) const
+{
+ if (m_pDict == NULL) {
+ return NULL;
+ }
+ return m_pDict->GetDict(g_sAATypes[(int)eType]);
+}
+FX_POSITION CPDF_AAction::GetStartPos() const
+{
+ if (m_pDict == NULL) {
+ return NULL;
+ }
+ return m_pDict->GetStartPos();
+}
+CPDF_Action CPDF_AAction::GetNextAction(FX_POSITION& pos, AActionType& eType) const
+{
+ if (m_pDict == NULL) {
+ return NULL;
+ }
+ CFX_ByteString csKey;
+ CPDF_Object* pObj = m_pDict->GetNextElement(pos, csKey);
+ if (pObj != NULL) {
+ CPDF_Object* pDirect = pObj->GetDirect();
+ if (pDirect != NULL && pDirect->GetType() == PDFOBJ_DICTIONARY) {
+ int i = 0;
+ while (g_sAATypes[i][0] != '\0') {
+ if (csKey == g_sAATypes[i]) {
+ break;
+ }
+ i ++;
+ }
+ eType = (AActionType)i;
+ return (CPDF_Dictionary*)pDirect;
+ }
+ }
+ return NULL;
+}
+CPDF_DocJSActions::CPDF_DocJSActions(CPDF_Document* pDoc)
+{
+ m_pDocument = pDoc;
+}
+int CPDF_DocJSActions::CountJSActions() const
+{
+ ASSERT(m_pDocument != NULL);
+ CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
+ return name_tree.GetCount();
+}
+CPDF_Action CPDF_DocJSActions::GetJSAction(int index, CFX_ByteString& csName) const
+{
+ ASSERT(m_pDocument != NULL);
+ CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
+ CPDF_Object *pAction = name_tree.LookupValue(index, csName);
+ if (pAction == NULL || pAction->GetType() != PDFOBJ_DICTIONARY) {
+ return NULL;
+ }
+ return pAction->GetDict();
+}
+CPDF_Action CPDF_DocJSActions::GetJSAction(const CFX_ByteString& csName) const
+{
+ ASSERT(m_pDocument != NULL);
+ CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
+ CPDF_Object *pAction = name_tree.LookupValue(csName);
+ if (pAction == NULL || pAction->GetType() != PDFOBJ_DICTIONARY) {
+ return NULL;
+ }
+ return pAction->GetDict();
+}
+int CPDF_DocJSActions::FindJSAction(const CFX_ByteString& csName) const
+{
+ ASSERT(m_pDocument != NULL);
+ CPDF_NameTree name_tree(m_pDocument, FX_BSTRC("JavaScript"));
+ return name_tree.GetIndex(csName);
+}
diff --git a/core/src/fpdfdoc/doc_annot.cpp b/core/src/fpdfdoc/doc_annot.cpp new file mode 100644 index 0000000000..da30485073 --- /dev/null +++ b/core/src/fpdfdoc/doc_annot.cpp @@ -0,0 +1,519 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+#include "../../include/fpdfapi/fpdf_pageobj.h"
+CPDF_AnnotList::CPDF_AnnotList(CPDF_Page* pPage)
+{
+ ASSERT(pPage != NULL);
+ m_pPageDict = pPage->m_pFormDict;
+ if (m_pPageDict == NULL) {
+ return;
+ }
+ m_pDocument = pPage->m_pDocument;
+ CPDF_Array* pAnnots = m_pPageDict->GetArray("Annots");
+ if (pAnnots == NULL) {
+ return;
+ }
+ CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
+ CPDF_Dictionary* pAcroForm = pRoot->GetDict("AcroForm");
+ FX_BOOL bRegenerateAP = pAcroForm && pAcroForm->GetBoolean("NeedAppearances");
+ for (FX_DWORD i = 0; i < pAnnots->GetCount(); i ++) {
+ CPDF_Dictionary* pDict = (CPDF_Dictionary*)pAnnots->GetElementValue(i);
+ if (pDict == NULL || pDict->GetType() != PDFOBJ_DICTIONARY) {
+ continue;
+ }
+ FX_DWORD dwObjNum = pDict->GetObjNum();
+ if (dwObjNum == 0) {
+ dwObjNum = m_pDocument->AddIndirectObject(pDict);
+ CPDF_Reference* pAction = CPDF_Reference::Create(m_pDocument, dwObjNum);
+ if (pAction == NULL) {
+ break;
+ }
+ pAnnots->InsertAt(i, pAction);
+ pAnnots->RemoveAt(i + 1);
+ pDict = pAnnots->GetDict(i);
+ }
+ CPDF_Annot* pAnnot = FX_NEW CPDF_Annot(pDict);
+ if (pAnnot == NULL) {
+ break;
+ }
+ pAnnot->m_pList = this;
+ m_AnnotList.Add(pAnnot);
+ if (bRegenerateAP && pDict->GetConstString(FX_BSTRC("Subtype")) == FX_BSTRC("Widget"))
+ if (CPDF_InterForm::UpdatingAPEnabled()) {
+ FPDF_GenerateAP(m_pDocument, pDict);
+ }
+ }
+}
+CPDF_AnnotList::~CPDF_AnnotList()
+{
+ int i = 0;
+ for (i = 0; i < m_AnnotList.GetSize(); i ++) {
+ delete (CPDF_Annot*)m_AnnotList[i];
+ }
+ for (i = 0; i < m_Borders.GetSize(); ++i) {
+ delete (CPDF_PageObjects*)m_Borders[i];
+ }
+}
+void CPDF_AnnotList::DisplayPass(const CPDF_Page* pPage, CFX_RenderDevice* pDevice,
+ CPDF_RenderContext* pContext, FX_BOOL bPrinting, CFX_AffineMatrix* pMatrix,
+ FX_BOOL bWidgetPass, CPDF_RenderOptions* pOptions, FX_RECT* clip_rect)
+{
+ for (int i = 0; i < m_AnnotList.GetSize(); i ++) {
+ CPDF_Annot* pAnnot = (CPDF_Annot*)m_AnnotList[i];
+ FX_BOOL bWidget = pAnnot->GetSubType() == "Widget";
+ if ((bWidgetPass && !bWidget) || (!bWidgetPass && bWidget)) {
+ continue;
+ }
+ FX_DWORD annot_flags = pAnnot->GetFlags();
+ if (annot_flags & ANNOTFLAG_HIDDEN) {
+ continue;
+ }
+ if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) {
+ continue;
+ }
+ if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) {
+ continue;
+ }
+ if (pOptions != NULL) {
+ IPDF_OCContext* pOCContext = pOptions->m_pOCContext;
+ CPDF_Dictionary* pAnnotDict = pAnnot->m_pAnnotDict;
+ if (pOCContext != NULL && pAnnotDict != NULL &&
+ !pOCContext->CheckOCGVisible(pAnnotDict->GetDict(FX_BSTRC("OC")))) {
+ continue;
+ }
+ }
+ CPDF_Rect annot_rect_f;
+ pAnnot->GetRect(annot_rect_f);
+ CFX_Matrix matrix;
+ matrix = *pMatrix;
+ if (clip_rect) {
+ annot_rect_f.Transform(&matrix);
+ FX_RECT annot_rect = annot_rect_f.GetOutterRect();
+ annot_rect.Intersect(*clip_rect);
+ if (annot_rect.IsEmpty()) {
+ continue;
+ }
+ }
+ if (pContext) {
+ pAnnot->DrawInContext(pPage, pContext, &matrix, CPDF_Annot::Normal);
+ } else if (!pAnnot->DrawAppearance(pPage, pDevice, &matrix, CPDF_Annot::Normal, pOptions)) {
+ pAnnot->DrawBorder(pDevice, &matrix, pOptions);
+ }
+ }
+}
+void CPDF_AnnotList::DisplayAnnots(const CPDF_Page* pPage, CFX_RenderDevice* pDevice,
+ CFX_AffineMatrix* pUser2Device,
+ FX_BOOL bShowWidget, CPDF_RenderOptions* pOptions)
+{
+ FX_RECT clip_rect;
+ if (pDevice) {
+ clip_rect = pDevice->GetClipBox();
+ }
+ FX_BOOL bPrinting = pDevice->GetDeviceClass() == FXDC_PRINTER || (pOptions && (pOptions->m_Flags & RENDER_PRINTPREVIEW));
+ DisplayAnnots(pPage, pDevice, NULL, bPrinting, pUser2Device, bShowWidget ? 3 : 1, pOptions, &clip_rect);
+}
+void CPDF_AnnotList::DisplayAnnots(const CPDF_Page* pPage, CFX_RenderDevice* pDevice, CPDF_RenderContext* pContext,
+ FX_BOOL bPrinting, CFX_AffineMatrix* pUser2Device, FX_DWORD dwAnnotFlags,
+ CPDF_RenderOptions* pOptions, FX_RECT* pClipRect)
+{
+ if (dwAnnotFlags & 0x01) {
+ DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, FALSE, pOptions, pClipRect);
+ }
+ if (dwAnnotFlags & 0x02) {
+ DisplayPass(pPage, pDevice, pContext, bPrinting, pUser2Device, TRUE, pOptions, pClipRect);
+ }
+}
+int CPDF_AnnotList::GetIndex(CPDF_Annot* pAnnot)
+{
+ for (int i = 0; i < m_AnnotList.GetSize(); i ++)
+ if (m_AnnotList[i] == (FX_LPVOID)pAnnot) {
+ return i;
+ }
+ return -1;
+}
+CPDF_Annot::CPDF_Annot(CPDF_Dictionary* pDict)
+{
+ m_pList = NULL;
+ m_pAnnotDict = pDict;
+}
+CPDF_Annot::~CPDF_Annot()
+{
+ ClearCachedAP();
+}
+CPDF_Reference* CPDF_Annot::NewAnnotRef()
+{
+ if (m_pAnnotDict->GetObjNum() == 0) {
+ m_pList->m_pDocument->AddIndirectObject(m_pAnnotDict);
+ }
+ return CPDF_Reference::Create(m_pList->m_pDocument, m_pAnnotDict->GetObjNum());
+}
+void CPDF_Annot::ClearCachedAP()
+{
+ FX_POSITION pos = m_APMap.GetStartPosition();
+ while (pos) {
+ void* pForm;
+ void* pObjects;
+ m_APMap.GetNextAssoc(pos, pForm, pObjects);
+ delete (CPDF_PageObjects*)pObjects;
+ }
+ m_APMap.RemoveAll();
+}
+CFX_ByteString CPDF_Annot::GetSubType() const
+{
+ return m_pAnnotDict->GetConstString(FX_BSTRC("Subtype"));
+}
+void CPDF_Annot::GetRect(CPDF_Rect& rect) const
+{
+ if (m_pAnnotDict == NULL) {
+ return;
+ }
+ rect = m_pAnnotDict->GetRect("Rect");
+ rect.Normalize();
+}
+CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict, CPDF_Annot::AppearanceMode mode)
+{
+ CPDF_Dictionary* pAP = pAnnotDict->GetDict("AP");
+ if (pAP == NULL) {
+ return NULL;
+ }
+ const FX_CHAR* ap_entry = "N";
+ if (mode == CPDF_Annot::Down) {
+ ap_entry = "D";
+ } else if (mode == CPDF_Annot::Rollover) {
+ ap_entry = "R";
+ }
+ if (!pAP->KeyExist(ap_entry)) {
+ ap_entry = "N";
+ }
+ CPDF_Object* psub = pAP->GetElementValue(ap_entry);
+ if (psub == NULL) {
+ return NULL;
+ }
+ CPDF_Stream* pStream = NULL;
+ if (psub->GetType() == PDFOBJ_STREAM) {
+ pStream = (CPDF_Stream*)psub;
+ } else if (psub->GetType() == PDFOBJ_DICTIONARY) {
+ CFX_ByteString as = pAnnotDict->GetString("AS");
+ if (as.IsEmpty()) {
+ CFX_ByteString value = pAnnotDict->GetString(FX_BSTRC("V"));
+ if (value.IsEmpty()) {
+ value = pAnnotDict->GetDict(FX_BSTRC("Parent"))->GetString(FX_BSTRC("V"));
+ }
+ if (value.IsEmpty() || !((CPDF_Dictionary*)psub)->KeyExist(value)) {
+ as = FX_BSTRC("Off");
+ } else {
+ as = value;
+ }
+ }
+ pStream = ((CPDF_Dictionary*)psub)->GetStream(as);
+ }
+ return pStream;
+}
+CPDF_Form* CPDF_Annot::GetAPForm(const CPDF_Page* pPage, AppearanceMode mode)
+{
+ CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pAnnotDict, mode);
+ if (pStream == NULL) {
+ return NULL;
+ }
+ CPDF_Form* pForm;
+ if (m_APMap.Lookup(pStream, (void*&)pForm)) {
+ return pForm;
+ }
+ pForm = FX_NEW CPDF_Form(m_pList->m_pDocument, pPage->m_pResources, pStream);
+ if (pForm == NULL) {
+ return NULL;
+ }
+ pForm->ParseContent(NULL, NULL, NULL, NULL);
+ m_APMap.SetAt(pStream, pForm);
+ return pForm;
+}
+static CPDF_Form* FPDFDOC_Annot_GetMatrix(const CPDF_Page* pPage, CPDF_Annot* pAnnot, CPDF_Annot::AppearanceMode mode, const CFX_AffineMatrix* pUser2Device, CFX_Matrix &matrix)
+{
+ CPDF_Form* pForm = pAnnot->GetAPForm(pPage, mode);
+ if (!pForm) {
+ return NULL;
+ }
+ CFX_FloatRect form_bbox = pForm->m_pFormDict->GetRect(FX_BSTRC("BBox"));
+ CFX_Matrix form_matrix = pForm->m_pFormDict->GetMatrix(FX_BSTRC("Matrix"));
+ form_matrix.TransformRect(form_bbox);
+ CPDF_Rect arect;
+ pAnnot->GetRect(arect);
+ matrix.MatchRect(arect, form_bbox);
+ matrix.Concat(*pUser2Device);
+ return pForm;
+}
+FX_BOOL CPDF_Annot::DrawAppearance(const CPDF_Page* pPage, CFX_RenderDevice* pDevice, const CFX_AffineMatrix* pUser2Device,
+ AppearanceMode mode, const CPDF_RenderOptions* pOptions)
+{
+ CFX_Matrix matrix;
+ CPDF_Form* pForm = FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device, matrix);
+ if (!pForm) {
+ return FALSE;
+ }
+ CPDF_RenderContext context;
+ context.Create((CPDF_Page*)pPage);
+ context.DrawObjectList(pDevice, pForm, &matrix, pOptions);
+ return TRUE;
+}
+FX_BOOL CPDF_Annot::DrawInContext(const CPDF_Page* pPage, const CPDF_RenderContext* pContext, const CFX_AffineMatrix* pUser2Device, AppearanceMode mode)
+{
+ CFX_Matrix matrix;
+ CPDF_Form* pForm = FPDFDOC_Annot_GetMatrix(pPage, this, mode, pUser2Device, matrix);
+ if (!pForm) {
+ return FALSE;
+ }
+ ((CPDF_RenderContext*)pContext)->AppendObjectList(pForm, &matrix);
+ return TRUE;
+}
+CPDF_PageObject* CPDF_Annot::GetBorder(FX_BOOL bPrint, const CPDF_RenderOptions* pOptions)
+{
+ if (GetSubType() == "Popup") {
+ return NULL;
+ }
+ FX_DWORD annot_flags = GetFlags();
+ if (annot_flags & ANNOTFLAG_HIDDEN) {
+ return NULL;
+ }
+ FX_BOOL bPrinting = bPrint || (pOptions && (pOptions->m_Flags & RENDER_PRINTPREVIEW));
+ if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) {
+ return NULL;
+ }
+ if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) {
+ return NULL;
+ }
+ CPDF_Dictionary* pBS = m_pAnnotDict->GetDict("BS");
+ char style_char;
+ FX_FLOAT width;
+ CPDF_Array* pDashArray = NULL;
+ if (pBS == NULL) {
+ CPDF_Array* pBorderArray = m_pAnnotDict->GetArray("Border");
+ style_char = 'S';
+ if (pBorderArray) {
+ width = pBorderArray->GetNumber(2);
+ if (pBorderArray->GetCount() == 4) {
+ pDashArray = pBorderArray->GetArray(3);
+ if (pDashArray == NULL) {
+ return NULL;
+ }
+ style_char = 'D';
+ }
+ } else {
+ width = 1;
+ }
+ } else {
+ CFX_ByteString style = pBS->GetString("S");
+ pDashArray = pBS->GetArray("D");
+ style_char = style[1];
+ width = pBS->GetNumber("W");
+ }
+ if (width <= 0) {
+ return NULL;
+ }
+ CPDF_Array* pColor = m_pAnnotDict->GetArray("C");
+ FX_DWORD argb = 0xff000000;
+ if (pColor != NULL) {
+ int R = (FX_INT32)(pColor->GetNumber(0) * 255);
+ int G = (FX_INT32)(pColor->GetNumber(1) * 255);
+ int B = (FX_INT32)(pColor->GetNumber(2) * 255);
+ argb = ArgbEncode(0xff, R, G, B);
+ }
+ CPDF_PathObject *pPathObject = FX_NEW CPDF_PathObject();
+ if (!pPathObject) {
+ return NULL;
+ }
+ CPDF_GraphStateData *pGraphState = pPathObject->m_GraphState.GetModify();
+ if (!pGraphState) {
+ pPathObject->Release();
+ return NULL;
+ }
+ pGraphState->m_LineWidth = width;
+ CPDF_ColorStateData *pColorData = pPathObject->m_ColorState.GetModify();
+ if (!pColorData) {
+ pPathObject->Release();
+ return NULL;
+ }
+ pColorData->m_StrokeRGB = argb;
+ pPathObject->m_bStroke = TRUE;
+ pPathObject->m_FillType = 0;
+ if (style_char == 'D') {
+ if (pDashArray) {
+ FX_DWORD dash_count = pDashArray->GetCount();
+ if (dash_count % 2) {
+ dash_count ++;
+ }
+ pGraphState->m_DashArray = FX_Alloc(FX_FLOAT, dash_count);
+ if (pGraphState->m_DashArray == NULL) {
+ pPathObject->Release();
+ return NULL;
+ }
+ pGraphState->m_DashCount = dash_count;
+ FX_DWORD i;
+ for (i = 0; i < pDashArray->GetCount(); i ++) {
+ pGraphState->m_DashArray[i] = pDashArray->GetNumber(i);
+ }
+ if (i < dash_count) {
+ pGraphState->m_DashArray[i] = pGraphState->m_DashArray[i - 1];
+ }
+ } else {
+ pGraphState->m_DashArray = FX_Alloc(FX_FLOAT, 2);
+ if (pGraphState->m_DashArray == NULL) {
+ pPathObject->Release();
+ return NULL;
+ }
+ pGraphState->m_DashCount = 2;
+ pGraphState->m_DashArray[0] = pGraphState->m_DashArray[1] = 3 * 1.0f;
+ }
+ }
+ CFX_FloatRect rect;
+ GetRect(rect);
+ width /= 2;
+ CPDF_PathData *pPathData = pPathObject->m_Path.GetModify();
+ if (pPathData) {
+ pPathData->AppendRect(rect.left + width, rect.bottom + width, rect.right - width, rect.top - width);
+ }
+ pPathObject->CalcBoundingBox();
+ return pPathObject;
+}
+void CPDF_Annot::DrawBorder(CFX_RenderDevice* pDevice, const CFX_AffineMatrix* pUser2Device, const CPDF_RenderOptions* pOptions)
+{
+ if (GetSubType() == "Popup") {
+ return;
+ }
+ FX_DWORD annot_flags = GetFlags();
+ if (annot_flags & ANNOTFLAG_HIDDEN) {
+ return;
+ }
+ FX_BOOL bPrinting = pDevice->GetDeviceClass() == FXDC_PRINTER || (pOptions && (pOptions->m_Flags & RENDER_PRINTPREVIEW));
+ if (bPrinting && (annot_flags & ANNOTFLAG_PRINT) == 0) {
+ return;
+ }
+ if (!bPrinting && (annot_flags & ANNOTFLAG_NOVIEW)) {
+ return;
+ }
+ CPDF_Dictionary* pBS = m_pAnnotDict->GetDict("BS");
+ char style_char;
+ FX_FLOAT width;
+ CPDF_Array* pDashArray = NULL;
+ if (pBS == NULL) {
+ CPDF_Array* pBorderArray = m_pAnnotDict->GetArray("Border");
+ style_char = 'S';
+ if (pBorderArray) {
+ width = pBorderArray->GetNumber(2);
+ if (pBorderArray->GetCount() == 4) {
+ pDashArray = pBorderArray->GetArray(3);
+ if (pDashArray == NULL) {
+ return;
+ }
+ int nLen = pDashArray->GetCount();
+ int i = 0;
+ for (; i < nLen; ++i) {
+ CPDF_Object*pObj = pDashArray->GetElementValue(i);
+ if (pObj && pObj->GetInteger()) {
+ break;
+ }
+ }
+ if (i == nLen) {
+ return;
+ }
+ style_char = 'D';
+ }
+ } else {
+ width = 1;
+ }
+ } else {
+ CFX_ByteString style = pBS->GetString("S");
+ pDashArray = pBS->GetArray("D");
+ style_char = style[1];
+ width = pBS->GetNumber("W");
+ }
+ if (width <= 0) {
+ return;
+ }
+ CPDF_Array* pColor = m_pAnnotDict->GetArray("C");
+ FX_DWORD argb = 0xff000000;
+ if (pColor != NULL) {
+ int R = (FX_INT32)(pColor->GetNumber(0) * 255);
+ int G = (FX_INT32)(pColor->GetNumber(1) * 255);
+ int B = (FX_INT32)(pColor->GetNumber(2) * 255);
+ argb = ArgbEncode(0xff, R, G, B);
+ }
+ CPDF_GraphStateData graph_state;
+ graph_state.m_LineWidth = width;
+ if (style_char == 'D') {
+ if (pDashArray) {
+ FX_DWORD dash_count = pDashArray->GetCount();
+ if (dash_count % 2) {
+ dash_count ++;
+ }
+ graph_state.m_DashArray = FX_Alloc(FX_FLOAT, dash_count);
+ if (graph_state.m_DashArray == NULL) {
+ return ;
+ }
+ graph_state.m_DashCount = dash_count;
+ FX_DWORD i;
+ for (i = 0; i < pDashArray->GetCount(); i ++) {
+ graph_state.m_DashArray[i] = pDashArray->GetNumber(i);
+ }
+ if (i < dash_count) {
+ graph_state.m_DashArray[i] = graph_state.m_DashArray[i - 1];
+ }
+ } else {
+ graph_state.m_DashArray = FX_Alloc(FX_FLOAT, 2);
+ if (graph_state.m_DashArray == NULL) {
+ return ;
+ }
+ graph_state.m_DashCount = 2;
+ graph_state.m_DashArray[0] = graph_state.m_DashArray[1] = 3 * 1.0f;
+ }
+ }
+ CFX_FloatRect rect;
+ GetRect(rect);
+ CPDF_PathData path;
+ width /= 2;
+ path.AppendRect(rect.left + width, rect.bottom + width, rect.right - width, rect.top - width);
+ int fill_type = 0;
+ if (pOptions && (pOptions->m_Flags & RENDER_NOPATHSMOOTH)) {
+ fill_type |= FXFILL_NOPATHSMOOTH;
+ }
+ pDevice->DrawPath(&path, pUser2Device, &graph_state, argb, argb, fill_type);
+}
+int CPDF_Annot::CountIRTNotes()
+{
+ int count = 0;
+ for (int i = 0; i < m_pList->Count(); i ++) {
+ CPDF_Annot* pAnnot = m_pList->GetAt(i);
+ if (pAnnot == NULL) {
+ continue;
+ }
+ CPDF_Dictionary* pIRT = pAnnot->m_pAnnotDict->GetDict("IRT");
+ if (pIRT != m_pAnnotDict) {
+ continue;
+ }
+ count ++;
+ }
+ return count;
+}
+CPDF_Annot* CPDF_Annot::GetIRTNote(int index)
+{
+ int count = 0;
+ for (int i = 0; i < m_pList->Count(); i ++) {
+ CPDF_Annot* pAnnot = m_pList->GetAt(i);
+ if (pAnnot == NULL) {
+ continue;
+ }
+ CPDF_Dictionary* pIRT = pAnnot->m_pAnnotDict->GetDict("IRT");
+ if (pIRT != m_pAnnotDict) {
+ continue;
+ }
+ if (count == index) {
+ return pAnnot;
+ }
+ count ++;
+ }
+ return NULL;
+}
diff --git a/core/src/fpdfdoc/doc_ap.cpp b/core/src/fpdfdoc/doc_ap.cpp new file mode 100644 index 0000000000..0afe718fcd --- /dev/null +++ b/core/src/fpdfdoc/doc_ap.cpp @@ -0,0 +1,808 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+#include "../../include/fpdfdoc/fpdf_vt.h"
+#include "pdf_vt.h"
+#include "../../include/fpdfdoc/fpdf_ap.h"
+FX_BOOL FPDF_GenerateAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict)
+{
+ if (pAnnotDict->GetConstString("Subtype") != FX_BSTRC("Widget")) {
+ return FALSE;
+ }
+ CFX_ByteString field_type = FPDF_GetFieldAttr(pAnnotDict, "FT")->GetString();
+ FX_DWORD flags = FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger();
+ if (field_type == "Tx") {
+ return CPVT_GenerateAP::GenerateTextFieldAP(pDoc, pAnnotDict);
+ } else if (field_type == "Ch") {
+ if (flags & (1 << 17)) {
+ return CPVT_GenerateAP::GenerateComboBoxAP(pDoc, pAnnotDict);
+ } else {
+ return CPVT_GenerateAP::GenerateListBoxAP(pDoc, pAnnotDict);
+ }
+ } else if (field_type == "Btn") {
+ if (!(flags & (1 << 16))) {
+ if (!pAnnotDict->KeyExist("AS")) {
+ if (CPDF_Dictionary* pParentDict = pAnnotDict->GetDict("Parent")) {
+ if (pParentDict->KeyExist("AS")) {
+ pAnnotDict->SetAtString("AS", pParentDict->GetString("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);
+ virtual ~CPVT_FontMap();
+ CPDF_Font* GetPDFFont(FX_INT32 nFontIndex);
+ CFX_ByteString GetPDFFontAlias(FX_INT32 nFontIndex);
+ 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()
+{
+}
+extern CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag);
+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()->GetDict("AcroForm");
+ if (CPDF_Font * pPDFFont = AddNativeInterFormFont(pFormDict, pDoc, sSysFontAlias)) {
+ if (CPDF_Dictionary * pFontList = pResDict->GetDict("Font")) {
+ if (!pFontList->KeyExist(sSysFontAlias)) {
+ pFontList->SetAtReference(sSysFontAlias, pDoc, pPDFFont->GetFontDict());
+ }
+ }
+ pSysFont = pPDFFont;
+ }
+ }
+}
+CPDF_Font* CPVT_FontMap::GetPDFFont(FX_INT32 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(FX_INT32 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 != NULL);
+}
+CPVT_Provider::~CPVT_Provider()
+{
+}
+FX_INT32 CPVT_Provider::GetCharWidth(FX_INT32 nFontIndex, FX_WORD word, FX_INT32 nWordStyle)
+{
+ if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) {
+ FX_DWORD charcode = pPDFFont->CharCodeFromUnicode(word);
+ if (charcode != -1) {
+ return pPDFFont->GetCharWidthF(charcode);
+ }
+ }
+ return 0;
+}
+FX_INT32 CPVT_Provider::GetTypeAscent(FX_INT32 nFontIndex)
+{
+ if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) {
+ return pPDFFont->GetTypeAscent();
+ }
+ return 0;
+}
+FX_INT32 CPVT_Provider::GetTypeDescent(FX_INT32 nFontIndex)
+{
+ if (CPDF_Font* pPDFFont = m_pFontMap->GetPDFFont(nFontIndex)) {
+ return pPDFFont->GetTypeDescent();
+ }
+ return 0;
+}
+FX_INT32 CPVT_Provider::GetWordFontIndex(FX_WORD word, FX_INT32 charset, FX_INT32 nFontIndex)
+{
+ if (CPDF_Font* pDefFont = m_pFontMap->GetPDFFont(0)) {
+ if (pDefFont->CharCodeFromUnicode(word) != -1) {
+ return 0;
+ }
+ }
+ if (CPDF_Font* pSysFont = m_pFontMap->GetPDFFont(1))
+ if (pSysFont->CharCodeFromUnicode(word) != -1) {
+ return 1;
+ }
+ return -1;
+}
+FX_BOOL CPVT_Provider::IsLatinWord(FX_WORD word)
+{
+ if ((word >= 0x61 && word <= 0x7A) || (word >= 0x41 && word <= 0x5A) || word == 0x2D || word == 0x27) {
+ return TRUE;
+ }
+ return FALSE;
+}
+FX_INT32 CPVT_Provider::GetDefaultFontIndex()
+{
+ return 0;
+}
+static CFX_ByteString GetPDFWordString(IPVT_FontMap * pFontMap, FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord)
+{
+ CFX_ByteString sWord;
+ if (SubWord > 0) {
+ sWord.Format("%c", SubWord);
+ } else {
+ if (pFontMap) {
+ if (CPDF_Font * pPDFFont = pFontMap->GetPDFFont(nFontIndex)) {
+ if (pPDFFont->GetBaseFont().Compare("Symbol") == 0 || pPDFFont->GetBaseFont().Compare("ZapfDingbats") == 0) {
+ sWord.Format("%c", Word);
+ } else {
+ FX_DWORD dwCharCode = pPDFFont->CharCodeFromUnicode(Word);
+ if (dwCharCode != -1) {
+ 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, FX_INT32 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);
+ syntax.SetPos(0);
+ if (syntax.FindTagParam("g", 1)) {
+ return CPVT_Color(CT_GRAY, FX_atof(syntax.GetWord()));
+ }
+ syntax.SetPos(0);
+ if (syntax.FindTagParam("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(CT_RGB, f1, f2, f3);
+ }
+ syntax.SetPos(0);
+ if (syntax.FindTagParam("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(CT_CMYK, f1, f2, f3, f4);
+ }
+ return CPVT_Color(CT_TRANSPARENT);
+}
+static CPVT_Color ParseColor(const CPDF_Array & array)
+{
+ CPVT_Color rt;
+ switch (array.GetCount()) {
+ case 1:
+ rt = CPVT_Color(CT_GRAY, array.GetFloat(0));
+ break;
+ case 3:
+ rt = CPVT_Color(CT_RGB, array.GetFloat(0), array.GetFloat(1), array.GetFloat(2));
+ break;
+ case 4:
+ rt = CPVT_Color(CT_CMYK, array.GetFloat(0), array.GetFloat(1), array.GetFloat(2), array.GetFloat(3));
+ break;
+ }
+ return rt;
+}
+static FX_BOOL GenerateWidgetAP(CPDF_Document* pDoc, CPDF_Dictionary* pAnnotDict, const FX_INT32 & nWidgetType)
+{
+ CPDF_Dictionary* pFormDict = NULL;
+ if (CPDF_Dictionary * pRootDict = pDoc->GetRoot()) {
+ pFormDict = pRootDict->GetDict("AcroForm");
+ }
+ if (!pFormDict) {
+ return FALSE;
+ }
+ CFX_ByteString DA = FPDF_GetFieldAttr(pAnnotDict, "DA")->GetString();
+ if (DA.IsEmpty()) {
+ DA = pFormDict->GetString("DA");
+ }
+ if (DA.IsEmpty()) {
+ return FALSE;
+ }
+ CPDF_SimpleParser syntax(DA);
+ syntax.FindTagParam("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->GetDict(FX_BSTRC("DR"));
+ if (pDRDict == NULL) {
+ pDRDict = pFormDict->GetDict(FX_BSTRC("DR"));
+ bUseFormRes = TRUE;
+ }
+ CPDF_Dictionary * pDRFontDict = NULL;
+ if ((pDRFontDict = pDRDict->GetDict("Font"))) {
+ pFontDict = pDRFontDict->GetDict(sFontName.Mid(1));
+ if (!pFontDict && !bUseFormRes) {
+ pDRDict = pFormDict->GetDict(FX_BSTRC("DR"));
+ pDRFontDict = pDRDict->GetDict("Font");
+ if (pDRFontDict) {
+ pFontDict = pDRFontDict->GetDict(sFontName.Mid(1));
+ }
+ }
+ }
+ if (!pDRFontDict) {
+ return FALSE;
+ }
+ if (!pFontDict) {
+ pFontDict = CPDF_Dictionary::Create();
+ if (pFontDict == NULL) {
+ return FALSE;
+ }
+ pFontDict->SetAtName(FX_BSTRC("Type"), "Font");
+ pFontDict->SetAtName(FX_BSTRC("Subtype"), "Type1");
+ pFontDict->SetAtName(FX_BSTRC("BaseFont"), "Helvetica");
+ pFontDict->SetAtName(FX_BSTRC("Encoding"), "WinAnsiEncoding");
+ pDoc->AddIndirectObject(pFontDict);
+ pDRFontDict->SetAtReference(sFontName.Mid(1), pDoc, pFontDict);
+ }
+ CPDF_Font* pDefFont = pDoc->LoadFont(pFontDict);
+ if (!pDefFont) {
+ return FALSE;
+ }
+ CFX_CharMap* pCharMap = pDefFont->GetCharMap();
+ CPDF_Rect rcAnnot = pAnnotDict->GetRect("Rect");
+ FX_INT32 nRotate = 0;
+ if (CPDF_Dictionary * pMKDict = pAnnotDict->GetDict("MK")) {
+ nRotate = pMKDict->GetInteger("R");
+ }
+ CPDF_Rect rcBBox;
+ CPDF_Matrix matrix;
+ switch (nRotate % 360) {
+ case 0:
+ rcBBox = CPDF_Rect(0, 0, rcAnnot.right - rcAnnot.left, rcAnnot.top - rcAnnot.bottom);
+ break;
+ case 90:
+ matrix = CPDF_Matrix(0, 1, -1, 0, rcAnnot.right - rcAnnot.left, 0);
+ rcBBox = CPDF_Rect(0, 0, rcAnnot.top - rcAnnot.bottom, rcAnnot.right - rcAnnot.left);
+ break;
+ case 180:
+ matrix = CPDF_Matrix(-1, 0, 0, -1, rcAnnot.right - rcAnnot.left, rcAnnot.top - rcAnnot.bottom);
+ rcBBox = CPDF_Rect(0, 0, rcAnnot.right - rcAnnot.left, rcAnnot.top - rcAnnot.bottom);
+ break;
+ case 270:
+ matrix = CPDF_Matrix(0, -1, 1, 0, 0, rcAnnot.top - rcAnnot.bottom);
+ rcBBox = CPDF_Rect(0, 0, rcAnnot.top - rcAnnot.bottom, rcAnnot.right - rcAnnot.left);
+ break;
+ }
+ FX_INT32 nBorderStyle = PBS_SOLID;
+ FX_FLOAT fBorderWidth = 1;
+ CPVT_Dash dsBorder(3, 0, 0);
+ CPVT_Color crLeftTop, crRightBottom;
+ if (CPDF_Dictionary * pBSDict = pAnnotDict->GetDict("BS")) {
+ if (pBSDict->KeyExist("W")) {
+ fBorderWidth = pBSDict->GetNumber("W");
+ }
+ if (CPDF_Array * pArray = pBSDict->GetArray("D")) {
+ dsBorder = CPVT_Dash(pArray->GetInteger(0), pArray->GetInteger(1), pArray->GetInteger(2));
+ }
+ switch (pBSDict->GetString("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(CT_GRAY, 1);
+ crRightBottom = CPVT_Color(CT_GRAY, 0.5);
+ break;
+ case 'I':
+ nBorderStyle = PBS_INSET;
+ fBorderWidth *= 2;
+ crLeftTop = CPVT_Color(CT_GRAY, 0.5);
+ crRightBottom = CPVT_Color(CT_GRAY, 0.75);
+ break;
+ case 'U':
+ nBorderStyle = PBS_UNDERLINED;
+ break;
+ }
+ }
+ CPVT_Color crBorder, crBG;
+ if (CPDF_Dictionary * pMKDict = pAnnotDict->GetDict("MK")) {
+ if (CPDF_Array * pArray = pMKDict->GetArray("BC")) {
+ crBorder = ParseColor(*pArray);
+ }
+ if (CPDF_Array * pArray = pMKDict->GetArray("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";
+ }
+ CPDF_Rect rcBody = CPDF_Rect(rcBBox.left + fBorderWidth, rcBBox.bottom + fBorderWidth,
+ rcBBox.right - fBorderWidth, rcBBox.top - fBorderWidth);
+ rcBody.Normalize();
+ CPDF_Dictionary* pAPDict = pAnnotDict->GetDict("AP");
+ if (pAPDict == NULL) {
+ pAPDict = CPDF_Dictionary::Create();
+ if (pAPDict == NULL) {
+ return FALSE;
+ }
+ pAnnotDict->SetAt("AP", pAPDict);
+ }
+ CPDF_Stream* pNormalStream = pAPDict->GetStream("N");
+ if (pNormalStream == NULL) {
+ pNormalStream = CPDF_Stream::Create(NULL, 0, NULL);
+ if (pNormalStream == NULL) {
+ return FALSE;
+ }
+ FX_INT32 objnum = pDoc->AddIndirectObject(pNormalStream);
+ pAnnotDict->GetDict("AP")->SetAtReference("N", pDoc, objnum);
+ }
+ CPDF_Dictionary * pStreamDict = pNormalStream->GetDict();
+ if (pStreamDict) {
+ pStreamDict->SetAtMatrix("Matrix", matrix);
+ pStreamDict->SetAtRect("BBox", rcBBox);
+ CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources");
+ if (pStreamResList) {
+ CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font");
+ if (!pStreamResFontList) {
+ pStreamResFontList = CPDF_Dictionary::Create();
+ if (pStreamResFontList == NULL) {
+ return FALSE;
+ }
+ pStreamResList->SetAt("Font", pStreamResFontList);
+ }
+ if (!pStreamResFontList->KeyExist(sFontName)) {
+ pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict);
+ }
+ } else {
+ pStreamDict->SetAt("Resources", pFormDict->GetDict("DR")->Clone());
+ pStreamResList = pStreamDict->GetDict("Resources");
+ }
+ }
+ switch (nWidgetType) {
+ case 0: {
+ CFX_WideString swValue = FPDF_GetFieldAttr(pAnnotDict, "V")->GetUnicodeText();
+ FX_INT32 nAlign = FPDF_GetFieldAttr(pAnnotDict, "Q")->GetInteger();
+ FX_DWORD dwFlags = FPDF_GetFieldAttr(pAnnotDict, "Ff")->GetInteger();
+ FX_DWORD dwMaxLen = FPDF_GetFieldAttr(pAnnotDict, "MaxLen")->GetInteger();
+ CPVT_FontMap map(pDoc, pStreamDict->GetDict("Resources"), 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);
+ }
+ FX_WORD 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);
+ vt.RearrangeAll();
+ CPDF_Rect rcContent = vt.GetContentRect();
+ CPDF_Point ptOffset(0.0f, 0.0f);
+ if (!bMultiLine) {
+ ptOffset = CPDF_Point(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")->GetUnicodeText();
+ CPVT_FontMap map(pDoc, pStreamDict->GetDict("Resources"), pDefFont, sFontName.Right(sFontName.GetLength() - 1));
+ CPVT_Provider prd(&map);
+ CPDF_VariableText vt;
+ vt.SetProvider(&prd);
+ CPDF_Rect rcButton = rcBody;
+ rcButton.left = rcButton.right - 13;
+ rcButton.Normalize();
+ CPDF_Rect 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);
+ vt.RearrangeAll();
+ CPDF_Rect rcContent = vt.GetContentRect();
+ CPDF_Point ptOffset = CPDF_Point(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(CT_RGB, 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(CT_GRAY, 0), CPVT_Color(CT_GRAY, 1), CPVT_Color(CT_GRAY, 0.5), PBS_BEVELED, CPVT_Dash(3, 0, 0));
+ if (sButtonBorder.GetLength() > 0) {
+ sAppStream << "q\n" << sButtonBorder << "Q\n";
+ }
+ CPDF_Point ptCenter = CPDF_Point((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->GetDict("Resources"), pDefFont, sFontName.Right(sFontName.GetLength() - 1));
+ CPVT_Provider prd(&map);
+ CPDF_Array * pOpts = FPDF_GetFieldAttr(pAnnotDict, "Opt")->GetArray();
+ CPDF_Array * pSels = FPDF_GetFieldAttr(pAnnotDict, "I")->GetArray();
+ FX_INT32 nTop = FPDF_GetFieldAttr(pAnnotDict, "TI")->GetInteger();
+ CFX_ByteTextBuf sBody;
+ if (pOpts) {
+ FX_FLOAT fy = rcBody.top;
+ for (FX_INT32 i = nTop, sz = pOpts->GetCount(); i < sz; i++) {
+ if (IsFloatSmaller(fy, rcBody.bottom)) {
+ break;
+ }
+ if (CPDF_Object* pOpt = pOpts->GetElementValue(i)) {
+ CFX_WideString swItem;
+ if (pOpt->GetType() == PDFOBJ_STRING) {
+ swItem = pOpt->GetUnicodeText();
+ } else if (pOpt->GetType() == PDFOBJ_ARRAY) {
+ swItem = ((CPDF_Array*)pOpt)->GetElementValue(1)->GetUnicodeText();
+ }
+ FX_BOOL bSelected = FALSE;
+ if (pSels) {
+ for (FX_DWORD s = 0, ssz = pSels->GetCount(); s < ssz; s++) {
+ if (i == pSels->GetInteger(s)) {
+ bSelected = TRUE;
+ break;
+ }
+ }
+ }
+ CPDF_VariableText vt;
+ vt.SetProvider(&prd);
+ vt.SetPlateRect(CPDF_Rect(rcBody.left, 0.0f, rcBody.right, 0.0f));
+ if (IsFloatZero(fFontSize)) {
+ vt.SetFontSize(12.0f);
+ } else {
+ vt.SetFontSize(fFontSize);
+ }
+ vt.Initialize();
+ vt.SetText(swItem);
+ vt.RearrangeAll();
+ FX_FLOAT fItemHeight = vt.GetContentRect().Height();
+ if (bSelected) {
+ CPDF_Rect rcItem = CPDF_Rect(rcBody.left, fy - fItemHeight, rcBody.right, fy);
+ sBody << "q\n" << CPVT_GenerateAP::GenerateColorAP(CPVT_Color(CT_RGB, 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(CT_GRAY, 1), TRUE) << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), CPDF_Point(0.0f, fy), TRUE, 0) << "ET\n";
+ } else {
+ sBody << "BT\n" << CPVT_GenerateAP::GenerateColorAP(crText, TRUE) << CPVT_GenerateAP::GenerateEditAP(&map, vt.GetIterator(), CPDF_Point(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((FX_BYTE*)sAppStream.GetBuffer(), sAppStream.GetSize(), FALSE, FALSE);
+ pStreamDict = pNormalStream->GetDict();
+ if (pStreamDict) {
+ pStreamDict->SetAtMatrix("Matrix", matrix);
+ pStreamDict->SetAtRect("BBox", rcBBox);
+ CPDF_Dictionary* pStreamResList = pStreamDict->GetDict("Resources");
+ if (pStreamResList) {
+ CPDF_Dictionary* pStreamResFontList = pStreamResList->GetDict("Font");
+ if (!pStreamResFontList) {
+ pStreamResFontList = CPDF_Dictionary::Create();
+ if (pStreamResFontList == NULL) {
+ return FALSE;
+ }
+ pStreamResList->SetAt("Font", pStreamResFontList);
+ }
+ if (!pStreamResFontList->KeyExist(sFontName)) {
+ pStreamResFontList->SetAtReference(sFontName, pDoc, pFontDict);
+ }
+ } else {
+ pStreamDict->SetAt("Resources", pFormDict->GetDict("DR")->Clone());
+ pStreamResList = pStreamDict->GetDict("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 CPDF_Point & ptOffset, FX_BOOL bContinuous, FX_WORD SubWord, const CPVT_WordRange * pVisible)
+{
+ CFX_ByteTextBuf sEditStream, sLineStream, sWords;
+ CPDF_Point ptOld(0.0f, 0.0f), ptNew(0.0f, 0.0f);
+ FX_INT32 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 = CPDF_Point(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
+ } else {
+ CPVT_Line line;
+ pIterator->GetLine(line);
+ ptNew = CPDF_Point(line.ptLine.x + ptOffset.x, line.ptLine.y + ptOffset.y);
+ }
+ if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
+ 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 = CPDF_Point(word.ptWord.x + ptOffset.x, word.ptWord.y + ptOffset.y);
+ if (ptNew.x != ptOld.x || ptNew.y != ptOld.y) {
+ sEditStream << ptNew.x - ptOld.x << " " << ptNew.y - ptOld.y << " Td\n";
+ ptOld = ptNew;
+ }
+ if (word.nFontIndex != nCurFontIndex) {
+ sEditStream << GetFontSetString(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 CPDF_Rect & rect, FX_FLOAT fWidth,
+ const CPVT_Color & color, const CPVT_Color & crLeftTop, const CPVT_Color & crRightBottom,
+ FX_INT32 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 CT_RGB:
+ sColorStream << color.fColor1 << " " << color.fColor2 << " " << color.fColor3 << " "
+ << (bFillOrStroke ? "rg" : "RG") << "\n";
+ break;
+ case CT_GRAY:
+ sColorStream << color.fColor1 << " " << (bFillOrStroke ? "g" : "G") << "\n";
+ break;
+ case CT_CMYK:
+ sColorStream << color.fColor1 << " " << color.fColor2 << " " << color.fColor3 << " " << color.fColor4 << " "
+ << (bFillOrStroke ? "k" : "K") << "\n";
+ break;
+ }
+ return sColorStream.GetByteString();
+}
diff --git a/core/src/fpdfdoc/doc_basic.cpp b/core/src/fpdfdoc/doc_basic.cpp new file mode 100644 index 0000000000..4ec8fb74fd --- /dev/null +++ b/core/src/fpdfdoc/doc_basic.cpp @@ -0,0 +1,567 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+const int nMaxRecursion = 32;
+int CPDF_Dest::GetPageIndex(CPDF_Document* pDoc)
+{
+ if (m_pObj == NULL || m_pObj->GetType() != PDFOBJ_ARRAY) {
+ return 0;
+ }
+ CPDF_Object* pPage = ((CPDF_Array*)m_pObj)->GetElementValue(0);
+ if (pPage == NULL) {
+ return 0;
+ }
+ if (pPage->GetType() == PDFOBJ_NUMBER) {
+ return pPage->GetInteger();
+ }
+ if (pPage->GetType() != PDFOBJ_DICTIONARY) {
+ return 0;
+ }
+ return pDoc->GetPageIndex(pPage->GetObjNum());
+}
+FX_DWORD CPDF_Dest::GetPageObjNum()
+{
+ if (m_pObj == NULL || m_pObj->GetType() != PDFOBJ_ARRAY) {
+ return 0;
+ }
+ CPDF_Object* pPage = ((CPDF_Array*)m_pObj)->GetElementValue(0);
+ if (pPage == NULL) {
+ return 0;
+ }
+ if (pPage->GetType() == PDFOBJ_NUMBER) {
+ return pPage->GetInteger();
+ }
+ if (pPage->GetType() == PDFOBJ_DICTIONARY) {
+ return pPage->GetObjNum();
+ }
+ return 0;
+}
+const FX_CHAR* g_sZoomModes[] = {"XYZ", "Fit", "FitH", "FitV", "FitR", "FitB", "FitBH", "FitBV", ""};
+int CPDF_Dest::GetZoomMode()
+{
+ if (m_pObj == NULL || m_pObj->GetType() != PDFOBJ_ARRAY) {
+ return 0;
+ }
+ CFX_ByteString mode = ((CPDF_Array*)m_pObj)->GetElementValue(1)->GetString();
+ int i = 0;
+ while (g_sZoomModes[i][0] != '\0') {
+ if (mode == g_sZoomModes[i]) {
+ return i + 1;
+ }
+ i ++;
+ }
+ return 0;
+}
+FX_FLOAT CPDF_Dest::GetParam(int index)
+{
+ if (m_pObj == NULL || m_pObj->GetType() != PDFOBJ_ARRAY) {
+ return 0;
+ }
+ return ((CPDF_Array*)m_pObj)->GetNumber(2 + index);
+}
+CFX_ByteString CPDF_Dest::GetRemoteName()
+{
+ if (m_pObj == NULL) {
+ return CFX_ByteString();
+ }
+ return m_pObj->GetString();
+}
+CPDF_NameTree::CPDF_NameTree(CPDF_Document* pDoc, FX_BSTR category)
+{
+ m_pRoot = pDoc->GetRoot()->GetDict(FX_BSTRC("Names"))->GetDict(category);
+}
+static CPDF_Object* SearchNameNode(CPDF_Dictionary* pNode, const CFX_ByteString& csName,
+ int& nIndex, CPDF_Array** ppFind, int nLevel = 0)
+{
+ if (nLevel > nMaxRecursion) {
+ return NULL;
+ }
+ CPDF_Array* pLimits = pNode->GetArray(FX_BSTRC("Limits"));
+ if (pLimits != NULL) {
+ CFX_ByteString csLeft = pLimits->GetString(0);
+ CFX_ByteString csRight = pLimits->GetString(1);
+ if (csLeft.Compare(csRight) > 0) {
+ CFX_ByteString csTmp = csRight;
+ csRight = csLeft;
+ csLeft = csTmp;
+ }
+ if (csName.Compare(csLeft) < 0 || csName.Compare(csRight) > 0) {
+ return NULL;
+ }
+ }
+ CPDF_Array* pNames = pNode->GetArray(FX_BSTRC("Names"));
+ if (pNames) {
+ FX_DWORD dwCount = pNames->GetCount() / 2;
+ for (FX_DWORD i = 0; i < dwCount; i ++) {
+ CFX_ByteString csValue = pNames->GetString(i * 2);
+ FX_INT32 iCompare = csValue.Compare(csName);
+ if (iCompare <= 0) {
+ if (ppFind != NULL) {
+ *ppFind = pNames;
+ }
+ if (iCompare < 0) {
+ continue;
+ }
+ } else {
+ break;
+ }
+ nIndex += i;
+ return pNames->GetElementValue(i * 2 + 1);
+ }
+ nIndex += dwCount;
+ return NULL;
+ }
+ CPDF_Array* pKids = pNode->GetArray(FX_BSTRC("Kids"));
+ if (pKids == NULL) {
+ return NULL;
+ }
+ for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
+ CPDF_Dictionary* pKid = pKids->GetDict(i);
+ if (pKid == NULL) {
+ continue;
+ }
+ CPDF_Object* pFound = SearchNameNode(pKid, csName, nIndex, ppFind, nLevel + 1);
+ if (pFound) {
+ return pFound;
+ }
+ }
+ return NULL;
+}
+static CPDF_Object* SearchNameNode(CPDF_Dictionary* pNode, int nIndex, int& nCurIndex,
+ CFX_ByteString& csName, CPDF_Array** ppFind, int nLevel = 0)
+{
+ if (nLevel > nMaxRecursion) {
+ return NULL;
+ }
+ CPDF_Array* pNames = pNode->GetArray(FX_BSTRC("Names"));
+ if (pNames) {
+ int nCount = pNames->GetCount() / 2;
+ if (nIndex >= nCurIndex + nCount) {
+ nCurIndex += nCount;
+ return NULL;
+ } else {
+ if (ppFind != NULL) {
+ *ppFind = pNames;
+ }
+ csName = pNames->GetString((nIndex - nCurIndex) * 2);
+ return pNames->GetElementValue((nIndex - nCurIndex) * 2 + 1);
+ }
+ }
+ CPDF_Array* pKids = pNode->GetArray(FX_BSTRC("Kids"));
+ if (pKids == NULL) {
+ return NULL;
+ }
+ for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
+ CPDF_Dictionary* pKid = pKids->GetDict(i);
+ if (pKid == NULL) {
+ continue;
+ }
+ CPDF_Object* pFound = SearchNameNode(pKid, nIndex, nCurIndex, csName, ppFind, nLevel + 1);
+ if (pFound) {
+ return pFound;
+ }
+ }
+ return NULL;
+}
+static int CountNames(CPDF_Dictionary* pNode, int nLevel = 0)
+{
+ if (nLevel > nMaxRecursion) {
+ return 0;
+ }
+ CPDF_Array* pNames = pNode->GetArray(FX_BSTRC("Names"));
+ if (pNames) {
+ return pNames->GetCount() / 2;
+ }
+ CPDF_Array* pKids = pNode->GetArray(FX_BSTRC("Kids"));
+ if (pKids == NULL) {
+ return 0;
+ }
+ int nCount = 0;
+ for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
+ CPDF_Dictionary* pKid = pKids->GetDict(i);
+ if (pKid == NULL) {
+ continue;
+ }
+ nCount += CountNames(pKid, nLevel + 1);
+ }
+ return nCount;
+}
+int CPDF_NameTree::GetCount() const
+{
+ if (m_pRoot == NULL) {
+ return 0;
+ }
+ return ::CountNames(m_pRoot);
+}
+int CPDF_NameTree::GetIndex(const CFX_ByteString& csName) const
+{
+ if (m_pRoot == NULL) {
+ return -1;
+ }
+ int nIndex = 0;
+ if (SearchNameNode(m_pRoot, csName, nIndex, NULL) == NULL) {
+ return -1;
+ }
+ return nIndex;
+}
+CPDF_Object* CPDF_NameTree::LookupValue(int nIndex, CFX_ByteString& csName) const
+{
+ if (m_pRoot == NULL) {
+ return NULL;
+ }
+ int nCurIndex = 0;
+ return SearchNameNode(m_pRoot, nIndex, nCurIndex, csName, NULL);
+}
+CPDF_Object* CPDF_NameTree::LookupValue(const CFX_ByteString& csName) const
+{
+ if (m_pRoot == NULL) {
+ return NULL;
+ }
+ int nIndex = 0;
+ return SearchNameNode(m_pRoot, csName, nIndex, NULL);
+}
+CPDF_Array* CPDF_NameTree::LookupNamedDest(CPDF_Document* pDoc, FX_BSTR sName)
+{
+ CPDF_Object* pValue = LookupValue(sName);
+ if (pValue == NULL) {
+ CPDF_Dictionary* pDests = pDoc->GetRoot()->GetDict(FX_BSTRC("Dests"));
+ if (pDests == NULL) {
+ return NULL;
+ }
+ pValue = pDests->GetElementValue(sName);
+ }
+ if (pValue == NULL) {
+ return NULL;
+ }
+ if (pValue->GetType() == PDFOBJ_ARRAY) {
+ return (CPDF_Array*)pValue;
+ }
+ if (pValue->GetType() == PDFOBJ_DICTIONARY) {
+ return ((CPDF_Dictionary*)pValue)->GetArray(FX_BSTRC("D"));
+ }
+ return NULL;
+}
+static CFX_WideString ChangeSlashToPlatform(FX_LPCWSTR str)
+{
+ CFX_WideString result;
+ while (*str) {
+ if (*str == '/') {
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+ result += ':';
+#elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ result += '\\';
+#else
+ result += *str;
+#endif
+ } else {
+ result += *str;
+ }
+ str++;
+ }
+ return result;
+}
+static CFX_WideString FILESPEC_DecodeFileName(FX_WSTR filepath)
+{
+ if (filepath.GetLength() <= 1) {
+ return CFX_WideString();
+ }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+ if (filepath.Left(sizeof("/Mac") - 1) == CFX_WideStringC(L"/Mac")) {
+ return ChangeSlashToPlatform(filepath.GetPtr() + 1);
+ }
+ return ChangeSlashToPlatform(filepath.GetPtr());
+#elif _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ if (filepath.GetAt(0) != '/') {
+ return ChangeSlashToPlatform(filepath.GetPtr());
+ }
+ if (filepath.GetAt(1) == '/') {
+ return ChangeSlashToPlatform(filepath.GetPtr() + 1);
+ }
+ if (filepath.GetAt(2) == '/') {
+ CFX_WideString result;
+ result += filepath.GetAt(1);
+ result += ':';
+ result += ChangeSlashToPlatform(filepath.GetPtr() + 2);
+ return result;
+ }
+ CFX_WideString result;
+ result += '\\';
+ result += ChangeSlashToPlatform(filepath.GetPtr());
+ return result;
+#else
+ return filepath;
+#endif
+}
+FX_BOOL CPDF_FileSpec::GetFileName(CFX_WideString &csFileName) const
+{
+ if (m_pObj == NULL) {
+ return FALSE;
+ }
+ if (m_pObj->GetType() == PDFOBJ_DICTIONARY) {
+ CPDF_Dictionary* pDict = (CPDF_Dictionary*)m_pObj;
+ csFileName = pDict->GetUnicodeText(FX_BSTRC("UF"));
+ if (csFileName.IsEmpty()) {
+ csFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("F")));
+ }
+ if (pDict->GetString(FX_BSTRC("FS")) == FX_BSTRC("URL")) {
+ return TRUE;
+ }
+ if (csFileName.IsEmpty()) {
+ if (pDict->KeyExist(FX_BSTRC("DOS"))) {
+ csFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("DOS")));
+ } else if (pDict->KeyExist(FX_BSTRC("Mac"))) {
+ csFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("Mac")));
+ } else if (pDict->KeyExist(FX_BSTRC("Unix"))) {
+ csFileName = CFX_WideString::FromLocal(pDict->GetString(FX_BSTRC("Unix")));
+ } else {
+ return FALSE;
+ }
+ }
+ } else {
+ csFileName = CFX_WideString::FromLocal(m_pObj->GetString());
+ }
+ csFileName = FILESPEC_DecodeFileName(csFileName);
+ return TRUE;
+}
+CPDF_FileSpec::CPDF_FileSpec()
+{
+ m_pObj = CPDF_Dictionary::Create();
+ if (m_pObj != NULL) {
+ ((CPDF_Dictionary*)m_pObj)->SetAtName(FX_BSTRC("Type"), FX_BSTRC("Filespec"));
+ }
+}
+FX_BOOL CPDF_FileSpec::IsURL() const
+{
+ if (m_pObj == NULL) {
+ return FALSE;
+ }
+ if (m_pObj->GetType() != PDFOBJ_DICTIONARY) {
+ return FALSE;
+ }
+ return ((CPDF_Dictionary*)m_pObj)->GetString(FX_BSTRC("FS")) == FX_BSTRC("URL");
+}
+static CFX_WideString ChangeSlashToPDF(FX_LPCWSTR str)
+{
+ CFX_WideString result;
+ while (*str) {
+ if (*str == '\\' || *str == ':') {
+ result += '/';
+ } else {
+ result += *str;
+ }
+ str++;
+ }
+ return result;
+}
+CFX_WideString FILESPEC_EncodeFileName(FX_WSTR filepath)
+{
+ if (filepath.GetLength() <= 1) {
+ return CFX_WideString();
+ }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ if (filepath.GetAt(1) == ':') {
+ CFX_WideString result;
+ result = '/';
+ result += filepath.GetAt(0);
+ if (filepath.GetAt(2) != '\\') {
+ result += '/';
+ }
+ result += ChangeSlashToPDF(filepath.GetPtr() + 2);
+ return result;
+ }
+ if (filepath.GetAt(0) == '\\' && filepath.GetAt(1) == '\\') {
+ return ChangeSlashToPDF(filepath.GetPtr() + 1);
+ }
+ if (filepath.GetAt(0) == '\\') {
+ CFX_WideString result;
+ result = '/';
+ result += ChangeSlashToPDF(filepath.GetPtr());
+ return result;
+ }
+ return ChangeSlashToPDF(filepath.GetPtr());
+#elif _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+ if (filepath.Left(sizeof("Mac") - 1) == FX_WSTRC(L"Mac")) {
+ CFX_WideString result;
+ result = '/';
+ result += ChangeSlashToPDF(filepath.GetPtr());
+ return result;
+ }
+ return ChangeSlashToPDF(filepath.GetPtr());
+#else
+ return filepath;
+#endif
+}
+CPDF_Stream* CPDF_FileSpec::GetFileStream() const
+{
+ if (m_pObj == NULL) {
+ return NULL;
+ }
+ FX_INT32 iType = m_pObj->GetType();
+ if (iType == PDFOBJ_STREAM) {
+ return (CPDF_Stream*)m_pObj;
+ } else if (iType == PDFOBJ_DICTIONARY) {
+ CPDF_Dictionary *pEF = ((CPDF_Dictionary*)m_pObj)->GetDict(FX_BSTRC("EF"));
+ if (pEF == NULL) {
+ return NULL;
+ }
+ return pEF->GetStream(FX_BSTRC("F"));
+ }
+ return NULL;
+}
+static void FPDFDOC_FILESPEC_SetFileName(CPDF_Object *pObj, FX_WSTR wsFileName, FX_BOOL bURL)
+{
+ ASSERT(pObj != NULL);
+ CFX_WideString wsStr;
+ if (bURL) {
+ wsStr = wsFileName;
+ } else {
+ wsStr = FILESPEC_EncodeFileName(wsFileName);
+ }
+ FX_INT32 iType = pObj->GetType();
+ if (iType == PDFOBJ_STRING) {
+ pObj->SetString(CFX_ByteString::FromUnicode(wsStr));
+ } else if (iType == PDFOBJ_DICTIONARY) {
+ CPDF_Dictionary* pDict = (CPDF_Dictionary*)pObj;
+ pDict->SetAtString(FX_BSTRC("F"), CFX_ByteString::FromUnicode(wsStr));
+ pDict->SetAtString(FX_BSTRC("UF"), PDF_EncodeText(wsStr));
+ }
+}
+void CPDF_FileSpec::SetFileName(FX_WSTR wsFileName, FX_BOOL bURL)
+{
+ ASSERT(m_pObj != NULL);
+ if (m_pObj->GetType() == PDFOBJ_DICTIONARY && bURL) {
+ ((CPDF_Dictionary*)m_pObj)->SetAtName(FX_BSTRC("FS"), "URL");
+ }
+ FPDFDOC_FILESPEC_SetFileName(m_pObj, wsFileName, bURL);
+}
+static CFX_WideString _MakeRoman(int num)
+{
+ const int arabic[] = {
+ 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1
+ };
+ const CFX_WideString roman[] = {
+ L"m", L"cm", L"d", L"cd", L"c", L"xc", L"l", L"xl", L"x", L"ix", L"v", L"iv", L"i"
+ };
+ const int nMaxNum = 1000000;
+ num %= nMaxNum;
+ int i = 0;
+ CFX_WideString wsRomanNumber;
+ while (num > 0) {
+ while (num >= arabic[i]) {
+ num = num - arabic[i];
+ wsRomanNumber += roman[i];
+ }
+ i = i + 1;
+ }
+ return wsRomanNumber;
+}
+static CFX_WideString _MakeLetters(int num)
+{
+ if (num == 0) {
+ return CFX_WideString();
+ }
+ CFX_WideString wsLetters;
+ const int nMaxCount = 1000;
+ const int nLetterCount = 26;
+ num -= 1;
+ int count = num / nLetterCount + 1;
+ count %= nMaxCount;
+ FX_WCHAR ch = L'a' + num % nLetterCount;
+ for (int i = 0; i < count; i++) {
+ wsLetters += ch;
+ }
+ return wsLetters;
+}
+static CFX_WideString _GetLabelNumPortion(int num, const CFX_ByteString& bsStyle)
+{
+ CFX_WideString wsNumPortion;
+ if (bsStyle.IsEmpty()) {
+ return wsNumPortion;
+ }
+ if (bsStyle == "D") {
+ wsNumPortion.Format((FX_LPCWSTR)L"%d", num);
+ } else if (bsStyle == "R") {
+ wsNumPortion = _MakeRoman(num);
+ wsNumPortion.MakeUpper();
+ } else if (bsStyle == "r") {
+ wsNumPortion = _MakeRoman(num);
+ } else if (bsStyle == "A") {
+ wsNumPortion = _MakeLetters(num);
+ wsNumPortion.MakeUpper();
+ } else if (bsStyle == "a") {
+ wsNumPortion = _MakeLetters(num);
+ }
+ return wsNumPortion;
+}
+CFX_WideString CPDF_PageLabel::GetLabel(int nPage) const
+{
+ CFX_WideString wsLabel;
+ if (m_pDocument == NULL) {
+ return wsLabel;
+ }
+ CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot();
+ if (pPDFRoot == NULL) {
+ return wsLabel;
+ }
+ CPDF_Dictionary* pLabels = pPDFRoot->GetDict(FX_BSTRC("PageLabels"));
+ CPDF_NumberTree numberTree(pLabels);
+ CPDF_Object* pValue = NULL;
+ int n = nPage;
+ while (n >= 0) {
+ pValue = numberTree.LookupValue(n);
+ if (pValue != NULL) {
+ break;
+ }
+ n--;
+ }
+ if (pValue != NULL) {
+ pValue = pValue->GetDirect();
+ if (pValue->GetType() == PDFOBJ_DICTIONARY) {
+ CPDF_Dictionary* pLabel = (CPDF_Dictionary*)pValue;
+ if (pLabel->KeyExist(FX_BSTRC("P"))) {
+ wsLabel += pLabel->GetUnicodeText(FX_BSTRC("P"));
+ }
+ CFX_ByteString bsNumberingStyle = pLabel->GetString(FX_BSTRC("S"), NULL);
+ int nLabelNum = nPage - n + pLabel->GetInteger(FX_BSTRC("St"), 1);
+ CFX_WideString wsNumPortion = _GetLabelNumPortion(nLabelNum, bsNumberingStyle);
+ wsLabel += wsNumPortion;
+ return wsLabel;
+ }
+ }
+ wsLabel.Format((FX_LPCWSTR)L"%d", nPage + 1);
+ return wsLabel;
+}
+FX_INT32 CPDF_PageLabel::GetPageByLabel(FX_BSTR bsLabel) const
+{
+ if (m_pDocument == NULL) {
+ return -1;
+ }
+ CPDF_Dictionary* pPDFRoot = m_pDocument->GetRoot();
+ if (pPDFRoot == NULL) {
+ return -1;
+ }
+ int nPages = m_pDocument->GetPageCount();
+ CFX_ByteString bsLbl;
+ CFX_ByteString bsOrig = bsLabel;
+ for (int i = 0; i < nPages; i++) {
+ bsLbl = PDF_EncodeText(GetLabel(i));
+ if (!bsLbl.Compare(bsOrig)) {
+ return i;
+ }
+ }
+ bsLbl = bsOrig;
+ int nPage = FXSYS_atoi(bsLbl);
+ if (nPage > 0 && nPage <= nPages) {
+ return nPage;
+ }
+ return -1;
+}
+FX_INT32 CPDF_PageLabel::GetPageByLabel(FX_WSTR wsLabel) const
+{
+ CFX_ByteString bsLabel = PDF_EncodeText((CFX_WideString)wsLabel);
+ return GetPageByLabel(bsLabel);
+}
diff --git a/core/src/fpdfdoc/doc_bookmark.cpp b/core/src/fpdfdoc/doc_bookmark.cpp new file mode 100644 index 0000000000..6cc954bd69 --- /dev/null +++ b/core/src/fpdfdoc/doc_bookmark.cpp @@ -0,0 +1,91 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+CPDF_Bookmark CPDF_BookmarkTree::GetFirstChild(CPDF_Bookmark Parent)
+{
+ if (Parent.m_pDict == NULL) {
+ CPDF_Dictionary* pRoot = m_pDocument->GetRoot()->GetDict("Outlines");
+ if (pRoot == NULL) {
+ return NULL;
+ }
+ return pRoot->GetDict("First");
+ }
+ return Parent.m_pDict->GetDict("First");
+}
+CPDF_Bookmark CPDF_BookmarkTree::GetNextSibling(CPDF_Bookmark This)
+{
+ if (This.m_pDict == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary *pNext = This.m_pDict->GetDict("Next");
+ return pNext == This.m_pDict ? NULL : pNext;
+}
+FX_DWORD CPDF_Bookmark::GetColorRef()
+{
+ if (!m_pDict) {
+ return 0;
+ }
+ CPDF_Array* pColor = m_pDict->GetArray("C");
+ if (pColor == NULL) {
+ return FXSYS_RGB(0, 0, 0);
+ }
+ int r = FXSYS_round(pColor->GetNumber(0) * 255);
+ int g = FXSYS_round(pColor->GetNumber(1) * 255);
+ int b = FXSYS_round(pColor->GetNumber(2) * 255);
+ return FXSYS_RGB(r, g, b);
+}
+FX_DWORD CPDF_Bookmark::GetFontStyle()
+{
+ if (!m_pDict) {
+ return 0;
+ }
+ return m_pDict->GetInteger("F");
+}
+CFX_WideString CPDF_Bookmark::GetTitle()
+{
+ if (!m_pDict) {
+ return CFX_WideString();
+ }
+ CPDF_String* pString = (CPDF_String*)m_pDict->GetElementValue("Title");
+ if (pString == NULL || pString->GetType() != PDFOBJ_STRING) {
+ return CFX_WideString();
+ }
+ CFX_WideString title = pString->GetUnicodeText();
+ FX_LPWSTR buf = title.LockBuffer();
+ int len = title.GetLength(), i;
+ for (i = 0; i < len; i ++)
+ if (buf[i] < 0x20) {
+ buf[i] = 0x20;
+ }
+ title.ReleaseBuffer(len);
+ return title;
+}
+CPDF_Dest CPDF_Bookmark::GetDest(CPDF_Document* pDocument)
+{
+ if (!m_pDict) {
+ return NULL;
+ }
+ CPDF_Object* pDest = m_pDict->GetElementValue("Dest");
+ if (pDest == NULL) {
+ return NULL;
+ }
+ if (pDest->GetType() == PDFOBJ_STRING || pDest->GetType() == PDFOBJ_NAME) {
+ CPDF_NameTree name_tree(pDocument, FX_BSTRC("Dests"));
+ CFX_ByteStringC name = pDest->GetString();
+ return name_tree.LookupNamedDest(pDocument, name);
+ } else if (pDest->GetType() == PDFOBJ_ARRAY) {
+ return (CPDF_Array*)pDest;
+ }
+ return NULL;
+}
+CPDF_Action CPDF_Bookmark::GetAction()
+{
+ if (!m_pDict) {
+ return NULL;
+ }
+ return m_pDict->GetDict("A");
+}
diff --git a/core/src/fpdfdoc/doc_form.cpp b/core/src/fpdfdoc/doc_form.cpp new file mode 100644 index 0000000000..1139233987 --- /dev/null +++ b/core/src/fpdfdoc/doc_form.cpp @@ -0,0 +1,1664 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+#include "../../include/fxcrt/fx_xml.h"
+CFX_WideString GetFullName(CPDF_Dictionary* pFieldDict);
+void InitInterFormDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument);
+FX_DWORD CountInterFormFonts(CPDF_Dictionary* pFormDict);
+CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_DWORD index, CFX_ByteString& csNameTag);
+CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csNameTag);
+CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CFX_ByteString& csNameTag);
+CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag);
+CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag);
+FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont, CFX_ByteString& csNameTag);
+FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CPDF_Font*& pFont, CFX_ByteString& csNameTag);
+void AddInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont, CFX_ByteString& csNameTag);
+CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag);
+CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag);
+void RemoveInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont);
+void RemoveInterFormFont(CPDF_Dictionary* pFormDict, CFX_ByteString csNameTag);
+CPDF_Font* GetDefaultInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument);
+void SetDefaultInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont);
+void SaveCheckedFieldStatus(CPDF_FormField* pField, CFX_ByteArray& statusArray);
+FX_BOOL NeedPDFEncodeForFieldFullName(const CFX_WideString& csFieldName);
+FX_BOOL NeedPDFEncodeForFieldTree(CPDF_Dictionary* pFieldDict, int nLevel = 0);
+void EncodeFieldName(const CFX_WideString& csName, CFX_ByteString& csT);
+void UpdateEncodeFieldName(CPDF_Dictionary* pFieldDict, int nLevel = 0);
+const int nMaxRecursion = 32;
+class _CFieldNameExtractor : public CFX_Object
+{
+public:
+ _CFieldNameExtractor(const CFX_WideString& full_name)
+ {
+ m_pStart = full_name;
+ m_pEnd = m_pStart + full_name.GetLength();
+ m_pCur = m_pStart;
+ }
+ void GetNext(FX_LPCWSTR &pSubName, FX_STRSIZE& size)
+ {
+ pSubName = m_pCur;
+ while (m_pCur < m_pEnd && m_pCur[0] != L'.') {
+ m_pCur++;
+ }
+ size = (FX_STRSIZE)(m_pCur - pSubName);
+ if (m_pCur < m_pEnd && m_pCur[0] == L'.') {
+ m_pCur++;
+ }
+ }
+protected:
+ FX_LPCWSTR m_pStart;
+ FX_LPCWSTR m_pEnd;
+ FX_LPCWSTR m_pCur;
+};
+class CFieldTree : public CFX_Object
+{
+public:
+ struct _Node : public CFX_Object {
+ _Node *parent;
+ CFX_PtrArray children;
+ CFX_WideString short_name;
+ CPDF_FormField *field_ptr;
+ int CountFields(int nLevel = 0)
+ {
+ if (nLevel > nMaxRecursion) {
+ return 0;
+ }
+ if (field_ptr) {
+ return 1;
+ }
+ int count = 0;
+ for (int i = 0; i < children.GetSize(); i ++) {
+ count += ((_Node *)children.GetAt(i))->CountFields(nLevel + 1);
+ }
+ return count;
+ }
+ CPDF_FormField* GetField(int* fields_to_go)
+ {
+ if (field_ptr) {
+ if (*fields_to_go == 0) {
+ return field_ptr;
+ }
+ --*fields_to_go;
+ return NULL;
+ }
+ for (int i = 0; i < children.GetSize(); i++) {
+ _Node *pNode = (_Node *)children.GetAt(i);
+ CPDF_FormField* pField = pNode->GetField(fields_to_go);
+ if (pField) {
+ return pField;
+ }
+ }
+ return NULL;
+ }
+ CPDF_FormField* GetField(int index)
+ {
+ int fields_to_go = index;
+ return GetField(&fields_to_go);
+ }
+ };
+ CFieldTree();
+ ~CFieldTree();
+ void SetField(const CFX_WideString &full_name, CPDF_FormField *field_ptr);
+ CPDF_FormField *GetField(const CFX_WideString &full_name);
+ CPDF_FormField *RemoveField(const CFX_WideString &full_name);
+ void RemoveAll();
+ _Node *FindNode(const CFX_WideString &full_name);
+ _Node * AddChild(_Node *pParent, const CFX_WideString &short_name, CPDF_FormField *field_ptr);
+ void RemoveNode(_Node *pNode, int nLevel = 0);
+ _Node *_Lookup(_Node *pParent, const CFX_WideString &short_name);
+ _Node m_Root;
+};
+CFieldTree::CFieldTree()
+{
+ m_Root.parent = NULL;
+ m_Root.field_ptr = NULL;
+}
+CFieldTree::~CFieldTree()
+{
+ RemoveAll();
+}
+CFieldTree::_Node *CFieldTree::AddChild(_Node *pParent, const CFX_WideString &short_name, CPDF_FormField *field_ptr)
+{
+ if (pParent == NULL) {
+ return NULL;
+ }
+ _Node *pNode = FX_NEW _Node;
+ if (pNode == NULL) {
+ return NULL;
+ }
+ pNode->parent = pParent;
+ pNode->short_name = short_name;
+ pNode->field_ptr = field_ptr;
+ pParent->children.Add(pNode);
+ return pNode;
+}
+void CFieldTree::RemoveNode(_Node *pNode, int nLevel)
+{
+ if (pNode == NULL) {
+ return ;
+ }
+ if (nLevel > nMaxRecursion) {
+ delete pNode;
+ return ;
+ }
+ CFX_PtrArray& ptr_array = pNode->children;
+ for (int i = 0; i < ptr_array.GetSize(); i ++) {
+ _Node *pChild = (_Node *)ptr_array[i];
+ RemoveNode(pChild, nLevel + 1);
+ }
+ delete pNode;
+}
+CFieldTree::_Node *CFieldTree::_Lookup(_Node *pParent, const CFX_WideString &short_name)
+{
+ if (pParent == NULL) {
+ return NULL;
+ }
+ CFX_PtrArray& ptr_array = pParent->children;
+ for (int i = 0; i < ptr_array.GetSize(); i ++) {
+ _Node *pNode = (_Node *)ptr_array[i];
+ if (pNode->short_name.GetLength() == short_name.GetLength() &&
+ FXSYS_memcmp32((FX_LPCWSTR)pNode->short_name, (FX_LPCWSTR)short_name, short_name.GetLength()*sizeof(FX_WCHAR)) == 0) {
+ return pNode;
+ }
+ }
+ return NULL;
+}
+void CFieldTree::RemoveAll()
+{
+ CFX_PtrArray& ptr_array = m_Root.children;
+ for (int i = 0; i < ptr_array.GetSize(); i ++) {
+ _Node *pNode = (_Node *)ptr_array[i];
+ RemoveNode(pNode);
+ }
+}
+void CFieldTree::SetField(const CFX_WideString &full_name, CPDF_FormField *field_ptr)
+{
+ if (full_name == L"") {
+ return;
+ }
+ _CFieldNameExtractor name_extractor(full_name);
+ FX_LPCWSTR pName;
+ FX_STRSIZE nLength;
+ name_extractor.GetNext(pName, nLength);
+ _Node *pNode = &m_Root, *pLast = NULL;
+ while (nLength > 0) {
+ pLast = pNode;
+ CFX_WideString name = CFX_WideString(pName, nLength);
+ pNode = _Lookup(pLast, name);
+ if (pNode == NULL) {
+ pNode = AddChild(pLast, name, NULL);
+ }
+ name_extractor.GetNext(pName, nLength);
+ }
+ if (pNode != &m_Root) {
+ pNode->field_ptr = field_ptr;
+ }
+}
+CPDF_FormField *CFieldTree::GetField(const CFX_WideString &full_name)
+{
+ if (full_name == L"") {
+ return NULL;
+ }
+ _CFieldNameExtractor name_extractor(full_name);
+ FX_LPCWSTR pName;
+ FX_STRSIZE nLength;
+ name_extractor.GetNext(pName, nLength);
+ _Node *pNode = &m_Root, *pLast = NULL;
+ while (nLength > 0 && pNode) {
+ pLast = pNode;
+ CFX_WideString name = CFX_WideString(pName, nLength);
+ pNode = _Lookup(pLast, name);
+ name_extractor.GetNext(pName, nLength);
+ }
+ return pNode ? pNode->field_ptr : NULL;
+}
+CPDF_FormField *CFieldTree::RemoveField(const CFX_WideString & full_name)
+{
+ if (full_name == L"") {
+ return NULL;
+ }
+ _CFieldNameExtractor name_extractor(full_name);
+ FX_LPCWSTR pName;
+ FX_STRSIZE nLength;
+ name_extractor.GetNext(pName, nLength);
+ _Node *pNode = &m_Root, *pLast = NULL;
+ while (nLength > 0 && pNode) {
+ pLast = pNode;
+ CFX_WideString name = CFX_WideString(pName, nLength);
+ pNode = _Lookup(pLast, name);
+ name_extractor.GetNext(pName, nLength);
+ }
+ if (pNode && pNode != &m_Root) {
+ CFX_PtrArray& ptr_array = pLast->children;
+ for (int i = 0; i < ptr_array.GetSize(); i ++) {
+ if (pNode == (_Node *)ptr_array[i]) {
+ ptr_array.RemoveAt(i);
+ break;
+ }
+ }
+ CPDF_FormField *pField = pNode->field_ptr;
+ RemoveNode(pNode);
+ return pField;
+ }
+ return NULL;
+}
+CFieldTree::_Node *CFieldTree::FindNode(const CFX_WideString& full_name)
+{
+ if (full_name == L"") {
+ return NULL;
+ }
+ _CFieldNameExtractor name_extractor(full_name);
+ FX_LPCWSTR pName;
+ FX_STRSIZE nLength;
+ name_extractor.GetNext(pName, nLength);
+ _Node *pNode = &m_Root, *pLast = NULL;
+ while (nLength > 0 && pNode) {
+ pLast = pNode;
+ CFX_WideString name = CFX_WideString(pName, nLength);
+ pNode = _Lookup(pLast, name);
+ name_extractor.GetNext(pName, nLength);
+ }
+ return pNode;
+}
+CPDF_InterForm::CPDF_InterForm(CPDF_Document* pDocument, FX_BOOL bGenerateAP) : CFX_PrivateData()
+{
+ m_pDocument = pDocument;
+ m_bGenerateAP = bGenerateAP;
+ m_pFormNotify = NULL;
+ m_bUpdated = FALSE;
+ m_pFieldTree = FX_NEW CFieldTree;
+ CPDF_Dictionary* pRoot = m_pDocument->GetRoot();
+ m_pFormDict = pRoot->GetDict("AcroForm");
+ if (m_pFormDict == NULL) {
+ return;
+ }
+ CPDF_Array* pFields = m_pFormDict->GetArray("Fields");
+ if (pFields == NULL) {
+ return;
+ }
+ int count = pFields->GetCount();
+ for (int i = 0; i < count; i ++) {
+ LoadField(pFields->GetDict(i));
+ }
+}
+CPDF_InterForm::~CPDF_InterForm()
+{
+ FX_POSITION pos = m_ControlMap.GetStartPosition();
+ while (pos) {
+ FX_LPVOID key, value;
+ m_ControlMap.GetNextAssoc(pos, key, value);
+ delete (CPDF_FormControl*)value;
+ }
+ if (m_pFieldTree != NULL) {
+ int nCount = m_pFieldTree->m_Root.CountFields();
+ for (int i = 0; i < nCount; i++) {
+ CPDF_FormField *pField = m_pFieldTree->m_Root.GetField(i);
+ delete pField;
+ }
+ delete m_pFieldTree;
+ }
+}
+FX_BOOL CPDF_InterForm::m_bUpdateAP = TRUE;
+FX_BOOL CPDF_InterForm::UpdatingAPEnabled()
+{
+ return m_bUpdateAP;
+}
+void CPDF_InterForm::EnableUpdateAP(FX_BOOL bUpdateAP)
+{
+ m_bUpdateAP = bUpdateAP;
+}
+CFX_ByteString CPDF_InterForm::GenerateNewResourceName(const CPDF_Dictionary* pResDict, FX_LPCSTR csType, int iMinLen, FX_LPCSTR csPrefix)
+{
+ CFX_ByteString csStr = csPrefix;
+ CFX_ByteString csBType = csType;
+ if (csStr.IsEmpty()) {
+ if (csBType == "ExtGState") {
+ csStr = "GS";
+ } else if (csBType == "ColorSpace") {
+ csStr = "CS";
+ } else if (csBType == "Font") {
+ csStr = "ZiTi";
+ } else {
+ csStr = "Res";
+ }
+ }
+ CFX_ByteString csTmp = csStr;
+ int iCount = csStr.GetLength();
+ int m = 0;
+ if (iMinLen > 0) {
+ csTmp = "";
+ while (m < iMinLen && m < iCount) {
+ csTmp += csStr[m ++];
+ }
+ while (m < iMinLen) {
+ csTmp += '0' + m % 10;
+ m ++;
+ }
+ } else {
+ m = iCount;
+ }
+ if (pResDict == NULL) {
+ return csTmp;
+ }
+ CPDF_Dictionary* pDict = pResDict->GetDict(csType);
+ if (pDict == NULL) {
+ return csTmp;
+ }
+ int num = 0;
+ CFX_ByteString bsNum;
+ while (TRUE) {
+ if (!pDict->KeyExist(csTmp + bsNum)) {
+ return csTmp + bsNum;
+ }
+ if (m < iCount) {
+ csTmp += csStr[m ++];
+ } else {
+ bsNum.Format("%d", num++);
+ }
+ m ++;
+ }
+ return csTmp;
+}
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+typedef struct _PDF_FONTDATA {
+ FX_BOOL bFind;
+ LOGFONTA lf;
+} PDF_FONTDATA, FAR* LPDF_FONTDATA;
+static int CALLBACK EnumFontFamExProc( ENUMLOGFONTEXA *lpelfe,
+ NEWTEXTMETRICEX *lpntme,
+ DWORD FontType,
+ LPARAM lParam
+ )
+{
+ if (FontType != 0x004 || strchr(lpelfe->elfLogFont.lfFaceName, '@') != NULL) {
+ return 1;
+ } else {
+ LPDF_FONTDATA pData = (LPDF_FONTDATA)lParam;
+ memcpy(&pData->lf, &lpelfe->elfLogFont, sizeof(LOGFONTA));
+ pData->bFind = TRUE;
+ return 0;
+ }
+}
+static FX_BOOL RetrieveSpecificFont(LOGFONTA& lf)
+{
+ PDF_FONTDATA fd;
+ memset(&fd, 0, sizeof(PDF_FONTDATA));
+ HDC hDC = ::GetDC(NULL);
+ EnumFontFamiliesExA(hDC, &lf, (FONTENUMPROCA)EnumFontFamExProc, (LPARAM)&fd, 0);
+ ::ReleaseDC(NULL, hDC);
+ if (fd.bFind) {
+ memcpy(&lf, &fd.lf, sizeof(LOGFONTA));
+ }
+ return fd.bFind;
+}
+static FX_BOOL RetrieveSpecificFont(FX_BYTE charSet, FX_BYTE pitchAndFamily, LPCSTR pcsFontName, LOGFONTA& lf)
+{
+ memset(&lf, 0, sizeof(LOGFONTA));
+ lf.lfCharSet = charSet;
+ lf.lfPitchAndFamily = pitchAndFamily;
+ if (pcsFontName != NULL) {
+ strcpy(lf.lfFaceName, pcsFontName);
+ }
+ return RetrieveSpecificFont(lf);
+}
+static FX_BOOL RetrieveStockFont(int iFontObject, FX_BYTE charSet, LOGFONTA& lf)
+{
+ HFONT hFont = (HFONT)::GetStockObject(iFontObject);
+ if (hFont != NULL) {
+ memset(&lf, 0, sizeof(LOGFONTA));
+ int iRet = ::GetObject(hFont, sizeof(LOGFONTA), &lf);
+ if (iRet > 0 && (lf.lfCharSet == charSet || charSet == 255)) {
+ return RetrieveSpecificFont(lf);
+ }
+ }
+ return FALSE;
+}
+#endif
+CPDF_Font* CPDF_InterForm::AddSystemDefaultFont(const CPDF_Document* pDocument)
+{
+ if (pDocument == NULL) {
+ return NULL;
+ }
+ CPDF_Font* pFont = NULL;
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ LOGFONTA lf;
+ FX_BOOL bRet;
+ bRet = RetrieveStockFont(DEFAULT_GUI_FONT, 255, lf);
+ if (!bRet) {
+ bRet = RetrieveStockFont(SYSTEM_FONT, 255, lf);
+ }
+ if (bRet) {
+ pFont = ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
+ }
+#endif
+ return pFont;
+}
+CPDF_Font* CPDF_InterForm::AddSystemFont(const CPDF_Document* pDocument, CFX_ByteString csFontName, FX_BYTE iCharSet)
+{
+ if (pDocument == NULL || csFontName.IsEmpty()) {
+ return NULL;
+ }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ if (iCharSet == 1) {
+ iCharSet = GetNativeCharSet();
+ }
+ HFONT hFont = ::CreateFontA(0, 0, 0, 0, 0, 0, 0, 0, iCharSet, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, (FX_LPCSTR)csFontName);
+ if (hFont != NULL) {
+ LOGFONTA lf;
+ memset(&lf, 0, sizeof(LOGFONTA));
+ ::GetObjectA(hFont, sizeof(LOGFONTA), &lf);
+ ::DeleteObject(hFont);
+ if (strlen(lf.lfFaceName) > 0) {
+ return ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
+ }
+ }
+#endif
+ return NULL;
+}
+CPDF_Font* CPDF_InterForm::AddSystemFont(const CPDF_Document* pDocument, CFX_WideString csFontName, FX_BYTE iCharSet)
+{
+ if (pDocument == NULL || csFontName.IsEmpty()) {
+ return NULL;
+ }
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ if (iCharSet == 1) {
+ iCharSet = GetNativeCharSet();
+ }
+ HFONT hFont = ::CreateFontW(0, 0, 0, 0, 0, 0, 0, 0, iCharSet, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, csFontName);
+ if (hFont != NULL) {
+ LOGFONTA lf;
+ memset(&lf, 0, sizeof(LOGFONTA));
+ ::GetObject(hFont, sizeof(LOGFONTA), &lf);
+ ::DeleteObject(hFont);
+ if (strlen(lf.lfFaceName) > 0) {
+ return ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
+ }
+ }
+#endif
+ return NULL;
+}
+CPDF_Font* CPDF_InterForm::AddStandardFont(const CPDF_Document* pDocument, CFX_ByteString csFontName)
+{
+ if (pDocument == NULL || csFontName.IsEmpty()) {
+ return NULL;
+ }
+ CPDF_Font* pFont = NULL;
+ if (csFontName == "ZapfDingbats") {
+ pFont = ((CPDF_Document*)pDocument)->AddStandardFont(csFontName, NULL);
+ } else {
+ CPDF_FontEncoding encoding(PDFFONT_ENCODING_WINANSI);
+ pFont = ((CPDF_Document*)pDocument)->AddStandardFont(csFontName, &encoding);
+ }
+ return pFont;
+}
+CFX_ByteString CPDF_InterForm::GetNativeFont(FX_BYTE charSet, FX_LPVOID pLogFont)
+{
+ CFX_ByteString csFontName;
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ LOGFONTA lf;
+ FX_BOOL bRet;
+ if (charSet == ANSI_CHARSET) {
+ csFontName = "Helvetica";
+ return csFontName;
+ }
+ bRet = FALSE;
+ if (charSet == SHIFTJIS_CHARSET) {
+ bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MS Mincho", lf);
+ } else if (charSet == GB2312_CHARSET) {
+ bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "SimSun", lf);
+ } else if (charSet == CHINESEBIG5_CHARSET) {
+ bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "MingLiU", lf);
+ }
+ if (!bRet) {
+ bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "Arial Unicode MS", lf);
+ }
+ if (!bRet) {
+ bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, "Microsoft Sans Serif", lf);
+ }
+ if (!bRet) {
+ bRet = RetrieveSpecificFont(charSet, DEFAULT_PITCH | FF_DONTCARE, NULL, lf);
+ }
+ if (bRet) {
+ if (pLogFont != NULL) {
+ memcpy(pLogFont, &lf, sizeof(LOGFONTA));
+ }
+ csFontName = lf.lfFaceName;
+ return csFontName;
+ }
+#endif
+ return csFontName;
+}
+CFX_ByteString CPDF_InterForm::GetNativeFont(FX_LPVOID pLogFont)
+{
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ FX_BYTE charSet = GetNativeCharSet();
+ return GetNativeFont(charSet, pLogFont);
+#else
+ return CFX_ByteString();
+#endif
+}
+FX_BYTE CPDF_InterForm::GetNativeCharSet()
+{
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ FX_BYTE charSet = ANSI_CHARSET;
+ UINT iCodePage = ::GetACP();
+ switch (iCodePage) {
+ case 932:
+ charSet = SHIFTJIS_CHARSET;
+ break;
+ case 936:
+ charSet = GB2312_CHARSET;
+ break;
+ case 950:
+ charSet = CHINESEBIG5_CHARSET;
+ break;
+ case 1252:
+ charSet = ANSI_CHARSET;
+ break;
+ case 874:
+ charSet = THAI_CHARSET;
+ break;
+ case 949:
+ charSet = HANGUL_CHARSET;
+ break;
+ case 1200:
+ charSet = ANSI_CHARSET;
+ break;
+ case 1250:
+ charSet = EASTEUROPE_CHARSET;
+ break;
+ case 1251:
+ charSet = RUSSIAN_CHARSET;
+ break;
+ case 1253:
+ charSet = GREEK_CHARSET;
+ break;
+ case 1254:
+ charSet = TURKISH_CHARSET;
+ break;
+ case 1255:
+ charSet = HEBREW_CHARSET;
+ break;
+ case 1256:
+ charSet = ARABIC_CHARSET;
+ break;
+ case 1257:
+ charSet = BALTIC_CHARSET;
+ break;
+ case 1258:
+ charSet = VIETNAMESE_CHARSET;
+ break;
+ case 1361:
+ charSet = JOHAB_CHARSET;
+ break;
+ }
+ return charSet;
+#else
+ return 0;
+#endif
+}
+CPDF_Font* CPDF_InterForm::AddNativeFont(FX_BYTE charSet, const CPDF_Document* pDocument)
+{
+ if (pDocument == NULL) {
+ return NULL;
+ }
+ CPDF_Font* pFont = NULL;
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
+ LOGFONTA lf;
+ CFX_ByteString csFontName = GetNativeFont(charSet, &lf);
+ if (!csFontName.IsEmpty()) {
+ if (csFontName == "Helvetica") {
+ pFont = AddStandardFont(pDocument, csFontName);
+ } else {
+ pFont = ((CPDF_Document*)pDocument)->AddWindowsFont(&lf, FALSE, TRUE);
+ }
+ }
+#endif
+ return pFont;
+}
+CPDF_Font* CPDF_InterForm::AddNativeFont(const CPDF_Document* pDocument)
+{
+ if (pDocument == NULL) {
+ return NULL;
+ }
+ CPDF_Font* pFont = NULL;
+ FX_BYTE charSet = GetNativeCharSet();
+ pFont = AddNativeFont(charSet, pDocument);
+ return pFont;
+}
+FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName, int iType, const CPDF_FormField* pExcludedField, const CPDF_FormControl* pExcludedControl)
+{
+ if (csNewFieldName.IsEmpty()) {
+ return FALSE;
+ }
+ int iPos = 0;
+ int iLength = csNewFieldName.GetLength();
+ CFX_WideString csSub;
+ while (TRUE) {
+ while (iPos < iLength && (csNewFieldName[iPos] == L'.' || csNewFieldName[iPos] == L' ')) {
+ iPos ++;
+ }
+ if (iPos < iLength && !csSub.IsEmpty()) {
+ csSub += L'.';
+ }
+ while (iPos < iLength && csNewFieldName[iPos] != L'.') {
+ csSub += csNewFieldName[iPos ++];
+ }
+ for (int i = csSub.GetLength() - 1; i > -1; i --) {
+ if (csSub[i] == L' ' || csSub[i] == L'.') {
+ csSub.SetAt(i, L'\0');
+ } else {
+ break;
+ }
+ }
+ FX_DWORD dwCount = m_pFieldTree->m_Root.CountFields();
+ for (FX_DWORD m = 0; m < dwCount; m ++) {
+ CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(m);
+ if (pField == NULL) {
+ continue;
+ }
+ if (pField == pExcludedField) {
+ if (pExcludedControl != NULL) {
+ if (pField->CountControls() < 2) {
+ continue;
+ }
+ } else {
+ continue;
+ }
+ }
+ CFX_WideString csFullName = pField->GetFullName();
+ int iRet = CompareFieldName(csSub, csFullName);
+ if (iRet == 1) {
+ if (pField->GetFieldType() != iType) {
+ return FALSE;
+ }
+ } else if (iRet == 2 && csSub == csNewFieldName) {
+ if (csFullName[iPos] == L'.') {
+ return FALSE;
+ }
+ } else if (iRet == 3 && csSub == csNewFieldName) {
+ if (csNewFieldName[csFullName.GetLength()] == L'.') {
+ return FALSE;
+ }
+ }
+ }
+ if (iPos >= iLength) {
+ break;
+ }
+ }
+ if (csSub.IsEmpty()) {
+ return FALSE;
+ }
+ csNewFieldName = csSub;
+ return TRUE;
+}
+FX_BOOL CPDF_InterForm::ValidateFieldName(CFX_WideString& csNewFieldName, int iType)
+{
+ return ValidateFieldName(csNewFieldName, iType, NULL, NULL);
+}
+FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormField* pField, CFX_WideString& csNewFieldName)
+{
+ if (pField == NULL || csNewFieldName.IsEmpty()) {
+ return FALSE;
+ }
+ return ValidateFieldName(csNewFieldName, ((CPDF_FormField*)pField)->GetFieldType(), pField, NULL);
+}
+FX_BOOL CPDF_InterForm::ValidateFieldName(const CPDF_FormControl* pControl, CFX_WideString& csNewFieldName)
+{
+ if (pControl == NULL || csNewFieldName.IsEmpty()) {
+ return FALSE;
+ }
+ CPDF_FormField* pField = ((CPDF_FormControl*)pControl)->GetField();
+ return ValidateFieldName(csNewFieldName, pField->GetFieldType(), pField, pControl);
+}
+int CPDF_InterForm::CompareFieldName(const CFX_ByteString& name1, const CFX_ByteString& name2)
+{
+ FX_LPCSTR ptr1 = name1, ptr2 = name2;
+ if (name1.GetLength() != name2.GetLength()) {
+ int i = 0;
+ while (ptr1[i] == ptr2[i]) {
+ i ++;
+ }
+ if (i == name1.GetLength()) {
+ return 2;
+ }
+ if (i == name2.GetLength()) {
+ return 3;
+ }
+ return 0;
+ } else {
+ return name1 == name2 ? 1 : 0;
+ }
+}
+int CPDF_InterForm::CompareFieldName(const CFX_WideString& name1, const CFX_WideString& name2)
+{
+ FX_LPCWSTR ptr1 = name1, ptr2 = name2;
+ if (name1.GetLength() != name2.GetLength()) {
+ int i = 0;
+ while (ptr1[i] == ptr2[i]) {
+ i ++;
+ }
+ if (i == name1.GetLength()) {
+ return 2;
+ }
+ if (i == name2.GetLength()) {
+ return 3;
+ }
+ return 0;
+ } else {
+ return name1 == name2 ? 1 : 0;
+ }
+}
+FX_DWORD CPDF_InterForm::CountFields(const CFX_WideString &csFieldName)
+{
+ if (csFieldName.IsEmpty()) {
+ return (FX_DWORD)m_pFieldTree->m_Root.CountFields();
+ }
+ CFieldTree::_Node *pNode = m_pFieldTree->FindNode(csFieldName);
+ if (pNode == NULL) {
+ return 0;
+ }
+ return pNode->CountFields();
+}
+CPDF_FormField* CPDF_InterForm::GetField(FX_DWORD index, const CFX_WideString &csFieldName)
+{
+ if (csFieldName == L"") {
+ return m_pFieldTree->m_Root.GetField(index);
+ }
+ CFieldTree::_Node *pNode = m_pFieldTree->FindNode(csFieldName);
+ if (pNode == NULL) {
+ return NULL;
+ }
+ return pNode->GetField(index);
+}
+void CPDF_InterForm::GetAllFieldNames(CFX_WideStringArray& allFieldNames)
+{
+ allFieldNames.RemoveAll();
+ int nCount = m_pFieldTree->m_Root.CountFields();
+ for (int i = 0; i < nCount; i ++) {
+ CPDF_FormField *pField = m_pFieldTree->m_Root.GetField(i);
+ if (pField) {
+ CFX_WideString full_name = GetFullName(pField->GetFieldDict());
+ allFieldNames.Add(full_name);
+ }
+ }
+}
+FX_BOOL CPDF_InterForm::IsValidFormField(const void* pField)
+{
+ if (pField == NULL) {
+ return FALSE;
+ }
+ int nCount = m_pFieldTree->m_Root.CountFields();
+ for (int i = 0; i < nCount; i++) {
+ CPDF_FormField *pFormField = m_pFieldTree->m_Root.GetField(i);
+ if (pField == pFormField) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+CPDF_FormField* CPDF_InterForm::GetFieldByDict(CPDF_Dictionary* pFieldDict) const
+{
+ if (pFieldDict == NULL) {
+ return NULL;
+ }
+ CFX_WideString csWName = GetFullName(pFieldDict);
+ return m_pFieldTree->GetField(csWName);
+}
+FX_DWORD CPDF_InterForm::CountControls(CFX_WideString csFieldName)
+{
+ if (csFieldName.IsEmpty()) {
+ return (FX_DWORD)m_ControlMap.GetCount();
+ }
+ CPDF_FormField *pField = m_pFieldTree->GetField(csFieldName);
+ if (pField == NULL) {
+ return 0;
+ }
+ return pField->m_ControlList.GetSize();
+}
+CPDF_FormControl* CPDF_InterForm::GetControl(FX_DWORD index, CFX_WideString csFieldName)
+{
+ CPDF_FormField *pField = m_pFieldTree->GetField(csFieldName);
+ if (pField == NULL) {
+ return NULL;
+ }
+ if (index < (FX_DWORD)pField->m_ControlList.GetSize()) {
+ return (CPDF_FormControl *)pField->m_ControlList.GetAt(index);
+ }
+ return NULL;
+}
+FX_BOOL CPDF_InterForm::IsValidFormControl(const void* pControl)
+{
+ if (pControl == NULL) {
+ return FALSE;
+ }
+ FX_POSITION pos = m_ControlMap.GetStartPosition();
+ while (pos) {
+ CPDF_Dictionary* pWidgetDict = NULL;
+ void* pFormControl = NULL;
+ m_ControlMap.GetNextAssoc(pos, (FX_LPVOID&)pWidgetDict, pFormControl);
+ if (pControl == pFormControl) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+int CPDF_InterForm::CountPageControls(CPDF_Page* pPage) const
+{
+ CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
+ if (pAnnotList == NULL) {
+ return 0;
+ }
+ int count = 0;
+ for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i ++) {
+ CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i);
+ if (pAnnot == NULL) {
+ continue;
+ }
+ CPDF_FormControl* pControl;
+ if (!m_ControlMap.Lookup(pAnnot, (FX_LPVOID&)pControl)) {
+ continue;
+ }
+ count ++;
+ }
+ return count;
+}
+CPDF_FormControl* CPDF_InterForm::GetPageControl(CPDF_Page* pPage, int index) const
+{
+ CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
+ if (pAnnotList == NULL) {
+ return NULL;
+ }
+ int count = 0;
+ for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i ++) {
+ CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i);
+ if (pAnnot == NULL) {
+ continue;
+ }
+ CPDF_FormControl* pControl;
+ if (!m_ControlMap.Lookup(pAnnot, (FX_LPVOID&)pControl)) {
+ continue;
+ }
+ if (index == count) {
+ return pControl;
+ }
+ count ++;
+ }
+ return NULL;
+}
+CPDF_FormControl* CPDF_InterForm::GetControlAtPoint(CPDF_Page* pPage, FX_FLOAT pdf_x, FX_FLOAT pdf_y) const
+{
+ CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
+ if (pAnnotList == NULL) {
+ return NULL;
+ }
+ for (FX_DWORD i = pAnnotList->GetCount(); i > 0; i --) {
+ CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i - 1);
+ if (pAnnot == NULL) {
+ continue;
+ }
+ CPDF_FormControl* pControl;
+ if (!m_ControlMap.Lookup(pAnnot, (FX_LPVOID&)pControl)) {
+ continue;
+ }
+ CFX_FloatRect rect = pControl->GetRect();
+ if (rect.Contains(pdf_x, pdf_y)) {
+ return pControl;
+ }
+ }
+ return NULL;
+}
+CPDF_FormControl* CPDF_InterForm::GetControlByDict(CPDF_Dictionary* pWidgetDict) const
+{
+ CPDF_FormControl* pControl = NULL;
+ m_ControlMap.Lookup(pWidgetDict, (FX_LPVOID&)pControl);
+ return pControl;
+}
+FX_DWORD CPDF_InterForm::CountInternalFields(const CFX_WideString& csFieldName) const
+{
+ if (m_pFormDict == NULL) {
+ return 0;
+ }
+ CPDF_Array* pArray = m_pFormDict->GetArray("Fields");
+ if (pArray == NULL) {
+ return 0;
+ }
+ if (csFieldName.IsEmpty()) {
+ return pArray->GetCount();
+ } else {
+ int iLength = csFieldName.GetLength();
+ int iPos = 0;
+ CPDF_Dictionary* pDict = NULL;
+ while (pArray != NULL) {
+ CFX_WideString csSub;
+ if (iPos < iLength && csFieldName[iPos] == L'.') {
+ iPos ++;
+ }
+ while (iPos < iLength && csFieldName[iPos] != L'.') {
+ csSub += csFieldName[iPos ++];
+ }
+ int iCount = pArray->GetCount();
+ FX_BOOL bFind = FALSE;
+ for (int i = 0; i < iCount; i ++) {
+ pDict = pArray->GetDict(i);
+ if (pDict == NULL) {
+ continue;
+ }
+ CFX_WideString csT = pDict->GetUnicodeText("T");
+ if (csT == csSub) {
+ bFind = TRUE;
+ break;
+ }
+ }
+ if (!bFind) {
+ return 0;
+ }
+ if (iPos >= iLength) {
+ break;
+ }
+ pArray = pDict->GetArray("Kids");
+ }
+ if (pDict == NULL) {
+ return 0;
+ } else {
+ pArray = pDict->GetArray("Kids");
+ if (pArray == NULL) {
+ return 1;
+ } else {
+ return pArray->GetCount();
+ }
+ }
+ }
+}
+CPDF_Dictionary* CPDF_InterForm::GetInternalField(FX_DWORD index, const CFX_WideString& csFieldName) const
+{
+ if (m_pFormDict == NULL) {
+ return NULL;
+ }
+ CPDF_Array* pArray = m_pFormDict->GetArray("Fields");
+ if (pArray == NULL) {
+ return 0;
+ }
+ if (csFieldName.IsEmpty()) {
+ return pArray->GetDict(index);
+ } else {
+ int iLength = csFieldName.GetLength();
+ int iPos = 0;
+ CPDF_Dictionary* pDict = NULL;
+ while (pArray != NULL) {
+ CFX_WideString csSub;
+ if (iPos < iLength && csFieldName[iPos] == L'.') {
+ iPos ++;
+ }
+ while (iPos < iLength && csFieldName[iPos] != L'.') {
+ csSub += csFieldName[iPos ++];
+ }
+ int iCount = pArray->GetCount();
+ FX_BOOL bFind = FALSE;
+ for (int i = 0; i < iCount; i ++) {
+ pDict = pArray->GetDict(i);
+ if (pDict == NULL) {
+ continue;
+ }
+ CFX_WideString csT = pDict->GetUnicodeText("T");
+ if (csT == csSub) {
+ bFind = TRUE;
+ break;
+ }
+ }
+ if (!bFind) {
+ return NULL;
+ }
+ if (iPos >= iLength) {
+ break;
+ }
+ pArray = pDict->GetArray("Kids");
+ }
+ if (pDict == NULL) {
+ return NULL;
+ } else {
+ pArray = pDict->GetArray("Kids");
+ if (pArray == NULL) {
+ return pDict;
+ } else {
+ return pArray->GetDict(index);
+ }
+ }
+ }
+}
+FX_BOOL CPDF_InterForm::NeedConstructAP()
+{
+ if (m_pFormDict == NULL) {
+ return FALSE;
+ }
+ return m_pFormDict->GetBoolean("NeedAppearances");
+}
+void CPDF_InterForm::NeedConstructAP(FX_BOOL bNeedAP)
+{
+ if (m_pFormDict == NULL) {
+ InitInterFormDict(m_pFormDict, m_pDocument);
+ }
+ m_pFormDict->SetAtBoolean("NeedAppearances", bNeedAP);
+ m_bGenerateAP = bNeedAP;
+}
+int CPDF_InterForm::CountFieldsInCalculationOrder()
+{
+ if (m_pFormDict == NULL) {
+ return 0;
+ }
+ CPDF_Array* pArray = m_pFormDict->GetArray("CO");
+ if (pArray == NULL) {
+ return 0;
+ }
+ return pArray->GetCount();
+}
+CPDF_FormField* CPDF_InterForm::GetFieldInCalculationOrder(int index)
+{
+ if (m_pFormDict == NULL || index < 0) {
+ return NULL;
+ }
+ CPDF_Array* pArray = m_pFormDict->GetArray("CO");
+ if (pArray == NULL) {
+ return NULL;
+ }
+ CPDF_Object* pElement = pArray->GetElementValue(index);
+ if (pElement != NULL && pElement->GetType() == PDFOBJ_DICTIONARY) {
+ return GetFieldByDict((CPDF_Dictionary*)pElement);
+ }
+ return NULL;
+}
+int CPDF_InterForm::FindFieldInCalculationOrder(const CPDF_FormField* pField)
+{
+ if (m_pFormDict == NULL || pField == NULL) {
+ return -1;
+ }
+ CPDF_Array* pArray = m_pFormDict->GetArray("CO");
+ if (pArray == NULL) {
+ return -1;
+ }
+ for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
+ CPDF_Object* pElement = pArray->GetElementValue(i);
+ if (pElement == pField->m_pDict) {
+ return i;
+ }
+ }
+ return -1;
+}
+FX_DWORD CPDF_InterForm::CountFormFonts()
+{
+ return CountInterFormFonts(m_pFormDict);
+}
+CPDF_Font* CPDF_InterForm::GetFormFont(FX_DWORD index, CFX_ByteString& csNameTag)
+{
+ return GetInterFormFont(m_pFormDict, m_pDocument, index, csNameTag);
+}
+CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csNameTag)
+{
+ return GetInterFormFont(m_pFormDict, m_pDocument, csNameTag);
+}
+CPDF_Font* CPDF_InterForm::GetFormFont(CFX_ByteString csFontName, CFX_ByteString& csNameTag)
+{
+ return GetInterFormFont(m_pFormDict, m_pDocument, csFontName, csNameTag);
+}
+CPDF_Font* CPDF_InterForm::GetNativeFormFont(FX_BYTE charSet, CFX_ByteString& csNameTag)
+{
+ return GetNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
+}
+CPDF_Font* CPDF_InterForm::GetNativeFormFont(CFX_ByteString& csNameTag)
+{
+ return GetNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
+}
+FX_BOOL CPDF_InterForm::FindFormFont(const CPDF_Font* pFont, CFX_ByteString& csNameTag)
+{
+ return FindInterFormFont(m_pFormDict, pFont, csNameTag);
+}
+FX_BOOL CPDF_InterForm::FindFormFont(CFX_ByteString csFontName, CPDF_Font*& pFont, CFX_ByteString& csNameTag)
+{
+ return FindInterFormFont(m_pFormDict, m_pDocument, csFontName, pFont, csNameTag);
+}
+void CPDF_InterForm::AddFormFont(const CPDF_Font* pFont, CFX_ByteString& csNameTag)
+{
+ AddInterFormFont(m_pFormDict, m_pDocument, pFont, csNameTag);
+ m_bUpdated = TRUE;
+}
+CPDF_Font* CPDF_InterForm::AddNativeFormFont(FX_BYTE charSet, CFX_ByteString& csNameTag)
+{
+ m_bUpdated = TRUE;
+ return AddNativeInterFormFont(m_pFormDict, m_pDocument, charSet, csNameTag);
+}
+CPDF_Font* CPDF_InterForm::AddNativeFormFont(CFX_ByteString& csNameTag)
+{
+ m_bUpdated = TRUE;
+ return AddNativeInterFormFont(m_pFormDict, m_pDocument, csNameTag);
+}
+void CPDF_InterForm::RemoveFormFont(const CPDF_Font* pFont)
+{
+ m_bUpdated = TRUE;
+ RemoveInterFormFont(m_pFormDict, pFont);
+}
+void CPDF_InterForm::RemoveFormFont(CFX_ByteString csNameTag)
+{
+ m_bUpdated = TRUE;
+ RemoveInterFormFont(m_pFormDict, csNameTag);
+}
+CPDF_DefaultAppearance CPDF_InterForm::GetDefaultAppearance()
+{
+ CFX_ByteString csDA;
+ if (m_pFormDict == NULL) {
+ return csDA;
+ }
+ csDA = m_pFormDict->GetString("DA");
+ return csDA;
+}
+CPDF_Font* CPDF_InterForm::GetDefaultFormFont()
+{
+ return GetDefaultInterFormFont(m_pFormDict, m_pDocument);
+}
+int CPDF_InterForm::GetFormAlignment()
+{
+ if (m_pFormDict == NULL) {
+ return 0;
+ }
+ return m_pFormDict->GetInteger("Q", 0);
+}
+FX_BOOL CPDF_InterForm::ResetForm(const CFX_PtrArray& fields, FX_BOOL bIncludeOrExclude, FX_BOOL bNotify)
+{
+ if (bNotify && m_pFormNotify != NULL) {
+ int iRet = m_pFormNotify->BeforeFormReset(this);
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ int nCount = m_pFieldTree->m_Root.CountFields();
+ for (int i = 0; i < nCount; i++) {
+ CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
+ if (pField == NULL) {
+ continue;
+ }
+ FX_BOOL bFind = FALSE;
+ int iCount = fields.GetSize();
+ for (int i = 0; i < iCount; i ++) {
+ if (pField == (CPDF_FormField*)fields[i]) {
+ bFind = TRUE;
+ break;
+ }
+ }
+ if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
+ pField->ResetField(bNotify);
+ }
+ }
+ if (bNotify && m_pFormNotify != NULL) {
+ m_pFormNotify->AfterFormReset(this);
+ }
+ return TRUE;
+}
+FX_BOOL CPDF_InterForm::ResetForm(FX_BOOL bNotify)
+{
+ if (bNotify && m_pFormNotify != NULL) {
+ int iRet = m_pFormNotify->BeforeFormReset(this);
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ int nCount = m_pFieldTree->m_Root.CountFields();
+ for (int i = 0; i < nCount; i++) {
+ CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
+ if (pField == NULL) {
+ continue;
+ }
+ pField->ResetField(bNotify);
+ }
+ if (bNotify && m_pFormNotify != NULL) {
+ m_pFormNotify->AfterFormReset(this);
+ }
+ return TRUE;
+}
+void CPDF_InterForm::ReloadForm()
+{
+ FX_POSITION pos = m_ControlMap.GetStartPosition();
+ while (pos) {
+ CPDF_Dictionary* pWidgetDict;
+ CPDF_FormControl* pControl;
+ m_ControlMap.GetNextAssoc(pos, (FX_LPVOID&)pWidgetDict, (FX_LPVOID&)pControl);
+ delete pControl;
+ }
+ m_ControlMap.RemoveAll();
+ int nCount = m_pFieldTree->m_Root.CountFields();
+ for (int k = 0; k < nCount; k ++) {
+ CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(k);
+ delete pField;
+ }
+ m_pFieldTree->RemoveAll();
+ if (m_pFormDict == NULL) {
+ return;
+ }
+ CPDF_Array* pFields = m_pFormDict->GetArray("Fields");
+ if (pFields == NULL) {
+ return;
+ }
+ int iCount = pFields->GetCount();
+ for (int i = 0; i < iCount; i ++) {
+ LoadField(pFields->GetDict(i));
+ }
+}
+void CPDF_InterForm::LoadField(CPDF_Dictionary* pFieldDict, int nLevel)
+{
+ if (nLevel > nMaxRecursion) {
+ return;
+ }
+ if (pFieldDict == NULL) {
+ return;
+ }
+ FX_DWORD dwParentObjNum = pFieldDict->GetObjNum();
+ CPDF_Array* pKids = pFieldDict->GetArray("Kids");
+ if (!pKids) {
+ AddTerminalField(pFieldDict);
+ return;
+ }
+ CPDF_Dictionary* pFirstKid = pKids->GetDict(0);
+ if (pFirstKid == NULL) {
+ return;
+ }
+ if (pFirstKid->KeyExist("T") || pFirstKid->KeyExist("Kids")) {
+ for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
+ CPDF_Dictionary * pChildDict = pKids->GetDict(i);
+ if (pChildDict) {
+ if (pChildDict->GetObjNum() != dwParentObjNum) {
+ LoadField(pChildDict, nLevel + 1);
+ }
+ }
+ }
+ } else {
+ AddTerminalField(pFieldDict);
+ }
+}
+FX_BOOL CPDF_InterForm::HasXFAForm() const
+{
+ return m_pFormDict && m_pFormDict->GetArray(FX_BSTRC("XFA")) != NULL;
+}
+void CPDF_InterForm::FixPageFields(const CPDF_Page* pPage)
+{
+ ASSERT(pPage != NULL);
+ CPDF_Dictionary* pPageDict = pPage->m_pFormDict;
+ if (pPageDict == NULL) {
+ return;
+ }
+ CPDF_Array* pAnnots = pPageDict->GetArray(FX_BSTRC("Annots"));
+ if (pAnnots == NULL) {
+ return;
+ }
+ int iAnnotCount = pAnnots->GetCount();
+ for (int i = 0; i < iAnnotCount; i++) {
+ CPDF_Dictionary* pAnnot = pAnnots->GetDict(i);
+ if (pAnnot != NULL && pAnnot->GetString(FX_BSTRC("Subtype")) == "Widget") {
+ LoadField(pAnnot);
+ }
+ }
+}
+CPDF_FormField* CPDF_InterForm::AddTerminalField(const CPDF_Dictionary* pFieldDict)
+{
+ if (!pFieldDict->KeyExist(FX_BSTRC("T"))) {
+ return NULL;
+ }
+ CPDF_Dictionary* pDict = (CPDF_Dictionary*)pFieldDict;
+ CFX_WideString csWName = GetFullName(pDict);
+ if (csWName.IsEmpty()) {
+ return NULL;
+ }
+ CPDF_FormField* pField = NULL;
+ pField = m_pFieldTree->GetField(csWName);
+ if (pField == NULL) {
+ CPDF_Dictionary *pParent = (CPDF_Dictionary*)pFieldDict;
+ if (!pFieldDict->KeyExist(FX_BSTR("T")) &&
+ pFieldDict->GetString(FX_BSTRC("Subtype")) == FX_BSTRC("Widget")) {
+ pParent = pFieldDict->GetDict(FX_BSTRC("Parent"));
+ if (!pParent) {
+ pParent = (CPDF_Dictionary*)pFieldDict;
+ }
+ }
+ if (pParent && pParent != pFieldDict && !pParent->KeyExist(FX_BSTRC("FT"))) {
+ if (pFieldDict->KeyExist(FX_BSTRC("FT"))) {
+ CPDF_Object *pFTValue = pFieldDict->GetElementValue(FX_BSTRC("FT"));
+ if (pFTValue) {
+ pParent->SetAt(FX_BSTRC("FT"), pFTValue->Clone());
+ }
+ }
+ if (pFieldDict->KeyExist(FX_BSTRC("Ff"))) {
+ CPDF_Object *pFfValue = pFieldDict->GetElementValue(FX_BSTRC("Ff"));
+ if (pFfValue) {
+ pParent->SetAt(FX_BSTRC("Ff"), pFfValue->Clone());
+ }
+ }
+ }
+ pField = FX_NEW CPDF_FormField(this, pParent);
+ CPDF_Object* pTObj = pDict->GetElement("T");
+ if (pTObj && pTObj->GetType() == PDFOBJ_REFERENCE) {
+ CPDF_Object* pClone = pTObj->Clone(TRUE);
+ if (pClone) {
+ pDict->SetAt("T", pClone);
+ } else {
+ pDict->SetAtName("T", "");
+ }
+ }
+ m_pFieldTree->SetField(csWName, pField);
+ }
+ CPDF_Array* pKids = pFieldDict->GetArray("Kids");
+ if (pKids == NULL) {
+ if (pFieldDict->GetString("Subtype") == "Widget") {
+ AddControl(pField, pFieldDict);
+ }
+ } else {
+ for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
+ CPDF_Dictionary* pKid = pKids->GetDict(i);
+ if (pKid == NULL) {
+ continue;
+ }
+ if (pKid->GetString("Subtype") != "Widget") {
+ continue;
+ }
+ AddControl(pField, pKid);
+ }
+ }
+ return pField;
+}
+CPDF_FormControl* CPDF_InterForm::AddControl(const CPDF_FormField* pField, const CPDF_Dictionary* pWidgetDict)
+{
+ void *rValue = NULL;
+ if (m_ControlMap.Lookup((CPDF_Dictionary*)pWidgetDict, rValue)) {
+ return (CPDF_FormControl*)rValue;
+ }
+ CPDF_FormControl* pControl = FX_NEW CPDF_FormControl((CPDF_FormField*)pField, (CPDF_Dictionary*)pWidgetDict);
+ if (pControl == NULL) {
+ return NULL;
+ }
+ m_ControlMap.SetAt((CPDF_Dictionary*)pWidgetDict, pControl);
+ ((CPDF_FormField*)pField)->m_ControlList.Add(pControl);
+ return pControl;
+}
+CPDF_FormField* CPDF_InterForm::CheckRequiredFields(const CFX_PtrArray *fields, FX_BOOL bIncludeOrExclude) const
+{
+ int nCount = m_pFieldTree->m_Root.CountFields();
+ for (int i = 0; i < nCount; i++) {
+ CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
+ if (pField == NULL) {
+ continue;
+ }
+ FX_INT32 iType = pField->GetType();
+ if (iType == CPDF_FormField::PushButton || iType == CPDF_FormField::CheckBox || iType == CPDF_FormField::ListBox) {
+ continue;
+ }
+ FX_DWORD dwFlags = pField->GetFieldFlags();
+ if (dwFlags & 0x04) {
+ continue;
+ }
+ FX_BOOL bFind = TRUE;
+ if (fields != NULL) {
+ bFind = fields->Find(pField, 0) >= 0;
+ }
+ if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
+ CPDF_Dictionary *pFieldDict = pField->m_pDict;
+ if ((dwFlags & 0x02) != 0 && pFieldDict->GetString("V").IsEmpty()) {
+ return pField;
+ }
+ }
+ }
+ return NULL;
+}
+CFDF_Document* CPDF_InterForm::ExportToFDF(FX_WSTR pdf_path, FX_BOOL bSimpleFileSpec) const
+{
+ CFX_PtrArray fields;
+ int nCount = m_pFieldTree->m_Root.CountFields();
+ for (int i = 0; i < nCount; i ++) {
+ CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
+ fields.Add(pField);
+ }
+ return ExportToFDF(pdf_path, fields, TRUE, bSimpleFileSpec);
+}
+CFX_WideString FILESPEC_EncodeFileName(FX_WSTR filepath);
+CFDF_Document* CPDF_InterForm::ExportToFDF(FX_WSTR pdf_path, CFX_PtrArray& fields, FX_BOOL bIncludeOrExclude, FX_BOOL bSimpleFileSpec) const
+{
+ CFDF_Document* pDoc = CFDF_Document::CreateNewDoc();
+ if (pDoc == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pMainDict = pDoc->GetRoot()->GetDict("FDF");
+ if (!pdf_path.IsEmpty()) {
+ if (bSimpleFileSpec) {
+ CFX_WideString wsFilePath = FILESPEC_EncodeFileName(pdf_path);
+ pMainDict->SetAtString(FX_BSTRC("F"), CFX_ByteString::FromUnicode(wsFilePath));
+ pMainDict->SetAtString(FX_BSTRC("UF"), PDF_EncodeText(wsFilePath));
+ } else {
+ CPDF_FileSpec filespec;
+ filespec.SetFileName(pdf_path);
+ pMainDict->SetAt("F", (CPDF_Object*)filespec);
+ }
+ }
+ CPDF_Array* pFields = CPDF_Array::Create();
+ if (pFields == NULL) {
+ return NULL;
+ }
+ pMainDict->SetAt("Fields", pFields);
+ int nCount = m_pFieldTree->m_Root.CountFields();
+ for (int i = 0; i < nCount; i ++) {
+ CPDF_FormField* pField = m_pFieldTree->m_Root.GetField(i);
+ if (pField == NULL || pField->GetType() == CPDF_FormField::PushButton) {
+ continue;
+ }
+ FX_DWORD dwFlags = pField->GetFieldFlags();
+ if (dwFlags & 0x04) {
+ continue;
+ }
+ FX_BOOL bFind = fields.Find(pField, 0) >= 0;
+ if ((bIncludeOrExclude && bFind) || (!bIncludeOrExclude && !bFind)) {
+ if ((dwFlags & 0x02) != 0 && pField->m_pDict->GetString("V").IsEmpty()) {
+ continue;
+ }
+ CFX_WideString fullname = GetFullName(pField->GetFieldDict());
+ CPDF_Dictionary* pFieldDict = CPDF_Dictionary::Create();
+ if (pFieldDict == NULL) {
+ return NULL;
+ }
+ CPDF_String* pString = CPDF_String::Create(fullname);
+ if (pString == NULL) {
+ pFieldDict->Release();
+ return NULL;
+ }
+ pFieldDict->SetAt("T", pString);
+ if (pField->GetType() == CPDF_FormField::CheckBox || pField->GetType() == CPDF_FormField::RadioButton) {
+ CFX_WideString csExport = pField->GetCheckValue(FALSE);
+ CFX_ByteString csBExport = PDF_EncodeText(csExport);
+ CPDF_Object* pOpt = FPDF_GetFieldAttr(pField->m_pDict, "Opt");
+ if (pOpt == NULL) {
+ pFieldDict->SetAtName("V", csBExport);
+ } else {
+ pFieldDict->SetAtString("V", csBExport);
+ }
+ } else {
+ CPDF_Object* pV = FPDF_GetFieldAttr(pField->m_pDict, "V");
+ if (pV != NULL) {
+ pFieldDict->SetAt("V", pV->Clone(TRUE));
+ }
+ }
+ pFields->Add(pFieldDict);
+ }
+ }
+ return pDoc;
+}
+const struct _SupportFieldEncoding {
+ FX_LPCSTR m_name;
+ FX_INT32 m_codePage;
+} g_fieldEncoding[] = {
+ "BigFive", 950,
+ "GBK", 936,
+ "Shift-JIS", 932,
+ "UHC", 949,
+};
+static void FPDFDOC_FDF_GetFieldValue(CPDF_Dictionary *pFieldDict, CFX_WideString &csValue, CFX_ByteString &bsEncoding)
+{
+ ASSERT(pFieldDict != NULL);
+ CFX_ByteString csBValue = pFieldDict->GetString("V");
+ FX_INT32 iCount = sizeof(g_fieldEncoding) / sizeof(g_fieldEncoding[0]);
+ FX_INT32 i = 0;
+ for (; i < iCount; ++i)
+ if (bsEncoding == g_fieldEncoding[i].m_name) {
+ break;
+ }
+ if (i < iCount) {
+ CFX_CharMap *pCharMap = CFX_CharMap::GetDefaultMapper(g_fieldEncoding[i].m_codePage);
+ FXSYS_assert(pCharMap != NULL);
+ csValue.ConvertFrom(csBValue, pCharMap);
+ return;
+ }
+ CFX_ByteString csTemp = csBValue.Left(2);
+ if (csTemp == "\xFF\xFE" || csTemp == "\xFE\xFF") {
+ csValue = PDF_DecodeText(csBValue);
+ } else {
+ csValue = CFX_WideString::FromLocal(csBValue);
+ }
+}
+void CPDF_InterForm::FDF_ImportField(CPDF_Dictionary* pFieldDict, const CFX_WideString& parent_name, FX_BOOL bNotify, int nLevel)
+{
+ CFX_WideString name;
+ if (!parent_name.IsEmpty()) {
+ name = parent_name + L".";
+ }
+ name += pFieldDict->GetUnicodeText("T");
+ CPDF_Array* pKids = pFieldDict->GetArray("Kids");
+ if (pKids) {
+ for (FX_DWORD i = 0; i < pKids->GetCount(); i ++) {
+ CPDF_Dictionary* pKid = pKids->GetDict(i);
+ if (pKid == NULL) {
+ continue;
+ }
+ if (nLevel <= nMaxRecursion) {
+ FDF_ImportField(pKid, name, bNotify, nLevel + 1);
+ }
+ }
+ return;
+ }
+ if (!pFieldDict->KeyExist("V")) {
+ return;
+ }
+ CPDF_FormField* pField = m_pFieldTree->GetField(name);
+ if (pField == NULL) {
+ return;
+ }
+ CFX_WideString csWValue;
+ FPDFDOC_FDF_GetFieldValue(pFieldDict, csWValue, m_bsEncoding);
+ int iType = pField->GetFieldType();
+ if (bNotify && m_pFormNotify != NULL) {
+ int iRet = 0;
+ if (iType == FIELDTYPE_LISTBOX) {
+ iRet = m_pFormNotify->BeforeSelectionChange(pField, csWValue);
+ } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) {
+ iRet = m_pFormNotify->BeforeValueChange(pField, csWValue);
+ }
+ if (iRet < 0) {
+ return;
+ }
+ }
+ CFX_ByteArray statusArray;
+ if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) {
+ SaveCheckedFieldStatus(pField, statusArray);
+ }
+ pField->SetValue(csWValue);
+ CPDF_FormField::Type eType = pField->GetType();
+ if ((eType == CPDF_FormField::ListBox || eType == CPDF_FormField::ComboBox) && pFieldDict->KeyExist("Opt")) {
+ pField->m_pDict->SetAt("Opt", pFieldDict->GetElementValue("Opt")->Clone(TRUE));
+ }
+ if (bNotify && m_pFormNotify != NULL) {
+ if (iType == FIELDTYPE_CHECKBOX || iType == FIELDTYPE_RADIOBUTTON) {
+ m_pFormNotify->AfterCheckedStatusChange(pField, statusArray);
+ } else if (iType == FIELDTYPE_LISTBOX) {
+ m_pFormNotify->AfterSelectionChange(pField);
+ } else if (iType == FIELDTYPE_COMBOBOX || iType == FIELDTYPE_TEXTFIELD) {
+ m_pFormNotify->AfterValueChange(pField);
+ }
+ }
+ if (CPDF_InterForm::m_bUpdateAP) {
+ pField->UpdateAP(NULL);
+ }
+}
+FX_BOOL CPDF_InterForm::ImportFromFDF(const CFDF_Document* pFDF, FX_BOOL bNotify)
+{
+ if (pFDF == NULL) {
+ return FALSE;
+ }
+ CPDF_Dictionary* pMainDict = pFDF->GetRoot()->GetDict("FDF");
+ if (pMainDict == NULL) {
+ return FALSE;
+ }
+ CPDF_Array* pFields = pMainDict->GetArray("Fields");
+ if (pFields == NULL) {
+ return FALSE;
+ }
+ m_bsEncoding = pMainDict->GetString(FX_BSTRC("Encoding"));
+ if (bNotify && m_pFormNotify != NULL) {
+ int iRet = m_pFormNotify->BeforeFormImportData(this);
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ for (FX_DWORD i = 0; i < pFields->GetCount(); i ++) {
+ CPDF_Dictionary* pField = pFields->GetDict(i);
+ if (pField == NULL) {
+ continue;
+ }
+ FDF_ImportField(pField, L"", bNotify);
+ }
+ if (bNotify && m_pFormNotify != NULL) {
+ m_pFormNotify->AfterFormImportData(this);
+ }
+ return TRUE;
+}
+void CPDF_InterForm::SetFormNotify(const CPDF_FormNotify* pNotify)
+{
+ m_pFormNotify = (CPDF_FormNotify*)pNotify;
+}
+int CPDF_InterForm::GetPageWithWidget(int iCurPage, FX_BOOL bNext)
+{
+ if (iCurPage < 0) {
+ return -1;
+ }
+ int iPageCount = m_pDocument->GetPageCount();
+ if (iCurPage >= iPageCount) {
+ return -1;
+ }
+ int iNewPage = iCurPage;
+ do {
+ iNewPage += bNext ? 1 : -1;
+ if (iNewPage >= iPageCount) {
+ iNewPage = 0;
+ }
+ if (iNewPage < 0) {
+ iNewPage = iPageCount - 1;
+ }
+ if (iNewPage == iCurPage) {
+ break;
+ }
+ CPDF_Dictionary* pPageDict = m_pDocument->GetPage(iNewPage);
+ if (pPageDict == NULL) {
+ continue;
+ }
+ CPDF_Array* pAnnots = pPageDict->GetArray("Annots");
+ if (pAnnots == NULL) {
+ continue;
+ }
+ FX_DWORD dwCount = pAnnots->GetCount();
+ for (FX_DWORD i = 0; i < dwCount; i ++) {
+ CPDF_Object* pAnnotDict = pAnnots->GetElementValue(i);
+ if (pAnnotDict == NULL) {
+ continue;
+ }
+ CPDF_FormControl* pControl = NULL;
+ if (m_ControlMap.Lookup(pAnnotDict, (void*&)pControl)) {
+ return iNewPage;
+ }
+ }
+ } while (TRUE);
+ return -1;
+}
diff --git a/core/src/fpdfdoc/doc_formcontrol.cpp b/core/src/fpdfdoc/doc_formcontrol.cpp new file mode 100644 index 0000000000..f92b87e5f6 --- /dev/null +++ b/core/src/fpdfdoc/doc_formcontrol.cpp @@ -0,0 +1,461 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+CPDF_FormControl::CPDF_FormControl(CPDF_FormField* pField, CPDF_Dictionary* pWidgetDict)
+{
+ m_pField = pField;
+ m_pWidgetDict = pWidgetDict;
+ m_pForm = m_pField->m_pForm;
+}
+CFX_FloatRect CPDF_FormControl::GetRect()
+{
+ return m_pWidgetDict->GetRect("Rect");
+}
+CFX_ByteString CPDF_FormControl::GetOnStateName()
+{
+ ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
+ CFX_ByteString csOn;
+ CPDF_Dictionary* pAP = m_pWidgetDict->GetDict("AP");
+ if (pAP == NULL) {
+ return csOn;
+ }
+ CPDF_Dictionary* pN = pAP->GetDict("N");
+ if (pN == NULL) {
+ return csOn;
+ }
+ FX_POSITION pos = pN->GetStartPos();
+ while (pos) {
+ pN->GetNextElement(pos, csOn);
+ if (csOn != "Off") {
+ return csOn;
+ }
+ }
+ return CFX_ByteString();
+}
+void CPDF_FormControl::SetOnStateName(const CFX_ByteString& csOn)
+{
+ ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
+ CFX_ByteString csValue = csOn;
+ if (csValue.IsEmpty()) {
+ csValue = "Yes";
+ }
+ if (csValue == "Off") {
+ csValue = "Yes";
+ }
+ CFX_ByteString csAS = m_pWidgetDict->GetString("AS", "Off");
+ if (csAS != "Off") {
+ m_pWidgetDict->SetAtName("AS", csValue);
+ }
+ CPDF_Dictionary* pAP = m_pWidgetDict->GetDict("AP");
+ if (pAP == NULL) {
+ return;
+ }
+ FX_POSITION pos1 = pAP->GetStartPos();
+ while (pos1) {
+ CFX_ByteString csKey1;
+ CPDF_Object* pObj1 = pAP->GetNextElement(pos1, csKey1);
+ if (pObj1 == NULL) {
+ continue;
+ }
+ CPDF_Object* pObjDirect1 = pObj1->GetDirect();
+ if (pObjDirect1->GetType() != PDFOBJ_DICTIONARY) {
+ continue;
+ }
+ CPDF_Dictionary* pSubDict = (CPDF_Dictionary*)pObjDirect1;
+ FX_POSITION pos2 = pSubDict->GetStartPos();
+ while (pos2) {
+ CFX_ByteString csKey2;
+ CPDF_Object* pObj2 = pSubDict->GetNextElement(pos2, csKey2);
+ if (pObj2 == NULL) {
+ continue;
+ }
+ if (csKey2 != "Off") {
+ pSubDict->ReplaceKey(csKey2, csValue);
+ break;
+ }
+ }
+ }
+}
+CFX_ByteString CPDF_FormControl::GetCheckedAPState()
+{
+ ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
+ CFX_ByteString csOn = GetOnStateName();
+ if (GetType() == CPDF_FormField::RadioButton || GetType() == CPDF_FormField::CheckBox) {
+ CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pField->m_pDict, "Opt");
+ if (pOpt != NULL && pOpt->GetType() == PDFOBJ_ARRAY) {
+ int iIndex = m_pField->GetControlIndex(this);
+ csOn.Format("%d", iIndex);
+ }
+ }
+ if (csOn.IsEmpty()) {
+ csOn = "Yes";
+ }
+ return csOn;
+}
+CFX_WideString CPDF_FormControl::GetExportValue()
+{
+ ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
+ CFX_ByteString csOn = GetOnStateName();
+ if (GetType() == CPDF_FormField::RadioButton || GetType() == CPDF_FormField::CheckBox) {
+ CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pField->m_pDict, "Opt");
+ if (pOpt != NULL && pOpt->GetType() == PDFOBJ_ARRAY) {
+ int iIndex = m_pField->GetControlIndex(this);
+ csOn = ((CPDF_Array*)pOpt)->GetString(iIndex);
+ }
+ }
+ if (csOn.IsEmpty()) {
+ csOn = "Yes";
+ }
+ CFX_WideString csWOn = PDF_DecodeText(csOn);
+ return csWOn;
+}
+FX_BOOL CPDF_FormControl::IsChecked()
+{
+ ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
+ CFX_ByteString csOn = GetOnStateName();
+ CFX_ByteString csAS = m_pWidgetDict->GetString("AS");
+ return csAS == csOn;
+}
+FX_BOOL CPDF_FormControl::IsDefaultChecked()
+{
+ ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
+ CPDF_Object* pDV = FPDF_GetFieldAttr(m_pField->m_pDict, "DV");
+ if (pDV == NULL) {
+ return FALSE;
+ }
+ CFX_ByteString csDV = pDV->GetString();
+ CFX_ByteString csOn = GetOnStateName();
+ return (csDV == csOn);
+}
+void CPDF_FormControl::CheckControl(FX_BOOL bChecked)
+{
+ ASSERT(GetType() == CPDF_FormField::CheckBox || GetType() == CPDF_FormField::RadioButton);
+ CFX_ByteString csOn = GetOnStateName();
+ CFX_ByteString csOldAS = m_pWidgetDict->GetString("AS", "Off");
+ CFX_ByteString csAS = "Off";
+ if (bChecked) {
+ csAS = csOn;
+ }
+ if (csOldAS == csAS) {
+ return;
+ }
+ m_pWidgetDict->SetAtName("AS", csAS);
+ m_pForm->m_bUpdated = TRUE;
+}
+CPDF_Stream* FPDFDOC_GetAnnotAP(CPDF_Dictionary* pAnnotDict, CPDF_Annot::AppearanceMode mode);
+void CPDF_FormControl::DrawControl(CFX_RenderDevice* pDevice, CFX_AffineMatrix* pMatrix, CPDF_Page* pPage,
+ CPDF_Annot::AppearanceMode mode, const CPDF_RenderOptions* pOptions)
+{
+ if (m_pWidgetDict->GetInteger("F") & ANNOTFLAG_HIDDEN) {
+ return;
+ }
+ CPDF_Stream* pStream = FPDFDOC_GetAnnotAP(m_pWidgetDict, mode);
+ if (pStream == NULL) {
+ return;
+ }
+ CFX_FloatRect form_bbox = pStream->GetDict()->GetRect("BBox");
+ CFX_AffineMatrix form_matrix = pStream->GetDict()->GetMatrix("Matrix");
+ form_matrix.TransformRect(form_bbox);
+ CFX_FloatRect arect = m_pWidgetDict->GetRect("Rect");
+ CFX_AffineMatrix matrix;
+ matrix.MatchRect(arect, form_bbox);
+ matrix.Concat(*pMatrix);
+ CPDF_Form form(m_pField->m_pForm->m_pDocument, m_pField->m_pForm->m_pFormDict->GetDict("DR"), pStream);
+ form.ParseContent(NULL, NULL, NULL, NULL);
+ CPDF_RenderContext context;
+ context.Create(pPage);
+ context.DrawObjectList(pDevice, &form, &matrix, pOptions);
+}
+const FX_CHAR* g_sHighlightingMode[] = {"N", "I", "O", "P", "T", ""};
+CPDF_FormControl::HighlightingMode CPDF_FormControl::GetHighlightingMode()
+{
+ if (m_pWidgetDict == NULL) {
+ return Invert;
+ }
+ CFX_ByteString csH = m_pWidgetDict->GetString("H", "I");
+ int i = 0;
+ while (g_sHighlightingMode[i][0] != '\0') {
+ if (csH.Equal(g_sHighlightingMode[i])) {
+ return (HighlightingMode)i;
+ }
+ i ++;
+ }
+ return Invert;
+}
+CPDF_ApSettings CPDF_FormControl::GetMK(FX_BOOL bCreate)
+{
+ if (!m_pWidgetDict) {
+ return NULL;
+ }
+ CPDF_ApSettings mk = m_pWidgetDict->GetDict(FX_BSTRC("MK"));
+ if (!mk && bCreate) {
+ mk = CPDF_Dictionary::Create();
+ if (mk == NULL) {
+ return NULL;
+ }
+ m_pWidgetDict->SetAt(FX_BSTRC("MK"), mk);
+ }
+ return mk;
+}
+FX_BOOL CPDF_FormControl::HasMKEntry(CFX_ByteString csEntry)
+{
+ CPDF_ApSettings mk = GetMK(FALSE);
+ return mk.HasMKEntry(csEntry);
+}
+int CPDF_FormControl::GetRotation()
+{
+ CPDF_ApSettings mk = GetMK(FALSE);
+ return mk.GetRotation();
+}
+FX_ARGB CPDF_FormControl::GetColor(int& iColorType, CFX_ByteString csEntry)
+{
+ CPDF_ApSettings mk = GetMK(FALSE);
+ return mk.GetColor(iColorType, csEntry);
+}
+FX_FLOAT CPDF_FormControl::GetOriginalColor(int index, CFX_ByteString csEntry)
+{
+ CPDF_ApSettings mk = GetMK(FALSE);
+ return mk.GetOriginalColor(index, csEntry);
+}
+void CPDF_FormControl::GetOriginalColor(int& iColorType, FX_FLOAT fc[4], CFX_ByteString csEntry)
+{
+ CPDF_ApSettings mk = GetMK(FALSE);
+ mk.GetOriginalColor(iColorType, fc, csEntry);
+}
+CFX_WideString CPDF_FormControl::GetCaption(CFX_ByteString csEntry)
+{
+ CPDF_ApSettings mk = GetMK(FALSE);
+ return mk.GetCaption(csEntry);
+}
+CPDF_Stream* CPDF_FormControl::GetIcon(CFX_ByteString csEntry)
+{
+ CPDF_ApSettings mk = GetMK(FALSE);
+ return mk.GetIcon(csEntry);
+}
+CPDF_IconFit CPDF_FormControl::GetIconFit()
+{
+ CPDF_ApSettings mk = GetMK(FALSE);
+ return mk.GetIconFit();
+}
+int CPDF_FormControl::GetTextPosition()
+{
+ CPDF_ApSettings mk = GetMK(FALSE);
+ return mk.GetTextPosition();
+}
+CPDF_Action CPDF_FormControl::GetAction()
+{
+ if (m_pWidgetDict == NULL) {
+ return NULL;
+ }
+ if (m_pWidgetDict->KeyExist("A")) {
+ return m_pWidgetDict->GetDict("A");
+ } else {
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "A");
+ if (pObj == NULL) {
+ return NULL;
+ }
+ return pObj->GetDict();
+ }
+}
+CPDF_AAction CPDF_FormControl::GetAdditionalAction()
+{
+ if (m_pWidgetDict == NULL) {
+ return NULL;
+ }
+ if (m_pWidgetDict->KeyExist("AA")) {
+ return m_pWidgetDict->GetDict("AA");
+ } else {
+ return m_pField->GetAdditionalAction();
+ }
+}
+CPDF_DefaultAppearance CPDF_FormControl::GetDefaultAppearance()
+{
+ if (m_pWidgetDict == NULL) {
+ return CFX_ByteString();
+ }
+ if (m_pWidgetDict->KeyExist("DA")) {
+ return m_pWidgetDict->GetString("DA");
+ } else {
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "DA");
+ if (pObj == NULL) {
+ return m_pField->m_pForm->GetDefaultAppearance();
+ }
+ return pObj->GetString();
+ }
+}
+CPDF_Font* CPDF_FormControl::GetDefaultControlFont()
+{
+ CPDF_DefaultAppearance cDA = GetDefaultAppearance();
+ CFX_ByteString csFontNameTag;
+ FX_FLOAT fFontSize;
+ cDA.GetFont(csFontNameTag, fFontSize);
+ if (csFontNameTag.IsEmpty()) {
+ return NULL;
+ }
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pWidgetDict, "DR");
+ if (pObj != NULL && pObj->GetType() == PDFOBJ_DICTIONARY) {
+ CPDF_Dictionary* pFonts = ((CPDF_Dictionary*)pObj)->GetDict("Font");
+ if (pFonts != NULL) {
+ CPDF_Dictionary *pElement = pFonts->GetDict(csFontNameTag);
+ CPDF_Font *pFont = m_pField->m_pForm->m_pDocument->LoadFont(pElement);
+ if (pFont != NULL) {
+ return pFont;
+ }
+ }
+ }
+ CPDF_Font *pFont = m_pField->m_pForm->GetFormFont(csFontNameTag);
+ if (pFont != NULL) {
+ return pFont;
+ }
+ CPDF_Dictionary *pPageDict = m_pWidgetDict->GetDict("P");
+ pObj = FPDF_GetFieldAttr(pPageDict, "Resources");
+ if (pObj != NULL && pObj->GetType() == PDFOBJ_DICTIONARY) {
+ CPDF_Dictionary* pFonts = ((CPDF_Dictionary*)pObj)->GetDict("Font");
+ if (pFonts != NULL) {
+ CPDF_Dictionary *pElement = pFonts->GetDict(csFontNameTag);
+ CPDF_Font *pFont = m_pField->m_pForm->m_pDocument->LoadFont(pElement);
+ if (pFont != NULL) {
+ return pFont;
+ }
+ }
+ }
+ return NULL;
+}
+int CPDF_FormControl::GetControlAlignment()
+{
+ if (m_pWidgetDict == NULL) {
+ return 0;
+ }
+ if (m_pWidgetDict->KeyExist("Q")) {
+ return m_pWidgetDict->GetInteger("Q", 0);
+ } else {
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pField->m_pDict, "Q");
+ if (pObj == NULL) {
+ return m_pField->m_pForm->GetFormAlignment();
+ }
+ return pObj->GetInteger();
+ }
+}
+FX_BOOL CPDF_ApSettings::HasMKEntry(FX_BSTR csEntry)
+{
+ if (m_pDict == NULL) {
+ return FALSE;
+ }
+ return m_pDict->KeyExist(csEntry);
+}
+int CPDF_ApSettings::GetRotation()
+{
+ if (m_pDict == NULL) {
+ return 0;
+ }
+ return m_pDict->GetInteger(FX_BSTRC("R"));
+}
+FX_ARGB CPDF_ApSettings::GetColor(int& iColorType, FX_BSTR csEntry)
+{
+ iColorType = COLORTYPE_TRANSPARENT;
+ if (m_pDict == NULL) {
+ return 0;
+ }
+ FX_ARGB color = 0;
+ CPDF_Array* pEntry = m_pDict->GetArray(csEntry);
+ if (pEntry == NULL) {
+ return color;
+ }
+ FX_DWORD dwCount = pEntry->GetCount();
+ if (dwCount == 1) {
+ iColorType = COLORTYPE_GRAY;
+ FX_FLOAT g = pEntry->GetNumber(0) * 255;
+ color = ArgbEncode(255, (int)g, (int)g, (int)g);
+ } else if (dwCount == 3) {
+ iColorType = COLORTYPE_RGB;
+ FX_FLOAT r = pEntry->GetNumber(0) * 255;
+ FX_FLOAT g = pEntry->GetNumber(1) * 255;
+ FX_FLOAT b = pEntry->GetNumber(2) * 255;
+ color = ArgbEncode(255, (int)r, (int)g, (int)b);
+ } else if (dwCount == 4) {
+ iColorType = COLORTYPE_CMYK;
+ FX_FLOAT c = pEntry->GetNumber(0);
+ FX_FLOAT m = pEntry->GetNumber(1);
+ FX_FLOAT y = pEntry->GetNumber(2);
+ FX_FLOAT k = pEntry->GetNumber(3);
+ FX_FLOAT r = 1.0f - FX_MIN(1.0f, c + k);
+ FX_FLOAT g = 1.0f - FX_MIN(1.0f, m + k);
+ FX_FLOAT b = 1.0f - FX_MIN(1.0f, y + k);
+ color = ArgbEncode(255, (int)(r * 255), (int)(g * 255), (int)(b * 255));
+ }
+ return color;
+}
+FX_FLOAT CPDF_ApSettings::GetOriginalColor(int index, FX_BSTR csEntry)
+{
+ if (m_pDict == NULL) {
+ return 0;
+ }
+ CPDF_Array* pEntry = m_pDict->GetArray(csEntry);
+ if (pEntry != NULL) {
+ return pEntry->GetNumber(index);
+ }
+ return 0;
+}
+void CPDF_ApSettings::GetOriginalColor(int& iColorType, FX_FLOAT fc[4], FX_BSTR csEntry)
+{
+ iColorType = COLORTYPE_TRANSPARENT;
+ for (int i = 0; i < 4; i ++) {
+ fc[i] = 0;
+ }
+ if (m_pDict == NULL) {
+ return;
+ }
+ CPDF_Array* pEntry = m_pDict->GetArray(csEntry);
+ if (pEntry == NULL) {
+ return;
+ }
+ FX_DWORD dwCount = pEntry->GetCount();
+ if (dwCount == 1) {
+ iColorType = COLORTYPE_GRAY;
+ fc[0] = pEntry->GetNumber(0);
+ } else if (dwCount == 3) {
+ iColorType = COLORTYPE_RGB;
+ fc[0] = pEntry->GetNumber(0);
+ fc[1] = pEntry->GetNumber(1);
+ fc[2] = pEntry->GetNumber(2);
+ } else if (dwCount == 4) {
+ iColorType = COLORTYPE_CMYK;
+ fc[0] = pEntry->GetNumber(0);
+ fc[1] = pEntry->GetNumber(1);
+ fc[2] = pEntry->GetNumber(2);
+ fc[3] = pEntry->GetNumber(3);
+ }
+}
+CFX_WideString CPDF_ApSettings::GetCaption(FX_BSTR csEntry)
+{
+ CFX_WideString csCaption;
+ if (m_pDict == NULL) {
+ return csCaption;
+ }
+ return m_pDict->GetUnicodeText(csEntry);
+}
+CPDF_Stream* CPDF_ApSettings::GetIcon(FX_BSTR csEntry)
+{
+ if (m_pDict == NULL) {
+ return NULL;
+ }
+ return m_pDict->GetStream(csEntry);
+}
+CPDF_IconFit CPDF_ApSettings::GetIconFit()
+{
+ if (m_pDict == NULL) {
+ return NULL;
+ }
+ return m_pDict->GetDict(FX_BSTRC("IF"));
+}
+int CPDF_ApSettings::GetTextPosition()
+{
+ if (m_pDict == NULL) {
+ return TEXTPOS_CAPTION;
+ }
+ return m_pDict->GetInteger(FX_BSTRC("TP"), TEXTPOS_CAPTION);
+}
diff --git a/core/src/fpdfdoc/doc_formfield.cpp b/core/src/fpdfdoc/doc_formfield.cpp new file mode 100644 index 0000000000..d84a6b14be --- /dev/null +++ b/core/src/fpdfdoc/doc_formfield.cpp @@ -0,0 +1,1095 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+CFX_WideString GetFullName(CPDF_Dictionary* pFieldDict);
+void SaveCheckedFieldStatus(CPDF_FormField* pField, CFX_ByteArray& statusArray);
+FX_BOOL PDF_FormField_IsUnison(CPDF_FormField *pField)
+{
+ FX_BOOL bUnison = FALSE;
+ if (pField->GetType() == CPDF_FormField::CheckBox) {
+ bUnison = TRUE;
+ } else {
+ FX_DWORD dwFlags = pField->GetFieldFlags();
+ bUnison = ((dwFlags & 0x2000000) != 0);
+ }
+ return bUnison;
+}
+CPDF_FormField::CPDF_FormField(CPDF_InterForm* pForm, CPDF_Dictionary* pDict)
+{
+ m_pDict = pDict;
+ m_Type = Unknown;
+ m_pForm = pForm;
+ m_pFont = NULL;
+ m_FontSize = 0;
+ SyncFieldFlags();
+}
+CPDF_FormField::~CPDF_FormField()
+{
+}
+void CPDF_FormField::SyncFieldFlags()
+{
+ CFX_ByteString type_name = FPDF_GetFieldAttr(m_pDict, "FT")->GetString();
+ FX_DWORD flags = FPDF_GetFieldAttr(m_pDict, "Ff")->GetInteger();
+ m_Flags = 0;
+ if (flags & 1) {
+ m_Flags |= FORMFIELD_READONLY;
+ }
+ if (flags & 2) {
+ m_Flags |= FORMFIELD_REQUIRED;
+ }
+ if (flags & 4) {
+ m_Flags |= FORMFIELD_NOEXPORT;
+ }
+ if (type_name == "Btn") {
+ if (flags & 0x8000) {
+ m_Type = RadioButton;
+ if (flags & 0x4000) {
+ m_Flags |= FORMRADIO_NOTOGGLEOFF;
+ }
+ if (flags & 0x2000000) {
+ m_Flags |= FORMRADIO_UNISON;
+ }
+ } else if (flags & 0x10000) {
+ m_Type = PushButton;
+ } else {
+ m_Type = CheckBox;
+ }
+ } else if (type_name == "Tx") {
+ if (flags & 0x100000) {
+ m_Type = File;
+ } else if (flags & 0x2000000) {
+ m_Type = RichText;
+ } else {
+ m_Type = Text;
+ if (flags & 0x1000) {
+ m_Flags |= FORMTEXT_MULTILINE;
+ }
+ if (flags & 0x2000) {
+ m_Flags |= FORMTEXT_PASSWORD;
+ }
+ if (flags & 0x800000) {
+ m_Flags |= FORMTEXT_NOSCROLL;
+ }
+ if (flags & 0x100000) {
+ m_Flags |= FORMTEXT_COMB;
+ }
+ }
+ LoadDA();
+ } else if (type_name == "Ch") {
+ if (flags & 0x20000) {
+ m_Type = ComboBox;
+ if (flags & 0x40000) {
+ m_Flags |= FORMCOMBO_EDIT;
+ }
+ } else {
+ m_Type = ListBox;
+ if (flags & 0x200000) {
+ m_Flags |= FORMLIST_MULTISELECT;
+ }
+ }
+ LoadDA();
+ } else if (type_name == "Sig") {
+ m_Type = Sign;
+ }
+}
+CFX_WideString CPDF_FormField::GetFullName()
+{
+ return ::GetFullName(m_pDict);
+}
+FX_BOOL CPDF_FormField::ResetField(FX_BOOL bNotify)
+{
+ switch (m_Type) {
+ case CPDF_FormField::CheckBox:
+ case CPDF_FormField::RadioButton: {
+ CFX_ByteArray statusArray;
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ SaveCheckedFieldStatus(this, statusArray);
+ }
+ int iCount = CountControls();
+ if (iCount) {
+ if (PDF_FormField_IsUnison(this)) {
+ for(int i = 0; i < iCount; i++) {
+ CheckControl(i, GetControl(i)->IsDefaultChecked(), FALSE);
+ }
+ } else {
+ for (int i = 0; i < iCount; i ++) {
+ CPDF_FormControl* pControl = GetControl(i);
+ FX_BOOL bChecked = pControl->IsDefaultChecked();
+ CheckControl(i, bChecked, FALSE);
+ }
+ }
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
+ }
+ }
+ break;
+ case CPDF_FormField::ComboBox: {
+ CFX_WideString csValue;
+ ClearSelection();
+ int iIndex = GetDefaultSelectedItem();
+ if (iIndex >= 0) {
+ csValue = GetOptionLabel(iIndex);
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ SetItemSelection(iIndex, TRUE);
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ m_pForm->m_pFormNotify->AfterValueChange(this);
+ }
+ }
+ break;
+ case CPDF_FormField::ListBox: {
+ CFX_WideString csValue;
+ ClearSelection();
+ int iIndex = GetDefaultSelectedItem();
+ if (iIndex >= 0) {
+ csValue = GetOptionLabel(iIndex);
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ int iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ SetItemSelection(iIndex, TRUE);
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ m_pForm->m_pFormNotify->AfterSelectionChange(this);
+ }
+ }
+ break;
+ case CPDF_FormField::Text:
+ case CPDF_FormField::RichText:
+ case CPDF_FormField::File:
+ default: {
+ CPDF_Object* pDV = FPDF_GetFieldAttr(m_pDict, "DV");
+ CFX_WideString csDValue;
+ if (pDV != NULL) {
+ csDValue = pDV->GetUnicodeText();
+ }
+ CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
+ CFX_WideString csValue;
+ if (pV != NULL) {
+ csValue = pV->GetUnicodeText();
+ }
+ CPDF_Object* pRV = FPDF_GetFieldAttr(m_pDict, "RV");
+ if (!pRV && (csDValue == csValue)) {
+ return FALSE;
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csDValue);
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ if (pDV == NULL) {
+ m_pDict->RemoveAt("V");
+ m_pDict->RemoveAt("RV");
+ } else {
+ CPDF_Object* pClone = pDV->Clone();
+ if (pClone == NULL) {
+ return FALSE;
+ }
+ m_pDict->SetAt("V", pClone);
+ if(pRV) {
+ CPDF_Object* pCloneR = pDV->Clone();
+ m_pDict->SetAt("RV", pCloneR);
+ }
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ m_pForm->m_pFormNotify->AfterValueChange(this);
+ }
+ m_pForm->m_bUpdated = TRUE;
+ }
+ break;
+ }
+ return TRUE;
+}
+int CPDF_FormField::GetControlIndex(const CPDF_FormControl* pControl)
+{
+ if (pControl == NULL) {
+ return -1;
+ }
+ int iCount = m_ControlList.GetSize();
+ for (int i = 0; i < iCount; i ++) {
+ CPDF_FormControl* pFind = (CPDF_FormControl*)m_ControlList.GetAt(i);
+ if (pFind == pControl) {
+ return i;
+ }
+ }
+ return -1;
+}
+int CPDF_FormField::GetFieldType()
+{
+ switch (m_Type) {
+ case PushButton:
+ return FIELDTYPE_PUSHBUTTON;
+ case CheckBox:
+ return FIELDTYPE_CHECKBOX;
+ case RadioButton:
+ return FIELDTYPE_RADIOBUTTON;
+ case ComboBox:
+ return FIELDTYPE_COMBOBOX;
+ case ListBox:
+ return FIELDTYPE_LISTBOX;
+ case Text:
+ case RichText:
+ case File:
+ return FIELDTYPE_TEXTFIELD;
+ case Sign:
+ return FIELDTYPE_SIGNATURE;
+ default:
+ break;
+ }
+ return FIELDTYPE_UNKNOWN;
+}
+CPDF_AAction CPDF_FormField::GetAdditionalAction()
+{
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "AA");
+ if (pObj == NULL) {
+ return NULL;
+ }
+ return pObj->GetDict();
+}
+CFX_WideString CPDF_FormField::GetAlternateName()
+{
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TU");
+ if (pObj == NULL) {
+ return L"";
+ }
+ return pObj->GetUnicodeText();
+}
+CFX_WideString CPDF_FormField::GetMappingName()
+{
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TM");
+ if (pObj == NULL) {
+ return L"";
+ }
+ return pObj->GetUnicodeText();
+}
+FX_DWORD CPDF_FormField::GetFieldFlags()
+{
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "Ff");
+ if (pObj == NULL) {
+ return 0;
+ }
+ return pObj->GetInteger();
+}
+CFX_ByteString CPDF_FormField::GetDefaultStyle()
+{
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "DS");
+ if (pObj == NULL) {
+ return "";
+ }
+ return pObj->GetString();
+}
+CFX_WideString CPDF_FormField::GetRichTextString()
+{
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "RV");
+ if (pObj == NULL) {
+ return L"";
+ }
+ return pObj->GetUnicodeText();
+}
+CFX_WideString CPDF_FormField::GetValue(FX_BOOL bDefault)
+{
+ if (GetType() == CheckBox || GetType() == RadioButton) {
+ return GetCheckValue(bDefault);
+ }
+ CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, bDefault ? "DV" : "V");
+ if (pValue == NULL) {
+ if (!bDefault) {
+ if (m_Type == RichText) {
+ pValue = FPDF_GetFieldAttr(m_pDict, "V");
+ }
+ if (pValue == NULL && m_Type != Text) {
+ pValue = FPDF_GetFieldAttr(m_pDict, "DV");
+ }
+ }
+ if (pValue == NULL) {
+ return CFX_WideString();
+ }
+ }
+ switch (pValue->GetType()) {
+ case PDFOBJ_STRING:
+ case PDFOBJ_STREAM:
+ return pValue->GetUnicodeText();
+ case PDFOBJ_ARRAY:
+ pValue = ((CPDF_Array*)pValue)->GetElementValue(0);
+ return pValue->GetUnicodeText();
+ break;
+ }
+ return CFX_WideString();
+}
+CFX_WideString CPDF_FormField::GetValue()
+{
+ return GetValue(FALSE);
+}
+CFX_WideString CPDF_FormField::GetDefaultValue()
+{
+ return GetValue(TRUE);
+}
+FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bDefault, FX_BOOL bNotify)
+{
+ switch (m_Type) {
+ case CheckBox:
+ case RadioButton: {
+ SetCheckValue(value, bDefault, bNotify);
+ return TRUE;
+ }
+ case File:
+ case RichText:
+ case Text:
+ case ComboBox: {
+ CFX_WideString csValue = value;
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ int iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ int iIndex = FindOptionValue(csValue);
+ if (iIndex < 0) {
+ CFX_ByteString bsEncodeText = PDF_EncodeText(csValue);
+ m_pDict->SetAtString(bDefault ? "DV" : "V", bsEncodeText);
+ if (m_Type == RichText && !bDefault) {
+ m_pDict->SetAtString("RV", bsEncodeText);
+ }
+ m_pDict->RemoveAt("I");
+ } else {
+ m_pDict->SetAtString(bDefault ? "DV" : "V", PDF_EncodeText(csValue));
+ if (bDefault) {
+ } else {
+ ClearSelection();
+ SetItemSelection(iIndex, TRUE);
+ }
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ m_pForm->m_pFormNotify->AfterValueChange(this);
+ }
+ m_pForm->m_bUpdated = TRUE;
+ }
+ break;
+ case ListBox: {
+ int iIndex = FindOptionValue(value);
+ if (iIndex < 0) {
+ return FALSE;
+ }
+ if (bDefault && iIndex == GetDefaultSelectedItem()) {
+ return FALSE;
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ CFX_WideString csValue = value;
+ int iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ if (bDefault) {
+ } else {
+ ClearSelection();
+ SetItemSelection(iIndex, TRUE);
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ m_pForm->m_pFormNotify->AfterSelectionChange(this);
+ }
+ m_pForm->m_bUpdated = TRUE;
+ break;
+ }
+ default:
+ break;
+ }
+ if (CPDF_InterForm::m_bUpdateAP) {
+ UpdateAP(NULL);
+ }
+ return TRUE;
+}
+FX_BOOL CPDF_FormField::SetValue(const CFX_WideString& value, FX_BOOL bNotify)
+{
+ return SetValue(value, FALSE, bNotify);
+}
+int CPDF_FormField::GetMaxLen()
+{
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "MaxLen");
+ if (pObj == NULL) {
+ int iCount = m_ControlList.GetSize();
+ for (int i = 0; i < iCount; i ++) {
+ CPDF_FormControl* pControl = (CPDF_FormControl*)m_ControlList.GetAt(i);
+ if (pControl == NULL) {
+ continue;
+ }
+ CPDF_Dictionary* pWidgetDict = pControl->m_pWidgetDict;
+ if (pWidgetDict->KeyExist("MaxLen")) {
+ return pWidgetDict->GetInteger("MaxLen");
+ }
+ }
+ return 0;
+ }
+ return pObj->GetInteger();
+}
+int CPDF_FormField::CountSelectedItems()
+{
+ CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
+ if (pValue == NULL) {
+ pValue = FPDF_GetFieldAttr(m_pDict, "I");
+ if (pValue == NULL) {
+ return 0;
+ }
+ }
+ if (pValue->GetType() == PDFOBJ_STRING) {
+ if (pValue->GetString().IsEmpty()) {
+ return 0;
+ }
+ return 1;
+ }
+ if (pValue->GetType() == PDFOBJ_NUMBER) {
+ if (pValue->GetString().IsEmpty()) {
+ return 0;
+ }
+ return 1;
+ }
+ if (pValue->GetType() != PDFOBJ_ARRAY) {
+ return 0;
+ }
+ return ((CPDF_Array*)pValue)->GetCount();
+}
+int CPDF_FormField::GetSelectedIndex(int index)
+{
+ CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
+ if (pValue == NULL) {
+ pValue = FPDF_GetFieldAttr(m_pDict, "I");
+ if (pValue == NULL) {
+ return -1;
+ }
+ }
+ CFX_WideString sel_value;
+ if (pValue->GetType() == PDFOBJ_STRING) {
+ if (index != 0) {
+ return -1;
+ }
+ sel_value = pValue->GetUnicodeText();
+ } else if (pValue->GetType() == PDFOBJ_NUMBER) {
+ return pValue->GetInteger();
+ } else {
+ if (pValue->GetType() != PDFOBJ_ARRAY) {
+ return -1;
+ }
+ if (index < 0) {
+ return -1;
+ }
+ sel_value = ((CPDF_Array*)pValue)->GetElementValue(index)->GetUnicodeText();
+ }
+ if (index < CountSelectedOptions()) {
+ int iOptIndex = GetSelectedOptionIndex(index);
+ CFX_WideString csOpt = GetOptionValue(iOptIndex);
+ if (csOpt == sel_value) {
+ return iOptIndex;
+ }
+ }
+ int nOpts = CountOptions();
+ for (int i = 0; i < nOpts; i ++) {
+ if (sel_value == GetOptionValue(i)) {
+ return i;
+ }
+ }
+ return -1;
+}
+FX_BOOL CPDF_FormField::ClearSelection(FX_BOOL bNotify)
+{
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ int iRet = 0;
+ CFX_WideString csValue;
+ int iIndex = GetSelectedIndex(0);
+ if (iIndex >= 0) {
+ csValue = GetOptionLabel(iIndex);
+ }
+ if (GetType() == ListBox) {
+ iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
+ }
+ if (GetType() == ComboBox) {
+ iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
+ }
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ m_pDict->RemoveAt("V");
+ m_pDict->RemoveAt("I");
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ if (GetType() == ListBox) {
+ m_pForm->m_pFormNotify->AfterSelectionChange(this);
+ }
+ if (GetType() == ComboBox) {
+ m_pForm->m_pFormNotify->AfterValueChange(this);
+ }
+ }
+ if (CPDF_InterForm::m_bUpdateAP) {
+ UpdateAP(NULL);
+ }
+ m_pForm->m_bUpdated = TRUE;
+ return TRUE;
+}
+FX_BOOL CPDF_FormField::IsItemSelected(int index)
+{
+ ASSERT(GetType() == ComboBox || GetType() == ListBox);
+ if (index < 0 || index >= CountOptions()) {
+ return FALSE;
+ }
+ if (IsOptionSelected(index)) {
+ return TRUE;
+ }
+ CFX_WideString opt_value = GetOptionValue(index);
+ CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
+ if (pValue == NULL) {
+ pValue = FPDF_GetFieldAttr(m_pDict, "I");
+ if (pValue == NULL) {
+ return FALSE;
+ }
+ }
+ if (pValue->GetType() == PDFOBJ_STRING) {
+ if (pValue->GetUnicodeText() == opt_value) {
+ return TRUE;
+ }
+ return FALSE;
+ }
+ if (pValue->GetType() == PDFOBJ_NUMBER) {
+ if (pValue->GetString().IsEmpty()) {
+ return FALSE;
+ }
+ if (pValue->GetInteger() == index) {
+ return TRUE;
+ }
+ return FALSE;
+ }
+ if (pValue->GetType() != PDFOBJ_ARRAY) {
+ return FALSE;
+ }
+ CPDF_Array* pArray = (CPDF_Array*)pValue;
+ int iPos = -1;
+ for (int j = 0; j < CountSelectedOptions(); j ++) {
+ if (GetSelectedOptionIndex(j) == index) {
+ iPos = j;
+ break;
+ }
+ }
+ for (FX_DWORD i = 0; i < pArray->GetCount(); i ++)
+ if (pArray->GetElementValue(i)->GetUnicodeText() == opt_value && (int)i == iPos) {
+ return TRUE;
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_FormField::SetItemSelection(int index, FX_BOOL bSelected, FX_BOOL bNotify)
+{
+ ASSERT(GetType() == ComboBox || GetType() == ListBox);
+ if (index < 0 || index >= CountOptions()) {
+ return FALSE;
+ }
+ CFX_WideString opt_value = GetOptionValue(index);
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ int iRet = 0;
+ if (GetType() == ListBox) {
+ iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, opt_value);
+ }
+ if (GetType() == ComboBox) {
+ iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, opt_value);
+ }
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ if (!bSelected) {
+ CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "V");
+ if (pValue != NULL) {
+ if (m_Type == ListBox) {
+ SelectOption(index, FALSE);
+ if (pValue->GetType() == PDFOBJ_STRING) {
+ if (pValue->GetUnicodeText() == opt_value) {
+ m_pDict->RemoveAt("V");
+ }
+ } else if (pValue->GetType() == PDFOBJ_ARRAY) {
+ CPDF_Array* pArray = CPDF_Array::Create();
+ if (pArray == NULL) {
+ return FALSE;
+ }
+ int iCount = CountOptions();
+ for (int i = 0; i < iCount; i ++) {
+ if (i != index) {
+ if (IsItemSelected(i)) {
+ opt_value = GetOptionValue(i);
+ pArray->AddString(PDF_EncodeText(opt_value));
+ }
+ }
+ }
+ if (pArray->GetCount() < 1) {
+ pArray->Release();
+ } else {
+ m_pDict->SetAt("V", pArray);
+ }
+ }
+ } else if (m_Type == ComboBox) {
+ m_pDict->RemoveAt("V");
+ m_pDict->RemoveAt("I");
+ }
+ }
+ } else {
+ if (m_Type == ListBox) {
+ SelectOption(index, TRUE);
+ if (!(m_Flags & FORMLIST_MULTISELECT)) {
+ m_pDict->SetAtString("V", PDF_EncodeText(opt_value, opt_value.GetLength()));
+ } else {
+ CPDF_Array* pArray = CPDF_Array::Create();
+ if (pArray == NULL) {
+ return FALSE;
+ }
+ FX_BOOL bSelected;
+ int iCount = CountOptions();
+ for (int i = 0; i < iCount; i ++) {
+ if (i != index) {
+ bSelected = IsItemSelected(i);
+ } else {
+ bSelected = TRUE;
+ }
+ if (bSelected) {
+ opt_value = GetOptionValue(i);
+ pArray->AddString(PDF_EncodeText(opt_value));
+ }
+ }
+ m_pDict->SetAt("V", pArray);
+ }
+ } else if (m_Type == ComboBox) {
+ m_pDict->SetAtString("V", PDF_EncodeText(opt_value, opt_value.GetLength()));
+ CPDF_Array* pI = CPDF_Array::Create();
+ if (pI == NULL) {
+ return FALSE;
+ }
+ pI->AddInteger(index);
+ m_pDict->SetAt("I", pI);
+ }
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ if (GetType() == ListBox) {
+ m_pForm->m_pFormNotify->AfterSelectionChange(this);
+ }
+ if (GetType() == ComboBox) {
+ m_pForm->m_pFormNotify->AfterValueChange(this);
+ }
+ }
+ if (CPDF_InterForm::m_bUpdateAP) {
+ UpdateAP(NULL);
+ }
+ m_pForm->m_bUpdated = TRUE;
+ return TRUE;
+}
+FX_BOOL CPDF_FormField::IsItemDefaultSelected(int index)
+{
+ ASSERT(GetType() == ComboBox || GetType() == ListBox);
+ if (index < 0 || index >= CountOptions()) {
+ return FALSE;
+ }
+ int iDVIndex = GetDefaultSelectedItem();
+ if (iDVIndex < 0) {
+ return FALSE;
+ }
+ return (iDVIndex == index);
+}
+int CPDF_FormField::GetDefaultSelectedItem()
+{
+ ASSERT(GetType() == ComboBox || GetType() == ListBox);
+ CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "DV");
+ if (pValue == NULL) {
+ return -1;
+ }
+ CFX_WideString csDV = pValue->GetUnicodeText();
+ if (csDV.IsEmpty()) {
+ return -1;
+ }
+ int iCount = CountOptions();
+ for (int i = 0; i < iCount; i ++) {
+ if (csDV == GetOptionValue(i)) {
+ return i;
+ }
+ }
+ return -1;
+}
+void CPDF_FormField::UpdateAP(CPDF_FormControl* pControl)
+{
+ if (m_Type == PushButton) {
+ return;
+ }
+ if (m_Type == RadioButton || m_Type == CheckBox) {
+ return;
+ }
+ if (!m_pForm->m_bGenerateAP) {
+ return;
+ }
+ for (int i = 0; i < CountControls(); i ++) {
+ CPDF_FormControl* pControl = GetControl(i);
+ FPDF_GenerateAP(m_pForm->m_pDocument, pControl->m_pWidgetDict);
+ }
+}
+int CPDF_FormField::CountOptions()
+{
+ CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt");
+ if (pValue == NULL || pValue->GetType() != PDFOBJ_ARRAY) {
+ return 0;
+ }
+ return ((CPDF_Array*)pValue)->GetCount();
+}
+CFX_WideString CPDF_FormField::GetOptionText(int index, int sub_index)
+{
+ CPDF_Object* pValue = FPDF_GetFieldAttr(m_pDict, "Opt");
+ if (pValue == NULL || pValue->GetType() != PDFOBJ_ARRAY) {
+ return CFX_WideString();
+ }
+ CPDF_Object* pOption = ((CPDF_Array*)pValue)->GetElementValue(index);
+ if (pOption == NULL) {
+ return CFX_WideString();
+ }
+ if (pOption->GetType() == PDFOBJ_ARRAY) {
+ pOption = ((CPDF_Array*)pOption)->GetElementValue(sub_index);
+ }
+ if (pOption == NULL || pOption->GetType() != PDFOBJ_STRING) {
+ return CFX_WideString();
+ }
+ return ((CPDF_String*)pOption)->GetUnicodeText();
+}
+CFX_WideString CPDF_FormField::GetOptionLabel(int index)
+{
+ return GetOptionText(index, 1);
+}
+CFX_WideString CPDF_FormField::GetOptionValue(int index)
+{
+ return GetOptionText(index, 0);
+}
+int CPDF_FormField::FindOption(CFX_WideString csOptLabel)
+{
+ int iCount = CountOptions();
+ for (int i = 0; i < iCount; i ++) {
+ CFX_WideString csValue = GetOptionValue(i);
+ if (csValue == csOptLabel) {
+ return i;
+ }
+ }
+ return -1;
+}
+int CPDF_FormField::FindOptionValue(FX_LPCWSTR csOptValue, int iStartIndex)
+{
+ if (iStartIndex < 0) {
+ iStartIndex = 0;
+ }
+ int iCount = CountOptions();
+ for (; iStartIndex < iCount; iStartIndex ++) {
+ CFX_WideString csValue = GetOptionValue(iStartIndex);
+ if (csValue == csOptValue) {
+ return iStartIndex;
+ }
+ }
+ return -1;
+}
+FX_BOOL CPDF_FormField::CheckControl(int iControlIndex, FX_BOOL bChecked, FX_BOOL bNotify)
+{
+ ASSERT(GetType() == CheckBox || GetType() == RadioButton);
+ CPDF_FormControl* pControl = GetControl(iControlIndex);
+ if (pControl == NULL) {
+ return FALSE;
+ }
+ if (!bChecked && pControl->IsChecked() == bChecked) {
+ return FALSE;
+ }
+ CFX_ByteArray statusArray;
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ SaveCheckedFieldStatus(this, statusArray);
+ }
+ CFX_WideString csWExport = pControl->GetExportValue();
+ CFX_ByteString csBExport = PDF_EncodeText(csWExport);
+ int iCount = CountControls();
+ FX_BOOL bUnison = PDF_FormField_IsUnison(this);
+ for (int i = 0; i < iCount; i ++) {
+ CPDF_FormControl* pCtrl = GetControl(i);
+ if (bUnison) {
+ CFX_WideString csEValue = pCtrl->GetExportValue();
+ if (csEValue == csWExport) {
+ if (pCtrl->GetOnStateName() == pControl->GetOnStateName()) {
+ pCtrl->CheckControl(bChecked);
+ } else if (bChecked) {
+ pCtrl->CheckControl(FALSE);
+ }
+ } else if (bChecked) {
+ pCtrl->CheckControl(FALSE);
+ }
+ } else {
+ if (i == iControlIndex) {
+ pCtrl->CheckControl(bChecked);
+ } else if (bChecked) {
+ pCtrl->CheckControl(FALSE);
+ }
+ }
+ }
+ CPDF_Object* pOpt = FPDF_GetFieldAttr(m_pDict, "Opt");
+ if (pOpt == NULL || pOpt->GetType() != PDFOBJ_ARRAY) {
+ if (bChecked) {
+ m_pDict->SetAtName("V", csBExport);
+ } else {
+ CFX_ByteString csV;
+ CPDF_Object* pV = FPDF_GetFieldAttr(m_pDict, "V");
+ if (pV != NULL) {
+ csV = pV->GetString();
+ }
+ if (csV == csBExport) {
+ m_pDict->SetAtName("V", "Off");
+ }
+ }
+ } else if (bChecked) {
+ CFX_ByteString csIndex;
+ csIndex.Format("%d", iControlIndex);
+ m_pDict->SetAtName("V", csIndex);
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
+ }
+ m_pForm->m_bUpdated = TRUE;
+ return TRUE;
+}
+CFX_WideString CPDF_FormField::GetCheckValue(FX_BOOL bDefault)
+{
+ ASSERT(GetType() == CheckBox || GetType() == RadioButton);
+ CFX_WideString csExport = L"Off";
+ FX_BOOL bChecked;
+ int iCount = CountControls();
+ for (int i = 0; i < iCount; i ++) {
+ CPDF_FormControl* pControl = GetControl(i);
+ if (bDefault) {
+ bChecked = pControl->IsDefaultChecked();
+ } else {
+ bChecked = pControl->IsChecked();
+ }
+ if (bChecked) {
+ csExport = pControl->GetExportValue();
+ break;
+ }
+ }
+ return csExport;
+}
+FX_BOOL CPDF_FormField::SetCheckValue(const CFX_WideString& value, FX_BOOL bDefault, FX_BOOL bNotify)
+{
+ ASSERT(GetType() == CheckBox || GetType() == RadioButton);
+ CFX_ByteArray statusArray;
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ SaveCheckedFieldStatus(this, statusArray);
+ }
+ int iCount = CountControls();
+ for (int i = 0; i < iCount; i ++) {
+ CPDF_FormControl* pControl = GetControl(i);
+ CFX_WideString csExport = pControl->GetExportValue();
+ if (csExport == value) {
+ if (bDefault) {
+ } else {
+ CheckControl(GetControlIndex(pControl), TRUE);
+ }
+ break;
+ } else {
+ if (bDefault) {
+ } else {
+ CheckControl(GetControlIndex(pControl), FALSE);
+ }
+ }
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ m_pForm->m_pFormNotify->AfterCheckedStatusChange(this, statusArray);
+ }
+ m_pForm->m_bUpdated = TRUE;
+ return TRUE;
+}
+int CPDF_FormField::GetTopVisibleIndex()
+{
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "TI");
+ if (pObj == NULL) {
+ return 0;
+ }
+ return pObj->GetInteger();
+}
+int CPDF_FormField::CountSelectedOptions()
+{
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
+ if (pObj == NULL) {
+ return 0;
+ }
+ CPDF_Array* pArray = pObj->GetArray();
+ if (pArray == NULL) {
+ return 0;
+ }
+ return (int)pArray->GetCount();
+}
+int CPDF_FormField::GetSelectedOptionIndex(int index)
+{
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
+ if (pObj == NULL) {
+ return -1;
+ }
+ CPDF_Array* pArray = pObj->GetArray();
+ if (pArray == NULL) {
+ return -1;
+ }
+ int iCount = (int)pArray->GetCount();
+ if (iCount > 0 && index < iCount) {
+ return pArray->GetInteger(index);
+ }
+ return -1;
+}
+FX_BOOL CPDF_FormField::IsOptionSelected(int iOptIndex)
+{
+ CPDF_Object* pObj = FPDF_GetFieldAttr(m_pDict, "I");
+ if (pObj == NULL) {
+ return FALSE;
+ }
+ CPDF_Array* pArray = pObj->GetArray();
+ if (pArray == NULL) {
+ return FALSE;
+ }
+ int iCount = (int)pArray->GetCount();
+ for (int i = 0; i < iCount; i ++) {
+ if (pArray->GetInteger(i) == iOptIndex) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_FormField::SelectOption(int iOptIndex, FX_BOOL bSelected, FX_BOOL bNotify)
+{
+ CPDF_Array* pArray = m_pDict->GetArray("I");
+ if (pArray == NULL) {
+ if (!bSelected) {
+ return TRUE;
+ }
+ pArray = CPDF_Array::Create();
+ if (pArray == NULL) {
+ return FALSE;
+ }
+ m_pDict->SetAt("I", pArray);
+ }
+ FX_BOOL bReturn = FALSE;
+ for (int i = 0; i < (int)pArray->GetCount(); i ++) {
+ int iFind = pArray->GetInteger(i);
+ if (iFind == iOptIndex) {
+ if (bSelected) {
+ return TRUE;
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ int iRet = 0;
+ CFX_WideString csValue = GetOptionLabel(iOptIndex);
+ if (GetType() == ListBox) {
+ iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
+ }
+ if (GetType() == ComboBox) {
+ iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
+ }
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ pArray->RemoveAt(i);
+ bReturn = TRUE;
+ break;
+ } else if (iFind > iOptIndex) {
+ if (!bSelected) {
+ continue;
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ int iRet = 0;
+ CFX_WideString csValue = GetOptionLabel(iOptIndex);
+ if (GetType() == ListBox) {
+ iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
+ }
+ if (GetType() == ComboBox) {
+ iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
+ }
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ CPDF_Number* pNum = CPDF_Number::Create(iOptIndex);
+ if (pNum == NULL) {
+ return FALSE;
+ }
+ pArray->InsertAt(i, pNum);
+ bReturn = TRUE;
+ break;
+ }
+ }
+ if (!bReturn) {
+ if (bSelected) {
+ pArray->AddInteger(iOptIndex);
+ }
+ if (pArray->GetCount() == 0) {
+ m_pDict->RemoveAt("I");
+ }
+ }
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ if (GetType() == ListBox) {
+ m_pForm->m_pFormNotify->AfterSelectionChange(this);
+ }
+ if (GetType() == ComboBox) {
+ m_pForm->m_pFormNotify->AfterValueChange(this);
+ }
+ }
+ m_pForm->m_bUpdated = TRUE;
+ return TRUE;
+}
+FX_BOOL CPDF_FormField::ClearSelectedOptions(FX_BOOL bNotify)
+{
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ int iRet = 0;
+ CFX_WideString csValue;
+ int iIndex = GetSelectedIndex(0);
+ if (iIndex >= 0) {
+ csValue = GetOptionLabel(iIndex);
+ }
+ if (GetType() == ListBox) {
+ iRet = m_pForm->m_pFormNotify->BeforeSelectionChange(this, csValue);
+ }
+ if (GetType() == ComboBox) {
+ iRet = m_pForm->m_pFormNotify->BeforeValueChange(this, csValue);
+ }
+ if (iRet < 0) {
+ return FALSE;
+ }
+ }
+ m_pDict->RemoveAt("I");
+ if (bNotify && m_pForm->m_pFormNotify != NULL) {
+ if (GetType() == ListBox) {
+ m_pForm->m_pFormNotify->AfterSelectionChange(this);
+ }
+ if (GetType() == ComboBox) {
+ m_pForm->m_pFormNotify->AfterValueChange(this);
+ }
+ }
+ m_pForm->m_bUpdated = TRUE;
+ return TRUE;
+}
+void CPDF_FormField::LoadDA()
+{
+ CFX_ByteString DA = FPDF_GetFieldAttr(m_pDict, "DA")->GetString();
+ if (DA.IsEmpty()) {
+ DA = m_pForm->m_pFormDict->GetString("DA");
+ }
+ if (DA.IsEmpty()) {
+ return;
+ }
+ CPDF_SimpleParser syntax(DA);
+ syntax.FindTagParam("Tf", 2);
+ CFX_ByteString font_name = syntax.GetWord();
+ CPDF_Dictionary* pFontDict = m_pForm->m_pFormDict->GetDict("DR")->GetDict("Font")->GetDict(font_name);
+ if (pFontDict == NULL) {
+ return;
+ }
+ m_pFont = m_pForm->m_pDocument->LoadFont(pFontDict);
+ m_FontSize = FX_atof(syntax.GetWord());
+}
diff --git a/core/src/fpdfdoc/doc_link.cpp b/core/src/fpdfdoc/doc_link.cpp new file mode 100644 index 0000000000..4c8fda7a34 --- /dev/null +++ b/core/src/fpdfdoc/doc_link.cpp @@ -0,0 +1,105 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+CPDF_LinkList::~CPDF_LinkList()
+{
+ FX_POSITION pos = m_PageMap.GetStartPosition();
+ while (pos) {
+ FX_LPVOID key, value;
+ m_PageMap.GetNextAssoc(pos, key, value);
+ delete (CFX_PtrArray*)value;
+ }
+}
+CFX_PtrArray* CPDF_LinkList::GetPageLinks(CPDF_Page* pPage)
+{
+ FX_DWORD objnum = pPage->m_pFormDict->GetObjNum();
+ if (objnum == 0) {
+ return NULL;
+ }
+ CFX_PtrArray* pPageLinkList = NULL;
+ if (!m_PageMap.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, (FX_LPVOID&)pPageLinkList)) {
+ pPageLinkList = FX_NEW CFX_PtrArray;
+ if (pPageLinkList == NULL) {
+ return NULL;
+ }
+ m_PageMap.SetAt((FX_LPVOID)(FX_UINTPTR)objnum, pPageLinkList);
+ LoadPageLinks(pPage, pPageLinkList);
+ }
+ return pPageLinkList;
+}
+int CPDF_LinkList::CountLinks(CPDF_Page* pPage)
+{
+ CFX_PtrArray* pPageLinkList = GetPageLinks(pPage);
+ if (pPageLinkList == NULL) {
+ return 0;
+ }
+ return pPageLinkList->GetSize();
+}
+CPDF_Link CPDF_LinkList::GetLink(CPDF_Page* pPage, int index)
+{
+ CFX_PtrArray* pPageLinkList = GetPageLinks(pPage);
+ if (pPageLinkList == NULL) {
+ return NULL;
+ }
+ return (CPDF_Dictionary*)pPageLinkList->GetAt(index);
+}
+CPDF_Link CPDF_LinkList::GetLinkAtPoint(CPDF_Page* pPage, FX_FLOAT pdf_x, FX_FLOAT pdf_y)
+{
+ CFX_PtrArray* pPageLinkList = GetPageLinks(pPage);
+ if (pPageLinkList == NULL) {
+ return NULL;
+ }
+ int size = pPageLinkList->GetSize();
+ for (int i = 0; i < size; i ++) {
+ CPDF_Link Link = (CPDF_Dictionary*)pPageLinkList->GetAt(i);
+ CPDF_Rect rect = Link.GetRect();
+ if (rect.Contains(pdf_x, pdf_y)) {
+ return Link;
+ }
+ }
+ return NULL;
+}
+void CPDF_LinkList::LoadPageLinks(CPDF_Page* pPage, CFX_PtrArray* pList)
+{
+ CPDF_Array* pAnnotList = pPage->m_pFormDict->GetArray("Annots");
+ if (pAnnotList == NULL) {
+ return;
+ }
+ for (FX_DWORD i = 0; i < pAnnotList->GetCount(); i ++) {
+ CPDF_Dictionary* pAnnot = pAnnotList->GetDict(i);
+ if (pAnnot == NULL) {
+ continue;
+ }
+ if (pAnnot->GetString("Subtype") != "Link") {
+ continue;
+ }
+ pList->Add(pAnnot);
+ }
+}
+CPDF_Rect CPDF_Link::GetRect()
+{
+ return m_pDict->GetRect("Rect");
+}
+CPDF_Dest CPDF_Link::GetDest(CPDF_Document* pDoc)
+{
+ CPDF_Object* pDest = m_pDict->GetElementValue("Dest");
+ if (pDest == NULL) {
+ return NULL;
+ }
+ if (pDest->GetType() == PDFOBJ_STRING || pDest->GetType() == PDFOBJ_NAME) {
+ CPDF_NameTree name_tree(pDoc, FX_BSTRC("Dests"));
+ CFX_ByteStringC name = pDest->GetString();
+ return name_tree.LookupNamedDest(pDoc, name);
+ } else if (pDest->GetType() == PDFOBJ_ARRAY) {
+ return (CPDF_Array*)pDest;
+ }
+ return NULL;
+}
+CPDF_Action CPDF_Link::GetAction()
+{
+ return m_pDict->GetDict("A");
+}
diff --git a/core/src/fpdfdoc/doc_metadata.cpp b/core/src/fpdfdoc/doc_metadata.cpp new file mode 100644 index 0000000000..e3ac9e3779 --- /dev/null +++ b/core/src/fpdfdoc/doc_metadata.cpp @@ -0,0 +1,152 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+#include "../../include/fxcrt/fx_xml.h"
+typedef struct _PDFDOC_METADATA {
+ CPDF_Document *m_pDoc;
+ CXML_Element *m_pXmlElmnt;
+ CXML_Element *m_pElmntRdf;
+ CFX_CMapByteStringToPtr *m_pStringMap;
+} PDFDOC_METADATA, * PDFDOC_LPMETADATA;
+typedef PDFDOC_METADATA const * PDFDOC_LPCMETADATA;
+const FX_LPCSTR gs_FPDFDOC_Metadata_Titles[] = {
+ "Title", "title",
+ "Subject", "description",
+ "Author", "creator",
+ "Keywords", "Keywords",
+ "Producer", "Producer",
+ "Creator", "CreatorTool",
+ "CreationDate", "CreateDate",
+ "ModDate", "ModifyDate",
+ "MetadataDate", "MetadataDate"
+};
+CPDF_Metadata::CPDF_Metadata()
+{
+ m_pData = FX_Alloc(PDFDOC_METADATA, 1);
+ FXSYS_memset32(m_pData, 0, sizeof(PDFDOC_METADATA));
+ CFX_CMapByteStringToPtr *&pStringMap = ((PDFDOC_LPMETADATA)m_pData)->m_pStringMap;
+ pStringMap = FX_NEW(CFX_CMapByteStringToPtr);
+ if (pStringMap != NULL) {
+ CFX_ByteString bstr;
+ for (int i = 0; i < 18; i += 2) {
+ bstr = gs_FPDFDOC_Metadata_Titles[i];
+ pStringMap->AddValue(bstr, (void*)gs_FPDFDOC_Metadata_Titles[i + 1]);
+ }
+ }
+}
+CPDF_Metadata::~CPDF_Metadata()
+{
+ FXSYS_assert(m_pData != NULL);
+ CXML_Element *&p = ((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt;
+ if (p) {
+ delete p;
+ }
+ CFX_CMapByteStringToPtr *pStringMap = ((PDFDOC_LPMETADATA)m_pData)->m_pStringMap;
+ if (pStringMap) {
+ pStringMap->RemoveAll();
+ FX_Free(pStringMap);
+ }
+ FX_Free(m_pData);
+}
+void CPDF_Metadata::LoadDoc(CPDF_Document *pDoc)
+{
+ FXSYS_assert(pDoc != NULL);
+ ((PDFDOC_LPMETADATA)m_pData)->m_pDoc = pDoc;
+ CPDF_Dictionary *pRoot = pDoc->GetRoot();
+ CPDF_Stream *pStream = pRoot->GetStream(FX_BSTRC("Metadata"));
+ if (!pStream) {
+ return;
+ }
+ CPDF_StreamAcc acc;
+ acc.LoadAllData(pStream, FALSE);
+ int size = acc.GetSize();
+ FX_LPCBYTE pBuf = acc.GetData();
+ CXML_Element *&pXmlElmnt = ((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt;
+ pXmlElmnt = CXML_Element::Parse(pBuf, size);
+ if (!pXmlElmnt) {
+ return;
+ }
+ CXML_Element *&pElmntRdf = ((PDFDOC_LPMETADATA)m_pData)->m_pElmntRdf;
+ if (pXmlElmnt->GetTagName() == FX_BSTRC("RDF")) {
+ pElmntRdf = pXmlElmnt;
+ } else {
+ pElmntRdf = pXmlElmnt->GetElement(NULL, FX_BSTRC("RDF"));
+ }
+}
+FX_INT32 CPDF_Metadata::GetString(FX_BSTR bsItem, CFX_WideString &wsStr)
+{
+ if (!((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt) {
+ return -1;
+ }
+ if (!((PDFDOC_LPMETADATA)m_pData)->m_pStringMap) {
+ return -1;
+ }
+ void *szTag;
+ if (!((PDFDOC_LPMETADATA)m_pData)->m_pStringMap->Lookup(bsItem, szTag)) {
+ return -1;
+ }
+ CFX_ByteString bsTag = (FX_LPCSTR)szTag;
+ wsStr = L"";
+ CXML_Element *pElmntRdf = ((PDFDOC_LPMETADATA)m_pData)->m_pElmntRdf;
+ if (!pElmntRdf) {
+ return -1;
+ }
+ int nChild = pElmntRdf->CountChildren();
+ for (int i = 0; i < nChild; i++) {
+ CXML_Element *pTag = pElmntRdf->GetElement(NULL, FX_BSTRC("Description"), i);
+ if (!pTag) {
+ continue;
+ }
+ if (bsItem == FX_BSTRC("Title") || bsItem == FX_BSTRC("Subject")) {
+ CXML_Element *pElmnt = pTag->GetElement(NULL, bsTag);
+ if (!pElmnt) {
+ continue;
+ }
+ pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("Alt"));
+ if (!pElmnt) {
+ continue;
+ }
+ pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("li"));
+ if (!pElmnt) {
+ continue;
+ }
+ wsStr = pElmnt->GetContent(0);
+ return wsStr.GetLength();
+ } else if (bsItem == FX_BSTRC("Author")) {
+ CXML_Element *pElmnt = pTag->GetElement(NULL, bsTag);
+ if (!pElmnt) {
+ continue;
+ }
+ pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("Seq"));
+ if (!pElmnt) {
+ continue;
+ }
+ pElmnt = pElmnt->GetElement(NULL, FX_BSTRC("li"));
+ if (!pElmnt) {
+ continue;
+ }
+ wsStr = pElmnt->GetContent(0);
+ return wsStr.GetLength();
+ } else {
+ CXML_Element *pElmnt = pTag->GetElement(NULL, bsTag);
+ if (!pElmnt) {
+ continue;
+ }
+ wsStr = pElmnt->GetContent(0);
+ return wsStr.GetLength();
+ }
+ }
+ return -1;
+}
+CXML_Element* CPDF_Metadata::GetRoot() const
+{
+ return ((PDFDOC_LPMETADATA)m_pData)->m_pXmlElmnt;
+}
+CXML_Element* CPDF_Metadata::GetRDF() const
+{
+ return ((PDFDOC_LPMETADATA)m_pData)->m_pElmntRdf;
+}
diff --git a/core/src/fpdfdoc/doc_ocg.cpp b/core/src/fpdfdoc/doc_ocg.cpp new file mode 100644 index 0000000000..39b8e37521 --- /dev/null +++ b/core/src/fpdfdoc/doc_ocg.cpp @@ -0,0 +1,300 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+static FX_INT32 FPDFDOC_OCG_FindGroup(const CPDF_Object *pObject, const CPDF_Dictionary *pGroupDict)
+{
+ if (pObject == NULL || pGroupDict == NULL) {
+ return -1;
+ }
+ FX_INT32 iType = pObject->GetType();
+ if (iType == PDFOBJ_ARRAY) {
+ FX_DWORD dwCount = ((CPDF_Array*)pObject)->GetCount();
+ for (FX_DWORD i = 0; i < dwCount; i++) {
+ if (((CPDF_Array*)pObject)->GetDict(i) == pGroupDict) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ if (pObject->GetDict() == pGroupDict) {
+ return 0;
+ }
+ return -1;
+}
+static FX_BOOL FPDFDOC_OCG_HasIntent(const CPDF_Dictionary *pDict, FX_BSTR csElement, FX_BSTR csDef = FX_BSTRC(""))
+{
+ FXSYS_assert(pDict != NULL);
+ CPDF_Object *pIntent = pDict->GetElementValue(FX_BSTRC("Intent"));
+ if (pIntent == NULL) {
+ return csElement == csDef;
+ }
+ CFX_ByteString bsIntent;
+ if (pIntent->GetType() == PDFOBJ_ARRAY) {
+ FX_DWORD dwCount = ((CPDF_Array*)pIntent)->GetCount();
+ for (FX_DWORD i = 0; i < dwCount; i++) {
+ bsIntent = ((CPDF_Array*)pIntent)->GetString(i);
+ if (bsIntent == FX_BSTRC("All") || bsIntent == csElement) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+ }
+ bsIntent = pIntent->GetString();
+ return bsIntent == FX_BSTRC("All") || bsIntent == csElement;
+}
+static CPDF_Dictionary* FPDFDOC_OCG_GetConfig(CPDF_Document *pDoc, const CPDF_Dictionary *pOCGDict, FX_BSTR bsState)
+{
+ FXSYS_assert(pDoc && pOCGDict);
+ CPDF_Dictionary *pOCProperties = pDoc->GetRoot()->GetDict(FX_BSTRC("OCProperties"));
+ if (!pOCProperties) {
+ return NULL;
+ }
+ CPDF_Array *pOCGs = pOCProperties->GetArray(FX_BSTRC("OCGs"));
+ if (!pOCGs) {
+ return NULL;
+ }
+ if (FPDFDOC_OCG_FindGroup(pOCGs, pOCGDict) < 0) {
+ return NULL;
+ }
+ CPDF_Dictionary *pConfig = pOCProperties->GetDict(FX_BSTRC("D"));
+ CPDF_Array *pConfigs = pOCProperties->GetArray(FX_BSTRC("Configs"));
+ if (pConfigs) {
+ CPDF_Dictionary *pFind;
+ FX_INT32 iCount = pConfigs->GetCount();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ pFind = pConfigs->GetDict(i);
+ if (!pFind) {
+ continue;
+ }
+ if (!FPDFDOC_OCG_HasIntent(pFind, FX_BSTRC("View"), FX_BSTRC("View"))) {
+ continue;
+ }
+ pConfig = pFind;
+ break;
+ }
+ }
+ return pConfig;
+}
+static CFX_ByteString FPDFDOC_OCG_GetUsageTypeString(CPDF_OCContext::UsageType eType)
+{
+ CFX_ByteString csState = FX_BSTRC("View");
+ if (eType == CPDF_OCContext::Design) {
+ csState = FX_BSTRC("Design");
+ } else if (eType == CPDF_OCContext::Print) {
+ csState = FX_BSTRC("Print");
+ } else if (eType == CPDF_OCContext::Export) {
+ csState = FX_BSTRC("Export");
+ }
+ return csState;
+}
+CPDF_OCContext::CPDF_OCContext(CPDF_Document *pDoc, UsageType eUsageType)
+{
+ FXSYS_assert(pDoc != NULL);
+ m_pDocument = pDoc;
+ m_eUsageType = eUsageType;
+}
+CPDF_OCContext::~CPDF_OCContext()
+{
+ m_OCGStates.RemoveAll();
+}
+FX_BOOL CPDF_OCContext::LoadOCGStateFromConfig(FX_BSTR csConfig, const CPDF_Dictionary *pOCGDict, FX_BOOL &bValidConfig) const
+{
+ CPDF_Dictionary *pConfig = FPDFDOC_OCG_GetConfig(m_pDocument, pOCGDict, csConfig);
+ if (!pConfig) {
+ return TRUE;
+ }
+ bValidConfig = TRUE;
+ FX_BOOL bState = pConfig->GetString(FX_BSTRC("BaseState"), FX_BSTRC("ON")) != FX_BSTRC("OFF");
+ CPDF_Array *pArray = pConfig->GetArray(FX_BSTRC("ON"));
+ if (pArray) {
+ if (FPDFDOC_OCG_FindGroup(pArray, pOCGDict) >= 0) {
+ bState = TRUE;
+ }
+ }
+ pArray = pConfig->GetArray(FX_BSTRC("OFF"));
+ if (pArray) {
+ if (FPDFDOC_OCG_FindGroup(pArray, pOCGDict) >= 0) {
+ bState = FALSE;
+ }
+ }
+ pArray = pConfig->GetArray(FX_BSTRC("AS"));
+ if (pArray) {
+ CFX_ByteString csFind = csConfig + FX_BSTRC("State");
+ FX_INT32 iCount = pArray->GetCount();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ CPDF_Dictionary *pUsage = pArray->GetDict(i);
+ if (!pUsage) {
+ continue;
+ }
+ if (pUsage->GetString(FX_BSTRC("Event"), FX_BSTRC("View")) != csConfig) {
+ continue;
+ }
+ CPDF_Array *pOCGs = pUsage->GetArray(FX_BSTRC("OCGs"));
+ if (!pOCGs) {
+ continue;
+ }
+ if (FPDFDOC_OCG_FindGroup(pOCGs, pOCGDict) < 0) {
+ continue;
+ }
+ CPDF_Dictionary *pState = pUsage->GetDict(csConfig);
+ if (!pState) {
+ continue;
+ }
+ bState = pState->GetString(csFind) != FX_BSTRC("OFF");
+ }
+ }
+ return bState;
+}
+FX_BOOL CPDF_OCContext::LoadOCGState(const CPDF_Dictionary *pOCGDict) const
+{
+ if (!FPDFDOC_OCG_HasIntent(pOCGDict, FX_BSTRC("View"), FX_BSTRC("View"))) {
+ return TRUE;
+ }
+ CFX_ByteString csState = FPDFDOC_OCG_GetUsageTypeString(m_eUsageType);
+ CPDF_Dictionary *pUsage = pOCGDict->GetDict(FX_BSTRC("Usage"));
+ if (pUsage) {
+ CPDF_Dictionary *pState = pUsage->GetDict(csState);
+ if (pState) {
+ CFX_ByteString csFind = csState + FX_BSTRC("State");
+ if (pState->KeyExist(csFind)) {
+ return pState->GetString(csFind) != FX_BSTRC("OFF");
+ }
+ }
+ if (csState != FX_BSTRC("View")) {
+ pState = pUsage->GetDict(FX_BSTRC("View"));
+ if (pState && pState->KeyExist(FX_BSTRC("ViewState"))) {
+ return pState->GetString(FX_BSTRC("ViewState")) != FX_BSTRC("OFF");
+ }
+ }
+ }
+ FX_BOOL bDefValid = FALSE;
+ return LoadOCGStateFromConfig(csState, pOCGDict, bDefValid);
+}
+FX_BOOL CPDF_OCContext::GetOCGVisible(const CPDF_Dictionary *pOCGDict)
+{
+ if (!pOCGDict) {
+ return FALSE;
+ }
+ FX_LPVOID bState = NULL;
+ if (m_OCGStates.Lookup(pOCGDict, bState)) {
+ return (FX_UINTPTR)bState != 0;
+ }
+ bState = (FX_LPVOID)(FX_UINTPTR)LoadOCGState(pOCGDict);
+ m_OCGStates.SetAt(pOCGDict, bState);
+ return (FX_UINTPTR)bState != 0;
+}
+FX_BOOL CPDF_OCContext::GetOCGVE(CPDF_Array *pExpression, FX_BOOL bFromConfig, int nLevel)
+{
+ if (nLevel > 32) {
+ return FALSE;
+ }
+ if (pExpression == NULL) {
+ return FALSE;
+ }
+ FX_INT32 iCount = pExpression->GetCount();
+ CPDF_Object *pOCGObj;
+ CFX_ByteString csOperator = pExpression->GetString(0);
+ if (csOperator == FX_BSTRC("Not")) {
+ pOCGObj = pExpression->GetElementValue(1);
+ if (pOCGObj == NULL) {
+ return FALSE;
+ }
+ if (pOCGObj->GetType() == PDFOBJ_DICTIONARY) {
+ return !(bFromConfig ? LoadOCGState((CPDF_Dictionary*)pOCGObj) : GetOCGVisible((CPDF_Dictionary*)pOCGObj));
+ } else if (pOCGObj->GetType() == PDFOBJ_ARRAY) {
+ return !GetOCGVE((CPDF_Array*)pOCGObj, bFromConfig, nLevel + 1);
+ } else {
+ return FALSE;
+ }
+ }
+ if (csOperator == FX_BSTRC("Or") || csOperator == FX_BSTRC("And")) {
+ FX_BOOL bValue = FALSE;
+ for (FX_INT32 i = 1; i < iCount; i ++) {
+ pOCGObj = pExpression->GetElementValue(1);
+ if (pOCGObj == NULL) {
+ continue;
+ }
+ FX_BOOL bItem = FALSE;
+ if (pOCGObj->GetType() == PDFOBJ_DICTIONARY) {
+ bItem = bFromConfig ? LoadOCGState((CPDF_Dictionary*)pOCGObj) : GetOCGVisible((CPDF_Dictionary*)pOCGObj);
+ } else if (pOCGObj->GetType() == PDFOBJ_ARRAY) {
+ bItem = GetOCGVE((CPDF_Array*)pOCGObj, bFromConfig, nLevel + 1);
+ }
+ if (i == 1) {
+ bValue = bItem;
+ } else {
+ if (csOperator == FX_BSTRC("Or")) {
+ bValue = bValue || bItem;
+ } else {
+ bValue = bValue && bItem;
+ }
+ }
+ }
+ return bValue;
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_OCContext::LoadOCMDState(const CPDF_Dictionary *pOCMDDict, FX_BOOL bFromConfig)
+{
+ FXSYS_assert(pOCMDDict != NULL);
+ CPDF_Array *pVE = pOCMDDict->GetArray(FX_BSTRC("VE"));
+ if (pVE != NULL) {
+ return GetOCGVE(pVE, bFromConfig);
+ }
+ CFX_ByteString csP = pOCMDDict->GetString(FX_BSTRC("P"), FX_BSTRC("AnyOn"));
+ CPDF_Object *pOCGObj = pOCMDDict->GetElementValue(FX_BSTRC("OCGs"));
+ if (pOCGObj == NULL) {
+ return TRUE;
+ }
+ if (pOCGObj->GetType() == PDFOBJ_DICTIONARY) {
+ return bFromConfig ? LoadOCGState((CPDF_Dictionary*)pOCGObj) : GetOCGVisible((CPDF_Dictionary*)pOCGObj);
+ }
+ if (pOCGObj->GetType() != PDFOBJ_ARRAY) {
+ return TRUE;
+ }
+ FX_BOOL bState = FALSE;
+ if (csP == FX_BSTRC("AllOn") || csP == FX_BSTRC("AllOff")) {
+ bState = TRUE;
+ }
+ FX_INT32 iCount = ((CPDF_Array*)pOCGObj)->GetCount();
+ for (FX_INT32 i = 0; i < iCount; i ++) {
+ FX_BOOL bItem = TRUE;
+ CPDF_Dictionary* pItemDict = ((CPDF_Array*)pOCGObj)->GetDict(i);
+ if (pItemDict) {
+ bItem = bFromConfig ? LoadOCGState(pItemDict) : GetOCGVisible(pItemDict);
+ }
+ if (csP == FX_BSTRC("AnyOn") && bItem) {
+ return TRUE;
+ }
+ if (csP == FX_BSTRC("AnyOff") && !bItem) {
+ return TRUE;
+ }
+ if (csP == FX_BSTRC("AllOn") && !bItem) {
+ return FALSE;
+ }
+ if (csP == FX_BSTRC("AllOff") && bItem) {
+ return FALSE;
+ }
+ }
+ return bState;
+}
+FX_BOOL CPDF_OCContext::CheckOCGVisible(const CPDF_Dictionary *pOCGDict)
+{
+ if (pOCGDict == NULL) {
+ return TRUE;
+ }
+ CFX_ByteString csType = pOCGDict->GetString(FX_BSTRC("Type"), FX_BSTRC("OCG"));
+ if (csType == FX_BSTRC("OCG")) {
+ return GetOCGVisible(pOCGDict);
+ } else {
+ return LoadOCMDState(pOCGDict, FALSE);
+ }
+}
+void CPDF_OCContext::ResetOCContext()
+{
+ m_OCGStates.RemoveAll();
+}
diff --git a/core/src/fpdfdoc/doc_tagged.cpp b/core/src/fpdfdoc/doc_tagged.cpp new file mode 100644 index 0000000000..95ae8d581e --- /dev/null +++ b/core/src/fpdfdoc/doc_tagged.cpp @@ -0,0 +1,448 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfapi/fpdf_parser.h"
+#include "../../include/fpdfapi/fpdf_page.h"
+#include "../../include/fpdfdoc/fpdf_tagged.h"
+#include "tagged_int.h"
+const int nMaxRecursion = 32;
+static FX_BOOL IsTagged(const CPDF_Document* pDoc)
+{
+ CPDF_Dictionary* pCatalog = pDoc->GetRoot();
+ CPDF_Dictionary* pMarkInfo = pCatalog->GetDict(FX_BSTRC("MarkInfo"));
+ return pMarkInfo != NULL && pMarkInfo->GetInteger(FX_BSTRC("Marked"));
+}
+CPDF_StructTree* CPDF_StructTree::LoadPage(const CPDF_Document* pDoc, const CPDF_Dictionary* pPageDict)
+{
+ if (!IsTagged(pDoc)) {
+ return NULL;
+ }
+ CPDF_StructTreeImpl* pTree = FX_NEW CPDF_StructTreeImpl(pDoc);
+ if (pTree == NULL) {
+ return NULL;
+ }
+ pTree->LoadPageTree(pPageDict);
+ return pTree;
+}
+CPDF_StructTree* CPDF_StructTree::LoadDoc(const CPDF_Document* pDoc)
+{
+ if (!IsTagged(pDoc)) {
+ return NULL;
+ }
+ CPDF_StructTreeImpl* pTree = FX_NEW CPDF_StructTreeImpl(pDoc);
+ if (pTree == NULL) {
+ return NULL;
+ }
+ pTree->LoadDocTree();
+ return pTree;
+}
+CPDF_StructTreeImpl::CPDF_StructTreeImpl(const CPDF_Document* pDoc)
+{
+ CPDF_Dictionary* pCatalog = pDoc->GetRoot();
+ m_pTreeRoot = pCatalog->GetDict(FX_BSTRC("StructTreeRoot"));
+ if (m_pTreeRoot == NULL) {
+ return;
+ }
+ m_pRoleMap = m_pTreeRoot->GetDict(FX_BSTRC("RoleMap"));
+}
+CPDF_StructTreeImpl::~CPDF_StructTreeImpl()
+{
+ for (int i = 0; i < m_Kids.GetSize(); i ++)
+ if (m_Kids[i]) {
+ m_Kids[i]->Release();
+ }
+}
+void CPDF_StructTreeImpl::LoadDocTree()
+{
+ m_pPage = NULL;
+ if (m_pTreeRoot == NULL) {
+ return;
+ }
+ CPDF_Object* pKids = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
+ if (pKids == NULL) {
+ return;
+ }
+ if (pKids->GetType() == PDFOBJ_DICTIONARY) {
+ CPDF_StructElementImpl* pStructElementImpl = FX_NEW CPDF_StructElementImpl(this, NULL, (CPDF_Dictionary*)pKids);
+ if (pStructElementImpl == NULL) {
+ return;
+ }
+ m_Kids.Add(pStructElementImpl);
+ return;
+ }
+ if (pKids->GetType() != PDFOBJ_ARRAY) {
+ return;
+ }
+ CPDF_Array* pArray = (CPDF_Array*)pKids;
+ for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
+ CPDF_Dictionary* pKid = pArray->GetDict(i);
+ CPDF_StructElementImpl* pStructElementImpl = FX_NEW CPDF_StructElementImpl(this, NULL, pKid);
+ if (pStructElementImpl == NULL) {
+ return;
+ }
+ m_Kids.Add(pStructElementImpl);
+ }
+}
+void CPDF_StructTreeImpl::LoadPageTree(const CPDF_Dictionary* pPageDict)
+{
+ m_pPage = pPageDict;
+ if (m_pTreeRoot == NULL) {
+ return;
+ }
+ CPDF_Object* pKids = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
+ if (pKids == NULL) {
+ return;
+ }
+ FX_DWORD dwKids = 0;
+ if (pKids->GetType() == PDFOBJ_DICTIONARY) {
+ dwKids = 1;
+ } else if (pKids->GetType() == PDFOBJ_ARRAY) {
+ dwKids = ((CPDF_Array*)pKids)->GetCount();
+ } else {
+ return;
+ }
+ FX_DWORD i;
+ m_Kids.SetSize(dwKids);
+ for (i = 0; i < dwKids; i ++) {
+ m_Kids[i] = NULL;
+ }
+ CFX_MapPtrToPtr element_map;
+ CPDF_Dictionary* pParentTree = m_pTreeRoot->GetDict(FX_BSTRC("ParentTree"));
+ if (pParentTree == NULL) {
+ return;
+ }
+ CPDF_NumberTree parent_tree(pParentTree);
+ int parents_id = pPageDict->GetInteger(FX_BSTRC("StructParents"), -1);
+ if (parents_id >= 0) {
+ CPDF_Object* pParents = parent_tree.LookupValue(parents_id);
+ if (pParents == NULL || pParents->GetType() != PDFOBJ_ARRAY) {
+ return;
+ }
+ CPDF_Array* pParentArray = (CPDF_Array*)pParents;
+ for (i = 0; i < pParentArray->GetCount(); i ++) {
+ CPDF_Dictionary* pParent = pParentArray->GetDict(i);
+ if (pParent == NULL) {
+ continue;
+ }
+ AddPageNode(pParent, element_map);
+ }
+ }
+}
+CPDF_StructElementImpl* CPDF_StructTreeImpl::AddPageNode(CPDF_Dictionary* pDict, CFX_MapPtrToPtr& map, int nLevel)
+{
+ if (nLevel > nMaxRecursion) {
+ return NULL;
+ }
+ CPDF_StructElementImpl* pElement = NULL;
+ if (map.Lookup(pDict, (FX_LPVOID&)pElement)) {
+ return pElement;
+ }
+ pElement = FX_NEW CPDF_StructElementImpl(this, NULL, pDict);
+ if (pElement == NULL) {
+ return NULL;
+ }
+ map.SetAt(pDict, pElement);
+ CPDF_Dictionary* pParent = pDict->GetDict(FX_BSTRC("P"));
+ if (pParent == NULL || pParent->GetString(FX_BSTRC("Type")) == FX_BSTRC("StructTreeRoot")) {
+ if (!AddTopLevelNode(pDict, pElement)) {
+ pElement->Release();
+ map.RemoveKey(pDict);
+ }
+ } else {
+ CPDF_StructElementImpl* pParentElement = AddPageNode(pParent, map, nLevel + 1);
+ FX_BOOL bSave = FALSE;
+ for (int i = 0; i < pParentElement->m_Kids.GetSize(); i ++) {
+ if (pParentElement->m_Kids[i].m_Type != CPDF_StructKid::Element) {
+ continue;
+ }
+ if (pParentElement->m_Kids[i].m_Element.m_pDict != pDict) {
+ continue;
+ }
+ pParentElement->m_Kids[i].m_Element.m_pElement = pElement->Retain();
+ bSave = TRUE;
+ }
+ if (!bSave) {
+ pElement->Release();
+ map.RemoveKey(pDict);
+ }
+ }
+ return pElement;
+}
+FX_BOOL CPDF_StructTreeImpl::AddTopLevelNode(CPDF_Dictionary* pDict, CPDF_StructElementImpl* pElement)
+{
+ CPDF_Object *pObj = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
+ if (!pObj) {
+ return FALSE;
+ }
+ if (pObj->GetType() == PDFOBJ_DICTIONARY) {
+ if (pObj->GetObjNum() == pDict->GetObjNum()) {
+ if (m_Kids[0]) {
+ m_Kids[0]->Release();
+ }
+ m_Kids[0] = pElement->Retain();
+ } else {
+ return FALSE;
+ }
+ }
+ if (pObj->GetType() == PDFOBJ_ARRAY) {
+ CPDF_Array* pTopKids = (CPDF_Array*)pObj;
+ FX_DWORD i;
+ FX_BOOL bSave = FALSE;
+ for (i = 0; i < pTopKids->GetCount(); i ++) {
+ CPDF_Reference* pKidRef = (CPDF_Reference*)pTopKids->GetElement(i);
+ if (pKidRef->GetType() != PDFOBJ_REFERENCE || pKidRef->GetRefObjNum() != pDict->GetObjNum()) {
+ continue;
+ }
+ if (m_Kids[i]) {
+ m_Kids[i]->Release();
+ }
+ m_Kids[i] = pElement->Retain();
+ bSave = TRUE;
+ }
+ if (!bSave) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+CPDF_StructElementImpl::CPDF_StructElementImpl(CPDF_StructTreeImpl* pTree, CPDF_StructElementImpl* pParent, CPDF_Dictionary* pDict)
+ : m_RefCount(0)
+{
+ m_pTree = pTree;
+ m_pDict = pDict;
+ m_Type = pDict->GetString(FX_BSTRC("S"));
+ CFX_ByteString mapped = pTree->m_pRoleMap->GetString(m_Type);
+ if (!mapped.IsEmpty()) {
+ m_Type = mapped;
+ }
+ m_pParent = pParent;
+ LoadKids(pDict);
+}
+CPDF_StructElementImpl::~CPDF_StructElementImpl()
+{
+ for (int i = 0; i < m_Kids.GetSize(); i ++) {
+ if (m_Kids[i].m_Type == CPDF_StructKid::Element && m_Kids[i].m_Element.m_pElement) {
+ ((CPDF_StructElementImpl*)m_Kids[i].m_Element.m_pElement)->Release();
+ }
+ }
+}
+CPDF_StructElementImpl* CPDF_StructElementImpl::Retain()
+{
+ m_RefCount++;
+ return this;
+}
+void CPDF_StructElementImpl::Release()
+{
+ if(--m_RefCount < 1) {
+ delete this;
+ }
+}
+void CPDF_StructElementImpl::LoadKids(CPDF_Dictionary* pDict)
+{
+ CPDF_Object* pObj = pDict->GetElement(FX_BSTRC("Pg"));
+ FX_DWORD PageObjNum = 0;
+ if (pObj && pObj->GetType() == PDFOBJ_REFERENCE) {
+ PageObjNum = ((CPDF_Reference*)pObj)->GetRefObjNum();
+ }
+ CPDF_Object* pKids = pDict->GetElementValue(FX_BSTRC("K"));
+ if (pKids == NULL) {
+ return;
+ }
+ if (pKids->GetType() == PDFOBJ_ARRAY) {
+ CPDF_Array* pArray = (CPDF_Array*)pKids;
+ m_Kids.SetSize(pArray->GetCount());
+ for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
+ CPDF_Object* pKid = pArray->GetElementValue(i);
+ LoadKid(PageObjNum, pKid, &m_Kids[i]);
+ }
+ } else {
+ m_Kids.SetSize(1);
+ LoadKid(PageObjNum, pKids, &m_Kids[0]);
+ }
+}
+void CPDF_StructElementImpl::LoadKid(FX_DWORD PageObjNum, CPDF_Object* pKidObj, CPDF_StructKid* pKid)
+{
+ pKid->m_Type = CPDF_StructKid::Invalid;
+ if (pKidObj == NULL) {
+ return;
+ }
+ if (pKidObj->GetType() == PDFOBJ_NUMBER) {
+ if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
+ return;
+ }
+ pKid->m_Type = CPDF_StructKid::PageContent;
+ pKid->m_PageContent.m_ContentId = pKidObj->GetInteger();
+ pKid->m_PageContent.m_PageObjNum = PageObjNum;
+ return;
+ }
+ if (pKidObj->GetType() != PDFOBJ_DICTIONARY) {
+ return;
+ }
+ CPDF_Dictionary* pKidDict = (CPDF_Dictionary*)pKidObj;
+ CPDF_Object* pPageObj = pKidDict->GetElement(FX_BSTRC("Pg"));
+ if (pPageObj && pPageObj->GetType() == PDFOBJ_REFERENCE) {
+ PageObjNum = ((CPDF_Reference*)pPageObj)->GetRefObjNum();
+ }
+ CFX_ByteString type = pKidDict->GetString(FX_BSTRC("Type"));
+ if (type == FX_BSTRC("MCR")) {
+ if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
+ return;
+ }
+ pKid->m_Type = CPDF_StructKid::StreamContent;
+ CPDF_Object* pStreamObj = pKidDict->GetElement(FX_BSTRC("Stm"));
+ if (pStreamObj && pStreamObj->GetType() == PDFOBJ_REFERENCE) {
+ pKid->m_StreamContent.m_RefObjNum = ((CPDF_Reference*)pStreamObj)->GetRefObjNum();
+ } else {
+ pKid->m_StreamContent.m_RefObjNum = 0;
+ }
+ pKid->m_StreamContent.m_PageObjNum = PageObjNum;
+ pKid->m_StreamContent.m_ContentId = pKidDict->GetInteger(FX_BSTRC("MCID"));
+ } else if (type == FX_BSTRC("OBJR")) {
+ if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
+ return;
+ }
+ pKid->m_Type = CPDF_StructKid::Object;
+ CPDF_Object* pObj = pKidDict->GetElement(FX_BSTRC("Obj"));
+ if (pObj && pObj->GetType() == PDFOBJ_REFERENCE) {
+ pKid->m_Object.m_RefObjNum = ((CPDF_Reference*)pObj)->GetRefObjNum();
+ } else {
+ pKid->m_Object.m_RefObjNum = 0;
+ }
+ pKid->m_Object.m_PageObjNum = PageObjNum;
+ } else {
+ pKid->m_Type = CPDF_StructKid::Element;
+ pKid->m_Element.m_pDict = pKidDict;
+ if (m_pTree->m_pPage == NULL) {
+ pKid->m_Element.m_pElement = FX_NEW CPDF_StructElementImpl(m_pTree, this, pKidDict);
+ } else {
+ pKid->m_Element.m_pElement = NULL;
+ }
+ }
+}
+static CPDF_Dictionary* FindAttrDict(CPDF_Object* pAttrs, FX_BSTR owner, FX_FLOAT nLevel = 0.0F)
+{
+ if (nLevel > nMaxRecursion) {
+ return NULL;
+ }
+ if (pAttrs == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pDict = NULL;
+ if (pAttrs->GetType() == PDFOBJ_DICTIONARY) {
+ pDict = (CPDF_Dictionary*)pAttrs;
+ } else if (pAttrs->GetType() == PDFOBJ_STREAM) {
+ pDict = ((CPDF_Stream*)pAttrs)->GetDict();
+ } else if (pAttrs->GetType() == PDFOBJ_ARRAY) {
+ CPDF_Array* pArray = (CPDF_Array*)pAttrs;
+ for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
+ CPDF_Object* pElement = pArray->GetElementValue(i);
+ pDict = FindAttrDict(pElement, owner, nLevel + 1);
+ if (pDict) {
+ return pDict;
+ }
+ }
+ }
+ if (pDict && pDict->GetString(FX_BSTRC("O")) == owner) {
+ return pDict;
+ }
+ return NULL;
+}
+CPDF_Object* CPDF_StructElementImpl::GetAttr(FX_BSTR owner, FX_BSTR name, FX_BOOL bInheritable, FX_FLOAT fLevel)
+{
+ if (fLevel > nMaxRecursion) {
+ return NULL;
+ }
+ if (bInheritable) {
+ CPDF_Object* pAttr = GetAttr(owner, name, FALSE);
+ if (pAttr) {
+ return pAttr;
+ }
+ if (m_pParent == NULL) {
+ return NULL;
+ }
+ return m_pParent->GetAttr(owner, name, TRUE, fLevel + 1);
+ }
+ CPDF_Object* pA = m_pDict->GetElementValue(FX_BSTRC("A"));
+ if (pA) {
+ CPDF_Dictionary* pAttrDict = FindAttrDict(pA, owner);
+ if (pAttrDict) {
+ CPDF_Object* pAttr = pAttrDict->GetElementValue(name);
+ if (pAttr) {
+ return pAttr;
+ }
+ }
+ }
+ CPDF_Object* pC = m_pDict->GetElementValue(FX_BSTRC("C"));
+ if (pC == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pClassMap = m_pTree->m_pTreeRoot->GetDict(FX_BSTRC("ClassMap"));
+ if (pClassMap == NULL) {
+ return NULL;
+ }
+ if (pC->GetType() == PDFOBJ_ARRAY) {
+ CPDF_Array* pArray = (CPDF_Array*)pC;
+ for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
+ CFX_ByteString class_name = pArray->GetString(i);
+ CPDF_Dictionary* pClassDict = pClassMap->GetDict(class_name);
+ if (pClassDict && pClassDict->GetString(FX_BSTRC("O")) == owner) {
+ return pClassDict->GetElementValue(name);
+ }
+ }
+ return NULL;
+ }
+ CFX_ByteString class_name = pC->GetString();
+ CPDF_Dictionary* pClassDict = pClassMap->GetDict(class_name);
+ if (pClassDict && pClassDict->GetString(FX_BSTRC("O")) == owner) {
+ return pClassDict->GetElementValue(name);
+ }
+ return NULL;
+}
+CPDF_Object* CPDF_StructElementImpl::GetAttr(FX_BSTR owner, FX_BSTR name, FX_BOOL bInheritable, int subindex)
+{
+ CPDF_Object* pAttr = GetAttr(owner, name, bInheritable);
+ if (pAttr == NULL || subindex == -1 || pAttr->GetType() != PDFOBJ_ARRAY) {
+ return pAttr;
+ }
+ CPDF_Array* pArray = (CPDF_Array*)pAttr;
+ if (subindex >= (int)pArray->GetCount()) {
+ return pAttr;
+ }
+ return pArray->GetElementValue(subindex);
+}
+CFX_ByteString CPDF_StructElementImpl::GetName(FX_BSTR owner, FX_BSTR name, FX_BSTR default_value, FX_BOOL bInheritable, int subindex)
+{
+ CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
+ if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NAME) {
+ return default_value;
+ }
+ return pAttr->GetString();
+}
+FX_ARGB CPDF_StructElementImpl::GetColor(FX_BSTR owner, FX_BSTR name, FX_ARGB default_value, FX_BOOL bInheritable, int subindex)
+{
+ CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
+ if (pAttr == NULL || pAttr->GetType() != PDFOBJ_ARRAY) {
+ return default_value;
+ }
+ CPDF_Array* pArray = (CPDF_Array*)pAttr;
+ return 0xff000000 | ((int)(pArray->GetNumber(0) * 255) << 16) | ((int)(pArray->GetNumber(1) * 255) << 8) | (int)(pArray->GetNumber(2) * 255);
+}
+FX_FLOAT CPDF_StructElementImpl::GetNumber(FX_BSTR owner, FX_BSTR name, FX_FLOAT default_value, FX_BOOL bInheritable, int subindex)
+{
+ CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
+ if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NUMBER) {
+ return default_value;
+ }
+ return pAttr->GetNumber();
+}
+int CPDF_StructElementImpl::GetInteger(FX_BSTR owner, FX_BSTR name, int default_value, FX_BOOL bInheritable, int subindex)
+{
+ CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
+ if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NUMBER) {
+ return default_value;
+ }
+ return pAttr->GetInteger();
+}
diff --git a/core/src/fpdfdoc/doc_utils.cpp b/core/src/fpdfdoc/doc_utils.cpp new file mode 100644 index 0000000000..dd81594998 --- /dev/null +++ b/core/src/fpdfdoc/doc_utils.cpp @@ -0,0 +1,749 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+static const int FPDFDOC_UTILS_MAXRECURSION = 32;
+CFX_WideString GetFullName(CPDF_Dictionary* pFieldDict);
+void InitInterFormDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument);
+FX_DWORD CountInterFormFonts(CPDF_Dictionary* pFormDict);
+CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_DWORD index, CFX_ByteString& csNameTag);
+CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csNameTag);
+CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CFX_ByteString& csNameTag);
+CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag);
+CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag);
+FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont, CFX_ByteString& csNameTag);
+FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CPDF_Font*& pFont, CFX_ByteString& csNameTag);
+void AddInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont, CFX_ByteString& csNameTag);
+CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag);
+CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag);
+void RemoveInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont);
+void RemoveInterFormFont(CPDF_Dictionary* pFormDict, CFX_ByteString csNameTag);
+CPDF_Font* GetDefaultInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument);
+void SetDefaultInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont);
+void SaveCheckedFieldStatus(CPDF_FormField* pField, CFX_ByteArray& statusArray);
+FX_BOOL NeedPDFEncodeForFieldFullName(const CFX_WideString& csFieldName);
+FX_BOOL NeedPDFEncodeForFieldTree(CPDF_Dictionary* pFieldDict, int nLevel = 0);
+void EncodeFieldName(const CFX_WideString& csName, CFX_ByteString& csT);
+void UpdateEncodeFieldName(CPDF_Dictionary* pFieldDict, int nLevel = 0);
+CFX_WideString GetFullName(CPDF_Dictionary* pFieldDict)
+{
+ CFX_WideString full_name;
+ CPDF_Dictionary* pLevel = pFieldDict;
+ while (pLevel) {
+ CFX_WideString short_name = pLevel->GetUnicodeText("T");
+ if (short_name != L"") {
+ if (full_name == L"") {
+ full_name = short_name;
+ } else {
+ full_name = short_name + L"." + full_name;
+ }
+ }
+ pLevel = pLevel->GetDict("Parent");
+ }
+ return full_name;
+}
+FX_BOOL CPDF_DefaultAppearance::HasFont()
+{
+ if (m_csDA.IsEmpty()) {
+ return FALSE;
+ }
+ CPDF_SimpleParser syntax(m_csDA);
+ return syntax.FindTagParam("Tf", 2);
+}
+CFX_ByteString CPDF_DefaultAppearance::GetFontString()
+{
+ CFX_ByteString csFont;
+ if (m_csDA.IsEmpty()) {
+ return csFont;
+ }
+ CPDF_SimpleParser syntax(m_csDA);
+ if (syntax.FindTagParam("Tf", 2)) {
+ csFont += (CFX_ByteString)syntax.GetWord();
+ csFont += " ";
+ csFont += (CFX_ByteString)syntax.GetWord();
+ csFont += " ";
+ csFont += (CFX_ByteString)syntax.GetWord();
+ }
+ return csFont;
+}
+void CPDF_DefaultAppearance::GetFont(CFX_ByteString& csFontNameTag, FX_FLOAT& fFontSize)
+{
+ csFontNameTag = "";
+ fFontSize = 0;
+ if (m_csDA.IsEmpty()) {
+ return;
+ }
+ CPDF_SimpleParser syntax(m_csDA);
+ if (syntax.FindTagParam("Tf", 2)) {
+ csFontNameTag = (CFX_ByteString)syntax.GetWord();
+ csFontNameTag.Delete(0, 1);
+ fFontSize = FX_atof((CFX_ByteString)syntax.GetWord());
+ }
+ csFontNameTag = PDF_NameDecode(csFontNameTag);
+}
+FX_BOOL CPDF_DefaultAppearance::HasColor(FX_BOOL bStrokingOperation)
+{
+ if (m_csDA.IsEmpty()) {
+ return FALSE;
+ }
+ CPDF_SimpleParser syntax(m_csDA);
+ if (syntax.FindTagParam(bStrokingOperation ? "G" : "g", 1)) {
+ return TRUE;
+ }
+ syntax.SetPos(0);
+ if (syntax.FindTagParam(bStrokingOperation ? "RG" : "rg", 3)) {
+ return TRUE;
+ }
+ syntax.SetPos(0);
+ return syntax.FindTagParam(bStrokingOperation ? "K" : "k", 4);
+}
+CFX_ByteString CPDF_DefaultAppearance::GetColorString(FX_BOOL bStrokingOperation)
+{
+ CFX_ByteString csColor;
+ if (m_csDA.IsEmpty()) {
+ return csColor;
+ }
+ CPDF_SimpleParser syntax(m_csDA);
+ if (syntax.FindTagParam(bStrokingOperation ? "G" : "g", 1)) {
+ csColor += (CFX_ByteString)syntax.GetWord();
+ csColor += " ";
+ csColor += (CFX_ByteString)syntax.GetWord();
+ return csColor;
+ }
+ syntax.SetPos(0);
+ if (syntax.FindTagParam(bStrokingOperation ? "RG" : "rg", 3)) {
+ csColor += (CFX_ByteString)syntax.GetWord();
+ csColor += " ";
+ csColor += (CFX_ByteString)syntax.GetWord();
+ csColor += " ";
+ csColor += (CFX_ByteString)syntax.GetWord();
+ csColor += " ";
+ csColor += (CFX_ByteString)syntax.GetWord();
+ return csColor;
+ }
+ syntax.SetPos(0);
+ if (syntax.FindTagParam(bStrokingOperation ? "K" : "k", 4)) {
+ csColor += (CFX_ByteString)syntax.GetWord();
+ csColor += " ";
+ csColor += (CFX_ByteString)syntax.GetWord();
+ csColor += " ";
+ csColor += (CFX_ByteString)syntax.GetWord();
+ csColor += " ";
+ csColor += (CFX_ByteString)syntax.GetWord();
+ csColor += " ";
+ csColor += (CFX_ByteString)syntax.GetWord();
+ }
+ return csColor;
+}
+void CPDF_DefaultAppearance::GetColor(int& iColorType, FX_FLOAT fc[4], FX_BOOL bStrokingOperation)
+{
+ iColorType = COLORTYPE_TRANSPARENT;
+ for (int c = 0; c < 4; c ++) {
+ fc[c] = 0;
+ }
+ if (m_csDA.IsEmpty()) {
+ return;
+ }
+ CPDF_SimpleParser syntax(m_csDA);
+ if (syntax.FindTagParam(bStrokingOperation ? "G" : "g", 1)) {
+ iColorType = COLORTYPE_GRAY;
+ fc[0] = FX_atof((CFX_ByteString)syntax.GetWord());
+ return;
+ }
+ syntax.SetPos(0);
+ if (syntax.FindTagParam(bStrokingOperation ? "RG" : "rg", 3)) {
+ iColorType = COLORTYPE_RGB;
+ fc[0] = FX_atof((CFX_ByteString)syntax.GetWord());
+ fc[1] = FX_atof((CFX_ByteString)syntax.GetWord());
+ fc[2] = FX_atof((CFX_ByteString)syntax.GetWord());
+ return;
+ }
+ syntax.SetPos(0);
+ if (syntax.FindTagParam(bStrokingOperation ? "K" : "k", 4)) {
+ iColorType = COLORTYPE_CMYK;
+ fc[0] = FX_atof((CFX_ByteString)syntax.GetWord());
+ fc[1] = FX_atof((CFX_ByteString)syntax.GetWord());
+ fc[2] = FX_atof((CFX_ByteString)syntax.GetWord());
+ fc[3] = FX_atof((CFX_ByteString)syntax.GetWord());
+ }
+}
+void CPDF_DefaultAppearance::GetColor(FX_ARGB& color, int& iColorType, FX_BOOL bStrokingOperation)
+{
+ color = 0;
+ iColorType = COLORTYPE_TRANSPARENT;
+ if (m_csDA.IsEmpty()) {
+ return;
+ }
+ CPDF_SimpleParser syntax(m_csDA);
+ if (syntax.FindTagParam(bStrokingOperation ? "G" : "g", 1)) {
+ iColorType = COLORTYPE_GRAY;
+ FX_FLOAT g = FX_atof((CFX_ByteString)syntax.GetWord()) * 255 + 0.5f;
+ color = ArgbEncode(255, (int)g, (int)g, (int)g);
+ return;
+ }
+ syntax.SetPos(0);
+ if (syntax.FindTagParam(bStrokingOperation ? "RG" : "rg", 3)) {
+ iColorType = COLORTYPE_RGB;
+ FX_FLOAT r = FX_atof((CFX_ByteString)syntax.GetWord()) * 255 + 0.5f;
+ FX_FLOAT g = FX_atof((CFX_ByteString)syntax.GetWord()) * 255 + 0.5f;
+ FX_FLOAT b = FX_atof((CFX_ByteString)syntax.GetWord()) * 255 + 0.5f;
+ color = ArgbEncode(255, (int)r, (int)g, (int)b);
+ return;
+ }
+ syntax.SetPos(0);
+ if (syntax.FindTagParam(bStrokingOperation ? "K" : "k", 4)) {
+ iColorType = COLORTYPE_CMYK;
+ FX_FLOAT c = FX_atof((CFX_ByteString)syntax.GetWord());
+ FX_FLOAT m = FX_atof((CFX_ByteString)syntax.GetWord());
+ FX_FLOAT y = FX_atof((CFX_ByteString)syntax.GetWord());
+ FX_FLOAT k = FX_atof((CFX_ByteString)syntax.GetWord());
+ FX_FLOAT r = 1.0f - FX_MIN(1.0f, c + k);
+ FX_FLOAT g = 1.0f - FX_MIN(1.0f, m + k);
+ FX_FLOAT b = 1.0f - FX_MIN(1.0f, y + k);
+ color = ArgbEncode(255, (int)(r * 255 + 0.5f), (int)(g * 255 + 0.5f), (int)(b * 255 + 0.5f));
+ }
+}
+FX_BOOL CPDF_DefaultAppearance::HasTextMatrix()
+{
+ if (m_csDA.IsEmpty()) {
+ return FALSE;
+ }
+ CPDF_SimpleParser syntax(m_csDA);
+ return syntax.FindTagParam("Tm", 6);
+}
+CFX_ByteString CPDF_DefaultAppearance::GetTextMatrixString()
+{
+ CFX_ByteString csTM;
+ if (m_csDA.IsEmpty()) {
+ return csTM;
+ }
+ CPDF_SimpleParser syntax(m_csDA);
+ if (syntax.FindTagParam("Tm", 6)) {
+ for (int i = 0; i < 6; i ++) {
+ csTM += (CFX_ByteString)syntax.GetWord();
+ csTM += " ";
+ }
+ csTM += (CFX_ByteString)syntax.GetWord();
+ }
+ return csTM;
+}
+CFX_AffineMatrix CPDF_DefaultAppearance::GetTextMatrix()
+{
+ CFX_AffineMatrix tm;
+ if (m_csDA.IsEmpty()) {
+ return tm;
+ }
+ CPDF_SimpleParser syntax(m_csDA);
+ if (syntax.FindTagParam("Tm", 6)) {
+ FX_FLOAT f[6];
+ for (int i = 0; i < 6; i ++) {
+ f[i] = FX_atof((CFX_ByteString)syntax.GetWord());
+ }
+ tm.Set(f[0], f[1], f[2], f[3], f[4], f[5]);
+ }
+ return tm;
+}
+void InitInterFormDict(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument)
+{
+ if (pDocument == NULL) {
+ return;
+ }
+ if (pFormDict == NULL) {
+ pFormDict = CPDF_Dictionary::Create();
+ if (pFormDict == NULL) {
+ return;
+ }
+ FX_DWORD dwObjNum = pDocument->AddIndirectObject(pFormDict);
+ CPDF_Dictionary* pRoot = pDocument->GetRoot();
+ pRoot->SetAtReference("AcroForm", pDocument, dwObjNum);
+ }
+ CFX_ByteString csDA;
+ if (!pFormDict->KeyExist("DR")) {
+ CPDF_Font* pFont = NULL;
+ CFX_ByteString csBaseName, csDefault;
+ FX_BYTE charSet = CPDF_InterForm::GetNativeCharSet();
+ pFont = CPDF_InterForm::AddStandardFont(pDocument, "Helvetica");
+ if (pFont != NULL) {
+ AddInterFormFont(pFormDict, pDocument, pFont, csBaseName);
+ csDefault = csBaseName;
+ }
+ if (charSet != 0) {
+ CFX_ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet, NULL);
+ if (pFont == NULL || csFontName != "Helvetica") {
+ pFont = CPDF_InterForm::AddNativeFont(pDocument);
+ if (pFont != NULL) {
+ csBaseName = "";
+ AddInterFormFont(pFormDict, pDocument, pFont, csBaseName);
+ csDefault = csBaseName;
+ }
+ }
+ }
+ if (pFont != NULL) {
+ csDA = "/" + PDF_NameEncode(csDefault) + " 0 Tf";
+ }
+ }
+ if (!csDA.IsEmpty()) {
+ csDA += " ";
+ }
+ csDA += "0 g";
+ if (!pFormDict->KeyExist("DA")) {
+ pFormDict->SetAtString("DA", csDA);
+ }
+}
+FX_DWORD CountInterFormFonts(CPDF_Dictionary* pFormDict)
+{
+ if (pFormDict == NULL) {
+ return 0;
+ }
+ CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
+ if (pDR == NULL) {
+ return 0;
+ }
+ CPDF_Dictionary* pFonts = pDR->GetDict("Font");
+ if (pFonts == NULL) {
+ return 0;
+ }
+ FX_DWORD dwCount = 0;
+ FX_POSITION pos = pFonts->GetStartPos();
+ while (pos) {
+ CPDF_Object* pObj = NULL;
+ CFX_ByteString csKey;
+ pObj = pFonts->GetNextElement(pos, csKey);
+ if (pObj == NULL) {
+ continue;
+ }
+ CPDF_Object* pDirect = pObj->GetDirect();
+ if (pDirect != NULL && pDirect->GetType() == PDFOBJ_DICTIONARY) {
+ if (((CPDF_Dictionary*)pDirect)->GetString("Type") == "Font") {
+ dwCount ++;
+ }
+ }
+ }
+ return dwCount;
+}
+CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_DWORD index, CFX_ByteString& csNameTag)
+{
+ if (pFormDict == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
+ if (pDR == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pFonts = pDR->GetDict("Font");
+ if (pFonts == NULL) {
+ return NULL;
+ }
+ FX_DWORD dwCount = 0;
+ FX_POSITION pos = pFonts->GetStartPos();
+ while (pos) {
+ CPDF_Object* pObj = NULL;
+ CFX_ByteString csKey;
+ pObj = pFonts->GetNextElement(pos, csKey);
+ if (pObj == NULL) {
+ continue;
+ }
+ CPDF_Object* pDirect = pObj->GetDirect();
+ if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {
+ continue;
+ }
+ CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;
+ if (pElement->GetString("Type") != "Font") {
+ continue;
+ }
+ if (dwCount == index) {
+ csNameTag = csKey;
+ return pDocument->LoadFont(pElement);
+ }
+ dwCount ++;
+ }
+ return NULL;
+}
+CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csNameTag)
+{
+ CFX_ByteString csAlias = PDF_NameDecode(csNameTag);
+ if (pFormDict == NULL || csAlias.IsEmpty()) {
+ return NULL;
+ }
+ CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
+ if (pDR == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pFonts = pDR->GetDict("Font");
+ if (pFonts == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pElement = pFonts->GetDict(csAlias);
+ if (pElement == NULL) {
+ return NULL;
+ }
+ if (pElement->GetString("Type") == "Font") {
+ return pDocument->LoadFont(pElement);
+ }
+ return NULL;
+}
+CPDF_Font* GetInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CFX_ByteString& csNameTag)
+{
+ if (pFormDict == NULL || csFontName.IsEmpty()) {
+ return NULL;
+ }
+ CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
+ if (pDR == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pFonts = pDR->GetDict("Font");
+ if (pFonts == NULL) {
+ return NULL;
+ }
+ FX_POSITION pos = pFonts->GetStartPos();
+ while (pos) {
+ CPDF_Object* pObj = NULL;
+ CFX_ByteString csKey;
+ pObj = pFonts->GetNextElement(pos, csKey);
+ if (pObj == NULL) {
+ continue;
+ }
+ CPDF_Object* pDirect = pObj->GetDirect();
+ if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {
+ continue;
+ }
+ CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;
+ if (pElement->GetString("Type") != "Font") {
+ continue;
+ }
+ CPDF_Font* pFind = pDocument->LoadFont(pElement);
+ if (pFind == NULL) {
+ continue;
+ }
+ CFX_ByteString csBaseFont;
+ csBaseFont = pFind->GetBaseFont();
+ csBaseFont.Remove(' ');
+ if (csBaseFont == csFontName) {
+ csNameTag = csKey;
+ return pFind;
+ }
+ }
+ return NULL;
+}
+CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag)
+{
+ if (pFormDict == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
+ if (pDR == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pFonts = pDR->GetDict("Font");
+ if (pFonts == NULL) {
+ return NULL;
+ }
+ FX_POSITION pos = pFonts->GetStartPos();
+ while (pos) {
+ CPDF_Object* pObj = NULL;
+ CFX_ByteString csKey;
+ pObj = pFonts->GetNextElement(pos, csKey);
+ if (pObj == NULL) {
+ continue;
+ }
+ CPDF_Object* pDirect = pObj->GetDirect();
+ if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {
+ continue;
+ }
+ CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;
+ if (pElement->GetString("Type") != "Font") {
+ continue;
+ }
+ CPDF_Font* pFind = pDocument->LoadFont(pElement);
+ if (pFind == NULL) {
+ continue;
+ }
+ CFX_SubstFont* pSubst = (CFX_SubstFont*)pFind->GetSubstFont();
+ if (pSubst == NULL) {
+ continue;
+ }
+ if (pSubst->m_Charset == (int)charSet) {
+ csNameTag = csKey;
+ return pFind;
+ }
+ }
+ return NULL;
+}
+CPDF_Font* GetNativeInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag)
+{
+ csNameTag = "";
+ FX_BYTE charSet = CPDF_InterForm::GetNativeCharSet();
+ CFX_SubstFont* pSubst;
+ CPDF_Font* pFont = GetDefaultInterFormFont(pFormDict, pDocument);
+ if (pFont != NULL) {
+ pSubst = (CFX_SubstFont*)pFont->GetSubstFont();
+ if (pSubst != NULL && pSubst->m_Charset == (int)charSet) {
+ FindInterFormFont(pFormDict, pFont, csNameTag);
+ return pFont;
+ }
+ }
+ return GetNativeInterFormFont(pFormDict, pDocument, charSet, csNameTag);
+}
+FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont, CFX_ByteString& csNameTag)
+{
+ if (pFormDict == NULL || pFont == NULL) {
+ return FALSE;
+ }
+ CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
+ if (pDR == NULL) {
+ return FALSE;
+ }
+ CPDF_Dictionary* pFonts = pDR->GetDict("Font");
+ if (pFonts == NULL) {
+ return FALSE;
+ }
+ FX_POSITION pos = pFonts->GetStartPos();
+ while (pos) {
+ CPDF_Object* pObj = NULL;
+ CFX_ByteString csKey;
+ pObj = pFonts->GetNextElement(pos, csKey);
+ if (pObj == NULL) {
+ continue;
+ }
+ CPDF_Object* pDirect = pObj->GetDirect();
+ if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {
+ continue;
+ }
+ CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;
+ if (pElement->GetString("Type") != "Font") {
+ continue;
+ }
+ if (pFont->GetFontDict() == pElement) {
+ csNameTag = csKey;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+FX_BOOL FindInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument, CFX_ByteString csFontName, CPDF_Font*& pFont, CFX_ByteString& csNameTag)
+{
+ if (pFormDict == NULL) {
+ return FALSE;
+ }
+ CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
+ if (pDR == NULL) {
+ return FALSE;
+ }
+ CPDF_Dictionary* pFonts = pDR->GetDict("Font");
+ if (pFonts == NULL) {
+ return FALSE;
+ }
+ if (csFontName.GetLength() > 0) {
+ csFontName.Remove(' ');
+ }
+ FX_POSITION pos = pFonts->GetStartPos();
+ while (pos) {
+ CPDF_Object* pObj = NULL;
+ CFX_ByteString csKey, csTmp;
+ pObj = pFonts->GetNextElement(pos, csKey);
+ if (pObj == NULL) {
+ continue;
+ }
+ CPDF_Object* pDirect = pObj->GetDirect();
+ if (pDirect == NULL || pDirect->GetType() != PDFOBJ_DICTIONARY) {
+ continue;
+ }
+ CPDF_Dictionary* pElement = (CPDF_Dictionary*)pDirect;
+ if (pElement->GetString("Type") != "Font") {
+ continue;
+ }
+ pFont = pDocument->LoadFont(pElement);
+ if (pFont == NULL) {
+ continue;
+ }
+ CFX_ByteString csBaseFont;
+ csBaseFont = pFont->GetBaseFont();
+ csBaseFont.Remove(' ');
+ if (csBaseFont == csFontName) {
+ csNameTag = csKey;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+void AddInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, const CPDF_Font* pFont, CFX_ByteString& csNameTag)
+{
+ if (pFont == NULL) {
+ return;
+ }
+ if (pFormDict == NULL) {
+ InitInterFormDict(pFormDict, pDocument);
+ }
+ CFX_ByteString csTag;
+ if (FindInterFormFont(pFormDict, pFont, csTag)) {
+ csNameTag = csTag;
+ return;
+ }
+ if (pFormDict == NULL) {
+ InitInterFormDict(pFormDict, pDocument);
+ }
+ CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
+ if (pDR == NULL) {
+ pDR = CPDF_Dictionary::Create();
+ if (pDR == NULL) {
+ return;
+ }
+ pFormDict->SetAt("DR", pDR);
+ }
+ CPDF_Dictionary* pFonts = pDR->GetDict("Font");
+ if (pFonts == NULL) {
+ pFonts = CPDF_Dictionary::Create();
+ pDR->SetAt("Font", pFonts);
+ }
+ if (csNameTag.IsEmpty()) {
+ csNameTag = pFont->GetBaseFont();
+ }
+ csNameTag.Remove(' ');
+ csNameTag = CPDF_InterForm::GenerateNewResourceName(pDR, "Font", 4, csNameTag);
+ pFonts->SetAtReference(csNameTag, pDocument, pFont->GetFontDict());
+}
+CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, FX_BYTE charSet, CFX_ByteString& csNameTag)
+{
+ if (pFormDict == NULL) {
+ InitInterFormDict(pFormDict, pDocument);
+ }
+ CFX_ByteString csTemp;
+ CPDF_Font* pFont = GetNativeInterFormFont(pFormDict, pDocument, charSet, csTemp);
+ if (pFont != NULL) {
+ csNameTag = csTemp;
+ return pFont;
+ }
+ CFX_ByteString csFontName = CPDF_InterForm::GetNativeFont(charSet);
+ if (!csFontName.IsEmpty()) {
+ if (FindInterFormFont(pFormDict, pDocument, csFontName, pFont, csNameTag)) {
+ return pFont;
+ }
+ }
+ pFont = CPDF_InterForm::AddNativeFont(charSet, pDocument);
+ if (pFont != NULL) {
+ AddInterFormFont(pFormDict, pDocument, pFont, csNameTag);
+ }
+ return pFont;
+}
+CPDF_Font* AddNativeInterFormFont(CPDF_Dictionary*& pFormDict, CPDF_Document* pDocument, CFX_ByteString& csNameTag)
+{
+ FX_BYTE charSet = CPDF_InterForm::GetNativeCharSet();
+ return AddNativeInterFormFont(pFormDict, pDocument, charSet, csNameTag);
+}
+void RemoveInterFormFont(CPDF_Dictionary* pFormDict, const CPDF_Font* pFont)
+{
+ if (pFormDict == NULL || pFont == NULL) {
+ return;
+ }
+ CFX_ByteString csTag;
+ if (!FindInterFormFont(pFormDict, pFont, csTag)) {
+ return;
+ }
+ CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
+ CPDF_Dictionary* pFonts = pDR->GetDict("Font");
+ pFonts->RemoveAt(csTag);
+}
+void RemoveInterFormFont(CPDF_Dictionary* pFormDict, CFX_ByteString csNameTag)
+{
+ if (pFormDict == NULL || csNameTag.IsEmpty()) {
+ return;
+ }
+ CPDF_Dictionary* pDR = pFormDict->GetDict("DR");
+ if (pDR == NULL) {
+ return;
+ }
+ CPDF_Dictionary* pFonts = pDR->GetDict("Font");
+ if (pFonts == NULL) {
+ return;
+ }
+ pFonts->RemoveAt(csNameTag);
+}
+CPDF_Font* GetDefaultInterFormFont(CPDF_Dictionary* pFormDict, CPDF_Document* pDocument)
+{
+ if (pFormDict == NULL) {
+ return NULL;
+ }
+ CPDF_DefaultAppearance cDA = pFormDict->GetString("DA");
+ CFX_ByteString csFontNameTag;
+ FX_FLOAT fFontSize;
+ cDA.GetFont(csFontNameTag, fFontSize);
+ return GetInterFormFont(pFormDict, pDocument, csFontNameTag);
+}
+CPDF_IconFit::ScaleMethod CPDF_IconFit::GetScaleMethod()
+{
+ if (m_pDict == NULL) {
+ return Always;
+ }
+ CFX_ByteString csSW = m_pDict->GetString("SW", "A");
+ if (csSW == "B") {
+ return Bigger;
+ } else if (csSW == "S") {
+ return Smaller;
+ } else if (csSW == "N") {
+ return Never;
+ }
+ return Always;
+}
+FX_BOOL CPDF_IconFit::IsProportionalScale()
+{
+ if (m_pDict == NULL) {
+ return TRUE;
+ }
+ return m_pDict->GetString("S", "P") != "A";
+}
+void CPDF_IconFit::GetIconPosition(FX_FLOAT& fLeft, FX_FLOAT& fBottom)
+{
+ fLeft = fBottom = 0.5;
+ if (m_pDict == NULL) {
+ return;
+ }
+ CPDF_Array* pA = m_pDict->GetArray("A");
+ if (pA != NULL) {
+ FX_DWORD dwCount = pA->GetCount();
+ if (dwCount > 0) {
+ fLeft = pA->GetNumber(0);
+ }
+ if (dwCount > 1) {
+ fBottom = pA->GetNumber(1);
+ }
+ }
+}
+FX_BOOL CPDF_IconFit::GetFittingBounds()
+{
+ if (m_pDict == NULL) {
+ return FALSE;
+ }
+ return m_pDict->GetBoolean("FB");
+}
+void SaveCheckedFieldStatus(CPDF_FormField* pField, CFX_ByteArray& statusArray)
+{
+ int iCount = pField->CountControls();
+ for (int i = 0; i < iCount; i ++) {
+ CPDF_FormControl* pControl = pField->GetControl(i);
+ if (pControl == NULL) {
+ continue;
+ }
+ statusArray.Add(pControl->IsChecked() ? 1 : 0);
+ }
+}
+CPDF_Object* FPDF_GetFieldAttr(CPDF_Dictionary* pFieldDict, const FX_CHAR* name, int nLevel)
+{
+ if (nLevel > FPDFDOC_UTILS_MAXRECURSION) {
+ return NULL;
+ }
+ if (pFieldDict == NULL) {
+ return NULL;
+ }
+ CPDF_Object* pAttr = pFieldDict->GetElementValue(name);
+ if (pAttr) {
+ return pAttr;
+ }
+ CPDF_Dictionary* pParent = pFieldDict->GetDict("Parent");
+ if (pParent == NULL) {
+ return NULL;
+ }
+ return FPDF_GetFieldAttr(pParent, name, nLevel + 1);
+}
diff --git a/core/src/fpdfdoc/doc_viewerPreferences.cpp b/core/src/fpdfdoc/doc_viewerPreferences.cpp new file mode 100644 index 0000000000..80af0b50fd --- /dev/null +++ b/core/src/fpdfdoc/doc_viewerPreferences.cpp @@ -0,0 +1,31 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+CPDF_ViewerPreferences::CPDF_ViewerPreferences(CPDF_Document *pDoc): m_pDoc(pDoc)
+{
+}
+CPDF_ViewerPreferences::~CPDF_ViewerPreferences()
+{
+}
+FX_BOOL CPDF_ViewerPreferences::IsDirectionR2L() const
+{
+ CPDF_Dictionary *pDict = m_pDoc->GetRoot();
+ pDict = pDict->GetDict(FX_BSTRC("ViewerPreferences"));
+ if (!pDict) {
+ return FALSE;
+ }
+ return FX_BSTRC("R2L") == pDict->GetString(FX_BSTRC("Direction"));
+}
+FX_BOOL CPDF_ViewerPreferences::PrintScaling() const
+{
+ CPDF_Dictionary *pDict = m_pDoc->GetRoot();
+ pDict = pDict->GetDict(FX_BSTRC("ViewerPreferences"));
+ if (!pDict) {
+ return TRUE;
+ }
+ return FX_BSTRC("None") != pDict->GetString(FX_BSTRC("PrintScaling"));
+}
diff --git a/core/src/fpdfdoc/doc_vt.cpp b/core/src/fpdfdoc/doc_vt.cpp new file mode 100644 index 0000000000..251173da22 --- /dev/null +++ b/core/src/fpdfdoc/doc_vt.cpp @@ -0,0 +1,1864 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+#include "../../include/fpdfdoc/fpdf_vt.h"
+#include "pdf_vt.h"
+const FX_BYTE gFontSizeSteps[] = { 4, 6, 8, 9, 10, 12, 14, 18, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80, 90, 100, 110, 120, 130, 144};
+#define PVT_RETURN_LENGTH 1
+#define PVT_DEFAULT_FONTSIZE 18.0f
+#define PVTWORD_SCRIPT_NORMAL 0
+#define PVTWORD_SCRIPT_SUPER 1
+#define PVTWORD_SCRIPT_SUB 2
+#define PVT_FONTSCALE 0.001f
+#define PVT_PERCENT 0.01f
+#define PVT_HALF 0.5f
+CLine::CLine()
+{
+}
+CLine::~CLine()
+{
+}
+CPVT_WordPlace CLine::GetBeginWordPlace() const
+{
+ return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, -1);
+}
+CPVT_WordPlace CLine::GetEndWordPlace() const
+{
+ return CPVT_WordPlace(LinePlace.nSecIndex, LinePlace.nLineIndex, m_LineInfo.nEndWordIndex);
+}
+CPVT_WordPlace CLine::GetPrevWordPlace(const CPVT_WordPlace & place) const
+{
+ if (place.nWordIndex > m_LineInfo.nEndWordIndex) {
+ return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, m_LineInfo.nEndWordIndex);
+ }
+ return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, place.nWordIndex - 1);
+}
+CPVT_WordPlace CLine::GetNextWordPlace(const CPVT_WordPlace & place) const
+{
+ if (place.nWordIndex < m_LineInfo.nBeginWordIndex) {
+ return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, m_LineInfo.nBeginWordIndex);
+ }
+ return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, place.nWordIndex + 1);
+}
+CSection::CSection(CPDF_VariableText * pVT) : m_pVT(pVT)
+{
+}
+CSection::~CSection()
+{
+ ResetAll();
+}
+void CSection::ResetAll()
+{
+ ResetWordArray();
+ ResetLineArray();
+}
+void CSection::ResetLineArray()
+{
+ m_LineArray.RemoveAll();
+}
+void CSection::ResetWordArray()
+{
+ for (FX_INT32 i = 0, sz = m_WordArray.GetSize(); i < sz; i++) {
+ delete m_WordArray.GetAt(i);
+ }
+ m_WordArray.RemoveAll();
+}
+void CSection::ResetLinePlace()
+{
+ for (FX_INT32 i = 0, sz = m_LineArray.GetSize(); i < sz; i++) {
+ if (CLine * pLine = m_LineArray.GetAt(i)) {
+ pLine->LinePlace = CPVT_WordPlace(SecPlace.nSecIndex, i, -1);
+ }
+ }
+}
+CPVT_WordPlace CSection::AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
+{
+ if (CPVT_WordInfo * pWord = FX_NEW CPVT_WordInfo(wordinfo)) {
+ FX_INT32 nWordIndex = FPDF_MAX(FPDF_MIN(place.nWordIndex, this->m_WordArray.GetSize()), 0);
+ if (nWordIndex == m_WordArray.GetSize()) {
+ m_WordArray.Add(pWord);
+ } else {
+ m_WordArray.InsertAt(nWordIndex, pWord);
+ }
+ }
+ return place;
+}
+CPVT_WordPlace CSection::AddLine(const CPVT_LineInfo & lineinfo)
+{
+ return CPVT_WordPlace(SecPlace.nSecIndex, m_LineArray.Add(lineinfo), -1);
+}
+CPVT_FloatRect CSection::Rearrange()
+{
+ ASSERT(m_pVT != NULL);
+ if (m_pVT->m_nCharArray > 0) {
+ return CTypeset(this).CharArray();
+ } else {
+ return CTypeset(this).Typeset();
+ }
+}
+CPVT_Size CSection::GetSectionSize(FX_FLOAT fFontSize)
+{
+ return CTypeset(this).GetEditSize(fFontSize);
+}
+CPVT_WordPlace CSection::GetBeginWordPlace() const
+{
+ if (CLine * pLine = m_LineArray.GetAt(0)) {
+ return pLine->GetBeginWordPlace();
+ } else {
+ return SecPlace;
+ }
+}
+CPVT_WordPlace CSection::GetEndWordPlace() const
+{
+ if (CLine * pLine = m_LineArray.GetAt(m_LineArray.GetSize() - 1)) {
+ return pLine->GetEndWordPlace();
+ } else {
+ return this->SecPlace;
+ }
+}
+CPVT_WordPlace CSection::GetPrevWordPlace(const CPVT_WordPlace & place) const
+{
+ if (place.nLineIndex < 0) {
+ return GetBeginWordPlace();
+ }
+ if (place.nLineIndex >= m_LineArray.GetSize()) {
+ return GetEndWordPlace();
+ }
+ if (CLine * pLine = m_LineArray.GetAt(place.nLineIndex)) {
+ if (place.nWordIndex == pLine->m_LineInfo.nBeginWordIndex) {
+ return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
+ } else if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
+ if (CLine * pPrevLine = m_LineArray.GetAt(place.nLineIndex - 1)) {
+ return pPrevLine->GetEndWordPlace();
+ }
+ } else {
+ return pLine->GetPrevWordPlace(place);
+ }
+ }
+ return place;
+}
+CPVT_WordPlace CSection::GetNextWordPlace(const CPVT_WordPlace & place) const
+{
+ if (place.nLineIndex < 0) {
+ return GetBeginWordPlace();
+ }
+ if (place.nLineIndex >= m_LineArray.GetSize()) {
+ return GetEndWordPlace();
+ }
+ if (CLine * pLine = m_LineArray.GetAt(place.nLineIndex)) {
+ if (place.nWordIndex >= pLine->m_LineInfo.nEndWordIndex) {
+ if (CLine * pNextLine = m_LineArray.GetAt(place.nLineIndex + 1)) {
+ return pNextLine->GetBeginWordPlace();
+ }
+ } else {
+ return pLine->GetNextWordPlace(place);
+ }
+ }
+ return place;
+}
+void CSection::UpdateWordPlace(CPVT_WordPlace & place) const
+{
+ FX_INT32 nLeft = 0;
+ FX_INT32 nRight = m_LineArray.GetSize() - 1;
+ FX_INT32 nMid = (nLeft + nRight) / 2;
+ while (nLeft <= nRight) {
+ if (CLine * pLine = m_LineArray.GetAt(nMid)) {
+ if (place.nWordIndex < pLine->m_LineInfo.nBeginWordIndex) {
+ nRight = nMid - 1;
+ nMid = (nLeft + nRight) / 2;
+ } else if (place.nWordIndex > pLine->m_LineInfo.nEndWordIndex) {
+ nLeft = nMid + 1;
+ nMid = (nLeft + nRight) / 2;
+ } else {
+ place.nLineIndex = nMid;
+ return;
+ }
+ } else {
+ break;
+ }
+ }
+}
+CPVT_WordPlace CSection::SearchWordPlace(const CPDF_Point & point) const
+{
+ ASSERT(m_pVT != NULL);
+ CPVT_WordPlace place = GetBeginWordPlace();
+ FX_BOOL bUp = TRUE;
+ FX_BOOL bDown = TRUE;
+ FX_INT32 nLeft = 0;
+ FX_INT32 nRight = m_LineArray.GetSize() - 1;
+ FX_INT32 nMid = m_LineArray.GetSize() / 2;
+ FX_FLOAT fTop = 0;
+ FX_FLOAT fBottom = 0;
+ while (nLeft <= nRight) {
+ if (CLine * pLine = m_LineArray.GetAt(nMid)) {
+ fTop = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineAscent - m_pVT->GetLineLeading(m_SecInfo);
+ fBottom = pLine->m_LineInfo.fLineY - pLine->m_LineInfo.fLineDescent;
+ if (IsFloatBigger(point.y, fTop)) {
+ bUp = FALSE;
+ }
+ if (IsFloatSmaller(point.y, fBottom)) {
+ bDown = FALSE;
+ }
+ if (IsFloatSmaller(point.y, fTop)) {
+ nRight = nMid - 1;
+ nMid = (nLeft + nRight) / 2;
+ continue;
+ } else if (IsFloatBigger(point.y, fBottom)) {
+ nLeft = nMid + 1;
+ nMid = (nLeft + nRight) / 2;
+ continue;
+ } else {
+ place = SearchWordPlace(point.x,
+ CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), pLine->GetEndWordPlace())
+ );
+ place.nLineIndex = nMid;
+ return place;
+ }
+ }
+ }
+ if (bUp) {
+ place = GetBeginWordPlace();
+ }
+ if (bDown) {
+ place = GetEndWordPlace();
+ }
+ return place;
+}
+CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, const CPVT_WordPlace & lineplace) const
+{
+ if (CLine * pLine = m_LineArray.GetAt(lineplace.nLineIndex)) {
+ return SearchWordPlace(fx - m_SecInfo.rcSection.left,
+ CPVT_WordRange(pLine->GetNextWordPlace(pLine->GetBeginWordPlace()), pLine->GetEndWordPlace()));
+ }
+ return GetBeginWordPlace();
+}
+CPVT_WordPlace CSection::SearchWordPlace(FX_FLOAT fx, const CPVT_WordRange & range) const
+{
+ CPVT_WordPlace wordplace = range.BeginPos;
+ wordplace.nWordIndex = -1;
+ if (!m_pVT) {
+ return wordplace;
+ }
+ FX_INT32 nLeft = range.BeginPos.nWordIndex;
+ FX_INT32 nRight = range.EndPos.nWordIndex + 1;
+ FX_INT32 nMid = (nLeft + nRight) / 2;
+ while (nLeft < nRight) {
+ if (nMid == nLeft) {
+ break;
+ }
+ if (nMid == nRight) {
+ nMid--;
+ break;
+ }
+ if (CPVT_WordInfo * pWord = m_WordArray.GetAt(nMid)) {
+ if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {
+ nLeft = nMid;
+ nMid = (nLeft + nRight) / 2;
+ continue;
+ } else {
+ nRight = nMid;
+ nMid = (nLeft + nRight) / 2;
+ continue;
+ }
+ } else {
+ break;
+ }
+ }
+ if (CPVT_WordInfo * pWord = m_WordArray.GetAt(nMid)) {
+ if (fx > pWord->fWordX + m_pVT->GetWordWidth(*pWord) * PVT_HALF) {
+ wordplace.nWordIndex = nMid;
+ }
+ }
+ return wordplace;
+}
+void CSection::ClearLeftWords(FX_INT32 nWordIndex)
+{
+ for (FX_INT32 i = nWordIndex; i >= 0; i--) {
+ delete m_WordArray.GetAt(i);
+ m_WordArray.RemoveAt(i);
+ }
+}
+void CSection::ClearRightWords(FX_INT32 nWordIndex)
+{
+ for (FX_INT32 i = m_WordArray.GetSize() - 1; i > nWordIndex; i--) {
+ delete m_WordArray.GetAt(i);
+ m_WordArray.RemoveAt(i);
+ }
+}
+void CSection::ClearMidWords(FX_INT32 nBeginIndex, FX_INT32 nEndIndex)
+{
+ for (FX_INT32 i = nEndIndex; i > nBeginIndex; i--) {
+ delete m_WordArray.GetAt(i);
+ m_WordArray.RemoveAt(i);
+ }
+}
+void CSection::ClearWords(const CPVT_WordRange & PlaceRange)
+{
+ CPVT_WordPlace SecBeginPos = GetBeginWordPlace();
+ CPVT_WordPlace SecEndPos = GetEndWordPlace();
+ if (PlaceRange.BeginPos.WordCmp(SecBeginPos) >= 0) {
+ if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
+ ClearMidWords(PlaceRange.BeginPos.nWordIndex, PlaceRange.EndPos.nWordIndex);
+ } else {
+ ClearRightWords(PlaceRange.BeginPos.nWordIndex);
+ }
+ } else if (PlaceRange.EndPos.WordCmp(SecEndPos) <= 0) {
+ ClearLeftWords(PlaceRange.EndPos.nWordIndex);
+ } else {
+ ResetWordArray();
+ }
+}
+void CSection::ClearWord(const CPVT_WordPlace & place)
+{
+ delete m_WordArray.GetAt(place.nWordIndex);
+ m_WordArray.RemoveAt(place.nWordIndex);
+}
+CTypeset::CTypeset(CSection * pSection) : m_pSection(pSection), m_pVT(pSection->m_pVT), m_rcRet(0.0f, 0.0f, 0.0f, 0.0f)
+{
+}
+CTypeset::~CTypeset()
+{
+}
+CPVT_FloatRect CTypeset::CharArray()
+{
+ ASSERT(m_pSection != NULL);
+ ASSERT(m_pVT != NULL);
+ FX_FLOAT fLineAscent = m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());
+ FX_FLOAT fLineDescent = m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), m_pVT->GetFontSize());
+ m_rcRet.Default();
+ FX_FLOAT x = 0.0f, y = 0.0f;
+ FX_FLOAT fNextWidth;
+ FX_INT32 nStart = 0;
+ FX_FLOAT fNodeWidth = m_pVT->GetPlateWidth() / (m_pVT->m_nCharArray <= 0 ? 1 : m_pVT->m_nCharArray);
+ if (CLine * pLine = m_pSection->m_LineArray.GetAt(0)) {
+ x = 0.0f;
+ y += m_pVT->GetLineLeading(m_pSection->m_SecInfo);
+ y += fLineAscent;
+ nStart = 0;
+ switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
+ case 0:
+ pLine->m_LineInfo.fLineX = fNodeWidth * PVT_HALF;
+ break;
+ case 1:
+ nStart = (m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize()) / 2;
+ pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;
+ break;
+ case 2:
+ nStart = m_pVT->m_nCharArray - m_pSection->m_WordArray.GetSize();
+ pLine->m_LineInfo.fLineX = fNodeWidth * nStart - fNodeWidth * PVT_HALF;
+ break;
+ }
+ for (FX_INT32 w = 0, sz = m_pSection->m_WordArray.GetSize(); w < sz; w++) {
+ if (w >= m_pVT->m_nCharArray) {
+ break;
+ }
+ fNextWidth = 0;
+ if (CPVT_WordInfo * pNextWord = (CPVT_WordInfo *)m_pSection->m_WordArray.GetAt(w + 1)) {
+ pNextWord->fWordTail = 0;
+ fNextWidth = m_pVT->GetWordWidth(*pNextWord);
+ }
+ if (CPVT_WordInfo * pWord = (CPVT_WordInfo *)m_pSection->m_WordArray.GetAt(w)) {
+ pWord->fWordTail = 0;
+ FX_FLOAT fWordWidth = m_pVT->GetWordWidth(*pWord);
+ FX_FLOAT fWordAscent = m_pVT->GetWordAscent(*pWord);
+ FX_FLOAT fWordDescent = m_pVT->GetWordDescent(*pWord);
+ x = (FX_FLOAT)(fNodeWidth * (w + nStart + 0.5) - fWordWidth * PVT_HALF);
+ pWord->fWordX = x;
+ pWord->fWordY = y;
+ if (w == 0) {
+ pLine->m_LineInfo.fLineX = x;
+ }
+ if (w != m_pSection->m_WordArray.GetSize() - 1)
+ pWord->fWordTail = (fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF > 0 ?
+ fNodeWidth - (fWordWidth + fNextWidth) * PVT_HALF : 0);
+ else {
+ pWord->fWordTail = 0;
+ }
+ x += fWordWidth;
+ fLineAscent = FPDF_MAX(fLineAscent, fWordAscent);
+ fLineDescent = FPDF_MIN(fLineDescent, fWordDescent);
+ }
+ }
+ pLine->m_LineInfo.nBeginWordIndex = 0;
+ pLine->m_LineInfo.nEndWordIndex = m_pSection->m_WordArray.GetSize() - 1;
+ pLine->m_LineInfo.fLineY = y;
+ pLine->m_LineInfo.fLineWidth = x - pLine->m_LineInfo.fLineX;
+ pLine->m_LineInfo.fLineAscent = fLineAscent;
+ pLine->m_LineInfo.fLineDescent = fLineDescent;
+ y += (-fLineDescent);
+ }
+ return m_rcRet = CPVT_FloatRect(0, 0, x, y);
+}
+CPVT_Size CTypeset::GetEditSize(FX_FLOAT fFontSize)
+{
+ ASSERT(m_pSection != NULL);
+ ASSERT(m_pVT != NULL);
+ SplitLines(FALSE, fFontSize);
+ return CPVT_Size(m_rcRet.Width(), m_rcRet.Height());
+}
+CPVT_FloatRect CTypeset::Typeset()
+{
+ ASSERT(m_pSection != NULL);
+ ASSERT(m_pVT != NULL);
+ m_pSection->m_LineArray.Empty();
+ SplitLines(TRUE, 0.0f);
+ m_pSection->m_LineArray.Clear();
+ OutputLines();
+ return m_rcRet;
+}
+static int special_chars[128] = {
+ 0x0000, 0x000C, 0x0008, 0x000C, 0x0008, 0x0000, 0x0020, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0008, 0x0008, 0x0000, 0x0010, 0x0000, 0x0000, 0x0028,
+ 0x000C, 0x0008, 0x0000, 0x0000, 0x0028, 0x0028, 0x0028, 0x0028,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0008, 0x0008, 0x0000, 0x0000, 0x0000, 0x0008,
+ 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x000C, 0x0000, 0x0008, 0x0000, 0x0000,
+ 0x0000, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x000C, 0x0000, 0x0008, 0x0000, 0x0000,
+};
+static FX_BOOL IsLatin(FX_WORD word)
+{
+ if (word <= 0x007F) {
+ if (special_chars[word] & 0x0001) {
+ return TRUE;
+ }
+ }
+ if ((word >= 0x00C0 && word <= 0x00FF) ||
+ (word >= 0x0100 && word <= 0x024F) ||
+ (word >= 0x1E00 && word <= 0x1EFF) ||
+ (word >= 0x2C60 && word <= 0x2C7F) ||
+ (word >= 0xA720 && word <= 0xA7FF) ||
+ (word >= 0xFF21 && word <= 0xFF3A) ||
+ (word >= 0xFF41 && word <= 0xFF5A)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+static FX_BOOL IsDigit(FX_DWORD word)
+{
+ return (word >= 0x0030 && word <= 0x0039) ? TRUE : FALSE;
+}
+static FX_BOOL IsCJK(FX_DWORD word)
+{
+ if ((word >= 0x1100 && word <= 0x11FF) ||
+ (word >= 0x2E80 && word <= 0x2FFF) ||
+ (word >= 0x3040 && word <= 0x9FBF) ||
+ (word >= 0xAC00 && word <= 0xD7AF) ||
+ (word >= 0xF900 && word <= 0xFAFF) ||
+ (word >= 0xFE30 && word <= 0xFE4F) ||
+ (word >= 0x20000 && word <= 0x2A6DF) ||
+ (word >= 0x2F800 && word <= 0x2FA1F)) {
+ return TRUE;
+ }
+ if (word >= 0x3000 && word <= 0x303F) {
+ if (word == 0x3005 || word == 0x3006 || word == 0x3021 || word == 0x3022 ||
+ word == 0x3023 || word == 0x3024 || word == 0x3025 || word == 0x3026 ||
+ word == 0x3027 || word == 0x3028 || word == 0x3029 || word == 0x3031 ||
+ word == 0x3032 || word == 0x3033 || word == 0x3034 || word == 0x3035) {
+ return TRUE;
+ }
+ return FALSE;
+ }
+ if (word >= 0xFF66 && word <= 0xFF9D) {
+ return TRUE;
+ }
+ return FALSE;
+}
+static FX_BOOL IsPunctuation(FX_DWORD word)
+{
+ if (word <= 0x007F) {
+ if ((special_chars[word] >> 3) & 1) {
+ return TRUE;
+ }
+ } else if (word >= 0x0080 && word <= 0x00FF) {
+ if (word == 0x0082 || word == 0x0084 || word == 0x0085 || word == 0x0091 ||
+ word == 0x0092 || word == 0x0093 || word <= 0x0094 || word == 0x0096 ||
+ word == 0x00B4 || word == 0x00B8) {
+ return TRUE;
+ }
+ } else if (word >= 0x2000 && word <= 0x206F) {
+ if (word == 0x2010 || word == 0x2011 || word == 0x2012 || word == 0x2013 ||
+ word == 0x2018 || word == 0x2019 || word == 0x201A || word == 0x201B ||
+ word == 0x201C || word == 0x201D || word == 0x201E || word == 0x201F ||
+ word == 0x2032 || word == 0x2033 || word == 0x2034 || word == 0x2035 ||
+ word == 0x2036 || word == 0x2037 || word == 0x203C || word == 0x203D ||
+ word == 0x203E || word == 0x2044) {
+ return TRUE;
+ }
+ } else if (word >= 0x3000 && word <= 0x303F) {
+ if (word == 0x3001 || word == 0x3002 || word == 0x3003 || word == 0x3005 ||
+ word == 0x3009 || word == 0x300A || word == 0x300B || word == 0x300C ||
+ word == 0x300D || word == 0x300F || word == 0x300E || word == 0x3010 ||
+ word == 0x3011 || word == 0x3014 || word == 0x3015 || word == 0x3016 ||
+ word == 0x3017 || word == 0x3018 || word == 0x3019 || word == 0x301A ||
+ word == 0x301B || word == 0x301D || word == 0x301E || word == 0x301F) {
+ return TRUE;
+ }
+ } else if (word >= 0xFE50 && word <= 0xFE6F) {
+ if ((word >= 0xFE50 && word <= 0xFE5E) || word == 0xFE63) {
+ return TRUE;
+ }
+ } else if (word >= 0xFF00 && word <= 0xFFEF) {
+ if (word == 0xFF01 || word == 0xFF02 || word == 0xFF07 || word == 0xFF08 ||
+ word == 0xFF09 || word == 0xFF0C || word == 0xFF0E || word == 0xFF0F ||
+ word == 0xFF1A || word == 0xFF1B || word == 0xFF1F || word == 0xFF3B ||
+ word == 0xFF3D || word == 0xFF40 || word == 0xFF5B || word == 0xFF5C ||
+ word == 0xFF5D || word == 0xFF61 || word == 0xFF62 || word == 0xFF63 ||
+ word == 0xFF64 || word == 0xFF65 || word == 0xFF9E || word == 0xFF9F) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+static FX_BOOL IsConnectiveSymbol(FX_DWORD word)
+{
+ if (word <= 0x007F) {
+ if ((special_chars[word] >> 5) & 1) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+static FX_BOOL IsOpenStylePunctuation(FX_DWORD word)
+{
+ if (word <= 0x007F) {
+ if ((special_chars[word] >> 2) & 1) {
+ return TRUE;
+ }
+ } else if (word == 0x300A || word == 0x300C || word == 0x300E || word == 0x3010 ||
+ word == 0x3014 || word == 0x3016 || word == 0x3018 || word == 0x301A ||
+ word == 0xFF08 || word == 0xFF3B || word == 0xFF5B || word == 0xFF62) {
+ return TRUE;
+ }
+ return FALSE;
+}
+static FX_BOOL IsCurrencySymbol(FX_WORD word)
+{
+ if (word == 0x0024 || word == 0x0080 || word == 0x00A2 || word == 0x00A3 ||
+ word == 0x00A4 || word == 0x00A5 || (word >= 0x20A0 && word <= 0x20CF) ||
+ word == 0xFE69 || word == 0xFF04 || word == 0xFFE0 || word == 0xFFE1 ||
+ word == 0xFFE5 || word == 0xFFE6) {
+ return TRUE;
+ }
+ return FALSE;
+}
+static FX_BOOL IsPrefixSymbol(FX_WORD word)
+{
+ if (IsCurrencySymbol(word)) {
+ return TRUE;
+ }
+ if (word == 0x2116) {
+ return TRUE;
+ }
+ return FALSE;
+}
+static FX_BOOL IsSpace(FX_WORD word)
+{
+ return (word == 0x0020 || word == 0x3000) ? TRUE : FALSE;
+}
+static FX_BOOL NeedDivision(FX_WORD prevWord, FX_WORD curWord)
+{
+ if ((IsLatin(prevWord) || IsDigit(prevWord)) && (IsLatin(curWord) || IsDigit(curWord))) {
+ return FALSE;
+ } else if (IsSpace(curWord) || IsPunctuation(curWord)) {
+ return FALSE;
+ } else if (IsConnectiveSymbol(prevWord) || IsConnectiveSymbol(curWord)) {
+ return FALSE;
+ } else if (IsSpace(prevWord) || IsPunctuation(prevWord)) {
+ return TRUE;
+ } else if (IsPrefixSymbol(prevWord)) {
+ return FALSE;
+ } else if (IsPrefixSymbol(curWord) || IsCJK(curWord)) {
+ return TRUE;
+ } else if (IsCJK(prevWord)) {
+ return TRUE;
+ }
+ return FALSE;
+}
+void CTypeset::SplitLines(FX_BOOL bTypeset, FX_FLOAT fFontSize)
+{
+ ASSERT(m_pVT != NULL);
+ ASSERT(m_pSection != NULL);
+ FX_INT32 nLineHead = 0;
+ FX_INT32 nLineTail = 0;
+ FX_FLOAT fMaxX = 0.0f, fMaxY = 0.0f;
+ FX_FLOAT fLineWidth = 0.0f, fBackupLineWidth = 0.0f;
+ FX_FLOAT fLineAscent = 0.0f, fBackupLineAscent = 0.0f;
+ FX_FLOAT fLineDescent = 0.0f, fBackupLineDescent = 0.0f;
+ FX_INT32 nWordStartPos = 0;
+ FX_BOOL bFullWord = FALSE;
+ FX_INT32 nLineFullWordIndex = 0;
+ FX_INT32 nCharIndex = 0;
+ CPVT_LineInfo line;
+ FX_FLOAT fWordWidth = 0;
+ FX_FLOAT fTypesetWidth = FPDF_MAX(m_pVT->GetPlateWidth() - m_pVT->GetLineIndent(m_pSection->m_SecInfo), 0.0f);
+ FX_INT32 nTotalWords = m_pSection->m_WordArray.GetSize();
+ FX_BOOL bOpened = FALSE;
+ if (nTotalWords > 0) {
+ FX_INT32 i = 0;
+ while (i < nTotalWords) {
+ CPVT_WordInfo * pWord = m_pSection->m_WordArray.GetAt(i);
+ CPVT_WordInfo* pOldWord = pWord;
+ if (i > 0) {
+ pOldWord = m_pSection->m_WordArray.GetAt(i - 1);
+ }
+ if (pWord) {
+ if (bTypeset) {
+ fLineAscent = FPDF_MAX(fLineAscent, m_pVT->GetWordAscent(*pWord, TRUE));
+ fLineDescent = FPDF_MIN(fLineDescent, m_pVT->GetWordDescent(*pWord, TRUE));
+ fWordWidth = m_pVT->GetWordWidth(*pWord);
+ } else {
+ fLineAscent = FPDF_MAX(fLineAscent, m_pVT->GetWordAscent(*pWord, fFontSize));
+ fLineDescent = FPDF_MIN(fLineDescent, m_pVT->GetWordDescent(*pWord, fFontSize));
+ fWordWidth = m_pVT->GetWordWidth(pWord->nFontIndex,
+ pWord->Word,
+ m_pVT->m_wSubWord,
+ m_pVT->m_fCharSpace,
+ m_pVT->m_nHorzScale,
+ fFontSize,
+ pWord->fWordTail,
+ 0);
+ }
+ if (!bOpened) {
+ if (IsOpenStylePunctuation(pWord->Word)) {
+ bOpened = TRUE;
+ bFullWord = TRUE;
+ } else if (pOldWord != NULL) {
+ if (NeedDivision(pOldWord->Word, pWord->Word)) {
+ bFullWord = TRUE;
+ }
+ }
+ } else {
+ if (!IsSpace(pWord->Word) && !IsOpenStylePunctuation(pWord->Word)) {
+ bOpened = FALSE;
+ }
+ }
+ if (bFullWord) {
+ bFullWord = FALSE;
+ if (nCharIndex > 0) {
+ nLineFullWordIndex ++;
+ }
+ nWordStartPos = i;
+ fBackupLineWidth = fLineWidth;
+ fBackupLineAscent = fLineAscent;
+ fBackupLineDescent = fLineDescent;
+ }
+ nCharIndex++;
+ }
+ if (m_pVT->m_bLimitWidth && fTypesetWidth > 0 &&
+ fLineWidth + fWordWidth > fTypesetWidth) {
+ if (nLineFullWordIndex > 0) {
+ i = nWordStartPos;
+ fLineWidth = fBackupLineWidth;
+ fLineAscent = fBackupLineAscent;
+ fLineDescent = fBackupLineDescent;
+ }
+ if (nCharIndex == 1) {
+ fLineWidth = fWordWidth;
+ i++;
+ }
+ nLineTail = i - 1;
+ if (bTypeset) {
+ line.nBeginWordIndex = nLineHead;
+ line.nEndWordIndex = nLineTail;
+ line.nTotalWord = nLineTail - nLineHead + 1;
+ line.fLineWidth = fLineWidth;
+ line.fLineAscent = fLineAscent;
+ line.fLineDescent = fLineDescent;
+ m_pSection->AddLine(line);
+ }
+ fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo));
+ fMaxY += (-fLineDescent);
+ fMaxX = FPDF_MAX(fLineWidth, fMaxX);
+ nLineHead = i;
+ fLineWidth = 0.0f;
+ fLineAscent = 0.0f;
+ fLineDescent = 0.0f;
+ nCharIndex = 0;
+ nLineFullWordIndex = 0;
+ bFullWord = FALSE;
+ } else {
+ fLineWidth += fWordWidth;
+ i++;
+ }
+ }
+ if (nLineHead <= nTotalWords - 1) {
+ nLineTail = nTotalWords - 1;
+ if (bTypeset) {
+ line.nBeginWordIndex = nLineHead;
+ line.nEndWordIndex = nLineTail;
+ line.nTotalWord = nLineTail - nLineHead + 1;
+ line.fLineWidth = fLineWidth;
+ line.fLineAscent = fLineAscent;
+ line.fLineDescent = fLineDescent;
+ m_pSection->AddLine(line);
+ }
+ fMaxY += (fLineAscent + m_pVT->GetLineLeading(m_pSection->m_SecInfo));
+ fMaxY += (-fLineDescent);
+ fMaxX = FPDF_MAX(fLineWidth, fMaxX);
+ }
+ } else {
+ if (bTypeset) {
+ fLineAscent = m_pVT->GetLineAscent(m_pSection->m_SecInfo);
+ fLineDescent = m_pVT->GetLineDescent(m_pSection->m_SecInfo);
+ } else {
+ fLineAscent = m_pVT->GetFontAscent(m_pVT->GetDefaultFontIndex(), fFontSize);
+ fLineDescent = m_pVT->GetFontDescent(m_pVT->GetDefaultFontIndex(), fFontSize);
+ }
+ if (bTypeset) {
+ line.nBeginWordIndex = -1;
+ line.nEndWordIndex = -1;
+ line.nTotalWord = 0;
+ line.fLineWidth = 0;
+ line.fLineAscent = fLineAscent;
+ line.fLineDescent = fLineDescent;
+ m_pSection->AddLine(line);
+ }
+ fMaxY += (m_pVT->GetLineLeading(m_pSection->m_SecInfo) + fLineAscent + (-fLineDescent));
+ }
+ m_rcRet = CPVT_FloatRect(0, 0, fMaxX, fMaxY);
+}
+void CTypeset::OutputLines()
+{
+ ASSERT(m_pVT != NULL);
+ ASSERT(m_pSection != NULL);
+ FX_FLOAT fMinX = 0.0f, fMinY = 0.0f, fMaxX = 0.0f, fMaxY = 0.0f;
+ FX_FLOAT fPosX = 0.0f, fPosY = 0.0f;
+ FX_FLOAT fLineIndent = m_pVT->GetLineIndent(m_pSection->m_SecInfo);
+ FX_FLOAT fTypesetWidth = FPDF_MAX(m_pVT->GetPlateWidth() - fLineIndent, 0.0f);
+ switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
+ default:
+ case 0:
+ fMinX = 0.0f;
+ break;
+ case 1:
+ fMinX = (fTypesetWidth - m_rcRet.Width()) * PVT_HALF;
+ break;
+ case 2:
+ fMinX = fTypesetWidth - m_rcRet.Width();
+ break;
+ }
+ fMaxX = fMinX + m_rcRet.Width();
+ fMinY = 0.0f;
+ fMaxY = m_rcRet.Height();
+ FX_INT32 nTotalLines = m_pSection->m_LineArray.GetSize();
+ if (nTotalLines > 0) {
+ m_pSection->m_SecInfo.nTotalLine = nTotalLines;
+ for (FX_INT32 l = 0; l < nTotalLines; l++) {
+ if (CLine * pLine = m_pSection->m_LineArray.GetAt(l)) {
+ switch (m_pVT->GetAlignment(m_pSection->m_SecInfo)) {
+ default:
+ case 0:
+ fPosX = 0;
+ break;
+ case 1:
+ fPosX = (fTypesetWidth - pLine->m_LineInfo.fLineWidth) * PVT_HALF;
+ break;
+ case 2:
+ fPosX = fTypesetWidth - pLine->m_LineInfo.fLineWidth;
+ break;
+ }
+ fPosX += fLineIndent;
+ fPosY += m_pVT->GetLineLeading(m_pSection->m_SecInfo);
+ fPosY += pLine->m_LineInfo.fLineAscent;
+ pLine->m_LineInfo.fLineX = fPosX - fMinX;
+ pLine->m_LineInfo.fLineY = fPosY - fMinY;
+ for (FX_INT32 w = pLine->m_LineInfo.nBeginWordIndex; w <= pLine->m_LineInfo.nEndWordIndex; w++) {
+ if (CPVT_WordInfo * pWord = m_pSection->m_WordArray.GetAt(w)) {
+ pWord->fWordX = fPosX - fMinX;
+ if (pWord->pWordProps) {
+ switch (pWord->pWordProps->nScriptType) {
+ default:
+ case PVTWORD_SCRIPT_NORMAL:
+ pWord->fWordY = fPosY - fMinY;
+ break;
+ case PVTWORD_SCRIPT_SUPER:
+ pWord->fWordY = fPosY - m_pVT->GetWordAscent(*pWord) - fMinY;
+ break;
+ case PVTWORD_SCRIPT_SUB:
+ pWord->fWordY = fPosY - m_pVT->GetWordDescent(*pWord) - fMinY;
+ break;
+ }
+ } else {
+ pWord->fWordY = fPosY - fMinY;
+ }
+ fPosX += m_pVT->GetWordWidth(*pWord);
+ }
+ }
+ fPosY += (-pLine->m_LineInfo.fLineDescent);
+ }
+ }
+ }
+ m_rcRet = CPVT_FloatRect(fMinX, fMinY, fMaxX, fMaxY);
+}
+CPDF_VariableText::CPDF_VariableText() :
+ m_pVTProvider(NULL),
+ m_pVTIterator(NULL),
+ m_bInitial(FALSE),
+ m_bRichText(FALSE),
+ m_bMultiLine(FALSE),
+ m_bLimitWidth(FALSE),
+ m_bAutoFontSize(FALSE),
+ m_nLimitChar(0),
+ m_nCharArray(0),
+ m_nAlignment(0),
+ m_fCharSpace(0.0f),
+ m_fWordSpace(0.0f),
+ m_fFontSize(0.0f),
+ m_nHorzScale(100),
+ m_wSubWord(0),
+ m_fLineLeading(0.0f)
+{
+}
+CPDF_VariableText::~CPDF_VariableText()
+{
+ if (m_pVTIterator) {
+ delete m_pVTIterator;
+ m_pVTIterator = NULL;
+ }
+ ResetAll();
+}
+void CPDF_VariableText::Initialize()
+{
+ if (!m_bInitial) {
+ CPVT_SectionInfo secinfo;
+ if (m_bRichText) {
+ secinfo.pSecProps = FX_NEW CPVT_SecProps(0.0f, 0.0f, 0);
+ secinfo.pWordProps = FX_NEW CPVT_WordProps(GetDefaultFontIndex(), PVT_DEFAULT_FONTSIZE, 0, 0, 0);
+ }
+ CPVT_WordPlace place;
+ place.nSecIndex = 0;
+ AddSection(place, secinfo);
+ CPVT_LineInfo lineinfo;
+ lineinfo.fLineAscent = GetFontAscent(GetDefaultFontIndex(), GetFontSize());
+ lineinfo.fLineDescent = GetFontDescent(GetDefaultFontIndex(), GetFontSize());
+ AddLine(place, lineinfo);
+ if (CSection * pSection = m_SectionArray.GetAt(0)) {
+ pSection->ResetLinePlace();
+ }
+ m_bInitial = TRUE;
+ }
+}
+void CPDF_VariableText::ResetAll()
+{
+ m_bInitial = FALSE;
+ ResetSectionArray();
+}
+CPVT_WordPlace CPDF_VariableText::InsertWord(const CPVT_WordPlace & place, FX_WORD word, FX_INT32 charset,
+ const CPVT_WordProps * pWordProps)
+{
+ FX_INT32 nTotlaWords = this->GetTotalWords();
+ if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {
+ return place;
+ }
+ if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {
+ return place;
+ }
+ CPVT_WordPlace newplace = place;
+ newplace.nWordIndex ++;
+ if (m_bRichText) {
+ CPVT_WordProps * pNewProps = pWordProps ? FX_NEW CPVT_WordProps(*pWordProps) : FX_NEW CPVT_WordProps();
+ if (pNewProps) {
+ pNewProps->nFontIndex = GetWordFontIndex(word, charset, pWordProps->nFontIndex);
+ return AddWord(newplace, CPVT_WordInfo(word, charset, -1, pNewProps));
+ }
+ } else {
+ FX_INT32 nFontIndex = GetSubWord() > 0 ? GetDefaultFontIndex() : GetWordFontIndex(word, charset, GetDefaultFontIndex());
+ return AddWord(newplace, CPVT_WordInfo(word, charset, nFontIndex, NULL));
+ }
+ return place;
+}
+CPVT_WordPlace CPDF_VariableText::InsertSection(const CPVT_WordPlace & place, const CPVT_SecProps * pSecProps,
+ const CPVT_WordProps * pWordProps)
+{
+ FX_INT32 nTotlaWords = this->GetTotalWords();
+ if (m_nLimitChar > 0 && nTotlaWords >= m_nLimitChar) {
+ return place;
+ }
+ if (m_nCharArray > 0 && nTotlaWords >= m_nCharArray) {
+ return place;
+ }
+ if (!m_bMultiLine) {
+ return place;
+ }
+ CPVT_WordPlace wordplace = place;
+ UpdateWordPlace(wordplace);
+ CPVT_WordPlace newplace = place;
+ if (CSection * pSection = m_SectionArray.GetAt(wordplace.nSecIndex)) {
+ CPVT_WordPlace NewPlace(wordplace.nSecIndex + 1, 0, -1);
+ CPVT_SectionInfo secinfo;
+ if (m_bRichText) {
+ if (pSecProps) {
+ secinfo.pSecProps = FX_NEW CPVT_SecProps(*pSecProps);
+ }
+ if (pWordProps) {
+ secinfo.pWordProps = FX_NEW CPVT_WordProps(*pWordProps);
+ }
+ }
+ AddSection(NewPlace, secinfo);
+ newplace = NewPlace;
+ if (CSection * pNewSection = m_SectionArray.GetAt(NewPlace.nSecIndex)) {
+ for (FX_INT32 w = wordplace.nWordIndex + 1, sz = pSection->m_WordArray.GetSize(); w < sz; w++) {
+ if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(w)) {
+ NewPlace.nWordIndex++;
+ pNewSection->AddWord(NewPlace, *pWord);
+ }
+ }
+ }
+ ClearSectionRightWords(wordplace);
+ }
+ return newplace;
+}
+CPVT_WordPlace CPDF_VariableText::InsertText(const CPVT_WordPlace & place, FX_LPCWSTR text, FX_INT32 charset,
+ const CPVT_SecProps * pSecProps, const CPVT_WordProps * pProps)
+{
+ CFX_WideString swText = text;
+ CPVT_WordPlace wp = place;
+ for (FX_INT32 i = 0, sz = swText.GetLength(); i < sz; i++) {
+ CPVT_WordPlace oldwp = wp;
+ FX_WORD word = swText.GetAt(i);
+ switch (word) {
+ case 0x0D:
+ if (m_bMultiLine) {
+ if (swText.GetAt(i + 1) == 0x0A) {
+ i += 1;
+ }
+ wp = InsertSection(wp, pSecProps, pProps);
+ }
+ break;
+ case 0x0A:
+ if (m_bMultiLine) {
+ if (swText.GetAt(i + 1) == 0x0D) {
+ i += 1;
+ }
+ wp = InsertSection(wp, pSecProps, pProps);
+ }
+ break;
+ case 0x09:
+ word = 0x20;
+ default:
+ wp = InsertWord(wp, word, charset, pProps);
+ break;
+ }
+ if (wp == oldwp) {
+ break;
+ }
+ }
+ return wp;
+}
+CPVT_WordPlace CPDF_VariableText::DeleteWords(const CPVT_WordRange & PlaceRange)
+{
+ FX_BOOL bLastSecPos = FALSE;
+ if (CSection * pSection = m_SectionArray.GetAt(PlaceRange.EndPos.nSecIndex)) {
+ bLastSecPos = (PlaceRange.EndPos == pSection->GetEndWordPlace());
+ }
+ ClearWords(PlaceRange);
+ if (PlaceRange.BeginPos.nSecIndex != PlaceRange.EndPos.nSecIndex) {
+ ClearEmptySections(PlaceRange);
+ if (!bLastSecPos) {
+ LinkLatterSection(PlaceRange.BeginPos);
+ }
+ }
+ return PlaceRange.BeginPos;
+}
+CPVT_WordPlace CPDF_VariableText::DeleteWord(const CPVT_WordPlace & place)
+{
+ return ClearRightWord(AjustLineHeader(place, TRUE));
+}
+CPVT_WordPlace CPDF_VariableText::BackSpaceWord(const CPVT_WordPlace & place)
+{
+ return ClearLeftWord(AjustLineHeader(place, TRUE));
+}
+void CPDF_VariableText::SetText(FX_LPCWSTR text, FX_INT32 charset, const CPVT_SecProps * pSecProps,
+ const CPVT_WordProps * pWordProps)
+{
+ DeleteWords(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
+ CFX_WideString swText = text;
+ CPVT_WordPlace wp(0, 0, -1);
+ CPVT_SectionInfo secinfo;
+ if (m_bRichText) {
+ if (pSecProps) {
+ secinfo.pSecProps = FX_NEW CPVT_SecProps(*pSecProps);
+ }
+ if (pWordProps) {
+ secinfo.pWordProps = FX_NEW CPVT_WordProps(*pWordProps);
+ }
+ }
+ if (CSection * pSection = m_SectionArray.GetAt(0)) {
+ pSection->m_SecInfo = secinfo;
+ }
+ FX_INT32 nCharCount = 0;
+ for (FX_INT32 i = 0, sz = swText.GetLength(); i < sz; i++) {
+ if (m_nLimitChar > 0 && nCharCount >= m_nLimitChar) {
+ break;
+ }
+ if (m_nCharArray > 0 && nCharCount >= m_nCharArray) {
+ break;
+ }
+ FX_WORD word = swText.GetAt(i);
+ switch (word) {
+ case 0x0D:
+ if (m_bMultiLine) {
+ if (swText.GetAt(i + 1) == 0x0A) {
+ i += 1;
+ }
+ wp.nSecIndex ++;
+ wp.nLineIndex = 0;
+ wp.nWordIndex = -1;
+ AddSection(wp, secinfo);
+ }
+ break;
+ case 0x0A:
+ if (m_bMultiLine) {
+ if (swText.GetAt(i + 1) == 0x0D) {
+ i += 1;
+ }
+ wp.nSecIndex ++;
+ wp.nLineIndex = 0;
+ wp.nWordIndex = -1;
+ AddSection(wp, secinfo);
+ }
+ break;
+ case 0x09:
+ word = 0x20;
+ default:
+ wp = InsertWord(wp, word, charset, pWordProps);
+ break;
+ }
+ nCharCount++;
+ }
+}
+void CPDF_VariableText::UpdateWordPlace(CPVT_WordPlace & place) const
+{
+ if (place.nSecIndex < 0) {
+ place = GetBeginWordPlace();
+ }
+ if (place.nSecIndex >= m_SectionArray.GetSize()) {
+ place = GetEndWordPlace();
+ }
+ place = AjustLineHeader(place, TRUE);
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ pSection->UpdateWordPlace(place);
+ }
+}
+FX_INT32 CPDF_VariableText::WordPlaceToWordIndex(const CPVT_WordPlace & place) const
+{
+ CPVT_WordPlace newplace = place;
+ UpdateWordPlace(newplace);
+ FX_INT32 nIndex = 0;
+ FX_INT32 i = 0;
+ FX_INT32 sz = 0;
+ for (i = 0, sz = m_SectionArray.GetSize(); i < sz && i < newplace.nSecIndex; i++) {
+ if (CSection * pSection = m_SectionArray.GetAt(i)) {
+ nIndex += pSection->m_WordArray.GetSize();
+ if (i != m_SectionArray.GetSize() - 1) {
+ nIndex += PVT_RETURN_LENGTH;
+ }
+ }
+ }
+ if (i >= 0 && i < m_SectionArray.GetSize()) {
+ nIndex += newplace.nWordIndex + PVT_RETURN_LENGTH;
+ }
+ return nIndex;
+}
+CPVT_WordPlace CPDF_VariableText::WordIndexToWordPlace(FX_INT32 index) const
+{
+ CPVT_WordPlace place = GetBeginWordPlace();
+ FX_INT32 nOldIndex = 0 , nIndex = 0;
+ FX_BOOL bFind = FALSE;
+ for (FX_INT32 i = 0, sz = m_SectionArray.GetSize(); i < sz; i++) {
+ if (CSection * pSection = m_SectionArray.GetAt(i)) {
+ nIndex += pSection->m_WordArray.GetSize();
+ if (nIndex == index) {
+ place = pSection->GetEndWordPlace();
+ bFind = TRUE;
+ break;
+ } else if (nIndex > index) {
+ place.nSecIndex = i;
+ place.nWordIndex = index - nOldIndex - 1;
+ pSection->UpdateWordPlace(place);
+ bFind = TRUE;
+ break;
+ }
+ if (i != m_SectionArray.GetSize() - 1) {
+ nIndex += PVT_RETURN_LENGTH;
+ }
+ nOldIndex = nIndex;
+ }
+ }
+ if (!bFind) {
+ place = GetEndWordPlace();
+ }
+ return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetBeginWordPlace() const
+{
+ return m_bInitial ? CPVT_WordPlace(0, 0, -1) : CPVT_WordPlace();
+}
+CPVT_WordPlace CPDF_VariableText::GetEndWordPlace() const
+{
+ if (CSection * pSection = m_SectionArray.GetAt(m_SectionArray.GetSize() - 1)) {
+ return pSection->GetEndWordPlace();
+ }
+ return CPVT_WordPlace();
+}
+CPVT_WordPlace CPDF_VariableText::GetPrevWordPlace(const CPVT_WordPlace & place) const
+{
+ if( place.nSecIndex < 0) {
+ return GetBeginWordPlace();
+ }
+ if (place.nSecIndex >= m_SectionArray.GetSize()) {
+ return GetEndWordPlace();
+ }
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ if (place.WordCmp(pSection->GetBeginWordPlace()) <= 0) {
+ if (CSection * pPrevSection = m_SectionArray.GetAt(place.nSecIndex - 1)) {
+ return pPrevSection->GetEndWordPlace();
+ } else {
+ return GetBeginWordPlace();
+ }
+ } else {
+ return pSection->GetPrevWordPlace(place);
+ }
+ }
+ return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetNextWordPlace(const CPVT_WordPlace & place) const
+{
+ if (place.nSecIndex < 0) {
+ return GetBeginWordPlace();
+ }
+ if (place.nSecIndex >= m_SectionArray.GetSize()) {
+ return GetEndWordPlace();
+ }
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ if (place.WordCmp(pSection->GetEndWordPlace()) >= 0) {
+ if (CSection * pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
+ return pNextSection->GetBeginWordPlace();
+ } else {
+ return GetEndWordPlace();
+ }
+ } else {
+ return pSection->GetNextWordPlace(place);
+ }
+ }
+ return place;
+}
+CPVT_WordPlace CPDF_VariableText::SearchWordPlace(const CPDF_Point & point) const
+{
+ CPDF_Point pt = OutToIn(point);
+ CPVT_WordPlace place = GetBeginWordPlace();
+ FX_INT32 nLeft = 0;
+ FX_INT32 nRight = m_SectionArray.GetSize() - 1;
+ FX_INT32 nMid = m_SectionArray.GetSize() / 2;
+ FX_BOOL bUp = TRUE;
+ FX_BOOL bDown = TRUE;
+ while (nLeft <= nRight) {
+ if (CSection * pSection = m_SectionArray.GetAt(nMid)) {
+ if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.top)) {
+ bUp = FALSE;
+ }
+ if (IsFloatBigger(pSection->m_SecInfo.rcSection.bottom, pt.y)) {
+ bDown = FALSE;
+ }
+ if (IsFloatSmaller(pt.y, pSection->m_SecInfo.rcSection.top)) {
+ nRight = nMid - 1;
+ nMid = (nLeft + nRight) / 2;
+ continue;
+ } else if (IsFloatBigger(pt.y, pSection->m_SecInfo.rcSection.bottom)) {
+ nLeft = nMid + 1;
+ nMid = (nLeft + nRight) / 2;
+ continue;
+ } else {
+ place = pSection->SearchWordPlace(
+ CPDF_Point(pt.x - pSection->m_SecInfo.rcSection.left, pt.y - pSection->m_SecInfo.rcSection.top)
+ );
+ place.nSecIndex = nMid;
+ return place;
+ }
+ } else {
+ break;
+ }
+ }
+ if (bUp) {
+ place = GetBeginWordPlace();
+ }
+ if (bDown) {
+ place = GetEndWordPlace();
+ }
+ return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetUpWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const
+{
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ CPVT_WordPlace temp = place;
+ CPDF_Point pt = OutToIn(point);
+ if (temp.nLineIndex-- > 0) {
+ return pSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
+ } else {
+ if (temp.nSecIndex-- > 0) {
+ if (CSection * pLastSection = m_SectionArray.GetAt(temp.nSecIndex)) {
+ temp.nLineIndex = pLastSection->m_LineArray.GetSize() - 1;
+ return pLastSection->SearchWordPlace(pt.x - pLastSection->m_SecInfo.rcSection.left, temp);
+ }
+ }
+ }
+ }
+ return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetDownWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const
+{
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ CPVT_WordPlace temp = place;
+ CPDF_Point pt = OutToIn(point);
+ if (temp.nLineIndex++ < pSection->m_LineArray.GetSize() - 1) {
+ return pSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
+ } else {
+ if (temp.nSecIndex++ < m_SectionArray.GetSize() - 1) {
+ if (CSection * pNextSection = m_SectionArray.GetAt(temp.nSecIndex)) {
+ temp.nLineIndex = 0;
+ return pNextSection->SearchWordPlace(pt.x - pSection->m_SecInfo.rcSection.left, temp);
+ }
+ }
+ }
+ }
+ return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetLineBeginPlace(const CPVT_WordPlace & place) const
+{
+ return CPVT_WordPlace(place.nSecIndex, place.nLineIndex, -1);
+}
+CPVT_WordPlace CPDF_VariableText::GetLineEndPlace(const CPVT_WordPlace & place) const
+{
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex))
+ if (CLine * pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {
+ return pLine->GetEndWordPlace();
+ }
+ return place;
+}
+CPVT_WordPlace CPDF_VariableText::GetSectionBeginPlace(const CPVT_WordPlace & place) const
+{
+ return CPVT_WordPlace(place.nSecIndex, 0, -1);
+}
+CPVT_WordPlace CPDF_VariableText::GetSectionEndPlace(const CPVT_WordPlace & place) const
+{
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ return pSection->GetEndWordPlace();
+ }
+ return place;
+}
+FX_INT32 CPDF_VariableText::GetTotalWords() const
+{
+ FX_INT32 nTotal = 0;
+ for (FX_INT32 i = 0, sz = m_SectionArray.GetSize(); i < sz; i++)
+ if (CSection * pSection = m_SectionArray.GetAt(i)) {
+ nTotal += (pSection->m_WordArray.GetSize() + PVT_RETURN_LENGTH);
+ }
+ return nTotal - PVT_RETURN_LENGTH;
+}
+void CPDF_VariableText::ResetSectionArray()
+{
+ for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
+ delete m_SectionArray.GetAt(s);
+ }
+ m_SectionArray.RemoveAll();
+}
+CPVT_WordPlace CPDF_VariableText::AddSection(const CPVT_WordPlace & place, const CPVT_SectionInfo & secinfo)
+{
+ if (IsValid() && !m_bMultiLine) {
+ return place;
+ }
+ FX_INT32 nSecIndex = FPDF_MAX(FPDF_MIN(place.nSecIndex, m_SectionArray.GetSize()), 0);
+ CSection * pSection = FX_NEW CSection(this);
+ if (!pSection) {
+ return place;
+ }
+ pSection->m_SecInfo = secinfo;
+ pSection->SecPlace.nSecIndex = nSecIndex;
+ if (nSecIndex == m_SectionArray.GetSize()) {
+ m_SectionArray.Add(pSection);
+ } else {
+ m_SectionArray.InsertAt(nSecIndex, pSection);
+ }
+ return place;
+}
+CPVT_WordPlace CPDF_VariableText::AddLine(const CPVT_WordPlace & place, const CPVT_LineInfo & lineinfo)
+{
+ if (m_SectionArray.IsEmpty()) {
+ return place;
+ }
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ return pSection->AddLine(lineinfo);
+ }
+ return place;
+}
+CPVT_WordPlace CPDF_VariableText::AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
+{
+ if (m_SectionArray.GetSize() <= 0) {
+ return place;
+ }
+ CPVT_WordPlace newplace = place;
+ newplace.nSecIndex = FPDF_MAX(FPDF_MIN(newplace.nSecIndex, m_SectionArray.GetSize() - 1), 0);
+ if (CSection * pSection = m_SectionArray.GetAt(newplace.nSecIndex)) {
+ return pSection->AddWord(newplace, wordinfo);
+ }
+ return place;
+}
+FX_BOOL CPDF_VariableText::GetWordInfo(const CPVT_WordPlace & place, CPVT_WordInfo & wordinfo)
+{
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
+ wordinfo = *pWord;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_VariableText::SetWordInfo(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo)
+{
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(place.nWordIndex)) {
+ *pWord = wordinfo;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_VariableText::GetLineInfo(const CPVT_WordPlace & place, CPVT_LineInfo & lineinfo)
+{
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ if (CLine * pLine = pSection->m_LineArray.GetAt(place.nLineIndex)) {
+ lineinfo = pLine->m_LineInfo;
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_VariableText::GetSectionInfo(const CPVT_WordPlace & place, CPVT_SectionInfo & secinfo)
+{
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ secinfo = pSection->m_SecInfo;
+ return TRUE;
+ }
+ return FALSE;
+}
+CPDF_Rect CPDF_VariableText::GetContentRect() const
+{
+ return InToOut(CPDF_EditContainer::GetContentRect());
+}
+FX_FLOAT CPDF_VariableText::GetWordFontSize(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
+{
+ return m_bRichText && WordInfo.pWordProps ? (WordInfo.pWordProps->nScriptType == PVTWORD_SCRIPT_NORMAL || bFactFontSize ? WordInfo.pWordProps->fFontSize : WordInfo.pWordProps->fFontSize * PVT_HALF) : GetFontSize();
+}
+FX_INT32 CPDF_VariableText::GetWordFontIndex(const CPVT_WordInfo & WordInfo)
+{
+ return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nFontIndex : WordInfo.nFontIndex;
+}
+FX_FLOAT CPDF_VariableText::GetWordWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord,
+ FX_FLOAT fCharSpace, FX_INT32 nHorzScale,
+ FX_FLOAT fFontSize, FX_FLOAT fWordTail, FX_INT32 nWordStyle)
+{
+ return (GetCharWidth(nFontIndex, Word, SubWord, nWordStyle) * fFontSize * PVT_FONTSCALE + fCharSpace) * nHorzScale * PVT_PERCENT + fWordTail;
+}
+FX_FLOAT CPDF_VariableText::GetWordWidth(const CPVT_WordInfo & WordInfo)
+{
+ return GetWordWidth(GetWordFontIndex(WordInfo), WordInfo.Word, GetSubWord(), GetCharSpace(WordInfo), GetHorzScale(WordInfo),
+ GetWordFontSize(WordInfo), WordInfo.fWordTail,
+ WordInfo.pWordProps ? WordInfo.pWordProps->nWordStyle : 0);
+}
+FX_FLOAT CPDF_VariableText::GetLineAscent(const CPVT_SectionInfo & SecInfo)
+{
+ return m_bRichText && SecInfo.pWordProps ? GetFontAscent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :
+ GetFontAscent(GetDefaultFontIndex(), GetFontSize());
+}
+FX_FLOAT CPDF_VariableText::GetLineDescent(const CPVT_SectionInfo & SecInfo)
+{
+ return m_bRichText && SecInfo.pWordProps ? GetFontDescent(SecInfo.pWordProps->nFontIndex, SecInfo.pWordProps->fFontSize) :
+ GetFontDescent(GetDefaultFontIndex(), GetFontSize());
+}
+FX_FLOAT CPDF_VariableText::GetFontAscent(FX_INT32 nFontIndex, FX_FLOAT fFontSize)
+{
+ return (FX_FLOAT)GetTypeAscent(nFontIndex) * fFontSize * PVT_FONTSCALE;
+}
+FX_FLOAT CPDF_VariableText::GetFontDescent(FX_INT32 nFontIndex, FX_FLOAT fFontSize)
+{
+ return (FX_FLOAT)GetTypeDescent(nFontIndex) * fFontSize * PVT_FONTSCALE;
+}
+FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)
+{
+ return GetFontAscent(GetWordFontIndex(WordInfo), fFontSize);
+}
+FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize)
+{
+ return GetFontDescent(GetWordFontIndex(WordInfo), fFontSize);
+}
+FX_FLOAT CPDF_VariableText::GetWordAscent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
+{
+ return GetFontAscent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));
+}
+FX_FLOAT CPDF_VariableText::GetWordDescent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize)
+{
+ return GetFontDescent(GetWordFontIndex(WordInfo), GetWordFontSize(WordInfo, bFactFontSize));
+}
+FX_FLOAT CPDF_VariableText::GetLineLeading(const CPVT_SectionInfo & SecInfo)
+{
+ return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineLeading : m_fLineLeading;
+}
+FX_FLOAT CPDF_VariableText::GetLineIndent(const CPVT_SectionInfo & SecInfo)
+{
+ return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->fLineIndent : 0.0f;
+}
+FX_INT32 CPDF_VariableText::GetAlignment(const CPVT_SectionInfo& SecInfo)
+{
+ return m_bRichText && SecInfo.pSecProps ? SecInfo.pSecProps->nAlignment : this->m_nAlignment;
+}
+FX_FLOAT CPDF_VariableText::GetCharSpace(const CPVT_WordInfo & WordInfo)
+{
+ return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->fCharSpace : m_fCharSpace;
+}
+FX_INT32 CPDF_VariableText::GetHorzScale(const CPVT_WordInfo & WordInfo)
+{
+ return m_bRichText && WordInfo.pWordProps ? WordInfo.pWordProps->nHorzScale : m_nHorzScale;
+}
+void CPDF_VariableText::ClearSectionRightWords(const CPVT_WordPlace & place)
+{
+ CPVT_WordPlace wordplace = AjustLineHeader(place, TRUE);
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ for (FX_INT32 w = pSection->m_WordArray.GetSize() - 1; w > wordplace.nWordIndex; w--) {
+ delete pSection->m_WordArray.GetAt(w);
+ pSection->m_WordArray.RemoveAt(w);
+ }
+ }
+}
+CPVT_WordPlace CPDF_VariableText::AjustLineHeader(const CPVT_WordPlace & place, FX_BOOL bPrevOrNext) const
+{
+ if (place.nWordIndex < 0 && place.nLineIndex > 0) {
+ if (bPrevOrNext) {
+ return GetPrevWordPlace(place);
+ } else {
+ return GetNextWordPlace(place);
+ }
+ }
+ return place;
+}
+FX_BOOL CPDF_VariableText::ClearEmptySection(const CPVT_WordPlace & place)
+{
+ if (place.nSecIndex == 0 && m_SectionArray.GetSize() == 1) {
+ return FALSE;
+ }
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ if (pSection->m_WordArray.GetSize() == 0) {
+ delete pSection;
+ m_SectionArray.RemoveAt(place.nSecIndex);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+void CPDF_VariableText::ClearEmptySections(const CPVT_WordRange & PlaceRange)
+{
+ CPVT_WordPlace wordplace;
+ for (FX_INT32 s = PlaceRange.EndPos.nSecIndex; s > PlaceRange.BeginPos.nSecIndex; s--) {
+ wordplace.nSecIndex = s;
+ ClearEmptySection(wordplace);
+ }
+}
+void CPDF_VariableText::LinkLatterSection(const CPVT_WordPlace & place)
+{
+ CPVT_WordPlace oldplace = AjustLineHeader(place, TRUE);
+ if (CSection * pNextSection = m_SectionArray.GetAt(place.nSecIndex + 1)) {
+ if (CSection * pSection = m_SectionArray.GetAt(oldplace.nSecIndex)) {
+ for (FX_INT32 w = 0, sz = pNextSection->m_WordArray.GetSize(); w < sz; w++) {
+ if (CPVT_WordInfo * pWord = pNextSection->m_WordArray.GetAt(w)) {
+ oldplace.nWordIndex ++;
+ pSection->AddWord(oldplace, *pWord);
+ }
+ }
+ }
+ delete pNextSection;
+ m_SectionArray.RemoveAt(place.nSecIndex + 1);
+ }
+}
+void CPDF_VariableText::ClearWords(const CPVT_WordRange & PlaceRange)
+{
+ CPVT_WordRange NewRange;
+ NewRange.BeginPos = AjustLineHeader(PlaceRange.BeginPos, TRUE);
+ NewRange.EndPos = AjustLineHeader(PlaceRange.EndPos, TRUE);
+ for (FX_INT32 s = NewRange.EndPos.nSecIndex; s >= NewRange.BeginPos.nSecIndex; s--) {
+ if (CSection * pSection = m_SectionArray.GetAt(s)) {
+ pSection->ClearWords(NewRange);
+ }
+ }
+}
+CPVT_WordPlace CPDF_VariableText::ClearLeftWord(const CPVT_WordPlace & place)
+{
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ CPVT_WordPlace leftplace = this->GetPrevWordPlace(place);
+ if (leftplace != place) {
+ if (leftplace.nSecIndex != place.nSecIndex) {
+ if (pSection->m_WordArray.GetSize() == 0) {
+ this->ClearEmptySection(place);
+ } else {
+ this->LinkLatterSection(leftplace);
+ }
+ } else {
+ pSection->ClearWord(place);
+ }
+ }
+ return leftplace;
+ }
+ return place;
+}
+CPVT_WordPlace CPDF_VariableText::ClearRightWord(const CPVT_WordPlace & place)
+{
+ if (CSection * pSection = m_SectionArray.GetAt(place.nSecIndex)) {
+ CPVT_WordPlace rightplace = AjustLineHeader(this->GetNextWordPlace(place), FALSE);
+ if (rightplace != place) {
+ if(rightplace.nSecIndex != place.nSecIndex) {
+ LinkLatterSection(place);
+ } else {
+ pSection->ClearWord(rightplace);
+ }
+ }
+ }
+ return place;
+}
+void CPDF_VariableText::RearrangeAll()
+{
+ Rearrange(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
+}
+void CPDF_VariableText::RearrangePart(const CPVT_WordRange & PlaceRange)
+{
+ Rearrange(PlaceRange);
+}
+CPVT_FloatRect CPDF_VariableText::Rearrange(const CPVT_WordRange & PlaceRange)
+{
+ CPVT_FloatRect rcRet;
+ if (IsValid()) {
+ if (m_bAutoFontSize) {
+ SetFontSize(GetAutoFontSize());
+ rcRet = RearrangeSections(CPVT_WordRange(GetBeginWordPlace(), GetEndWordPlace()));
+ } else {
+ rcRet = RearrangeSections(PlaceRange);
+ }
+ }
+ SetContentRect(rcRet);
+ return rcRet;
+}
+FX_FLOAT CPDF_VariableText::GetAutoFontSize()
+{
+ FX_INT32 nTotal = sizeof(gFontSizeSteps) / sizeof(FX_BYTE);
+ if (IsMultiLine()) {
+ nTotal /= 4;
+ }
+ if (nTotal <= 0) {
+ return 0;
+ }
+ if (GetPlateWidth() <= 0) {
+ return 0;
+ }
+ FX_INT32 nLeft = 0;
+ FX_INT32 nRight = nTotal - 1;
+ FX_INT32 nMid = nTotal / 2;
+ while (nLeft <= nRight) {
+ if (IsBigger(gFontSizeSteps[nMid])) {
+ nRight = nMid - 1;
+ nMid = (nLeft + nRight) / 2;
+ continue;
+ } else {
+ nLeft = nMid + 1;
+ nMid = (nLeft + nRight) / 2;
+ continue;
+ }
+ }
+ return (FX_FLOAT)gFontSizeSteps[nMid];
+}
+FX_BOOL CPDF_VariableText::IsBigger(FX_FLOAT fFontSize)
+{
+ FX_BOOL bBigger = FALSE;
+ CPVT_Size szTotal;
+ for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
+ if (CSection * pSection = m_SectionArray.GetAt(s)) {
+ CPVT_Size size = pSection->GetSectionSize(fFontSize);
+ szTotal.x = FPDF_MAX(size.x, szTotal.x);
+ szTotal.y += size.y;
+ if (IsFloatBigger(szTotal.x, GetPlateWidth())
+ || IsFloatBigger(szTotal.y, GetPlateHeight())
+ ) {
+ bBigger = TRUE;
+ break;
+ }
+ }
+ }
+ return bBigger;
+}
+CPVT_FloatRect CPDF_VariableText::RearrangeSections(const CPVT_WordRange & PlaceRange)
+{
+ CPVT_WordPlace place;
+ FX_FLOAT fPosY = 0;
+ FX_FLOAT fOldHeight;
+ FX_INT32 nSSecIndex = PlaceRange.BeginPos.nSecIndex;
+ FX_INT32 nESecIndex = PlaceRange.EndPos.nSecIndex;
+ CPVT_FloatRect rcRet;
+ for (FX_INT32 s = 0, sz = m_SectionArray.GetSize(); s < sz; s++) {
+ place.nSecIndex = s;
+ if (CSection * pSection = m_SectionArray.GetAt(s)) {
+ pSection->SecPlace = place;
+ CPVT_FloatRect rcSec = pSection->m_SecInfo.rcSection;
+ if (s >= nSSecIndex) {
+ if (s <= nESecIndex) {
+ rcSec = pSection->Rearrange();
+ rcSec.top += fPosY;
+ rcSec.bottom += fPosY;
+ } else {
+ fOldHeight = pSection->m_SecInfo.rcSection.bottom - pSection->m_SecInfo.rcSection.top;
+ rcSec.top = fPosY;
+ rcSec.bottom = fPosY + fOldHeight;
+ }
+ pSection->m_SecInfo.rcSection = rcSec;
+ pSection->ResetLinePlace();
+ }
+ if (s == 0) {
+ rcRet = rcSec;
+ } else {
+ rcRet.left = FPDF_MIN(rcSec.left, rcRet.left);
+ rcRet.top = FPDF_MIN(rcSec.top, rcRet.top);
+ rcRet.right = FPDF_MAX(rcSec.right, rcRet.right);
+ rcRet.bottom = FPDF_MAX(rcSec.bottom, rcRet.bottom);
+ }
+ fPosY += rcSec.Height();
+ }
+ }
+ return rcRet;
+}
+FX_INT32 CPDF_VariableText::GetCharWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord, FX_INT32 nWordStyle)
+{
+ if (m_pVTProvider) {
+ if (SubWord > 0) {
+ return m_pVTProvider->GetCharWidth(nFontIndex, SubWord, nWordStyle);
+ } else {
+ return m_pVTProvider->GetCharWidth(nFontIndex, Word, nWordStyle);
+ }
+ }
+ return 0;
+}
+FX_INT32 CPDF_VariableText::GetTypeAscent(FX_INT32 nFontIndex)
+{
+ return m_pVTProvider ? m_pVTProvider->GetTypeAscent(nFontIndex) : 0;
+}
+FX_INT32 CPDF_VariableText::GetTypeDescent(FX_INT32 nFontIndex)
+{
+ return m_pVTProvider ? m_pVTProvider->GetTypeDescent(nFontIndex) : 0;
+}
+FX_INT32 CPDF_VariableText::GetWordFontIndex(FX_WORD word, FX_INT32 charset, FX_INT32 nFontIndex)
+{
+ return m_pVTProvider ? m_pVTProvider->GetWordFontIndex(word, charset, nFontIndex) : -1;
+}
+FX_INT32 CPDF_VariableText::GetDefaultFontIndex()
+{
+ return m_pVTProvider ? m_pVTProvider->GetDefaultFontIndex() : -1;
+}
+FX_BOOL CPDF_VariableText::IsLatinWord(FX_WORD word)
+{
+ return m_pVTProvider ? m_pVTProvider->IsLatinWord(word) : FALSE;
+}
+IPDF_VariableText_Iterator * CPDF_VariableText::GetIterator()
+{
+ if (!m_pVTIterator) {
+ return m_pVTIterator = FX_NEW CPDF_VariableText_Iterator(this);
+ }
+ return m_pVTIterator;
+}
+IPDF_VariableText_Provider* CPDF_VariableText::SetProvider(IPDF_VariableText_Provider * pProvider)
+{
+ IPDF_VariableText_Provider* pOld = m_pVTProvider;
+ m_pVTProvider = pProvider;
+ return pOld;
+}
+CPDF_VariableText_Iterator::CPDF_VariableText_Iterator(CPDF_VariableText * pVT):
+ m_pVT(pVT),
+ m_CurPos(-1, -1, -1)
+{
+}
+CPDF_VariableText_Iterator::~CPDF_VariableText_Iterator()
+{
+}
+void CPDF_VariableText_Iterator::SetAt(FX_INT32 nWordIndex)
+{
+ ASSERT(m_pVT != NULL);
+ m_CurPos = m_pVT->WordIndexToWordPlace(nWordIndex);
+}
+void CPDF_VariableText_Iterator::SetAt(const CPVT_WordPlace & place)
+{
+ ASSERT(m_pVT != NULL);
+ m_CurPos = place;
+}
+FX_BOOL CPDF_VariableText_Iterator::NextWord()
+{
+ ASSERT(m_pVT != NULL);
+ if (m_CurPos == m_pVT->GetEndWordPlace()) {
+ return FALSE;
+ }
+ m_CurPos = m_pVT->GetNextWordPlace(m_CurPos);
+ return TRUE;
+}
+FX_BOOL CPDF_VariableText_Iterator::PrevWord()
+{
+ ASSERT(m_pVT != NULL);
+ if (m_CurPos == m_pVT->GetBeginWordPlace()) {
+ return FALSE;
+ }
+ m_CurPos = m_pVT->GetPrevWordPlace(m_CurPos);
+ return TRUE;
+}
+FX_BOOL CPDF_VariableText_Iterator::NextLine()
+{
+ ASSERT(m_pVT != NULL);
+ if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+ if (m_CurPos.nLineIndex < pSection->m_LineArray.GetSize() - 1) {
+ m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex + 1, -1);
+ return TRUE;
+ } else {
+ if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
+ m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_VariableText_Iterator::PrevLine()
+{
+ ASSERT(m_pVT != NULL);
+ if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+ if (m_CurPos.nLineIndex > 0) {
+ m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex - 1, -1);
+ return TRUE;
+ } else {
+ if (m_CurPos.nSecIndex > 0) {
+ if (CSection * pLastSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex - 1)) {
+ m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, pLastSection->m_LineArray.GetSize() - 1, -1);
+ return TRUE;
+ }
+ }
+ }
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_VariableText_Iterator::NextSection()
+{
+ ASSERT(m_pVT != NULL);
+ if (m_CurPos.nSecIndex < m_pVT->m_SectionArray.GetSize() - 1) {
+ m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex + 1, 0, -1);
+ return TRUE;
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_VariableText_Iterator::PrevSection()
+{
+ ASSERT(m_pVT != NULL);
+ if (m_CurPos.nSecIndex > 0) {
+ m_CurPos = CPVT_WordPlace(m_CurPos.nSecIndex - 1, 0, -1);
+ return TRUE;
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_VariableText_Iterator::GetWord(CPVT_Word & word) const
+{
+ ASSERT(m_pVT != NULL);
+ word.WordPlace = m_CurPos;
+ if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+ if (CLine * pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
+ if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
+ word.Word = pWord->Word;
+ word.nCharset = pWord->nCharset;
+ word.fWidth = m_pVT->GetWordWidth(*pWord);
+ word.ptWord = m_pVT->InToOut(
+ CPDF_Point(pWord->fWordX + pSection->m_SecInfo.rcSection.left,
+ pWord->fWordY + pSection->m_SecInfo.rcSection.top) );
+ word.fAscent = m_pVT->GetWordAscent(*pWord);
+ word.fDescent = m_pVT->GetWordDescent(*pWord);
+ if (pWord->pWordProps) {
+ word.WordProps = *pWord->pWordProps;
+ }
+ word.nFontIndex = m_pVT->GetWordFontIndex(*pWord);
+ word.fFontSize = m_pVT->GetWordFontSize(*pWord);
+ return TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_VariableText_Iterator::SetWord(const CPVT_Word & word)
+{
+ ASSERT(m_pVT != NULL);
+ if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+ if (CPVT_WordInfo * pWord = pSection->m_WordArray.GetAt(m_CurPos.nWordIndex)) {
+ if (pWord->pWordProps) {
+ *pWord->pWordProps = word.WordProps;
+ }
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_VariableText_Iterator::GetLine(CPVT_Line & line) const
+{
+ ASSERT(m_pVT != NULL);
+ line.lineplace = CPVT_WordPlace(m_CurPos.nSecIndex, m_CurPos.nLineIndex, -1);
+ if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+ if (CLine * pLine = pSection->m_LineArray.GetAt(m_CurPos.nLineIndex)) {
+ line.ptLine = m_pVT->InToOut(
+ CPDF_Point(pLine->m_LineInfo.fLineX + pSection->m_SecInfo.rcSection.left,
+ pLine->m_LineInfo.fLineY + pSection->m_SecInfo.rcSection.top) );
+ line.fLineWidth = pLine->m_LineInfo.fLineWidth;
+ line.fLineAscent = pLine->m_LineInfo.fLineAscent;
+ line.fLineDescent = pLine->m_LineInfo.fLineDescent;
+ line.lineEnd = pLine->GetEndWordPlace();
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_VariableText_Iterator::GetSection(CPVT_Section & section) const
+{
+ ASSERT(m_pVT != NULL);
+ section.secplace = CPVT_WordPlace(m_CurPos.nSecIndex, 0, -1);
+ if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+ section.rcSection = m_pVT->InToOut(pSection->m_SecInfo.rcSection);
+ if (pSection->m_SecInfo.pSecProps) {
+ section.SecProps = *pSection->m_SecInfo.pSecProps;
+ }
+ if (pSection->m_SecInfo.pWordProps) {
+ section.WordProps = *pSection->m_SecInfo.pWordProps;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+FX_BOOL CPDF_VariableText_Iterator::SetSection(const CPVT_Section & section)
+{
+ ASSERT(m_pVT != NULL);
+ if (CSection * pSection = m_pVT->m_SectionArray.GetAt(m_CurPos.nSecIndex)) {
+ if (pSection->m_SecInfo.pSecProps) {
+ *pSection->m_SecInfo.pSecProps = section.SecProps;
+ }
+ if (pSection->m_SecInfo.pWordProps) {
+ *pSection->m_SecInfo.pWordProps = section.WordProps;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
diff --git a/core/src/fpdfdoc/doc_vtmodule.cpp b/core/src/fpdfdoc/doc_vtmodule.cpp new file mode 100644 index 0000000000..8bc4e7b771 --- /dev/null +++ b/core/src/fpdfdoc/doc_vtmodule.cpp @@ -0,0 +1,17 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfdoc/fpdf_doc.h"
+#include "../../include/fpdfdoc/fpdf_vt.h"
+#include "pdf_vt.h"
+IPDF_VariableText* IPDF_VariableText::NewVariableText()
+{
+ return FX_NEW CPDF_VariableText();
+}
+void IPDF_VariableText::DelVariableText(IPDF_VariableText* pVT)
+{
+ delete (CPDF_VariableText*)pVT;
+}
diff --git a/core/src/fpdfdoc/pdf_vt.h b/core/src/fpdfdoc/pdf_vt.h new file mode 100644 index 0000000000..fc1af0415f --- /dev/null +++ b/core/src/fpdfdoc/pdf_vt.h @@ -0,0 +1,642 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#define _PDF_VT_H_
+class CPVT_Size;
+class CPVT_FloatRect;
+struct CPVT_SectionInfo;
+struct CPVT_LineInfo;
+struct CPVT_WordInfo;
+class CLine;
+class CLines;
+class CSection;
+class CTypeset;
+class CPDF_EditContainer;
+class CPDF_VariableText;
+class CPDF_VariableText_Iterator;
+#define IsFloatZero(f) ((f) < 0.0001 && (f) > -0.0001)
+#define IsFloatBigger(fa,fb) ((fa) > (fb) && !IsFloatZero((fa) - (fb)))
+#define IsFloatSmaller(fa,fb) ((fa) < (fb) && !IsFloatZero((fa) - (fb)))
+template<class T> T FPDF_MIN (const T & i, const T & j)
+{
+ return ((i < j) ? i : j);
+}
+template<class T> T FPDF_MAX (const T & i, const T & j)
+{
+ return ((i > j) ? i : j);
+}
+class CPVT_Size
+{
+public:
+ CPVT_Size() : x(0.0f), y(0.0f)
+ {
+ }
+ CPVT_Size(FX_FLOAT x, FX_FLOAT y)
+ {
+ this->x = x;
+ this->y = y;
+ }
+ FX_FLOAT x, y;
+};
+class CPVT_FloatRect : public CFX_FloatRect
+{
+public:
+ CPVT_FloatRect()
+ {
+ left = top = right = bottom = 0.0f;
+ }
+ CPVT_FloatRect(FX_FLOAT left, FX_FLOAT top,
+ FX_FLOAT right, FX_FLOAT bottom)
+ {
+ this->left = left;
+ this->top = top;
+ this->right = right;
+ this->bottom = bottom;
+ }
+ CPVT_FloatRect(const CPDF_Rect & rect)
+ {
+ this->left = rect.left;
+ this->top = rect.top;
+ this->right = rect.right;
+ this->bottom = rect.bottom;
+ }
+ void Default()
+ {
+ left = top = right = bottom = 0.0f;
+ }
+ FX_FLOAT Height() const
+ {
+ if(this->top > this->bottom) {
+ return this->top - this->bottom;
+ } else {
+ return this->bottom - this->top;
+ }
+ }
+};
+struct CPVT_SectionInfo {
+ CPVT_SectionInfo() : rcSection(), nTotalLine(0), pSecProps(NULL), pWordProps(NULL)
+ {
+ }
+ virtual ~CPVT_SectionInfo()
+ {
+ if (pSecProps) {
+ delete pSecProps;
+ }
+ if (pWordProps) {
+ delete pWordProps;
+ }
+ }
+ CPVT_SectionInfo(const CPVT_SectionInfo & other): rcSection(), nTotalLine(0), pSecProps(NULL), pWordProps(NULL)
+ {
+ operator = (other);
+ }
+ void operator = (const CPVT_SectionInfo & other)
+ {
+ if (this == &other) {
+ return;
+ }
+ this->rcSection = other.rcSection;
+ this->nTotalLine = other.nTotalLine;
+ if (other.pSecProps) {
+ if (pSecProps) {
+ *pSecProps = *other.pSecProps;
+ } else {
+ pSecProps = FX_NEW CPVT_SecProps(*other.pSecProps);
+ }
+ }
+ if (other.pWordProps) {
+ if (pWordProps) {
+ *pWordProps = *other.pWordProps;
+ } else {
+ pWordProps = FX_NEW CPVT_WordProps(*other.pWordProps);
+ }
+ }
+ }
+ CPVT_FloatRect rcSection;
+ FX_INT32 nTotalLine;
+ CPVT_SecProps* pSecProps;
+ CPVT_WordProps* pWordProps;
+};
+struct CPVT_LineInfo {
+ CPVT_LineInfo() : nTotalWord(0), nBeginWordIndex(-1), nEndWordIndex(-1),
+ fLineX(0.0f), fLineY(0.0f), fLineWidth(0.0f), fLineAscent(0.0f), fLineDescent(0.0f)
+ {
+ }
+ FX_INT32 nTotalWord;
+ FX_INT32 nBeginWordIndex;
+ FX_INT32 nEndWordIndex;
+ FX_FLOAT fLineX;
+ FX_FLOAT fLineY;
+ FX_FLOAT fLineWidth;
+ FX_FLOAT fLineAscent;
+ FX_FLOAT fLineDescent;
+};
+struct CPVT_WordInfo : public CFX_Object {
+ CPVT_WordInfo() : Word(0), nCharset(0),
+ fWordX(0.0f), fWordY(0.0f), fWordTail(0.0f), nFontIndex(-1), pWordProps(NULL)
+ {
+ }
+ CPVT_WordInfo(FX_WORD word, FX_INT32 charset, FX_INT32 fontIndex, CPVT_WordProps * pProps):
+ Word(word), nCharset(charset), fWordX(0.0f), fWordY(0.0f), fWordTail(0.0f),
+ nFontIndex(fontIndex), pWordProps(pProps)
+ {
+ }
+ virtual ~CPVT_WordInfo()
+ {
+ if (pWordProps) {
+ delete pWordProps;
+ }
+ }
+ CPVT_WordInfo(const CPVT_WordInfo & word): Word(0), nCharset(0),
+ fWordX(0.0f), fWordY(0.0f), fWordTail(0.0f), nFontIndex(-1), pWordProps(NULL)
+ {
+ operator = (word);
+ }
+ void operator = (const CPVT_WordInfo & word)
+ {
+ if (this == &word) {
+ return;
+ }
+ this->Word = word.Word;
+ this->nCharset = word.nCharset;
+ this->nFontIndex = word.nFontIndex;
+ if (word.pWordProps) {
+ if (pWordProps) {
+ *pWordProps = *word.pWordProps;
+ } else {
+ pWordProps = FX_NEW CPVT_WordProps(*word.pWordProps);
+ }
+ }
+ }
+ FX_WORD Word;
+ FX_INT32 nCharset;
+ FX_FLOAT fWordX;
+ FX_FLOAT fWordY;
+ FX_FLOAT fWordTail;
+ FX_INT32 nFontIndex;
+ CPVT_WordProps* pWordProps;
+};
+struct CPVT_FloatRange {
+ CPVT_FloatRange() : fMin(0.0f), fMax(0.0f)
+ {
+ }
+ CPVT_FloatRange(FX_FLOAT min, FX_FLOAT max) : fMin(min), fMax(max)
+ {
+ }
+ FX_FLOAT Range() const
+ {
+ return fMax - fMin;
+ }
+ FX_FLOAT fMin, fMax;
+};
+template<class TYPE> class CPVT_ArrayTemplate : public CFX_ArrayTemplate<TYPE>
+{
+public:
+ FX_BOOL IsEmpty()
+ {
+ return CFX_ArrayTemplate<TYPE>::GetSize() <= 0;
+ }
+ TYPE GetAt(int nIndex) const
+ {
+ if (nIndex >= 0 && nIndex < CFX_ArrayTemplate<TYPE>::GetSize()) {
+ return CFX_ArrayTemplate<TYPE>::GetAt(nIndex);
+ }
+ return NULL;
+ }
+ void RemoveAt(int nIndex)
+ {
+ if (nIndex >= 0 && nIndex < CFX_ArrayTemplate<TYPE>::GetSize()) {
+ CFX_ArrayTemplate<TYPE>::RemoveAt(nIndex);
+ }
+ }
+};
+class CLine : public CFX_Object
+{
+public:
+ CLine();
+ virtual ~CLine();
+ CPVT_WordPlace GetBeginWordPlace() const;
+ CPVT_WordPlace GetEndWordPlace() const;
+ CPVT_WordPlace GetPrevWordPlace(const CPVT_WordPlace & place) const;
+ CPVT_WordPlace GetNextWordPlace(const CPVT_WordPlace & place) const;
+ CPVT_WordPlace LinePlace;
+ CPVT_LineInfo m_LineInfo;
+};
+class CLines
+{
+public:
+ CLines() : m_nTotal(0) {}
+ virtual ~CLines()
+ {
+ RemoveAll();
+ }
+ FX_INT32 GetSize() const
+ {
+ return m_Lines.GetSize();
+ }
+ CLine * GetAt(FX_INT32 nIndex) const
+ {
+ return m_Lines.GetAt(nIndex);
+ }
+ void Empty()
+ {
+ m_nTotal = 0;
+ }
+ void RemoveAll()
+ {
+ for (FX_INT32 i = 0, sz = GetSize(); i < sz; i++) {
+ delete GetAt(i);
+ }
+ m_Lines.RemoveAll();
+ m_nTotal = 0;
+ }
+ FX_INT32 Add(const CPVT_LineInfo & lineinfo)
+ {
+ if (m_nTotal >= GetSize()) {
+ if (CLine * pLine = FX_NEW CLine) {
+ pLine->m_LineInfo = lineinfo;
+ m_Lines.Add(pLine);
+ return m_nTotal++;
+ }
+ return m_nTotal;
+ } else {
+ if (CLine * pLine = GetAt(m_nTotal)) {
+ pLine->m_LineInfo = lineinfo;
+ }
+ return m_nTotal++;
+ }
+ }
+ void Clear()
+ {
+ for (FX_INT32 i = GetSize() - 1; i >= m_nTotal; i--) {
+ delete GetAt(i);
+ m_Lines.RemoveAt(i);
+ }
+ }
+private:
+ CPVT_ArrayTemplate<CLine*> m_Lines;
+ FX_INT32 m_nTotal;
+};
+class CSection : public CFX_Object
+{
+ friend class CTypeset;
+public:
+ CSection(CPDF_VariableText * pVT);
+ virtual ~CSection();
+ void ResetAll();
+ void ResetLineArray();
+ void ResetWordArray();
+ void ResetLinePlace();
+ CPVT_WordPlace AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo);
+ CPVT_WordPlace AddLine(const CPVT_LineInfo & lineinfo);
+ void ClearWords(const CPVT_WordRange & PlaceRange);
+ void ClearWord(const CPVT_WordPlace & place);
+ CPVT_FloatRect Rearrange();
+ CPVT_Size GetSectionSize(FX_FLOAT fFontSize);
+ CPVT_WordPlace GetBeginWordPlace() const;
+ CPVT_WordPlace GetEndWordPlace() const;
+ CPVT_WordPlace GetPrevWordPlace(const CPVT_WordPlace & place) const;
+ CPVT_WordPlace GetNextWordPlace(const CPVT_WordPlace & place) const;
+ void UpdateWordPlace(CPVT_WordPlace & place) const;
+ CPVT_WordPlace SearchWordPlace(const CPDF_Point & point) const;
+ CPVT_WordPlace SearchWordPlace(FX_FLOAT fx, const CPVT_WordPlace & lineplace) const;
+ CPVT_WordPlace SearchWordPlace(FX_FLOAT fx, const CPVT_WordRange & range) const;
+public:
+ CPVT_WordPlace SecPlace;
+ CPVT_SectionInfo m_SecInfo;
+ CLines m_LineArray;
+ CPVT_ArrayTemplate<CPVT_WordInfo*> m_WordArray;
+private:
+ void ClearLeftWords(FX_INT32 nWordIndex);
+ void ClearRightWords(FX_INT32 nWordIndex);
+ void ClearMidWords(FX_INT32 nBeginIndex, FX_INT32 nEndIndex);
+
+ CPDF_VariableText *m_pVT;
+};
+class CTypeset
+{
+public:
+ CTypeset(CSection * pSection);
+ virtual ~CTypeset();
+ CPVT_Size GetEditSize(FX_FLOAT fFontSize);
+ CPVT_FloatRect Typeset();
+ CPVT_FloatRect CharArray();
+private:
+ void SplitLines(FX_BOOL bTypeset, FX_FLOAT fFontSize);
+ void OutputLines();
+
+ CPVT_FloatRect m_rcRet;
+ CPDF_VariableText * m_pVT;
+ CSection * m_pSection;
+};
+class CPDF_EditContainer
+{
+public:
+ CPDF_EditContainer(): m_rcPlate(0, 0, 0, 0), m_rcContent(0, 0, 0, 0) {};
+ virtual ~CPDF_EditContainer() {};
+ virtual void SetPlateRect(const CPDF_Rect & rect)
+ {
+ m_rcPlate = rect;
+ };
+ virtual const CPDF_Rect & GetPlateRect() const
+ {
+ return m_rcPlate;
+ };
+ virtual void SetContentRect(const CPVT_FloatRect & rect)
+ {
+ m_rcContent = rect;
+ };
+ virtual CPDF_Rect GetContentRect() const
+ {
+ return m_rcContent;
+ };
+ FX_FLOAT GetPlateWidth() const
+ {
+ return m_rcPlate.right - m_rcPlate.left;
+ };
+ FX_FLOAT GetPlateHeight() const
+ {
+ return m_rcPlate.top - m_rcPlate.bottom;
+ };
+ CPVT_Size GetPlateSize() const
+ {
+ return CPVT_Size(GetPlateWidth(), GetPlateHeight());
+ };
+ CPDF_Point GetBTPoint() const
+ {
+ return CPDF_Point(m_rcPlate.left, m_rcPlate.top);
+ };
+ CPDF_Point GetETPoint() const
+ {
+ return CPDF_Point(m_rcPlate.right, m_rcPlate.bottom);
+ };
+ inline CPDF_Point InToOut(const CPDF_Point & point) const
+ {
+ return CPDF_Point(point.x + GetBTPoint().x, GetBTPoint().y - point.y);
+ };
+ inline CPDF_Point OutToIn(const CPDF_Point & point) const
+ {
+ return CPDF_Point(point.x - GetBTPoint().x, GetBTPoint().y - point.y);
+ };
+ inline CPDF_Rect InToOut(const CPVT_FloatRect & rect) const
+ {
+ CPDF_Point ptLeftTop = InToOut(CPDF_Point(rect.left, rect.top));
+ CPDF_Point ptRightBottom = InToOut(CPDF_Point(rect.right, rect.bottom));
+ return CPDF_Rect(ptLeftTop.x, ptRightBottom.y, ptRightBottom.x, ptLeftTop.y);
+ };
+ inline CPVT_FloatRect OutToIn(const CPDF_Rect & rect) const
+ {
+ CPDF_Point ptLeftTop = OutToIn(CPDF_Point(rect.left, rect.top));
+ CPDF_Point ptRightBottom = OutToIn(CPDF_Point(rect.right, rect.bottom));
+ return CPVT_FloatRect(ptLeftTop.x, ptLeftTop.y, ptRightBottom.x, ptRightBottom.y);
+ };
+
+private:
+ CPDF_Rect m_rcPlate;
+ CPVT_FloatRect m_rcContent;
+};
+class CPDF_VariableText : public IPDF_VariableText, public CFX_Object, private CPDF_EditContainer
+{
+ friend class CTypeset;
+ friend class CSection;
+ friend class CPDF_VariableText_Iterator;
+public:
+ CPDF_VariableText();
+ virtual ~CPDF_VariableText();
+ IPDF_VariableText_Provider* SetProvider(IPDF_VariableText_Provider * pProvider);
+ IPDF_VariableText_Iterator* GetIterator();
+ void SetPlateRect(const CPDF_Rect & rect)
+ {
+ CPDF_EditContainer::SetPlateRect(rect);
+ }
+ void SetAlignment(FX_INT32 nFormat = 0)
+ {
+ m_nAlignment = nFormat;
+ }
+ void SetPasswordChar(FX_WORD wSubWord = '*')
+ {
+ m_wSubWord = wSubWord;
+ }
+ void SetLimitChar(FX_INT32 nLimitChar = 0)
+ {
+ m_nLimitChar = nLimitChar;
+ }
+ void SetCharSpace(FX_FLOAT fCharSpace = 0.0f)
+ {
+ m_fCharSpace = fCharSpace;
+ }
+ void SetHorzScale(FX_INT32 nHorzScale = 100)
+ {
+ m_nHorzScale = nHorzScale;
+ }
+ void SetMultiLine(FX_BOOL bMultiLine = TRUE)
+ {
+ m_bMultiLine = bMultiLine;
+ }
+ void SetAutoReturn(FX_BOOL bAuto = TRUE)
+ {
+ m_bLimitWidth = bAuto;
+ }
+ void SetFontSize(FX_FLOAT fFontSize)
+ {
+ m_fFontSize = fFontSize;
+ }
+ void SetCharArray(FX_INT32 nCharArray = 0)
+ {
+ m_nCharArray = nCharArray;
+ }
+ void SetAutoFontSize(FX_BOOL bAuto = TRUE)
+ {
+ m_bAutoFontSize = bAuto;
+ }
+ void SetRichText(FX_BOOL bRichText)
+ {
+ m_bRichText = bRichText;
+ }
+ void SetLineLeading(FX_FLOAT fLineLeading)
+ {
+ m_fLineLeading = fLineLeading;
+ }
+ void Initialize();
+ FX_BOOL IsValid() const
+ {
+ return m_bInitial;
+ }
+ FX_BOOL IsRichText() const
+ {
+ return m_bRichText;
+ }
+ void RearrangeAll();
+ void RearrangePart(const CPVT_WordRange & PlaceRange);
+ void ResetAll();
+ void SetText(FX_LPCWSTR text, FX_INT32 charset = 1, const CPVT_SecProps * pSecProps = NULL,
+ const CPVT_WordProps * pWordProps = NULL);
+ CPVT_WordPlace InsertWord(const CPVT_WordPlace & place, FX_WORD word, FX_INT32 charset = 1,
+ const CPVT_WordProps * pWordProps = NULL);
+ CPVT_WordPlace InsertSection(const CPVT_WordPlace & place, const CPVT_SecProps * pSecProps = NULL,
+ const CPVT_WordProps * pWordProps = NULL);
+ CPVT_WordPlace InsertText(const CPVT_WordPlace & place, FX_LPCWSTR text, FX_INT32 charset = 1,
+ const CPVT_SecProps * pSecProps = NULL, const CPVT_WordProps * pWordProps = NULL);
+ CPVT_WordPlace DeleteWords(const CPVT_WordRange & PlaceRange);
+ CPVT_WordPlace DeleteWord(const CPVT_WordPlace & place);
+ CPVT_WordPlace BackSpaceWord(const CPVT_WordPlace & place);
+ const CPDF_Rect & GetPlateRect() const
+ {
+ return CPDF_EditContainer::GetPlateRect();
+ }
+ CPDF_Rect GetContentRect() const;
+ FX_INT32 GetTotalWords() const;
+ FX_FLOAT GetFontSize() const
+ {
+ return m_fFontSize;
+ }
+ FX_INT32 GetAlignment() const
+ {
+ return m_nAlignment;
+ }
+ FX_INT32 GetCharArray() const
+ {
+ return m_nCharArray;
+ }
+ FX_INT32 GetLimitChar() const
+ {
+ return m_nLimitChar;
+ }
+ FX_BOOL IsMultiLine() const
+ {
+ return m_bMultiLine;
+ }
+ FX_INT32 GetHorzScale() const
+ {
+ return m_nHorzScale;
+ }
+ FX_FLOAT GetCharSpace() const
+ {
+ return m_fCharSpace;
+ }
+
+ inline CPVT_WordPlace GetBeginWordPlace() const;
+ inline CPVT_WordPlace GetEndWordPlace() const;
+ CPVT_WordPlace GetPrevWordPlace(const CPVT_WordPlace & place) const;
+ CPVT_WordPlace GetNextWordPlace(const CPVT_WordPlace & place) const;
+ CPVT_WordPlace SearchWordPlace(const CPDF_Point & point) const;
+ CPVT_WordPlace GetUpWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const;
+ CPVT_WordPlace GetDownWordPlace(const CPVT_WordPlace & place, const CPDF_Point & point) const;
+ CPVT_WordPlace GetLineBeginPlace(const CPVT_WordPlace & place) const;
+ CPVT_WordPlace GetLineEndPlace(const CPVT_WordPlace & place) const;
+ CPVT_WordPlace GetSectionBeginPlace(const CPVT_WordPlace & place) const;
+ CPVT_WordPlace GetSectionEndPlace(const CPVT_WordPlace & place) const;
+ void UpdateWordPlace(CPVT_WordPlace & place) const;
+ FX_INT32 WordPlaceToWordIndex(const CPVT_WordPlace & place) const;
+ CPVT_WordPlace WordIndexToWordPlace(FX_INT32 index) const;
+ FX_WORD GetPasswordChar() const
+ {
+ return GetSubWord();
+ }
+ FX_WORD GetSubWord() const
+ {
+ return m_wSubWord;
+ }
+private:
+ FX_INT32 GetCharWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord, FX_INT32 nWordStyle);
+ FX_INT32 GetTypeAscent(FX_INT32 nFontIndex);
+ FX_INT32 GetTypeDescent(FX_INT32 nFontIndex);
+ FX_INT32 GetWordFontIndex(FX_WORD word, FX_INT32 charset, FX_INT32 nFontIndex);
+ FX_INT32 GetDefaultFontIndex();
+ FX_BOOL IsLatinWord(FX_WORD word);
+private:
+
+ CPVT_WordPlace AddSection(const CPVT_WordPlace & place, const CPVT_SectionInfo & secinfo);
+ CPVT_WordPlace AddLine(const CPVT_WordPlace & place, const CPVT_LineInfo & lineinfo);
+ CPVT_WordPlace AddWord(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo);
+ FX_BOOL GetWordInfo(const CPVT_WordPlace & place, CPVT_WordInfo & wordinfo);
+ FX_BOOL SetWordInfo(const CPVT_WordPlace & place, const CPVT_WordInfo & wordinfo);
+ FX_BOOL GetLineInfo(const CPVT_WordPlace & place, CPVT_LineInfo & lineinfo);
+ FX_BOOL GetSectionInfo(const CPVT_WordPlace & place, CPVT_SectionInfo & secinfo);
+ FX_FLOAT GetWordFontSize(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize = FALSE);
+ FX_FLOAT GetWordWidth(FX_INT32 nFontIndex, FX_WORD Word, FX_WORD SubWord,
+ FX_FLOAT fCharSpace, FX_INT32 nHorzScale,
+ FX_FLOAT fFontSize, FX_FLOAT fWordTail, FX_INT32 nWordStyle);
+ FX_FLOAT GetWordWidth(const CPVT_WordInfo & WordInfo);
+ FX_FLOAT GetWordAscent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize);
+ FX_FLOAT GetWordDescent(const CPVT_WordInfo & WordInfo, FX_FLOAT fFontSize);
+ FX_FLOAT GetWordAscent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize = FALSE);
+ FX_FLOAT GetWordDescent(const CPVT_WordInfo & WordInfo, FX_BOOL bFactFontSize = FALSE);
+ FX_FLOAT GetLineAscent(const CPVT_SectionInfo & SecInfo);
+ FX_FLOAT GetLineDescent(const CPVT_SectionInfo & SecInfo);
+ FX_FLOAT GetFontAscent(FX_INT32 nFontIndex, FX_FLOAT fFontSize);
+ FX_FLOAT GetFontDescent(FX_INT32 nFontIndex, FX_FLOAT fFontSize);
+ FX_INT32 GetWordFontIndex(const CPVT_WordInfo & WordInfo);
+ FX_FLOAT GetCharSpace(const CPVT_WordInfo & WordInfo);
+ FX_INT32 GetHorzScale(const CPVT_WordInfo & WordInfo);
+ FX_FLOAT GetLineLeading(const CPVT_SectionInfo & SecInfo);
+ FX_FLOAT GetLineIndent(const CPVT_SectionInfo & SecInfo);
+ FX_INT32 GetAlignment(const CPVT_SectionInfo& SecInfo);
+
+ void ClearSectionRightWords(const CPVT_WordPlace & place);
+ CPVT_WordPlace AjustLineHeader(const CPVT_WordPlace & place, FX_BOOL bPrevOrNext) const;
+ FX_BOOL ClearEmptySection(const CPVT_WordPlace & place);
+ void ClearEmptySections(const CPVT_WordRange & PlaceRange);
+ void LinkLatterSection(const CPVT_WordPlace & place);
+ void ClearWords(const CPVT_WordRange & PlaceRange);
+ CPVT_WordPlace ClearLeftWord(const CPVT_WordPlace & place);
+ CPVT_WordPlace ClearRightWord(const CPVT_WordPlace & place);
+private:
+ CPVT_FloatRect Rearrange(const CPVT_WordRange & PlaceRange);
+ FX_FLOAT GetAutoFontSize();
+ FX_BOOL IsBigger(FX_FLOAT fFontSize);
+ CPVT_FloatRect RearrangeSections(const CPVT_WordRange & PlaceRange);
+private:
+ void ResetSectionArray();
+private:
+ CPVT_ArrayTemplate<CSection*> m_SectionArray;
+ FX_INT32 m_nLimitChar;
+ FX_INT32 m_nCharArray;
+ FX_BOOL m_bMultiLine;
+ FX_BOOL m_bLimitWidth;
+ FX_BOOL m_bAutoFontSize;
+ FX_INT32 m_nAlignment;
+ FX_FLOAT m_fLineLeading;
+ FX_FLOAT m_fCharSpace;
+ FX_INT32 m_nHorzScale;
+ FX_WORD m_wSubWord;
+ FX_FLOAT m_fWordSpace;
+ FX_FLOAT m_fFontSize;
+
+private:
+ FX_BOOL m_bInitial;
+ FX_BOOL m_bRichText;
+ FX_FLOAT m_fCaretOriginX;
+ FX_INT32 m_nCurFontIndex;
+ IPDF_VariableText_Provider * m_pVTProvider;
+ CPDF_VariableText_Iterator * m_pVTIterator;
+};
+class CPDF_VariableText_Iterator : public IPDF_VariableText_Iterator, public CFX_Object
+{
+public:
+ CPDF_VariableText_Iterator(CPDF_VariableText * pVT);
+ virtual ~CPDF_VariableText_Iterator();
+ FX_BOOL NextWord();
+ FX_BOOL PrevWord();
+ FX_BOOL NextLine();
+ FX_BOOL PrevLine();
+ FX_BOOL NextSection();
+ FX_BOOL PrevSection();
+ FX_BOOL SetWord(const CPVT_Word & word);
+ FX_BOOL GetWord(CPVT_Word & word) const;
+ FX_BOOL GetLine(CPVT_Line & line) const;
+ FX_BOOL GetSection(CPVT_Section & section) const;
+ FX_BOOL SetSection(const CPVT_Section & section);
+ void SetAt(FX_INT32 nWordIndex);
+ void SetAt(const CPVT_WordPlace & place);
+ const CPVT_WordPlace & GetAt() const
+ {
+ return m_CurPos;
+ };
+private:
+ CPVT_WordPlace m_CurPos;
+ CPDF_VariableText * m_pVT;
+};
diff --git a/core/src/fpdfdoc/tagged_int.h b/core/src/fpdfdoc/tagged_int.h new file mode 100644 index 0000000000..a343a801f3 --- /dev/null +++ b/core/src/fpdfdoc/tagged_int.h @@ -0,0 +1,91 @@ +// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#ifndef _FPDF_TAGGED_INT_H_
+#define _FPDF_TAGGED_INT_H_
+class CPDF_StructTreeImpl;
+class CPDF_StructElementImpl;
+class CPDF_StructTreeImpl : public CPDF_StructTree
+{
+public:
+ CPDF_StructTreeImpl(const CPDF_Document* pDoc);
+ ~CPDF_StructTreeImpl();
+ int CountTopElements() const
+ {
+ return m_Kids.GetSize();
+ }
+ CPDF_StructElement* GetTopElement(int i) const
+ {
+ return (CPDF_StructElement*)m_Kids.GetAt(i);
+ }
+ void LoadDocTree();
+ void LoadPageTree(const CPDF_Dictionary* pPageDict);
+ CPDF_StructElementImpl* AddPageNode(CPDF_Dictionary* pElement, CFX_MapPtrToPtr& map, int nLevel = 0);
+ FX_BOOL AddTopLevelNode(CPDF_Dictionary* pDict, CPDF_StructElementImpl* pElement);
+protected:
+ const CPDF_Dictionary* m_pTreeRoot;
+ const CPDF_Dictionary* m_pRoleMap;
+ const CPDF_Dictionary* m_pPage;
+ CFX_ArrayTemplate<CPDF_StructElementImpl*> m_Kids;
+ friend class CPDF_StructElementImpl;
+};
+class CPDF_StructElementImpl : public CPDF_StructElement
+{
+public:
+ CPDF_StructElementImpl(CPDF_StructTreeImpl* pTree, CPDF_StructElementImpl* pParent, CPDF_Dictionary* pDict);
+ ~CPDF_StructElementImpl();
+ CPDF_StructTree* GetTree() const
+ {
+ return m_pTree;
+ }
+ const CFX_ByteString& GetType() const
+ {
+ return m_Type;
+ }
+ CPDF_StructElement* GetParent() const
+ {
+ return m_pParent;
+ }
+ CPDF_Dictionary * GetDict() const
+ {
+ return m_pDict;
+ }
+ int CountKids() const
+ {
+ return m_Kids.GetSize();
+ }
+ const CPDF_StructKid& GetKid(int index) const
+ {
+ return m_Kids.GetData()[index];
+ }
+ CFX_PtrArray* GetObjectArray()
+ {
+ return &m_ObjectArray;
+ }
+
+ CPDF_Object* GetAttr(FX_BSTR owner, FX_BSTR name, FX_BOOL bInheritable = FALSE, FX_FLOAT fLevel = 0.0F);
+
+ CFX_ByteString GetName(FX_BSTR owner, FX_BSTR name, FX_BSTR default_value, FX_BOOL bInheritable = FALSE, int subindex = -1);
+ FX_ARGB GetColor(FX_BSTR owner, FX_BSTR name, FX_ARGB default_value, FX_BOOL bInheritable = FALSE, int subindex = -1);
+ FX_FLOAT GetNumber(FX_BSTR owner, FX_BSTR name, FX_FLOAT default_value, FX_BOOL bInheritable = FALSE, int subindex = -1);
+ int GetInteger(FX_BSTR owner, FX_BSTR name, int default_value, FX_BOOL bInheritable = FALSE, int subindex = -1);
+ CFX_PtrArray m_ObjectArray;
+ void LoadKids(CPDF_Dictionary* pDict);
+ void LoadKid(FX_DWORD PageObjNum, CPDF_Object* pObj, CPDF_StructKid* pKid);
+ CPDF_Object* GetAttr(FX_BSTR owner, FX_BSTR name, FX_BOOL bInheritable, int subindex);
+ CPDF_StructElementImpl* Retain();
+ void Release();
+protected:
+ CPDF_StructTreeImpl* m_pTree;
+ CFX_ByteString m_Type;
+ CPDF_StructElementImpl* m_pParent;
+ CPDF_Dictionary* m_pDict;
+ CFX_ArrayTemplate<CPDF_StructKid> m_Kids;
+
+ int m_RefCount;
+ friend class CPDF_StructTreeImpl;
+};
+#endif
|