Преглед на файлове

LibPDF: Implement stubs for all graphical commands

Matthew Olsson преди 4 години
родител
ревизия
bf96ad674c
променени са 3 файла, в които са добавени 199 реда и са изтрити 94 реда
  1. 90 41
      Userland/Libraries/LibPDF/Command.h
  2. 108 53
      Userland/Libraries/LibPDF/Renderer.cpp
  3. 1 0
      Userland/Libraries/LibPDF/Renderer.h

+ 90 - 41
Userland/Libraries/LibPDF/Command.h

@@ -11,43 +11,78 @@
 #include <AK/StringBuilder.h>
 #include <LibPDF/Value.h>
 
-#define ENUMERATE_COMMANDS(V)                                          \
-    V(SaveState, save_state, q)                                        \
-    V(RestoreState, restore_state, Q)                                  \
-    V(ConcatenateMatrix, concatenate_matrix, cm)                       \
-    V(SetLineWidth, set_line_width, w)                                 \
-    V(SetLineCap, set_line_cap, J)                                     \
-    V(SetLineJoin, set_line_join, j)                                   \
-    V(SetMiterLimit, set_miter_limit, M)                               \
-    V(SetDashPattern, set_dash_pattern, d)                             \
-    V(PathBegin, path_begin, m)                                        \
-    V(PathEnd, path_end, n)                                            \
-    V(PathLine, path_line, l)                                          \
-    V(PathClose, path_close, h)                                        \
-    V(PathAppendRect, path_append_rect, re)                            \
-    V(PathStroke, path_stroke, S)                                      \
-    V(PathCloseAndStroke, path_close_and_stroke, s)                    \
-    V(PathFillNonZero, path_fill_nonzero, f)                           \
-    V(PathFillNonZeroDeprecated, path_fill_nonzero_deprecated, F)      \
-    V(PathFillEvenOdd, path_fill_evenodd, f*)                          \
-    V(PathFillStrokeNonZero, path_fill_stroke_nonzero, B)              \
-    V(PathFillStrokeEvenOdd, path_fill_stroke_evenodd, B*)             \
-    V(PathCloseFillStrokeNonZero, path_close_fill_stroke_nonzero, b)   \
-    V(PathCloseFillStrokeEvenOdd, path_close_fill_stroke_evenodd, b*)  \
-    V(TextSetCharSpace, text_set_char_space, Tc)                       \
-    V(TextSetWordSpace, text_set_word_space, Tw)                       \
-    V(TextSetHorizontalScale, text_set_horizontal_scale, Tz)           \
-    V(TextSetLeading, text_set_leading, TL)                            \
-    V(TextSetFont, text_set_font, Tf)                                  \
-    V(TextSetRenderingMode, text_set_rendering_mode, Tr)               \
-    V(TextSetRise, text_set_rise, Ts)                                  \
-    V(TextBegin, text_begin, BT)                                       \
-    V(TextEnd, text_end, ET)                                           \
-    V(TextNextLineOffset, text_next_line_offset, Td)                   \
-    V(TextNextLineAndSetLeading, text_next_line_and_set_leading, TD)   \
-    V(TextSetMatrixAndLineMatrix, text_set_matrix_and_line_matrix, Tm) \
-    V(TextNextLine, text_next_line, T*)                                \
-    V(TextShowString, text_show_string, Tj)
+#define ENUMERATE_COMMANDS(V)                                                            \
+    V(SaveState, save_state, q)                                                          \
+    V(RestoreState, restore_state, Q)                                                    \
+    V(ConcatenateMatrix, concatenate_matrix, cm)                                         \
+    V(SetLineWidth, set_line_width, w)                                                   \
+    V(SetLineCap, set_line_cap, J)                                                       \
+    V(SetLineJoin, set_line_join, j)                                                     \
+    V(SetMiterLimit, set_miter_limit, M)                                                 \
+    V(SetDashPattern, set_dash_pattern, d)                                               \
+    V(SetColorRenderingIntent, set_color_rendering_intent, ri)                           \
+    V(SetFlatnessTolerance, set_flatness_tolerance, i)                                   \
+    V(SetGraphicsStateFromDict, set_graphics_state_from_dict, gs)                        \
+    V(PathBegin, path_begin, m)                                                          \
+    V(PathLine, path_line, l)                                                            \
+    V(PathCubicBezierCurve, path_cubic_bezier_curve, c)                                  \
+    V(PathCubicBezierCurveNoFirstControl, path_cubic_bezier_curve_no_first_control, v)   \
+    V(PathCubicBezierCurveNoSecondControl, path_cubic_bezier_curve_no_second_control, y) \
+    V(PathClose, path_close, h)                                                          \
+    V(PathAppendRect, path_append_rect, re)                                              \
+    V(PathStroke, path_stroke, S)                                                        \
+    V(PathCloseAndStroke, path_close_and_stroke, s)                                      \
+    V(PathFillNonZero, path_fill_nonzero, f)                                             \
+    V(PathFillNonZeroDeprecated, path_fill_nonzero_deprecated, F)                        \
+    V(PathFillEvenOdd, path_fill_evenodd, f*)                                            \
+    V(PathFillStrokeNonZero, path_fill_stroke_nonzero, B)                                \
+    V(PathFillStrokeEvenOdd, path_fill_stroke_evenodd, B*)                               \
+    V(PathCloseFillStrokeNonZero, path_close_fill_stroke_nonzero, b)                     \
+    V(PathCloseFillStrokeEvenOdd, path_close_fill_stroke_evenodd, b*)                    \
+    V(PathEnd, path_end, n)                                                              \
+    V(PathIntersectClipNonZero, path_intersect_clip_nonzero, W)                          \
+    V(PathIntersectClipEvenOdd, path_intersect_clip_evenodd, W*)                         \
+    V(TextBegin, text_begin, BT)                                                         \
+    V(TextEnd, text_end, ET)                                                             \
+    V(TextSetCharSpace, text_set_char_space, Tc)                                         \
+    V(TextSetWordSpace, text_set_word_space, Tw)                                         \
+    V(TextSetHorizontalScale, text_set_horizontal_scale, Tz)                             \
+    V(TextSetLeading, text_set_leading, TL)                                              \
+    V(TextSetFont, text_set_font, Tf)                                                    \
+    V(TextSetRenderingMode, text_set_rendering_mode, Tr)                                 \
+    V(TextSetRise, text_set_rise, Ts)                                                    \
+    V(TextNextLineOffset, text_next_line_offset, Td)                                     \
+    V(TextNextLineAndSetLeading, text_next_line_and_set_leading, TD)                     \
+    V(TextSetMatrixAndLineMatrix, text_set_matrix_and_line_matrix, Tm)                   \
+    V(TextNextLine, text_next_line, T*)                                                  \
+    V(TextShowString, text_show_string, Tj)                                              \
+    V(TextShowStringArray, text_show_string_array, TJ)                                   \
+    V(Type3FontSetGlyphWidth, type3_font_set_glyph_width, d0)                            \
+    V(Type3FontSetGlyphWidthAndBBox, type3_font_set_glyph_width_and_bbox, d1)            \
+    V(ColorSetStrokingSpace, color_set_stroking_space, CS)                               \
+    V(ColorSetPaintingSpace, color_set_painting_space, cs)                               \
+    V(ColorSetStroking, color_set_stroking, SC)                                          \
+    V(ColorSetStrokingExtended, color_set_stroking_extended, SCN)                        \
+    V(ColorSetPainting, color_set_painting, sc)                                          \
+    V(ColorSetPaintingExtended, color_set_painting_extended, scn)                        \
+    V(ColorSetStrokingSpaceToGray, color_set_stroking_space_to_gray, G)                  \
+    V(ColorSetPaintingSpaceToGray, color_set_painting_space_to_gray, g)                  \
+    V(ColorSetStrokingSpaceToRGB, color_set_stroking_space_to_rgb, RG)                   \
+    V(ColorSetPaintingSpaceToRGB, color_set_painting_space_to_rgb, rg)                   \
+    V(ColorSetStrokingSpaceToCMYK, color_set_stroking_space_to_cmyk, K)                  \
+    V(ColorSetPaintingSpaceToCMYK, color_set_painting_space_to_cmyk, k)                  \
+    V(Shade, shade, sh)                                                                  \
+    V(InlineImageBegin, inline_image_begin, BI)                                          \
+    V(InlineImageBeginData, inline_image_begin_data, ID)                                 \
+    V(InlineImageEnd, inline_image_end, EI)                                              \
+    V(PaintXObject, paint_xobject, Do)                                                   \
+    V(MarkedContentPoint, marked_content_point, MP)                                      \
+    V(MarkedContentDesignate, marked_content_designate, DP)                              \
+    V(MarkedContentBegin, marked_content_begin, BMC)                                     \
+    V(MarkedContentBeginWithPropertyList, marked_content_begin_with_property_list, BDC)  \
+    V(MarkedContentEnd, marked_content_end, EMC)                                         \
+    V(CompatibilityBegin, compatibility_begin, BX)                                       \
+    V(CompatibilityEnd, compatibility_end, EX)
 
 namespace PDF {
 
@@ -56,6 +91,7 @@ enum class CommandType {
     ENUMERATE_COMMANDS(V)
 #undef V
         TextNextLineShowString,
+    TextNextLineShowStringSetSpacing,
 };
 
 class Command {
@@ -70,6 +106,8 @@ public:
 
         if (symbol_string == "'")
             return CommandType::TextNextLineShowString;
+        if (symbol_string == "''")
+            return CommandType::TextNextLineShowStringSetSpacing;
 
         dbgln("unsupported graphics symbol {}", symbol_string);
         VERIFY_NOT_REACHED();
@@ -85,6 +123,8 @@ public:
 
         if (command_name == CommandType::TextNextLineShowString)
             return "TextNextLineShowString";
+        if (command_name == CommandType::TextNextLineShowStringSetSpacing)
+            return "TextNextLineShowStringSetSpacing";
 
         VERIFY_NOT_REACHED();
     }
@@ -99,6 +139,8 @@ public:
 
         if (command_name == CommandType::TextNextLineShowString)
             return "'";
+        if (command_name == CommandType::TextNextLineShowStringSetSpacing)
+            return "''";
 
         VERIFY_NOT_REACHED();
     }
@@ -126,10 +168,17 @@ struct Formatter<PDF::Command> : Formatter<StringView> {
     void format(FormatBuilder& format_builder, const PDF::Command& command)
     {
         StringBuilder builder;
-        builder.appendff("{} [ ", PDF::Command::command_name(command.command_type()));
-        for (auto& argument : command.arguments())
-            builder.appendff(" {}", argument);
-        builder.append(" ]");
+        builder.appendff("{} ({})",
+            PDF::Command::command_name(command.command_type()),
+            PDF::Command::command_symbol(command.command_type()));
+
+        if (!command.arguments().is_empty()) {
+            builder.append(" [");
+            for (auto& argument : command.arguments())
+                builder.appendff(" {}", argument);
+            builder.append(" ]");
+        }
+
         Formatter<StringView>::format(format_builder, builder.to_string());
     }
 };

+ 108 - 53
Userland/Libraries/LibPDF/Renderer.cpp

@@ -9,6 +9,16 @@
 #include <ctype.h>
 #include <math.h>
 
+#define RENDERER_HANDLER(name) \
+    void Renderer::handle_##name([[maybe_unused]] const Vector<Value>& args)
+
+#define RENDERER_TODO(name)                                         \
+    RENDERER_HANDLER(name)                                          \
+    {                                                               \
+        dbgln("[PDF::Renderer] Unsupported draw operation " #name); \
+        TODO();                                                     \
+    }
+
 namespace PDF {
 
 void Renderer::render(Document& document, const Page& page, RefPtr<Gfx::Bitmap> bitmap)
@@ -67,27 +77,32 @@ void Renderer::render()
 void Renderer::handle_command(const Command& command)
 {
     switch (command.command_type()) {
-#define V(name, snake_name, symbol) \
-    case CommandType::name:         \
-        return handle_##snake_name(command.arguments());
+#define V(name, snake_name, symbol)               \
+    case CommandType::name:                       \
+        handle_##snake_name(command.arguments()); \
+        break;
         ENUMERATE_COMMANDS(V)
 #undef V
     case CommandType::TextNextLineShowString:
-        return handle_text_next_line_show_string(command.arguments());
+        handle_text_next_line_show_string(command.arguments());
+        break;
+    case CommandType::TextNextLineShowStringSetSpacing:
+        handle_text_next_line_show_string_set_spacing(command.arguments());
+        break;
     }
 }
 
-void Renderer::handle_save_state(const Vector<Value>&)
+RENDERER_HANDLER(save_state)
 {
     m_graphics_state_stack.append(state());
 }
 
-void Renderer::handle_restore_state(const Vector<Value>&)
+RENDERER_HANDLER(restore_state)
 {
     m_graphics_state_stack.take_last();
 }
 
-void Renderer::handle_concatenate_matrix(const Vector<Value>& args)
+RENDERER_HANDLER(concatenate_matrix)
 {
     Gfx::AffineTransform new_transform(
         args[0].to_float(),
@@ -101,27 +116,27 @@ void Renderer::handle_concatenate_matrix(const Vector<Value>& args)
     m_text_rendering_matrix_is_dirty = true;
 }
 
-void Renderer::handle_set_line_width(const Vector<Value>& args)
+RENDERER_HANDLER(set_line_width)
 {
     state().line_width = args[0].to_float();
 }
 
-void Renderer::handle_set_line_cap(const Vector<Value>& args)
+RENDERER_HANDLER(set_line_cap)
 {
     state().line_cap_style = static_cast<LineCapStyle>(args[0].as_int());
 }
 
-void Renderer::handle_set_line_join(const Vector<Value>& args)
+RENDERER_HANDLER(set_line_join)
 {
     state().line_join_style = static_cast<LineJoinStyle>(args[0].as_int());
 }
 
-void Renderer::handle_set_miter_limit(const Vector<Value>& args)
+RENDERER_HANDLER(set_miter_limit)
 {
     state().miter_limit = args[0].to_float();
 }
 
-void Renderer::handle_set_dash_pattern(const Vector<Value>& args)
+RENDERER_HANDLER(set_dash_pattern)
 {
     auto dash_array = m_document->resolve_to<ArrayObject>(args[0]);
     Vector<int> pattern;
@@ -130,26 +145,30 @@ void Renderer::handle_set_dash_pattern(const Vector<Value>& args)
     state().line_dash_pattern = LineDashPattern { pattern, args[1].as_int() };
 }
 
-void Renderer::handle_path_begin(const Vector<Value>&)
-{
-    m_path = Gfx::Path();
-}
+RENDERER_TODO(set_color_rendering_intent);
+RENDERER_TODO(set_flatness_tolerance);
+RENDERER_TODO(set_graphics_state_from_dict);
 
-void Renderer::handle_path_end(const Vector<Value>&)
+RENDERER_HANDLER(path_begin)
 {
+    m_path = Gfx::Path();
 }
 
-void Renderer::handle_path_line(const Vector<Value>& args)
+RENDERER_HANDLER(path_line)
 {
     m_path.line_to(map(args[0].to_float(), args[1].to_float()));
 }
 
-void Renderer::handle_path_close(const Vector<Value>&)
+RENDERER_TODO(path_cubic_bezier_curve);
+RENDERER_TODO(path_cubic_bezier_curve_no_first_control);
+RENDERER_TODO(path_cubic_bezier_curve_no_second_control);
+
+RENDERER_HANDLER(path_close)
 {
     m_path.close();
 }
 
-void Renderer::handle_path_append_rect(const Vector<Value>& args)
+RENDERER_HANDLER(path_append_rect)
 {
     auto pos = map(args[0].to_float(), args[1].to_float());
     auto size = map(Gfx::FloatSize { args[2].to_float(), args[3].to_float() });
@@ -161,78 +180,96 @@ void Renderer::handle_path_append_rect(const Vector<Value>& args)
     m_path.close();
 }
 
-void Renderer::handle_path_stroke(const Vector<Value>&)
+RENDERER_HANDLER(path_stroke)
 {
     m_painter.stroke_path(m_path, state().stroke_color, state().line_width);
 }
 
-void Renderer::handle_path_close_and_stroke(const Vector<Value>& args)
+RENDERER_HANDLER(path_close_and_stroke)
 {
     m_path.close();
     handle_path_stroke(args);
 }
 
-void Renderer::handle_path_fill_nonzero(const Vector<Value>&)
+RENDERER_HANDLER(path_fill_nonzero)
 {
     m_painter.fill_path(m_path, state().paint_color, Gfx::Painter::WindingRule::Nonzero);
 }
 
-void Renderer::handle_path_fill_nonzero_deprecated(const Vector<Value>& args)
+RENDERER_HANDLER(path_fill_nonzero_deprecated)
 {
     handle_path_fill_nonzero(args);
 }
 
-void Renderer::handle_path_fill_evenodd(const Vector<Value>&)
+RENDERER_HANDLER(path_fill_evenodd)
 {
     m_painter.fill_path(m_path, state().paint_color, Gfx::Painter::WindingRule::EvenOdd);
 }
 
-void Renderer::handle_path_fill_stroke_nonzero(const Vector<Value>& args)
+RENDERER_HANDLER(path_fill_stroke_nonzero)
 {
     m_painter.stroke_path(m_path, state().stroke_color, state().line_width);
     handle_path_fill_nonzero(args);
 }
 
-void Renderer::handle_path_fill_stroke_evenodd(const Vector<Value>& args)
+RENDERER_HANDLER(path_fill_stroke_evenodd)
 {
     m_painter.stroke_path(m_path, state().stroke_color, state().line_width);
     handle_path_fill_evenodd(args);
 }
 
-void Renderer::handle_path_close_fill_stroke_nonzero(const Vector<Value>& args)
+RENDERER_HANDLER(path_close_fill_stroke_nonzero)
 {
     m_path.close();
     handle_path_fill_stroke_nonzero(args);
 }
 
-void Renderer::handle_path_close_fill_stroke_evenodd(const Vector<Value>& args)
+RENDERER_HANDLER(path_close_fill_stroke_evenodd)
 {
     m_path.close();
     handle_path_fill_stroke_evenodd(args);
 }
 
-void Renderer::handle_text_set_char_space(const Vector<Value>& args)
+RENDERER_HANDLER(path_end)
+{
+}
+
+RENDERER_TODO(path_intersect_clip_nonzero);
+RENDERER_TODO(path_intersect_clip_evenodd);
+
+RENDERER_HANDLER(text_begin)
+{
+    m_text_matrix = Gfx::AffineTransform();
+    m_text_line_matrix = Gfx::AffineTransform();
+}
+
+RENDERER_HANDLER(text_end)
+{
+    // FIXME: Do we need to do anything here?
+}
+
+RENDERER_HANDLER(text_set_char_space)
 {
     text_state().character_spacing = args[0].to_float();
 }
 
-void Renderer::handle_text_set_word_space(const Vector<Value>& args)
+RENDERER_HANDLER(text_set_word_space)
 {
     text_state().word_spacing = args[0].to_float();
 }
 
-void Renderer::handle_text_set_horizontal_scale(const Vector<Value>& args)
+RENDERER_HANDLER(text_set_horizontal_scale)
 {
     m_text_rendering_matrix_is_dirty = true;
     text_state().horizontal_scaling = args[0].to_float() / 100.0f;
 }
 
-void Renderer::handle_text_set_leading(const Vector<Value>& args)
+RENDERER_HANDLER(text_set_leading)
 {
     text_state().leading = args[0].to_float();
 }
 
-void Renderer::handle_text_set_font(const Vector<Value>& args)
+RENDERER_HANDLER(text_set_font)
 {
     auto target_font_name = m_document->resolve_to<NameObject>(args[0])->name();
     auto fonts_dictionary = m_page.resources->get_dict(m_document, "Font");
@@ -268,29 +305,18 @@ void Renderer::handle_text_set_font(const Vector<Value>& args)
     m_text_rendering_matrix_is_dirty = true;
 }
 
-void Renderer::handle_text_set_rendering_mode(const Vector<Value>& args)
+RENDERER_HANDLER(text_set_rendering_mode)
 {
     text_state().rendering_mode = static_cast<TextRenderingMode>(args[0].as_int());
 }
 
-void Renderer::handle_text_set_rise(const Vector<Value>& args)
+RENDERER_HANDLER(text_set_rise)
 {
     m_text_rendering_matrix_is_dirty = true;
     text_state().rise = args[0].to_float();
 }
 
-void Renderer::handle_text_begin(const Vector<Value>&)
-{
-    m_text_matrix = Gfx::AffineTransform();
-    m_text_line_matrix = Gfx::AffineTransform();
-}
-
-void Renderer::handle_text_end(const Vector<Value>&)
-{
-    // FIXME: Do we need to do anything here?
-}
-
-void Renderer::handle_text_next_line_offset(const Vector<Value>& args)
+RENDERER_HANDLER(text_next_line_offset)
 {
     Gfx::AffineTransform transform(1.0f, 0.0f, 0.0f, 1.0f, args[0].to_float(), args[1].to_float());
     transform.multiply(m_text_line_matrix);
@@ -299,13 +325,13 @@ void Renderer::handle_text_next_line_offset(const Vector<Value>& args)
     m_text_rendering_matrix_is_dirty = true;
 }
 
-void Renderer::handle_text_next_line_and_set_leading(const Vector<Value>& args)
+RENDERER_HANDLER(text_next_line_and_set_leading)
 {
     text_state().leading = -args[1].to_float();
     handle_text_next_line_offset(args);
 }
 
-void Renderer::handle_text_set_matrix_and_line_matrix(const Vector<Value>& args)
+RENDERER_HANDLER(text_set_matrix_and_line_matrix)
 {
     Gfx::AffineTransform new_transform(
         args[0].to_float(),
@@ -319,23 +345,52 @@ void Renderer::handle_text_set_matrix_and_line_matrix(const Vector<Value>& args)
     m_text_rendering_matrix_is_dirty = true;
 }
 
-void Renderer::handle_text_next_line(const Vector<Value>&)
+RENDERER_HANDLER(text_next_line)
 {
     handle_text_next_line_offset({ 0.0f, -text_state().leading });
 }
 
-void Renderer::handle_text_show_string(const Vector<Value>& args)
+RENDERER_HANDLER(text_show_string)
 {
     auto text = m_document->resolve_to<StringObject>(args[0])->string();
     show_text(text);
 }
 
-void Renderer::handle_text_next_line_show_string(const Vector<Value>& args)
+RENDERER_HANDLER(text_next_line_show_string)
 {
     handle_text_next_line(args);
     handle_text_show_string(args);
 }
 
+RENDERER_TODO(text_next_line_show_string_set_spacing);
+RENDERER_TODO(text_show_string_array);
+RENDERER_TODO(type3_font_set_glyph_width);
+RENDERER_TODO(type3_font_set_glyph_width_and_bbox);
+RENDERER_TODO(color_set_stroking_space);
+RENDERER_TODO(color_set_painting_space);
+RENDERER_TODO(color_set_stroking);
+RENDERER_TODO(color_set_stroking_extended);
+RENDERER_TODO(color_set_painting);
+RENDERER_TODO(color_set_painting_extended);
+RENDERER_TODO(color_set_stroking_space_to_gray);
+RENDERER_TODO(color_set_painting_space_to_gray);
+RENDERER_TODO(color_set_stroking_space_to_rgb);
+RENDERER_TODO(color_set_painting_space_to_rgb);
+RENDERER_TODO(color_set_stroking_space_to_cmyk);
+RENDERER_TODO(color_set_painting_space_to_cmyk);
+RENDERER_TODO(shade);
+RENDERER_TODO(inline_image_begin);
+RENDERER_TODO(inline_image_begin_data);
+RENDERER_TODO(inline_image_end);
+RENDERER_TODO(paint_xobject);
+RENDERER_TODO(marked_content_point);
+RENDERER_TODO(marked_content_designate);
+RENDERER_TODO(marked_content_begin);
+RENDERER_TODO(marked_content_begin_with_property_list);
+RENDERER_TODO(marked_content_end);
+RENDERER_TODO(compatibility_begin);
+RENDERER_TODO(compatibility_end);
+
 template<typename T>
 Gfx::Point<T> Renderer::map(T x, T y) const
 {

+ 1 - 0
Userland/Libraries/LibPDF/Renderer.h

@@ -87,6 +87,7 @@ private:
     ENUMERATE_COMMANDS(V)
 #undef V
     void handle_text_next_line_show_string(const Vector<Value>& args);
+    void handle_text_next_line_show_string_set_spacing(const Vector<Value>& args);
 
     // shift is the manual advance given in the TJ command array
     void show_text(const String&, int shift = 0);