• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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