1 // Copyright 2017 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 #include <utility>
6
7 #include "core/fpdfapi/cpdf_modulemgr.h"
8 #include "core/fpdfapi/font/cpdf_font.h"
9 #include "core/fpdfapi/font/cpdf_type1font.h"
10 #include "core/fpdfapi/page/cpdf_textobject.h"
11 #include "core/fpdfapi/parser/cpdf_array.h"
12 #include "core/fpdfapi/parser/cpdf_dictionary.h"
13 #include "core/fpdfapi/parser/cpdf_document.h"
14 #include "core/fpdfapi/parser/cpdf_name.h"
15 #include "core/fpdfapi/parser/cpdf_number.h"
16 #include "core/fpdfapi/parser/cpdf_reference.h"
17 #include "core/fpdfapi/parser/cpdf_stream.h"
18 #include "core/fxge/cfx_fontmgr.h"
19 #include "core/fxge/fx_font.h"
20 #include "fpdfsdk/fsdk_define.h"
21 #include "public/fpdf_edit.h"
22
FPDFPageObj_NewTextObj(FPDF_DOCUMENT document,FPDF_BYTESTRING font,float font_size)23 DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_NewTextObj(FPDF_DOCUMENT document,
24 FPDF_BYTESTRING font,
25 float font_size) {
26 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
27 if (!pDoc)
28 return nullptr;
29
30 CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc, CFX_ByteStringC(font));
31 if (!pFont)
32 return nullptr;
33
34 CPDF_TextObject* pTextObj = new CPDF_TextObject;
35 pTextObj->m_TextState.SetFont(pFont);
36 pTextObj->m_TextState.SetFontSize(font_size);
37 pTextObj->DefaultStates();
38 return pTextObj;
39 }
40
FPDFText_SetText(FPDF_PAGEOBJECT text_object,FPDF_BYTESTRING text)41 DLLEXPORT FPDF_BOOL STDCALL FPDFText_SetText(FPDF_PAGEOBJECT text_object,
42 FPDF_BYTESTRING text) {
43 if (!text_object)
44 return false;
45
46 auto pTextObj = reinterpret_cast<CPDF_TextObject*>(text_object);
47 pTextObj->SetText(CFX_ByteString(text));
48 return true;
49 }
50
FPDFText_LoadType1Font(FPDF_DOCUMENT document,const uint8_t * data,uint32_t size)51 DLLEXPORT FPDF_FONT STDCALL FPDFText_LoadType1Font(FPDF_DOCUMENT document,
52 const uint8_t* data,
53 uint32_t size) {
54 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document);
55 if (!pDoc || !data || size == 0)
56 return nullptr;
57
58 auto pFont = pdfium::MakeUnique<CFX_Font>();
59
60 // TODO(npm): Maybe use FT_Get_X11_Font_Format to check format?
61 if (!pFont->LoadEmbedded(data, size))
62 return nullptr;
63
64 CPDF_Dictionary* fontDict = pDoc->NewIndirect<CPDF_Dictionary>();
65 fontDict->SetNewFor<CPDF_Name>("Type", "Font");
66 fontDict->SetNewFor<CPDF_Name>("Subtype", "Type1");
67 CFX_ByteString name = pFont->GetFaceName();
68 if (name.IsEmpty())
69 name = "Unnamed";
70 fontDict->SetNewFor<CPDF_Name>("BaseFont", name);
71
72 uint32_t glyphIndex;
73 int currentChar = FXFT_Get_First_Char(pFont->GetFace(), &glyphIndex);
74 fontDict->SetNewFor<CPDF_Number>("FirstChar", currentChar);
75 int nextChar;
76 CPDF_Array* widthsArray = pDoc->NewIndirect<CPDF_Array>();
77 while (true) {
78 int width = pFont->GetGlyphWidth(glyphIndex);
79 widthsArray->AddNew<CPDF_Number>(width);
80 nextChar = FXFT_Get_Next_Char(pFont->GetFace(), currentChar, &glyphIndex);
81 if (glyphIndex == 0)
82 break;
83 for (int i = currentChar + 1; i < nextChar; i++)
84 widthsArray->AddNew<CPDF_Number>(0);
85 currentChar = nextChar;
86 }
87 fontDict->SetNewFor<CPDF_Number>("LastChar", currentChar);
88 fontDict->SetNewFor<CPDF_Reference>("Widths", pDoc, widthsArray->GetObjNum());
89 CPDF_Dictionary* fontDesc = pDoc->NewIndirect<CPDF_Dictionary>();
90 fontDesc->SetNewFor<CPDF_Name>("Type", "FontDescriptor");
91 fontDesc->SetNewFor<CPDF_Name>("FontName", name);
92 int flags = 0;
93 if (FXFT_Is_Face_fixedwidth(pFont->GetFace()))
94 flags |= FXFONT_FIXED_PITCH;
95 if (name.Find("Serif") > -1)
96 flags |= FXFONT_SERIF;
97 if (FXFT_Is_Face_Italic(pFont->GetFace()))
98 flags |= FXFONT_ITALIC;
99 if (FXFT_Is_Face_Bold(pFont->GetFace()))
100 flags |= FXFONT_BOLD;
101
102 // TODO(npm): How do I know if a Type1 font is symbolic, script, allcap,
103 // smallcap
104 flags |= FXFONT_NONSYMBOLIC;
105
106 fontDesc->SetNewFor<CPDF_Number>("Flags", flags);
107 FX_RECT bbox;
108 pFont->GetBBox(bbox);
109 auto pBBox = pdfium::MakeUnique<CPDF_Array>();
110 pBBox->AddNew<CPDF_Number>(bbox.left);
111 pBBox->AddNew<CPDF_Number>(bbox.bottom);
112 pBBox->AddNew<CPDF_Number>(bbox.right);
113 pBBox->AddNew<CPDF_Number>(bbox.top);
114 fontDesc->SetFor("FontBBox", std::move(pBBox));
115
116 // TODO(npm): calculate italic angle correctly
117 fontDesc->SetNewFor<CPDF_Number>("ItalicAngle", pFont->IsItalic() ? -12 : 0);
118
119 fontDesc->SetNewFor<CPDF_Number>("Ascent", pFont->GetAscent());
120 fontDesc->SetNewFor<CPDF_Number>("Descent", pFont->GetDescent());
121
122 // TODO(npm): calculate the capheight, stemV correctly
123 fontDesc->SetNewFor<CPDF_Number>("CapHeight", pFont->GetAscent());
124 fontDesc->SetNewFor<CPDF_Number>("StemV", pFont->IsBold() ? 120 : 70);
125
126 CPDF_Stream* pStream = pDoc->NewIndirect<CPDF_Stream>();
127 pStream->SetData(data, size);
128 fontDesc->SetNewFor<CPDF_Reference>("FontFile", pDoc, pStream->GetObjNum());
129 fontDict->SetNewFor<CPDF_Reference>("FontDescriptor", pDoc,
130 fontDesc->GetObjNum());
131 return pDoc->LoadFont(fontDict);
132 }
133