void PSDUtilsTest::test_psdread_pascalstring() { QBuffer buf; QString s; QString r; // test null string buf.open(QBuffer::ReadWrite); QVERIFY(psdwrite_pascalstring(&buf, s)); buf.close(); buf.open(QBuffer::ReadOnly); psdread_pascalstring(&buf, r, 2); QCOMPARE(r, s); QVERIFY(buf.bytesAvailable() == 0); // test even string buf.close(); buf.buffer().clear(); r.clear(); buf.open(QBuffer::ReadWrite); s = QString("bl"); QVERIFY(psdwrite_pascalstring(&buf, s)); buf.close(); buf.open(QBuffer::ReadOnly); psdread_pascalstring(&buf, r, 1); QCOMPARE(r, s); QVERIFY(buf.bytesAvailable() == 0); // test uneven string buf.close(); buf.buffer().clear(); r.clear(); buf.open(QBuffer::ReadWrite); s = QString("bla"); QVERIFY(psdwrite_pascalstring(&buf, s, 2)); buf.close(); buf.open(QBuffer::ReadOnly); psdread_pascalstring(&buf, r, 2); QCOMPARE(r, s); dbgKrita << buf.bytesAvailable(); QVERIFY(buf.bytesAvailable() == 0); }
void PSDUtilsTest::test_psdwrite_pascalstring() { QBuffer buf; buf.open(QBuffer::ReadWrite); // test null string QString s; QVERIFY(psdwrite_pascalstring(&buf, s)); QCOMPARE(buf.buffer().size(), 2); QCOMPARE(buf.buffer().at(0), '\0'); QCOMPARE(buf.buffer().at(1), '\0'); buf.close(); buf.buffer().clear(); buf.open(QBuffer::ReadWrite); // test even string s = QString("bl"); QVERIFY(psdwrite_pascalstring(&buf, s)); QCOMPARE(buf.buffer().size(), 3); QCOMPARE(buf.buffer().at(0), '\2'); QCOMPARE(buf.buffer().at(1), 'b'); QCOMPARE(buf.buffer().at(2), 'l'); buf.close(); buf.buffer().clear(); buf.open(QBuffer::ReadWrite); // test uneven string s = QString("bla"); QVERIFY(psdwrite_pascalstring(&buf, s)); QCOMPARE(buf.buffer().size(), 5); QCOMPARE(buf.buffer().at(0), '\3'); QCOMPARE(buf.buffer().at(1), 'b'); QCOMPARE(buf.buffer().at(2), 'l'); QCOMPARE(buf.buffer().at(3), 'a'); QCOMPARE(buf.buffer().at(4), '\0'); }
bool PSDResourceBlock::write(QIODevice* io) const { dbgFile << "Writing Resource Block" << PSDImageResourceSection::idToString((PSDImageResourceSection::PSDResourceID)identifier) << identifier; if (resource && !resource->valid()) { error = QString("Cannot write an invalid Resource Block"); return false; } if (identifier == PSDImageResourceSection::LAYER_STATE || identifier == PSDImageResourceSection::LAYER_GROUP || identifier == PSDImageResourceSection::LAYER_COMPS || identifier == PSDImageResourceSection::LAYER_GROUP_ENABLED_ID || identifier == PSDImageResourceSection::LAYER_SELECTION_ID) { /** * We can actually handle LAYER_SELECTION_ID. It consists * of a number of layers and a list of IDs to select, which * are retrieved from 'lyid' additional layer block. */ dbgFile << "Skip writing resource block" << identifier << displayText(); return true; } QByteArray ba; // createBlock returns true by default but does not change the data. if (resource && !resource->createBlock(ba)) { error = resource->error; return false; } else if (!resource) { // reconstruct from the data QBuffer buf(&ba); buf.open(QBuffer::WriteOnly); buf.write("8BIM", 4); psdwrite(&buf, identifier); psdwrite_pascalstring(&buf, name); psdwrite(&buf, dataSize); buf.write(data); buf.close(); } if (io->write(ba.constData(), ba.size()) != ba.size()) { error = QString("Could not write complete resource"); return false; } return true; }
void PSDLayerRecord::write(QIODevice* io, KisPaintDeviceSP layerContentDevice, KisNodeSP onlyTransparencyMask, const QRect &maskRect, psd_section_type sectionType, const QDomDocument &stylesXmlDoc) { dbgFile << "writing layer info record" << "at" << io->pos(); m_layerContentDevice = layerContentDevice; m_onlyTransparencyMask = onlyTransparencyMask; m_onlyTransparencyMaskRect = maskRect; dbgFile << "saving layer record for " << layerName << "at pos" << io->pos(); dbgFile << "\ttop" << top << "left" << left << "bottom" << bottom << "right" << right << "number of channels" << nChannels; Q_ASSERT(left <= right); Q_ASSERT(top <= bottom); Q_ASSERT(nChannels > 0); try { const QRect layerRect(left, top, right - left, bottom - top); KisAslWriterUtils::writeRect(layerRect, io); { quint16 realNumberOfChannels = nChannels + bool(m_onlyTransparencyMask); SAFE_WRITE_EX(io, realNumberOfChannels); } foreach(ChannelInfo *channel, channelInfoRecords) { SAFE_WRITE_EX(io, (quint16)channel->channelId); channel->channelInfoPosition = io->pos(); // to be filled in when we know how big channel block is const quint32 fakeChannelSize = 0; SAFE_WRITE_EX(io, fakeChannelSize); } if (m_onlyTransparencyMask) { const quint16 userSuppliedMaskChannelId = -2; SAFE_WRITE_EX(io, userSuppliedMaskChannelId); m_transparencyMaskSizeOffset = io->pos(); const quint32 fakeTransparencyMaskSize = 0; SAFE_WRITE_EX(io, fakeTransparencyMaskSize); } // blend mode dbgFile << ppVar(blendModeKey) << ppVar(io->pos()); KisAslWriterUtils::writeFixedString("8BIM", io); KisAslWriterUtils::writeFixedString(blendModeKey, io); SAFE_WRITE_EX(io, opacity); SAFE_WRITE_EX(io, clipping); // unused // visibility and protection quint8 flags = 0; if (transparencyProtected) flags |= 1; if (!visible) flags |= 2; if (irrelevant) { flags |= (1 << 3) | (1 << 4); } SAFE_WRITE_EX(io, flags); { quint8 padding = 0; SAFE_WRITE_EX(io, padding); } { // extra fields with their own length tag KisAslWriterUtils::OffsetStreamPusher<quint32> extraDataSizeTag(io); if (m_onlyTransparencyMask) { { const quint32 layerMaskDataSize = 20; // support simple case only SAFE_WRITE_EX(io, layerMaskDataSize); } KisAslWriterUtils::writeRect(m_onlyTransparencyMaskRect, io); { KIS_ASSERT_RECOVER_NOOP(m_onlyTransparencyMask->paintDevice()->pixelSize() == 1); const quint8 defaultPixel = *m_onlyTransparencyMask->paintDevice()->defaultPixel(); SAFE_WRITE_EX(io, defaultPixel); } { const quint8 maskFlags = 0; // nothing serious SAFE_WRITE_EX(io, maskFlags); const quint16 padding = 0; // 2-byte padding SAFE_WRITE_EX(io, padding); } } else { const quint32 nullLayerMaskDataSize = 0; SAFE_WRITE_EX(io, nullLayerMaskDataSize); } { // blending ranges are not implemented yet const quint32 nullBlendingRangesSize = 0; SAFE_WRITE_EX(io, nullBlendingRangesSize); } // layer name: Pascal string, padded to a multiple of 4 bytes. psdwrite_pascalstring(io, layerName, 4); PsdAdditionalLayerInfoBlock additionalInfoBlock(m_header); // write 'luni' data block additionalInfoBlock.writeLuniBlockEx(io, layerName); // write 'lsct' data block if (sectionType != psd_other) { additionalInfoBlock.writeLsctBlockEx(io, sectionType, isPassThrough, blendModeKey); } // write 'lfx2' data block if (!stylesXmlDoc.isNull()) { additionalInfoBlock.writeLfx2BlockEx(io, stylesXmlDoc); } } } catch (KisAslWriterUtils::ASLWriteException &e) {