summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fpdfsdk/fpdf_edit_embeddertest.cpp215
-rw-r--r--fpdfsdk/fpdf_editpage.cpp30
-rw-r--r--public/fpdf_edit.h66
3 files changed, 260 insertions, 51 deletions
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp
index 3bacb0b2eb..4250091fce 100644
--- a/fpdfsdk/fpdf_edit_embeddertest.cpp
+++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -541,7 +541,11 @@ void CheckMarkCounts(FPDF_PAGE page,
FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
char buffer[256];
- ASSERT_GT(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer)), 0u);
+ unsigned long name_len = 999u;
+ ASSERT_TRUE(
+ FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
+ EXPECT_GT(name_len, 0u);
+ EXPECT_NE(999u, name_len);
std::wstring name =
GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
if (name == L"Prime") {
@@ -551,9 +555,9 @@ void CheckMarkCounts(FPDF_PAGE page,
int expected_square = start_from + i;
EXPECT_EQ(1, FPDFPageObjMark_CountParams(mark));
- unsigned long get_param_key_return =
- FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer));
- ASSERT_GT(get_param_key_return, 0u);
+ unsigned long get_param_key_return = 999u;
+ ASSERT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer),
+ &get_param_key_return));
EXPECT_EQ((6u + 1u) * 2u, get_param_key_return);
std::wstring key =
GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
@@ -571,9 +575,9 @@ void CheckMarkCounts(FPDF_PAGE page,
bounds_count++;
EXPECT_EQ(1, FPDFPageObjMark_CountParams(mark));
- unsigned long get_param_key_return =
- FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer));
- ASSERT_GT(get_param_key_return, 0u);
+ unsigned long get_param_key_return = 999u;
+ ASSERT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer),
+ &get_param_key_return));
EXPECT_EQ((8u + 1u) * 2u, get_param_key_return);
std::wstring key =
GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
@@ -660,7 +664,11 @@ TEST_F(FPDFEditEmbeddertest, RemoveMarkedObjectsPrime) {
FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
char buffer[256];
- ASSERT_GT(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer)), 0u);
+ unsigned long name_len = 999u;
+ ASSERT_TRUE(
+ FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
+ EXPECT_GT(name_len, 0u);
+ EXPECT_NE(999u, name_len);
std::wstring name =
GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
if (name == L"Prime") {
@@ -726,7 +734,11 @@ TEST_F(FPDFEditEmbeddertest, RemoveMarks) {
FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
char buffer[256];
- ASSERT_GT(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer)), 0u);
+ unsigned long name_len = 999u;
+ ASSERT_TRUE(
+ FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
+ EXPECT_GT(name_len, 0u);
+ EXPECT_NE(999u, name_len);
std::wstring name =
GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
if (name == L"Prime") {
@@ -775,7 +787,11 @@ TEST_F(FPDFEditEmbeddertest, RemoveMarkParam) {
FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
char buffer[256];
- ASSERT_GT(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer)), 0u);
+ unsigned long name_len = 999u;
+ ASSERT_TRUE(
+ FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
+ EXPECT_GT(name_len, 0u);
+ EXPECT_NE(999u, name_len);
std::wstring name =
GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
if (name == L"Square") {
@@ -812,7 +828,11 @@ TEST_F(FPDFEditEmbeddertest, RemoveMarkParam) {
FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, j);
char buffer[256];
- ASSERT_GT(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer)), 0u);
+ unsigned long name_len = 999u;
+ ASSERT_TRUE(
+ FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
+ EXPECT_GT(name_len, 0u);
+ EXPECT_NE(999u, name_len);
std::wstring name =
GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
if (name == L"Square") {
@@ -2497,7 +2517,9 @@ TEST_F(FPDFEditEmbeddertest, SetMarkParam) {
FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
ASSERT_TRUE(mark);
char buffer[256];
- ASSERT_GT(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer)), 0u);
+ unsigned long name_len = 999u;
+ ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
+ EXPECT_EQ((6u + 1u) * 2u, name_len);
ASSERT_EQ(L"Bounds",
GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
unsigned long out_buffer_len;
@@ -2573,7 +2595,9 @@ TEST_F(FPDFEditEmbeddertest, AddMarkedText) {
EXPECT_EQ(1, FPDFPageObj_CountMarks(text_object));
EXPECT_EQ(mark, FPDFPageObj_GetMark(text_object, 0));
char buffer[256];
- EXPECT_GT(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer)), 0u);
+ unsigned long name_len = 999u;
+ ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
+ EXPECT_EQ((14u + 1u) * 2, name_len);
std::wstring name =
GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
EXPECT_EQ(L"Test Mark Name", name);
@@ -2603,10 +2627,11 @@ TEST_F(FPDFEditEmbeddertest, AddMarkedText) {
EXPECT_EQ(FPDF_OBJECT_STRING,
FPDFPageObjMark_GetParamValueType(mark, "StringKey"));
- unsigned long out_buffer_len;
+ unsigned long out_buffer_len = 999u;
EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(
mark, "StringKey", buffer, sizeof(buffer), &out_buffer_len));
EXPECT_GT(out_buffer_len, 0u);
+ EXPECT_NE(999u, out_buffer_len);
name = GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
EXPECT_EQ(L"StringValue", name);
@@ -2648,7 +2673,10 @@ TEST_F(FPDFEditEmbeddertest, AddMarkedText) {
EXPECT_EQ(1, FPDFPageObj_CountMarks(text_object));
mark = FPDFPageObj_GetMark(text_object, 0);
EXPECT_TRUE(mark);
- EXPECT_GT(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer)), 0u);
+
+ name_len = 999u;
+ ASSERT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &name_len));
+ EXPECT_EQ((14u + 1u) * 2, name_len);
name = GetPlatformWString(reinterpret_cast<unsigned short*>(buffer));
EXPECT_EQ(L"Test Mark Name", name);
@@ -2656,6 +2684,163 @@ TEST_F(FPDFEditEmbeddertest, AddMarkedText) {
CloseSavedDocument();
}
+TEST_F(FPDFEditEmbeddertest, MarkGetName) {
+ EXPECT_TRUE(OpenDocument("text_in_page_marked.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+ FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
+ FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
+ ASSERT_TRUE(mark);
+
+ char buffer[256];
+ unsigned long out_len;
+
+ // Show the positive cases of FPDFPageObjMark_GetName.
+ out_len = 999u;
+ EXPECT_TRUE(FPDFPageObjMark_GetName(mark, nullptr, 0, &out_len));
+ EXPECT_EQ((6u + 1u) * 2u, out_len);
+
+ out_len = 999u;
+ EXPECT_TRUE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), &out_len));
+ EXPECT_EQ(L"Bounds",
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
+ EXPECT_EQ((6u + 1u) * 2u, out_len);
+
+ // Show the negative cases of FPDFPageObjMark_GetName.
+ out_len = 999u;
+ EXPECT_FALSE(
+ FPDFPageObjMark_GetName(nullptr, buffer, sizeof(buffer), &out_len));
+ EXPECT_EQ(999u, out_len);
+
+ EXPECT_FALSE(FPDFPageObjMark_GetName(mark, buffer, sizeof(buffer), nullptr));
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFEditEmbeddertest, MarkGetParamKey) {
+ EXPECT_TRUE(OpenDocument("text_in_page_marked.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+ FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
+ FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
+ ASSERT_TRUE(mark);
+
+ char buffer[256];
+ unsigned long out_len;
+
+ // Show the positive cases of FPDFPageObjMark_GetParamKey.
+ out_len = 999u;
+ EXPECT_TRUE(FPDFPageObjMark_GetParamKey(mark, 0, nullptr, 0, &out_len));
+ EXPECT_EQ((8u + 1u) * 2u, out_len);
+
+ out_len = 999u;
+ EXPECT_TRUE(
+ FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer), &out_len));
+ EXPECT_EQ(L"Position",
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
+ EXPECT_EQ((8u + 1u) * 2u, out_len);
+
+ // Show the negative cases of FPDFPageObjMark_GetParamKey.
+ out_len = 999u;
+ EXPECT_FALSE(FPDFPageObjMark_GetParamKey(nullptr, 0, buffer, sizeof(buffer),
+ &out_len));
+ EXPECT_EQ(999u, out_len);
+
+ out_len = 999u;
+ EXPECT_FALSE(
+ FPDFPageObjMark_GetParamKey(mark, 1, buffer, sizeof(buffer), &out_len));
+ EXPECT_EQ(999u, out_len);
+
+ EXPECT_FALSE(
+ FPDFPageObjMark_GetParamKey(mark, 0, buffer, sizeof(buffer), nullptr));
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFEditEmbeddertest, MarkGetIntParam) {
+ EXPECT_TRUE(OpenDocument("text_in_page_marked.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+ FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 8);
+ FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 0);
+ ASSERT_TRUE(mark);
+
+ int out_value;
+
+ // Show the positive cases of FPDFPageObjMark_GetParamIntValue.
+ out_value = 999;
+ EXPECT_TRUE(FPDFPageObjMark_GetParamIntValue(mark, "Factor", &out_value));
+ EXPECT_EQ(3, out_value);
+
+ // Show the negative cases of FPDFPageObjMark_GetParamIntValue.
+ out_value = 999;
+ EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(nullptr, "Factor", &out_value));
+ EXPECT_EQ(999, out_value);
+
+ out_value = 999;
+ EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "ParamThatDoesNotExist",
+ &out_value));
+ EXPECT_EQ(999, out_value);
+
+ EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "Factor", nullptr));
+
+ page_object = FPDFPage_GetObject(page, 18);
+ mark = FPDFPageObj_GetMark(page_object, 1);
+ out_value = 999;
+ EXPECT_FALSE(FPDFPageObjMark_GetParamIntValue(mark, "Position", &out_value));
+ EXPECT_EQ(999, out_value);
+
+ UnloadPage(page);
+}
+
+TEST_F(FPDFEditEmbeddertest, MarkGetStringParam) {
+ EXPECT_TRUE(OpenDocument("text_in_page_marked.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ ASSERT_TRUE(page);
+ FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(page, 18);
+ FPDF_PAGEOBJECTMARK mark = FPDFPageObj_GetMark(page_object, 1);
+ ASSERT_TRUE(mark);
+
+ char buffer[256];
+ unsigned long out_len;
+
+ // Show the positive cases of FPDFPageObjMark_GetParamStringValue.
+ out_len = 999u;
+ EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(mark, "Position", nullptr, 0,
+ &out_len));
+ EXPECT_EQ((4u + 1u) * 2u, out_len);
+
+ out_len = 999u;
+ EXPECT_TRUE(FPDFPageObjMark_GetParamStringValue(mark, "Position", buffer,
+ sizeof(buffer), &out_len));
+ EXPECT_EQ(L"Last",
+ GetPlatformWString(reinterpret_cast<unsigned short*>(buffer)));
+ EXPECT_EQ((4u + 1u) * 2u, out_len);
+
+ // Show the negative cases of FPDFPageObjMark_GetParamStringValue.
+ out_len = 999u;
+ EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(nullptr, "Position", buffer,
+ sizeof(buffer), &out_len));
+ EXPECT_EQ(999u, out_len);
+
+ out_len = 999u;
+ EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(
+ mark, "ParamThatDoesNotExist", buffer, sizeof(buffer), &out_len));
+ EXPECT_EQ(999u, out_len);
+
+ EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(mark, "Position", buffer,
+ sizeof(buffer), nullptr));
+
+ page_object = FPDFPage_GetObject(page, 8);
+ mark = FPDFPageObj_GetMark(page_object, 0);
+ out_len = 999u;
+ EXPECT_FALSE(FPDFPageObjMark_GetParamStringValue(mark, "Factor", buffer,
+ sizeof(buffer), &out_len));
+ EXPECT_EQ(999u, out_len);
+
+ UnloadPage(page);
+}
+
TEST_F(FPDFEditEmbeddertest, ExtractImageBitmap) {
ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
FPDF_PAGE page = LoadPage(0);
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp
index 30049342ca..c71f7e27be 100644
--- a/fpdfsdk/fpdf_editpage.cpp
+++ b/fpdfsdk/fpdf_editpage.cpp
@@ -345,19 +345,21 @@ FPDFPageObj_RemoveMark(FPDF_PAGEOBJECT page_object, FPDF_PAGEOBJECTMARK mark) {
return result;
}
-FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFPageObjMark_GetName(FPDF_PAGEOBJECTMARK mark,
void* buffer,
- unsigned long buflen) {
- if (!mark)
- return 0;
+ unsigned long buflen,
+ unsigned long* out_buflen) {
+ if (!mark || !out_buflen)
+ return false;
const CPDF_ContentMarkItem* pMarkItem =
CPDFContentMarkItemFromFPDFPageObjectMark(mark);
- return Utf16EncodeMaybeCopyAndReturnLength(
+ *out_buflen = Utf16EncodeMaybeCopyAndReturnLength(
WideString::FromUTF8(pMarkItem->GetName().AsStringView()), buffer,
buflen);
+ return true;
}
FPDF_EXPORT int FPDF_CALLCONV
@@ -372,24 +374,29 @@ FPDFPageObjMark_CountParams(FPDF_PAGEOBJECTMARK mark) {
return pParams ? pParams->GetCount() : 0;
}
-FPDF_EXPORT unsigned long FPDF_CALLCONV
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFPageObjMark_GetParamKey(FPDF_PAGEOBJECTMARK mark,
unsigned long index,
void* buffer,
- unsigned long buflen) {
+ unsigned long buflen,
+ unsigned long* out_buflen) {
+ if (!out_buflen)
+ return false;
+
const CPDF_Dictionary* pParams = GetMarkParamDict(mark);
if (!pParams)
- return 0;
+ return false;
for (auto& it : *pParams) {
if (index == 0) {
- return Utf16EncodeMaybeCopyAndReturnLength(
+ *out_buflen = Utf16EncodeMaybeCopyAndReturnLength(
WideString::FromUTF8(it.first.AsStringView()), buffer, buflen);
+ return true;
}
--index;
}
- return 0;
+ return false;
}
FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV
@@ -407,6 +414,9 @@ FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFPageObjMark_GetParamIntValue(FPDF_PAGEOBJECTMARK mark,
FPDF_BYTESTRING key,
int* out_value) {
+ if (!out_value)
+ return false;
+
const CPDF_Dictionary* pParams = GetMarkParamDict(mark);
if (!pParams)
return false;
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index dcf6201fe8..180d50247e 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -332,18 +332,23 @@ FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFPageObj_RemoveMark(FPDF_PAGEOBJECT page_object, FPDF_PAGEOBJECTMARK mark);
// Experimental API.
-// Get name of a content mark. |buffer| is only modified if |buflen| is longer
-// than the length of the name.
+// Get the name of a content mark.
//
-// mark - handle to a content mark.
-// buffer - buffer for holding the returned name in UTF16-LE.
-// buflen - length of the buffer.
+// mark - handle to a content mark.
+// buffer - buffer for holding the returned name in UTF16-LE. This is only
+// modified if |buflen| is longer than the length of the name.
+// Optional, pass null to just retrieve the size of the buffer
+// needed.
+// buflen - length of the buffer.
+// out_buflen - pointer to variable that will receive the minimum buffer size
+// to contain the name. Not filled if FALSE is returned.
//
-// Returns the length of the name.
-FPDF_EXPORT unsigned long FPDF_CALLCONV
+// Returns TRUE if the operation succeeded, FALSE if it failed.
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFPageObjMark_GetName(FPDF_PAGEOBJECTMARK mark,
void* buffer,
- unsigned long buflen);
+ unsigned long buflen,
+ unsigned long* out_buflen);
// Experimental API.
// Get the number of key/value pair parameters in |mark|.
@@ -356,20 +361,25 @@ FPDF_EXPORT int FPDF_CALLCONV
FPDFPageObjMark_CountParams(FPDF_PAGEOBJECTMARK mark);
// Experimental API.
-// Get the key of a property in a content mark. |buffer| is only modified if
-// |buflen| is longer than the length of the key.
+// Get the key of a property in a content mark.
//
-// mark - handle to a content mark.
-// index - index of the property.
-// buffer - buffer for holding the returned key in UTF16-LE.
-// buflen - length of the buffer.
+// mark - handle to a content mark.
+// index - index of the property.
+// buffer - buffer for holding the returned key in UTF16-LE. This is only
+// modified if |buflen| is longer than the length of the key.
+// Optional, pass null to just retrieve the size of the buffer
+// needed.
+// buflen - length of the buffer.
+// out_buflen - pointer to variable that will receive the minimum buffer size
+// to contain the key. Not filled if FALSE is returned.
//
-// Returns the length of the key.
-FPDF_EXPORT unsigned long FPDF_CALLCONV
+// Returns TRUE if the operation was successful, FALSE otherwise.
+FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
FPDFPageObjMark_GetParamKey(FPDF_PAGEOBJECTMARK mark,
unsigned long index,
void* buffer,
- unsigned long buflen);
+ unsigned long buflen,
+ unsigned long* out_buflen);
// Experimental API.
// Get the type of the value of a property in a content mark by key.
@@ -400,14 +410,17 @@ FPDFPageObjMark_GetParamIntValue(FPDF_PAGEOBJECTMARK mark,
// Experimental API.
// Get the value of a string property in a content mark by key.
-// |buffer| is only modified if |buflen| is longer than the length of the value.
//
// mark - handle to a content mark.
// key - string key of the property.
-// buffer - buffer for holding the returned value in UTF16-LE.
+// buffer - buffer for holding the returned value in UTF16-LE. This is
+// only modified if |buflen| is longer than the length of the
+// value.
+// Optional, pass null to just retrieve the size of the buffer
+// needed.
// buflen - length of the buffer.
-// out_buflen - pointer to variable that will receive the length of the value.
-// Not filled if false is returned.
+// out_buflen - pointer to variable that will receive the minimum buffer size
+// to contain the value. Not filled if FALSE is returned.
//
// Returns TRUE if the key maps to a string/blob value, FALSE otherwise.
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV
@@ -419,15 +432,16 @@ FPDFPageObjMark_GetParamStringValue(FPDF_PAGEOBJECTMARK mark,
// Experimental API.
// Get the value of a blob property in a content mark by key.
-// |buffer| is only modified if |buflen| is longer than or equal to the length
-// of the value.
//
// mark - handle to a content mark.
// key - string key of the property.
-// buffer - buffer for holding the returned value.
+// buffer - buffer for holding the returned value. This is only modified
+// if |buflen| is at least as long as the length of the value.
+// Optional, pass null to just retrieve the size of the buffer
+// needed.
// buflen - length of the buffer.
-// out_buflen - pointer to variable that will receive the length of the value.
-// Not filled if false is returned.
+// out_buflen - pointer to variable that will receive the minimum buffer size
+// to contain the value. Not filled if FALSE is returned.
//
// Returns TRUE if the key maps to a string/blob value, FALSE otherwise.
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV