mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 23:47:45 +00:00
LibPDF: Use Variant<Color, PaintStyle> instead of Color for ColorSpaces
This is in anticipation of Pattern color space support which does not yield a simple color.
This commit is contained in:
parent
e4b8d68039
commit
082a4197b6
6 changed files with 116 additions and 55 deletions
|
@ -101,7 +101,7 @@ NonnullRefPtr<DeviceGrayColorSpace> DeviceGrayColorSpace::the()
|
|||
return instance;
|
||||
}
|
||||
|
||||
PDFErrorOr<Color> DeviceGrayColorSpace::color(ReadonlySpan<Value> arguments) const
|
||||
PDFErrorOr<ColorOrStyle> DeviceGrayColorSpace::style(ReadonlySpan<Value> arguments) const
|
||||
{
|
||||
VERIFY(arguments.size() == 1);
|
||||
auto gray = static_cast<u8>(arguments[0].to_float() * 255.0f);
|
||||
|
@ -119,7 +119,7 @@ NonnullRefPtr<DeviceRGBColorSpace> DeviceRGBColorSpace::the()
|
|||
return instance;
|
||||
}
|
||||
|
||||
PDFErrorOr<Color> DeviceRGBColorSpace::color(ReadonlySpan<Value> arguments) const
|
||||
PDFErrorOr<ColorOrStyle> DeviceRGBColorSpace::style(ReadonlySpan<Value> arguments) const
|
||||
{
|
||||
VERIFY(arguments.size() == 3);
|
||||
auto r = static_cast<u8>(arguments[0].to_float() * 255.0f);
|
||||
|
@ -139,7 +139,7 @@ NonnullRefPtr<DeviceCMYKColorSpace> DeviceCMYKColorSpace::the()
|
|||
return instance;
|
||||
}
|
||||
|
||||
PDFErrorOr<Color> DeviceCMYKColorSpace::color(ReadonlySpan<Value> arguments) const
|
||||
PDFErrorOr<ColorOrStyle> DeviceCMYKColorSpace::style(ReadonlySpan<Value> arguments) const
|
||||
{
|
||||
VERIFY(arguments.size() == 4);
|
||||
auto c = arguments[0].to_float();
|
||||
|
@ -197,7 +197,7 @@ DeviceNColorSpace::DeviceNColorSpace(NonnullRefPtr<ColorSpace> alternate_space,
|
|||
{
|
||||
}
|
||||
|
||||
PDFErrorOr<Color> DeviceNColorSpace::color(ReadonlySpan<Value> arguments) const
|
||||
PDFErrorOr<ColorOrStyle> DeviceNColorSpace::style(ReadonlySpan<Value> arguments) const
|
||||
{
|
||||
// FIXME: Does this need handling for the special colorant name "None"?
|
||||
// FIXME: When drawing to a printer, do something else.
|
||||
|
@ -211,7 +211,7 @@ PDFErrorOr<Color> DeviceNColorSpace::color(ReadonlySpan<Value> arguments) const
|
|||
for (size_t i = 0; i < tint_output.size(); ++i)
|
||||
m_tint_output_values[i] = tint_output[i];
|
||||
|
||||
return m_alternate_space->color(m_tint_output_values);
|
||||
return m_alternate_space->style(m_tint_output_values);
|
||||
}
|
||||
|
||||
int DeviceNColorSpace::number_of_components() const
|
||||
|
@ -347,7 +347,7 @@ PDFErrorOr<NonnullRefPtr<CalGrayColorSpace>> CalGrayColorSpace::create(Document*
|
|||
return color_space;
|
||||
}
|
||||
|
||||
PDFErrorOr<Color> CalGrayColorSpace::color(ReadonlySpan<Value> arguments) const
|
||||
PDFErrorOr<ColorOrStyle> CalGrayColorSpace::style(ReadonlySpan<Value> arguments) const
|
||||
{
|
||||
VERIFY(arguments.size() == 1);
|
||||
auto a = clamp(arguments[0].to_float(), 0.0f, 1.0f);
|
||||
|
@ -433,7 +433,7 @@ PDFErrorOr<NonnullRefPtr<CalRGBColorSpace>> CalRGBColorSpace::create(Document* d
|
|||
return color_space;
|
||||
}
|
||||
|
||||
PDFErrorOr<Color> CalRGBColorSpace::color(ReadonlySpan<Value> arguments) const
|
||||
PDFErrorOr<ColorOrStyle> CalRGBColorSpace::style(ReadonlySpan<Value> arguments) const
|
||||
{
|
||||
VERIFY(arguments.size() == 3);
|
||||
auto a = clamp(arguments[0].to_float(), 0.0f, 1.0f);
|
||||
|
@ -493,7 +493,7 @@ ICCBasedColorSpace::ICCBasedColorSpace(NonnullRefPtr<Gfx::ICC::Profile> profile)
|
|||
{
|
||||
}
|
||||
|
||||
PDFErrorOr<Color> ICCBasedColorSpace::color(ReadonlySpan<Value> arguments) const
|
||||
PDFErrorOr<ColorOrStyle> ICCBasedColorSpace::style(ReadonlySpan<Value> arguments) const
|
||||
{
|
||||
if (!s_srgb_profile)
|
||||
s_srgb_profile = TRY(Gfx::ICC::sRGB());
|
||||
|
@ -593,7 +593,7 @@ PDFErrorOr<NonnullRefPtr<LabColorSpace>> LabColorSpace::create(Document* documen
|
|||
return color_space;
|
||||
}
|
||||
|
||||
PDFErrorOr<Color> LabColorSpace::color(ReadonlySpan<Value> arguments) const
|
||||
PDFErrorOr<ColorOrStyle> LabColorSpace::style(ReadonlySpan<Value> arguments) const
|
||||
{
|
||||
VERIFY(arguments.size() == 3);
|
||||
auto L_star = clamp(arguments[0].to_float(), 0.0f, 100.0f);
|
||||
|
@ -692,7 +692,7 @@ IndexedColorSpace::IndexedColorSpace(NonnullRefPtr<ColorSpace> base)
|
|||
{
|
||||
}
|
||||
|
||||
PDFErrorOr<Color> IndexedColorSpace::color(ReadonlySpan<Value> arguments) const
|
||||
PDFErrorOr<ColorOrStyle> IndexedColorSpace::style(ReadonlySpan<Value> arguments) const
|
||||
{
|
||||
VERIFY(arguments.size() == 1);
|
||||
|
||||
|
@ -705,7 +705,7 @@ PDFErrorOr<Color> IndexedColorSpace::color(ReadonlySpan<Value> arguments) const
|
|||
for (size_t i = 0; i < n; ++i)
|
||||
TRY(components.try_append(Value(m_lookup[index * n + i] / 255.0f)));
|
||||
|
||||
return m_base->color(components);
|
||||
return m_base->style(components);
|
||||
}
|
||||
|
||||
Vector<float> IndexedColorSpace::default_decode() const
|
||||
|
@ -748,7 +748,7 @@ SeparationColorSpace::SeparationColorSpace(NonnullRefPtr<ColorSpace> alternate_s
|
|||
{
|
||||
}
|
||||
|
||||
PDFErrorOr<Color> SeparationColorSpace::color(ReadonlySpan<Value> arguments) const
|
||||
PDFErrorOr<ColorOrStyle> SeparationColorSpace::style(ReadonlySpan<Value> arguments) const
|
||||
{
|
||||
// "For an additive device such as a computer display, a Separation color space never applies a process colorant directly;
|
||||
// it always reverts to the alternate color space as described below."
|
||||
|
@ -765,12 +765,11 @@ PDFErrorOr<Color> SeparationColorSpace::color(ReadonlySpan<Value> arguments) con
|
|||
for (size_t i = 0; i < tint_output.size(); ++i)
|
||||
m_tint_output_values[i] = tint_output[i];
|
||||
|
||||
return m_alternate_space->color(m_tint_output_values);
|
||||
return m_alternate_space->style(m_tint_output_values);
|
||||
}
|
||||
|
||||
Vector<float> SeparationColorSpace::default_decode() const
|
||||
{
|
||||
return { 0.0f, 1.0f };
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <AK/Forward.h>
|
||||
#include <LibGfx/Color.h>
|
||||
#include <LibGfx/ICC/Profile.h>
|
||||
#include <LibGfx/PaintStyle.h>
|
||||
#include <LibPDF/Function.h>
|
||||
#include <LibPDF/Value.h>
|
||||
|
||||
|
@ -28,6 +29,9 @@
|
|||
|
||||
namespace PDF {
|
||||
|
||||
typedef Variant<Gfx::Color, NonnullRefPtr<Gfx::PaintStyle>> ColorOrStyle;
|
||||
class Renderer;
|
||||
|
||||
class ColorSpaceFamily {
|
||||
public:
|
||||
ColorSpaceFamily(DeprecatedFlyString name, bool may_be_specified_directly)
|
||||
|
@ -62,7 +66,7 @@ public:
|
|||
|
||||
virtual ~ColorSpace() = default;
|
||||
|
||||
virtual PDFErrorOr<Color> color(ReadonlySpan<Value> arguments) const = 0;
|
||||
virtual PDFErrorOr<ColorOrStyle> style(ReadonlySpan<Value> arguments) const = 0;
|
||||
virtual int number_of_components() const = 0;
|
||||
virtual Vector<float> default_decode() const = 0; // "TABLE 4.40 Default Decode arrays"
|
||||
virtual ColorSpaceFamily const& family() const = 0;
|
||||
|
@ -74,7 +78,7 @@ public:
|
|||
|
||||
~DeviceGrayColorSpace() override = default;
|
||||
|
||||
PDFErrorOr<Color> color(ReadonlySpan<Value> arguments) const override;
|
||||
PDFErrorOr<ColorOrStyle> style(ReadonlySpan<Value> arguments) const override;
|
||||
int number_of_components() const override { return 1; }
|
||||
Vector<float> default_decode() const override;
|
||||
ColorSpaceFamily const& family() const override { return ColorSpaceFamily::DeviceGray; }
|
||||
|
@ -89,7 +93,7 @@ public:
|
|||
|
||||
~DeviceRGBColorSpace() override = default;
|
||||
|
||||
PDFErrorOr<Color> color(ReadonlySpan<Value> arguments) const override;
|
||||
PDFErrorOr<ColorOrStyle> style(ReadonlySpan<Value> arguments) const override;
|
||||
int number_of_components() const override { return 3; }
|
||||
Vector<float> default_decode() const override;
|
||||
ColorSpaceFamily const& family() const override { return ColorSpaceFamily::DeviceRGB; }
|
||||
|
@ -104,7 +108,7 @@ public:
|
|||
|
||||
~DeviceCMYKColorSpace() override = default;
|
||||
|
||||
PDFErrorOr<Color> color(ReadonlySpan<Value> arguments) const override;
|
||||
PDFErrorOr<ColorOrStyle> style(ReadonlySpan<Value> arguments) const override;
|
||||
int number_of_components() const override { return 4; }
|
||||
Vector<float> default_decode() const override;
|
||||
ColorSpaceFamily const& family() const override { return ColorSpaceFamily::DeviceCMYK; }
|
||||
|
@ -119,7 +123,7 @@ public:
|
|||
|
||||
~DeviceNColorSpace() override = default;
|
||||
|
||||
PDFErrorOr<Color> color(ReadonlySpan<Value> arguments) const override;
|
||||
PDFErrorOr<ColorOrStyle> style(ReadonlySpan<Value> arguments) const override;
|
||||
int number_of_components() const override;
|
||||
Vector<float> default_decode() const override;
|
||||
ColorSpaceFamily const& family() const override { return ColorSpaceFamily::DeviceN; }
|
||||
|
@ -140,7 +144,7 @@ public:
|
|||
|
||||
~CalGrayColorSpace() override = default;
|
||||
|
||||
PDFErrorOr<Color> color(ReadonlySpan<Value> arguments) const override;
|
||||
PDFErrorOr<ColorOrStyle> style(ReadonlySpan<Value> arguments) const override;
|
||||
int number_of_components() const override { return 1; }
|
||||
Vector<float> default_decode() const override;
|
||||
ColorSpaceFamily const& family() const override { return ColorSpaceFamily::CalGray; }
|
||||
|
@ -159,7 +163,7 @@ public:
|
|||
|
||||
~CalRGBColorSpace() override = default;
|
||||
|
||||
PDFErrorOr<Color> color(ReadonlySpan<Value> arguments) const override;
|
||||
PDFErrorOr<ColorOrStyle> style(ReadonlySpan<Value> arguments) const override;
|
||||
int number_of_components() const override { return 3; }
|
||||
Vector<float> default_decode() const override;
|
||||
ColorSpaceFamily const& family() const override { return ColorSpaceFamily::CalRGB; }
|
||||
|
@ -179,7 +183,7 @@ public:
|
|||
|
||||
~ICCBasedColorSpace() override = default;
|
||||
|
||||
PDFErrorOr<Color> color(ReadonlySpan<Value> arguments) const override;
|
||||
PDFErrorOr<ColorOrStyle> style(ReadonlySpan<Value> arguments) const override;
|
||||
int number_of_components() const override;
|
||||
Vector<float> default_decode() const override;
|
||||
ColorSpaceFamily const& family() const override { return ColorSpaceFamily::ICCBased; }
|
||||
|
@ -197,7 +201,7 @@ public:
|
|||
|
||||
~LabColorSpace() override = default;
|
||||
|
||||
PDFErrorOr<Color> color(ReadonlySpan<Value> arguments) const override;
|
||||
PDFErrorOr<ColorOrStyle> style(ReadonlySpan<Value> arguments) const override;
|
||||
int number_of_components() const override { return 3; }
|
||||
Vector<float> default_decode() const override;
|
||||
ColorSpaceFamily const& family() const override { return ColorSpaceFamily::Lab; }
|
||||
|
@ -216,7 +220,7 @@ public:
|
|||
|
||||
~IndexedColorSpace() override = default;
|
||||
|
||||
PDFErrorOr<Color> color(ReadonlySpan<Value> arguments) const override;
|
||||
PDFErrorOr<ColorOrStyle> style(ReadonlySpan<Value> arguments) const override;
|
||||
int number_of_components() const override { return 1; }
|
||||
Vector<float> default_decode() const override;
|
||||
ColorSpaceFamily const& family() const override { return ColorSpaceFamily::Indexed; }
|
||||
|
@ -235,7 +239,7 @@ public:
|
|||
|
||||
~SeparationColorSpace() override = default;
|
||||
|
||||
PDFErrorOr<Color> color(ReadonlySpan<Value> arguments) const override;
|
||||
PDFErrorOr<ColorOrStyle> style(ReadonlySpan<Value> arguments) const override;
|
||||
int number_of_components() const override { return 1; }
|
||||
Vector<float> default_decode() const override;
|
||||
ColorSpaceFamily const& family() const override { return ColorSpaceFamily::Separation; }
|
||||
|
@ -248,5 +252,4 @@ private:
|
|||
NonnullRefPtr<Function> m_tint_transform;
|
||||
Vector<Value> mutable m_tint_output_values;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -48,13 +48,20 @@ void TrueTypeFont::set_font_size(float font_size)
|
|||
m_font = m_font->with_size((font_size * POINTS_PER_INCH) / DEFAULT_DPI);
|
||||
}
|
||||
|
||||
PDFErrorOr<void> TrueTypeFont::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float, u8 char_code, Renderer const& renderer)
|
||||
PDFErrorOr<void> TrueTypeFont::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u8 char_code, Renderer const& renderer)
|
||||
{
|
||||
auto color = renderer.state().paint_color;
|
||||
auto style = renderer.state().paint_style;
|
||||
|
||||
// Account for the reversed font baseline
|
||||
auto position = point.translated(0, -m_font->baseline());
|
||||
painter.draw_glyph(position, char_code, *m_font, color);
|
||||
if (style.has<Color>()) {
|
||||
painter.draw_glyph(position, char_code, *m_font, style.get<Color>());
|
||||
} else {
|
||||
// FIXME: Bounding box and sample point look to be pretty wrong
|
||||
style.get<NonnullRefPtr<Gfx::PaintStyle>>()->paint(Gfx::IntRect(position.x(), position.y(), width, 0), [&](auto sample) {
|
||||
painter.draw_glyph(position, char_code, *m_font, sample(Gfx::IntPoint(position.x(), position.y())));
|
||||
});
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -67,12 +67,19 @@ void Type1Font::set_font_size(float font_size)
|
|||
|
||||
PDFErrorOr<void> Type1Font::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint point, float width, u8 char_code, Renderer const& renderer)
|
||||
{
|
||||
auto color = renderer.state().paint_color;
|
||||
auto style = renderer.state().paint_style;
|
||||
|
||||
if (!m_font_program) {
|
||||
// Account for the reversed font baseline
|
||||
auto position = point.translated(0, -m_font->baseline());
|
||||
painter.draw_glyph(position, char_code, *m_font, color);
|
||||
// FIXME: Bounding box and sample point look to be pretty wrong
|
||||
if (style.has<Color>()) {
|
||||
painter.draw_glyph(position, char_code, *m_font, style.get<Color>());
|
||||
} else {
|
||||
style.get<NonnullRefPtr<Gfx::PaintStyle>>()->paint(Gfx::IntRect(position.x(), position.y(), width, 0), [&](auto sample) {
|
||||
painter.draw_glyph(position, char_code, *m_font, sample(Gfx::IntPoint(position.x(), position.y())));
|
||||
});
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -97,9 +104,18 @@ PDFErrorOr<void> Type1Font::draw_glyph(Gfx::Painter& painter, Gfx::FloatPoint po
|
|||
m_glyph_cache.set(index, bitmap);
|
||||
}
|
||||
|
||||
painter.blit_filtered(glyph_position.blit_position, *bitmap, bitmap->rect(), [color](Color pixel) -> Color {
|
||||
return pixel.multiply(color);
|
||||
});
|
||||
if (style.has<Color>()) {
|
||||
painter.blit_filtered(glyph_position.blit_position, *bitmap, bitmap->rect(), [style](Color pixel) -> Color {
|
||||
return pixel.multiply(style.get<Color>());
|
||||
});
|
||||
} else {
|
||||
style.get<NonnullRefPtr<Gfx::PaintStyle>>()->paint(bitmap->physical_rect(), [&](auto sample) {
|
||||
painter.blit_filtered(glyph_position.blit_position, *bitmap, bitmap->rect(), [&](Color pixel) -> Color {
|
||||
// FIXME: Presumably we need to sample at every point in the glyph, not just the top left?
|
||||
return pixel.multiply(sample(glyph_position.blit_position));
|
||||
});
|
||||
});
|
||||
}
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -311,7 +311,11 @@ void Renderer::end_path_paint()
|
|||
RENDERER_HANDLER(path_stroke)
|
||||
{
|
||||
begin_path_paint();
|
||||
m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_color, state().ctm.x_scale() * state().line_width);
|
||||
if (state().stroke_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
|
||||
m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), state().ctm.x_scale() * state().line_width);
|
||||
} else {
|
||||
m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), state().ctm.x_scale() * state().line_width);
|
||||
}
|
||||
end_path_paint();
|
||||
return {};
|
||||
}
|
||||
|
@ -327,7 +331,11 @@ RENDERER_HANDLER(path_fill_nonzero)
|
|||
{
|
||||
begin_path_paint();
|
||||
m_current_path.close_all_subpaths();
|
||||
m_anti_aliasing_painter.fill_path(m_current_path, state().paint_color, Gfx::Painter::WindingRule::Nonzero);
|
||||
if (state().paint_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
|
||||
m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), 1.0, Gfx::Painter::WindingRule::Nonzero);
|
||||
} else {
|
||||
m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get<Color>(), Gfx::Painter::WindingRule::Nonzero);
|
||||
}
|
||||
end_path_paint();
|
||||
return {};
|
||||
}
|
||||
|
@ -341,20 +349,32 @@ RENDERER_HANDLER(path_fill_evenodd)
|
|||
{
|
||||
begin_path_paint();
|
||||
m_current_path.close_all_subpaths();
|
||||
m_anti_aliasing_painter.fill_path(m_current_path, state().paint_color, Gfx::Painter::WindingRule::EvenOdd);
|
||||
if (state().paint_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
|
||||
m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), 1.0, Gfx::Painter::WindingRule::EvenOdd);
|
||||
} else {
|
||||
m_anti_aliasing_painter.fill_path(m_current_path, state().paint_style.get<Color>(), Gfx::Painter::WindingRule::EvenOdd);
|
||||
}
|
||||
end_path_paint();
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_fill_stroke_nonzero)
|
||||
{
|
||||
m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_color, state().ctm.x_scale() * state().line_width);
|
||||
if (state().stroke_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
|
||||
m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), state().ctm.x_scale() * state().line_width);
|
||||
} else {
|
||||
m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), state().ctm.x_scale() * state().line_width);
|
||||
}
|
||||
return handle_path_fill_nonzero(args);
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(path_fill_stroke_evenodd)
|
||||
{
|
||||
m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_color, state().ctm.x_scale() * state().line_width);
|
||||
if (state().stroke_style.has<NonnullRefPtr<Gfx::PaintStyle>>()) {
|
||||
m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>(), state().ctm.x_scale() * state().line_width);
|
||||
} else {
|
||||
m_anti_aliasing_painter.stroke_path(m_current_path, state().stroke_style.get<Color>(), state().ctm.x_scale() * state().line_width);
|
||||
}
|
||||
return handle_path_fill_evenodd(args);
|
||||
}
|
||||
|
||||
|
@ -590,7 +610,7 @@ RENDERER_HANDLER(set_painting_space)
|
|||
|
||||
RENDERER_HANDLER(set_stroking_color)
|
||||
{
|
||||
state().stroke_color = TRY(state().stroke_color_space->color(args));
|
||||
state().stroke_style = TRY(state().stroke_color_space->style(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -603,13 +623,13 @@ RENDERER_HANDLER(set_stroking_color_extended)
|
|||
return Error::rendering_unsupported_error("Pattern color spaces not yet implemented");
|
||||
}
|
||||
|
||||
state().stroke_color = TRY(state().stroke_color_space->color(args));
|
||||
state().stroke_style = TRY(state().stroke_color_space->style(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_painting_color)
|
||||
{
|
||||
state().paint_color = TRY(state().paint_color_space->color(args));
|
||||
state().paint_style = TRY(state().paint_color_space->style(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -622,49 +642,49 @@ RENDERER_HANDLER(set_painting_color_extended)
|
|||
return Error::rendering_unsupported_error("Pattern color spaces not yet implemented");
|
||||
}
|
||||
|
||||
state().paint_color = TRY(state().paint_color_space->color(args));
|
||||
state().paint_style = TRY(state().paint_color_space->style(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_stroking_color_and_space_to_gray)
|
||||
{
|
||||
state().stroke_color_space = DeviceGrayColorSpace::the();
|
||||
state().stroke_color = TRY(state().stroke_color_space->color(args));
|
||||
state().stroke_style = TRY(state().stroke_color_space->style(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_painting_color_and_space_to_gray)
|
||||
{
|
||||
state().paint_color_space = DeviceGrayColorSpace::the();
|
||||
state().paint_color = TRY(state().paint_color_space->color(args));
|
||||
state().paint_style = TRY(state().paint_color_space->style(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_stroking_color_and_space_to_rgb)
|
||||
{
|
||||
state().stroke_color_space = DeviceRGBColorSpace::the();
|
||||
state().stroke_color = TRY(state().stroke_color_space->color(args));
|
||||
state().stroke_style = TRY(state().stroke_color_space->style(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_painting_color_and_space_to_rgb)
|
||||
{
|
||||
state().paint_color_space = DeviceRGBColorSpace::the();
|
||||
state().paint_color = TRY(state().paint_color_space->color(args));
|
||||
state().paint_style = TRY(state().paint_color_space->style(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_stroking_color_and_space_to_cmyk)
|
||||
{
|
||||
state().stroke_color_space = DeviceCMYKColorSpace::the();
|
||||
state().stroke_color = TRY(state().stroke_color_space->color(args));
|
||||
state().stroke_style = TRY(state().stroke_color_space->style(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
RENDERER_HANDLER(set_painting_color_and_space_to_cmyk)
|
||||
{
|
||||
state().paint_color_space = DeviceCMYKColorSpace::the();
|
||||
state().paint_color = TRY(state().paint_color_space->color(args));
|
||||
state().paint_style = TRY(state().paint_color_space->style(args));
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -956,8 +976,16 @@ PDFErrorOr<NonnullRefPtr<Gfx::Bitmap>> Renderer::load_image(NonnullRefPtr<Stream
|
|||
sample = sample.slice(bytes_per_component);
|
||||
component_values[i] = Value { component_value_decoders[i].interpolate(component[0]) };
|
||||
}
|
||||
auto color = TRY(color_space->color(component_values));
|
||||
bitmap->set_pixel(x, y, color);
|
||||
auto color = TRY(color_space->style(component_values));
|
||||
if (color.has<Color>()) {
|
||||
auto c = color.get<Color>();
|
||||
bitmap->set_pixel(x, y, c);
|
||||
} else {
|
||||
auto paint_style = color.get<NonnullRefPtr<Gfx::PaintStyle>>();
|
||||
paint_style->paint(bitmap->rect(), [&](auto sample) {
|
||||
bitmap->set_pixel(x, y, sample(Gfx::IntPoint(x, y)));
|
||||
});
|
||||
}
|
||||
++x;
|
||||
if (x == width) {
|
||||
x = 0;
|
||||
|
|
|
@ -74,8 +74,8 @@ struct GraphicsState {
|
|||
ClippingPaths clipping_paths;
|
||||
RefPtr<ColorSpace> stroke_color_space { DeviceGrayColorSpace::the() };
|
||||
RefPtr<ColorSpace> paint_color_space { DeviceGrayColorSpace::the() };
|
||||
Gfx::Color stroke_color { Gfx::Color::NamedColor::Black };
|
||||
Gfx::Color paint_color { Gfx::Color::NamedColor::Black };
|
||||
ColorOrStyle stroke_style { Color::Black };
|
||||
ColorOrStyle paint_style { Color::Black };
|
||||
DeprecatedString color_rendering_intent { "RelativeColorimetric"sv };
|
||||
float flatness_tolerance { 0.0f };
|
||||
float line_width { 1.0f };
|
||||
|
@ -286,8 +286,16 @@ struct Formatter<PDF::GraphicsState> : Formatter<StringView> {
|
|||
StringBuilder builder;
|
||||
builder.append("GraphicsState {\n"sv);
|
||||
builder.appendff(" ctm={}\n", state.ctm);
|
||||
builder.appendff(" stroke_color={}\n", state.stroke_color);
|
||||
builder.appendff(" paint_color={}\n", state.paint_color);
|
||||
if (state.stroke_style.has<Color>()) {
|
||||
builder.appendff(" stroke_style={}\n", state.stroke_style.get<Color>());
|
||||
} else {
|
||||
builder.appendff(" stroke_style={}\n", state.stroke_style.get<NonnullRefPtr<Gfx::PaintStyle>>());
|
||||
}
|
||||
if (state.paint_style.has<Color>()) {
|
||||
builder.appendff(" paint_style={}\n", state.paint_style.get<Color>());
|
||||
} else {
|
||||
builder.appendff(" paint_style={}\n", state.paint_style.get<NonnullRefPtr<Gfx::PaintStyle>>());
|
||||
}
|
||||
builder.appendff(" color_rendering_intent={}\n", state.color_rendering_intent);
|
||||
builder.appendff(" flatness_tolerance={}\n", state.flatness_tolerance);
|
||||
builder.appendff(" line_width={}\n", state.line_width);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue