From 002149a899bc91ff0b9b7882f659494b3f228835 Mon Sep 17 00:00:00 2001 From: Kevin Mihelich Date: Thu, 30 Apr 2015 20:45:20 +0000 Subject: [PATCH] extra/calligra to 2.9.3-3 --- extra/calligra/PKGBUILD | 11 +- extra/calligra/krita_psd2.patch | 754 ++++++++++++++++++++++++++++++++ 2 files changed, 762 insertions(+), 3 deletions(-) create mode 100644 extra/calligra/krita_psd2.patch diff --git a/extra/calligra/PKGBUILD b/extra/calligra/PKGBUILD index c2d3a94b7..4c59d6a93 100644 --- a/extra/calligra/PKGBUILD +++ b/extra/calligra/PKGBUILD @@ -5,6 +5,7 @@ # ALARM: Kevin Mihelich # - removed makedepend on vc - not for ARM +# - temporary source change for canceled 2.9.3 release pkgbase=calligra pkgname=('calligra-braindump' @@ -24,7 +25,7 @@ pkgname=('calligra-braindump' 'calligra-stage' 'calligra-words') pkgver=2.9.3 -pkgrel=2 +pkgrel=3 arch=('i686' 'x86_64') url='http://www.calligra-suite.org/' license=('FDL1.2' 'GPL2' 'LGPL') @@ -34,9 +35,12 @@ makedepends=('cmake' 'automoc4' 'boost' 'kdepimlibs' 'eigen' 'kdeedu-marble' 'openjpeg' 'kdegraphics-okular' 'pstoedit' 'libvisio' 'libetonyek' 'libpqxx' 'libspnav' 'postgresql') # 'libqgit2' groups=('calligra') -source=("http://download.kde.org/stable/${pkgbase}-${pkgver}/${pkgbase}-${pkgver}.tar.xz" 'krita_psd.patch') +#source=("http://download.kde.org/stable/${pkgbase}-${pkgver}/${pkgbase}-${pkgver}.tar.xz" +source=("http://fossies.org/linux/misc/calligra-${pkgver}.tar.gz" + 'krita_psd.patch' 'krita_psd2.patch') md5sums=('9242b44eeeb7f13f72aeafb8e9365c07' - '7f90c54dc15bfeaf14c58e74f3f4aae7') + '7f90c54dc15bfeaf14c58e74f3f4aae7' + 'ed427b5a854d554e4028422fa03082aa') prepare() { mkdir build @@ -44,6 +48,7 @@ prepare() { cd $pkgbase-$pkgver # fix loading PSD files in Krita patch -p1 -i "$srcdir"/krita_psd.patch + patch -p1 -l -i "$srcdir"/krita_psd2.patch } build() { diff --git a/extra/calligra/krita_psd2.patch b/extra/calligra/krita_psd2.patch new file mode 100644 index 000000000..691c722d7 --- /dev/null +++ b/extra/calligra/krita_psd2.patch @@ -0,0 +1,754 @@ +From 039b58067e06eece1cc0c2788151b4a761847794 Mon Sep 17 00:00:00 2001 +From: Dmitry Kazakov +Date: Wed, 29 Apr 2015 18:20:23 +0300 +Subject: [PATCH] Properly fix PsdAdditionalLayerInfoBlock + +This patch ports PsdAdditionalLayerInfoBlock class into ASL framework +so that all the offsets will be correct all the time. + +Also parse lfx2 section into XML as a bonus :) +--- + krita/libpsd/CMakeLists.txt | 1 + + krita/libpsd/asl/kis_asl_reader.cpp | 138 ++++++------------- + krita/libpsd/asl/kis_asl_reader.h | 1 + + krita/libpsd/asl/kis_asl_reader_utils.cpp | 73 ++++++++++ + krita/libpsd/asl/kis_asl_reader_utils.h | 122 +++++++++++++++++ + krita/libpsd/asl/kis_asl_writer_utils.h | 2 +- + .../psd/psd_additional_layer_info_block.cpp | 147 ++++++++++----------- + .../formats/psd/psd_additional_layer_info_block.h | 3 + + krita/plugins/formats/psd/tests/CMakeLists.txt | 6 +- + .../formats/psd/tests/data/testing_psd_ls.psd | Bin 0 -> 272169 bytes + krita/plugins/formats/psd/tests/kis_psd_test.cpp | 17 +++ + krita/plugins/formats/psd/tests/kis_psd_test.h | 1 + + 12 files changed, 332 insertions(+), 179 deletions(-) + create mode 100644 krita/libpsd/asl/kis_asl_reader_utils.cpp + create mode 100644 krita/libpsd/asl/kis_asl_reader_utils.h + create mode 100644 krita/plugins/formats/psd/tests/data/testing_psd_ls.psd + +diff --git a/krita/libpsd/CMakeLists.txt b/krita/libpsd/CMakeLists.txt +index c0beca3..ca3c48b 100644 +--- a/krita/libpsd/CMakeLists.txt ++++ b/krita/libpsd/CMakeLists.txt +@@ -7,6 +7,7 @@ set(libkispsd_LIB_SRCS + psd_pattern.cpp + + asl/kis_asl_reader.cpp ++ asl/kis_asl_reader_utils.cpp + asl/kis_asl_xml_parser.cpp + asl/kis_asl_object_catcher.cpp + asl/kis_asl_callback_object_catcher.cpp +diff --git a/krita/libpsd/asl/kis_asl_reader.cpp b/krita/libpsd/asl/kis_asl_reader.cpp +index 93afef4..4ae7a68 100644 +--- a/krita/libpsd/asl/kis_asl_reader.cpp ++++ b/krita/libpsd/asl/kis_asl_reader.cpp +@@ -33,103 +33,11 @@ + #include "kis_offset_on_exit_verifier.h" + + #include "kis_asl_writer_utils.h" +- +-namespace Private { +- +-/** +- * Default value for variabled read from a file +- */ +-#define GARBAGE_VALUE_MARK 999 ++#include "kis_asl_reader_utils.h" + + +-/** +- * Exception that is emitted when any parse error appear. +- * Thanks to KisOffsetOnExitVerifier parsing can be continued +- * most of the time, based on the offset values written in PSD. +- */ +- +-struct ASLParseException : public std::runtime_error +-{ +- ASLParseException(const QString &msg) +- : std::runtime_error(msg.toAscii().data()) +- { +- } +-}; +- +-#define SAFE_READ_EX(device, varname) \ +- if (!psdread(device, &varname)) { \ +- QString msg = QString("Failed to read \'%1\' tag!").arg(#varname); \ +- throw ASLParseException(msg); \ +- } +- +-#define SAFE_READ_SIGNATURE_EX(device, varname, expected) \ +- if (!psdread(device, &varname) || varname != expected) { \ +- QString msg = QString("Failed to check signature \'%1\' tag!\n" \ +- "Value: \'%2\' Expected: \'%3\'") \ +- .arg(#varname).arg(varname).arg(expected); \ +- throw ASLParseException(msg); \ +- } +- +-/** +- * String fetch functions +- * +- * ASL has 4 types of strings: +- * +- * - fixed length (4 bytes) +- * - variable length (length (4 bytes) + string (var)) +- * - pascal (length (1 byte) + string (var)) +- * - unicode string (length (4 bytes) + null-terminated unicode string (var) +- */ +- +-QString readStringCommon(QIODevice *device, int length) +-{ +- QByteArray data; +- data.resize(length); +- qint64 dataRead = device->read(data.data(), length); +- +- if (dataRead != length) { +- QString msg = +- QString("Failed to read a string! " +- "Bytes read: %1 Expected: %2") +- .arg(dataRead).arg(length); +- throw ASLParseException(msg); +- } +- +- return QString(data); +-} +- +-QString readFixedString(QIODevice *device) { +- return readStringCommon(device, 4); +-} +- +-QString readVarString(QIODevice *device) { +- quint32 length = 0; +- SAFE_READ_EX(device, length); +- +- if (!length) { +- length = 4; +- } +- +- return readStringCommon(device, length); +-} + +-QString readPascalString(QIODevice *device) { +- quint8 length = 0; +- SAFE_READ_EX(device, length); +- +- return readStringCommon(device, length); +-} +- +-QString readUnicodeString(QIODevice *device) { +- QString string; +- +- if (!psdread_unicodestring(device, string)) { +- QString msg = QString("Failed to read a unicode string!"); +- throw ASLParseException(msg); +- } +- +- return string; +-} ++namespace Private { + + /** + * Numerical fetch functions +@@ -229,6 +137,8 @@ void readChildObject(QIODevice *device, + QDomDocument *doc, + bool skipKey = false) + { ++ using namespace KisAslReaderUtils; ++ + QString key; + + if (!skipKey) { +@@ -298,6 +208,8 @@ void readDescriptor(QIODevice *device, + QDomElement *parent, + QDomDocument *doc) + { ++ using namespace KisAslReaderUtils; ++ + QString name = readUnicodeString(device); + QString classId = readVarString(device); + +@@ -318,6 +230,8 @@ void readDescriptor(QIODevice *device, + QImage readVirtualArrayList(QIODevice *device, + int numPlanes) + { ++ using namespace KisAslReaderUtils; ++ + quint32 arrayVersion = GARBAGE_VALUE_MARK; + SAFE_READ_EX(device, arrayVersion); + +@@ -479,6 +393,8 @@ qint64 readPattern(QIODevice *device, + QDomElement *parent, + QDomDocument *doc) + { ++ using namespace KisAslReaderUtils; ++ + quint32 patternSize = GARBAGE_VALUE_MARK; + SAFE_READ_EX(device, patternSize); + +@@ -577,6 +493,8 @@ qint64 readPattern(QIODevice *device, + + QDomDocument readFileImpl(QIODevice *device) + { ++ using namespace KisAslReaderUtils; ++ + QDomDocument doc; + QDomElement root = doc.createElement("asl"); + doc.appendChild(root); +@@ -663,9 +581,39 @@ QDomDocument KisAslReader::readFile(QIODevice *device) + + try { + doc = Private::readFileImpl(device); +- } catch (Private::ASLParseException &e) { ++ } catch (KisAslReaderUtils::ASLParseException &e) { + qWarning() << "WARNING: ASL:" << e.what(); + } + + return doc; + } ++ ++QDomDocument KisAslReader::readLfx2PsdSection(QIODevice *device) ++{ ++ QDomDocument doc; ++ ++ try { ++ { ++ quint32 objectEffectsVersion = GARBAGE_VALUE_MARK; ++ const quint32 ref = 0x00; ++ SAFE_READ_SIGNATURE_EX(device, objectEffectsVersion, ref); ++ } ++ ++ { ++ quint32 descriptorVersion = GARBAGE_VALUE_MARK; ++ const quint32 ref = 0x10; ++ SAFE_READ_SIGNATURE_EX(device, descriptorVersion, ref); ++ } ++ ++ ++ QDomElement root = doc.createElement("asl"); ++ doc.appendChild(root); ++ ++ Private::readDescriptor(device, "", &root, &doc); ++ ++ } catch (KisAslReaderUtils::ASLParseException &e) { ++ qWarning() << "WARNING: PSD: lfx2 section:" << e.what(); ++ } ++ ++ return doc; ++} +diff --git a/krita/libpsd/asl/kis_asl_reader.h b/krita/libpsd/asl/kis_asl_reader.h +index b28db5e..efe8e67 100644 +--- a/krita/libpsd/asl/kis_asl_reader.h ++++ b/krita/libpsd/asl/kis_asl_reader.h +@@ -29,6 +29,7 @@ class LIBKISPSD_EXPORT KisAslReader + { + public: + QDomDocument readFile(QIODevice *device); ++ QDomDocument readLfx2PsdSection(QIODevice *device); + }; + + #endif /* __KIS_ASL_READER_H */ +diff --git a/krita/libpsd/asl/kis_asl_reader_utils.cpp b/krita/libpsd/asl/kis_asl_reader_utils.cpp +new file mode 100644 +index 0000000..3c34aae +--- /dev/null ++++ b/krita/libpsd/asl/kis_asl_reader_utils.cpp +@@ -0,0 +1,73 @@ ++/* ++ * Copyright (c) 2015 Dmitry Kazakov ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++#include "kis_asl_reader_utils.h" ++ ++namespace KisAslReaderUtils { ++ ++QString readStringCommon(QIODevice *device, int length) ++{ ++ QByteArray data; ++ data.resize(length); ++ qint64 dataRead = device->read(data.data(), length); ++ ++ if (dataRead != length) { ++ QString msg = ++ QString("Failed to read a string! " ++ "Bytes read: %1 Expected: %2") ++ .arg(dataRead).arg(length); ++ throw ASLParseException(msg); ++ } ++ ++ return QString(data); ++} ++ ++QString readFixedString(QIODevice *device) { ++ return readStringCommon(device, 4); ++} ++ ++QString readVarString(QIODevice *device) { ++ quint32 length = 0; ++ SAFE_READ_EX(device, length); ++ ++ if (!length) { ++ length = 4; ++ } ++ ++ return readStringCommon(device, length); ++} ++ ++QString readPascalString(QIODevice *device) { ++ quint8 length = 0; ++ SAFE_READ_EX(device, length); ++ ++ return readStringCommon(device, length); ++} ++ ++QString readUnicodeString(QIODevice *device) { ++ QString string; ++ ++ if (!psdread_unicodestring(device, string)) { ++ QString msg = QString("Failed to read a unicode string!"); ++ throw ASLParseException(msg); ++ } ++ ++ return string; ++} ++ ++} +diff --git a/krita/libpsd/asl/kis_asl_reader_utils.h b/krita/libpsd/asl/kis_asl_reader_utils.h +new file mode 100644 +index 0000000..0f2f2b6 +--- /dev/null ++++ b/krita/libpsd/asl/kis_asl_reader_utils.h +@@ -0,0 +1,122 @@ ++/* ++ * Copyright (c) 2015 Dmitry Kazakov ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ++ */ ++ ++#ifndef __KIS_ASL_READER_UTILS_H ++#define __KIS_ASL_READER_UTILS_H ++ ++#include "psd_utils.h" ++ ++#include ++#include ++ ++#include ++ ++/** ++ * Default value for variable read from a file ++ */ ++ ++#define GARBAGE_VALUE_MARK 999 ++ ++namespace KisAslReaderUtils { ++ ++/** ++ * Exception that is emitted when any parse error appear. ++ * Thanks to KisOffsetOnExitVerifier parsing can be continued ++ * most of the time, based on the offset values written in PSD. ++ */ ++ ++struct LIBKISPSD_EXPORT ASLParseException : public std::runtime_error ++{ ++ ASLParseException(const QString &msg) ++ : std::runtime_error(msg.toAscii().data()) ++ { ++ } ++}; ++ ++} ++ ++#define SAFE_READ_EX(device, varname) \ ++ if (!psdread(device, &varname)) { \ ++ QString msg = QString("Failed to read \'%1\' tag!").arg(#varname); \ ++ throw KisAslReaderUtils::ASLParseException(msg); \ ++ } ++ ++#define SAFE_READ_SIGNATURE_EX(device, varname, expected) \ ++ if (!psdread(device, &varname) || varname != expected) { \ ++ QString msg = QString("Failed to check signature \'%1\' tag!\n" \ ++ "Value: \'%2\' Expected: \'%3\'") \ ++ .arg(#varname).arg(varname).arg(expected); \ ++ throw KisAslReaderUtils::ASLParseException(msg); \ ++ } ++ ++#define SAFE_READ_SIGNATURE_2OPS_EX(device, varname, expected1, expected2) \ ++ if (!psdread(device, &varname) || (varname != expected1 && varname != expected2)) { \ ++ QString msg = QString("Failed to check signature \'%1\' tag!\n" \ ++ "Value: \'%2\' Expected1: \'%3\' Expected2: \'%4\'") \ ++ .arg(#varname).arg(varname).arg(expected1).arg(expected2); \ ++ throw KisAslReaderUtils::ASLParseException(msg); \ ++ } ++ ++template ++inline bool TRY_READ_SIGNATURE_2OPS_EX(QIODevice *device, T expected1, T expected2) ++{ ++ T var; ++ ++ qint64 bytesRead = device->peek((char*)&var, sizeof(T)); ++ if (bytesRead != sizeof(T)) { ++ return false; ++ } ++ ++ var = qFromBigEndian(var); ++ ++ bool result = var == expected1 || var == expected2; ++ ++ // If read successfully, adjust current position of the io device ++ ++ if (result) { ++ // read, not seek, to support sequential devices ++ bytesRead = device->read((char*)&var, sizeof(T)); ++ if (bytesRead != sizeof(T)) { ++ return false; ++ } ++ } ++ ++ return result; ++} ++ ++namespace KisAslReaderUtils { ++ ++/** ++ * String fetch functions ++ * ++ * ASL has 4 types of strings: ++ * ++ * - fixed length (4 bytes) ++ * - variable length (length (4 bytes) + string (var)) ++ * - pascal (length (1 byte) + string (var)) ++ * - unicode string (length (4 bytes) + null-terminated unicode string (var) ++ */ ++ ++LIBKISPSD_EXPORT QString readFixedString(QIODevice *device); ++LIBKISPSD_EXPORT QString readVarString(QIODevice *device); ++LIBKISPSD_EXPORT QString readPascalString(QIODevice *device); ++LIBKISPSD_EXPORT QString readUnicodeString(QIODevice *device); ++ ++} ++ ++#endif /* __KIS_ASL_READER_UTILS_H */ +diff --git a/krita/libpsd/asl/kis_asl_writer_utils.h b/krita/libpsd/asl/kis_asl_writer_utils.h +index 58419e5..00b480a 100644 +--- a/krita/libpsd/asl/kis_asl_writer_utils.h ++++ b/krita/libpsd/asl/kis_asl_writer_utils.h +@@ -34,7 +34,7 @@ namespace KisAslWriterUtils { + /** + * Exception that is emitted when any write error appear. + */ +-struct ASLWriteException : public std::runtime_error ++struct LIBKISPSD_EXPORT ASLWriteException : public std::runtime_error + { + ASLWriteException(const QString &msg) + : std::runtime_error(msg.toAscii().data()) +diff --git a/krita/plugins/formats/psd/psd_additional_layer_info_block.cpp b/krita/plugins/formats/psd/psd_additional_layer_info_block.cpp +index b3eaa52..3c7c11d 100644 +--- a/krita/plugins/formats/psd/psd_additional_layer_info_block.cpp ++++ b/krita/plugins/formats/psd/psd_additional_layer_info_block.cpp +@@ -18,9 +18,12 @@ + + #include "psd_additional_layer_info_block.h" + +-#include ++#include + +-#include "psd_utils.h" ++#include ++ ++#include ++#include + + + PsdAdditionalLayerInfoBlock::PsdAdditionalLayerInfoBlock() +@@ -29,6 +32,22 @@ PsdAdditionalLayerInfoBlock::PsdAdditionalLayerInfoBlock() + + bool PsdAdditionalLayerInfoBlock::read(QIODevice *io) + { ++ bool result = true; ++ ++ try { ++ readImpl(io); ++ } catch (KisAslReaderUtils::ASLParseException &e) { ++ error = e.what(); ++ result = false; ++ } ++ ++ return result; ++} ++ ++void PsdAdditionalLayerInfoBlock::readImpl(QIODevice* io) ++{ ++ using namespace KisAslReaderUtils; ++ + QStringList longBlocks; + if (m_header.version > 1) { + longBlocks << "LMsk" << "Lr16" << "Layr" << "Mt16" << "Mtrn" << "Alph"; +@@ -36,48 +55,36 @@ bool PsdAdditionalLayerInfoBlock::read(QIODevice *io) + + while (!io->atEnd()) { + +- // read all the additional layer info 8BIM blocks +- QByteArray b; +- b = io->peek(4); +- if (b.size() != 4 || QString(b) != "8BIM") { +- error = "No 8BIM marker for additional layer info block"; +- return true; +- } +- else { +- io->seek(io->pos() + 4); // skip the 8BIM header we peeked ahead for ++ { ++ const quint32 refSignature1 = 0x3842494D; // '8BIM' in little-endian ++ const quint32 refSignature2 = 0x38423634; // '8B64' in little-endian ++ if (!TRY_READ_SIGNATURE_2OPS_EX(io, refSignature1, refSignature2)) { ++ break; ++ } + } + +- QString key(io->read(4)); +- if (key.size() != 4) { +- error = "Could not read key for additional layer info block"; +- return false; +- } ++ QString key = readFixedString(io); + dbgFile << "found info block with key" << key; +- if (keys.contains(key)) { +- error = "Found duplicate entry for key "; +- continue; +- } +- keys << key; + +- quint64 size; ++ quint64 blockSize = GARBAGE_VALUE_MARK; + if (longBlocks.contains(key)) { +- psdread(io, &size); +- } +- else { +- quint32 _size; +- psdread(io, &_size); +- size = _size; ++ SAFE_READ_EX(io, blockSize); ++ } else { ++ quint32 size32; ++ SAFE_READ_EX(io, size32); ++ blockSize = size32; + } + +- QByteArray data = io->read(size); +- if (data.size() != (qint64)size) { +- error = QString("Could not read full info block for key %1.").arg(key); +- return false; +- } ++ // offset verifier will correct the position on the exit from ++ // current namespace, including 'continue', 'return' and ++ // exceptions. ++ SETUP_OFFSET_VERIFIER(infoBlockEndVerifier, io, blockSize, 0); + +- dbgFile << "\tRead layer info block" << key << "for size" << data.size(); +- QBuffer buf(&data); +- buf.open(QBuffer::ReadOnly); ++ if (keys.contains(key)) { ++ error = "Found duplicate entry for key "; ++ continue; ++ } ++ keys << key; + + if (key == "SoCo") { + +@@ -140,47 +147,23 @@ bool PsdAdditionalLayerInfoBlock::read(QIODevice *io) + + } + else if (key == "lrFX") { +-// if (!psdread(&buf, &layerEffects.version) || layerEffects.version != 0) { +-// dbgFile << "Layer Effect version is not zero" << layerEffects.version; +-// continue; +-// } +-// if (!psdread(&buf, &layerEffects.effects_count) +-// || layerEffects.effects_count < 6 +-// || layerEffects.effects_count > 7) { +-// dbgFile << "Wrong number of Layer Effects " << layerEffects.effects_count; +-// continue; +-// } +-// for (int i = 0; i < layerEffects.effects_count; ++i) { +-// QByteArray b; +-// b = buf.peek(4); +-// if (b.size() != 4 || QString(b) != "8BIM") { +-// error = "No 8BIM marker for lrFX block"; +-// return false; +-// } +-// else { +-// buf.seek(buf.pos() + 4); // skip the 8BIM header we peeked ahead for +-// } +-// QString tag = QString(io->read(4)); +-// if (tag.size() != 4) { +-// error = "Could not read layer effect type tag"; +-// return false; +-// } +- +-// } +- ++ // deprecated! use lfx2 instead! + } + else if (key == "tySh") { + } + else if (key == "luni") { + // get the unicode layer name +- psdread_unicodestring(&buf, unicodeLayerName); ++ unicodeLayerName = readUnicodeString(io); + dbgFile << "unicodeLayerName" << unicodeLayerName; + } + else if (key == "lyid") { + + } + else if (key == "lfx2") { ++ KisAslReader reader; ++ QDomDocument doc = reader.readLfx2PsdSection(io); + ++ //qDebug() << ppVar(doc.toString()); + } + else if (key == "Patt" || key == "Pat2" || key == "Pat3") { + +@@ -210,20 +193,27 @@ bool PsdAdditionalLayerInfoBlock::read(QIODevice *io) + + } + else if (key == "lsct") { +- quint32 type; +- if (!psdread(&buf, &type)) { +- error = "Could not read group type"; +- return false; +- } +- if (size >= 12) { +- if (!psd_read_blendmode(io, sectionDividerBlendMode)) { +- error = QString("Could not read blend mode key. Got: %1").arg(sectionDividerBlendMode); +- return false; +- } ++ quint32 dividerType = GARBAGE_VALUE_MARK; ++ SAFE_READ_EX(io, dividerType); ++ this->sectionDividerType = (psd_section_type)dividerType; ++ ++ ++ if (blockSize >= 12) { ++ quint32 lsctSignature = GARBAGE_VALUE_MARK; ++ const quint32 refSignature1 = 0x3842494D; // '8BIM' in little-endian ++ SAFE_READ_SIGNATURE_EX(io, lsctSignature, refSignature1); ++ ++ this->sectionDividerBlendMode = readFixedString(io); + } +- if (size >= 16) { +- // Don't care: animation scene group ++ ++ // Animation ++ if (blockSize >= 14) { ++ /** ++ * "I don't care ++ * I don't care, no... !" (c) ++ */ + } ++ + } + else if (key == "brst") { + +@@ -329,9 +319,6 @@ bool PsdAdditionalLayerInfoBlock::read(QIODevice *io) + } + + } +- return true; +- +- + } + + bool PsdAdditionalLayerInfoBlock::write(QIODevice */*io*/, KisNodeSP /*node*/) +diff --git a/krita/plugins/formats/psd/psd_additional_layer_info_block.h b/krita/plugins/formats/psd/psd_additional_layer_info_block.h +index 3028514..ff5a72e 100644 +--- a/krita/plugins/formats/psd/psd_additional_layer_info_block.h ++++ b/krita/plugins/formats/psd/psd_additional_layer_info_block.h +@@ -267,6 +267,9 @@ public: + psd_section_type sectionDividerType; + QString sectionDividerBlendMode; + ++private: ++ void readImpl(QIODevice* io); ++ + }; + + #endif // PSD_ADDITIONAL_LAYER_INFO_BLOCK_H +diff --git a/krita/plugins/formats/psd/tests/CMakeLists.txt b/krita/plugins/formats/psd/tests/CMakeLists.txt +index c9f32b2..8d9573b 100644 +--- a/krita/plugins/formats/psd/tests/CMakeLists.txt ++++ b/krita/plugins/formats/psd/tests/CMakeLists.txt +@@ -28,6 +28,6 @@ kde4_add_unit_test(compression_test TESTNAME krita-psd-compression_test ${compr + target_link_libraries(compression_test ${KDE4_KDEUI_LIBS} ${QT_QTTEST_LIBRARY}) + + ########### next target ############### +-#set(kis_psd_test_SRCS kis_psd_test.cpp ) +-#kde4_add_unit_test(kis_psd_test TESTNAME krita-plugins-formats-psd_test ${kis_psd_test_SRCS}) +-#target_link_libraries(kis_psd_test ${KDE4_KDEUI_LIBS} kritaui ${QT_QTTEST_LIBRARY}) ++set(kis_psd_test_SRCS kis_psd_test.cpp ) ++kde4_add_unit_test(kis_psd_test TESTNAME krita-plugins-formats-psd_test ${kis_psd_test_SRCS}) ++target_link_libraries(kis_psd_test ${KDE4_KDEUI_LIBS} kritaui ${QT_QTTEST_LIBRARY}) +diff --git a/krita/plugins/formats/psd/tests/kis_psd_test.cpp b/krita/plugins/formats/psd/tests/kis_psd_test.cpp +index c2a2900..181a6f1 100644 +--- a/krita/plugins/formats/psd/tests/kis_psd_test.cpp ++++ b/krita/plugins/formats/psd/tests/kis_psd_test.cpp +@@ -36,6 +36,23 @@ void KisPSDTest::testFiles() + TestUtil::testFiles(QString(FILES_DATA_DIR) + "/sources", QStringList()); + } + ++void KisPSDTest::testOpening() ++{ ++ QFileInfo sourceFileInfo(QString(FILES_DATA_DIR) + QDir::separator() + "testing_psd_ls.psd"); ++ ++ QScopedPointer doc(qobject_cast(KisPart::instance()->createDocument())); ++ ++ KisImportExportManager manager(doc.data()); ++ manager.setBatchMode(true); ++ ++ KisImportExportFilter::ConversionStatus status; ++ QString s = manager.importDocument(sourceFileInfo.absoluteFilePath(), QString(), ++ status); ++ qDebug() << s; ++ ++ Q_ASSERT(doc->image()); ++} ++ + QTEST_KDEMAIN(KisPSDTest, GUI) + + #include "kis_psd_test.moc" +diff --git a/krita/plugins/formats/psd/tests/kis_psd_test.h b/krita/plugins/formats/psd/tests/kis_psd_test.h +index 4773b6a..bc45a0c 100644 +--- a/krita/plugins/formats/psd/tests/kis_psd_test.h ++++ b/krita/plugins/formats/psd/tests/kis_psd_test.h +@@ -26,6 +26,7 @@ class KisPSDTest : public QObject + Q_OBJECT + private Q_SLOTS: + void testFiles(); ++ void testOpening(); + }; + + #endif +-- +2.3.7 +