Home | History | Annotate | Download | only in src
      1 // Copyright 2014 PDFium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
      6 
      7 #include "../include/fsdk_define.h"
      8 #include "../../public/fpdf_doc.h"
      9 
     10 static int THISMODULE = 0;
     11 
     12 static CPDF_Bookmark FindBookmark(const CPDF_BookmarkTree& tree, CPDF_Bookmark bookmark, const CFX_WideString& title)
     13 {
     14 	if (bookmark && bookmark.GetTitle().CompareNoCase(title.c_str()) == 0) {
     15 		// First check this item
     16 		return bookmark;
     17 	}
     18 	// go into children items
     19 	CPDF_Bookmark child = tree.GetFirstChild(bookmark);
     20 	while (child) {
     21 		// check if this item
     22 		CPDF_Bookmark found = FindBookmark(tree, child, title);
     23 		if (found)
     24 			return found;
     25 		child = tree.GetNextSibling(child);
     26 	}
     27 	return CPDF_Bookmark();
     28 }
     29 
     30 DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_GetFirstChild(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict)
     31 {
     32     if (!document)
     33         return NULL;
     34     CPDF_Document* pDoc = (CPDF_Document*)document;
     35     CPDF_BookmarkTree tree(pDoc);
     36     CPDF_Bookmark bookmark = CPDF_Bookmark((CPDF_Dictionary*)pDict);
     37     return tree.GetFirstChild(bookmark).GetDict();
     38 }
     39 
     40 DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_GetNextSibling(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict)
     41 {
     42     if (!document || !pDict)
     43         return NULL;
     44     CPDF_Document* pDoc = (CPDF_Document*)document;
     45     CPDF_BookmarkTree tree(pDoc);
     46     CPDF_Bookmark bookmark = CPDF_Bookmark((CPDF_Dictionary*)pDict);
     47     return tree.GetNextSibling(bookmark).GetDict();
     48 }
     49 
     50 DLLEXPORT unsigned long STDCALL FPDFBookmark_GetTitle(FPDF_BOOKMARK pDict, void* buffer, unsigned long buflen)
     51 {
     52     if (!pDict)
     53         return 0;
     54     CPDF_Bookmark bookmark((CPDF_Dictionary*)pDict);
     55     CFX_WideString title = bookmark.GetTitle();
     56     CFX_ByteString encodedTitle = title.UTF16LE_Encode();
     57     unsigned long len = encodedTitle.GetLength();
     58     if (buffer && buflen >= len) {
     59         FXSYS_memcpy(buffer, encodedTitle.c_str(), len);
     60     }
     61     return len;
     62 }
     63 
     64 DLLEXPORT FPDF_BOOKMARK STDCALL FPDFBookmark_Find(FPDF_DOCUMENT document, FPDF_WIDESTRING title)
     65 {
     66 	if (!document)
     67 		return NULL;
     68 	if (!title || title[0] == 0)
     69 		return NULL;
     70 	CPDF_Document* pDoc = (CPDF_Document*)document;
     71 	CPDF_BookmarkTree tree(pDoc);
     72 	FX_STRSIZE len = CFX_WideString::WStringLength(title);
     73 	CFX_WideString encodedTitle = CFX_WideString::FromUTF16LE(title, len);
     74 	return FindBookmark(tree, CPDF_Bookmark(), encodedTitle).GetDict();
     75 }
     76 
     77 DLLEXPORT FPDF_DEST STDCALL FPDFBookmark_GetDest(FPDF_DOCUMENT document, FPDF_BOOKMARK pDict)
     78 {
     79 	if (!document)
     80 		return NULL;
     81 	if (!pDict)
     82 		return NULL;
     83 	CPDF_Bookmark bookmark((CPDF_Dictionary*)pDict);
     84 	CPDF_Document* pDoc = (CPDF_Document*)document;
     85 	CPDF_Dest dest = bookmark.GetDest(pDoc);
     86 	if (dest)
     87 		return dest.GetObject();
     88 	// If this bookmark is not directly associated with a dest, we try to get action
     89 	CPDF_Action action = bookmark.GetAction();
     90 	if (!action)
     91 		return NULL;
     92 	return action.GetDest(pDoc).GetObject();
     93 }
     94 
     95 DLLEXPORT FPDF_ACTION STDCALL FPDFBookmark_GetAction(FPDF_BOOKMARK pDict)
     96 {
     97 	if (!pDict)
     98 		return NULL;
     99 	CPDF_Bookmark bookmark((CPDF_Dictionary*)pDict);
    100 	return bookmark.GetAction().GetDict();
    101 }
    102 
    103 DLLEXPORT unsigned long STDCALL FPDFAction_GetType(FPDF_ACTION pDict)
    104 {
    105 	if (!pDict)
    106 		return 0;
    107 	CPDF_Action action((CPDF_Dictionary*)pDict);
    108 	CPDF_Action::ActionType type = action.GetType();
    109 	switch (type) {
    110 		case CPDF_Action::GoTo:
    111 			return PDFACTION_GOTO;
    112 		case CPDF_Action::GoToR:
    113 			return PDFACTION_REMOTEGOTO;
    114 		case CPDF_Action::URI:
    115 			return PDFACTION_URI;
    116 		case CPDF_Action::Launch:
    117 			return PDFACTION_LAUNCH;
    118 		default:
    119 			return PDFACTION_UNSUPPORTED;
    120 	}
    121 	return PDFACTION_UNSUPPORTED;
    122 }
    123 
    124 DLLEXPORT FPDF_DEST STDCALL FPDFAction_GetDest(FPDF_DOCUMENT document, FPDF_ACTION pDict)
    125 {
    126 	if (!document)
    127 		return NULL;
    128 	if (!pDict)
    129 		return NULL;
    130 	CPDF_Document* pDoc = (CPDF_Document*)document;
    131 	CPDF_Action action((CPDF_Dictionary*)pDict);
    132 	return action.GetDest(pDoc).GetObject();
    133 }
    134 
    135 DLLEXPORT unsigned long STDCALL FPDFAction_GetURIPath(FPDF_DOCUMENT document, FPDF_ACTION pDict,
    136 											  void* buffer, unsigned long buflen)
    137 {
    138 	if (!document)
    139 		return 0;
    140 	if (!pDict)
    141 		return 0;
    142 	CPDF_Document* pDoc = (CPDF_Document*)document;
    143 	CPDF_Action action((CPDF_Dictionary*)pDict);
    144 	CFX_ByteString path = action.GetURI(pDoc);
    145 	unsigned long len = path.GetLength() + 1;
    146 	if (buffer != NULL && buflen >= len)
    147 		FXSYS_memcpy(buffer, path.c_str(), len);
    148 	return len;
    149 }
    150 
    151 DLLEXPORT unsigned long STDCALL FPDFDest_GetPageIndex(FPDF_DOCUMENT document, FPDF_DEST pDict)
    152 {
    153 	if (!document)
    154 		return 0;
    155 	if (!pDict)
    156 		return 0;
    157 	CPDF_Document* pDoc = (CPDF_Document*)document;
    158 	CPDF_Dest dest((CPDF_Array*)pDict);
    159 	return dest.GetPageIndex(pDoc);
    160 }
    161 
    162 static void ReleaseLinkList(FX_LPVOID data)
    163 {
    164 	delete (CPDF_LinkList*)data;
    165 }
    166 
    167 DLLEXPORT FPDF_LINK STDCALL FPDFLink_GetLinkAtPoint(FPDF_PAGE page, double x, double y)
    168 {
    169 	if (!page)
    170 		return NULL;
    171 	CPDF_Page* pPage = (CPDF_Page*)page;
    172 	// Link list is stored with the document
    173 	CPDF_Document* pDoc = pPage->m_pDocument;
    174 	CPDF_LinkList* pLinkList = (CPDF_LinkList*)pDoc->GetPrivateData(&THISMODULE);
    175 	if (!pLinkList) {
    176 		pLinkList = new CPDF_LinkList(pDoc);
    177 		pDoc->SetPrivateData(&THISMODULE, pLinkList, ReleaseLinkList);
    178 	}
    179 	return pLinkList->GetLinkAtPoint(pPage, (FX_FLOAT)x, (FX_FLOAT)y).GetDict();
    180 }
    181 
    182 DLLEXPORT FPDF_DEST STDCALL FPDFLink_GetDest(FPDF_DOCUMENT document, FPDF_LINK pDict)
    183 {
    184 	if (!document)
    185 		return NULL;
    186 	if (!pDict)
    187 		return NULL;
    188 	CPDF_Document* pDoc = (CPDF_Document*)document;
    189 	CPDF_Link link((CPDF_Dictionary*)pDict);
    190 	FPDF_DEST dest = link.GetDest(pDoc).GetObject();
    191 	if (dest)
    192 		return dest;
    193 	// If this link is not directly associated with a dest, we try to get action
    194 	CPDF_Action action = link.GetAction();
    195 	if (!action)
    196 		return NULL;
    197 	return action.GetDest(pDoc).GetObject();
    198 }
    199 
    200 DLLEXPORT FPDF_ACTION STDCALL FPDFLink_GetAction(FPDF_LINK pDict)
    201 {
    202 	if (!pDict)
    203 		return NULL;
    204 	CPDF_Link link((CPDF_Dictionary*)pDict);
    205 	return link.GetAction().GetDict();
    206 }
    207 
    208 DLLEXPORT FPDF_BOOL STDCALL FPDFLink_Enumerate(FPDF_PAGE page, int* startPos, FPDF_LINK* linkAnnot)
    209 {
    210 	if(!page || !startPos || !linkAnnot)
    211 		return FALSE;
    212 	CPDF_Page* pPage = (CPDF_Page*)page;
    213 	if(!pPage->m_pFormDict)
    214 		return FALSE;
    215 	CPDF_Array* pAnnots = pPage->m_pFormDict->GetArray("Annots");
    216 	if(!pAnnots)
    217 		return FALSE;
    218 	for (int i = *startPos; i < (int)pAnnots->GetCount(); i++) {
    219 		CPDF_Dictionary* pDict = (CPDF_Dictionary*)pAnnots->GetElementValue(i);
    220 		if (!pDict || pDict->GetType() != PDFOBJ_DICTIONARY)
    221 			continue;
    222 		if(pDict->GetString(FX_BSTRC("Subtype")).Equal(FX_BSTRC("Link"))) {
    223 			*startPos = i + 1;
    224 			*linkAnnot = (FPDF_LINK)pDict;
    225 			return TRUE;
    226 		}
    227 	}
    228 	return FALSE;
    229 }
    230 
    231 DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetAnnotRect(FPDF_LINK linkAnnot, FS_RECTF* rect)
    232 {
    233 	if(!linkAnnot || !rect)
    234 		return FALSE;
    235 	CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
    236 	CPDF_Rect rt = pAnnotDict->GetRect(FX_BSTRC("Rect"));
    237 	rect->left = rt.left;
    238 	rect->bottom = rt.bottom;
    239 	rect->right = rt.right;
    240 	rect->top = rt.top;
    241 	return TRUE;
    242 }
    243 
    244 DLLEXPORT int STDCALL FPDFLink_CountQuadPoints(FPDF_LINK linkAnnot)
    245 {
    246 	if(!linkAnnot)
    247 		return 0;
    248 	CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
    249 	CPDF_Array* pArray = pAnnotDict->GetArray(FX_BSTRC("QuadPoints"));
    250 	if (!pArray)
    251 		return 0;
    252 	else
    253 		return pArray->GetCount() / 8;
    254 }
    255 
    256 DLLEXPORT FPDF_BOOL STDCALL FPDFLink_GetQuadPoints(FPDF_LINK linkAnnot, int quadIndex, FS_QUADPOINTSF* quadPoints)
    257 {
    258 	if(!linkAnnot || !quadPoints)
    259 		return FALSE;
    260 	CPDF_Dictionary* pAnnotDict = (CPDF_Dictionary*)linkAnnot;
    261 	CPDF_Array* pArray = pAnnotDict->GetArray(FX_BSTRC("QuadPoints"));
    262 	if (pArray) {
    263 		if (quadIndex < 0 || quadIndex >= (int)pArray->GetCount()/8 || ((quadIndex*8+7) >= (int)pArray->GetCount()))
    264 			return FALSE;
    265 		quadPoints->x1 = pArray->GetNumber(quadIndex*8);
    266 		quadPoints->y1 = pArray->GetNumber(quadIndex*8+1);
    267 		quadPoints->x2 = pArray->GetNumber(quadIndex*8+2);
    268 		quadPoints->y2 = pArray->GetNumber(quadIndex*8+3);
    269 		quadPoints->x3 = pArray->GetNumber(quadIndex*8+4);
    270 		quadPoints->y3 = pArray->GetNumber(quadIndex*8+5);
    271 		quadPoints->x4 = pArray->GetNumber(quadIndex*8+6);
    272 		quadPoints->y4 = pArray->GetNumber(quadIndex*8+7);
    273 		return TRUE;
    274 	}
    275 	return FALSE;
    276 }
    277 
    278 DLLEXPORT unsigned long STDCALL FPDF_GetMetaText(FPDF_DOCUMENT doc, FPDF_BYTESTRING tag,
    279 												 void* buffer, unsigned long buflen)
    280 {
    281 	if (!doc || !tag)
    282 		return 0;
    283 	CPDF_Document* pDoc = (CPDF_Document*)doc;
    284 	// Get info dictionary
    285 	CPDF_Dictionary* pInfo = pDoc->GetInfo();
    286 	if (!pInfo)
    287 		return 0;
    288 	CFX_WideString text = pInfo->GetUnicodeText(tag);
    289 	// Use UTF-16LE encoding
    290 	CFX_ByteString encodedText = text.UTF16LE_Encode();
    291 	unsigned long len = encodedText.GetLength();
    292 	if (buffer && buflen >= len) {
    293 		FXSYS_memcpy(buffer, encodedText.c_str(), len);
    294 	}
    295 	return len;
    296 }
    297