// 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/fsdk_define.h" | |
#include "../include/fpdfdoc.h" | |
static int this_module = 0; | |
static CPDF_Bookmark FindBookmark(CPDF_BookmarkTree& tree, CPDF_Bookmark This, const CFX_WideString& title) | |
{ | |
if (This != NULL) { | |
// First check this item | |
CFX_WideString this_title = This.GetTitle(); | |
if (this_title.CompareNoCase(title) == 0) | |
return This; | |
} | |
// go into children items | |
CPDF_Bookmark Child = tree.GetFirstChild(This); | |
while (Child != NULL) { | |
// check if this item | |
CPDF_Bookmark Found = FindBookmark(tree, Child, title); | |
if (Found) return Found; | |
Child = tree.GetNextSibling(Child); | |
} | |
return NULL; | |
} | |
DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_Find(FPDF_DOCUMENT document, FPDF_WIDESTRING title) | |
{ | |
if (document == NULL) return NULL; | |
if (title == NULL || title[0] == 0) return NULL; | |
CPDF_Document* pDoc = (CPDF_Document*)document; | |
CPDF_BookmarkTree tree(pDoc); | |
CFX_WideString wstr = CFX_WideString::FromUTF16LE(title); | |
return FindBookmark(tree, NULL, wstr); | |
} | |
DLLEXPORT FPDF_DEST STDCALL FPDFBookmark_GetDest(FPDF_DOCUMENT document, FPDF_BOOKMARK bookmark) | |
{ | |
if (document == NULL) return NULL; | |
if (bookmark == NULL) return NULL; | |
CPDF_Bookmark Bookmark = (CPDF_Dictionary*)bookmark; | |
CPDF_Document* pDoc = (CPDF_Document*)document; | |
CPDF_Dest dest = Bookmark.GetDest(pDoc); | |
if (dest != NULL) return dest; | |
// If this bookmark is not directly associated with a dest, we try to get action | |
CPDF_Action Action = Bookmark.GetAction(); | |
if (Action == NULL) return NULL; | |
return Action.GetDest(pDoc); | |
} | |
DLLEXPORT FPDF_ACTION STDCALL FPDFBookmark_GetAction(FPDF_BOOKMARK bookmark) | |
{ | |
if (bookmark == NULL) return NULL; | |
CPDF_Bookmark Bookmark = (CPDF_Dictionary*)bookmark; | |
return Bookmark.GetAction(); | |
} | |
DLLEXPORT unsigned long STDCALL FPDFAction_GetType(FPDF_ACTION action) | |
{ | |
if (action == NULL) return 0; | |
CPDF_Action Action = (CPDF_Dictionary*)action; | |
CPDF_Action::ActionType type = Action.GetType(); | |
switch (type) { | |
case CPDF_Action::GoTo: | |
return PDFACTION_GOTO; | |
case CPDF_Action::GoToR: | |
return PDFACTION_REMOTEGOTO; | |
case CPDF_Action::URI: | |
return PDFACTION_URI; | |
case CPDF_Action::Launch: | |
return PDFACTION_LAUNCH; | |
default: | |
return PDFACTION_UNSUPPORTED; | |
} | |
return PDFACTION_UNSUPPORTED; | |
} | |
DLLEXPORT FPDF_DEST STDCALL FPDFAction_GetDest(FPDF_DOCUMENT document, FPDF_ACTION action) | |
{ | |
if (document == NULL) return NULL; | |
if (action == NULL) return NULL; | |
CPDF_Document* pDoc = (CPDF_Document*)document; | |
CPDF_Action Action = (CPDF_Dictionary*)action; | |
return Action.GetDest(pDoc); | |
} | |
DLLEXPORT unsigned long STDCALL FPDFAction_GetURIPath(FPDF_DOCUMENT document, FPDF_ACTION action, | |
void* buffer, unsigned long buflen) | |
{ | |
if (document == NULL) return 0; | |
if (action == NULL) return 0; | |
CPDF_Document* pDoc = (CPDF_Document*)document; | |
CPDF_Action Action = (CPDF_Dictionary*)action; | |
CFX_ByteString path = Action.GetURI(pDoc); | |
unsigned long len = path.GetLength() + 1; | |
if (buffer != NULL && buflen >= len) | |
FXSYS_memcpy(buffer, (FX_LPCSTR)path, len); | |
return len; | |
} | |
DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document, FPDF_DEST dest) | |
{ | |
if (document == NULL) return 0; | |
if (dest == NULL) return 0; | |
CPDF_Document* pDoc = (CPDF_Document*)document; | |
CPDF_Dest Dest = (CPDF_Array*)dest; | |
return Dest.GetPageIndex(pDoc); | |
} | |
static void ReleaseLinkList(FX_LPVOID data) | |
{ | |
delete (CPDF_LinkList*)data; | |
} | |
DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page, double x, double y) | |
{ | |
if (page == NULL) return NULL; | |
CPDF_Page* pPage = (CPDF_Page*)page; | |
// Link list is stored with the document | |
CPDF_Document* pDoc = pPage->m_pDocument; | |
CPDF_LinkList* pLinkList = (CPDF_LinkList*)pDoc->GetPrivateData(&this_module); | |
if (pLinkList == NULL) { | |
pLinkList = FX_NEW CPDF_LinkList(pDoc); | |
pDoc->SetPrivateData(&this_module, pLinkList, ReleaseLinkList); | |
} | |
return pLinkList->GetLinkAtPoint(pPage, (FX_FLOAT)x, (FX_FLOAT)y); | |
} | |
DLLEXPORT FPDF_DEST STDCALL FPDFLink_GetDest(FPDF_DOCUMENT document, FPDF_LINK link) | |
{ | |
if (document == NULL) return NULL; | |
CPDF_Document* pDoc = (CPDF_Document*)document; | |
if (link == NULL) return NULL; | |
CPDF_Link Link = (CPDF_Dictionary*)link; | |
FPDF_DEST dest = Link.GetDest(pDoc); | |
if (dest) return dest; | |
// If this link is not directly associated with a dest, we try to get action | |
CPDF_Action Action = Link.GetAction(); | |
if (Action == NULL) return NULL; | |
return Action.GetDest(pDoc); | |
} | |
DLLEXPORT FPDF_ACTION STDCALL FPDFLink_GetAction(FPDF_LINK link) | |
{ | |
if (link == NULL) return NULL; | |
CPDF_Link Link = (CPDF_Dictionary*)link; | |
return Link.GetAction(); | |
} | |
DLLEXPORT FPDF_BOOL STDCALL FPDFLink_Enumerate(FPDF_PAGE page, int* startPos, FPDF_LINK* linkAnnot) | |
{ | |
if(!page || !startPos || !linkAnnot) | |
return FALSE; | |
CPDF_Page* pPage = (CPDF_Page*)page; | |
if(!pPage->m_pFormDict) return FALSE; | |
CPDF_Array* pAnnots = pPage->m_pFormDict->GetArray("Annots"); | |
if(!pAnnots) return FALSE; | |
for (int i = *startPos; i < (int)pAnnots->GetCount(); i ++) { | |
CPDF_Dictionary* pDict = (CPDF_Dictionary*)pAnnots->GetElementValue(i); | |
if (pDict == NULL || pDict->GetType() != PDFOBJ_DICTIONARY) continue; | |
if(pDict->GetString(FX_BSTRC("Subtype")).Equal(FX_BSTRC("Link"))) | |
{ | |
*startPos = i+1; | |
*linkAnnot = (FPDF_LINK)pDict; | |
return TRUE; | |
} | |
} | |
return FALSE; | |
} | |
DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetAnnotRect(FPDF_LINK linkAnnot, FS_RECTF* rect) | |
{ | |
if(!linkAnnot || !rect) | |
return FALSE; | |
CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot; | |
CPDF_Rect rt = pAnnotDict->GetRect(FX_BSTRC("Rect")); | |
rect->left = rt.left; | |
rect->bottom = rt.bottom; | |
rect->right = rt.right; | |
rect->top = rt.top; | |
return TRUE; | |
} | |
DLLEXPORT int STDCALL FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot) | |
{ | |
if(!linkAnnot) | |
return 0; | |
CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot; | |
CPDF_Array* pArray = pAnnotDict->GetArray(FX_BSTRC("QuadPoints")); | |
if (pArray == NULL) | |
return 0; | |
else | |
return pArray->GetCount() / 8; | |
} | |
DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot, int quadIndex, FS_QUADPOINTSF* quadPoints) | |
{ | |
if(!linkAnnot || !quadPoints) | |
return FALSE; | |
CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot; | |
CPDF_Array* pArray = pAnnotDict->GetArray(FX_BSTRC("QuadPoints")); | |
if (pArray) { | |
if (0 > quadIndex || quadIndex >= (int)pArray->GetCount()/8 || | |
((quadIndex*8+7) >= (int)pArray->GetCount())) return FALSE; | |
quadPoints->x1 = pArray->GetNumber(quadIndex*8); | |
quadPoints->y1 = pArray->GetNumber(quadIndex*8+1); | |
quadPoints->x2 = pArray->GetNumber(quadIndex*8+2); | |
quadPoints->y2 = pArray->GetNumber(quadIndex*8+3); | |
quadPoints->x3 = pArray->GetNumber(quadIndex*8+4); | |
quadPoints->y3 = pArray->GetNumber(quadIndex*8+5); | |
quadPoints->x4 = pArray->GetNumber(quadIndex*8+6); | |
quadPoints->y4 = pArray->GetNumber(quadIndex*8+7); | |
return TRUE; | |
} | |
return FALSE; | |
} | |
DLLEXPORT unsigned long STDCALL FPDF_GetMetaText(FPDF_DOCUMENT doc, FPDF_BYTESTRING tag, | |
void* buffer, unsigned long buflen) | |
{ | |
if (doc == NULL || tag == NULL) return 0; | |
CPDF_Document* pDoc = (CPDF_Document*)doc; | |
// Get info dictionary | |
CPDF_Dictionary* pInfo = pDoc->GetInfo(); | |
if (pInfo == NULL) return 0; | |
CFX_WideString text = pInfo->GetUnicodeText(tag); | |
// Use UTF-16LE encoding | |
CFX_ByteString bstr = text.UTF16LE_Encode(); | |
unsigned long len = bstr.GetLength(); | |
if (buffer != NULL || buflen >= len+2) { | |
FXSYS_memcpy(buffer, (FX_LPCSTR)bstr, len); | |
// use double zero as trailer | |
((FX_BYTE*)buffer)[len] = ((FX_BYTE*)buffer)[len+1] = 0; | |
} | |
return len+2; | |
} | |