Serenity Operating System
1/*
2 * Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#pragma once
8
9#include <AK/DeprecatedString.h>
10#include <AK/Format.h>
11#include <AK/StringBuilder.h>
12#include <AK/Vector.h>
13#include <LibPDF/Value.h>
14
15#define ENUMERATE_OPERATORS(V) \
16 V(SaveState, save_state, q) \
17 V(RestoreState, restore_state, Q) \
18 V(ConcatenateMatrix, concatenate_matrix, cm) \
19 V(SetLineWidth, set_line_width, w) \
20 V(SetLineCap, set_line_cap, J) \
21 V(SetLineJoin, set_line_join, j) \
22 V(SetMiterLimit, set_miter_limit, M) \
23 V(SetDashPattern, set_dash_pattern, d) \
24 V(SetColorRenderingIntent, set_color_rendering_intent, ri) \
25 V(SetFlatnessTolerance, set_flatness_tolerance, i) \
26 V(SetGraphicsStateFromDict, set_graphics_state_from_dict, gs) \
27 V(PathMove, path_move, m) \
28 V(PathLine, path_line, l) \
29 V(PathCubicBezierCurve, path_cubic_bezier_curve, c) \
30 V(PathCubicBezierCurveNoFirstControl, path_cubic_bezier_curve_no_first_control, v) \
31 V(PathCubicBezierCurveNoSecondControl, path_cubic_bezier_curve_no_second_control, y) \
32 V(PathClose, path_close, h) \
33 V(PathAppendRect, path_append_rect, re) \
34 V(PathStroke, path_stroke, S) \
35 V(PathCloseAndStroke, path_close_and_stroke, s) \
36 V(PathFillNonZero, path_fill_nonzero, f) \
37 V(PathFillNonZeroDeprecated, path_fill_nonzero_deprecated, F) \
38 V(PathFillEvenOdd, path_fill_evenodd, f*) \
39 V(PathFillStrokeNonZero, path_fill_stroke_nonzero, B) \
40 V(PathFillStrokeEvenOdd, path_fill_stroke_evenodd, B*) \
41 V(PathCloseFillStrokeNonZero, path_close_fill_stroke_nonzero, b) \
42 V(PathCloseFillStrokeEvenOdd, path_close_fill_stroke_evenodd, b*) \
43 V(PathEnd, path_end, n) \
44 V(PathIntersectClipNonZero, path_intersect_clip_nonzero, W) \
45 V(PathIntersectClipEvenOdd, path_intersect_clip_evenodd, W*) \
46 V(TextBegin, text_begin, BT) \
47 V(TextEnd, text_end, ET) \
48 V(TextSetCharSpace, text_set_char_space, Tc) \
49 V(TextSetWordSpace, text_set_word_space, Tw) \
50 V(TextSetHorizontalScale, text_set_horizontal_scale, Tz) \
51 V(TextSetLeading, text_set_leading, TL) \
52 V(TextSetFont, text_set_font, Tf) \
53 V(TextSetRenderingMode, text_set_rendering_mode, Tr) \
54 V(TextSetRise, text_set_rise, Ts) \
55 V(TextNextLineOffset, text_next_line_offset, Td) \
56 V(TextNextLineAndSetLeading, text_next_line_and_set_leading, TD) \
57 V(TextSetMatrixAndLineMatrix, text_set_matrix_and_line_matrix, Tm) \
58 V(TextNextLine, text_next_line, T*) \
59 V(TextShowString, text_show_string, Tj) \
60 V(TextShowStringArray, text_show_string_array, TJ) \
61 V(Type3FontSetGlyphWidth, type3_font_set_glyph_width, d0) \
62 V(Type3FontSetGlyphWidthAndBBox, type3_font_set_glyph_width_and_bbox, d1) \
63 V(SetStrokingSpace, set_stroking_space, CS) \
64 V(SetPaintingSpace, set_painting_space, cs) \
65 V(SetStrokingColor, set_stroking_color, SC) \
66 V(SetStrokingColorExtended, set_stroking_color_extended, SCN) \
67 V(SetPaintingColor, set_painting_color, sc) \
68 V(SetPaintingColorExtended, set_painting_color_extended, scn) \
69 V(SetStrokingColorAndSpaceToGray, set_stroking_color_and_space_to_gray, G) \
70 V(SetPaintingColorAndSpaceToGray, set_painting_color_and_space_to_gray, g) \
71 V(SetStrokingColorAndSpaceToRGB, set_stroking_color_and_space_to_rgb, RG) \
72 V(SetPaintingColorAndSpaceToRGB, set_painting_color_and_space_to_rgb, rg) \
73 V(SetStrokingColorAndSpaceToCMYK, set_stroking_color_and_space_to_cmyk, K) \
74 V(SetPaintingColorAndSpaceToCMYK, set_painting_color_and_space_to_cmyk, k) \
75 V(Shade, shade, sh) \
76 V(InlineImageBegin, inline_image_begin, BI) \
77 V(InlineImageBeginData, inline_image_begin_data, ID) \
78 V(InlineImageEnd, inline_image_end, EI) \
79 V(PaintXObject, paint_xobject, Do) \
80 V(MarkedContentPoint, marked_content_point, MP) \
81 V(MarkedContentDesignate, marked_content_designate, DP) \
82 V(MarkedContentBegin, marked_content_begin, BMC) \
83 V(MarkedContentBeginWithPropertyList, marked_content_begin_with_property_list, BDC) \
84 V(MarkedContentEnd, marked_content_end, EMC) \
85 V(CompatibilityBegin, compatibility_begin, BX) \
86 V(CompatibilityEnd, compatibility_end, EX)
87
88namespace PDF {
89
90enum class OperatorType {
91#define V(name, snake_name, symbol) name,
92 ENUMERATE_OPERATORS(V)
93#undef V
94 TextNextLineShowString,
95 TextNextLineShowStringSetSpacing,
96};
97
98class Operator {
99public:
100 static OperatorType operator_type_from_symbol(StringView symbol_string)
101 {
102#define V(name, snake_name, symbol) \
103 if (symbol_string == #symbol) \
104 return OperatorType::name;
105 ENUMERATE_OPERATORS(V)
106#undef V
107
108 if (symbol_string == "'")
109 return OperatorType::TextNextLineShowString;
110 if (symbol_string == "''")
111 return OperatorType::TextNextLineShowStringSetSpacing;
112
113 dbgln("unsupported graphics symbol {}", symbol_string);
114 VERIFY_NOT_REACHED();
115 }
116
117 static char const* operator_name(OperatorType operator_type)
118 {
119#define V(name, snake_name, symbol) \
120 if (operator_type == OperatorType::name) \
121 return #name;
122 ENUMERATE_OPERATORS(V)
123#undef V
124
125 if (operator_type == OperatorType::TextNextLineShowString)
126 return "TextNextLineShowString";
127 if (operator_type == OperatorType::TextNextLineShowStringSetSpacing)
128 return "TextNextLineShowStringSetSpacing";
129
130 VERIFY_NOT_REACHED();
131 }
132
133 static char const* operator_symbol(OperatorType operator_type)
134 {
135#define V(name, snake_name, symbol) \
136 if (operator_type == OperatorType::name) \
137 return #symbol;
138 ENUMERATE_OPERATORS(V)
139#undef V
140
141 if (operator_type == OperatorType::TextNextLineShowString)
142 return "'";
143 if (operator_type == OperatorType::TextNextLineShowStringSetSpacing)
144 return "''";
145
146 VERIFY_NOT_REACHED();
147 }
148
149 Operator(OperatorType operator_type, Vector<Value> arguments)
150 : m_operator_type(operator_type)
151 , m_arguments(move(arguments))
152 {
153 }
154
155 [[nodiscard]] ALWAYS_INLINE OperatorType type() const { return m_operator_type; }
156 [[nodiscard]] ALWAYS_INLINE Vector<Value> const& arguments() const { return m_arguments; }
157
158private:
159 OperatorType m_operator_type;
160 Vector<Value> m_arguments;
161};
162
163}
164
165namespace AK {
166
167template<>
168struct Formatter<PDF::Operator> : Formatter<StringView> {
169 ErrorOr<void> format(FormatBuilder& format_builder, PDF::Operator const& op)
170 {
171 StringBuilder builder;
172 builder.appendff("{} ({})",
173 PDF::Operator::operator_name(op.type()),
174 PDF::Operator::operator_symbol(op.type()));
175
176 if (!op.arguments().is_empty()) {
177 builder.append(" ["sv);
178 for (auto& argument : op.arguments())
179 builder.appendff(" {}", argument);
180 builder.append(" ]"sv);
181 }
182
183 return Formatter<StringView>::format(format_builder, builder.to_deprecated_string());
184 }
185};
186
187}