1 /*
2  *  Copyright (c) 2010 Boudewijn Rempt <boud@valdyas.org>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 /*
19  * Constants and defines taken from gimp and psdparse
20  */
21 #ifndef PSD_H
22 #define PSD_H
23 
24 #include <QPair>
25 #include <QString>
26 #include <QColor>
27 #include <QVector>
28 
29 #include <KoColorModelStandardIds.h>
30 #include <KoCompositeOpRegistry.h>
31 #include <resources/KoAbstractGradient.h>
32 
33 #include "kritapsd_export.h"
34 
35 class KoPattern;
36 
37 const int MAX_CHANNELS = 56;
38 
39 typedef qint32  Fixed;                  /* Represents a fixed point implied decimal */
40 
41 /**
42  * Image color/depth modes
43  */
44 enum psd_color_mode {
45     Bitmap = 0,
46     Grayscale=1,
47     Indexed=2,
48     RGB=3,
49     CMYK=4,
50     MultiChannel=7,
51     DuoTone=8,
52     Lab=9,
53     Gray16,
54     RGB48,
55     Lab48,
56     CMYK64,
57     DeepMultichannel,
58     Duotone16,
59     COLORMODE_UNKNOWN = 9000
60  };
61 
62 
63 /**
64  * Color samplers, apparently distict from PSDColormode
65  */
66 namespace psd_color_sampler {
67 enum PSDColorSamplers {
68     RGB,
69     HSB,
70     CMYK,
71     PANTONE, // LAB
72     FOCOLTONE, // CMYK
73     TRUMATCH, // CMYK
74     TOYO, // LAB
75     LAB,
76     GRAYSCALE,
77     HKS, // CMYK
78     DIC, // LAB
79     TOTAL_INK,
80     MONITOR_RGB,
81     DUOTONE,
82     OPACITY,
83     ANPA      = 3000 // LAB
84 };
85 }
86 
87 // EFFECTS
88 enum psd_gradient_style {
89     psd_gradient_style_linear,				// 'Lnr '
90     psd_gradient_style_radial,				// 'Rdl '
91     psd_gradient_style_angle,				// 'Angl'
92     psd_gradient_style_reflected,			// 'Rflc'
93     psd_gradient_style_diamond				// 'Dmnd'
94 };
95 
96 enum psd_color_stop_type {
97     psd_color_stop_type_foreground_color,	// 'FrgC'
98     psd_color_stop_type_background_Color,	// 'BckC'
99     psd_color_stop_type_user_stop			// 'UsrS'
100 };
101 
102 enum psd_technique_type {
103     psd_technique_softer,
104     psd_technique_precise,
105     psd_technique_slope_limit,
106 };
107 
108 enum psd_stroke_position {
109     psd_stroke_outside,
110     psd_stroke_inside,
111     psd_stroke_center
112 };
113 
114 enum psd_fill_type {
115     psd_fill_solid_color,
116     psd_fill_gradient,
117     psd_fill_pattern,
118 };
119 
120 enum psd_glow_source {
121     psd_glow_center,
122     psd_glow_edge,
123 };
124 
125 enum psd_bevel_style {
126     psd_bevel_outer_bevel,
127     psd_bevel_inner_bevel,
128     psd_bevel_emboss,
129     psd_bevel_pillow_emboss,
130     psd_bevel_stroke_emboss,
131 };
132 
133 enum psd_direction {
134     psd_direction_up,
135     psd_direction_down
136 };
137 
138 enum psd_section_type {
139     psd_other = 0,
140     psd_open_folder,
141     psd_closed_folder,
142     psd_bounding_divider
143 };
144 
145 
146 
147 // GRADIENT MAP
148 // Each color stop
149 struct psd_gradient_color_stop
150 {
151     qint32 location; // Location of color stop
152     qint32 midpoint; // Midpoint of color stop
153     QColor actual_color;
154     psd_color_stop_type color_stop_type;
155 };
156 
157 // Each transparency stop
158 struct psd_gradient_transparency_stop
159 {
160     qint32 location; // Location of transparency stop
161     qint32 midpoint; // Midpoint of transparency stop
162     qint8 opacity; // Opacity of transparency stop
163 };
164 
165 // Gradient settings (Photoshop 6.0)
166 struct psd_layer_gradient_map
167 {
168     bool reverse; // Is gradient reverse
169     bool dithered; // Is gradient dithered
170     qint32 name_length;
171     quint16 *name; // Name of the gradient: Unicode string, padded
172     qint8 number_color_stops; // Number of color stops to follow
173     psd_gradient_color_stop * color_stop;
174     qint8 number_transparency_stops;// Number of transparency stops to follow
175     psd_gradient_transparency_stop * transparency_stop;
176     qint8 expansion_count; // Expansion count ( = 2 for Photoshop 6.0)
177     qint8 interpolation; // Interpolation if length above is non-zero
178     qint8 length; // Length (= 32 for Photoshop 6.0)
179     qint8 mode; // Mode for this gradient
180     qint32 random_number_seed; // Random number seed
181     qint8 showing_transparency_flag;// Flag for showing transparency
182     qint8 using_vector_color_flag;// Flag for using vector color
183     qint32 roughness_factor; // Roughness factor
184     QColor min_color;
185     QColor max_color;
186     QColor lookup_table[256];
187 };
188 
189 
190 struct psd_gradient_color {
191     qint32 smoothness;
192     qint32 name_length;
193     quint16 * name; // Name of the gradient: Unicode string, padded
194     qint8 number_color_stops; // Number of color stops to follow
195     psd_gradient_color_stop * color_stop;
196     qint8 number_transparency_stops;// Number of transparency stops to follow
197     psd_gradient_transparency_stop *transparency_stop;
198 };
199 
200 struct psd_pattern {
201 
202     psd_color_mode color_mode = Bitmap; // The image mode of the file.
203     quint8 height = 0; // Point: vertical, 2 bytes and horizontal, 2 bytes
204     quint8 width = 0;
205     QString name;
206     QString uuid;
207     qint32 version = 0;
208     quint8 top = 0; // Rectangle: top, left, bottom, right
209     quint8 left = 0;
210     quint8 bottom = 0;
211     quint8 right = 0;
212     qint32 max_channel = 0; // Max channels
213     qint32 channel_number = 0;
214     QVector<QRgb> color_table;
215 };
216 
217 struct psd_layer_effects_context {
psd_layer_effects_contextpsd_layer_effects_context218     psd_layer_effects_context()
219         : keep_original(false)
220     {
221     }
222 
223     bool keep_original;
224 };
225 
226 #define PSD_LOOKUP_TABLE_SIZE 256
227 
228 // dsdw, isdw: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_22203
229 class KRITAPSD_EXPORT psd_layer_effects_shadow_base {
230 public:
psd_layer_effects_shadow_base()231     psd_layer_effects_shadow_base()
232         : m_invertsSelection(false)
233         , m_edgeHidden(true)
234         , m_effectEnabled(false)
235         , m_blendMode(COMPOSITE_MULT)
236         , m_color(Qt::black)
237         , m_nativeColor(Qt::black)
238         , m_opacity(75)
239         , m_angle(120)
240         , m_useGlobalLight(true)
241         , m_distance(21)
242         , m_spread(0)
243         , m_size(21)
244         , m_antiAliased(0)
245         , m_noise(0)
246         , m_knocksOut(false)
247         , m_fillType(psd_fill_solid_color)
248         , m_technique(psd_technique_softer)
249         , m_range(100)
250         , m_jitter(0)
251         , m_gradient(0)
252     {
253         for(int i = 0; i < PSD_LOOKUP_TABLE_SIZE; ++i) {
254             m_contourLookupTable[i] = i;
255         }
256     }
257 
258     virtual ~psd_layer_effects_shadow_base();
259 
260     QPoint calculateOffset(const psd_layer_effects_context *context) const;
261 
setEffectEnabled(bool value)262     void setEffectEnabled(bool value) {
263         m_effectEnabled = value;
264     }
265 
effectEnabled()266     bool effectEnabled() const {
267         return m_effectEnabled;
268     }
269 
blendMode()270     QString blendMode() const {
271         return m_blendMode;
272     }
273 
color()274     QColor color() const {
275         return m_color;
276     }
277 
nativeColor()278     QColor nativeColor() const {
279         return m_nativeColor;
280     }
281 
opacity()282     qint32 opacity() const {
283         return m_opacity;
284     }
285 
angle()286     qint32 angle() const {
287         return m_angle;
288     }
289 
useGlobalLight()290     bool useGlobalLight() const {
291         return m_useGlobalLight;
292     }
293 
distance()294     qint32 distance() const {
295         return m_distance;
296     }
297 
spread()298     qint32 spread() const {
299         return m_spread;
300     }
301 
size()302     qint32 size() const {
303         return m_size;
304     }
305 
contourLookupTable()306     const quint8* contourLookupTable() const {
307         return m_contourLookupTable;
308     }
309 
antiAliased()310     bool antiAliased() const {
311         return m_antiAliased;
312     }
313 
noise()314     qint32 noise() const {
315         return m_noise;
316     }
317 
knocksOut()318     bool knocksOut() const {
319         return m_knocksOut;
320     }
321 
invertsSelection()322     bool invertsSelection() const {
323         return m_invertsSelection;
324     }
325 
edgeHidden()326     bool edgeHidden() const {
327         return m_edgeHidden;
328     }
329 
fillType()330     psd_fill_type fillType() const {
331         return m_fillType;
332     }
333 
technique()334     psd_technique_type technique() const {
335         return m_technique;
336     }
337 
range()338     qint32 range() const {
339         return m_range;
340     }
341 
jitter()342     qint32 jitter() const {
343         return m_jitter;
344     }
345 
gradient()346     KoAbstractGradientSP gradient() const {
347         return m_gradient;
348     }
349 
350 public:
351 
setBlendMode(QString value)352     void setBlendMode(QString value) {
353         m_blendMode = value;
354     }
355 
setColor(QColor value)356     void setColor(QColor value) {
357         m_color = value;
358     }
359 
setNativeColor(QColor value)360     void setNativeColor(QColor value) {
361         m_nativeColor = value;
362     }
363 
setOpacity(qint32 value)364     void setOpacity(qint32 value) {
365         m_opacity = value;
366     }
367 
setAngle(qint32 value)368     void setAngle(qint32 value) {
369         m_angle = value;
370     }
371 
setUseGlobalLight(bool value)372     void setUseGlobalLight(bool value) {
373         m_useGlobalLight = value;
374     }
375 
setDistance(qint32 value)376     void setDistance(qint32 value) {
377         m_distance = value;
378     }
379 
setSpread(qint32 value)380     void setSpread(qint32 value) {
381         m_spread = value;
382     }
383 
setSize(qint32 value)384     void setSize(qint32 value) {
385         m_size = value;
386     }
387 
setContourLookupTable(const quint8 * value)388     void setContourLookupTable(const quint8* value) {
389         memcpy(m_contourLookupTable, value, PSD_LOOKUP_TABLE_SIZE * sizeof(quint8));
390     }
391 
setAntiAliased(bool value)392     void setAntiAliased(bool value) {
393         m_antiAliased = value;
394     }
395 
setNoise(qint32 value)396     void setNoise(qint32 value) {
397         m_noise = value;
398     }
399 
setKnocksOut(bool value)400     void setKnocksOut(bool value) {
401         m_knocksOut = value;
402     }
403 
setInvertsSelection(bool value)404     void setInvertsSelection(bool value) {
405         m_invertsSelection = value;
406     }
407 
setEdgeHidden(bool value)408     void setEdgeHidden(bool value) {
409         m_edgeHidden = value;
410     }
411 
setFillType(psd_fill_type value)412     void setFillType(psd_fill_type value) {
413         m_fillType = value;
414     }
415 
setTechnique(psd_technique_type value)416     void setTechnique(psd_technique_type value) {
417         m_technique = value;
418     }
419 
setRange(qint32 value)420     void setRange(qint32 value) {
421         m_range = value;
422     }
423 
setJitter(qint32 value)424     void setJitter(qint32 value) {
425         m_jitter = value;
426     }
427 
setGradient(KoAbstractGradientSP value)428     void setGradient(KoAbstractGradientSP value) {
429         m_gradient = value;
430     }
431 
432     virtual void scaleLinearSizes(qreal scale);
433 
434 private:
435     // internal
436     bool m_invertsSelection;
437     bool m_edgeHidden;
438 
439 private:
440 
441     bool m_effectEnabled; // Effect enabled
442 
443     QString m_blendMode; // already in Krita format!
444     QColor m_color;
445     QColor m_nativeColor;
446     qint32 m_opacity; // Opacity as a percent (0...100)
447     qint32 m_angle; // Angle in degrees
448     bool m_useGlobalLight; // Use this angle in all of the layer effects
449     qint32 m_distance; // Distance in pixels
450     qint32 m_spread; // Intensity as a percent
451     qint32 m_size; // Blur value in pixels
452 
453     quint8 m_contourLookupTable[PSD_LOOKUP_TABLE_SIZE];
454     bool m_antiAliased;
455     qint32 m_noise;
456     bool m_knocksOut;
457 
458     // for Outer/Inner Glow
459     psd_fill_type m_fillType;
460     psd_technique_type m_technique;
461     qint32 m_range;
462     qint32 m_jitter;
463     KoAbstractGradientSP m_gradient;
464 };
465 
466 class KRITAPSD_EXPORT psd_layer_effects_shadow_common : public psd_layer_effects_shadow_base
467 {
468 public:
469     /// FIXME: 'using' is not supported by MSVC, so please refactor in
470     ///        some other way to ensure that the setters are not used
471     ///        in the classes we don't want
472 
473     // using psd_layer_effects_shadow_base::setBlendMode;
474     // using psd_layer_effects_shadow_base::setColor;
475     // using psd_layer_effects_shadow_base::setOpacity;
476     // using psd_layer_effects_shadow_base::setAngle;
477     // using psd_layer_effects_shadow_base::setUseGlobalLight;
478     // using psd_layer_effects_shadow_base::setDistance;
479     // using psd_layer_effects_shadow_base::setSpread;
480     // using psd_layer_effects_shadow_base::setSize;
481     // using psd_layer_effects_shadow_base::setContourLookupTable;
482     // using psd_layer_effects_shadow_base::setAntiAliased;
483     // using psd_layer_effects_shadow_base::setNoise;
484 
485     ~psd_layer_effects_shadow_common() override;
486 };
487 
488 class KRITAPSD_EXPORT psd_layer_effects_drop_shadow : public psd_layer_effects_shadow_common
489 {
490 public:
491     /// FIXME: 'using' is not supported by MSVC, so please refactor in
492     ///        some other way to ensure that the setters are not used
493     ///        in the classes we don't want
494 
495     //using psd_layer_effects_shadow_base::setKnocksOut;
496     ~psd_layer_effects_drop_shadow();
497 };
498 
499 // isdw: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_22203
500 class KRITAPSD_EXPORT psd_layer_effects_inner_shadow : public psd_layer_effects_shadow_common
501 {
502 public:
psd_layer_effects_inner_shadow()503     psd_layer_effects_inner_shadow() {
504         setKnocksOut(false);
505         setInvertsSelection(true);
506         setEdgeHidden(false);
507     }
508 
509     ~psd_layer_effects_inner_shadow() override;
510 };
511 
512 class KRITAPSD_EXPORT psd_layer_effects_glow_common : public psd_layer_effects_shadow_base
513 {
514 public:
psd_layer_effects_glow_common()515     psd_layer_effects_glow_common() {
516         setKnocksOut(true);
517         setDistance(0);
518         setBlendMode(COMPOSITE_LINEAR_DODGE);
519         setColor(Qt::white);
520     }
521     ~psd_layer_effects_glow_common() override;
522     /// FIXME: 'using' is not supported by MSVC, so please refactor in
523     ///        some other way to ensure that the setters are not used
524     ///        in the classes we don't want
525 
526     // using psd_layer_effects_shadow_base::setBlendMode;
527     // using psd_layer_effects_shadow_base::setColor;
528     // using psd_layer_effects_shadow_base::setOpacity;
529 
530     // using psd_layer_effects_shadow_base::setSpread;
531     // using psd_layer_effects_shadow_base::setSize;
532     // using psd_layer_effects_shadow_base::setContourLookupTable;
533     // using psd_layer_effects_shadow_base::setAntiAliased;
534     // using psd_layer_effects_shadow_base::setNoise;
535 
536     // using psd_layer_effects_shadow_base::setFillType;
537     // using psd_layer_effects_shadow_base::setTechnique;
538     // using psd_layer_effects_shadow_base::setRange;
539     // using psd_layer_effects_shadow_base::setJitter;
540     // using psd_layer_effects_shadow_base::setGradient;
541 };
542 
543 // oglw: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_25738
544 class KRITAPSD_EXPORT psd_layer_effects_outer_glow : public psd_layer_effects_glow_common
545 {
546 public:
547     ~psd_layer_effects_outer_glow() override;
548 };
549 
550 // iglw: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_27692
551 class KRITAPSD_EXPORT psd_layer_effects_inner_glow : public psd_layer_effects_glow_common
552 {
553 public:
psd_layer_effects_inner_glow()554     psd_layer_effects_inner_glow()
555         : m_source(psd_glow_edge) {
556         setInvertsSelection(true);
557         setEdgeHidden(false);
558         setKnocksOut(false);
559     }
560 
source()561     psd_glow_source source() const {
562         return m_source;
563     }
setSource(psd_glow_source value)564     void setSource(psd_glow_source value) {
565         m_source = value;
566     }
567     ~psd_layer_effects_inner_glow() override;
568 
569 private:
570     psd_glow_source m_source;
571 };
572 
573 struct psd_layer_effects_satin : public psd_layer_effects_shadow_base
574 {
psd_layer_effects_satinpsd_layer_effects_satin575     psd_layer_effects_satin() {
576         setInvert(false);
577         setUseGlobalLight(false);
578         setDistance(8);
579         setSize(7);
580         setSpread(0);
581         setKnocksOut(true);
582         setEdgeHidden(false);
583         setBlendMode(COMPOSITE_LINEAR_BURN);
584     }
585 
586     /// FIXME: 'using' is not supported by MSVC, so please refactor in
587     ///        some other way to ensure that the setters are not used
588     ///        in the classes we don't want
589 
590     // using psd_layer_effects_shadow_base::setBlendMode;
591     // using psd_layer_effects_shadow_base::setColor;
592     // using psd_layer_effects_shadow_base::setOpacity;
593 
594     // // NOTE: no global light setting explicitly!
595     // using psd_layer_effects_shadow_base::setAngle;
596     // using psd_layer_effects_shadow_base::setDistance;
597 
598     // using psd_layer_effects_shadow_base::setSize;
599 
600     // using psd_layer_effects_shadow_base::setContourLookupTable;
601     // using psd_layer_effects_shadow_base::setAntiAliased;
602 
invertpsd_layer_effects_satin603     bool invert() const {
604         return m_invert;
605     }
606 
setInvertpsd_layer_effects_satin607     void setInvert(bool value) {
608         m_invert = value;
609     }
610 
611 private:
612     bool m_invert;
613 };
614 
615 struct psd_pattern_info {
616     qint32 name_length;
617     quint16 * name;
618     quint8 identifier[256];
619 };
620 
621 // bevl: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_31889
622 struct psd_layer_effects_bevel_emboss : public psd_layer_effects_shadow_base
623 {
psd_layer_effects_bevel_embosspsd_layer_effects_bevel_emboss624     psd_layer_effects_bevel_emboss()
625         : m_style(psd_bevel_inner_bevel),
626           m_technique(psd_technique_softer),
627           m_depth(100),
628           m_direction(psd_direction_up),
629           m_soften(0),
630 
631           m_altitude(30),
632 
633           m_glossAntiAliased(false),
634 
635           m_highlightBlendMode(COMPOSITE_SCREEN),
636           m_highlightColor(Qt::white),
637           m_highlightOpacity(75),
638 
639           m_shadowBlendMode(COMPOSITE_MULT),
640           m_shadowColor(Qt::black),
641           m_shadowOpacity(75),
642 
643           m_contourEnabled(false),
644           m_contourRange(100),
645 
646           m_textureEnabled(false),
647           m_texturePattern(0),
648           m_textureScale(100),
649           m_textureDepth(100),
650           m_textureInvert(false),
651 
652           m_textureAlignWithLayer(true),
653           m_textureHorizontalPhase(0),
654           m_textureVerticalPhase(0)
655     {
656         for(int i = 0; i < PSD_LOOKUP_TABLE_SIZE; ++i) {
657             m_glossContourLookupTable[i] = i;
658         }
659     }
660 
661     /// FIXME: 'using' is not supported by MSVC, so please refactor in
662     ///        some other way to ensure that the setters are not used
663     ///        in the classes we don't want
664 
665     // using psd_layer_effects_shadow_base::setSize;
666 
667     // using psd_layer_effects_shadow_base::setAngle;
668     // using psd_layer_effects_shadow_base::setUseGlobalLight;
669 
670     // using psd_layer_effects_shadow_base::setContourLookupTable;
671     // using psd_layer_effects_shadow_base::setAntiAliased;
672 
stylepsd_layer_effects_bevel_emboss673     psd_bevel_style style() const {
674         return m_style;
675     }
setStylepsd_layer_effects_bevel_emboss676     void setStyle(psd_bevel_style value) {
677         m_style = value;
678     }
679 
techniquepsd_layer_effects_bevel_emboss680     psd_technique_type technique() const {
681         return m_technique;
682     }
setTechniquepsd_layer_effects_bevel_emboss683     void setTechnique(psd_technique_type value) {
684         m_technique = value;
685     }
686 
depthpsd_layer_effects_bevel_emboss687     int depth() const {
688         return m_depth;
689     }
setDepthpsd_layer_effects_bevel_emboss690     void setDepth(int value) {
691         m_depth = value;
692     }
693 
directionpsd_layer_effects_bevel_emboss694     psd_direction direction() const {
695         return m_direction;
696     }
setDirectionpsd_layer_effects_bevel_emboss697     void setDirection(psd_direction value) {
698         m_direction = value;
699     }
700 
softenpsd_layer_effects_bevel_emboss701     int soften() const {
702         return m_soften;
703     }
setSoftenpsd_layer_effects_bevel_emboss704     void setSoften(int value) {
705         m_soften = value;
706     }
707 
708 
altitudepsd_layer_effects_bevel_emboss709     int altitude() const {
710         return m_altitude;
711     }
setAltitudepsd_layer_effects_bevel_emboss712     void setAltitude(int value) {
713         m_altitude = value;
714     }
715 
716 
glossContourLookupTablepsd_layer_effects_bevel_emboss717     const quint8* glossContourLookupTable() const {
718         return m_glossContourLookupTable;
719     }
720 
setGlossContourLookupTablepsd_layer_effects_bevel_emboss721     void setGlossContourLookupTable(const quint8 *value) {
722         memcpy(m_glossContourLookupTable, value, PSD_LOOKUP_TABLE_SIZE * sizeof(quint8));
723     }
724 
glossAntiAliasedpsd_layer_effects_bevel_emboss725     bool glossAntiAliased() const {
726         return m_glossAntiAliased;
727     }
setGlossAntiAliasedpsd_layer_effects_bevel_emboss728     void setGlossAntiAliased(bool value) {
729         m_glossAntiAliased = value;
730     }
731 
732 
highlightBlendModepsd_layer_effects_bevel_emboss733     QString highlightBlendMode() const {
734         return m_highlightBlendMode;
735     }
setHighlightBlendModepsd_layer_effects_bevel_emboss736     void setHighlightBlendMode(QString value) {
737         m_highlightBlendMode = value;
738     }
739 
highlightColorpsd_layer_effects_bevel_emboss740     QColor highlightColor() const {
741         return m_highlightColor;
742     }
setHighlightColorpsd_layer_effects_bevel_emboss743     void setHighlightColor(QColor value) {
744         m_highlightColor = value;
745     }
746 
highlightOpacitypsd_layer_effects_bevel_emboss747     qint32 highlightOpacity() const {
748         return m_highlightOpacity;
749     }
setHighlightOpacitypsd_layer_effects_bevel_emboss750     void setHighlightOpacity(qint32 value) {
751         m_highlightOpacity = value;
752     }
753 
754 
shadowBlendModepsd_layer_effects_bevel_emboss755     QString shadowBlendMode() const {
756         return m_shadowBlendMode;
757     }
setShadowBlendModepsd_layer_effects_bevel_emboss758     void setShadowBlendMode(QString value) {
759         m_shadowBlendMode = value;
760     }
761 
shadowColorpsd_layer_effects_bevel_emboss762     QColor shadowColor() const {
763         return m_shadowColor;
764     }
setShadowColorpsd_layer_effects_bevel_emboss765     void setShadowColor(QColor value) {
766         m_shadowColor = value;
767     }
768 
shadowOpacitypsd_layer_effects_bevel_emboss769     qint32 shadowOpacity() const {
770         return m_shadowOpacity;
771     }
setShadowOpacitypsd_layer_effects_bevel_emboss772     void setShadowOpacity(qint32 value) {
773         m_shadowOpacity = value;
774     }
775 
776 
contourEnabledpsd_layer_effects_bevel_emboss777     bool contourEnabled() const {
778         return m_contourEnabled;
779     }
setContourEnabledpsd_layer_effects_bevel_emboss780     void setContourEnabled(bool value) {
781         m_contourEnabled = value;
782     }
783 
contourRangepsd_layer_effects_bevel_emboss784     int contourRange() const {
785         return m_contourRange;
786     }
setContourRangepsd_layer_effects_bevel_emboss787     void setContourRange(int value) {
788         m_contourRange = value;
789     }
790 
791 
textureEnabledpsd_layer_effects_bevel_emboss792     bool textureEnabled() const {
793         return m_textureEnabled;
794     }
setTextureEnabledpsd_layer_effects_bevel_emboss795     void setTextureEnabled(bool value) {
796         m_textureEnabled = value;
797     }
798 
texturePatternpsd_layer_effects_bevel_emboss799     KoPattern* texturePattern() const {
800         return m_texturePattern;
801     }
setTexturePatternpsd_layer_effects_bevel_emboss802     void setTexturePattern(KoPattern *value) {
803         m_texturePattern = value;
804     }
805 
textureScalepsd_layer_effects_bevel_emboss806     int textureScale() const {
807         return m_textureScale;
808     }
setTextureScalepsd_layer_effects_bevel_emboss809     void setTextureScale(int value) {
810         m_textureScale = value;
811     }
812 
textureDepthpsd_layer_effects_bevel_emboss813     int textureDepth() const {
814         return m_textureDepth;
815     }
setTextureDepthpsd_layer_effects_bevel_emboss816     void setTextureDepth(int value) {
817         m_textureDepth = value;
818     }
819 
textureInvertpsd_layer_effects_bevel_emboss820     bool textureInvert() const {
821         return m_textureInvert;
822     }
setTextureInvertpsd_layer_effects_bevel_emboss823     void setTextureInvert(bool value) {
824         m_textureInvert = value;
825     }
826 
827 
textureAlignWithLayerpsd_layer_effects_bevel_emboss828     bool textureAlignWithLayer() const {
829         return m_textureAlignWithLayer;
830     }
setTextureAlignWithLayerpsd_layer_effects_bevel_emboss831     void setTextureAlignWithLayer(bool value) {
832         m_textureAlignWithLayer = value;
833     }
834 
setTexturePhasepsd_layer_effects_bevel_emboss835     void setTexturePhase(const QPointF &phase) {
836         m_textureHorizontalPhase = phase.x();
837         m_textureVerticalPhase = phase.y();
838     }
839 
texturePhasepsd_layer_effects_bevel_emboss840     QPointF texturePhase() const {
841         return QPointF(m_textureHorizontalPhase, m_textureVerticalPhase);
842     }
843 
textureHorizontalPhasepsd_layer_effects_bevel_emboss844     int textureHorizontalPhase() const {
845         return m_textureHorizontalPhase;
846     }
setTextureHorizontalPhasepsd_layer_effects_bevel_emboss847     void setTextureHorizontalPhase(int value) {
848         m_textureHorizontalPhase = value;
849     }
850 
textureVerticalPhasepsd_layer_effects_bevel_emboss851     int textureVerticalPhase() const {
852         return m_textureVerticalPhase;
853     }
setTextureVerticalPhasepsd_layer_effects_bevel_emboss854     void setTextureVerticalPhase(int value) {
855         m_textureVerticalPhase = value;
856     }
857 
scaleLinearSizespsd_layer_effects_bevel_emboss858     void scaleLinearSizes(qreal scale) override {
859         psd_layer_effects_shadow_base::scaleLinearSizes(scale);
860         m_soften *= scale;
861         m_textureScale *= scale;
862     }
863 
864 private:
865     psd_bevel_style m_style;
866     psd_technique_type m_technique;
867     int m_depth;
868     psd_direction m_direction; // Up or down
869     int m_soften; // Blur value in pixels.
870 
871     int m_altitude;
872 
873     quint8 m_glossContourLookupTable[256];
874     bool m_glossAntiAliased;
875 
876     QString m_highlightBlendMode; // already in Krita format
877     QColor m_highlightColor;
878     qint32 m_highlightOpacity; // Highlight opacity as a percent
879 
880     QString m_shadowBlendMode; // already in Krita format
881     QColor m_shadowColor;
882     qint32 m_shadowOpacity; // Shadow opacity as a percent
883 
884     bool m_contourEnabled;
885     int m_contourRange;
886 
887     bool m_textureEnabled;
888     KoPattern *m_texturePattern;
889     int m_textureScale;
890     int m_textureDepth;
891     bool m_textureInvert;
892 
893     bool m_textureAlignWithLayer;
894     int m_textureHorizontalPhase; // 0..100%
895     int m_textureVerticalPhase; // 0..100%
896 };
897 
898 struct psd_layer_effects_overlay_base : public psd_layer_effects_shadow_base
899 {
psd_layer_effects_overlay_basepsd_layer_effects_overlay_base900     psd_layer_effects_overlay_base()
901         : m_scale(100),
902           m_alignWithLayer(true),
903           m_reverse(false),
904           m_style(psd_gradient_style_linear),
905           m_gradientXOffset(0),
906           m_gradientYOffset(0),
907           m_pattern(0),
908           m_horizontalPhase(0),
909           m_verticalPhase(0)
910     {
911         setUseGlobalLight(false);
912     }
913 
914     /// FIXME: 'using' is not supported by MSVC, so please refactor in
915     ///        some other way to ensure that the setters are not used
916     ///        in the classes we don't want
917 
918     // using psd_layer_effects_shadow_base::setBlendMode;
919     // using psd_layer_effects_shadow_base::setOpacity;
920 
scalepsd_layer_effects_overlay_base921     int scale() const {
922         return m_scale;
923     }
924 
alignWithLayerpsd_layer_effects_overlay_base925     bool alignWithLayer() const {
926         return m_alignWithLayer;
927     }
928 
reversepsd_layer_effects_overlay_base929     bool reverse() const {
930         return m_reverse;
931     }
932 
stylepsd_layer_effects_overlay_base933     psd_gradient_style style() const {
934         return m_style;
935     }
936 
gradientXOffsetpsd_layer_effects_overlay_base937     int gradientXOffset() const {
938         return m_gradientXOffset;
939     }
940 
gradientYOffsetpsd_layer_effects_overlay_base941     int gradientYOffset() const {
942         return m_gradientYOffset;
943     }
944 
patternpsd_layer_effects_overlay_base945     KoPattern* pattern() const {
946         return m_pattern;
947     }
948 
horizontalPhasepsd_layer_effects_overlay_base949     int horizontalPhase() const {
950         return m_horizontalPhase;
951     }
952 
verticalPhasepsd_layer_effects_overlay_base953     int verticalPhase() const {
954         return m_verticalPhase;
955     }
956 
957 // refactor that
958 public:
959 
setScalepsd_layer_effects_overlay_base960     void setScale(int value) {
961         m_scale = value;
962     }
963 
setAlignWithLayerpsd_layer_effects_overlay_base964     void setAlignWithLayer(bool value) {
965         m_alignWithLayer = value;
966     }
967 
setReversepsd_layer_effects_overlay_base968     void setReverse(bool value) {
969         m_reverse = value;
970     }
971 
setStylepsd_layer_effects_overlay_base972     void setStyle(psd_gradient_style value) {
973         m_style = value;
974     }
975 
setGradientOffsetpsd_layer_effects_overlay_base976     void setGradientOffset(const QPointF &pt) {
977         m_gradientXOffset = qRound(pt.x());
978         m_gradientYOffset = qRound(pt.y());
979     }
980 
gradientOffsetpsd_layer_effects_overlay_base981     QPointF gradientOffset() const {
982         return QPointF(m_gradientXOffset, m_gradientYOffset);
983     }
984 
setPatternpsd_layer_effects_overlay_base985     void setPattern(KoPattern *value) {
986         m_pattern = value;
987     }
988 
setPatternPhasepsd_layer_effects_overlay_base989     void setPatternPhase(const QPointF &phase) {
990         m_horizontalPhase = phase.x();
991         m_verticalPhase = phase.y();
992     }
993 
patternPhasepsd_layer_effects_overlay_base994     QPointF patternPhase() const {
995         return QPointF(m_horizontalPhase, m_verticalPhase);
996     }
997 
scaleLinearSizespsd_layer_effects_overlay_base998     void scaleLinearSizes(qreal scale) override {
999         psd_layer_effects_shadow_base::scaleLinearSizes(scale);
1000         m_scale *= scale;
1001     }
1002 
1003 private:
1004 
1005     // Gradient+Pattern
1006     int m_scale;
1007     bool m_alignWithLayer;
1008 
1009     // Gradient
1010     bool m_reverse;
1011     psd_gradient_style m_style;
1012     int m_gradientXOffset; // 0..100%
1013     int m_gradientYOffset; // 0..100%
1014 
1015     // Pattern
1016     KoPattern *m_pattern;
1017     int m_horizontalPhase; // 0..100%
1018     int m_verticalPhase; // 0..100%
1019 
1020 protected:
1021     /// FIXME: 'using' is not supported by MSVC, so please refactor in
1022     ///        some other way to ensure that the setters are not used
1023     ///        in the classes we don't want
1024 
1025     // must be called in the derived classes' c-tor
1026     // using psd_layer_effects_shadow_base::setFillType;
1027 };
1028 
1029 // sofi: https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_70055
1030 struct psd_layer_effects_color_overlay : public psd_layer_effects_overlay_base
1031 {
psd_layer_effects_color_overlaypsd_layer_effects_color_overlay1032     psd_layer_effects_color_overlay() {
1033         setFillType(psd_fill_solid_color);
1034         setColor(Qt::white);
1035 
1036     }
1037 
1038     /// FIXME: 'using' is not supported by MSVC, so please refactor in
1039     ///        some other way to ensure that the setters are not used
1040     ///        in the classes we don't want
1041 
1042     // using psd_layer_effects_shadow_base::setColor;
1043 };
1044 
1045 struct psd_layer_effects_gradient_overlay : public psd_layer_effects_overlay_base
1046 {
psd_layer_effects_gradient_overlaypsd_layer_effects_gradient_overlay1047     psd_layer_effects_gradient_overlay()
1048     {
1049         setFillType(psd_fill_gradient);
1050         setAngle(90);
1051         setReverse(false);
1052         setScale(100);
1053         setAlignWithLayer(true);
1054         setStyle(psd_gradient_style_linear);
1055 
1056     }
1057 public:
1058     /// FIXME: 'using' is not supported by MSVC, so please refactor in
1059     ///        some other way to ensure that the setters are not used
1060     ///        in the classes we don't want
1061 
1062     // using psd_layer_effects_shadow_base::setGradient;
1063     // using psd_layer_effects_shadow_base::setAngle;
1064 
1065     // using psd_layer_effects_overlay_base::setReverse;
1066     // using psd_layer_effects_overlay_base::setScale;
1067     // using psd_layer_effects_overlay_base::setAlignWithLayer;
1068     // using psd_layer_effects_overlay_base::setStyle;
1069 
1070     // using psd_layer_effects_overlay_base::setGradientOffset;
1071     // using psd_layer_effects_overlay_base::gradientOffset;
1072 };
1073 
1074 struct psd_layer_effects_pattern_overlay : public psd_layer_effects_overlay_base
1075 {
psd_layer_effects_pattern_overlaypsd_layer_effects_pattern_overlay1076     psd_layer_effects_pattern_overlay()
1077     {
1078         setFillType(psd_fill_pattern);
1079         setScale(100);
1080         setAlignWithLayer(true);
1081     }
1082 
1083     /// FIXME: 'using' is not supported by MSVC, so please refactor in
1084     ///        some other way to ensure that the setters are not used
1085     ///        in the classes we don't want
1086 
1087     // using psd_layer_effects_overlay_base::setScale;
1088     // using psd_layer_effects_overlay_base::setAlignWithLayer;
1089 
1090     // using psd_layer_effects_overlay_base::setPattern;
1091 
1092     // using psd_layer_effects_overlay_base::setPatternPhase;
1093     // using psd_layer_effects_overlay_base::patternPhase;
1094 
1095 private:
1096     // These are unused
1097     /*int m_scale;
1098     bool m_alignWithLayer;
1099     KoPattern *m_pattern;
1100 
1101     int m_horizontalPhase;
1102     int m_verticalPhase;*/
1103 };
1104 
1105 struct psd_layer_effects_stroke : public psd_layer_effects_overlay_base
1106 {
psd_layer_effects_strokepsd_layer_effects_stroke1107     psd_layer_effects_stroke()
1108         : m_position(psd_stroke_outside)
1109     {
1110         setFillType(psd_fill_solid_color);
1111         setColor(Qt::black);
1112 
1113         setAngle(90);
1114         setReverse(false);
1115         setScale(100);
1116         setAlignWithLayer(true);
1117         setStyle(psd_gradient_style_linear);
1118 
1119         setScale(100);
1120         setAlignWithLayer(true);
1121     }
1122 
1123     /// FIXME: 'using' is not supported by MSVC, so please refactor in
1124     ///        some other way to ensure that the setters are not used
1125     ///        in the classes we don't want
1126 
1127     // using psd_layer_effects_shadow_base::setFillType;
1128     // using psd_layer_effects_shadow_base::setSize;
1129 
1130     // using psd_layer_effects_shadow_base::setColor;
1131 
1132     // using psd_layer_effects_shadow_base::setGradient;
1133     // using psd_layer_effects_shadow_base::setAngle;
1134     // using psd_layer_effects_overlay_base::setReverse;
1135     // using psd_layer_effects_overlay_base::setScale;
1136     // using psd_layer_effects_overlay_base::setAlignWithLayer;
1137     // using psd_layer_effects_overlay_base::setStyle;
1138 
1139     // using psd_layer_effects_overlay_base::setGradientOffset;
1140     // using psd_layer_effects_overlay_base::gradientOffset;
1141 
1142     // using psd_layer_effects_overlay_base::setPattern;
1143 
1144     // using psd_layer_effects_overlay_base::setPatternPhase;
1145     // using psd_layer_effects_overlay_base::patternPhase;
1146 
positionpsd_layer_effects_stroke1147     psd_stroke_position position() const {
1148         return m_position;
1149     }
setPositionpsd_layer_effects_stroke1150     void setPosition(psd_stroke_position value) {
1151         m_position = value;
1152     }
1153 
1154 private:
1155     psd_stroke_position m_position;
1156 };
1157 
1158 /**
1159  * Convert PsdColorMode to pigment colormodelid and colordepthid.
1160  * @see KoColorModelStandardIds
1161  *
1162  * @return a QPair containing ColorModelId and ColorDepthID
1163  */
1164 QPair<QString, QString> KRITAPSD_EXPORT psd_colormode_to_colormodelid(psd_color_mode colormode, quint16 channelDepth);
1165 
1166 
1167 /**
1168  * Convert the Photoshop blend mode strings to Pigment compositeop id's
1169  */
1170 QString KRITAPSD_EXPORT psd_blendmode_to_composite_op(const QString& blendmode);
1171 QString KRITAPSD_EXPORT composite_op_to_psd_blendmode(const QString& compositeOp);
1172 
1173 #endif // PSD_H
1174