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

0001 /*
0002  *  SPDX-FileCopyrightText: 2009 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 #include "psd_layer_section.h"
0008 
0009 #include <QBuffer>
0010 #include <QIODevice>
0011 
0012 #include <KoColor.h>
0013 #include <KoColorSpace.h>
0014 
0015 #include <kis_debug.h>
0016 #include <kis_effect_mask.h>
0017 #include <kis_group_layer.h>
0018 #include <kis_generator_layer.h>
0019 #include <kis_image.h>
0020 #include <kis_node.h>
0021 #include <kis_paint_layer.h>
0022 #include <kis_painter.h>
0023 
0024 #include "kis_dom_utils.h"
0025 
0026 #include "psd.h"
0027 #include "psd_header.h"
0028 #include "psd_utils.h"
0029 
0030 #include "compression.h"
0031 
0032 #include <asl/kis_asl_reader_utils.h>
0033 #include <asl/kis_asl_writer_utils.h>
0034 #include <asl/kis_offset_on_exit_verifier.h>
0035 #include <kis_asl_layer_style_serializer.h>
0036 
0037 PSDLayerMaskSection::PSDLayerMaskSection(const PSDHeader &header)
0038     : globalInfoSection(header)
0039     , m_header(header)
0040 {
0041 }
0042 
0043 PSDLayerMaskSection::~PSDLayerMaskSection()
0044 {
0045     qDeleteAll(layers);
0046 }
0047 
0048 bool PSDLayerMaskSection::read(QIODevice &io)
0049 {
0050     bool retval = true; // be optimistic! <:-)
0051 
0052     try {
0053         if (m_header.tiffStyleLayerBlock) {
0054             switch (m_header.byteOrder) {
0055             case psd_byte_order::psdLittleEndian:
0056                 retval = readTiffImpl<psd_byte_order::psdLittleEndian>(io);
0057                 break;
0058             default:
0059                 retval = readTiffImpl(io);
0060                 break;
0061             }
0062         } else {
0063             retval = readPsdImpl(io);
0064         }
0065     } catch (KisAslReaderUtils::ASLParseException &e) {
0066         warnKrita << "WARNING: PSD (emb. pattern):" << e.what();
0067         retval = false;
0068     }
0069 
0070     return retval;
0071 }
0072 
0073 template<psd_byte_order byteOrder>
0074 bool PSDLayerMaskSection::readLayerInfoImpl(QIODevice &io)
0075 {
0076     quint64 layerInfoSectionSize = 0;
0077     if (m_header.version == 1) {
0078         quint32 _layerInfoSectionSize = 0;
0079         SAFE_READ_EX(byteOrder, io, _layerInfoSectionSize);
0080         layerInfoSectionSize = _layerInfoSectionSize;
0081     } else if (m_header.version == 2) {
0082         SAFE_READ_EX(byteOrder, io, layerInfoSectionSize);
0083     }
0084 
0085     if (layerInfoSectionSize & 0x1) {
0086         warnKrita << "WARNING: layerInfoSectionSize is NOT even! Fixing...";
0087         layerInfoSectionSize++;
0088     }
0089 
0090     {
0091         SETUP_OFFSET_VERIFIER(layerInfoSectionTag, io, layerInfoSectionSize, 0);
0092         dbgFile << "Layer info block size" << layerInfoSectionSize;
0093 
0094         if (layerInfoSectionSize > 0) {
0095             if (!psdread<byteOrder>(io, nLayers) || nLayers == 0) {
0096                 error = QString("Could not read read number of layers or no layers in image. %1").arg(nLayers);
0097                 return false;
0098             }
0099 
0100             hasTransparency = nLayers < 0; // first alpha channel is the alpha channel of the projection.
0101             nLayers = qAbs(nLayers);
0102 
0103             dbgFile << "Number of layers:" << nLayers;
0104             dbgFile << "Has separate projection transparency:" << hasTransparency;
0105 
0106             for (int i = 0; i < nLayers; ++i) {
0107                 dbgFile << "Going to read layer" << i << "pos" << io.pos();
0108                 dbgFile << "== Enter PSDLayerRecord";
0109                 PSDHeader sanitizedHeader(m_header);
0110                 sanitizedHeader.tiffStyleLayerBlock = false; // disable padding
0111                 QScopedPointer<PSDLayerRecord> layerRecord(new PSDLayerRecord(sanitizedHeader));
0112                 if (!layerRecord->read(io)) {
0113                     error = QString("Could not load layer %1: %2").arg(i).arg(layerRecord->error);
0114                     return false;
0115                 }
0116                 dbgFile << "== Leave PSDLayerRecord";
0117                 dbgFile << "Finished reading layer" << i << layerRecord->layerName << "blending mode" << layerRecord->blendModeKey << io.pos()
0118                         << "Number of channels:" << layerRecord->channelInfoRecords.size();
0119                 layers << layerRecord.take();
0120             }
0121         }
0122 
0123         // get the positions for the channels belonging to each layer
0124         for (int i = 0; i < nLayers; ++i) {
0125             dbgFile << "Going to seek channel positions for layer" << i << "pos" << io.pos();
0126             if (i > layers.size()) {
0127                 error = QString("Expected layer %1, but only have %2 layers").arg(i).arg(layers.size());
0128                 return false;
0129             }
0130 
0131             PSDLayerRecord *layerRecord = layers.at(i);
0132 
0133             for (int j = 0; j < layerRecord->nChannels; ++j) {
0134                 // save the current location so we can jump beyond this block later on.
0135                 quint64 channelStartPos = io.pos();
0136                 dbgFile << "\tReading channel image data for channel" << j << "from pos" << io.pos();
0137 
0138                 KIS_ASSERT_RECOVER(j < layerRecord->channelInfoRecords.size())
0139                 {
0140                     return false;
0141                 }
0142 
0143                 ChannelInfo *channelInfo = layerRecord->channelInfoRecords.at(j);
0144 
0145                 quint16 compressionType;
0146                 if (!psdread<byteOrder>(io, compressionType)) {
0147                     error = "Could not read compression type for channel";
0148                     return false;
0149                 }
0150                 channelInfo->compressionType = static_cast<psd_compression_type>(compressionType);
0151                 dbgFile << "\t\tChannel" << j << "has compression type" << compressionType;
0152 
0153                 QRect channelRect = layerRecord->channelRect(channelInfo);
0154 
0155                 // read the rle row lengths;
0156                 if (channelInfo->compressionType == psd_compression_type::RLE) {
0157                     for (qint64 row = 0; row < channelRect.height(); ++row) {
0158                         // dbgFile << "Reading the RLE bytecount position of row" << row << "at pos" << io.pos();
0159 
0160                         quint32 byteCount;
0161                         if (m_header.version == 1) {
0162                             quint16 _byteCount;
0163                             if (!psdread<byteOrder>(io, _byteCount)) {
0164                                 error = QString("Could not read byteCount for rle-encoded channel");
0165                                 return 0;
0166                             }
0167                             byteCount = _byteCount;
0168                         } else {
0169                             if (!psdread<byteOrder>(io, byteCount)) {
0170                                 error = QString("Could not read byteCount for rle-encoded channel");
0171                                 return 0;
0172                             }
0173                         }
0174                         ////dbgFile << "rle byte count" << byteCount;
0175                         channelInfo->rleRowLengths << byteCount;
0176                     }
0177                 }
0178 
0179                 // we're beyond all the length bytes, rle bytes and whatever, this is the
0180                 // location of the real pixel data
0181                 channelInfo->channelDataStart = io.pos();
0182 
0183                 dbgFile << "\t\tstart" << channelStartPos << "data start" << channelInfo->channelDataStart << "data length" << channelInfo->channelDataLength
0184                         << "pos" << io.pos();
0185 
0186                 // make sure we are at the start of the next channel data block
0187                 io.seek(channelStartPos + channelInfo->channelDataLength);
0188 
0189                 // this is the length of the actual channel data bytes
0190                 channelInfo->channelDataLength = channelInfo->channelDataLength - (channelInfo->channelDataStart - channelStartPos);
0191 
0192                 dbgFile << "\t\tchannel record" << j << "for layer" << i << "with id" << channelInfo->channelId << "starting position"
0193                         << channelInfo->channelDataStart << "with length" << channelInfo->channelDataLength << "and has compression type"
0194                         << channelInfo->compressionType;
0195             }
0196         }
0197     }
0198 
0199     return true;
0200 }
0201 
0202 bool PSDLayerMaskSection::readPsdImpl(QIODevice &io)
0203 {
0204     dbgFile << "(PSD) reading layer section. Pos:" << io.pos() << "bytes left:" << io.bytesAvailable();
0205 
0206     // https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_21849
0207     boost::optional<quint64> layerMaskBlockSize = 0;
0208 
0209     if (m_header.version == 1) {
0210         quint32 _layerMaskBlockSize = 0;
0211         SAFE_READ_EX(psd_byte_order::psdBigEndian, io, _layerMaskBlockSize);
0212         layerMaskBlockSize = _layerMaskBlockSize;
0213     } else if (m_header.version == 2) {
0214         SAFE_READ_EX(psd_byte_order::psdBigEndian, io, *layerMaskBlockSize);
0215     }
0216 
0217     qint64 start = io.pos();
0218 
0219     dbgFile << "layer block size" << *layerMaskBlockSize;
0220 
0221     if (*layerMaskBlockSize == 0) {
0222         dbgFile << "No layer info, so no PSD layers available";
0223         return true;
0224     }
0225 
0226     /**
0227      * PSD files created in some weird web applications may
0228      * have invalid layer-mask-block-size set. Just do a simple
0229      * sanity check to catch this case
0230      */
0231     if (static_cast<qint64>(*layerMaskBlockSize) > io.bytesAvailable()) {
0232         warnKrita << "WARNING: invalid layer block size. Got" << *layerMaskBlockSize << "Bytes left" << io.bytesAvailable() << "Triggering a workaround...";
0233 
0234         // just don't use this value for offset recovery at the end
0235         layerMaskBlockSize = boost::none;
0236     }
0237 
0238     if (!readLayerInfoImpl(io)) {
0239         return false;
0240     }
0241 
0242     dbgFile << "Leftover before additional blocks:" << io.pos() << io.bytesAvailable();
0243 
0244     quint32 globalMaskBlockLength;
0245     if (!psdread(io, globalMaskBlockLength)) {
0246         error = "Could not read global mask info block";
0247         return false;
0248     }
0249 
0250     dbgFile << "Global mask size:" << globalMaskBlockLength << "(" << io.pos() << io.bytesAvailable() << ")";
0251 
0252     if (globalMaskBlockLength > 0) {
0253         if (!psdread(io, globalLayerMaskInfo.overlayColorSpace)) {
0254             error = "Could not read global mask info overlay colorspace";
0255             return false;
0256         }
0257 
0258         for (int i = 0; i < 4; ++i) {
0259             if (!psdread(io, globalLayerMaskInfo.colorComponents[i])) {
0260                 error = QString("Could not read mask info visualizaion color component %1").arg(i);
0261                 return false;
0262             }
0263         }
0264 
0265         if (!psdread(io, globalLayerMaskInfo.opacity)) {
0266             error = "Could not read global mask info visualization opacity";
0267             return false;
0268         }
0269 
0270         if (!psdread(io, globalLayerMaskInfo.kind)) {
0271             error = "Could not read global mask info visualization type";
0272             return false;
0273         }
0274 
0275         // Global mask must measure at least 13 bytes
0276         // (excluding the 1 byte compiler enforced padding)
0277         if (globalMaskBlockLength >= 13) {
0278             dbgFile << "Padding for global mask block:"
0279                     << globalMaskBlockLength - 13 << "(" << io.pos() << ")";
0280             io.skip(static_cast<size_t>(globalMaskBlockLength) - 13);
0281         }
0282     }
0283 
0284     // global additional sections
0285 
0286     /**
0287      * Newer versions of PSD have layers info block wrapped into
0288      * 'Lr16' or 'Lr32' additional section, while the main block is
0289      * absent.
0290      *
0291      * Here we pass the callback which should be used when such
0292      * additional section is recognized.
0293      */
0294     globalInfoSection.setExtraLayerInfoBlockHandler(
0295         std::bind(&PSDLayerMaskSection::readLayerInfoImpl<psd_byte_order::psdBigEndian>, this, std::placeholders::_1));
0296 
0297     dbgFile << "Position before starting global info section:" << io.pos();
0298 
0299     globalInfoSection.read(io);
0300 
0301     if (layerMaskBlockSize) {
0302         /* put us after this section so reading the next section will work even if we mess up */
0303         io.seek(start + static_cast<qint64>(*layerMaskBlockSize));
0304     }
0305 
0306     return true;
0307 }
0308 
0309 template<psd_byte_order byteOrder>
0310 bool PSDLayerMaskSection::readGlobalMask(QIODevice &io)
0311 {
0312     quint32 globalMaskBlockLength;
0313     if (!psdread<byteOrder>(io, globalMaskBlockLength)) {
0314         error = "Could not read global mask info block";
0315         return false;
0316     }
0317 
0318     dbgFile << "Global mask size:" << globalMaskBlockLength << "(" << io.pos() << io.bytesAvailable() << ")";
0319 
0320     if (globalMaskBlockLength > 0) {
0321         if (!psdread<byteOrder>(io, globalLayerMaskInfo.overlayColorSpace)) {
0322             error = "Could not read global mask info overlay colorspace";
0323             return false;
0324         }
0325 
0326         for (int i = 0; i < 4; ++i) {
0327             if (!psdread<byteOrder>(io, globalLayerMaskInfo.colorComponents[i])) {
0328                 error = QString("Could not read mask info visualizaion color component %1").arg(i);
0329                 return false;
0330             }
0331         }
0332 
0333         if (!psdread<byteOrder>(io, globalLayerMaskInfo.opacity)) {
0334             error = "Could not read global mask info visualization opacity";
0335             return false;
0336         }
0337 
0338         if (!psdread<byteOrder>(io, globalLayerMaskInfo.kind)) {
0339             error = "Could not read global mask info visualization type";
0340             return false;
0341         }
0342 
0343         dbgFile << "Global mask info: ";
0344         dbgFile << "\tOverlay:" << globalLayerMaskInfo.overlayColorSpace; // 0
0345         dbgFile << "\tColor components:" << globalLayerMaskInfo.colorComponents[0] // 65535
0346                 << globalLayerMaskInfo.colorComponents[1] // 0
0347                 << globalLayerMaskInfo.colorComponents[2] // 0
0348                 << globalLayerMaskInfo.colorComponents[3]; // 0
0349         dbgFile << "\tOpacity:" << globalLayerMaskInfo.opacity; // 50
0350         dbgFile << "\tKind:" << globalLayerMaskInfo.kind; // 128
0351 
0352         if (globalMaskBlockLength >= 15) {
0353             io.skip(qMax(globalMaskBlockLength - 15, 0x0U));
0354         }
0355     }
0356 
0357     return true;
0358 }
0359 
0360 template<psd_byte_order byteOrder>
0361 bool PSDLayerMaskSection::readTiffImpl(QIODevice &io)
0362 {
0363     dbgFile << "(TIFF) reading layer section. Pos:" << io.pos() << "bytes left:" << io.bytesAvailable();
0364 
0365     // TIFF additional sections
0366 
0367     /**
0368      * Just like PSD, new versions of PSD have layers info block wrapped into
0369      * 'Lr16' or 'Lr32' additional section, while the main block is
0370      * absent.
0371      * Additionally, the global mask info is stored in a separate "LMsk" block.
0372      *
0373      * So, instead of having special handling, we just ship everything to the
0374      * additional layer info block handlers
0375      */
0376 
0377     globalInfoSection.setExtraLayerInfoBlockHandler(std::bind(&PSDLayerMaskSection::readLayerInfoImpl<byteOrder>, this, std::placeholders::_1));
0378     globalInfoSection.setUserMaskInfoBlockHandler(std::bind(&PSDLayerMaskSection::readGlobalMask<byteOrder>, this, std::placeholders::_1));
0379 
0380     if (!globalInfoSection.read(io)) {
0381         dbgFile << "Failed to read TIFF Photoshop blocks!";
0382         return false;
0383     }
0384 
0385     dbgFile << "Leftover data after parsing layer/extra blocks:" << io.pos() << io.bytesAvailable() << io.peek(io.bytesAvailable());
0386 
0387     return true;
0388 }
0389 
0390 struct FlattenedNode {
0391     FlattenedNode()
0392         : type(RASTER_LAYER)
0393     {
0394     }
0395 
0396     KisNodeSP node;
0397 
0398     enum Type { RASTER_LAYER, FOLDER_OPEN, FOLDER_CLOSED, SECTION_DIVIDER };
0399 
0400     Type type;
0401 };
0402 
0403 void addBackgroundIfNeeded(KisNodeSP root, QList<FlattenedNode> &nodes)
0404 {
0405     KisGroupLayer *group = dynamic_cast<KisGroupLayer *>(root.data());
0406     if (!group)
0407         return;
0408 
0409     KoColor projectionColor = group->defaultProjectionColor();
0410     if (projectionColor.opacityU8() == OPACITY_TRANSPARENT_U8)
0411         return;
0412 
0413     KisPaintLayerSP layer = new KisPaintLayer(group->image(), i18nc("Automatically created layer name when saving into PSD", "Background"), OPACITY_OPAQUE_U8);
0414 
0415     layer->paintDevice()->setDefaultPixel(projectionColor);
0416 
0417     {
0418         FlattenedNode item;
0419         item.node = layer;
0420         item.type = FlattenedNode::RASTER_LAYER;
0421         nodes << item;
0422     }
0423 }
0424 
0425 void flattenNodes(KisNodeSP node, QList<FlattenedNode> &nodes)
0426 {
0427     KisNodeSP child = node->firstChild();
0428     while (child) {
0429         const bool isLayer = child->inherits("KisLayer");
0430         const bool isGroupLayer = child->inherits("KisGroupLayer");
0431 
0432         if (isGroupLayer) {
0433             {
0434                 FlattenedNode item;
0435                 item.node = child;
0436                 item.type = FlattenedNode::SECTION_DIVIDER;
0437                 nodes << item;
0438             }
0439 
0440             flattenNodes(child, nodes);
0441 
0442             {
0443                 FlattenedNode item;
0444                 item.node = child;
0445                 item.type = FlattenedNode::FOLDER_OPEN;
0446                 nodes << item;
0447             }
0448         } else if (isLayer) {
0449             FlattenedNode item;
0450             item.node = child;
0451             item.type = FlattenedNode::RASTER_LAYER;
0452             nodes << item;
0453         }
0454 
0455         child = child->nextSibling();
0456     }
0457 }
0458 
0459 KisNodeSP findOnlyTransparencyMask(KisNodeSP node, FlattenedNode::Type type)
0460 {
0461     if (type != FlattenedNode::FOLDER_OPEN && type != FlattenedNode::FOLDER_CLOSED && type != FlattenedNode::RASTER_LAYER) {
0462         return 0;
0463     }
0464 
0465     KisLayer *layer = qobject_cast<KisLayer *>(node.data());
0466     QList<KisEffectMaskSP> masks = layer->effectMasks();
0467 
0468     if (masks.size() != 1)
0469         return 0;
0470 
0471     KisEffectMaskSP onlyMask = masks.first();
0472     return onlyMask->inherits("KisTransparencyMask") ? onlyMask : 0;
0473 }
0474 
0475 QDomDocument fetchLayerStyleXmlData(KisNodeSP node)
0476 {
0477     const KisLayer *layer = qobject_cast<KisLayer *>(node.data());
0478     KisPSDLayerStyleSP layerStyle = layer->layerStyle();
0479 
0480     if (!layerStyle)
0481         return QDomDocument();
0482 
0483     KisAslLayerStyleSerializer serializer;
0484     serializer.setStyles(QVector<KisPSDLayerStyleSP>() << layerStyle);
0485     return serializer.formPsdXmlDocument();
0486 }
0487 
0488 inline QDomNode findNodeByKey(const QString &key, QDomNode parent)
0489 {
0490     return KisDomUtils::findElementByAttibute(parent, "node", "key", key);
0491 }
0492 
0493 void mergePatternsXMLSection(const QDomDocument &src, QDomDocument &dst)
0494 {
0495     QDomNode srcPatternsNode = findNodeByKey(ResourceType::Patterns, src.documentElement());
0496     QDomNode dstPatternsNode = findNodeByKey(ResourceType::Patterns, dst.documentElement());
0497 
0498     if (srcPatternsNode.isNull())
0499         return;
0500     if (dstPatternsNode.isNull()) {
0501         dst = src;
0502         return;
0503     }
0504 
0505     KIS_ASSERT_RECOVER_RETURN(!srcPatternsNode.isNull());
0506     KIS_ASSERT_RECOVER_RETURN(!dstPatternsNode.isNull());
0507 
0508     QDomNode node = srcPatternsNode.firstChild();
0509     while (!node.isNull()) {
0510         QDomNode importedNode = dst.importNode(node, true);
0511         KIS_ASSERT_RECOVER_RETURN(!importedNode.isNull());
0512 
0513         dstPatternsNode.appendChild(importedNode);
0514         node = node.nextSibling();
0515     }
0516 }
0517 
0518 bool PSDLayerMaskSection::write(QIODevice &io, KisNodeSP rootLayer, psd_compression_type compressionType)
0519 {
0520     bool retval = true;
0521 
0522     try {
0523         if (m_header.tiffStyleLayerBlock) {
0524             switch (m_header.byteOrder) {
0525             case psd_byte_order::psdLittleEndian:
0526                 writeTiffImpl<psd_byte_order::psdLittleEndian>(io, rootLayer, compressionType);
0527                 break;
0528             default:
0529                 writeTiffImpl(io, rootLayer, compressionType);
0530                 break;
0531             }
0532         } else {
0533             writePsdImpl(io, rootLayer, compressionType);
0534         }
0535     } catch (KisAslWriterUtils::ASLWriteException &e) {
0536         error = PREPEND_METHOD(e.what());
0537         retval = false;
0538     }
0539 
0540     return retval;
0541 }
0542 
0543 void PSDLayerMaskSection::writePsdImpl(QIODevice &io, KisNodeSP rootLayer, psd_compression_type compressionType)
0544 {
0545     dbgFile << "Writing layer layer section";
0546 
0547     // Build the whole layer structure
0548     QList<FlattenedNode> nodes;
0549     addBackgroundIfNeeded(rootLayer, nodes);
0550     flattenNodes(rootLayer, nodes);
0551 
0552     if (nodes.isEmpty()) {
0553         throw KisAslWriterUtils::ASLWriteException("Could not find paint layers to save");
0554     }
0555 
0556     {
0557         KisAslWriterUtils::OffsetStreamPusher<quint32, psd_byte_order::psdBigEndian> layerAndMaskSectionSizeTag(io, 2);
0558         QDomDocument mergedPatternsXmlDoc;
0559 
0560         {
0561             KisAslWriterUtils::OffsetStreamPusher<quint32, psd_byte_order::psdBigEndian> layerInfoSizeTag(io, 2);
0562 
0563             {
0564                 // number of layers (negative, because krita always has alpha)
0565                 const qint16 layersSize = static_cast<qint16>(-nodes.size());
0566                 SAFE_WRITE_EX(psd_byte_order::psdBigEndian, io, layersSize);
0567 
0568                 dbgFile << "Number of layers" << layersSize << "at" << io.pos();
0569             }
0570 
0571             // Layer records section
0572             Q_FOREACH (const FlattenedNode &item, nodes) {
0573                 KisNodeSP node = item.node;
0574 
0575                 PSDLayerRecord *layerRecord = new PSDLayerRecord(m_header);
0576                 layers.append(layerRecord);
0577 
0578                 KisNodeSP onlyTransparencyMask = findOnlyTransparencyMask(node, item.type);
0579                 QRect maskRect = onlyTransparencyMask ? onlyTransparencyMask->paintDevice()->exactBounds() : QRect();
0580 
0581                 const bool nodeVisible = node->visible();
0582                 const KoColorSpace *colorSpace = node->colorSpace();
0583                 const quint8 nodeOpacity = node->opacity();
0584                 const quint8 nodeClipping = 0;
0585                 const int nodeLabelColor = node->colorLabelIndex();
0586                 const KisPaintLayer *paintLayer = qobject_cast<KisPaintLayer *>(node.data());
0587                 const bool alphaLocked = (paintLayer && paintLayer->alphaLocked());
0588                 const QString nodeCompositeOp = node->compositeOpId();
0589 
0590                 const KisGroupLayer *groupLayer = qobject_cast<KisGroupLayer *>(node.data());
0591                 const bool nodeIsPassThrough = groupLayer && groupLayer->passThroughMode();
0592 
0593                 const KisGeneratorLayer *fillLayer = qobject_cast<KisGeneratorLayer *>(node.data());
0594                 QDomDocument fillConfig;
0595                 psd_fill_type fillType = psd_fill_solid_color;
0596                 if (fillLayer) {
0597                     QString generatorName = fillLayer->filter()->name();
0598                     if (generatorName == "color") {
0599                         psd_layer_solid_color fill;
0600                         if (fill.loadFromConfig(fillLayer->filter())) {
0601                             if (node->image()) {
0602                                 fill.cs = node->image()->colorSpace();
0603                             } else {
0604                                 fill.cs = node->colorSpace();
0605                             }
0606                             fillConfig = fill.getASLXML();
0607                             fillType = psd_fill_solid_color;
0608                         }
0609                     } else if (generatorName == "gradient") {
0610                         psd_layer_gradient_fill fill;
0611                         fill.imageWidth = node->image()->width();
0612                         fill.imageHeight = node->image()->height();
0613                         if (fill.loadFromConfig(fillLayer->filter())) {
0614                             fillConfig = fill.getASLXML();
0615                             fillType = psd_fill_gradient;
0616                         }
0617                     } else if (generatorName == "pattern") {
0618 
0619                         psd_layer_pattern_fill fill;
0620                         if (fill.loadFromConfig(fillLayer->filter())) {
0621                             if (fill.pattern) {
0622                                 KisAslXmlWriter w;
0623                                 w.enterList(ResourceType::Patterns);
0624                                 QString uuid = w.writePattern("", fill.pattern);
0625                                 w.leaveList();
0626                                 mergedPatternsXmlDoc = w.document();
0627                                 fill.patternID = uuid;
0628                                 fillConfig = fill.getASLXML();
0629                                 fillType = psd_fill_pattern;
0630                             }
0631                         }
0632 
0633                     }
0634                     // And if anything else, it cannot be stored as a PSD fill layer.
0635                 }
0636 
0637                 QDomDocument stylesXmlDoc = fetchLayerStyleXmlData(node);
0638 
0639                 if (mergedPatternsXmlDoc.isNull() && !stylesXmlDoc.isNull()) {
0640                     mergedPatternsXmlDoc = stylesXmlDoc;
0641                 } else if (!mergedPatternsXmlDoc.isNull() && !stylesXmlDoc.isNull()) {
0642                     mergePatternsXMLSection(stylesXmlDoc, mergedPatternsXmlDoc);
0643                 }
0644 
0645                 bool nodeIrrelevant = false;
0646                 QString nodeName;
0647                 KisPaintDeviceSP layerContentDevice;
0648                 psd_section_type sectionType;
0649 
0650                 if (item.type == FlattenedNode::RASTER_LAYER) {
0651                     nodeIrrelevant = false;
0652                     nodeName = node->name();
0653                     layerContentDevice = onlyTransparencyMask ? node->original() : node->projection();
0654 
0655                     /**
0656                      * For fill layers we save their internal selection as a separate transparency mask
0657                      */
0658                     if (fillLayer) {
0659                         bool transparency = KisPainter::checkDeviceHasTransparency(node->paintDevice());
0660                         bool semiOpacity = node->paintDevice()->defaultPixel().opacityU8() < OPACITY_OPAQUE_U8;
0661                         if (transparency || semiOpacity) {
0662                             layerContentDevice = node->original();
0663                             onlyTransparencyMask = node;
0664                             maskRect = onlyTransparencyMask->paintDevice()->exactBounds();
0665                         }
0666                     }
0667                     sectionType = psd_other;
0668                 } else {
0669                     nodeIrrelevant = true;
0670                     nodeName = item.type == FlattenedNode::SECTION_DIVIDER ? QString("</Layer group>") : node->name();
0671                     layerContentDevice = 0;
0672                     sectionType = item.type == FlattenedNode::SECTION_DIVIDER ? psd_bounding_divider
0673                         : item.type == FlattenedNode::FOLDER_OPEN             ? psd_open_folder
0674                                                                               : psd_closed_folder;
0675                 }
0676 
0677                 // === no access to node anymore
0678 
0679                 QRect layerRect;
0680 
0681                 if (layerContentDevice) {
0682                     QRect rc = layerContentDevice->exactBounds();
0683                     rc = rc.normalized();
0684 
0685                     // keep to the max of photoshop's capabilities
0686                     if (rc.width() > 30000)
0687                         rc.setWidth(30000);
0688                     if (rc.height() > 30000)
0689                         rc.setHeight(30000);
0690 
0691                     layerRect = rc;
0692                 }
0693 
0694                 layerRecord->top = layerRect.y();
0695                 layerRecord->left = layerRect.x();
0696                 layerRecord->bottom = layerRect.y() + layerRect.height();
0697                 layerRecord->right = layerRect.x() + layerRect.width();
0698 
0699                 // colors + alpha channel
0700                 // note: transparency mask not included
0701                 layerRecord->nChannels = static_cast<quint16>(colorSpace->colorChannelCount() + 1);
0702 
0703                 ChannelInfo *info = new ChannelInfo;
0704                 info->channelId = -1; // For the alpha channel, which we always have in Krita, and should be saved first in
0705                 layerRecord->channelInfoRecords << info;
0706 
0707                 // the rest is in display order: rgb, cmyk, lab...
0708                 for (qint16 i = 0; i < (int)colorSpace->colorChannelCount(); ++i) {
0709                     info = new ChannelInfo;
0710                     info->channelId = i; // 0 for red, 1 = green, etc
0711                     layerRecord->channelInfoRecords << info;
0712                 }
0713 
0714                 layerRecord->blendModeKey = composite_op_to_psd_blendmode(nodeCompositeOp);
0715                 layerRecord->isPassThrough = nodeIsPassThrough;
0716                 layerRecord->opacity = nodeOpacity;
0717                 layerRecord->clipping = nodeClipping;
0718 
0719                 layerRecord->labelColor = nodeLabelColor;
0720 
0721                 layerRecord->transparencyProtected = alphaLocked;
0722                 layerRecord->visible = nodeVisible;
0723                 layerRecord->irrelevant = nodeIrrelevant;
0724 
0725                 layerRecord->layerName = nodeName.isEmpty() ? i18n("Unnamed Layer") : nodeName;
0726 
0727                 layerRecord->fillType = fillType;
0728                 layerRecord->fillConfig = fillConfig;
0729 
0730                 layerRecord->write(io, layerContentDevice, onlyTransparencyMask, maskRect, sectionType, stylesXmlDoc, node->inherits("KisGroupLayer"));
0731             }
0732 
0733             dbgFile << "start writing layer pixel data" << io.pos();
0734 
0735             // Now save the pixel data
0736             for (PSDLayerRecord *layerRecord : layers) {
0737                 layerRecord->writePixelData(io, compressionType);
0738             }
0739         }
0740 
0741         {
0742             // write the global layer mask info -- which is empty
0743             const quint32 globalMaskSize = 0;
0744             SAFE_WRITE_EX(psd_byte_order::psdBigEndian, io, globalMaskSize);
0745         }
0746 
0747         globalInfoSection.writePattBlockEx(io, mergedPatternsXmlDoc);
0748     }
0749 }
0750 
0751 template<psd_byte_order byteOrder>
0752 void PSDLayerMaskSection::writeTiffImpl(QIODevice &io, KisNodeSP rootLayer, psd_compression_type compressionType)
0753 {
0754     dbgFile << "(TIFF) Writing layer section";
0755 
0756     // Build the whole layer structure
0757     QList<FlattenedNode> nodes;
0758     addBackgroundIfNeeded(rootLayer, nodes);
0759     flattenNodes(rootLayer, nodes);
0760 
0761     if (nodes.isEmpty()) {
0762         throw KisAslWriterUtils::ASLWriteException("Could not find paint layers to save");
0763     }
0764 
0765     {
0766         QDomDocument mergedPatternsXmlDoc;
0767 
0768         {
0769             KisAslWriterUtils::writeFixedString<byteOrder>("8BIM", io);
0770             KisAslWriterUtils::writeFixedString<byteOrder>("Layr", io);
0771 
0772             KisAslWriterUtils::OffsetStreamPusher<quint32, byteOrder> layerAndMaskSectionSizeTag(io, 4);
0773             // number of layers (negative, because krita always has alpha)
0774             const qint16 layersSize = nodes.size();
0775             SAFE_WRITE_EX(byteOrder, io, layersSize);
0776 
0777             dbgFile << "Number of layers" << layersSize << "at" << io.pos();
0778 
0779             // Layer records section
0780             for (const FlattenedNode &item : nodes) {
0781                 KisNodeSP node = item.node;
0782 
0783                 PSDLayerRecord *layerRecord = new PSDLayerRecord(m_header);
0784                 layers.append(layerRecord);
0785 
0786                 const bool nodeVisible = node->visible();
0787                 const KoColorSpace *colorSpace = node->colorSpace();
0788                 const quint8 nodeOpacity = node->opacity();
0789                 const quint8 nodeClipping = 0;
0790                 const int nodeLabelColor = node->colorLabelIndex();
0791                 const KisPaintLayer *paintLayer = qobject_cast<KisPaintLayer *>(node.data());
0792                 const bool alphaLocked = (paintLayer && paintLayer->alphaLocked());
0793                 const QString nodeCompositeOp = node->compositeOpId();
0794 
0795                 const KisGroupLayer *groupLayer = qobject_cast<KisGroupLayer *>(node.data());
0796                 const bool nodeIsPassThrough = groupLayer && groupLayer->passThroughMode();
0797 
0798                 QDomDocument stylesXmlDoc = fetchLayerStyleXmlData(node);
0799 
0800                 if (mergedPatternsXmlDoc.isNull() && !stylesXmlDoc.isNull()) {
0801                     mergedPatternsXmlDoc = stylesXmlDoc;
0802                 } else if (!mergedPatternsXmlDoc.isNull() && !stylesXmlDoc.isNull()) {
0803                     mergePatternsXMLSection(stylesXmlDoc, mergedPatternsXmlDoc);
0804                 }
0805 
0806                 bool nodeIrrelevant = false;
0807                 QString nodeName;
0808                 KisPaintDeviceSP layerContentDevice;
0809                 psd_section_type sectionType;
0810 
0811                 if (item.type == FlattenedNode::RASTER_LAYER) {
0812                     nodeIrrelevant = false;
0813                     nodeName = node->name();
0814                     layerContentDevice = node->projection();
0815                     sectionType = psd_other;
0816                 } else {
0817                     nodeIrrelevant = true;
0818                     nodeName = item.type == FlattenedNode::SECTION_DIVIDER ? QString("</Layer group>") : node->name();
0819                     layerContentDevice = 0;
0820                     sectionType = item.type == FlattenedNode::SECTION_DIVIDER ? psd_bounding_divider
0821                         : item.type == FlattenedNode::FOLDER_OPEN             ? psd_open_folder
0822                                                                               : psd_closed_folder;
0823                 }
0824 
0825                 // === no access to node anymore
0826 
0827                 QRect layerRect;
0828 
0829                 if (layerContentDevice) {
0830                     QRect rc = layerContentDevice->exactBounds();
0831                     rc = rc.normalized();
0832 
0833                     // keep to the max of photoshop's capabilities
0834                     // XXX: update this to PSB
0835                     if (rc.width() > 30000)
0836                         rc.setWidth(30000);
0837                     if (rc.height() > 30000)
0838                         rc.setHeight(30000);
0839 
0840                     layerRect = rc;
0841                 }
0842 
0843                 layerRecord->top = layerRect.y();
0844                 layerRecord->left = layerRect.x();
0845                 layerRecord->bottom = layerRect.y() + layerRect.height();
0846                 layerRecord->right = layerRect.x() + layerRect.width();
0847 
0848                 // colors + alpha channel
0849                 // note: transparency mask not included
0850                 layerRecord->nChannels = static_cast<quint16>(colorSpace->colorChannelCount() + 1);
0851 
0852                 ChannelInfo *info = new ChannelInfo;
0853                 info->channelId = -1; // For the alpha channel, which we always have in Krita, and should be saved first in
0854                 layerRecord->channelInfoRecords << info;
0855 
0856                 // the rest is in display order: rgb, cmyk, lab...
0857                 for (quint32 i = 0; i < colorSpace->colorChannelCount(); ++i) {
0858                     info = new ChannelInfo;
0859                     info->channelId = static_cast<qint16>(i); // 0 for red, 1 = green, etc
0860                     layerRecord->channelInfoRecords << info;
0861                 }
0862 
0863                 layerRecord->blendModeKey = composite_op_to_psd_blendmode(nodeCompositeOp);
0864                 layerRecord->isPassThrough = nodeIsPassThrough;
0865                 layerRecord->opacity = nodeOpacity;
0866                 layerRecord->clipping = nodeClipping;
0867 
0868                 layerRecord->transparencyProtected = alphaLocked;
0869                 layerRecord->visible = nodeVisible;
0870                 layerRecord->irrelevant = nodeIrrelevant;
0871                 layerRecord->labelColor = nodeLabelColor;
0872 
0873                 layerRecord->layerName = nodeName.isEmpty() ? i18n("Unnamed Layer") : nodeName;
0874 
0875                 layerRecord->write(io, layerContentDevice, nullptr, QRect(), sectionType, stylesXmlDoc, node->inherits("KisGroupLayer"));
0876             }
0877 
0878             dbgFile << "start writing layer pixel data" << io.pos();
0879 
0880             // Now save the pixel data
0881             for (PSDLayerRecord *layerRecord : layers) {
0882                 layerRecord->writePixelData(io, compressionType);
0883             }
0884         }
0885 
0886         // {
0887         //     // write the global layer mask info -- which is NOT empty but fixed
0888         //     KisAslWriterUtils::writeFixedString<byteOrder>("8BIM", io);
0889         //     KisAslWriterUtils::writeFixedString<byteOrder>("LMsk", io);
0890 
0891         //     KisAslWriterUtils::OffsetStreamPusher<quint32, byteOrder> layerAndMaskSectionSizeTag(io, 4);
0892         //     // https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577411_22664
0893         //     psdwrite<byteOrder>(io, quint16(0));     // CS: RGB
0894         //     psdwrite<byteOrder>(io, quint16(65535)); // Pure red verification
0895         //     psdwrite<byteOrder>(io, quint16(0));
0896         //     psdwrite<byteOrder>(io, quint16(0));
0897         //     psdwrite<byteOrder>(io, quint16(0));
0898         //     psdwrite<byteOrder>(io, quint16(50)); // opacity
0899         //     psdwrite<byteOrder>(io, quint16(128)); // kind
0900         // }
0901 
0902         globalInfoSection.writePattBlockEx(io, mergedPatternsXmlDoc);
0903     }
0904 }