summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolas Pena <npm@chromium.org>2017-05-02 14:12:50 -0400
committerChromium commit bot <commit-bot@chromium.org>2017-05-02 18:37:40 +0000
commitb31618571938e4873dcf1cdd44eeedb40caa5bd7 (patch)
treea337f11a62a35e8c0d52be8c5c9ec55902a6055a
parent336544a7451ac80c9f33216b7f61e9347d251108 (diff)
downloadpdfium-b31618571938e4873dcf1cdd44eeedb40caa5bd7.tar.xz
Add API to create a text object using a loaded font.
There is already a method to add text from standard font, this CL adds an option to add text using a loaded font. The font set into a text object is ref counted and may be released, so call LoadFont on this new text obj, and add a method to close the font. This CL also improves the SetText method so that it now uses a WideString, in preparation for CID fonts with non-Latin characters. Bug: pdfium:667 Change-Id: I6829d702357d2a898a12f5297e4fd2ec993a9891 Reviewed-on: https://pdfium-review.googlesource.com/4770 Reviewed-by: Tom Sepez <tsepez@chromium.org> Commit-Queue: Nicolás Peña <npm@chromium.org>
-rw-r--r--fpdfsdk/fpdfedit_embeddertest.cpp152
-rw-r--r--fpdfsdk/fpdfedittext.cpp41
-rw-r--r--fpdfsdk/fpdfview_c_api_test.c2
-rw-r--r--public/cpp/fpdf_deleters.h5
-rw-r--r--public/fpdf_edit.h23
5 files changed, 184 insertions, 39 deletions
diff --git a/fpdfsdk/fpdfedit_embeddertest.cpp b/fpdfsdk/fpdfedit_embeddertest.cpp
index d62f5ca85c..4bf68cfe5e 100644
--- a/fpdfsdk/fpdfedit_embeddertest.cpp
+++ b/fpdfsdk/fpdfedit_embeddertest.cpp
@@ -14,6 +14,7 @@
#include "core/fpdfapi/parser/cpdf_stream.h"
#include "core/fxcrt/fx_system.h"
#include "fpdfsdk/fsdk_define.h"
+#include "public/cpp/fpdf_deleters.h"
#include "public/fpdf_edit.h"
#include "public/fpdfview.h"
#include "testing/embedder_test.h"
@@ -423,11 +424,14 @@ TEST_F(FPDFEditEmbeddertest, AddStandardFontText) {
FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
// Add some text to the page
- FPDF_PAGEOBJECT text1 = FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
- EXPECT_TRUE(text1);
- EXPECT_TRUE(FPDFText_SetText(text1, "I'm at the bottom of the page"));
- FPDFPageObj_Transform(text1, 1, 0, 0, 1, 20, 20);
- FPDFPage_InsertObject(page, text1);
+ FPDF_PAGEOBJECT text_object1 =
+ FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
+ EXPECT_TRUE(text_object1);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text1 =
+ GetFPDFWideString(L"I'm at the bottom of the page");
+ EXPECT_TRUE(FPDFText_SetText(text_object1, text1.get()));
+ FPDFPageObj_Transform(text_object1, 1, 0, 0, 1, 20, 20);
+ FPDFPage_InsertObject(page, text_object1);
EXPECT_TRUE(FPDFPage_GenerateContent(page));
FPDF_BITMAP page_bitmap = RenderPage(page);
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
@@ -439,12 +443,14 @@ TEST_F(FPDFEditEmbeddertest, AddStandardFontText) {
FPDFBitmap_Destroy(page_bitmap);
// Try another font
- FPDF_PAGEOBJECT text2 =
+ FPDF_PAGEOBJECT text_object2 =
FPDFPageObj_NewTextObj(document(), "TimesNewRomanBold", 15.0f);
- EXPECT_TRUE(text2);
- EXPECT_TRUE(FPDFText_SetText(text2, "Hi, I'm Bold. Times New Roman Bold."));
- FPDFPageObj_Transform(text2, 1, 0, 0, 1, 100, 600);
- FPDFPage_InsertObject(page, text2);
+ EXPECT_TRUE(text_object2);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text2 =
+ GetFPDFWideString(L"Hi, I'm Bold. Times New Roman Bold.");
+ EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
+ FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 100, 600);
+ FPDFPage_InsertObject(page, text_object2);
EXPECT_TRUE(FPDFPage_GenerateContent(page));
page_bitmap = RenderPage(page);
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
@@ -458,12 +464,14 @@ TEST_F(FPDFEditEmbeddertest, AddStandardFontText) {
FPDFBitmap_Destroy(page_bitmap);
// And some randomly transformed text
- FPDF_PAGEOBJECT text3 =
+ FPDF_PAGEOBJECT text_object3 =
FPDFPageObj_NewTextObj(document(), "Courier-Bold", 20.0f);
- EXPECT_TRUE(text3);
- EXPECT_TRUE(FPDFText_SetText(text3, "Can you read me? <:)>"));
- FPDFPageObj_Transform(text3, 1, 1.5, 2, 0.5, 200, 200);
- FPDFPage_InsertObject(page, text3);
+ EXPECT_TRUE(text_object3);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text3 =
+ GetFPDFWideString(L"Can you read me? <:)>");
+ EXPECT_TRUE(FPDFText_SetText(text_object3, text3.get()));
+ FPDFPageObj_Transform(text_object3, 1, 1.5, 2, 0.5, 200, 200);
+ FPDFPage_InsertObject(page, text_object3);
EXPECT_TRUE(FPDFPage_GenerateContent(page));
page_bitmap = RenderPage(page);
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
@@ -522,10 +530,13 @@ TEST_F(FPDFEditEmbeddertest, DoubleGenerating) {
FPDFBitmap_Destroy(page_bitmap);
// Add some text to the page
- FPDF_PAGEOBJECT text = FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
- EXPECT_TRUE(FPDFText_SetText(text, "Something something #text# something"));
- FPDFPageObj_Transform(text, 1, 0, 0, 1, 300, 300);
- FPDFPage_InsertObject(page, text);
+ FPDF_PAGEOBJECT text_object =
+ FPDFPageObj_NewTextObj(document(), "Arial", 12.0f);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
+ GetFPDFWideString(L"Something something #text# something");
+ EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
+ FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 300, 300);
+ FPDFPage_InsertObject(page, text_object);
EXPECT_TRUE(FPDFPage_GenerateContent(page));
CPDF_Dictionary* font_dict = the_page->m_pResources->GetDictFor("Font");
ASSERT_TRUE(font_dict);
@@ -545,10 +556,10 @@ TEST_F(FPDFEditEmbeddertest, LoadSimpleType1Font) {
CPDF_Font::GetStockFont(cpdf_doc(), "Times-Bold");
const uint8_t* data = stock_font->m_Font.GetFontData();
const uint32_t size = stock_font->m_Font.GetSize();
- FPDF_FONT font =
- FPDFText_LoadFont(document(), data, size, FPDF_FONT_TYPE1, false);
- ASSERT_TRUE(font);
- CPDF_Font* typed_font = reinterpret_cast<CPDF_Font*>(font);
+ std::unique_ptr<void, FPDFFontDeleter> font(
+ FPDFText_LoadFont(document(), data, size, FPDF_FONT_TYPE1, false));
+ ASSERT_TRUE(font.get());
+ CPDF_Font* typed_font = reinterpret_cast<CPDF_Font*>(font.get());
EXPECT_TRUE(typed_font->IsType1Font());
CPDF_Dictionary* font_dict = typed_font->GetFontDict();
@@ -574,10 +585,10 @@ TEST_F(FPDFEditEmbeddertest, LoadSimpleTrueTypeFont) {
const CPDF_Font* stock_font = CPDF_Font::GetStockFont(cpdf_doc(), "Courier");
const uint8_t* data = stock_font->m_Font.GetFontData();
const uint32_t size = stock_font->m_Font.GetSize();
- FPDF_FONT font =
- FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, false);
- ASSERT_TRUE(font);
- CPDF_Font* typed_font = reinterpret_cast<CPDF_Font*>(font);
+ std::unique_ptr<void, FPDFFontDeleter> font(
+ FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, false));
+ ASSERT_TRUE(font.get());
+ CPDF_Font* typed_font = reinterpret_cast<CPDF_Font*>(font.get());
EXPECT_TRUE(typed_font->IsTrueTypeFont());
CPDF_Dictionary* font_dict = typed_font->GetFontDict();
@@ -604,10 +615,10 @@ TEST_F(FPDFEditEmbeddertest, LoadCIDType0Font) {
CPDF_Font::GetStockFont(cpdf_doc(), "Times-Roman");
const uint8_t* data = stock_font->m_Font.GetFontData();
const uint32_t size = stock_font->m_Font.GetSize();
- FPDF_FONT font =
- FPDFText_LoadFont(document(), data, size, FPDF_FONT_TYPE1, 1);
- ASSERT_TRUE(font);
- CPDF_Font* typed_font = reinterpret_cast<CPDF_Font*>(font);
+ std::unique_ptr<void, FPDFFontDeleter> font(
+ FPDFText_LoadFont(document(), data, size, FPDF_FONT_TYPE1, 1));
+ ASSERT_TRUE(font.get());
+ CPDF_Font* typed_font = reinterpret_cast<CPDF_Font*>(font.get());
EXPECT_TRUE(typed_font->IsCIDFont());
// Check font dictionary entries
@@ -660,10 +671,10 @@ TEST_F(FPDFEditEmbeddertest, LoadCIDType2Font) {
const uint8_t* data = stock_font->m_Font.GetFontData();
const uint32_t size = stock_font->m_Font.GetSize();
- FPDF_FONT font =
- FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, 1);
- ASSERT_TRUE(font);
- CPDF_Font* typed_font = reinterpret_cast<CPDF_Font*>(font);
+ std::unique_ptr<void, FPDFFontDeleter> font(
+ FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, 1));
+ ASSERT_TRUE(font.get());
+ CPDF_Font* typed_font = reinterpret_cast<CPDF_Font*>(font.get());
EXPECT_TRUE(typed_font->IsCIDFont());
// Check font dictionary entries
@@ -704,3 +715,74 @@ TEST_F(FPDFEditEmbeddertest, NormalizeNegativeRotation) {
EXPECT_EQ(3, FPDFPage_GetRotation(page));
UnloadPage(page);
}
+
+TEST_F(FPDFEditEmbeddertest, AddTrueTypeFontText) {
+ // Start with a blank page
+ FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792);
+ {
+ const CPDF_Font* stock_font = CPDF_Font::GetStockFont(cpdf_doc(), "Arial");
+ const uint8_t* data = stock_font->m_Font.GetFontData();
+ const uint32_t size = stock_font->m_Font.GetSize();
+ std::unique_ptr<void, FPDFFontDeleter> font(
+ FPDFText_LoadFont(document(), data, size, FPDF_FONT_TRUETYPE, 0));
+ ASSERT_TRUE(font.get());
+
+ // Add some text to the page
+ FPDF_PAGEOBJECT text_object =
+ FPDFPageObj_CreateTextObj(document(), font.get(), 12.0f);
+ EXPECT_TRUE(text_object);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text =
+ GetFPDFWideString(L"I am testing my loaded font, WEE.");
+ EXPECT_TRUE(FPDFText_SetText(text_object, text.get()));
+ FPDFPageObj_Transform(text_object, 1, 0, 0, 1, 400, 400);
+ FPDFPage_InsertObject(page, text_object);
+ EXPECT_TRUE(FPDFPage_GenerateContent(page));
+ FPDF_BITMAP page_bitmap = RenderPage(page);
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+ const char md5[] = "17d2b6cd574cf66170b09c8927529a94";
+#else
+ const char md5[] = "28e5b10743660dcdfd1618db47b39d32";
+#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+ CompareBitmap(page_bitmap, 612, 792, md5);
+ FPDFBitmap_Destroy(page_bitmap);
+
+ // Add some more text, same font
+ FPDF_PAGEOBJECT text_object2 =
+ FPDFPageObj_CreateTextObj(document(), font.get(), 15.0f);
+ std::unique_ptr<unsigned short, pdfium::FreeDeleter> text2 =
+ GetFPDFWideString(L"Bigger font size");
+ EXPECT_TRUE(FPDFText_SetText(text_object2, text2.get()));
+ FPDFPageObj_Transform(text_object2, 1, 0, 0, 1, 200, 200);
+ FPDFPage_InsertObject(page, text_object2);
+ EXPECT_TRUE(FPDFPage_GenerateContent(page));
+ }
+ FPDF_BITMAP page_bitmap2 = RenderPage(page);
+#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+ const char md5_2[] = "8eded4193ff1f0f77b8b600a825e97ea";
+#else
+ const char md5_2[] = "a068eef4110d607f77c87ea8340fa2a5";
+#endif // _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
+ CompareBitmap(page_bitmap2, 612, 792, md5_2);
+ FPDFBitmap_Destroy(page_bitmap2);
+
+ EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+ FPDF_ClosePage(page);
+ std::string new_file = GetString();
+
+ // Render the saved result
+ FPDF_FILEACCESS file_access;
+ memset(&file_access, 0, sizeof(file_access));
+ file_access.m_FileLen = new_file.size();
+ file_access.m_GetBlock = GetBlockFromString;
+ file_access.m_Param = &new_file;
+ FPDF_DOCUMENT new_doc = FPDF_LoadCustomDocument(&file_access, nullptr);
+ ASSERT_NE(nullptr, new_doc);
+ EXPECT_EQ(1, FPDF_GetPageCount(new_doc));
+ FPDF_PAGE new_page = FPDF_LoadPage(new_doc, 0);
+ ASSERT_NE(nullptr, new_page);
+ FPDF_BITMAP new_bitmap = RenderPage(new_page);
+ CompareBitmap(new_bitmap, 612, 792, md5_2);
+ FPDFBitmap_Destroy(new_bitmap);
+ FPDF_ClosePage(new_page);
+ FPDF_CloseDocument(new_doc);
+}
diff --git a/fpdfsdk/fpdfedittext.cpp b/fpdfsdk/fpdfedittext.cpp
index aec6050d21..f4e1d66bc1 100644
--- a/fpdfsdk/fpdfedittext.cpp
+++ b/fpdfsdk/fpdfedittext.cpp
@@ -8,6 +8,7 @@
#include "core/fpdfapi/cpdf_modulemgr.h"
#include "core/fpdfapi/font/cpdf_font.h"
#include "core/fpdfapi/font/cpdf_type1font.h"
+#include "core/fpdfapi/page/cpdf_docpagedata.h"
#include "core/fpdfapi/page/cpdf_textobject.h"
#include "core/fpdfapi/parser/cpdf_array.h"
#include "core/fpdfapi/parser/cpdf_dictionary.h"
@@ -236,12 +237,20 @@ DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_NewTextObj(FPDF_DOCUMENT document,
}
DLLEXPORT FPDF_BOOL STDCALL FPDFText_SetText(FPDF_PAGEOBJECT text_object,
- FPDF_BYTESTRING text) {
+ FPDF_WIDESTRING text) {
if (!text_object)
return false;
auto* pTextObj = reinterpret_cast<CPDF_TextObject*>(text_object);
- pTextObj->SetText(CFX_ByteString(text));
+ FX_STRSIZE len = CFX_WideString::WStringLength(text);
+ CFX_WideString encodedText = CFX_WideString::FromUTF16LE(text, len);
+ CFX_ByteString byteText;
+ for (int i = 0; i < encodedText.GetLength(); ++i) {
+ uint32_t charcode =
+ pTextObj->GetFont()->CharCodeFromUnicode(encodedText[i]);
+ pTextObj->GetFont()->AppendChar(&byteText, charcode);
+ }
+ pTextObj->SetText(byteText);
return true;
}
@@ -267,3 +276,31 @@ DLLEXPORT FPDF_FONT STDCALL FPDFText_LoadFont(FPDF_DOCUMENT document,
return cid ? LoadCompositeFont(pDoc, std::move(pFont), data, size, font_type)
: LoadSimpleFont(pDoc, std::move(pFont), data, size, font_type);
}
+
+DLLEXPORT void STDCALL FPDFFont_Close(FPDF_FONT font) {
+ if (!font)
+ return;
+
+ CPDF_Font* cpdf_font = reinterpret_cast<CPDF_Font*>(font);
+ CPDF_Document* pDoc = cpdf_font->m_pDocument;
+ CPDF_DocPageData* pPageData = pDoc ? pDoc->GetPageData() : nullptr;
+ if (pPageData && !pPageData->IsForceClear())
+ pPageData->ReleaseFont(cpdf_font->GetFontDict());
+}
+
+DLLEXPORT FPDF_PAGEOBJECT STDCALL
+FPDFPageObj_CreateTextObj(FPDF_DOCUMENT document,
+ FPDF_FONT font,
+ float font_size) {
+ CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
+ if (!pDoc || !font)
+ return nullptr;
+
+ CPDF_Font* pFont = reinterpret_cast<CPDF_Font*>(font);
+
+ auto pTextObj = pdfium::MakeUnique<CPDF_TextObject>();
+ pTextObj->m_TextState.SetFont(pDoc->LoadFont(pFont->GetFontDict()));
+ pTextObj->m_TextState.SetFontSize(font_size);
+ pTextObj->DefaultStates();
+ return pTextObj.release();
+}
diff --git a/fpdfsdk/fpdfview_c_api_test.c b/fpdfsdk/fpdfview_c_api_test.c
index b4da951947..1606abbf08 100644
--- a/fpdfsdk/fpdfview_c_api_test.c
+++ b/fpdfsdk/fpdfview_c_api_test.c
@@ -102,6 +102,8 @@ int CheckPDFiumCApi() {
CHK(FPDFPageObj_NewTextObj);
CHK(FPDFText_SetText);
CHK(FPDFText_LoadFont);
+ CHK(FPDFFont_Close);
+ CHK(FPDFPageObj_CreateTextObj);
// fpdf_ext.h
CHK(FSDK_SetUnSpObjProcessHandler);
diff --git a/public/cpp/fpdf_deleters.h b/public/cpp/fpdf_deleters.h
index d56daf5c55..238ef30e62 100644
--- a/public/cpp/fpdf_deleters.h
+++ b/public/cpp/fpdf_deleters.h
@@ -6,6 +6,7 @@
#define PUBLIC_CPP_FPDF_DELETERS_H_
#include "public/fpdf_dataavail.h"
+#include "public/fpdf_edit.h"
#include "public/fpdf_formfill.h"
#include "public/fpdf_structtree.h"
#include "public/fpdf_text.h"
@@ -43,4 +44,8 @@ struct FPDFStructTreeDeleter {
inline void operator()(FPDF_STRUCTTREE tree) { FPDF_StructTree_Close(tree); }
};
+struct FPDFFontDeleter {
+ inline void operator()(FPDF_FONT font) { FPDFFont_Close(font); }
+};
+
#endif // PUBLIC_CPP_FPDF_DELETERS_H_
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index 4d06c2a0c8..5784b90feb 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -436,11 +436,11 @@ DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_NewTextObj(FPDF_DOCUMENT document,
// Set the text for a textobject. If it had text, it will be replaced.
//
// text_object - handle to the text object.
-// text - string containing the text to be added.
+// text - the UTF-16LE encoded string containing the text to be added.
//
// Returns TRUE on success
DLLEXPORT FPDF_BOOL STDCALL FPDFText_SetText(FPDF_PAGEOBJECT text_object,
- FPDF_BYTESTRING text);
+ FPDF_WIDESTRING text);
// Returns a font object loaded from a stream of data. The font is loaded
// into the document. The caller does not need to free the returned object.
@@ -452,6 +452,8 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFText_SetText(FPDF_PAGEOBJECT text_object,
// type.
// cid - a boolean specifying if the font is a CID font or not.
//
+// The loaded font can be closed using FPDF_Font_Close.
+//
// Returns NULL on failure
DLLEXPORT FPDF_FONT STDCALL FPDFText_LoadFont(FPDF_DOCUMENT document,
const uint8_t* data,
@@ -459,6 +461,23 @@ DLLEXPORT FPDF_FONT STDCALL FPDFText_LoadFont(FPDF_DOCUMENT document,
int font_type,
FPDF_BOOL cid);
+// Close a loaded PDF font.
+//
+// font - Handle to the loaded font.
+DLLEXPORT void STDCALL FPDFFont_Close(FPDF_FONT font);
+
+// Create a new text object using a loaded font.
+//
+// document - handle to the document.
+// font - handle to the font object.
+// font_size - the font size for the new text object.
+//
+// Returns a handle to a new text object, or NULL on failure
+DLLEXPORT FPDF_PAGEOBJECT STDCALL
+FPDFPageObj_CreateTextObj(FPDF_DOCUMENT document,
+ FPDF_FONT font,
+ float font_size);
+
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus