Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_open_raster_stack_load_visitor.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2007, 2009 Cyrille Berger <cberger@cberger.net>
3 * SPDX-FileCopyrightText: 2023 Carsten Hartenfels <carsten.hartenfels@pm.me>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
9
10#include <QDomElement>
11#include <QDomNode>
12
14
15// Includes from krita/image
17#include <filter/kis_filter.h>
19#include <kis_group_layer.h>
20#include <kis_image.h>
24
25#include <kis_dom_utils.h>
26#include <kis_paint_layer.h>
27#include <kis_selection.h>
28
29
30#include "KisDocument.h"
31
33
42
49
54
59
64
66{
67
68 QDomDocument doc = d->loadContext->loadStack();
69
70
71 for (QDomNode node = doc.firstChild(); !node.isNull(); node = node.nextSibling()) {
72 if (node.isElement() && node.nodeName() == "image") { // it's the image root
73 QDomElement subelem = node.toElement();
74
75 int width = 0;
76 if (!subelem.attribute("w").isNull()) {
77 width = subelem.attribute("w").toInt();
78 }
79
80 int height = 0;
81 if (!subelem.attribute("h").isNull()) {
82 height = subelem.attribute("h").toInt();
83 }
84
85 d->xRes = 75.0/72; // Setting the default value of the X Resolution = 75ppi
86 if (!subelem.attribute("xres").isNull()){
87 d->xRes = (KisDomUtils::toDouble(subelem.attribute("xres")) / 72);
88 }
89
90 d->yRes = 75.0/72;
91 if (!subelem.attribute("yres").isNull()){
92 d->yRes = (KisDomUtils::toDouble(subelem.attribute("yres")) / 72);
93 }
94
95 dbgFile << ppVar(width) << ppVar(height);
96 d->image = new KisImage(d->undoStore, width, height, KoColorSpaceRegistry::instance()->rgb8(), "OpenRaster Image (name)");
97 for (QDomNode node2 = node.firstChild(); !node2.isNull(); node2 = node2.nextSibling()) {
98 if (node2.isElement() && node2.nodeName() == "stack") { // it's the root layer !
99 QDomElement subelem2 = node2.toElement();
100 loadGroupLayer(subelem2, d->image->rootLayer());
101 break;
102 }
103 }
104 }
105 }
106}
107
109{
110 layer->setName(elem.attribute("name"));
111 layer->setX(elem.attribute("x").toInt());
112 layer->setY(elem.attribute("y").toInt());
113 if (elem.attribute("visibility") == "hidden") {
114 layer->setVisible(false);
115 } else {
116 layer->setVisible(true);
117 }
118 if (elem.hasAttribute("edit-locked")) {
119 layer->setUserLocked(elem.attribute("edit-locked") == "true");
120 }
121 if (elem.hasAttribute("selected") && elem.attribute("selected") == "true") {
122 d->activeNodes.append(layer);
123 }
124
125 QString compop = elem.attribute("composite-op");
126 if (compop.startsWith("svg:")) {
127 //we don't have a 'composite op clear' despite the registry reserving a string for it, doesn't matter, ora doesn't use it.
128 //if (compop == "svg:clear") layer->setCompositeOpId(COMPOSITE_CLEAR);
129 if (compop == "svg:src-over") layer->setCompositeOpId(COMPOSITE_OVER);
130 //not part of the spec.
131 //if (compop == "svg:dst-over") layer->setCompositeOpId(COMPOSITE_BEHIND);
132 //dst-in "The source that overlaps the destination, replaces the destination."
133 if (compop == "svg:dst-in") layer->setCompositeOpId(COMPOSITE_DESTINATION_IN);
134 //dst-out "dst is placed, where it falls outside of the source."
135 if (compop == "svg:dst-out") layer->setCompositeOpId(COMPOSITE_ERASE);
136 //src-atop "Destination which overlaps the source replaces the source. Source is placed elsewhere."
137 //this is basically our alpha-inherit.
138 if (compop == "svg:src-atop") layer->disableAlphaChannel(true);
139 //dst-atop
140 if (compop == "svg:dst-atop") layer->setCompositeOpId(COMPOSITE_DESTINATION_ATOP);
141 //plus is svg standard's way of saying addition... photoshop calls this linear dodge, btw, maybe make a similar alias?
142 if (compop == "svg:plus") layer->setCompositeOpId(COMPOSITE_ADD);
143 if (compop == "svg:multiply") layer->setCompositeOpId(COMPOSITE_MULT);
144 if (compop == "svg:screen") layer->setCompositeOpId(COMPOSITE_SCREEN);
145 if (compop == "svg:overlay") layer->setCompositeOpId(COMPOSITE_OVERLAY);
146 if (compop == "svg:darken") layer->setCompositeOpId(COMPOSITE_DARKEN);
147 if (compop == "svg:lighten") layer->setCompositeOpId(COMPOSITE_LIGHTEN);
148 if (compop == "svg:color-dodge") layer->setCompositeOpId(COMPOSITE_DODGE);
149 if (compop == "svg:color-burn") layer->setCompositeOpId(COMPOSITE_BURN);
150 if (compop == "svg:hard-light") layer->setCompositeOpId(COMPOSITE_HARD_LIGHT);
151 if (compop == "svg:soft-light") layer->setCompositeOpId(COMPOSITE_SOFT_LIGHT_SVG);
152 if (compop == "svg:difference") layer->setCompositeOpId(COMPOSITE_DIFF);
153 if (compop == "svg:color") layer->setCompositeOpId(COMPOSITE_COLOR);
154 if (compop == "svg:luminosity") layer->setCompositeOpId(COMPOSITE_LUMINIZE);
155 if (compop == "svg:hue") layer->setCompositeOpId(COMPOSITE_HUE);
156 if (compop == "svg:saturation") layer->setCompositeOpId(COMPOSITE_SATURATION);
157 //Exclusion isn't in the official list.
158 //if (compop == "svg:exclusion") layer->setCompositeOpId(COMPOSITE_EXCLUSION);
159 }
160 else if (compop.startsWith("krita:")) {
161 compop = compop.remove(0, 6);
162 layer->setCompositeOpId(compop);
163 }
164 else {
165 // to fix old bugs in krita's ora export
166 if (compop == "color-dodge") layer->setCompositeOpId(COMPOSITE_DODGE);
167 if (compop == "difference") layer->setCompositeOpId(COMPOSITE_DIFF);
168 if (compop == "svg:add") layer->setCompositeOpId(COMPOSITE_ADD);
169 }
170
171 if (elem.hasAttribute("alpha-preserve") && elem.attribute("alpha-preserve") == "true") {
172 layer->disableAlphaChannel(true);
173 }
174}
175
177{
178 loadLayerInfo(elem, aL);
179}
180
182{
183 loadLayerInfo(elem, pL);
184
185 dbgFile << "Loading was unsuccessful";
186}
187
188void KisOpenRasterStackLoadVisitor::loadGroupLayer(const QDomElement& elem, KisGroupLayerSP groupLayer)
189{
190 dbgFile << "Loading group layer" << d->image;
191 loadLayerInfo(elem, groupLayer);
192 for (QDomNode node = elem.firstChild(); !node.isNull(); node = node.nextSibling()) {
193 if (node.isElement()) {
194 QDomElement subelem = node.toElement();
195 if (node.nodeName() == "stack") {
196 double opacity = 1.0;
197 if (!subelem.attribute("opacity").isNull()) {
198 opacity = KisDomUtils::toDouble(subelem.attribute("opacity", "1.0"));
199 }
200 KisGroupLayerSP layer = new KisGroupLayer(d->image, "", opacity * 255);
201 bool passThrough = false;
202 if (subelem.attribute("isolation")=="auto") {
203 passThrough = true;
204 }
205 layer->setPassThroughMode(passThrough);
206 d->image->addNode(layer, groupLayer.data(), 0);
207 loadGroupLayer(subelem, layer);
208 } else if (node.nodeName() == "layer") {
209 QString filename = subelem.attribute("src");
210 if (!filename.isNull()) {
211 const qreal opacity = KisDomUtils::toDouble(subelem.attribute("opacity", "1.0"));
212 KisImageSP pngImage = d->loadContext->loadDeviceData(filename);
213 if (pngImage) {
214 // If ORA doesn't have resolution info, load the default value(75 ppi) else fetch from stack.xml
216 // now get the device
217 KisPaintDeviceSP device = new KisPaintDevice(*pngImage->projection());
218
219 KisPaintLayerSP layer = new KisPaintLayer(groupLayer->image() , "", opacity * 255, device);
220 d->image->addNode(layer, groupLayer, 0);
221 loadPaintLayer(subelem, layer);
222 dbgFile << "Loading was successful";
223 }
224 }
225 } else if (node.nodeName() == "filter") {
226
227 QString filterType = subelem.attribute("type");
228 QStringList filterTypeSplit = filterType.split(':');
229 KisFilterSP f = 0;
230 if (filterTypeSplit[0] == "applications" && filterTypeSplit[1] == "krita") {
231 f = KisFilterRegistry::instance()->value(filterTypeSplit[2]);
232 }
234 kfc->createLocalResourcesSnapshot();
235 KisAdjustmentLayerSP layer = new KisAdjustmentLayer(groupLayer->image() , "", kfc, KisSelectionSP(0));
236 d->image->addNode(layer.data(), groupLayer.data(), 0);
237 loadAdjustmentLayer(subelem, layer);
238
239 } else {
240 dbgFile << "Unknown element : " << node.nodeName();
241 }
242 }
243 }
244
245}
const QString COMPOSITE_OVER
const QString COMPOSITE_DARKEN
const QString COMPOSITE_OVERLAY
const QString COMPOSITE_DODGE
const QString COMPOSITE_SOFT_LIGHT_SVG
const QString COMPOSITE_ADD
const QString COMPOSITE_LIGHTEN
const QString COMPOSITE_MULT
const QString COMPOSITE_SATURATION
const QString COMPOSITE_DESTINATION_ATOP
const QString COMPOSITE_HARD_LIGHT
const QString COMPOSITE_SCREEN
const QString COMPOSITE_DIFF
const QString COMPOSITE_ERASE
const QString COMPOSITE_HUE
const QString COMPOSITE_BURN
const QString COMPOSITE_COLOR
const QString COMPOSITE_DESTINATION_IN
const QString COMPOSITE_LUMINIZE
static KisFilterRegistry * instance()
static KisResourcesInterfaceSP instance()
KisGroupLayerSP rootLayer() const
KisPaintDeviceSP projection() const
void setResolution(double xres, double yres)
KisImageSP loadDeviceData(const QString &fileName)
void loadPaintLayer(const QDomElement &elem, KisPaintLayerSP pL)
void loadAdjustmentLayer(const QDomElement &elem, KisAdjustmentLayerSP pL)
KisOpenRasterStackLoadVisitor(KisUndoStore *undoStore, KisOpenRasterLoadContext *orlc)
void loadGroupLayer(const QDomElement &elem, KisGroupLayerSP groupLayer)
void loadLayerInfo(const QDomElement &elem, KisLayerSP layer)
const T value(const QString &id) const
#define ppVar(var)
Definition kis_debug.h:155
#define dbgFile
Definition kis_debug.h:53
double toDouble(const QString &str, bool *ok=nullptr)
virtual void setUserLocked(bool l)
virtual void setVisible(bool visible, bool loading=false)
void setName(const QString &name)
KisImageWSP image
void setCompositeOpId(const QString &compositeOpId)
void setPassThroughMode(bool value)
void disableAlphaChannel(bool disable)
Definition kis_layer.cc:319
void setX(qint32 x) override
Definition kis_layer.cc:983
void setY(qint32 y) override
Definition kis_layer.cc:989
bool addNode(KisNodeSP node, KisNodeSP parent=KisNodeSP(), KisNodeAdditionFlags flags=KisNodeAdditionFlag::None)
static KoColorSpaceRegistry * instance()
const KoColorSpace * rgb8(const QString &profileName=QString())