/* * Copyright (c) 2021-2022, Matthew Olsson * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include #include #include #define ENUMERATE_COLOR_SPACE_FAMILIES(V) \ V(DeviceGray, true) \ V(DeviceRGB, true) \ V(DeviceCMYK, true) \ V(CalGray, false) \ V(CalRGB, false) \ V(Lab, false) \ V(ICCBased, false) \ V(Indexed, false) \ V(Pattern, true) \ V(Separation, false) \ V(DeviceN, false) namespace PDF { typedef Variant> ColorOrStyle; class Renderer; class ColorSpaceFamily { public: ColorSpaceFamily(DeprecatedFlyString name, bool may_be_specified_directly) : m_name(move(name)) , m_may_be_specified_directly(may_be_specified_directly) { } DeprecatedFlyString name() const { return m_name; } bool may_be_specified_directly() const { return m_may_be_specified_directly; } static PDFErrorOr get(DeprecatedFlyString const&); #define ENUMERATE(name, may_be_specified_directly) static ColorSpaceFamily name; ENUMERATE_COLOR_SPACE_FAMILIES(ENUMERATE) #undef ENUMERATE bool operator==(ColorSpaceFamily const& other) const { return m_name == other.m_name; } private: DeprecatedFlyString m_name; bool m_may_be_specified_directly; }; class ColorSpace : public RefCounted { public: static PDFErrorOr> create(Document*, NonnullRefPtr, Renderer&); static PDFErrorOr> create(DeprecatedFlyString const&, Renderer&); static PDFErrorOr> create(Document*, NonnullRefPtr, Renderer&); virtual ~ColorSpace() = default; virtual PDFErrorOr style(ReadonlySpan arguments) const = 0; virtual PDFErrorOr style(ReadonlySpan arguments) const { 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 { public: static NonnullRefPtr the(); ~DeviceGrayColorSpace() override = default; PDFErrorOr style(ReadonlySpan arguments) const override; int number_of_components() const override { return 1; } Vector default_decode() const override; ColorSpaceFamily const& family() const override { return ColorSpaceFamily::DeviceGray; } private: DeviceGrayColorSpace() = default; }; class DeviceRGBColorSpace final : public ColorSpace { public: static NonnullRefPtr the(); ~DeviceRGBColorSpace() override = default; PDFErrorOr style(ReadonlySpan arguments) const override; int number_of_components() const override { return 3; } Vector default_decode() const override; ColorSpaceFamily const& family() const override { return ColorSpaceFamily::DeviceRGB; } private: DeviceRGBColorSpace() = default; }; class DeviceCMYKColorSpace final : public ColorSpace { public: static ErrorOr> the(); ~DeviceCMYKColorSpace() override = default; PDFErrorOr style(ReadonlySpan arguments) const override; int number_of_components() const override { return 4; } Vector default_decode() const override; ColorSpaceFamily const& family() const override { return ColorSpaceFamily::DeviceCMYK; } private: DeviceCMYKColorSpace() = default; }; class DeviceNColorSpace final : public ColorSpace { public: static PDFErrorOr> create(Document*, Vector&& parameters, Renderer&); ~DeviceNColorSpace() 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::DeviceN; } private: DeviceNColorSpace(NonnullRefPtr, NonnullRefPtr); Vector m_names; NonnullRefPtr m_alternate_space; NonnullRefPtr m_tint_transform; Vector mutable m_tint_output_values; }; class CalGrayColorSpace final : public ColorSpace { public: static PDFErrorOr> create(Document*, Vector&& parameters); ~CalGrayColorSpace() override = default; PDFErrorOr style(ReadonlySpan arguments) const override; int number_of_components() const override { return 1; } Vector default_decode() const override; ColorSpaceFamily const& family() const override { return ColorSpaceFamily::CalGray; } private: CalGrayColorSpace() = default; Array m_whitepoint { 0, 0, 0 }; Array m_blackpoint { 0, 0, 0 }; float m_gamma { 1 }; }; class CalRGBColorSpace final : public ColorSpace { public: static PDFErrorOr> create(Document*, Vector&& parameters); ~CalRGBColorSpace() override = default; PDFErrorOr style(ReadonlySpan arguments) const override; int number_of_components() const override { return 3; } Vector default_decode() const override; ColorSpaceFamily const& family() const override { return ColorSpaceFamily::CalRGB; } private: CalRGBColorSpace() = default; Array m_whitepoint { 0, 0, 0 }; Array m_blackpoint { 0, 0, 0 }; Array m_gamma { 1, 1, 1 }; Array m_matrix { 1, 0, 0, 0, 1, 0, 0, 0, 1 }; }; class ICCBasedColorSpace final : public ColorSpace { public: static PDFErrorOr> create(Document*, Vector&& parameters, Renderer&); ~ICCBasedColorSpace() 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::ICCBased; } static NonnullRefPtr sRGB(); private: ICCBasedColorSpace(NonnullRefPtr); static RefPtr s_srgb_profile; NonnullRefPtr m_profile; mutable Vector m_components; mutable Vector m_bytes; Optional m_map; }; class LabColorSpace final : public ColorSpace { public: static PDFErrorOr> create(Document*, Vector&& parameters); ~LabColorSpace() override = default; PDFErrorOr style(ReadonlySpan arguments) const override; int number_of_components() const override { return 3; } Vector default_decode() const override; ColorSpaceFamily const& family() const override { return ColorSpaceFamily::Lab; } private: LabColorSpace() = default; Array m_whitepoint { 0, 0, 0 }; Array m_blackpoint { 0, 0, 0 }; Array m_range { -100, 100, -100, 100 }; }; class IndexedColorSpace final : public ColorSpace { public: static PDFErrorOr> create(Document*, Vector&& parameters, Renderer&); ~IndexedColorSpace() override = default; PDFErrorOr style(ReadonlySpan arguments) const override; int number_of_components() const override { return 1; } Vector default_decode() const override; ColorSpaceFamily const& family() const override { return ColorSpaceFamily::Indexed; } private: IndexedColorSpace(NonnullRefPtr); NonnullRefPtr m_base; int m_hival { 0 }; Vector m_lookup; }; class SeparationColorSpace final : public ColorSpace { public: static PDFErrorOr> create(Document*, Vector&& parameters, Renderer&); ~SeparationColorSpace() override = default; PDFErrorOr style(ReadonlySpan arguments) const override; int number_of_components() const override { return 1; } Vector default_decode() const override; ColorSpaceFamily const& family() const override { return ColorSpaceFamily::Separation; } private: SeparationColorSpace(NonnullRefPtr, NonnullRefPtr); ByteString m_name; NonnullRefPtr m_alternate_space; NonnullRefPtr m_tint_transform; Vector mutable m_tint_output_values; }; }