Serenity Operating System
1/*
2 * Copyright (c) 2022, Matthew Olsson <mattco@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/String.h>
8#include <AK/StringView.h>
9#include <LibGfx/Font/FontDatabase.h>
10#include <LibPDF/CommonNames.h>
11#include <LibPDF/Fonts/PDFFont.h>
12#include <LibPDF/Fonts/TrueTypeFont.h>
13#include <LibPDF/Fonts/Type0Font.h>
14#include <LibPDF/Fonts/Type1Font.h>
15
16namespace PDF {
17
18[[maybe_unused]] static bool is_standard_latin_font(DeprecatedFlyString const& font)
19{
20 return font.is_one_of(
21 "Times-Roman", "TimesNewRoman",
22 "Helvetica", "Arial",
23 "Courier", "CourierNew",
24 "Times-Bold", "TimesNewRoman,Bold",
25 "Helvetica-Bold", "Arial,Bold",
26 "Courier-Bold", "CourierNew,Bold",
27 "Times-Italic", "TimesNewRoman,Italic",
28 "Helvetica-Oblique", "Arial,Italic",
29 "Courier-Oblique", "CourierNew,Italic",
30 "Times-BoldItalic", "TimesNewRoman,BoldItalic",
31 "Helvetica-BoldOblique", "Arial,BoldItalic",
32 "Courier-BoldOblique", "CourierNew,BoldItalic");
33}
34
35PDFErrorOr<NonnullRefPtr<PDFFont>> PDFFont::create(Document* document, NonnullRefPtr<DictObject> const& dict, float font_size)
36{
37 auto subtype = TRY(dict->get_name(document, CommonNames::Subtype))->name();
38
39 RefPtr<PDFFont> font;
40 if (subtype == "Type1")
41 font = adopt_ref(*new Type1Font());
42 else if (subtype == "TrueType")
43 font = adopt_ref(*new TrueTypeFont());
44 else if (subtype == "Type0")
45 font = adopt_ref(*new Type0Font());
46 else
47 return Error::internal_error("Unhandled font subtype: {}", subtype);
48
49 TRY(font->initialize(document, dict, font_size));
50 return font.release_nonnull();
51}
52
53PDFErrorOr<void> PDFFont::initialize(Document* document, NonnullRefPtr<DictObject> const& dict, float)
54{
55 m_base_font_name = TRY(dict->get_name(document, CommonNames::BaseFont))->name();
56 return {};
57}
58
59PDFErrorOr<NonnullRefPtr<Gfx::Font>> PDFFont::replacement_for(StringView name, float font_size)
60{
61 bool is_bold = name.contains("bold"sv, CaseSensitivity::CaseInsensitive);
62 bool is_italic = name.contains("italic"sv, CaseSensitivity::CaseInsensitive);
63
64 DeprecatedString font_family;
65 if (name.contains("times"sv, CaseSensitivity::CaseInsensitive)) {
66 font_family = "Liberation Serif";
67 } else if (name.contains("courier"sv, CaseSensitivity::CaseInsensitive)) {
68 font_family = "Liberation Mono";
69 } else {
70 font_family = "Liberation Sans";
71 }
72
73 DeprecatedString font_variant;
74
75 if (is_bold && is_italic) {
76 font_variant = "BoldItalic";
77 } else if (is_bold) {
78 font_variant = "Bold";
79 } else if (is_italic) {
80 font_variant = "Italic";
81 } else {
82 font_variant = "Regular";
83 }
84
85 float point_size = (font_size * POINTS_PER_INCH) / DEFAULT_DPI;
86 auto font = Gfx::FontDatabase::the().get(font_family, font_variant, point_size);
87 if (!font)
88 Error::internal_error("Failed to load {} {} at {}pt", font_family, font_variant, point_size);
89 return font.release_nonnull();
90}
91
92}