diff --git a/Userland/Libraries/LibPDF/ColorSpace.cpp b/Userland/Libraries/LibPDF/ColorSpace.cpp index 14015d6109f997..fe1e16b6c9639f 100644 --- a/Userland/Libraries/LibPDF/ColorSpace.cpp +++ b/Userland/Libraries/LibPDF/ColorSpace.cpp @@ -45,7 +45,7 @@ PDFErrorOr> ColorSpace::create(Document* document, Non return Error { Error::Type::MalformedPDF, "Color space must be name or array" }; } -PDFErrorOr> ColorSpace::create(DeprecatedFlyString const& name, Renderer&) +PDFErrorOr> ColorSpace::create(DeprecatedFlyString const& name, Renderer& renderer) { // Simple color spaces with no parameters, which can be specified directly if (name == CommonNames::DeviceGray) @@ -55,7 +55,7 @@ PDFErrorOr> ColorSpace::create(DeprecatedFlyString con if (name == CommonNames::DeviceCMYK) return TRY(DeviceCMYKColorSpace::the()); if (name == CommonNames::Pattern) - return Error::rendering_unsupported_error("Pattern color spaces not yet implemented"); + return PatternColorSpace::create(renderer); VERIFY_NOT_REACHED(); } @@ -86,12 +86,12 @@ PDFErrorOr> ColorSpace::create(Document* document, Non if (color_space_name == CommonNames::Lab) return TRY(LabColorSpace::create(document, move(parameters))); - if (color_space_name == CommonNames::Pattern) - return Error::rendering_unsupported_error("Pattern color spaces not yet implemented"); - if (color_space_name == CommonNames::Separation) return TRY(SeparationColorSpace::create(document, move(parameters), renderer)); + if (color_space_name == CommonNames::Pattern) + return PatternColorSpace::create(renderer); + dbgln("Unknown color space: {}", color_space_name); return Error::rendering_unsupported_error("unknown color space"); } @@ -720,13 +720,13 @@ PDFErrorOr> IndexedColorSpace::create(Document* docume for (size_t i = 0; i < lookup.size(); ++i) lookup_float[i] = mix(decode[2 * (i % n)], decode[2 * (i % n) + 1], lookup[i] / 255.0f); - auto color_space = adopt_ref(*new IndexedColorSpace(move(base))); + auto color_space = adopt_ref(*new IndexedColorSpace(move(verify_cast(*base)))); color_space->m_hival = hival; color_space->m_lookup = move(lookup_float); return color_space; } -IndexedColorSpace::IndexedColorSpace(NonnullRefPtr base) +IndexedColorSpace::IndexedColorSpace(NonnullRefPtr base) : m_base(move(base)) { } @@ -802,4 +802,124 @@ Vector SeparationColorSpace::default_decode() const { return { 0.0f, 1.0f }; } +NonnullRefPtr PatternColorSpace::create(Renderer& renderer) +{ + return adopt_ref(*new PatternColorSpace(renderer)); +} + +PDFErrorOr PatternColorSpace::style(ReadonlySpan arguments) const +{ + VERIFY(arguments.size() >= 1); + + auto resources = m_renderer.m_page.resources; + if (!resources->contains(CommonNames::Pattern)) + return Error::malformed_error("Pattern resource dictionary missing"); + + auto pattern_resource = resources->get_value(CommonNames::Pattern); + auto* maybe_doc_pattern_dict = pattern_resource.get_pointer>(); + if (!maybe_doc_pattern_dict || !(*maybe_doc_pattern_dict)->is()) + return Error::malformed_error("Pattern resource dictionary not DictObject"); + + auto doc_pattern_dict = (*maybe_doc_pattern_dict)->cast(); + auto const& pattern_name = arguments.last().get>()->cast()->name(); + if (!doc_pattern_dict->contains(pattern_name)) + return Error::malformed_error("Pattern dictionary does not contain pattern {}", pattern_name); + + auto const pattern = TRY(m_renderer.m_document->resolve_to(doc_pattern_dict->get_value(pattern_name))); + NonnullRefPtr pattern_dict = [&] { + // Shading patterns do not have a content stream. + if (pattern->is()) + return pattern->cast(); + return pattern->cast()->dict(); + }(); + + // PatternType (Required) A code identifying the type of pattern that this dictionary describes; + // shall be 1 for a tiling pattern + auto const pattern_type = pattern_dict->get(CommonNames::PatternType)->get_u16(); + if (pattern_type != 1) + return Error::rendering_unsupported_error("Unsupported pattern type {}", pattern_type); + + // Type (Optional) The type of PDF object that this dictionary describes; + // if present, shall be Pattern for a pattern dictionary + auto const type = pattern_dict->get(CommonNames::Type); + if (type.has_value()) { + auto type_name = type->get>()->cast(); + if (type_name->name() != CommonNames::Pattern) + return Error::rendering_unsupported_error("Unsupported pattern type {}", type_name->name()); + } + + // PaintType (Required) A code that determines how the colour of the pattern cell shall be specified + auto const pattern_paint_type = pattern_dict->get("PaintType")->get_u16(); + if (pattern_paint_type != 1) + return Error::rendering_unsupported_error("Unsupported pattern paint type {}", pattern_paint_type); + + // Matrix (Optional) An array of six numbers specifying the pattern matrix + Vector pattern_matrix; + if (pattern_dict->contains(CommonNames::Matrix)) { + pattern_matrix = pattern_dict->get_array(m_renderer.m_document, CommonNames::Matrix).value()->elements(); + } else { + pattern_matrix = Vector { Value { 1 }, Value { 0 }, Value { 0 }, Value { 1 }, Value { 0 }, Value { 0 } }; + } + + auto pattern_bounding_box = pattern_dict->get_array(m_renderer.m_document, "BBox").value()->elements(); + auto pattern_transform = Gfx::AffineTransform( + pattern_matrix[0].to_float(), + pattern_matrix[1].to_float(), + pattern_matrix[2].to_float(), + pattern_matrix[3].to_float(), + pattern_matrix[4].to_float(), + pattern_matrix[5].to_float()); + + // To get the device space size for the bitmap, apply the pattern transform to the pattern space bounding box, and then apply the initial ctm. + // NB: the pattern pattern_matrix maps pattern space to the default (initial) coordinate space of the page. (i.e cannot be updated via cm). + + auto initial_ctm = Gfx::AffineTransform(m_renderer.m_graphics_state_stack.first().ctm); + initial_ctm.set_translation(0, 0); + initial_ctm.set_scale(initial_ctm.x_scale(), initial_ctm.y_scale()); + + auto pattern_space_lower_left = Gfx::FloatPoint { pattern_bounding_box[0].to_int(), pattern_bounding_box[1].to_int() }; + auto pattern_space_upper_right = Gfx::FloatPoint { pattern_bounding_box[2].to_int(), pattern_bounding_box[3].to_int() }; + + auto device_space_lower_left = initial_ctm.map(pattern_transform.map(pattern_space_lower_left)); + auto device_space_upper_right = initial_ctm.map(pattern_transform.map(pattern_space_upper_right)); + + auto bitmap_width = (int)device_space_upper_right.x() - (int)device_space_lower_left.x(); + auto bitmap_height = (int)device_space_upper_right.y() - (int)device_space_lower_left.y(); + + auto pattern_cell = TRY(Gfx::Bitmap::create(Gfx::BitmapFormat::BGRA8888, { bitmap_width, bitmap_height })); + auto page = Page(m_renderer.m_page); + page.media_box = Rectangle { + pattern_space_lower_left.x(), pattern_space_lower_left.y(), + pattern_space_upper_right.x(), pattern_space_upper_right.y() + }; + page.crop_box = page.media_box; + + auto pattern_renderer = Renderer(m_renderer.m_document, page, pattern_cell, {}, m_renderer.m_rendering_preferences); + + auto operators = TRY(Parser::parse_operators(m_renderer.m_document, pattern->cast()->bytes())); + for (auto& op : operators) + TRY(pattern_renderer.handle_operator(op, resources)); + + auto x_steps = pattern_dict->get("XStep").value_or(bitmap_width).to_int(); + auto y_steps = pattern_dict->get("YStep").value_or(bitmap_height).to_int(); + + auto device_space_steps = initial_ctm.map(pattern_transform.map(Gfx::IntPoint { x_steps, y_steps })); + + NonnullRefPtr style = MUST(Gfx::RepeatingBitmapPaintStyle::create( + *pattern_cell, + device_space_steps, + {})); + + return style; +} +int PatternColorSpace::number_of_components() const +{ + // Not permitted + VERIFY_NOT_REACHED(); +} +Vector PatternColorSpace::default_decode() const +{ + // Not permitted + VERIFY_NOT_REACHED(); +} } diff --git a/Userland/Libraries/LibPDF/ColorSpace.h b/Userland/Libraries/LibPDF/ColorSpace.h index c00c768daab73d..48e3fda0a6397a 100644 --- a/Userland/Libraries/LibPDF/ColorSpace.h +++ b/Userland/Libraries/LibPDF/ColorSpace.h @@ -66,21 +66,27 @@ class ColorSpace : public RefCounted { virtual ~ColorSpace() = default; + virtual PDFErrorOr style(ReadonlySpan arguments) const = 0; + + virtual int number_of_components() const = 0; + virtual Vector default_decode() const = 0; // "TABLE 4.40 Default Decode arrays" + virtual ColorSpaceFamily const& family() const = 0; +}; + +class ColorSpaceWithFloatArgs : public ColorSpace { +public: virtual PDFErrorOr style(ReadonlySpan arguments) const = 0; - virtual PDFErrorOr style(ReadonlySpan arguments) const + + PDFErrorOr style(ReadonlySpan arguments) const override { Vector float_arguments; for (auto& argument : arguments) float_arguments.append(argument.to_float()); return style(float_arguments); } - - virtual int number_of_components() const = 0; - virtual Vector default_decode() const = 0; // "TABLE 4.40 Default Decode arrays" - virtual ColorSpaceFamily const& family() const = 0; }; -class DeviceGrayColorSpace final : public ColorSpace { +class DeviceGrayColorSpace final : public ColorSpaceWithFloatArgs { public: static NonnullRefPtr the(); @@ -95,7 +101,7 @@ class DeviceGrayColorSpace final : public ColorSpace { DeviceGrayColorSpace() = default; }; -class DeviceRGBColorSpace final : public ColorSpace { +class DeviceRGBColorSpace final : public ColorSpaceWithFloatArgs { public: static NonnullRefPtr the(); @@ -110,7 +116,7 @@ class DeviceRGBColorSpace final : public ColorSpace { DeviceRGBColorSpace() = default; }; -class DeviceCMYKColorSpace final : public ColorSpace { +class DeviceCMYKColorSpace final : public ColorSpaceWithFloatArgs { public: static ErrorOr> the(); @@ -125,7 +131,7 @@ class DeviceCMYKColorSpace final : public ColorSpace { DeviceCMYKColorSpace() = default; }; -class DeviceNColorSpace final : public ColorSpace { +class DeviceNColorSpace final : public ColorSpaceWithFloatArgs { public: static PDFErrorOr> create(Document*, Vector&& parameters, Renderer&); @@ -145,7 +151,7 @@ class DeviceNColorSpace final : public ColorSpace { Vector mutable m_tint_output_values; }; -class CalGrayColorSpace final : public ColorSpace { +class CalGrayColorSpace final : public ColorSpaceWithFloatArgs { public: static PDFErrorOr> create(Document*, Vector&& parameters); @@ -164,7 +170,7 @@ class CalGrayColorSpace final : public ColorSpace { float m_gamma { 1 }; }; -class CalRGBColorSpace final : public ColorSpace { +class CalRGBColorSpace final : public ColorSpaceWithFloatArgs { public: static PDFErrorOr> create(Document*, Vector&& parameters); @@ -184,7 +190,7 @@ class CalRGBColorSpace final : public ColorSpace { Array m_matrix { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; }; -class ICCBasedColorSpace final : public ColorSpace { +class ICCBasedColorSpace final : public ColorSpaceWithFloatArgs { public: static PDFErrorOr> create(Document*, Vector&& parameters, Renderer&); @@ -207,7 +213,7 @@ class ICCBasedColorSpace final : public ColorSpace { Optional m_map; }; -class LabColorSpace final : public ColorSpace { +class LabColorSpace final : public ColorSpaceWithFloatArgs { public: static PDFErrorOr> create(Document*, Vector&& parameters); @@ -226,7 +232,7 @@ class LabColorSpace final : public ColorSpace { Array m_range { -100, 100, -100, 100 }; }; -class IndexedColorSpace final : public ColorSpace { +class IndexedColorSpace final : public ColorSpaceWithFloatArgs { public: static PDFErrorOr> create(Document*, Vector&& parameters, Renderer&); @@ -237,7 +243,7 @@ class IndexedColorSpace final : public ColorSpace { Vector default_decode() const override; ColorSpaceFamily const& family() const override { return ColorSpaceFamily::Indexed; } - NonnullRefPtr base_color_space() const { return m_base; } + NonnullRefPtr base_color_space() const { return m_base; } PDFErrorOr> base_components(int index) const { @@ -248,14 +254,14 @@ class IndexedColorSpace final : public ColorSpace { } private: - IndexedColorSpace(NonnullRefPtr); + IndexedColorSpace(NonnullRefPtr); - NonnullRefPtr m_base; + NonnullRefPtr m_base; int m_hival { 0 }; Vector m_lookup; }; -class SeparationColorSpace final : public ColorSpace { +class SeparationColorSpace final : public ColorSpaceWithFloatArgs { public: static PDFErrorOr> create(Document*, Vector&& parameters, Renderer&); @@ -274,4 +280,24 @@ class SeparationColorSpace final : public ColorSpace { NonnullRefPtr m_tint_transform; Vector mutable m_tint_output_values; }; + +class PatternColorSpace final : public ColorSpace { +public: + static NonnullRefPtr create(Renderer& renderer); + ~PatternColorSpace() override = default; + + PDFErrorOr style(ReadonlySpan arguments) const override; + int number_of_components() const override; + Vector default_decode() const override; + ColorSpaceFamily const& family() const override { return ColorSpaceFamily::Pattern; } + +private: + PatternColorSpace(Renderer& renderer) + : m_renderer(renderer) + { + } + + Renderer& m_renderer; +}; + } diff --git a/Userland/Libraries/LibPDF/CommonNames.h b/Userland/Libraries/LibPDF/CommonNames.h index 30937695079ca6..3c6e1d08805ad1 100644 --- a/Userland/Libraries/LibPDF/CommonNames.h +++ b/Userland/Libraries/LibPDF/CommonNames.h @@ -177,8 +177,10 @@ X(Overlay) \ X(P) \ X(Pages) \ + X(PaintType) \ X(Parent) \ X(Pattern) \ + X(PatternType) \ X(Perms) \ X(Predictor) \ X(Prev) \ diff --git a/Userland/Libraries/LibPDF/Renderer.cpp b/Userland/Libraries/LibPDF/Renderer.cpp index 5235c35db452a2..030e4bf9ad2059 100644 --- a/Userland/Libraries/LibPDF/Renderer.cpp +++ b/Userland/Libraries/LibPDF/Renderer.cpp @@ -415,6 +415,12 @@ PDFErrorOr Renderer::restore_previous_clip_after_graphics_state_restore() void Renderer::begin_path_paint() { m_current_path.transform(state().ctm); + if (state().paint_style.has>()) { + VERIFY(!m_original_paint_style); + m_original_paint_style = state().paint_style.get>(); + auto translation = Gfx::AffineTransform().translate(m_current_path.bounding_box().x(), m_current_path.bounding_box().y()); + state().paint_style = { MUST(Gfx::OffsetPaintStyle::create(state().paint_style.get>(), translation)) }; + } } PDFErrorOr Renderer::end_path_paint() @@ -424,6 +430,11 @@ PDFErrorOr Renderer::end_path_paint() m_add_path_as_clip = AddPathAsClip::No; } + if (m_original_paint_style) { + state().paint_style = m_original_paint_style.release_nonnull(); + m_original_paint_style = nullptr; + } + // "Once a path has been painted, it is no longer defined; there is then no current path // until a new one is begun with the m or re operator." m_current_path.clear(); @@ -805,13 +816,7 @@ RENDERER_HANDLER(set_stroking_color) RENDERER_HANDLER(set_stroking_color_extended) { - // FIXME: Handle Pattern color spaces - auto last_arg = args.last(); - if (last_arg.has>() && last_arg.get>()->is()) { - dbgln("pattern space {}", last_arg.get>()->cast()->name()); - return Error::rendering_unsupported_error("Pattern color spaces not yet implemented"); - } - + // FIXME: Pattern color spaces might need extra resources state().stroke_style = style_with_alpha(TRY(state().stroke_color_space->style(args)), state().stroke_alpha_constant); return {}; } @@ -824,13 +829,6 @@ RENDERER_HANDLER(set_painting_color) RENDERER_HANDLER(set_painting_color_extended) { - // FIXME: Handle Pattern color spaces - auto last_arg = args.last(); - if (last_arg.has>() && last_arg.get>()->is()) { - dbgln("pattern space {}", last_arg.get>()->cast()->name()); - return Error::rendering_unsupported_error("Pattern color spaces not yet implemented"); - } - state().paint_style = style_with_alpha(TRY(state().paint_color_space->style(args)), state().paint_alpha_constant); return {}; } @@ -1060,10 +1058,15 @@ RENDERER_HANDLER(paint_xobject) { VERIFY(args.size() > 0); auto resources = extra_resources.value_or(m_page.resources); + if (!resources->contains(CommonNames::XObject)) + return Error::malformed_error("XObject resource dictionary missing"); + auto xobject_name = args[0].get>()->cast()->name(); auto xobjects_dict = TRY(resources->get_dict(m_document, CommonNames::XObject)); - auto xobject = TRY(xobjects_dict->get_stream(m_document, xobject_name)); + if (!xobjects_dict->contains(xobject_name)) + return Error::malformed_error("XObject resource dictionary does not contain {}", xobject_name); + auto xobject = TRY(xobjects_dict->get_stream(m_document, xobject_name)); auto subtype = MUST(xobject->dict()->get_name(m_document, CommonNames::Subtype))->name(); if (subtype == CommonNames::Image) { TRY(paint_image_xobject(xobject)); @@ -1561,7 +1564,7 @@ PDFErrorOr Renderer::load_image(NonnullRefPtr color_space = DeviceGrayColorSpace::the(); + NonnullRefPtr color_space = DeviceGrayColorSpace::the(); if (!is_image_mask) { // "If ColorSpace is not present in the image dictionary, the color space informa- // tion in the JPEG2000 data is used." @@ -1570,7 +1573,7 @@ PDFErrorOr Renderer::load_image(NonnullRefPtrcontains(CommonNames::ColorSpace) && is_jpeg2000) return Error(Error::Type::RenderingUnsupported, "Using color space from jpeg2000 image not yet implemented"); auto color_space_object = MUST(image_dict->get_object(m_document, CommonNames::ColorSpace)); - color_space = TRY(get_color_space_from_document(color_space_object)); + color_space = verify_cast(*TRY(get_color_space_from_document(color_space_object))); } auto color_rendering_intent = state().color_rendering_intent; diff --git a/Userland/Libraries/LibPDF/Renderer.h b/Userland/Libraries/LibPDF/Renderer.h index 9c1b7d858cf404..a3c1f1403318a1 100644 --- a/Userland/Libraries/LibPDF/Renderer.h +++ b/Userland/Libraries/LibPDF/Renderer.h @@ -156,6 +156,8 @@ struct RenderingPreferences { }; class Renderer { + friend class PatternColorSpace; + public: static PDFErrorsOr render(Document&, Page const&, RefPtr, Color background_color, RenderingPreferences preferences); @@ -291,6 +293,8 @@ class Renderer { // Only used for m_rendering_preferences.show_clipping_paths. void show_clipping_paths(); Vector m_clip_paths_to_show_for_debugging; + // Used to offset the PaintStyle's origin when rendering a pattern. + RefPtr m_original_paint_style; }; } diff --git a/Userland/Libraries/LibPDF/Shading.cpp b/Userland/Libraries/LibPDF/Shading.cpp index e07e3907eb776c..2827c266de586a 100644 --- a/Userland/Libraries/LibPDF/Shading.cpp +++ b/Userland/Libraries/LibPDF/Shading.cpp @@ -23,7 +23,7 @@ namespace { struct CommonEntries { // "(Required) The color space in which color values are expressed. This may be // any device, CIE-based, or special color space except a Pattern space." - AK::NonnullRefPtr color_space; + AK::NonnullRefPtr color_space; // "(Optional) An array of color components appropriate to the color space, // specifying a single background color value. If present, this color is used, be- @@ -60,7 +60,7 @@ PDFErrorOr read_common_entries(Document* document, DictObject con if (color_space->family() == ColorSpaceFamily::Pattern) return Error::malformed_error("Shading color space must not be pattern"); - CommonEntries common_entries { .color_space = color_space }; + CommonEntries common_entries { .color_space = verify_cast(*color_space) }; if (shading_dict.contains(CommonNames::Background)) { auto background_array = TRY(shading_dict.get_array(document, CommonNames::Background)); @@ -634,7 +634,7 @@ static GouraudBounds bounds_from_decode_array(ReadonlySpan decode_array) class GouraudPaintStyle final : public Gfx::PaintStyle { public: - static NonnullRefPtr create(NonnullRefPtr color_space, ShadingFunctionsType functions, Array points, Array colors, GouraudBounds bounds) + static NonnullRefPtr create(NonnullRefPtr color_space, ShadingFunctionsType functions, Array points, Array colors, GouraudBounds bounds) { return adopt_ref(*new GouraudPaintStyle(move(color_space), move(functions), move(points), move(colors), move(bounds))); } @@ -648,7 +648,7 @@ class GouraudPaintStyle final : public Gfx::PaintStyle { } private: - GouraudPaintStyle(NonnullRefPtr color_space, ShadingFunctionsType functions, Array points, Array colors, GouraudBounds bounds) + GouraudPaintStyle(NonnullRefPtr color_space, ShadingFunctionsType functions, Array points, Array colors, GouraudBounds bounds) : m_functions(move(functions)) , m_color_space(move(color_space)) , m_points(move(points)) @@ -660,7 +660,7 @@ class GouraudPaintStyle final : public Gfx::PaintStyle { Gfx::Color sample_color_in_bbox(Gfx::IntPoint) const; ShadingFunctionsType m_functions; - NonnullRefPtr m_color_space; + NonnullRefPtr m_color_space; Array m_points; Array m_colors; GouraudBounds m_bounds; @@ -704,7 +704,7 @@ Gfx::Color GouraudPaintStyle::sample_color_in_bbox(Gfx::IntPoint point_in_bbox) return MUST(m_color_space->style(color)).get(); } -void draw_gouraud_triangle(Gfx::Painter& painter, NonnullRefPtr color_space, ShadingFunctionsType functions, Array points, Array colors, GouraudBounds const& bounds) +void draw_gouraud_triangle(Gfx::Painter& painter, NonnullRefPtr color_space, ShadingFunctionsType functions, Array points, Array colors, GouraudBounds const& bounds) { static_assert(points.size() == 3); static_assert(colors.size() == 3); @@ -727,7 +727,7 @@ struct Triangle { u32 c; }; -PDFErrorOr draw_gouraud_triangles(Gfx::Painter& painter, Gfx::AffineTransform const& ctm, NonnullRefPtr color_space, ShadingFunctionsType const& functions, Vector const& triangles, Vector const& vertex_data, GouraudBounds bounds) +PDFErrorOr draw_gouraud_triangles(Gfx::Painter& painter, Gfx::AffineTransform const& ctm, NonnullRefPtr color_space, ShadingFunctionsType const& functions, Vector const& triangles, Vector const& vertex_data, GouraudBounds bounds) { size_t const number_of_components = !functions.has() ? 1 : color_space->number_of_components(); bool is_indexed = color_space->family() == ColorSpaceFamily::Indexed; @@ -771,7 +771,7 @@ PDFErrorOr draw_gouraud_triangles(Gfx::Painter& painter, Gfx::AffineTransf return {}; } -static void draw_gouraud_quad(Gfx::Painter& painter, NonnullRefPtr color_space, ShadingFunctionsType functions, Array points, Array colors, GouraudBounds const& bounds) +static void draw_gouraud_quad(Gfx::Painter& painter, NonnullRefPtr color_space, ShadingFunctionsType functions, Array points, Array colors, GouraudBounds const& bounds) { // FIXME: https://gpuopen.com/learn/bilinear-interpolation-quadrilateral-barycentric-coordinates/ / https://jcgt.org/published/0011/03/04/paper.pdf instead. draw_gouraud_triangle(painter, color_space, functions, { points[0], points[1], points[3] }, { colors[0], colors[1], colors[3] }, bounds); @@ -783,7 +783,7 @@ struct GouraudBezierPatch { Array colors {}; }; -static void draw_gouraud_bezier_patch(Gfx::Painter& painter, NonnullRefPtr color_space, ShadingFunctionsType functions, GouraudBezierPatch const& patch, GouraudBounds const& bounds, int depth = 0) +static void draw_gouraud_bezier_patch(Gfx::Painter& painter, NonnullRefPtr color_space, ShadingFunctionsType functions, GouraudBezierPatch const& patch, GouraudBounds const& bounds, int depth = 0) { auto const& points = patch.points; auto const& colors = patch.colors; @@ -1425,7 +1425,7 @@ PDFErrorOr> CoonsPatchShading::create(Document* PDFErrorOr CoonsPatchShading::draw(Gfx::Painter& painter, Gfx::AffineTransform const& ctm) { - NonnullRefPtr color_space = m_common_entries.color_space; + NonnullRefPtr color_space = m_common_entries.color_space; size_t const number_of_components = !m_functions.has() ? 1 : color_space->number_of_components(); bool is_indexed = color_space->family() == ColorSpaceFamily::Indexed; @@ -1796,7 +1796,7 @@ PDFErrorOr> TensorProductPatchShading:: PDFErrorOr TensorProductPatchShading::draw(Gfx::Painter& painter, Gfx::AffineTransform const& ctm) { - NonnullRefPtr color_space = m_common_entries.color_space; + NonnullRefPtr color_space = m_common_entries.color_space; size_t const number_of_components = !m_functions.has() ? 1 : color_space->number_of_components(); bool is_indexed = color_space->family() == ColorSpaceFamily::Indexed; RefPtr indexed_color_space;