mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-20 10:02:51 +00:00
LibPDF: Propagate errors in Renderer/PDFViewer
This commit is contained in:
parent
d82bd885ce
commit
b240d23a87
Notes:
sideshowbarker
2024-07-17 17:50:53 +09:00
Author: https://github.com/mattco98
Commit: b240d23a87
Pull-request: https://github.com/SerenityOS/serenity/pull/12920
4 changed files with 140 additions and 72 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
|
||||
* Copyright (c) 2021-2022, Matthew Olsson <mattco@serenityos.org>
|
||||
* Copyright (c) 2022, the SerenityOS developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
|
@ -8,6 +8,7 @@
|
|||
#include "PDFViewer.h"
|
||||
#include <AK/Array.h>
|
||||
#include <LibGUI/Action.h>
|
||||
#include <LibGUI/MessageBox.h>
|
||||
#include <LibGUI/Painter.h>
|
||||
#include <LibPDF/Renderer.h>
|
||||
|
||||
|
@ -56,15 +57,15 @@ void PDFViewer::set_document(RefPtr<PDF::Document> document)
|
|||
update();
|
||||
}
|
||||
|
||||
RefPtr<Gfx::Bitmap> PDFViewer::get_rendered_page(u32 index)
|
||||
PDF::PDFErrorOr<NonnullRefPtr<Gfx::Bitmap>> PDFViewer::get_rendered_page(u32 index)
|
||||
{
|
||||
auto& rendered_page_map = m_rendered_page_list[index];
|
||||
auto existing_rendered_page = rendered_page_map.get(m_zoom_level);
|
||||
if (existing_rendered_page.has_value() && existing_rendered_page.value().rotation == m_rotations)
|
||||
return existing_rendered_page.value().bitmap;
|
||||
|
||||
// FIXME: Propogate errors in the Renderer
|
||||
auto rendered_page = render_page(MUST(m_document->get_page(index)));
|
||||
auto page = TRY(m_document->get_page(index));
|
||||
auto rendered_page = TRY(render_page(page));
|
||||
rendered_page_map.set(m_zoom_level, { rendered_page, m_rotations });
|
||||
return rendered_page;
|
||||
}
|
||||
|
@ -81,7 +82,14 @@ void PDFViewer::paint_event(GUI::PaintEvent& event)
|
|||
if (!m_document)
|
||||
return;
|
||||
|
||||
auto page = get_rendered_page(m_current_page_index);
|
||||
auto maybe_page = get_rendered_page(m_current_page_index);
|
||||
if (maybe_page.is_error()) {
|
||||
auto error = maybe_page.release_error();
|
||||
GUI::MessageBox::show_error(nullptr, String::formatted("Error rendering page:\n{}", error.message()));
|
||||
return;
|
||||
}
|
||||
|
||||
auto page = maybe_page.release_value();
|
||||
set_content_size(page->size());
|
||||
|
||||
painter.translate(frame_thickness(), frame_thickness());
|
||||
|
@ -196,7 +204,7 @@ void PDFViewer::rotate(int degrees)
|
|||
update();
|
||||
}
|
||||
|
||||
RefPtr<Gfx::Bitmap> PDFViewer::render_page(const PDF::Page& page)
|
||||
PDF::PDFErrorOr<NonnullRefPtr<Gfx::Bitmap>> PDFViewer::render_page(const PDF::Page& page)
|
||||
{
|
||||
auto zoom_scale_factor = static_cast<float>(zoom_levels[m_zoom_level]) / 100.0f;
|
||||
|
||||
|
@ -208,7 +216,7 @@ RefPtr<Gfx::Bitmap> PDFViewer::render_page(const PDF::Page& page)
|
|||
auto width = height / page_scale_factor;
|
||||
auto bitmap = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, { width, height }).release_value_but_fixme_should_propagate_errors();
|
||||
|
||||
PDF::Renderer::render(*m_document, page, bitmap);
|
||||
TRY(PDF::Renderer::render(*m_document, page, bitmap));
|
||||
|
||||
if (page.rotate + m_rotations != 0) {
|
||||
int rotation_count = ((page.rotate + m_rotations) / 90) % 4;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Matthew Olsson <mattco@serenityos.org>
|
||||
* Copyright (c) 2021-2022, Matthew Olsson <mattco@serenityos.org>
|
||||
* Copyright (c) 2022, the SerenityOS developers.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
|
@ -45,12 +45,12 @@ protected:
|
|||
|
||||
private:
|
||||
struct RenderedPage {
|
||||
RefPtr<Gfx::Bitmap> bitmap;
|
||||
NonnullRefPtr<Gfx::Bitmap> bitmap;
|
||||
int rotation;
|
||||
};
|
||||
|
||||
RefPtr<Gfx::Bitmap> get_rendered_page(u32 index);
|
||||
RefPtr<Gfx::Bitmap> render_page(const PDF::Page&);
|
||||
PDF::PDFErrorOr<NonnullRefPtr<Gfx::Bitmap>> get_rendered_page(u32 index);
|
||||
PDF::PDFErrorOr<NonnullRefPtr<Gfx::Bitmap>> render_page(const PDF::Page&);
|
||||
|
||||
RefPtr<PDF::Document> m_document;
|
||||
u32 m_current_page_index { 0 };
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
#include <LibPDF/Renderer.h>
|
||||
|
||||
#define RENDERER_HANDLER(name) \
|
||||
void Renderer::handle_##name([[maybe_unused]] Vector<Value> const& args)
|
||||
PDFErrorOr<void> Renderer::handle_##name([[maybe_unused]] Vector<Value> const& args)
|
||||
|
||||
#define RENDERER_TODO(name) \
|
||||
RENDERER_HANDLER(name) \
|
||||
|
@ -20,9 +20,9 @@
|
|||
|
||||
namespace PDF {
|
||||
|
||||
void Renderer::render(Document& document, Page const& page, RefPtr<Gfx::Bitmap> bitmap)
|
||||
PDFErrorOr<void> Renderer::render(Document& document, Page const& page, RefPtr<Gfx::Bitmap> bitmap)
|
||||
{
|
||||
Renderer(document, page, bitmap).render();
|
||||
return Renderer(document, page, bitmap).render();
|
||||
}
|
||||
|
||||
Renderer::Renderer(RefPtr<Document> document, Page const& page, RefPtr<Gfx::Bitmap> bitmap)
|
||||
|
@ -56,7 +56,7 @@ Renderer::Renderer(RefPtr<Document> document, Page const& page, RefPtr<Gfx::Bitm
|
|||
m_bitmap->fill(Gfx::Color::NamedColor::White);
|
||||
}
|
||||
|
||||
void Renderer::render()
|
||||
PDFErrorOr<void> Renderer::render()
|
||||
{
|
||||
// Use our own vector, as the /Content can be an array with multiple
|
||||
// streams which gets concatenated
|
||||
|
@ -68,7 +68,7 @@ void Renderer::render()
|
|||
if (m_page.contents->is<ArrayObject>()) {
|
||||
auto contents = m_page.contents->cast<ArrayObject>();
|
||||
for (auto& ref : *contents) {
|
||||
auto bytes = MUST(m_document->resolve_to<StreamObject>(ref))->bytes();
|
||||
auto bytes = TRY(m_document->resolve_to<StreamObject>(ref))->bytes();
|
||||
byte_buffer.append(bytes.data(), bytes.size());
|
||||
}
|
||||
} else {
|
||||
|
@ -76,38 +76,44 @@ void Renderer::render()
|
|||
byte_buffer.append(bytes.data(), bytes.size());
|
||||
}
|
||||
|
||||
auto commands = MUST(Parser::parse_graphics_commands(byte_buffer));
|
||||
auto commands = TRY(Parser::parse_graphics_commands(byte_buffer));
|
||||
|
||||
for (auto& command : commands)
|
||||
handle_command(command);
|
||||
TRY(handle_command(command));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void Renderer::handle_command(Command const& command)
|
||||
PDFErrorOr<void> Renderer::handle_command(Command const& command)
|
||||
{
|
||||
switch (command.command_type()) {
|
||||
#define V(name, snake_name, symbol) \
|
||||
case CommandType::name: \
|
||||
handle_##snake_name(command.arguments()); \
|
||||
TRY(handle_##snake_name(command.arguments())); \
|
||||
break;
|
||||
ENUMERATE_COMMANDS(V)
|
||||
#undef V
|
||||
case CommandType::TextNextLineShowString:
|
||||
handle_text_next_line_show_string(command.arguments());
|
||||
TRY(handle_text_next_line_show_string(command.arguments()));
|
||||
break;
|
||||
case CommandType::TextNextLineShowStringSetSpacing:
|
||||
handle_text_next_line_show_string_set_spacing(command.arguments());
|
||||
TRY(handle_text_next_line_show_string_set_spacing(command.arguments()));
|
||||
break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(save_state)
|
||||
{
|
||||
m_graphics_state_stack.append(state());
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(restore_state)
|
||||
{
|
||||
m_graphics_state_stack.take_last();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(concatenate_matrix)
|
||||
|
@ -122,26 +128,31 @@ RENDERER_HANDLER(concatenate_matrix)
|
|||
|
||||
state().ctm.multiply(new_transform);
|
||||
m_text_rendering_matrix_is_dirty = true;
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_line_width)
|
||||
{
|
||||
state().line_width = args[0].to_float();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_line_cap)
|
||||
{
|
||||
state().line_cap_style = static_cast<LineCapStyle>(args[0].get<int>());
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_line_join)
|
||||
{
|
||||
state().line_join_style = static_cast<LineJoinStyle>(args[0].get<int>());
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_miter_limit)
|
||||
{
|
||||
state().miter_limit = args[0].to_float();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_dash_pattern)
|
||||
|
@ -151,10 +162,11 @@ RENDERER_HANDLER(set_dash_pattern)
|
|||
for (auto& element : *dash_array)
|
||||
pattern.append(element.get<int>());
|
||||
state().line_dash_pattern = LineDashPattern { pattern, args[1].get<int>() };
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_TODO(set_color_rendering_intent);
|
||||
RENDERER_TODO(set_flatness_tolerance);
|
||||
RENDERER_TODO(set_color_rendering_intent)
|
||||
RENDERER_TODO(set_flatness_tolerance)
|
||||
|
||||
RENDERER_HANDLER(set_graphics_state_from_dict)
|
||||
{
|
||||
|
@ -162,27 +174,31 @@ RENDERER_HANDLER(set_graphics_state_from_dict)
|
|||
auto dict_name = MUST(m_document->resolve_to<NameObject>(args[0]))->name();
|
||||
auto ext_gstate_dict = MUST(m_page.resources->get_dict(m_document, CommonNames::ExtGState));
|
||||
auto target_dict = MUST(ext_gstate_dict->get_dict(m_document, dict_name));
|
||||
set_graphics_state_from_dict(target_dict);
|
||||
TRY(set_graphics_state_from_dict(target_dict));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_move)
|
||||
{
|
||||
m_current_path.move_to(map(args[0].to_float(), args[1].to_float()));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_line)
|
||||
{
|
||||
VERIFY(!m_current_path.segments().is_empty());
|
||||
m_current_path.line_to(map(args[0].to_float(), args[1].to_float()));
|
||||
return {};
|
||||
}
|
||||
|
||||
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_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_current_path.close();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_append_rect)
|
||||
|
@ -195,63 +211,74 @@ RENDERER_HANDLER(path_append_rect)
|
|||
m_current_path.line_to({ pos.x() + size.width(), pos.y() + size.height() });
|
||||
m_current_path.line_to({ pos.x(), pos.y() + size.height() });
|
||||
m_current_path.close();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_stroke)
|
||||
{
|
||||
m_painter.stroke_path(m_current_path, state().stroke_color, state().line_width);
|
||||
m_current_path.clear();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_close_and_stroke)
|
||||
{
|
||||
m_current_path.close();
|
||||
handle_path_stroke(args);
|
||||
TRY(handle_path_stroke(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_fill_nonzero)
|
||||
{
|
||||
m_painter.fill_path(m_current_path, state().paint_color, Gfx::Painter::WindingRule::Nonzero);
|
||||
m_current_path.clear();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_fill_nonzero_deprecated)
|
||||
{
|
||||
handle_path_fill_nonzero(args);
|
||||
TRY(handle_path_fill_nonzero(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_fill_evenodd)
|
||||
{
|
||||
m_painter.fill_path(m_current_path, state().paint_color, Gfx::Painter::WindingRule::EvenOdd);
|
||||
m_current_path.clear();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_fill_stroke_nonzero)
|
||||
{
|
||||
m_painter.stroke_path(m_current_path, state().stroke_color, state().line_width);
|
||||
handle_path_fill_nonzero(args);
|
||||
TRY(handle_path_fill_nonzero(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_fill_stroke_evenodd)
|
||||
{
|
||||
m_painter.stroke_path(m_current_path, state().stroke_color, state().line_width);
|
||||
handle_path_fill_evenodd(args);
|
||||
TRY(handle_path_fill_evenodd(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_close_fill_stroke_nonzero)
|
||||
{
|
||||
m_current_path.close();
|
||||
handle_path_fill_stroke_nonzero(args);
|
||||
TRY(handle_path_fill_stroke_nonzero(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_close_fill_stroke_evenodd)
|
||||
{
|
||||
m_current_path.close();
|
||||
handle_path_fill_stroke_evenodd(args);
|
||||
TRY(handle_path_fill_stroke_evenodd(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_end)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_intersect_clip_nonzero)
|
||||
|
@ -259,6 +286,7 @@ RENDERER_HANDLER(path_intersect_clip_nonzero)
|
|||
// FIXME: Support arbitrary path clipping in the painter and utilize that here
|
||||
auto bounding_box = map(m_current_path.bounding_box());
|
||||
m_painter.add_clip_rect(bounding_box.to_type<int>());
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_intersect_clip_evenodd)
|
||||
|
@ -266,38 +294,45 @@ RENDERER_HANDLER(path_intersect_clip_evenodd)
|
|||
// FIXME: Support arbitrary path clipping in the painter and utilize that here
|
||||
auto bounding_box = map(m_current_path.bounding_box());
|
||||
m_painter.add_clip_rect(bounding_box.to_type<int>());
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_begin)
|
||||
{
|
||||
m_text_matrix = Gfx::AffineTransform();
|
||||
m_text_line_matrix = Gfx::AffineTransform();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_end)
|
||||
{
|
||||
// FIXME: Do we need to do anything here?
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_set_char_space)
|
||||
{
|
||||
text_state().character_spacing = args[0].to_float();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_set_word_space)
|
||||
{
|
||||
text_state().word_spacing = args[0].to_float();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_set_horizontal_scale)
|
||||
{
|
||||
m_text_rendering_matrix_is_dirty = true;
|
||||
text_state().horizontal_scaling = args[0].to_float() / 100.0f;
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_set_leading)
|
||||
{
|
||||
text_state().leading = args[0].to_float();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_set_font)
|
||||
|
@ -330,17 +365,20 @@ RENDERER_HANDLER(text_set_font)
|
|||
text_state().font_variant = font_variant;
|
||||
|
||||
m_text_rendering_matrix_is_dirty = true;
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_set_rendering_mode)
|
||||
{
|
||||
text_state().rendering_mode = static_cast<TextRenderingMode>(args[0].get<int>());
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_set_rise)
|
||||
{
|
||||
m_text_rendering_matrix_is_dirty = true;
|
||||
text_state().rise = args[0].to_float();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_next_line_offset)
|
||||
|
@ -350,12 +388,14 @@ RENDERER_HANDLER(text_next_line_offset)
|
|||
m_text_matrix = transform;
|
||||
m_text_line_matrix = transform;
|
||||
m_text_rendering_matrix_is_dirty = true;
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_next_line_and_set_leading)
|
||||
{
|
||||
text_state().leading = -args[1].to_float();
|
||||
handle_text_next_line_offset(args);
|
||||
TRY(handle_text_next_line_offset(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_set_matrix_and_line_matrix)
|
||||
|
@ -370,26 +410,30 @@ RENDERER_HANDLER(text_set_matrix_and_line_matrix)
|
|||
m_text_line_matrix = new_transform;
|
||||
m_text_matrix = new_transform;
|
||||
m_text_rendering_matrix_is_dirty = true;
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_next_line)
|
||||
{
|
||||
handle_text_next_line_offset({ 0.0f, -text_state().leading });
|
||||
TRY(handle_text_next_line_offset({ 0.0f, -text_state().leading }));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_show_string)
|
||||
{
|
||||
auto text = MUST(m_document->resolve_to<StringObject>(args[0]))->string();
|
||||
show_text(text);
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(text_next_line_show_string)
|
||||
{
|
||||
handle_text_next_line(args);
|
||||
handle_text_show_string(args);
|
||||
TRY(handle_text_next_line(args));
|
||||
TRY(handle_text_show_string(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_TODO(text_next_line_show_string_set_spacing);
|
||||
RENDERER_TODO(text_next_line_show_string_set_spacing)
|
||||
|
||||
RENDERER_HANDLER(text_show_string_array)
|
||||
{
|
||||
|
@ -406,85 +450,97 @@ RENDERER_HANDLER(text_show_string_array)
|
|||
show_text(str, next_shift);
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_TODO(type3_font_set_glyph_width);
|
||||
RENDERER_TODO(type3_font_set_glyph_width_and_bbox);
|
||||
RENDERER_TODO(type3_font_set_glyph_width)
|
||||
RENDERER_TODO(type3_font_set_glyph_width_and_bbox)
|
||||
|
||||
RENDERER_HANDLER(set_stroking_space)
|
||||
{
|
||||
state().stroke_color_space = MUST(get_color_space(args[0]));
|
||||
VERIFY(state().stroke_color_space);
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_painting_space)
|
||||
{
|
||||
state().paint_color_space = MUST(get_color_space(args[0]));
|
||||
VERIFY(state().paint_color_space);
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_stroking_color)
|
||||
{
|
||||
state().stroke_color = state().stroke_color_space->color(args);
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_TODO(set_stroking_color_extended);
|
||||
RENDERER_TODO(set_stroking_color_extended)
|
||||
|
||||
RENDERER_HANDLER(set_painting_color)
|
||||
{
|
||||
state().paint_color = state().paint_color_space->color(args);
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_TODO(set_painting_color_extended);
|
||||
RENDERER_TODO(set_painting_color_extended)
|
||||
|
||||
RENDERER_HANDLER(set_stroking_color_and_space_to_gray)
|
||||
{
|
||||
state().stroke_color_space = DeviceGrayColorSpace::the();
|
||||
state().stroke_color = state().stroke_color_space->color(args);
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_painting_color_and_space_to_gray)
|
||||
{
|
||||
state().paint_color_space = DeviceGrayColorSpace::the();
|
||||
state().paint_color = state().paint_color_space->color(args);
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_stroking_color_and_space_to_rgb)
|
||||
{
|
||||
state().stroke_color_space = DeviceRGBColorSpace::the();
|
||||
state().stroke_color = state().stroke_color_space->color(args);
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_painting_color_and_space_to_rgb)
|
||||
{
|
||||
state().paint_color_space = DeviceRGBColorSpace::the();
|
||||
state().paint_color = state().paint_color_space->color(args);
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_stroking_color_and_space_to_cmyk)
|
||||
{
|
||||
state().stroke_color_space = DeviceCMYKColorSpace::the();
|
||||
state().stroke_color = state().stroke_color_space->color(args);
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_painting_color_and_space_to_cmyk)
|
||||
{
|
||||
state().paint_color_space = DeviceCMYKColorSpace::the();
|
||||
state().paint_color = state().paint_color_space->color(args);
|
||||
return {};
|
||||
}
|
||||
|
||||
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);
|
||||
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
|
||||
|
@ -505,25 +561,29 @@ Gfx::Rect<T> Renderer::map(Gfx::Rect<T> rect) const
|
|||
return state().ctm.map(rect);
|
||||
}
|
||||
|
||||
void Renderer::set_graphics_state_from_dict(NonnullRefPtr<DictObject> dict)
|
||||
PDFErrorOr<void> Renderer::set_graphics_state_from_dict(NonnullRefPtr<DictObject> dict)
|
||||
{
|
||||
if (dict->contains(CommonNames::LW))
|
||||
handle_set_line_width({ dict->get_value(CommonNames::LW) });
|
||||
TRY(handle_set_line_width({ dict->get_value(CommonNames::LW) }));
|
||||
|
||||
if (dict->contains(CommonNames::LC))
|
||||
handle_set_line_cap({ dict->get_value(CommonNames::LC) });
|
||||
TRY(handle_set_line_cap({ dict->get_value(CommonNames::LC) }));
|
||||
|
||||
if (dict->contains(CommonNames::LJ))
|
||||
handle_set_line_join({ dict->get_value(CommonNames::LJ) });
|
||||
TRY(handle_set_line_join({ dict->get_value(CommonNames::LJ) }));
|
||||
|
||||
if (dict->contains(CommonNames::ML))
|
||||
handle_set_miter_limit({ dict->get_value(CommonNames::ML) });
|
||||
TRY(handle_set_miter_limit({ dict->get_value(CommonNames::ML) }));
|
||||
|
||||
if (dict->contains(CommonNames::D))
|
||||
handle_set_dash_pattern(MUST(dict->get_array(m_document, CommonNames::D))->elements());
|
||||
if (dict->contains(CommonNames::D)) {
|
||||
auto array = MUST(dict->get_array(m_document, CommonNames::D));
|
||||
TRY(handle_set_dash_pattern(array->elements()));
|
||||
}
|
||||
|
||||
if (dict->contains(CommonNames::FL))
|
||||
handle_set_flatness_tolerance({ dict->get_value(CommonNames::FL) });
|
||||
TRY(handle_set_flatness_tolerance({ dict->get_value(CommonNames::FL) }));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void Renderer::show_text(String const& string, float shift)
|
||||
|
|
|
@ -79,22 +79,22 @@ struct GraphicsState {
|
|||
|
||||
class Renderer {
|
||||
public:
|
||||
static void render(Document&, Page const&, RefPtr<Gfx::Bitmap>);
|
||||
static PDFErrorOr<void> render(Document&, Page const&, RefPtr<Gfx::Bitmap>);
|
||||
|
||||
private:
|
||||
Renderer(RefPtr<Document>, Page const&, RefPtr<Gfx::Bitmap>);
|
||||
|
||||
void render();
|
||||
PDFErrorOr<void> render();
|
||||
|
||||
void handle_command(Command const&);
|
||||
PDFErrorOr<void> handle_command(Command const&);
|
||||
#define V(name, snake_name, symbol) \
|
||||
void handle_##snake_name(Vector<Value> const& args);
|
||||
PDFErrorOr<void> handle_##snake_name(Vector<Value> const& args);
|
||||
ENUMERATE_COMMANDS(V)
|
||||
#undef V
|
||||
void handle_text_next_line_show_string(Vector<Value> const& args);
|
||||
void handle_text_next_line_show_string_set_spacing(Vector<Value> const& args);
|
||||
PDFErrorOr<void> handle_text_next_line_show_string(Vector<Value> const& args);
|
||||
PDFErrorOr<void> handle_text_next_line_show_string_set_spacing(Vector<Value> const& args);
|
||||
|
||||
void set_graphics_state_from_dict(NonnullRefPtr<DictObject>);
|
||||
PDFErrorOr<void> set_graphics_state_from_dict(NonnullRefPtr<DictObject>);
|
||||
// shift is the manual advance given in the TJ command array
|
||||
void show_text(String const&, float shift = 0.0f);
|
||||
PDFErrorOr<NonnullRefPtr<ColorSpace>> get_color_space(Value const&);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue