File indexing completed on 2024-05-12 15:59:44

0001 /*
0002  *  SPDX-FileCopyrightText: 2010 Boudewijn Rempt <boud@valdyas.org>
0003  *  SPDX-FileCopyrightText: 2021 L. E. Segovia <amy@amyspark.me>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 /*
0008  * Constants and defines taken from gimp and psdparse
0009  */
0010 #ifndef PSD_H
0011 #define PSD_H
0012 
0013 #include "kritapsdutils_export.h"
0014 
0015 #include <QPair>
0016 #include <QString>
0017 #include <QVector>
0018 #include <cstdint>
0019 
0020 #include <KoColor.h>
0021 #include <KoColorModelStandardIds.h>
0022 #include <KoCompositeOpRegistry.h>
0023 #include <KoPattern.h>
0024 #include <resources/KoAbstractGradient.h>
0025 #include <KisResourcesInterface.h>
0026 
0027 const int MAX_CHANNELS = 56;
0028 
0029 const int MAX_PSD_SIZE = 30000;
0030 
0031 typedef qint32 Fixed; /* Represents a fixed point implied decimal */
0032 
0033 enum class psd_byte_order : std::uint_least8_t {
0034     psdBigEndian = 0,
0035     psdLittleEndian,
0036     psdInvalidByteOrder = 255,
0037 };
0038 
0039 enum psd_compression_type : std::uint16_t {
0040     Uncompressed = 0,
0041     RLE,
0042     ZIP,
0043     ZIPWithPrediction,
0044     Unknown = 255,
0045 };
0046 
0047 /**
0048  * Image color/depth modes
0049  */
0050 enum psd_color_mode {
0051     Bitmap = 0,
0052     Grayscale = 1,
0053     Indexed = 2,
0054     RGB = 3,
0055     CMYK = 4,
0056     MultiChannel = 7,
0057     DuoTone = 8,
0058     Lab = 9,
0059     Gray16,
0060     RGB48,
0061     Lab48,
0062     CMYK64,
0063     DeepMultichannel,
0064     Duotone16,
0065     COLORMODE_UNKNOWN = 9000
0066 };
0067 
0068 struct PsdResource {
0069     QString type;
0070     QString md5;
0071     QString filename;
0072     QString name;
0073 };
0074 
0075 /**
0076  * Color samplers, apparently distict from PSDColormode
0077  */
0078 namespace psd_color_sampler
0079 {
0080 enum PSDColorSamplers {
0081     RGB,
0082     HSB,
0083     CMYK,
0084     PANTONE, // LAB
0085     FOCOLTONE, // CMYK
0086     TRUMATCH, // CMYK
0087     TOYO, // LAB
0088     LAB,
0089     GRAYSCALE,
0090     HKS, // CMYK
0091     DIC, // LAB
0092     TOTAL_INK,
0093     MONITOR_RGB,
0094     DUOTONE,
0095     OPACITY,
0096     ANPA = 3000 // LAB
0097 };
0098 }
0099 
0100 // EFFECTS
0101 enum psd_gradient_style {
0102     psd_gradient_style_linear, // 'Lnr '
0103     psd_gradient_style_radial, // 'Rdl '
0104     psd_gradient_style_angle, // 'Angl'
0105     psd_gradient_style_reflected, // 'Rflc'
0106     psd_gradient_style_diamond // 'Dmnd'
0107 };
0108 
0109 enum psd_color_stop_type {
0110     psd_color_stop_type_foreground_color, // 'FrgC'
0111     psd_color_stop_type_background_Color, // 'BckC'
0112     psd_color_stop_type_user_stop // 'UsrS'
0113 };
0114 
0115 enum psd_technique_type {
0116     psd_technique_softer,
0117     psd_technique_precise,
0118     psd_technique_slope_limit,
0119 };
0120 
0121 enum psd_stroke_position { psd_stroke_outside, psd_stroke_inside, psd_stroke_center };
0122 
0123 enum psd_fill_type {
0124     psd_fill_solid_color,
0125     psd_fill_gradient,
0126     psd_fill_pattern,
0127 };
0128 
0129 enum psd_glow_source {
0130     psd_glow_center,
0131     psd_glow_edge,
0132 };
0133 
0134 enum psd_bevel_style {
0135     psd_bevel_outer_bevel,
0136     psd_bevel_inner_bevel,
0137     psd_bevel_emboss,
0138     psd_bevel_pillow_emboss,
0139     psd_bevel_stroke_emboss,
0140 };
0141 
0142 enum psd_direction { psd_direction_up, psd_direction_down };
0143 
0144 enum psd_section_type { psd_other = 0, psd_open_folder, psd_closed_folder, psd_bounding_divider };
0145 
0146 // GRADIENT MAP
0147 // Each color stop
0148 struct psd_gradient_color_stop {
0149     qint32 location; // Location of color stop
0150     qint32 midpoint; // Midpoint of color stop
0151     KoColor actual_color;
0152     psd_color_stop_type color_stop_type;
0153 };
0154 
0155 // Each transparency stop
0156 struct psd_gradient_transparency_stop {
0157     qint32 location; // Location of transparency stop
0158     qint32 midpoint; // Midpoint of transparency stop
0159     qint8 opacity; // Opacity of transparency stop
0160 };
0161 
0162 // Gradient settings (Photoshop 6.0)
0163 struct psd_layer_gradient_map {
0164     bool reverse; // Is gradient reverse
0165     bool dithered; // Is gradient dithered
0166     qint32 name_length;
0167     quint16 *name; // Name of the gradient: Unicode string, padded
0168     qint8 number_color_stops; // Number of color stops to follow
0169     psd_gradient_color_stop *color_stop;
0170     qint8 number_transparency_stops; // Number of transparency stops to follow
0171     psd_gradient_transparency_stop *transparency_stop;
0172     qint8 expansion_count; // Expansion count ( = 2 for Photoshop 6.0)
0173     qint8 interpolation; // Interpolation if length above is non-zero
0174     qint8 length; // Length (= 32 for Photoshop 6.0)
0175     qint8 mode; // Mode for this gradient
0176     qint32 random_number_seed; // Random number seed
0177     qint8 showing_transparency_flag; // Flag for showing transparency
0178     qint8 using_vector_color_flag; // Flag for using vector color
0179     qint32 roughness_factor; // Roughness factor
0180     QColor min_color;
0181     QColor max_color;
0182     QColor lookup_table[256];
0183 };
0184 
0185 struct psd_gradient_color {
0186     qint32 smoothness;
0187     qint32 name_length;
0188     quint16 *name; // Name of the gradient: Unicode string, padded
0189     qint8 number_color_stops; // Number of color stops to follow
0190     psd_gradient_color_stop *color_stop;
0191     qint8 number_transparency_stops; // Number of transparency stops to follow
0192     psd_gradient_transparency_stop *transparency_stop;
0193 };
0194 
0195 struct psd_pattern {
0196     psd_color_mode color_mode = Bitmap; // The image mode of the file.
0197     quint8 height = 0; // Point: vertical, 2 bytes and horizontal, 2 bytes
0198     quint8 width = 0;
0199     QString name;
0200     QString uuid;
0201     qint32 version = 0;
0202     quint8 top = 0; // Rectangle: top, left, bottom, right
0203     quint8 left = 0;
0204     quint8 bottom = 0;
0205     quint8 right = 0;
0206     qint32 max_channel = 0; // Max channels
0207     qint32 channel_number = 0;
0208     QVector<QRgb> color_table;
0209 };
0210 
0211 struct psd_layer_effects_context {
0212     psd_layer_effects_context()
0213         : keep_original(false)
0214     {
0215     }
0216 
0217     bool keep_original;
0218 };
0219 
0220 #define PSD_LOOKUP_TABLE_SIZE 256
0221 
0222 // dsdw, isdw: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_22203
0223 class KRITAPSDUTILS_EXPORT psd_layer_effects_shadow_base
0224 {
0225 public:
0226     psd_layer_effects_shadow_base()
0227         : m_invertsSelection(false)
0228         , m_edgeHidden(true)
0229         , m_effectEnabled(false)
0230         , m_blendMode(COMPOSITE_MULT)
0231         , m_color(KoColor::fromXML("<color channeldepth='U8'><sRGB r='0.0' g='0.0' b='0.0'/></color>"))
0232         , m_nativeColor(KoColor::fromXML("<color channeldepth='U8'><sRGB r='0.0' g='0.0' b='0.0'/></color>"))
0233         , m_opacity(75)
0234         , m_angle(120)
0235         , m_useGlobalLight(true)
0236         , m_distance(21)
0237         , m_spread(0)
0238         , m_size(21)
0239         , m_antiAliased(0)
0240         , m_noise(0)
0241         , m_knocksOut(false)
0242         , m_fillType(psd_fill_solid_color)
0243         , m_technique(psd_technique_softer)
0244         , m_range(100)
0245         , m_jitter(0)
0246     {
0247         for (int i = 0; i < PSD_LOOKUP_TABLE_SIZE; ++i) {
0248             m_contourLookupTable[i] = i;
0249         }
0250     }
0251 
0252     virtual ~psd_layer_effects_shadow_base();
0253 
0254     QPoint calculateOffset(const psd_layer_effects_context *context) const;
0255 
0256     void setEffectEnabled(bool value)
0257     {
0258         m_effectEnabled = value;
0259     }
0260 
0261     bool effectEnabled() const
0262     {
0263         return m_effectEnabled;
0264     }
0265 
0266     QString blendMode() const
0267     {
0268         return m_blendMode;
0269     }
0270 
0271     KoColor color() const
0272     {
0273         return m_color;
0274     }
0275 
0276     KoColor nativeColor() const
0277     {
0278         return m_nativeColor;
0279     }
0280 
0281     qint32 opacity() const
0282     {
0283         return m_opacity;
0284     }
0285 
0286     qint32 angle() const
0287     {
0288         return m_angle;
0289     }
0290 
0291     bool useGlobalLight() const
0292     {
0293         return m_useGlobalLight;
0294     }
0295 
0296     qint32 distance() const
0297     {
0298         return m_distance;
0299     }
0300 
0301     qint32 spread() const
0302     {
0303         return m_spread;
0304     }
0305 
0306     qint32 size() const
0307     {
0308         return m_size;
0309     }
0310 
0311     const quint8 *contourLookupTable() const
0312     {
0313         return m_contourLookupTable;
0314     }
0315 
0316     bool antiAliased() const
0317     {
0318         return m_antiAliased;
0319     }
0320 
0321     qint32 noise() const
0322     {
0323         return m_noise;
0324     }
0325 
0326     bool knocksOut() const
0327     {
0328         return m_knocksOut;
0329     }
0330 
0331     bool invertsSelection() const
0332     {
0333         return m_invertsSelection;
0334     }
0335 
0336     bool edgeHidden() const
0337     {
0338         return m_edgeHidden;
0339     }
0340 
0341     psd_fill_type fillType() const
0342     {
0343         return m_fillType;
0344     }
0345 
0346     psd_technique_type technique() const
0347     {
0348         return m_technique;
0349     }
0350 
0351     qint32 range() const
0352     {
0353         return m_range;
0354     }
0355 
0356     qint32 jitter() const
0357     {
0358         return m_jitter;
0359     }
0360 
0361     KoResourceSignature gradientLink() const {
0362         return m_gradientLink;
0363     }
0364 
0365     KoAbstractGradientSP gradient(KisResourcesInterfaceSP resourcesInterface) const
0366     {
0367         auto source = resourcesInterface->source<KoAbstractGradient>(m_gradientLink.type);
0368         return source.bestMatch(m_gradientLink.md5sum, m_gradientLink.filename, m_gradientLink.name);
0369     }
0370 
0371 public:
0372     void setBlendMode(QString value)
0373     {
0374         m_blendMode = value;
0375     }
0376 
0377     void setColor(KoColor value)
0378     {
0379         m_color = value;
0380     }
0381 
0382     void setNativeColor(KoColor value)
0383     {
0384         m_nativeColor = value;
0385     }
0386 
0387     void setOpacity(qint32 value)
0388     {
0389         m_opacity = value;
0390     }
0391 
0392     void setAngle(qint32 value)
0393     {
0394         m_angle = value;
0395     }
0396 
0397     void setUseGlobalLight(bool value)
0398     {
0399         m_useGlobalLight = value;
0400     }
0401 
0402     void setDistance(qint32 value)
0403     {
0404         m_distance = value;
0405     }
0406 
0407     void setSpread(qint32 value)
0408     {
0409         m_spread = value;
0410     }
0411 
0412     void setSize(qint32 value)
0413     {
0414         m_size = value;
0415     }
0416 
0417     void setContourLookupTable(const quint8 *value)
0418     {
0419         memcpy(m_contourLookupTable, value, PSD_LOOKUP_TABLE_SIZE * sizeof(quint8));
0420     }
0421 
0422     void setAntiAliased(bool value)
0423     {
0424         m_antiAliased = value;
0425     }
0426 
0427     void setNoise(qint32 value)
0428     {
0429         m_noise = value;
0430     }
0431 
0432     void setKnocksOut(bool value)
0433     {
0434         m_knocksOut = value;
0435     }
0436 
0437     void setInvertsSelection(bool value)
0438     {
0439         m_invertsSelection = value;
0440     }
0441 
0442     void setEdgeHidden(bool value)
0443     {
0444         m_edgeHidden = value;
0445     }
0446 
0447     void setFillType(psd_fill_type value)
0448     {
0449         m_fillType = value;
0450     }
0451 
0452     void setTechnique(psd_technique_type value)
0453     {
0454         m_technique = value;
0455     }
0456 
0457     void setRange(qint32 value)
0458     {
0459         m_range = value;
0460     }
0461 
0462     void setJitter(qint32 value)
0463     {
0464         m_jitter = value;
0465     }
0466 
0467     void setGradient(KoAbstractGradientSP value)
0468     {
0469         m_gradientLink.type = value->resourceType().first;
0470         m_gradientLink.md5sum = value->md5Sum();
0471         m_gradientLink.filename = value->filename();
0472         m_gradientLink.name = value->name();
0473     }
0474 
0475     virtual void scaleLinearSizes(qreal scale);
0476 
0477 private:
0478     // internal
0479     bool m_invertsSelection;
0480     bool m_edgeHidden;
0481 
0482 private:
0483     bool m_effectEnabled; // Effect enabled
0484 
0485     QString m_blendMode; // already in Krita format!
0486     KoColor m_color;
0487     KoColor m_nativeColor;
0488     qint32 m_opacity; // Opacity as a percent (0...100)
0489     qint32 m_angle; // Angle in degrees
0490     bool m_useGlobalLight; // Use this angle in all of the layer effects
0491     qint32 m_distance; // Distance in pixels
0492     qint32 m_spread; // Intensity as a percent
0493     qint32 m_size; // Blur value in pixels
0494 
0495     quint8 m_contourLookupTable[PSD_LOOKUP_TABLE_SIZE];
0496     bool m_antiAliased;
0497     qint32 m_noise;
0498     bool m_knocksOut;
0499 
0500     // for Outer/Inner Glow
0501     psd_fill_type m_fillType;
0502     psd_technique_type m_technique;
0503     qint32 m_range;
0504     qint32 m_jitter;
0505     KoResourceSignature m_gradientLink;
0506 };
0507 
0508 class KRITAPSDUTILS_EXPORT psd_layer_effects_shadow_common : public psd_layer_effects_shadow_base
0509 {
0510 public:
0511     /// FIXME: 'using' is not supported by MSVC, so please refactor in
0512     ///        some other way to ensure that the setters are not used
0513     ///        in the classes we don't want
0514 
0515     // using psd_layer_effects_shadow_base::setBlendMode;
0516     // using psd_layer_effects_shadow_base::setColor;
0517     // using psd_layer_effects_shadow_base::setOpacity;
0518     // using psd_layer_effects_shadow_base::setAngle;
0519     // using psd_layer_effects_shadow_base::setUseGlobalLight;
0520     // using psd_layer_effects_shadow_base::setDistance;
0521     // using psd_layer_effects_shadow_base::setSpread;
0522     // using psd_layer_effects_shadow_base::setSize;
0523     // using psd_layer_effects_shadow_base::setContourLookupTable;
0524     // using psd_layer_effects_shadow_base::setAntiAliased;
0525     // using psd_layer_effects_shadow_base::setNoise;
0526 
0527     ~psd_layer_effects_shadow_common() override;
0528 };
0529 
0530 class KRITAPSDUTILS_EXPORT psd_layer_effects_drop_shadow : public psd_layer_effects_shadow_common
0531 {
0532 public:
0533     /// FIXME: 'using' is not supported by MSVC, so please refactor in
0534     ///        some other way to ensure that the setters are not used
0535     ///        in the classes we don't want
0536 
0537     // using psd_layer_effects_shadow_base::setKnocksOut;
0538     ~psd_layer_effects_drop_shadow();
0539 };
0540 
0541 // isdw: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_22203
0542 class KRITAPSDUTILS_EXPORT psd_layer_effects_inner_shadow : public psd_layer_effects_shadow_common
0543 {
0544 public:
0545     psd_layer_effects_inner_shadow()
0546     {
0547         setKnocksOut(false);
0548         setInvertsSelection(true);
0549         setEdgeHidden(false);
0550     }
0551 
0552     ~psd_layer_effects_inner_shadow() override;
0553 };
0554 
0555 class KRITAPSDUTILS_EXPORT psd_layer_effects_glow_common : public psd_layer_effects_shadow_base
0556 {
0557 public:
0558     psd_layer_effects_glow_common()
0559     {
0560         setKnocksOut(true);
0561         setDistance(0);
0562         setBlendMode(COMPOSITE_LINEAR_DODGE);
0563         setColor(KoColor::fromXML("<color channeldepth='U8'><sRGB r='1.0' g='1.0' b='1.0'/></color>"));
0564     }
0565     ~psd_layer_effects_glow_common() override;
0566     /// FIXME: 'using' is not supported by MSVC, so please refactor in
0567     ///        some other way to ensure that the setters are not used
0568     ///        in the classes we don't want
0569 
0570     // using psd_layer_effects_shadow_base::setBlendMode;
0571     // using psd_layer_effects_shadow_base::setColor;
0572     // using psd_layer_effects_shadow_base::setOpacity;
0573 
0574     // using psd_layer_effects_shadow_base::setSpread;
0575     // using psd_layer_effects_shadow_base::setSize;
0576     // using psd_layer_effects_shadow_base::setContourLookupTable;
0577     // using psd_layer_effects_shadow_base::setAntiAliased;
0578     // using psd_layer_effects_shadow_base::setNoise;
0579 
0580     // using psd_layer_effects_shadow_base::setFillType;
0581     // using psd_layer_effects_shadow_base::setTechnique;
0582     // using psd_layer_effects_shadow_base::setRange;
0583     // using psd_layer_effects_shadow_base::setJitter;
0584     // using psd_layer_effects_shadow_base::setGradient;
0585 };
0586 
0587 // oglw: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_25738
0588 class KRITAPSDUTILS_EXPORT psd_layer_effects_outer_glow : public psd_layer_effects_glow_common
0589 {
0590 public:
0591     ~psd_layer_effects_outer_glow() override;
0592 };
0593 
0594 // iglw: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_27692
0595 class KRITAPSDUTILS_EXPORT psd_layer_effects_inner_glow : public psd_layer_effects_glow_common
0596 {
0597 public:
0598     psd_layer_effects_inner_glow()
0599         : m_source(psd_glow_edge)
0600     {
0601         setInvertsSelection(true);
0602         setEdgeHidden(false);
0603         setKnocksOut(false);
0604     }
0605 
0606     psd_glow_source source() const
0607     {
0608         return m_source;
0609     }
0610     void setSource(psd_glow_source value)
0611     {
0612         m_source = value;
0613     }
0614     ~psd_layer_effects_inner_glow() override;
0615 
0616 private:
0617     psd_glow_source m_source;
0618 };
0619 
0620 struct psd_layer_effects_satin : public psd_layer_effects_shadow_base {
0621     psd_layer_effects_satin()
0622     {
0623         setInvert(false);
0624         setUseGlobalLight(false);
0625         setDistance(8);
0626         setSize(7);
0627         setSpread(0);
0628         setKnocksOut(true);
0629         setEdgeHidden(false);
0630         setBlendMode(COMPOSITE_LINEAR_BURN);
0631     }
0632 
0633     /// FIXME: 'using' is not supported by MSVC, so please refactor in
0634     ///        some other way to ensure that the setters are not used
0635     ///        in the classes we don't want
0636 
0637     // using psd_layer_effects_shadow_base::setBlendMode;
0638     // using psd_layer_effects_shadow_base::setColor;
0639     // using psd_layer_effects_shadow_base::setOpacity;
0640 
0641     // // NOTE: no global light setting explicitly!
0642     // using psd_layer_effects_shadow_base::setAngle;
0643     // using psd_layer_effects_shadow_base::setDistance;
0644 
0645     // using psd_layer_effects_shadow_base::setSize;
0646 
0647     // using psd_layer_effects_shadow_base::setContourLookupTable;
0648     // using psd_layer_effects_shadow_base::setAntiAliased;
0649 
0650     bool invert() const
0651     {
0652         return m_invert;
0653     }
0654 
0655     void setInvert(bool value)
0656     {
0657         m_invert = value;
0658     }
0659 
0660 private:
0661     bool m_invert;
0662 };
0663 
0664 // bevl: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_31889
0665 struct psd_layer_effects_bevel_emboss : public psd_layer_effects_shadow_base {
0666     psd_layer_effects_bevel_emboss()
0667         : m_style(psd_bevel_inner_bevel)
0668         , m_technique(psd_technique_softer)
0669         , m_depth(100)
0670         , m_direction(psd_direction_up)
0671         , m_soften(0)
0672         ,
0673 
0674         m_altitude(30)
0675         ,
0676 
0677         m_glossAntiAliased(false)
0678         ,
0679 
0680         m_highlightBlendMode(COMPOSITE_SCREEN)
0681         , m_highlightColor(KoColor::fromXML("<color channeldepth='U8'><sRGB r='1.0' g='1.0' b='1.0'/></color>"))
0682         , m_highlightOpacity(75)
0683         ,
0684 
0685         m_shadowBlendMode(COMPOSITE_MULT)
0686         , m_shadowColor(KoColor::fromXML("<color channeldepth='U8'><sRGB r='0.0' g='0.0' b='0.0'/></color>"))
0687         , m_shadowOpacity(75)
0688         ,
0689 
0690         m_contourEnabled(false)
0691         , m_contourRange(100)
0692         ,
0693 
0694         m_textureEnabled(false)
0695         , m_textureScale(100)
0696         , m_textureDepth(100)
0697         , m_textureInvert(false)
0698         ,
0699 
0700         m_textureAlignWithLayer(true)
0701         , m_textureHorizontalPhase(0)
0702         , m_textureVerticalPhase(0)
0703     {
0704         for (int i = 0; i < PSD_LOOKUP_TABLE_SIZE; ++i) {
0705             m_glossContourLookupTable[i] = i;
0706         }
0707     }
0708 
0709     /// FIXME: 'using' is not supported by MSVC, so please refactor in
0710     ///        some other way to ensure that the setters are not used
0711     ///        in the classes we don't want
0712 
0713     // using psd_layer_effects_shadow_base::setSize;
0714 
0715     // using psd_layer_effects_shadow_base::setAngle;
0716     // using psd_layer_effects_shadow_base::setUseGlobalLight;
0717 
0718     // using psd_layer_effects_shadow_base::setContourLookupTable;
0719     // using psd_layer_effects_shadow_base::setAntiAliased;
0720 
0721     psd_bevel_style style() const
0722     {
0723         return m_style;
0724     }
0725     void setStyle(psd_bevel_style value)
0726     {
0727         m_style = value;
0728     }
0729 
0730     psd_technique_type technique() const
0731     {
0732         return m_technique;
0733     }
0734     void setTechnique(psd_technique_type value)
0735     {
0736         m_technique = value;
0737     }
0738 
0739     int depth() const
0740     {
0741         return m_depth;
0742     }
0743     void setDepth(int value)
0744     {
0745         m_depth = value;
0746     }
0747 
0748     psd_direction direction() const
0749     {
0750         return m_direction;
0751     }
0752     void setDirection(psd_direction value)
0753     {
0754         m_direction = value;
0755     }
0756 
0757     int soften() const
0758     {
0759         return m_soften;
0760     }
0761     void setSoften(int value)
0762     {
0763         m_soften = value;
0764     }
0765 
0766     int altitude() const
0767     {
0768         return m_altitude;
0769     }
0770     void setAltitude(int value)
0771     {
0772         m_altitude = value;
0773     }
0774 
0775     const quint8 *glossContourLookupTable() const
0776     {
0777         return m_glossContourLookupTable;
0778     }
0779 
0780     void setGlossContourLookupTable(const quint8 *value)
0781     {
0782         memcpy(m_glossContourLookupTable, value, PSD_LOOKUP_TABLE_SIZE * sizeof(quint8));
0783     }
0784 
0785     bool glossAntiAliased() const
0786     {
0787         return m_glossAntiAliased;
0788     }
0789     void setGlossAntiAliased(bool value)
0790     {
0791         m_glossAntiAliased = value;
0792     }
0793 
0794     QString highlightBlendMode() const
0795     {
0796         return m_highlightBlendMode;
0797     }
0798     void setHighlightBlendMode(QString value)
0799     {
0800         m_highlightBlendMode = value;
0801     }
0802 
0803     KoColor highlightColor() const
0804     {
0805         return m_highlightColor;
0806     }
0807     void setHighlightColor(KoColor value)
0808     {
0809         m_highlightColor = value;
0810     }
0811 
0812     qint32 highlightOpacity() const
0813     {
0814         return m_highlightOpacity;
0815     }
0816     void setHighlightOpacity(qint32 value)
0817     {
0818         m_highlightOpacity = value;
0819     }
0820 
0821     QString shadowBlendMode() const
0822     {
0823         return m_shadowBlendMode;
0824     }
0825     void setShadowBlendMode(QString value)
0826     {
0827         m_shadowBlendMode = value;
0828     }
0829 
0830     KoColor shadowColor() const
0831     {
0832         return m_shadowColor;
0833     }
0834     void setShadowColor(KoColor value)
0835     {
0836         m_shadowColor = value;
0837     }
0838 
0839     qint32 shadowOpacity() const
0840     {
0841         return m_shadowOpacity;
0842     }
0843     void setShadowOpacity(qint32 value)
0844     {
0845         m_shadowOpacity = value;
0846     }
0847 
0848     bool contourEnabled() const
0849     {
0850         return m_contourEnabled;
0851     }
0852     void setContourEnabled(bool value)
0853     {
0854         m_contourEnabled = value;
0855     }
0856 
0857     int contourRange() const
0858     {
0859         return m_contourRange;
0860     }
0861     void setContourRange(int value)
0862     {
0863         m_contourRange = value;
0864     }
0865 
0866     bool textureEnabled() const
0867     {
0868         return m_textureEnabled;
0869     }
0870     void setTextureEnabled(bool value)
0871     {
0872         m_textureEnabled = value;
0873     }
0874 
0875     KoResourceSignature texturePatternLink() const {
0876         return m_texturePatternLink;
0877     }
0878 
0879     KoPatternSP texturePattern(KisResourcesInterfaceSP resourcesInterface) const
0880     {
0881         auto source = resourcesInterface->source<KoPattern>(m_texturePatternLink.type);
0882         return source.bestMatch(m_texturePatternLink.md5sum, m_texturePatternLink.filename, m_texturePatternLink.name);
0883     }
0884 
0885     void setTexturePattern(KoPatternSP value)
0886     {
0887         m_texturePatternLink.type = value->resourceType().first;
0888         m_texturePatternLink.md5sum = value->md5Sum();
0889         m_texturePatternLink.filename = value->filename();
0890         m_texturePatternLink.name = value->name();
0891 
0892     }
0893 
0894     int textureScale() const
0895     {
0896         return m_textureScale;
0897     }
0898     void setTextureScale(int value)
0899     {
0900         m_textureScale = value;
0901     }
0902 
0903     int textureDepth() const
0904     {
0905         return m_textureDepth;
0906     }
0907     void setTextureDepth(int value)
0908     {
0909         m_textureDepth = value;
0910     }
0911 
0912     bool textureInvert() const
0913     {
0914         return m_textureInvert;
0915     }
0916     void setTextureInvert(bool value)
0917     {
0918         m_textureInvert = value;
0919     }
0920 
0921     bool textureAlignWithLayer() const
0922     {
0923         return m_textureAlignWithLayer;
0924     }
0925     void setTextureAlignWithLayer(bool value)
0926     {
0927         m_textureAlignWithLayer = value;
0928     }
0929 
0930     void setTexturePhase(const QPointF &phase)
0931     {
0932         m_textureHorizontalPhase = phase.x();
0933         m_textureVerticalPhase = phase.y();
0934     }
0935 
0936     QPointF texturePhase() const
0937     {
0938         return QPointF(m_textureHorizontalPhase, m_textureVerticalPhase);
0939     }
0940 
0941     int textureHorizontalPhase() const
0942     {
0943         return m_textureHorizontalPhase;
0944     }
0945     void setTextureHorizontalPhase(int value)
0946     {
0947         m_textureHorizontalPhase = value;
0948     }
0949 
0950     int textureVerticalPhase() const
0951     {
0952         return m_textureVerticalPhase;
0953     }
0954     void setTextureVerticalPhase(int value)
0955     {
0956         m_textureVerticalPhase = value;
0957     }
0958 
0959     void scaleLinearSizes(qreal scale) override
0960     {
0961         psd_layer_effects_shadow_base::scaleLinearSizes(scale);
0962         m_soften *= scale;
0963         m_textureScale *= scale;
0964     }
0965 
0966 private:
0967     psd_bevel_style m_style;
0968     psd_technique_type m_technique;
0969     int m_depth;
0970     psd_direction m_direction; // Up or down
0971     int m_soften; // Blur value in pixels.
0972 
0973     int m_altitude;
0974 
0975     quint8 m_glossContourLookupTable[256];
0976     bool m_glossAntiAliased;
0977 
0978     QString m_highlightBlendMode; // already in Krita format
0979     KoColor m_highlightColor;
0980     qint32 m_highlightOpacity; // Highlight opacity as a percent
0981 
0982     QString m_shadowBlendMode; // already in Krita format
0983     KoColor m_shadowColor;
0984     qint32 m_shadowOpacity; // Shadow opacity as a percent
0985 
0986     bool m_contourEnabled;
0987     int m_contourRange;
0988 
0989     bool m_textureEnabled;
0990     KoResourceSignature m_texturePatternLink;
0991     int m_textureScale;
0992     int m_textureDepth;
0993     bool m_textureInvert;
0994 
0995     bool m_textureAlignWithLayer;
0996     int m_textureHorizontalPhase; // 0..100%
0997     int m_textureVerticalPhase; // 0..100%
0998 };
0999 
1000 struct psd_layer_effects_overlay_base : public psd_layer_effects_shadow_base {
1001     psd_layer_effects_overlay_base()
1002         : m_scale(100)
1003         , m_alignWithLayer(true)
1004         , m_dither(false)
1005         , m_reverse(false)
1006         , m_style(psd_gradient_style_linear)
1007         , m_gradientXOffset(0)
1008         , m_gradientYOffset(0)
1009         , m_horizontalPhase(0)
1010         , m_verticalPhase(0)
1011     {
1012         setUseGlobalLight(false);
1013     }
1014 
1015     /// FIXME: 'using' is not supported by MSVC, so please refactor in
1016     ///        some other way to ensure that the setters are not used
1017     ///        in the classes we don't want
1018 
1019     // using psd_layer_effects_shadow_base::setBlendMode;
1020     // using psd_layer_effects_shadow_base::setOpacity;
1021 
1022     int scale() const
1023     {
1024         return m_scale;
1025     }
1026 
1027     bool alignWithLayer() const
1028     {
1029         return m_alignWithLayer;
1030     }
1031 
1032     bool dither() const
1033     {
1034         return m_dither;
1035     }
1036 
1037     bool reverse() const
1038     {
1039         return m_reverse;
1040     }
1041 
1042     psd_gradient_style style() const
1043     {
1044         return m_style;
1045     }
1046 
1047     int gradientXOffset() const
1048     {
1049         return m_gradientXOffset;
1050     }
1051 
1052     int gradientYOffset() const
1053     {
1054         return m_gradientYOffset;
1055     }
1056 
1057     KoResourceSignature patternLink() const {
1058         return m_patternLink;
1059     }
1060 
1061     KoPatternSP pattern(KisResourcesInterfaceSP resourcesInterface) const
1062     {
1063         auto source = resourcesInterface->source<KoPattern>(m_patternLink.type);
1064         return source.bestMatch(m_patternLink.md5sum, m_patternLink.filename, m_patternLink.name);
1065     }
1066 
1067     int horizontalPhase() const
1068     {
1069         return m_horizontalPhase;
1070     }
1071 
1072     int verticalPhase() const
1073     {
1074         return m_verticalPhase;
1075     }
1076 
1077     // refactor that
1078 public:
1079     void setScale(int value)
1080     {
1081         m_scale = value;
1082     }
1083 
1084     void setAlignWithLayer(bool value)
1085     {
1086         m_alignWithLayer = value;
1087     }
1088 
1089     void setDither(bool value)
1090     {
1091         m_dither = value;
1092     }
1093 
1094     void setReverse(bool value)
1095     {
1096         m_reverse = value;
1097     }
1098 
1099     void setStyle(psd_gradient_style value)
1100     {
1101         m_style = value;
1102     }
1103 
1104     void setGradientOffset(const QPointF &pt)
1105     {
1106         m_gradientXOffset = qRound(pt.x());
1107         m_gradientYOffset = qRound(pt.y());
1108     }
1109 
1110     QPointF gradientOffset() const
1111     {
1112         return QPointF(m_gradientXOffset, m_gradientYOffset);
1113     }
1114 
1115     void setPattern(KoPatternSP value)
1116     {
1117         m_patternLink.type = value->resourceType().first;
1118         m_patternLink.md5sum = value->md5Sum();
1119         m_patternLink.filename = value->filename();
1120         m_patternLink.name = value->name();
1121     }
1122 
1123     void setPatternPhase(const QPointF &phase)
1124     {
1125         m_horizontalPhase = phase.x();
1126         m_verticalPhase = phase.y();
1127     }
1128 
1129     QPointF patternPhase() const
1130     {
1131         return QPointF(m_horizontalPhase, m_verticalPhase);
1132     }
1133 
1134     void scaleLinearSizes(qreal scale) override
1135     {
1136         psd_layer_effects_shadow_base::scaleLinearSizes(scale);
1137         m_scale *= scale;
1138     }
1139 
1140 private:
1141     // Gradient+Pattern
1142     int m_scale;
1143     bool m_alignWithLayer;
1144 
1145     // Gradient
1146     bool m_dither;
1147     bool m_reverse;
1148     psd_gradient_style m_style;
1149     int m_gradientXOffset; // 0..100%
1150     int m_gradientYOffset; // 0..100%
1151 
1152     // Pattern
1153     KoResourceSignature m_patternLink;
1154     int m_horizontalPhase; // 0..100%
1155     int m_verticalPhase; // 0..100%
1156 
1157 protected:
1158     /// FIXME: 'using' is not supported by MSVC, so please refactor in
1159     ///        some other way to ensure that the setters are not used
1160     ///        in the classes we don't want
1161 
1162     // must be called in the derived classes' c-tor
1163     // using psd_layer_effects_shadow_base::setFillType;
1164 };
1165 
1166 // sofi: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_70055
1167 struct psd_layer_effects_color_overlay : public psd_layer_effects_overlay_base {
1168     psd_layer_effects_color_overlay()
1169     {
1170         setFillType(psd_fill_solid_color);
1171         setColor(KoColor::fromXML("<color channeldepth='U8'><sRGB r='1.0' g='1.0' b='1.0'/></color>"));
1172     }
1173 
1174     /// FIXME: 'using' is not supported by MSVC, so please refactor in
1175     ///        some other way to ensure that the setters are not used
1176     ///        in the classes we don't want
1177 
1178     // using psd_layer_effects_shadow_base::setColor;
1179 };
1180 
1181 struct psd_layer_effects_gradient_overlay : public psd_layer_effects_overlay_base {
1182     psd_layer_effects_gradient_overlay()
1183     {
1184         setFillType(psd_fill_gradient);
1185         setAngle(90);
1186         setReverse(false);
1187         setScale(100);
1188         setAlignWithLayer(true);
1189         setStyle(psd_gradient_style_linear);
1190     }
1191 
1192 public:
1193     /// FIXME: 'using' is not supported by MSVC, so please refactor in
1194     ///        some other way to ensure that the setters are not used
1195     ///        in the classes we don't want
1196 
1197     // using psd_layer_effects_shadow_base::setGradient;
1198     // using psd_layer_effects_shadow_base::setAngle;
1199 
1200     // using psd_layer_effects_overlay_base::setReverse;
1201     // using psd_layer_effects_overlay_base::setScale;
1202     // using psd_layer_effects_overlay_base::setAlignWithLayer;
1203     // using psd_layer_effects_overlay_base::setStyle;
1204 
1205     // using psd_layer_effects_overlay_base::setGradientOffset;
1206     // using psd_layer_effects_overlay_base::gradientOffset;
1207 };
1208 
1209 struct psd_layer_effects_pattern_overlay : public psd_layer_effects_overlay_base {
1210     psd_layer_effects_pattern_overlay()
1211     {
1212         setFillType(psd_fill_pattern);
1213         setScale(100);
1214         setAlignWithLayer(true);
1215     }
1216 
1217     /// FIXME: 'using' is not supported by MSVC, so please refactor in
1218     ///        some other way to ensure that the setters are not used
1219     ///        in the classes we don't want
1220 
1221     // using psd_layer_effects_overlay_base::setScale;
1222     // using psd_layer_effects_overlay_base::setAlignWithLayer;
1223 
1224     // using psd_layer_effects_overlay_base::setPattern;
1225 
1226     // using psd_layer_effects_overlay_base::setPatternPhase;
1227     // using psd_layer_effects_overlay_base::patternPhase;
1228 
1229 private:
1230     // These are unused
1231     /*int m_scale;
1232     bool m_alignWithLayer;
1233     KoPatternSP m_pattern;
1234 
1235     int m_horizontalPhase;
1236     int m_verticalPhase;*/
1237 };
1238 
1239 struct psd_layer_effects_stroke : public psd_layer_effects_overlay_base {
1240     psd_layer_effects_stroke()
1241         : m_position(psd_stroke_outside)
1242     {
1243         setFillType(psd_fill_solid_color);
1244         setColor(KoColor::fromXML("<color channeldepth='U8'><sRGB r='0.0' g='0.0' b='0.0'/></color>"));
1245 
1246         setAngle(90);
1247         setReverse(false);
1248         setScale(100);
1249         setAlignWithLayer(true);
1250         setStyle(psd_gradient_style_linear);
1251 
1252         setScale(100);
1253         setAlignWithLayer(true);
1254     }
1255 
1256     /// FIXME: 'using' is not supported by MSVC, so please refactor in
1257     ///        some other way to ensure that the setters are not used
1258     ///        in the classes we don't want
1259 
1260     // using psd_layer_effects_shadow_base::setFillType;
1261     // using psd_layer_effects_shadow_base::setSize;
1262 
1263     // using psd_layer_effects_shadow_base::setColor;
1264 
1265     // using psd_layer_effects_shadow_base::setGradient;
1266     // using psd_layer_effects_shadow_base::setAngle;
1267     // using psd_layer_effects_overlay_base::setReverse;
1268     // using psd_layer_effects_overlay_base::setScale;
1269     // using psd_layer_effects_overlay_base::setAlignWithLayer;
1270     // using psd_layer_effects_overlay_base::setStyle;
1271 
1272     // using psd_layer_effects_overlay_base::setGradientOffset;
1273     // using psd_layer_effects_overlay_base::gradientOffset;
1274 
1275     // using psd_layer_effects_overlay_base::setPattern;
1276 
1277     // using psd_layer_effects_overlay_base::setPatternPhase;
1278     // using psd_layer_effects_overlay_base::patternPhase;
1279 
1280     psd_stroke_position position() const
1281     {
1282         return m_position;
1283     }
1284     void setPosition(psd_stroke_position value)
1285     {
1286         m_position = value;
1287     }
1288 
1289 private:
1290     psd_stroke_position m_position;
1291 };
1292 
1293 /**
1294  * Convert PsdColorMode to pigment colormodelid and colordepthid.
1295  * @see KoColorModelStandardIds
1296  *
1297  * @return a QPair containing ColorModelId and ColorDepthID
1298  */
1299 QPair<QString, QString> KRITAPSDUTILS_EXPORT psd_colormode_to_colormodelid(psd_color_mode colormode, quint16 channelDepth);
1300 
1301 /**
1302  * Convert the Photoshop blend mode strings to Pigment compositeop id's
1303  */
1304 QString KRITAPSDUTILS_EXPORT psd_blendmode_to_composite_op(const QString &blendmode);
1305 QString KRITAPSDUTILS_EXPORT composite_op_to_psd_blendmode(const QString &compositeOp);
1306 
1307 
1308 #if defined(__clang__) && __clang_major__ < 10
1309 inline QDebug &operator<<(QDebug &self, psd_compression_type type)
1310 {
1311     self << static_cast<std::uint16_t>(type);
1312     return self;
1313 };
1314 #endif
1315 
1316 #endif // PSD_H