fpdfedittext.cpp revision 5ae9d0c6fd838a2967cca72aa5751b51dadc2769
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 23DLLEXPORT 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 41DLLEXPORT 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 51DLLEXPORT 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