Krita Source Code Documentation
Loading...
Searching...
No Matches
PSDLoader Class Reference

#include <psd_loader.h>

+ Inheritance diagram for PSDLoader:

Public Slots

virtual void cancel ()
 

Public Member Functions

KisImportExportErrorCode buildImage (QIODevice &io)
 
KisImageSP image ()
 
 PSDLoader (KisDocument *doc, KisImportUserFeedbackInterface *feedbackInterface)
 
 ~PSDLoader () override
 

Private Member Functions

KisImportExportErrorCode decode (QIODevice &io)
 

Private Attributes

KisDocument * m_doc
 
KisImportUserFeedbackInterface * m_feedbackInterface {nullptr}
 
KisImageSP m_image
 
bool m_stop
 

Detailed Description

Definition at line 19 of file psd_loader.h.

Constructor & Destructor Documentation

◆ PSDLoader()

PSDLoader::PSDLoader ( KisDocument * doc,
KisImportUserFeedbackInterface * feedbackInterface )

Definition at line 62 of file psd_loader.cpp.

63 : m_image(0)
64 , m_doc(doc)
65 , m_stop(false)
66 , m_feedbackInterface(feedbackInterface)
67{
68}
KisDocument * m_doc
Definition psd_loader.h:42
KisImageSP m_image
Definition psd_loader.h:41
bool m_stop
Definition psd_loader.h:43
KisImportUserFeedbackInterface * m_feedbackInterface
Definition psd_loader.h:44

◆ ~PSDLoader()

PSDLoader::~PSDLoader ( )
override

Definition at line 70 of file psd_loader.cpp.

71{
72}

Member Function Documentation

◆ buildImage()

KisImportExportErrorCode PSDLoader::buildImage ( QIODevice & io)

Definition at line 665 of file psd_loader.cpp.

666{
667 return decode(io);
668}
KisImportExportErrorCode decode(QIODevice &io)

References decode().

◆ cancel

void PSDLoader::cancel ( )
virtualslot

Definition at line 676 of file psd_loader.cpp.

677{
678 m_stop = true;
679}

References m_stop.

◆ decode()

KisImportExportErrorCode PSDLoader::decode ( QIODevice & io)
private

PSD has a weird "optimization": if a group layer has only one child layer, it omits it's 'psd_bounding_divider' section. So fi you ever see an unbalanced layers group in PSD, most probably, it is just a single layered group.

In some files saved by PS CS6 the group layer sections seem to be unbalanced. I don't know why it happens because the reporter didn't provide us an example file. So here we just check if the new layer was created, and if not, skip the initialization of masks.

See bug: 357559

Definition at line 74 of file psd_loader.cpp.

75{
76 // open the file
77
78 dbgFile << "pos:" << io.pos();
79
80 PSDHeader header;
81 if (!header.read(io)) {
82 dbgFile << "failed reading header: " << header.error;
84 }
85
86 dbgFile << header;
87 dbgFile << "Read header. pos:" << io.pos();
88
89 PSDColorModeBlock colorModeBlock(header.colormode);
90 if (!colorModeBlock.read(io)) {
91 dbgFile << "failed reading colormode block: " << colorModeBlock.error;
93 }
94
95 dbgFile << "Read color mode block. pos:" << io.pos();
96
97 PSDImageResourceSection resourceSection;
98 if (!resourceSection.read(io)) {
99 dbgFile << "failed image reading resource section: " << resourceSection.error;
101 }
102 dbgFile << "Read image resource section. pos:" << io.pos();
103
104 PSDLayerMaskSection layerSection(header);
105 if (!layerSection.read(io)) {
106 dbgFile << "failed reading layer/mask section: " << layerSection.error;
108 }
109 dbgFile << "Read layer/mask section. " << layerSection.nLayers << "layers. pos:" << io.pos();
110
111 // Done reading, except possibly for the image data block, which is only relevant if there
112 // are no layers.
113
114 // Get the right colorspace
115 QPair<QString, QString> colorSpaceId = psd_colormode_to_colormodelid(header.colormode,
116 header.channelDepth);
117 if (colorSpaceId.first.isNull()) {
118 dbgFile << "Unsupported colorspace" << header.colormode << header.channelDepth;
120 }
121
122 // Get the icc profile from the image resource section
123 const KoColorProfile* profile = 0;
124 if (resourceSection.resources.contains(PSDImageResourceSection::ICC_PROFILE)) {
125 ICC_PROFILE_1039 *iccProfileData = dynamic_cast<ICC_PROFILE_1039*>(resourceSection.resources[PSDImageResourceSection::ICC_PROFILE]->resource);
126 if (iccProfileData ) {
127 profile = KoColorSpaceRegistry::instance()->createColorProfile(colorSpaceId.first,
128 colorSpaceId.second,
129 iccProfileData->icc);
130 dbgFile << "Loaded ICC profile" << profile->name();
131 delete resourceSection.resources.take(PSDImageResourceSection::ICC_PROFILE);
132 }
133 }
134
135 // Create the colorspace
136 const KoColorSpace* cs = KoColorSpaceRegistry::instance()->colorSpace(colorSpaceId.first, colorSpaceId.second, profile);
137 if (!cs) {
139 }
140
141 // Creating the KisImage
142 QFile *file = dynamic_cast<QFile *>(&io);
143 QString name = file ? file->fileName() : "Imported";
144 m_image = new KisImage(m_doc->createUndoStore(), header.width, header.height, cs, name);
145 Q_CHECK_PTR(m_image);
146
147 KisImageBarrierLock lock(m_image);
148
149 // set the correct resolution
150 if (resourceSection.resources.contains(PSDImageResourceSection::RESN_INFO)) {
151 RESN_INFO_1005 *resInfo = dynamic_cast<RESN_INFO_1005*>(resourceSection.resources[PSDImageResourceSection::RESN_INFO]->resource);
152 if (resInfo) {
153 // check resolution size is not zero
154 if (resInfo->hRes * resInfo->vRes > 0)
156 // let's skip the unit for now; we can only set that on the KisDocument, and krita doesn't use it.
157 delete resourceSection.resources.take(PSDImageResourceSection::RESN_INFO);
158 }
159 }
160
161 if (resourceSection.resources.contains(PSDImageResourceSection::GRID_GUIDE)) {
162 GRID_GUIDE_1032 *gridGuidesInfo = dynamic_cast<GRID_GUIDE_1032*>(resourceSection.resources[PSDImageResourceSection::GRID_GUIDE]->resource);
163 if (gridGuidesInfo) {
165 Q_FOREACH(quint32 guide, gridGuidesInfo->verticalGuides) {
166 config.addGuideLine(Qt::Vertical, guide / m_image->xRes());
167 }
168 Q_FOREACH(quint32 guide, gridGuidesInfo->horizontalGuides) {
169 config.addGuideLine(Qt::Horizontal, guide / m_image->yRes());
170 }
171 config.setShowGuides(true);
172 m_doc->setGuidesConfig(config);
173 }
174 }
175
176 // Preserve all the annotations
177 Q_FOREACH (PSDResourceBlock *resourceBlock, resourceSection.resources.values()) {
178 m_image->addAnnotation(resourceBlock);
179 }
180
181 // Preserve the duotone colormode block for saving back to psd
182 if (header.colormode == DuoTone) {
183 KisAnnotationSP annotation = new KisAnnotation("DuotoneColormodeBlock",
184 i18n("Duotone Colormode Block"),
185 colorModeBlock.data);
186 m_image->addAnnotation(annotation);
187 }
188
189 // Load embedded patterns early for fill layers.
190
191 const QVector<QDomDocument> &embeddedPatterns =
192 layerSection.globalInfoSection.embeddedPatterns;
193
194 const QString storageLocation = m_doc->embeddedResourcesStorageId();
195
196 KisEmbeddedResourceStorageProxy resourceProxy(storageLocation);
197
199 if (!embeddedPatterns.isEmpty()) {
200 Q_FOREACH (const QDomDocument &doc, embeddedPatterns) {
201 serializer.registerPSDPattern(doc);
202 }
203 Q_FOREACH (KoPatternSP pattern, serializer.patterns()) {
204 if (pattern && pattern->valid()) {
205 resourceProxy.addResource(pattern);
206 dbgFile << "Loaded embedded pattern: " << pattern->name();
207 }
208 else {
209 qWarning() << "Invalid or empty pattern" << pattern;
210 }
211 }
212 }
213
214 // Read the projection into our single layer. Since we only read the projection when
215 // we have just one layer, we don't need to later on apply the alpha channel of the
216 // first layer to the projection if the number of layers is negative/
217 // See https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_16000.
218 if (layerSection.nLayers == 0) {
219 dbgFile << "Position" << io.pos() << "Going to read the projection into the first layer, which Photoshop calls 'Background'";
220
221 KisPaintLayerSP layer = new KisPaintLayer(m_image, i18nc("Name for the bottom-most layer in the layerstack", "Background"), OPACITY_OPAQUE_U8);
222
223 PSDImageData imageData(&header);
224 imageData.read(io, layer->paintDevice());
225
226 m_image->addNode(layer, m_image->rootLayer());
227
228 // Only one layer, the background layer, so we're done.
230 }
231
232 // More than one layer, so now construct the Krita image from the info we read.
233
234 QStack<KisGroupLayerSP> groupStack;
235 groupStack.push(m_image->rootLayer());
236
243 KisNodeSP lastAddedLayer;
244
245 typedef QPair<QDomDocument, KisLayerSP> LayerStyleMapping;
246 QVector<LayerStyleMapping> allStylesXml;
247 using namespace std::placeholders;
248
249 bool convertTextToShape = true;
250 for (int i = 0; i < layerSection.nLayers; i++) {
251 if (!layerSection.layers.at(i)->infoBlocks.textData.isNull()) {
253 m_feedbackInterface->askUser([&] (QWidget *parent) {
254 QMessageBox::StandardButton btn = QMessageBox::question(parent,
255 i18nc("@title:window PSD import question about text.", "Found Text Layers"),
256 i18nc("PSD import question about text",
257 "Found text objects, do you wish to load them as editable text shapes? "
258 "If not, they will be loaded as pixel data, which will be visually"
259 " more accurate to the original file."));
260 return (btn == QMessageBox::Yes);
261 });
262 convertTextToShape = (result == KisImportUserFeedbackInterface::Success
264 break;
265 }
266 }
267
268 // read the channels for the various layers
269 for(int i = 0; i < layerSection.nLayers; ++i) {
270
271 PSDLayerRecord* layerRecord = layerSection.layers.at(i);
272 dbgFile << "Going to read channels for layer" << i << layerRecord->layerName;
273 KisLayerSP newLayer;
274 if (layerRecord->infoBlocks.keys.contains("lsct") &&
275 layerRecord->infoBlocks.sectionDividerType != psd_other) {
276
277 if (layerRecord->infoBlocks.sectionDividerType == psd_bounding_divider && !groupStack.isEmpty()) {
278 KisGroupLayerSP groupLayer = new KisGroupLayer(m_image, "temp", OPACITY_OPAQUE_U8);
279 m_image->addNode(groupLayer, groupStack.top());
280 groupStack.push(groupLayer);
281 newLayer = groupLayer;
282 }
283 else if ((layerRecord->infoBlocks.sectionDividerType == psd_open_folder ||
285 (groupStack.size() > 1 || (lastAddedLayer && !groupStack.isEmpty()))) {
286 KisGroupLayerSP groupLayer;
287
288 if (groupStack.size() <= 1) {
289 groupLayer = new KisGroupLayer(m_image, "temp", OPACITY_OPAQUE_U8);
290 m_image->addNode(groupLayer, groupStack.top());
291 m_image->moveNode(lastAddedLayer, groupLayer, KisNodeSP());
292 } else {
293 groupLayer = groupStack.pop();
294 }
295
296 const QDomDocument &styleXml = layerRecord->infoBlocks.layerStyleXml;
297
298 if (!styleXml.isNull()) {
299 allStylesXml << LayerStyleMapping(styleXml, groupLayer);
300 }
301
302 groupLayer->setName(layerRecord->layerName);
303 groupLayer->setVisible(layerRecord->visible);
304 groupLayer->setUserLocked(layerRecord->userLocked);
305
306 if (layerRecord->infoBlocks.sectionDividerType == psd_closed_folder) {
307 groupLayer->setCollapsed(true);
308 }
309
310 QString compositeOp = psd_blendmode_to_composite_op(layerRecord->infoBlocks.sectionDividerBlendMode);
311
312 // Krita doesn't support pass-through blend
313 // mode. Instead it is just a property of a group
314 // layer, so flip it
315 if (compositeOp == COMPOSITE_PASS_THROUGH) {
316 compositeOp = COMPOSITE_OVER;
317 groupLayer->setPassThroughMode(true);
318 }
319
320 groupLayer->setCompositeOpId(compositeOp);
321
322 newLayer = groupLayer;
323 } else {
334 warnKrita << "WARNING: Provided PSD has unbalanced group "
335 << "layer markers. Some masks and/or layers can "
336 << "be lost while loading this file. Please "
337 << "report a bug to Krita developers and attach "
338 << "this file to the bugreport\n"
339 << " " << ppVar(layerRecord->layerName) << "\n"
340 << " " << ppVar(layerRecord->infoBlocks.sectionDividerType) << "\n"
341 << " " << ppVar(groupStack.size());
342 continue;
343 }
344 } else {
345 KisLayerSP layer;
346 if (!layerRecord->infoBlocks.fillConfig.isNull()) {
348 QDomDocument fillConfig;
350
351 KoShape *vectorMask = nullptr;
352 if (layerRecord->infoBlocks.keys.contains("vmsk") || layerRecord->infoBlocks.keys.contains("vsms")) {
354 if (!layerRecord->infoBlocks.vectorOriginationData.isNull()) {
356 psd_vector_origination_data::setupCatcher("/null", catcher, &data);
357 KisAslXmlParser parser;
358 parser.parseXML(layerRecord->infoBlocks.vectorOriginationData, catcher);
359 }
360 QString shapeName = data.shapeName();
362 if (!(data.canMakeParametricShape() && f)) {
363 double width = m_image->width() / m_image->xRes();
364 double height = m_image->height() / m_image->yRes();
365 vectorMask = layerRecord->constructPathShape(layerRecord->infoBlocks.vectorMask.path, width, height);
366 vectorMask->setUserData(new KisShapeSelectionMarker);
367 } else {
368 QSizeF size;
369 double angle;
370 data.OriginalSizeAndAngle(size, angle);
371 double resMultiplier = data.originResolution/72.0;
372 QTransform scaleToPt = QTransform::fromScale(resMultiplier, resMultiplier).inverted();
373 size = QSizeF(size.width()/resMultiplier, size.height()/resMultiplier);
374
376 KoProperties props;
377 if (shapeName == "RectangleShape") {
378 props.setProperty("x", 0);
379 props.setProperty("y", 0);
380 props.setProperty("width", size.width());
381 props.setProperty("height", size.height());
382 } else if (shapeName == "StarShape") {
383 props.setProperty("corners", data.originPolySides);
384 props.setProperty("convex", !data.isStar);
385
386 double angle = 360.0/(data.originPolySides*2);
387 double a = cos(kisDegreesToRadians(angle)) * 100.0;
388 double totalHeight = a + 100.0;
389 double l = size.height() / totalHeight * 100.0;
390
391 if (data.isStar) {
392 // 100% is a normal polygon.
393 a = cos(kisDegreesToRadians(angle)) * ((data.originPolyStarRatio*0.01) * l);
394 props.setProperty("baseRadius", a);
395 }
396 props.setProperty("tipRadius", l);
397 props.setProperty("baseRoundness", 0.0);
398 props.setProperty("tipRoundness", 0.0);
399 }
400 KoShape *shape = f->createShape(&props, &manager);
401 if (!shape)
402 continue;
403 shape->setSize(size);
404 QTransform t;
405 t.rotate(360.0-angle);
406
407 shape->setTransformation(t * scaleToPt.inverted() * data.transform * scaleToPt);
408 shape->setAbsolutePosition(scaleToPt.map(data.originShapeBBox.center()));
409
410 vectorMask = shape;
411 }
412 }
413 if (layerRecord->infoBlocks.fillType == psd_fill_gradient) {
414 cfg = KisGeneratorRegistry::instance()->value("gradient")->defaultConfiguration(resourceProxy.resourcesInterface());
415
417 fill.imageWidth = m_image->width();
418 fill.imageHeight = m_image->height();
419 psd_layer_gradient_fill::setupCatcher("/null", catcher, &fill);
420 KisAslXmlParser parser;
421 parser.parseXML(layerRecord->infoBlocks.fillConfig, catcher);
422 fillConfig = fill.getFillLayerConfig();
423 if (vectorMask) {
424 vectorMask->setBackground(fill.getBackground());
425 }
426
427 } else if (layerRecord->infoBlocks.fillType == psd_fill_pattern) {
428 cfg = KisGeneratorRegistry::instance()->value("pattern")->defaultConfiguration(resourceProxy.resourcesInterface());
429
431 psd_layer_pattern_fill::setupCatcher("/null", catcher, &fill);
432
433 KisAslXmlParser parser;
434 parser.parseXML(layerRecord->infoBlocks.fillConfig, catcher);
435 fillConfig = fill.getFillLayerConfig();
436 if (vectorMask) {
437 vectorMask->setBackground(fill.getBackground(resourceProxy));
438 }
439
440 } else {
441 cfg = KisGeneratorRegistry::instance()->value("color")->defaultConfiguration(resourceProxy.resourcesInterface());
442
444 fill.cs = m_image->colorSpace();
445 psd_layer_solid_color::setupCatcher("/null", catcher, &fill);
446 KisAslXmlParser parser;
447 parser.parseXML(layerRecord->infoBlocks.fillConfig, catcher);
448
449 fillConfig = fill.getFillLayerConfig();
450 if (vectorMask) {
451 vectorMask->setBackground(fill.getBackground());
452 }
453 }
454 if (vectorMask) {
455 KisShapeLayerSP shapeLayer = new KisShapeLayer(m_doc->shapeController(), m_image, layerRecord->layerName, layerRecord->opacity);
456
457
458 if (!layerRecord->infoBlocks.vectorStroke.isNull()) {
459 KoShapeStrokeSP stroke(new KoShapeStroke());
463 fill.cs = m_image->colorSpace();
464 KisAslCallbackObjectCatcher strokeCatcher;
465 psd_vector_stroke_data::setupCatcher("", strokeCatcher, &data);
466 psd_layer_solid_color::setupCatcher("/strokeStyle/strokeStyleContent", strokeCatcher, &fill);
467 psd_layer_gradient_fill::setupCatcher("/strokeStyle/strokeStyleContent", strokeCatcher, &grad);
468 KisAslXmlParser parser;
469 parser.parseXML(layerRecord->infoBlocks.vectorStroke, strokeCatcher);
470
471 if (!data.fillEnabled) {
473 }
474 if (data.strokeEnabled) {
475 QColor c = fill.getBrush().color();
476 c.setAlphaF(data.opacity);
477 stroke->setColor(c);
478 if (!grad.gradient.isNull()) {
479 stroke->setLineBrush(grad.getBrush());
480 }
481 } else {
482 stroke->setColor(Qt::transparent);
483 }
484 data.setupShapeStroke(stroke);
485
486 vectorMask->setStroke(stroke);
487 }
488
489 shapeLayer->addShape(vectorMask);
490 layer = shapeLayer;
491 } else {
492 cfg->fromXML(fillConfig.firstChildElement());
493 cfg->createLocalResourcesSnapshot();
494 KisGeneratorLayerSP genlayer = new KisGeneratorLayer(m_image, layerRecord->layerName, cfg, m_image->globalSelection());
495 genlayer->setFilter(cfg);
496 layer = genlayer;
497 }
498
499
500 } else if (!layerRecord->infoBlocks.textData.isNull() && convertTextToShape) {
501 KisShapeLayerSP textLayer = new KisShapeLayer(m_doc->shapeController(), m_image, layerRecord->layerName, layerRecord->opacity);
504 psd_layer_type_shape::setupCatcher(QString(), catcher, &text);
505 KisAslXmlParser parser;
506 parser.parseXML(layerRecord->infoBlocks.textData, catcher);
507 KoSvgTextShape *shape = new KoSvgTextShape();
508 PsdTextDataConverter converter;
509 KoSvgTextShapeMarkupConverter svgConverter(shape);
510
511 QString svg;
512 QString styles;
513 // This is to align inlinesize appropriately.
514 bool offsetByAscent = false;
515 QPointF offset1;
516 // PSD text layers have all their coordinates in pixels, and because fonts can be very precise-unit sensitive,
517 // we want to ensure all values are scaled appropriately.
518
519 QTransform scaleToPt = QTransform::fromScale(m_image->xRes(), m_image->yRes()).inverted();
520 bool res = converter.convertPSDTextEngineDataToSVG(text.engineData,
521 layerSection.globalInfoSection.txt2Data,
523 text.textIndex,
524 &svg, &styles,
525 offset1, offsetByAscent,
526 text.isHorizontal, scaleToPt);
527 if (!res || !converter.errors().isEmpty()) {
528 qWarning() << converter.errors();
529 }
530 dbgFile << converter.warnings();
531 svgConverter.convertFromSvg(svg, styles, m_image->bounds(), m_image->xRes()*72.0);
532 if (offsetByAscent) {
533 QPointF offset2 = QPointF() - shape->outlineRect().topLeft();
534 if (text.isHorizontal) {
535 offset2.setX(offset1.x());
536 } else {
537 offset2.setY(offset1.y());
538 }
539 shape->setTransformation(QTransform::fromTranslate(offset2.x(), offset2.y()) * scaleToPt.inverted()
540 * layerRecord->infoBlocks.textTransform * scaleToPt);
541 } else {
542 shape->setTransformation(scaleToPt.inverted() * layerRecord->infoBlocks.textTransform * scaleToPt);
543 }
544 textLayer->addShape(shape);
545 layer = textLayer;
546 } else {
547 layer = new KisPaintLayer(m_image, layerRecord->layerName, layerRecord->opacity);
548 if (!layerRecord->readPixelData(io, layer->paintDevice())) {
549 dbgFile << "failed reading channels for layer: " << layerRecord->layerName << layerRecord->error;
551 }
552 }
554
555 layer->setColorLabelIndex(layerRecord->labelColor);
556
557 const QDomDocument &styleXml = layerRecord->infoBlocks.layerStyleXml;
558
559 if (!styleXml.isNull()) {
560 allStylesXml << LayerStyleMapping(styleXml, layer);
561 }
562
563 if (!groupStack.isEmpty()) {
564 m_image->addNode(layer, groupStack.top());
565 }
566 else {
567 m_image->addNode(layer, m_image->root());
568 }
569 layer->setVisible(layerRecord->visible);
570 layer->setUserLocked(layerRecord->userLocked);
571 newLayer = layer;
572
573 }
574
575 Q_FOREACH (ChannelInfo *channelInfo, layerRecord->channelInfoRecords) {
576 if (channelInfo->channelId < -1) {
577 const KisGeneratorLayer *fillLayer = qobject_cast<KisGeneratorLayer *>(newLayer.data());
578 const KisShapeLayer *shapeLayer = qobject_cast<KisShapeLayer *>(newLayer.data());
579 KoPathShape *vectorMask = new KoPathShape();
580 if (layerRecord->infoBlocks.keys.contains("vmsk") || layerRecord->infoBlocks.keys.contains("vsms")) {
581 double width = m_image->width() / m_image->xRes();
582 double height = m_image->height() / m_image->yRes();
583 vectorMask = layerRecord->constructPathShape(layerRecord->infoBlocks.vectorMask.path, width, height);
584 vectorMask->setUserData(new KisShapeSelectionMarker);
585 }
586 bool hasVectorMask = vectorMask->pointCount() > 0 && layerRecord->infoBlocks.vectorMask.path.subPaths.size() > 0;
587 if (fillLayer) {
588 if (!layerRecord->readMask(io, fillLayer->paintDevice(), channelInfo)) {
589 dbgFile << "failed reading masks for generator layer: " << layerRecord->layerName << layerRecord->error;
590 }
591 if (hasVectorMask) {
592 KisShapeSelection* shapeSelection = new KisShapeSelection(m_doc->shapeController(), fillLayer->internalSelection());
593 fillLayer->internalSelection()->convertToVectorSelectionNoUndo(shapeSelection);
594 shapeSelection->addShape(vectorMask);
595 fillLayer->internalSelection()->updateProjection();
596 }
597 } else {
598 if (!(shapeLayer && hasVectorMask)) {
599 KisTransparencyMaskSP mask = new KisTransparencyMask(m_image, i18n("Transparency Mask"));
600 mask->initSelection(newLayer);
601 if (!layerRecord->readMask(io, mask->paintDevice(), channelInfo)) {
602 dbgFile << "failed reading masks for layer: " << layerRecord->layerName << layerRecord->error;
603 }
604 if (hasVectorMask) {
605 KisShapeSelection* shapeSelection = new KisShapeSelection(m_doc->shapeController(), mask->selection());
606 mask->selection()->convertToVectorSelectionNoUndo(shapeSelection);
607 shapeSelection->addShape(vectorMask);
608 mask->selection()->updateProjection();
609 }
610 m_image->addNode(mask, newLayer);
611 }
612 }
613 }
614 }
615
616 lastAddedLayer = newLayer;
617 }
618
619 if (!allStylesXml.isEmpty()) {
620 Q_FOREACH (const LayerStyleMapping &mapping, allStylesXml) {
621
622 serializer.readFromPSDXML(mapping.first);
623
624 if (serializer.styles().size() == 1) {
625 KisPSDLayerStyleSP layerStyle = serializer.styles().first();
626 KisLayerSP layer = mapping.second;
627
628 Q_FOREACH (KoAbstractGradientSP gradient, serializer.gradients()) {
629 if (gradient && gradient->valid()) {
630 resourceProxy.addResource(gradient);
631 }
632 else {
633 qWarning() << "Invalid or empty gradient" << gradient;
634 }
635 }
636
637 Q_FOREACH (const KoPatternSP &pattern, serializer.patterns()) {
638 if (pattern && pattern->valid()) {
639 resourceProxy.addResource(pattern);
640 } else {
641 qWarning() << "Invalid or empty pattern" << pattern;
642 }
643 }
644
645 layerStyle->setName(layer->name());
646 layerStyle->setResourcesInterface(resourceProxy.detachedResourcesInterface());
647 if (!layerStyle->uuid().isNull()) {
648 layerStyle->setUuid(QUuid::createUuid());
649 }
650 layerStyle->setValid(true);
651
652 resourceProxy.addResource(layerStyle);
653
654 layer->setLayerStyle(layerStyle->cloneWithResourcesSnapshot(layerStyle->resourcesInterface(), 0));
655 } else {
656 warnKrita << "WARNING: Couldn't read layer style!" << ppVar(serializer.styles());
657 }
658
659 }
660 }
661
663}
const quint8 OPACITY_OPAQUE_U8
const QString COMPOSITE_OVER
const QString COMPOSITE_PASS_THROUGH
constexpr qreal POINT_TO_INCH(qreal px)
Definition KoUnit.h:37
A data extension mechanism for Krita.
QVector< KoAbstractGradientSP > gradients() const
QVector< KisPSDLayerStyleSP > styles() const
void readFromPSDXML(const QDomDocument &doc)
void registerPSDPattern(const QDomDocument &doc)
QHash< QString, KoPatternSP > patterns() const
void parseXML(const QDomDocument &doc, KisAslObjectCatcher &catcher)
KisUndoStore * createUndoStore()
KisShapeController * shapeController
QString embeddedResourcesStorageId() const
void setGuidesConfig(const KisGuidesConfig &data)
KisGuidesConfig guidesConfig
static KisGeneratorRegistry * instance()
void setShowGuides(bool value)
void addGuideLine(Qt::Orientation orientation, qreal position)
Add a guide line to the canvas.
void addAnnotation(KisAnnotationSP annotation)
KisGroupLayerSP rootLayer() const
const KoColorSpace * colorSpace() const
qint32 width() const
double xRes() const
double yRes() const
qint32 height() const
KisSelectionSP globalSelection() const
Definition kis_image.cc:721
QRect bounds() const override
void setResolution(double xres, double yres)
virtual Result askUser(AskCallback callback)=0
ask the user a question about the loading process
const T value(const QString &id) const
The position of a path point within a path shape.
Definition KoPathShape.h:63
int pointCount() const
Returns the number of points in the path.
void setProperty(const QString &name, const QVariant &value)
void addShape(KoShape *shape)
static KoShapeRegistry * instance()
virtual void setStroke(KoShapeStrokeModelSP stroke)
Definition KoShape.cpp:899
void setTransformation(const QTransform &matrix)
Definition KoShape.cpp:369
virtual void setBackground(QSharedPointer< KoShapeBackground > background)
Definition KoShape.cpp:746
void setUserData(KoShapeUserData *userData)
Definition KoShape.cpp:620
void setAbsolutePosition(const QPointF &newPosition, KoFlake::AnchorPosition anchor=KoFlake::Center)
Definition KoShape.cpp:583
virtual void setSize(const QSizeF &size)
Resize the shape.
Definition KoShape.cpp:249
QRectF outlineRect() const override
bool read(QIODevice &device)
QString error
Definition psd_header.h:52
QMap< PSDResourceID, PSDResourceBlock * > resources
PsdAdditionalLayerInfoBlock infoBlocks
bool readPixelData(QIODevice &io, KisPaintDeviceSP device)
QVector< ChannelInfo * > channelInfoRecords
KoPathShape * constructPathShape(psd_path path, double shapeWidth, double shapeHeight)
constructPathShape create a KoPathshape based on a psd_path struct, used in vector masks and path res...
bool readMask(QIODevice &io, KisPaintDeviceSP dev, ChannelInfo *channel)
The PsdTextDataConverter class.
bool convertPSDTextEngineDataToSVG(const QVariantHash tySh, const QVariantHash txt2, const KoColorSpace *imageCs, const int textIndex, QString *svgText, QString *svgStyles, QPointF &offset, bool &offsetByAscent, bool &isHorizontal, QTransform scaleToPt=QTransform())
#define warnKrita
Definition kis_debug.h:94
#define ppVar(var)
Definition kis_debug.h:163
#define dbgFile
Definition kis_debug.h:57
T kisDegreesToRadians(T degrees)
Definition kis_global.h:176
KisSharedPtr< KisNode > KisNodeSP
Definition kis_types.h:86
const char * name(StandardAction id)
int size(const Forest< T > &forest)
Definition KisForest.h:1232
KisImportExportErrorCode workaroundUnsuitableImageColorSpace(KisImageSP image, KisImportUserFeedbackInterface *feedbackInterface, KisImageBarrierLock &lock)
QPair< QString, QString > psd_colormode_to_colormodelid(psd_color_mode colormode, quint16 channelDepth)
Definition psd.cpp:16
QString psd_blendmode_to_composite_op(const QString &blendmode)
Definition psd.cpp:59
@ psd_other
Definition psd.h:144
@ psd_open_folder
Definition psd.h:144
@ psd_closed_folder
Definition psd.h:144
@ psd_bounding_divider
Definition psd.h:144
@ psd_fill_gradient
Definition psd.h:125
@ psd_fill_pattern
Definition psd.h:126
@ DuoTone
Definition psd.h:57
QList< quint32 > verticalGuides
QList< quint32 > horizontalGuides
virtual void setUserLocked(bool l)
virtual void setVisible(bool visible, bool loading=false)
void setColorLabelIndex(int index)
void setName(const QString &name)
void setCollapsed(bool collapsed)
virtual KisPaintDeviceSP paintDevice() const =0
QString name() const
void setCompositeOpId(const QString &compositeOpId)
virtual KisFilterConfigurationSP defaultConfiguration(KisResourcesInterfaceSP resourcesInterface) const
void setFilter(KisFilterConfigurationSP filterConfig, bool checkCompareConfig=true) override
void setPassThroughMode(bool value)
void setLayerStyle(KisPSDLayerStyleSP layerStyle)
Definition kis_layer.cc:254
void initSelection(KisSelectionSP copyFrom, KisLayerSP parentLayer)
initSelection initializes the selection for the mask from the given selection's projection.
Definition kis_mask.cc:157
KisSelectionSP selection
Definition kis_mask.cc:44
KisPaintDeviceSP paintDevice() const override
Definition kis_mask.cc:223
bool addNode(KisNodeSP node, KisNodeSP parent=KisNodeSP(), KisNodeAdditionFlags flags=KisNodeAdditionFlag::None)
bool moveNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis)
KisPaintDeviceSP paintDevice
KisSelectionSP internalSelection() const
void updateProjection(const QRect &rect)
void convertToVectorSelectionNoUndo(KisSelectionComponent *shapeSelection)
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
const KoColorProfile * createColorProfile(const QString &colorModelId, const QString &colorDepthId, const QByteArray &rawData)
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_layer_gradient_fill *data)
QSharedPointer< KoShapeBackground > getBackground()
QSharedPointer< KoShapeBackground > getBackground(KisEmbeddedResourceStorageProxy &embeddedProxy)
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_layer_pattern_fill *data)
QSharedPointer< KoShapeBackground > getBackground()
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_layer_solid_color *data)
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_layer_type_shape *data)
QList< psd_path_sub_path > subPaths
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_vector_origination_data *data)
double originResolution
Resolution of the coordinates.
void OriginalSizeAndAngle(QSizeF &size, double &angle)
double originPolyStarRatio
Only for 8, percentage of small radius to big radius.
static void setupCatcher(const QString path, KisAslCallbackObjectCatcher &catcher, psd_vector_stroke_data *data)
void setupShapeStroke(KoShapeStrokeSP stroke)

References KisImage::addAnnotation(), KisGuidesConfig::addGuideLine(), KisNodeFacade::addNode(), KisEmbeddedResourceStorageProxy::addResource(), KoShapeContainer::addShape(), KisImportUserFeedbackInterface::askUser(), PSDLayerRecord::blendModeKey, KisImage::bounds(), psd_vector_origination_data::canMakeParametricShape(), PSDHeader::channelDepth, ChannelInfo::channelId, PSDLayerRecord::channelInfoRecords, PSDHeader::colormode, KisImage::colorSpace(), KoColorSpaceRegistry::colorSpace(), COMPOSITE_OVER, COMPOSITE_PASS_THROUGH, PSDLayerRecord::constructPathShape(), KoSvgTextShapeMarkupConverter::convertFromSvg(), PsdTextDataConverter::convertPSDTextEngineDataToSVG(), KisSelection::convertToVectorSelectionNoUndo(), KoColorSpaceRegistry::createColorProfile(), KisDocument::createUndoStore(), psd_layer_solid_color::cs, KisSharedPtr< T >::data(), PSDColorModeBlock::data, dbgFile, KisBaseProcessor::defaultConfiguration(), KisEmbeddedResourceStorageProxy::detachedResourcesInterface(), DuoTone, PsdAdditionalLayerInfoBlock::embeddedPatterns, KisDocument::embeddedResourcesStorageId(), psd_layer_type_shape::engineData, PSDHeader::error, PSDLayerRecord::error, PSDLayerMaskSection::error, PSDImageResourceSection::error, PSDColorModeBlock::error, PsdTextDataConverter::errors(), ImportExportCodes::FileFormatIncorrect, PsdAdditionalLayerInfoBlock::fillConfig, psd_vector_stroke_data::fillEnabled, PsdAdditionalLayerInfoBlock::fillType, ImportExportCodes::FormatColorSpaceUnsupported, psd_layer_solid_color::getBackground(), psd_layer_gradient_fill::getBackground(), psd_layer_pattern_fill::getBackground(), psd_layer_solid_color::getBrush(), psd_layer_gradient_fill::getBrush(), psd_layer_solid_color::getFillLayerConfig(), psd_layer_gradient_fill::getFillLayerConfig(), psd_layer_pattern_fill::getFillLayerConfig(), PSDLayerMaskSection::globalInfoSection, KisImage::globalSelection(), psd_layer_gradient_fill::gradient, KisAslLayerStyleSerializer::gradients(), PSDImageResourceSection::GRID_GUIDE, KisDocument::guidesConfig, KisImage::height(), PSDHeader::height, GRID_GUIDE_1032::horizontalGuides, RESN_INFO_1005::hRes, ICC_PROFILE_1039::icc, PSDImageResourceSection::ICC_PROFILE, psd_layer_gradient_fill::imageHeight, psd_layer_gradient_fill::imageWidth, PSDLayerRecord::infoBlocks, KisMask::initSelection(), KoShapeRegistry::instance(), KisGeneratorRegistry::instance(), KoColorSpaceRegistry::instance(), KisSelectionBasedLayer::internalSelection(), psd_layer_type_shape::isHorizontal, psd_vector_origination_data::isStar, PsdAdditionalLayerInfoBlock::keys, kisDegreesToRadians(), PSDLayerRecord::labelColor, PSDLayerRecord::layerName, PSDLayerMaskSection::layers, PsdAdditionalLayerInfoBlock::layerStyleXml, m_doc, m_feedbackInterface, m_image, KisNodeFacade::moveNode(), KisBaseNode::name(), KoColorProfile::name, PSDLayerMaskSection::nLayers, ImportExportCodes::OK, psd_vector_stroke_data::opacity, PSDLayerRecord::opacity, OPACITY_OPAQUE_U8, psd_vector_origination_data::OriginalSizeAndAngle(), psd_vector_origination_data::originPolySides, psd_vector_origination_data::originPolyStarRatio, psd_vector_origination_data::originResolution, psd_vector_origination_data::originShapeBBox, KoSvgTextShape::outlineRect(), KisBaseNode::paintDevice(), KisMask::paintDevice(), KisPaintLayer::paintDevice, KisSelectionBasedLayer::paintDevice, KisAslXmlParser::parseXML(), psd_vector_mask::path, KisAslLayerStyleSerializer::patterns(), POINT_TO_INCH(), KoPathShape::pointCount(), ppVar, psd_blendmode_to_composite_op(), psd_bounding_divider, psd_closed_folder, psd_colormode_to_colormodelid(), psd_fill_gradient, psd_fill_pattern, psd_open_folder, psd_other, PSDHeader::read(), PSDLayerMaskSection::read(), PSDImageResourceSection::read(), PSDColorModeBlock::read(), PSDImageData::read(), KisAslLayerStyleSerializer::readFromPSDXML(), PSDLayerRecord::readMask(), PSDLayerRecord::readPixelData(), KisAslLayerStyleSerializer::registerPSDPattern(), PSDImageResourceSection::RESN_INFO, PSDImageResourceSection::resources, KisEmbeddedResourceStorageProxy::resourcesInterface(), KisNodeFacade::root, KisImage::rootLayer(), PsdAdditionalLayerInfoBlock::sectionDividerBlendMode, PsdAdditionalLayerInfoBlock::sectionDividerType, KisMask::selection, KoShape::setAbsolutePosition(), KoShape::setBackground(), KisBaseNode::setCollapsed(), KisBaseNode::setColorLabelIndex(), KisBaseNode::setCompositeOpId(), KisGeneratorLayer::setFilter(), KisDocument::setGuidesConfig(), KisLayer::setLayerStyle(), KisBaseNode::setName(), KisGroupLayer::setPassThroughMode(), KoProperties::setProperty(), KisImage::setResolution(), KisGuidesConfig::setShowGuides(), KoShape::setSize(), KoShape::setStroke(), KoShape::setTransformation(), psd_layer_gradient_fill::setupCatcher(), psd_layer_pattern_fill::setupCatcher(), psd_layer_solid_color::setupCatcher(), psd_layer_type_shape::setupCatcher(), psd_vector_origination_data::setupCatcher(), psd_vector_stroke_data::setupCatcher(), psd_vector_stroke_data::setupShapeStroke(), KoShape::setUserData(), KisBaseNode::setUserLocked(), KisBaseNode::setVisible(), KisDocument::shapeController, psd_vector_origination_data::shapeName(), psd_vector_stroke_data::strokeEnabled, KisAslLayerStyleSerializer::styles(), psd_path::subPaths, KisImportUserFeedbackInterface::Success, KisImportUserFeedbackInterface::SuppressedByBatchMode, PsdAdditionalLayerInfoBlock::textData, psd_layer_type_shape::textIndex, PsdAdditionalLayerInfoBlock::textTransform, psd_vector_origination_data::transform, PsdAdditionalLayerInfoBlock::txt2Data, KisSelection::updateProjection(), PSDLayerRecord::userLocked, KoGenericRegistry< T >::value(), PsdAdditionalLayerInfoBlock::vectorMask, PsdAdditionalLayerInfoBlock::vectorOriginationData, PsdAdditionalLayerInfoBlock::vectorStroke, GRID_GUIDE_1032::verticalGuides, PSDLayerRecord::visible, RESN_INFO_1005::vRes, PsdTextDataConverter::warnings(), warnKrita, KisImage::width(), PSDHeader::width, KritaUtils::workaroundUnsuitableImageColorSpace(), KisImage::xRes(), and KisImage::yRes().

◆ image()

KisImageSP PSDLoader::image ( )

Definition at line 671 of file psd_loader.cpp.

672{
673 return m_image;
674}

References m_image.

Member Data Documentation

◆ m_doc

KisDocument* PSDLoader::m_doc
private

Definition at line 42 of file psd_loader.h.

◆ m_feedbackInterface

KisImportUserFeedbackInterface* PSDLoader::m_feedbackInterface {nullptr}
private

Definition at line 44 of file psd_loader.h.

44{nullptr};

◆ m_image

KisImageSP PSDLoader::m_image
private

Definition at line 41 of file psd_loader.h.

◆ m_stop

bool PSDLoader::m_stop
private

Definition at line 43 of file psd_loader.h.


The documentation for this class was generated from the following files: