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