Krita Source Code Documentation
Loading...
Searching...
No Matches
KoColorSet::Private Class Reference

#include <KoColorSet_p.h>

Public Member Functions

KisSwatchGroupSP global ()
 
bool init ()
 
bool loadAcb ()
 
bool loadAco ()
 
bool loadAct ()
 
bool loadAse ()
 
bool loadCss ()
 
bool loadGpl ()
 
bool loadKpl ()
 
bool loadPsp ()
 
bool loadRiff ()
 
bool loadSbz ()
 
bool loadXml ()
 
 Private (KoColorSet *a_colorSet)
 
bool saveGpl (QIODevice *dev) const
 
bool saveKpl (QIODevice *dev) const
 

Public Attributes

KoColorSetcolorSet {0}
 
int columns
 
QString comment
 
QByteArray data
 
bool isLocked {false}
 
KoColorSet::PaletteType paletteType {UNKNOWN}
 
QList< KisSwatchGroupSPswatchGroups
 
KUndo2Stack undoStack
 

Private Member Functions

KoColorSet::PaletteType detectFormat (const QString &fileName, const QByteArray &ba)
 
const KoColorProfileloadColorProfile (QScopedPointer< KoStore > &store, const QString &path, const QString &modelId, const QString &colorDepthId)
 
bool loadKplColorset (QScopedPointer< KoStore > &store)
 
void loadKplGroup (const QDomDocument &doc, const QDomElement &parentElement, KisSwatchGroupSP group, QString version)
 
bool loadKplProfiles (QScopedPointer< KoStore > &store)
 
bool loadSbzSwatchbook (QScopedPointer< KoStore > &store)
 
bool loadScribusXmlPalette (KoColorSet *set, QXmlStreamReader *xml)
 
quint8 readByte (QIODevice *io)
 
float readFloat (QIODevice *io)
 
qint32 readInt (QIODevice *io)
 
quint16 readShort (QIODevice *io)
 
QString readUnicodeString (QIODevice *io, bool sizeIsInt=false)
 
void saveKplGroup (QDomDocument &doc, QDomElement &groupEle, const KisSwatchGroupSP group, QSet< const KoColorSpace * > &colorSetSet) const
 
void scribusParseColor (KoColorSet *set, QXmlStreamReader *xml)
 

Friends

struct AddGroupCommand
 
struct AddSwatchCommand
 
struct ChangeGroupNameCommand
 
struct ClearCommand
 
struct MoveGroupCommand
 
struct RemoveGroupCommand
 
struct RemoveSwatchCommand
 
struct SetColumnCountCommand
 
struct SetCommentCommand
 
struct SetPaletteTypeCommand
 

Detailed Description

Definition at line 27 of file KoColorSet_p.h.

Constructor & Destructor Documentation

◆ Private()

KoColorSet::Private::Private ( KoColorSet * a_colorSet)

Definition at line 1041 of file KoColorSet.cpp.

1042 : colorSet(a_colorSet)
1043{
1046 group->setName(KoColorSet::GLOBAL_GROUP_NAME);
1047 swatchGroups.clear();
1048 swatchGroups.append(group);
1049}
void setUndoLimit(int limit)
The KisSwatchGroup class stores a matrix of color swatches swatches can accessed using (x,...
KUndo2Stack undoStack
KoColorSet * colorSet
QList< KisSwatchGroupSP > swatchGroups
static const QString GLOBAL_GROUP_NAME
Definition KoColorSet.h:33

References KoColorSet::GLOBAL_GROUP_NAME, KUndo2QStack::setUndoLimit(), swatchGroups, and undoStack.

Member Function Documentation

◆ detectFormat()

KoColorSet::PaletteType KoColorSet::Private::detectFormat ( const QString & fileName,
const QByteArray & ba )
private

Definition at line 1051 of file KoColorSet.cpp.

1052{
1053 QFileInfo fi(fileName);
1054
1055 // .pal
1056 if (ba.startsWith("RIFF") && ba.indexOf("PAL data", 8)) {
1057 return KoColorSet::RIFF_PAL;
1058 }
1059 // .gpl
1060 else if (ba.startsWith("GIMP Palette")) {
1061 return KoColorSet::GPL;
1062 }
1063 // .pal
1064 else if (ba.startsWith("JASC-PAL")) {
1065 return KoColorSet::PSP_PAL;
1066 }
1067 else if (ba.contains("krita/x-colorset") || ba.contains("application/x-krita-palette")) {
1068 return KoColorSet::KPL;
1069 }
1070 else if (fi.suffix().toLower() == "aco") {
1071 return KoColorSet::ACO;
1072 }
1073 else if (fi.suffix().toLower() == "act") {
1074 return KoColorSet::ACT;
1075 }
1076 else if (fi.suffix().toLower() == "xml") {
1077 return KoColorSet::XML;
1078 }
1079 else if (fi.suffix().toLower() == "sbz") {
1080 return KoColorSet::SBZ;
1081 }
1082 else if (fi.suffix().toLower() == "ase" || ba.startsWith("ASEF")) {
1083 return KoColorSet::ASE;
1084 }
1085 else if (fi.suffix().toLower() == "acb" || ba.startsWith("8BCB")) {
1086 return KoColorSet::ACB;
1087 }
1088 else if (fi.suffix().toLower() == "css") {
1089 return KoColorSet::CSS;
1090 }
1091 return KoColorSet::UNKNOWN;
1092}

References KoColorSet::ACB, KoColorSet::ACO, KoColorSet::ACT, KoColorSet::ASE, KoColorSet::CSS, KoColorSet::GPL, KoColorSet::KPL, KoColorSet::PSP_PAL, KoColorSet::RIFF_PAL, KoColorSet::SBZ, KoColorSet::UNKNOWN, and KoColorSet::XML.

◆ global()

KisSwatchGroupSP KoColorSet::Private::global ( )
inline

Definition at line 34 of file KoColorSet_p.h.

34 {
35 Q_ASSERT(swatchGroups.size() > 0 && swatchGroups.first()->name() == GLOBAL_GROUP_NAME);
36 return swatchGroups.first();
37 }

References KoColorSet::GLOBAL_GROUP_NAME, and swatchGroups.

◆ init()

bool KoColorSet::Private::init ( )

Definition at line 1270 of file KoColorSet.cpp.

1271{
1272 // just in case this is a reload (eg by KoEditColorSetDialog),
1273 swatchGroups.clear();
1274 KisSwatchGroupSP globalGroup(new KisSwatchGroup);
1275 globalGroup->setName(KoColorSet::GLOBAL_GROUP_NAME);
1276 swatchGroups.append(globalGroup);
1277 undoStack.clear();
1278
1279 if (colorSet->filename().isNull()) {
1280 warnPigment << "Cannot load palette" << colorSet->name() << "there is no filename set";
1281 return false;
1282 }
1283 if (data.isNull()) {
1284 QFile file(colorSet->filename());
1285 if (file.size() == 0) {
1286 warnPigment << "Cannot load palette" << colorSet->name() << "there is no data available";
1287 return false;
1288 }
1289 file.open(QIODevice::ReadOnly);
1290 data = file.readAll();
1291 file.close();
1292 }
1293
1294 bool res = false;
1296 switch(paletteType) {
1297 case GPL:
1298 res = loadGpl();
1299 break;
1300 case ACT:
1301 res = loadAct();
1302 break;
1303 case RIFF_PAL:
1304 res = loadRiff();
1305 break;
1306 case PSP_PAL:
1307 res = loadPsp();
1308 break;
1309 case ACO:
1310 res = loadAco();
1311 break;
1312 case XML:
1313 res = loadXml();
1314 break;
1315 case KPL:
1316 res = loadKpl();
1317 break;
1318 case SBZ:
1319 res = loadSbz();
1320 break;
1321 case ASE:
1322 res = loadAse();
1323 break;
1324 case ACB:
1325 res = loadAcb();
1326 break;
1327 case CSS:
1328 res = loadCss();
1329 break;
1330 default:
1331 res = false;
1332 }
1333 if (paletteType != KPL) {
1334 int rowCount = global()->colorCount() / global()->columnCount();
1335 if (global()->colorCount() % global()->columnCount() > 0) {
1336 rowCount ++;
1337 }
1338 global()->setRowCount(rowCount);
1339 }
1340 colorSet->setValid(res);
1342
1343 data.clear();
1344 undoStack.clear();
1345
1346 return res;
1347}
#define warnPigment
KoColorSet::PaletteType detectFormat(const QString &fileName, const QByteArray &ba)
KoColorSet::PaletteType paletteType
KisSwatchGroupSP global()
int rowCount() const
void updateThumbnail() override
updateThumbnail updates the thumbnail for this resource. Reimplement if your thumbnail is something e...
int columnCount() const
quint32 colorCount() const
void setValid(bool valid)
QString filename
QString name

References KoColorSet::ACB, KoColorSet::ACO, KoColorSet::ACT, KoColorSet::ASE, KUndo2QStack::clear(), KoColorSet::colorCount(), KoColorSet::columnCount(), KoColorSet::CSS, KoColorSet::GLOBAL_GROUP_NAME, KoColorSet::GPL, KoColorSet::KPL, KoColorSet::paletteType(), KoColorSet::PSP_PAL, KoColorSet::RIFF_PAL, KoColorSet::rowCount(), KoColorSet::SBZ, KoColorSet::undoStack(), warnPigment, and KoColorSet::XML.

◆ loadAcb()

bool KoColorSet::Private::loadAcb ( )

Definition at line 2318 of file KoColorSet.cpp.

2319{
2320
2321 QFileInfo info(colorSet->filename());
2322
2323 QBuffer buf(&data);
2324 buf.open(QBuffer::ReadOnly);
2325
2326 QByteArray signature; // should be "8BCB";
2327 signature = buf.read(4);
2328 quint16 version = readShort(&buf);
2329 quint16 bookID = readShort(&buf);
2330 Q_UNUSED(bookID);
2331
2332 if (signature != "8BCB" && version!= 1) {
2333 return false;
2334 }
2335
2337 for (int i = 0; i< 4; i++) {
2338
2339 QString metadataString = readUnicodeString(&buf, true);
2340 if (metadataString.startsWith("\"")) {
2341 metadataString = metadataString.remove(0, 1);
2342 }
2343 if (metadataString.endsWith("\"")) {
2344 metadataString.chop(1);
2345 }
2346 if (metadataString.startsWith("$$$/")) {
2347 if (metadataString.contains("=")) {
2348 metadataString = metadataString.split("=").last();
2349 } else {
2350 metadataString = QString();
2351 }
2352 }
2353 metadata.append(metadataString);
2354 }
2355 QString title = metadata.at(0);
2356 colorSet->setName(title);
2357 QString prefix = metadata.at(1);
2358 QString postfix = metadata.at(2);
2359 QString description = metadata.at(3);
2360 colorSet->setComment(description);
2361
2362 quint16 numColors = readShort(&buf);
2363 quint16 numColumns = readShort(&buf);
2364 numColumns = numColumns > 0 ? numColumns : 8; // overwrite with sane default in case of 0
2365 colorSet->setColumnCount(numColumns);
2366 quint16 numKeyColorPage = readShort(&buf);
2367 Q_UNUSED(numKeyColorPage);
2368 quint16 colorType = readShort(&buf);
2369
2371 if (colorType == 2) {
2372 QString profileName = "U.S. Web Coated (SWOP) v2";
2374 } else if (colorType == 7) {
2376 }
2377
2378 for (quint16 i = 0; i < numColors; i++) {
2379 KisSwatch swatch;
2381 name << prefix;
2382 name << readUnicodeString(&buf, true);
2383 name << postfix;
2384 swatch.setName(name.join(" ").trimmed());
2385 QByteArray key; // should be "8BCB";
2386 key = buf.read(6);
2387 swatch.setId(QString::fromLatin1(key));
2388 swatch.setSpotColor(true);
2389 quint8 c1 = readByte(&buf);
2390 quint8 c2 = readByte(&buf);
2391 quint8 c3 = readByte(&buf);
2392 KoColor c(cs);
2393 if (colorType == 0) {
2394 c.data()[0] = c3;
2395 c.data()[1] = c2;
2396 c.data()[2] = c1;
2397 } else if (colorType == 2) {
2398 quint8 c4 = readByte(&buf);
2399 c.data()[0] = c1;
2400 c.data()[1] = c2;
2401 c.data()[2] = c3;
2402 c.data()[3] = c4;
2403 } else if (colorType == 7) {
2404 c.data()[0] = c1;
2405 c.data()[1] = c2;
2406 c.data()[2] = c3;
2407 }
2408 c.setOpacity(1.0);
2409 swatch.setColor(c);
2410 colorSet->addSwatch(swatch);
2411 }
2412
2413 return true;
2414}
const KoID Integer8BitsColorDepthID("U8", ki18n("8-bit integer/channel"))
const KoID CMYKAColorModelID("CMYKA", ki18n("CMYK/Alpha"))
const KoID LABAColorModelID("LABA", ki18n("L*a*b*/Alpha"))
void setSpotColor(bool spotColor)
Definition KisSwatch.cpp:38
void setColor(const KoColor &color)
Definition KisSwatch.cpp:32
void setId(const QString &id)
Definition KisSwatch.cpp:26
void setName(const QString &name)
Definition KisSwatch.cpp:20
quint8 readByte(QIODevice *io)
quint16 readShort(QIODevice *io)
QString readUnicodeString(QIODevice *io, bool sizeIsInt=false)
void setColumnCount(int columns)
void addSwatch(const KisSwatch &swatch, const QString &groupName=GLOBAL_GROUP_NAME, int column=-1, int row=-1)
Add a color to the palette.
void setComment(QString comment)
QString id() const
Definition KoID.cpp:63
const KoColorSpace * colorSpace(const QString &colorModelId, const QString &colorDepthId, const KoColorProfile *profile)
static KoColorSpaceRegistry * instance()
const KoColorSpace * rgb8(const QString &profileName=QString())
void setName(const QString &name)
QMap< QString, QVariant > metadata
KoResourceSignature signature() const

References CMYKAColorModelID, KoColorSpaceRegistry::colorSpace(), KoColor::data(), KoID::id(), KoColorSpaceRegistry::instance(), Integer8BitsColorDepthID, LABAColorModelID, KoResource::metadata, KoResource::name, KoColorSpaceRegistry::rgb8(), KisSwatch::setColor(), KisSwatch::setId(), KisSwatch::setName(), KoColor::setOpacity(), KisSwatch::setSpotColor(), KoResource::signature(), and KoResource::version.

◆ loadAco()

bool KoColorSet::Private::loadAco ( )

Definition at line 1814 of file KoColorSet.cpp.

1815{
1816 QFileInfo info(colorSet->filename());
1817 colorSet->setName(info.completeBaseName());
1818
1819 QBuffer buf(&data);
1820 buf.open(QBuffer::ReadOnly);
1821
1822 quint16 version = readShort(&buf);
1823 quint16 numColors = readShort(&buf);
1824 KisSwatch swatch;
1825
1826 if (version == 1 && buf.size() > 4+numColors*10) {
1827 buf.seek(4+numColors*10);
1828 version = readShort(&buf);
1829 numColors = readShort(&buf);
1830 }
1831
1832 const quint16 quint16_MAX = 65535;
1833
1835
1836 for (int i = 0; i < numColors && !buf.atEnd(); ++i) {
1837
1838 quint16 colorSpace = readShort(&buf);
1839 quint16 ch1 = readShort(&buf);
1840 quint16 ch2 = readShort(&buf);
1841 quint16 ch3 = readShort(&buf);
1842 quint16 ch4 = readShort(&buf);
1843
1844 bool skip = false;
1845 if (colorSpace == 0) { // RGB
1847 KoColor c(KoColorSpaceRegistry::instance()->rgb16(srgb));
1848 reinterpret_cast<quint16*>(c.data())[0] = ch3;
1849 reinterpret_cast<quint16*>(c.data())[1] = ch2;
1850 reinterpret_cast<quint16*>(c.data())[2] = ch1;
1851 c.setOpacity(OPACITY_OPAQUE_U8);
1852 swatch.setColor(c);
1853 }
1854 else if (colorSpace == 1) { // HSB
1855 QColor qc;
1856 qc.setHsvF(ch1 / 65536.0, ch2 / 65536.0, ch3 / 65536.0);
1857 KoColor c(qc, KoColorSpaceRegistry::instance()->rgb16());
1858 c.setOpacity(OPACITY_OPAQUE_U8);
1859 swatch.setColor(c);
1860 }
1861 else if (colorSpace == 2) { // CMYK
1863 reinterpret_cast<quint16*>(c.data())[0] = quint16_MAX - ch1;
1864 reinterpret_cast<quint16*>(c.data())[1] = quint16_MAX - ch2;
1865 reinterpret_cast<quint16*>(c.data())[2] = quint16_MAX - ch3;
1866 reinterpret_cast<quint16*>(c.data())[3] = quint16_MAX - ch4;
1867 c.setOpacity(OPACITY_OPAQUE_U8);
1868 swatch.setColor(c);
1869 }
1870 else if (colorSpace == 7) { // LAB
1872 reinterpret_cast<quint16*>(c.data())[0] = ch3;
1873 reinterpret_cast<quint16*>(c.data())[1] = ch2;
1874 reinterpret_cast<quint16*>(c.data())[2] = ch1;
1876 swatch.setColor(c);
1877 }
1878 else if (colorSpace == 8) { // GRAY
1880 reinterpret_cast<quint16*>(c.data())[0] = ch1 * (quint16_MAX / 10000);
1882 swatch.setColor(c);
1883 }
1884 else {
1885 warnPigment << "Unsupported colorspace in palette" << colorSet->filename() << "(" << colorSpace << ")";
1886 skip = true;
1887 }
1888
1889 if (version == 2) {
1890 QString name = readUnicodeString(&buf, true);
1891 swatch.setName(name);
1892 }
1893 if (!skip) {
1894 group->addSwatch(swatch);
1895 }
1896 }
1897 return true;
1898}
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const quint8 OPACITY_OPAQUE_U8
KisSwatchGroupSP getGlobalGroup() const
getGlobalGroup
virtual const KoColorProfile * profile() const =0
void setOpacity(quint8 alpha)
Definition KoColor.cpp:333
quint8 * data()
Definition KoColor.h:144
const quint16 quint16_MAX
Definition kis_global.h:25

References CMYKAColorModelID, KoColor::data(), GrayAColorModelID, KoID::id(), KoColorSpaceRegistry::instance(), Integer16BitsColorDepthID, KoResource::name, OPACITY_OPAQUE_U8, KoColorSpace::profile(), quint16_MAX, KoColorSpaceRegistry::rgb8(), KisSwatch::setColor(), KisSwatch::setName(), KoColor::setOpacity(), KoResource::version, and warnPigment.

◆ loadAct()

bool KoColorSet::Private::loadAct ( )

Definition at line 1452 of file KoColorSet.cpp.

1453{
1454 QFileInfo info(colorSet->filename());
1455 colorSet->setName(info.completeBaseName());
1456 KisSwatch swatch;
1457 int numOfTriplets = int(data.size() / 3);
1458 for (int i = 0; i < numOfTriplets * 3; i += 3) {
1459 quint8 r = data[i];
1460 quint8 g = data[i+1];
1461 quint8 b = data[i+2];
1462 swatch.setColor(KoColor(QColor(r, g, b), KoColorSpaceRegistry::instance()->rgb8()));
1463 global()->addSwatch(swatch);
1464 }
1465 return true;
1466}

References KoColorSpaceRegistry::instance(), and KisSwatch::setColor().

◆ loadAse()

bool KoColorSet::Private::loadAse ( )

Definition at line 2213 of file KoColorSet.cpp.

2214{
2215 QFileInfo info(colorSet->filename());
2216 colorSet->setName(info.completeBaseName());
2217
2218 QBuffer buf(&data);
2219 buf.open(QBuffer::ReadOnly);
2220
2221 QByteArray signature; // should be "ASEF";
2222 signature = buf.read(4);
2223 quint16 version = readShort(&buf);
2224 quint16 version2 = readShort(&buf);
2225
2226 if (signature != "ASEF" && version!= 1 && version2 != 0) {
2227 qWarning() << "incorrect header:" << signature << version << version2;
2228 return false;
2229 }
2230 qint32 numBlocks = readInt(&buf);
2231
2232 QByteArray groupStart("\xC0\x01");
2233 QByteArray groupEnd("\xC0\x02");
2234 QByteArray swatchSig("\x00\x01");
2235
2236 bool inGroup = false;
2237 QString groupName;
2238 for (qint32 i = 0; i < numBlocks; i++) {
2239 QByteArray blockType;
2240 blockType = buf.read(2);
2241 qint32 blockSize = readInt(&buf);
2242 qint64 pos = buf.pos();
2243
2244 if (blockType == groupStart) {
2245 groupName = readUnicodeString(&buf);
2246 colorSet->addGroup(groupName);
2247 inGroup = true;
2248 }
2249 else if (blockType == groupEnd) {
2250 int colorCount = colorSet->getGroup(groupName)->colorCount();
2251 int columns = colorSet->columnCount();
2252 int rows = colorCount/columns;
2253 if (colorCount % columns > 0) {
2254 rows += 1;
2255 }
2256 colorSet->getGroup(groupName)->setRowCount(rows);
2257 inGroup = false;
2258 }
2259 else /* if (blockType == swatchSig)*/ {
2260 KisSwatch swatch;
2261 swatch.setName(readUnicodeString(&buf).trimmed());
2262 QByteArray colorModel;
2263 QDomDocument doc;
2264 colorModel = buf.read(4);
2265 if (colorModel == "RGB ") {
2266 QDomElement elt = doc.createElement("sRGB");
2267
2268 elt.setAttribute("r", readFloat(&buf));
2269 elt.setAttribute("g", readFloat(&buf));
2270 elt.setAttribute("b", readFloat(&buf));
2271
2272 KoColor color = KoColor::fromXML(elt, "U8");
2273 swatch.setColor(color);
2274 } else if (colorModel == "CMYK") {
2275 QDomElement elt = doc.createElement("CMYK");
2276
2277 elt.setAttribute("c", readFloat(&buf));
2278 elt.setAttribute("m", readFloat(&buf));
2279 elt.setAttribute("y", readFloat(&buf));
2280 elt.setAttribute("k", readFloat(&buf));
2281 //try to select the default PS icc profile if possible.
2282 elt.setAttribute("space", "U.S. Web Coated (SWOP) v2");
2283
2284 KoColor color = KoColor::fromXML(elt, "U8");
2285 swatch.setColor(color);
2286 } else if (colorModel == "LAB ") {
2287 QDomElement elt = doc.createElement("Lab");
2288
2289 elt.setAttribute("L", readFloat(&buf)*100.0);
2290 elt.setAttribute("a", readFloat(&buf));
2291 elt.setAttribute("b", readFloat(&buf));
2292
2293 KoColor color = KoColor::fromXML(elt, "U16");
2294 swatch.setColor(color);
2295 } else if (colorModel == "GRAY") {
2296 QDomElement elt = doc.createElement("Gray");
2297
2298 elt.setAttribute("g", readFloat(&buf));
2299
2300 KoColor color = KoColor::fromXML(elt, "U8");
2301 swatch.setColor(color);
2302 }
2303 qint16 type = readShort(&buf);
2304 if (type == 1) { //0 is global, 2 is regular;
2305 swatch.setSpotColor(true);
2306 }
2307 if (inGroup) {
2308 colorSet->addSwatch(swatch, groupName);
2309 } else {
2310 colorSet->addSwatch(swatch);
2311 }
2312 }
2313 buf.seek(pos + qint64(blockSize));
2314 }
2315 return true;
2316}
float readFloat(QIODevice *io)
qint32 readInt(QIODevice *io)
KisSwatchGroupSP getGroup(const QString &name) const
getGroup
void addGroup(const QString &groupName, int columnCount=KisSwatchGroup::DEFAULT_COLUMN_COUNT, int rowCount=KisSwatchGroup::DEFAULT_ROW_COUNT)
addGroup Adds a new group.
static KoColor fromXML(const QDomElement &elt, const QString &channelDepthId)
Definition KoColor.cpp:350
QString trimmed(const QString &string)

References KoColorSet::colorCount(), KoColor::fromXML(), KisSwatch::setColor(), KisSwatch::setName(), KisSwatch::setSpotColor(), KoResource::signature(), and KoResource::version.

◆ loadColorProfile()

const KoColorProfile * KoColorSet::Private::loadColorProfile ( QScopedPointer< KoStore > & store,
const QString & path,
const QString & modelId,
const QString & colorDepthId )
private

Definition at line 1691 of file KoColorSet.cpp.

1695{
1696 if (!store->open(path)) {
1697 return nullptr;
1698 }
1699
1700 QByteArray bytes = store->read(store->size());
1701 store->close();
1702
1704 ->createColorProfile(modelId, colorDepthId, bytes);
1705 if (!profile || !profile->valid()) {
1706 return nullptr;
1707 }
1708
1710 return profile;
1711}
virtual bool valid() const =0
const KoColorProfile * createColorProfile(const QString &colorModelId, const QString &colorDepthId, const QByteArray &rawData)
void addProfile(KoColorProfile *profile)

References KoColorSpaceRegistry::addProfile(), KoColorSpaceRegistry::createColorProfile(), KoColorSpaceRegistry::instance(), and KoColorProfile::valid().

◆ loadCss()

bool KoColorSet::Private::loadCss ( )

Definition at line 1531 of file KoColorSet.cpp.

1532{
1533 QFileInfo info(colorSet->filename());
1534 colorSet->setName(info.completeBaseName());
1535
1536 QString text = readAllLinesSafe(&data).join("").replace("\t", "").replace(" ", "");
1537
1538 QRegularExpression re("/\\*.*?\\*/");
1539
1540 text.remove(re); // Remove comments
1541
1542 KisSwatch swatch;
1543
1544 // Regex to detect a color in the palette
1545 QRegularExpression palette("(.*?){(?:[^:;]+:[^;]+;)*?color:(.*?)(?:;.*?)*?}");
1546
1547 QRegularExpressionMatchIterator colors = palette.globalMatch(text);
1548
1549 if (!colors.hasNext()) {
1550 warnPigment << "No color found in CSS palette : " << colorSet->filename();
1551 return false;
1552 }
1553
1554 while (colors.hasNext()) {
1555 QRegularExpressionMatch match = colors.next();
1556 QString colorInfo = match.captured();
1557 QString colorName = match.captured(1);
1558 QString colorValue = match.captured(2);
1559
1560 if (!colorInfo.startsWith(".") || colorValue.isEmpty()) {
1561 warnPigment << "Illegal CSS palette syntax : " << colorInfo;
1562 return false;
1563 }
1564
1565 QColor qColor;
1566
1567 colorName.remove(".");
1568 swatch.setName(colorName);
1569
1570 if (colorValue.startsWith("rgb")) {
1571 QStringList color;
1572
1573 if (colorValue.startsWith("rgba")) {
1574 colorValue.remove("rgba(").remove(")");
1575 color = colorValue.split(",");
1576
1577 if (color.size() != 4) {
1578 warnPigment << "Invalid RGBA color definition : " << colorInfo;
1579 return false;
1580 }
1581
1582 int alpha = color[3].toFloat() * 255;
1583
1584 if (alpha < 0 || alpha > 255) {
1585 warnPigment << "Invalid alpha parameter : " << colorInfo;
1586 return false;
1587 }
1588 }
1589 else {
1590 colorValue.remove("rgb(").remove(")");
1591
1592 color = colorValue.split(",");
1593
1594 if (color.size() != 3) {
1595 warnPigment << "Invalid RGB color definition : " << colorInfo;
1596 return false;
1597 }
1598 }
1599
1600 int rgb[3];
1601
1602 for (int i = 0; i < 3; i++) {
1603 if (color[i].endsWith("%")) {
1604 color[i].replace("%", "");
1605 rgb[i] = color[i].toFloat() / 100 * 255 ;
1606 }
1607 else {
1608 rgb[i] = color[i].toInt();
1609 };
1610 }
1611
1612 qColor = QColor(rgb[0], rgb[1], rgb[2]);
1613 }
1614 else if (colorValue.startsWith("hsl")) {
1615 QStringList color;
1616
1617 if (colorValue.startsWith("hsla")) {
1618 colorValue.remove("hsla(").remove(")").replace("%", "");
1619 color = colorValue.split(",");
1620 if (color.size() != 4) {
1621 warnPigment << "Invalid HSLA color definition : " << colorInfo;
1622 return false;
1623 }
1624
1625 float alpha = color[3].toFloat();
1626
1627 if (alpha < 0.0 || alpha > 1.0) {
1628 warnPigment << "Invalid alpha parameter : " << colorInfo;
1629 return false;
1630 }
1631
1632 }
1633 else {
1634 colorValue.remove("hsl(").remove(")").replace("%", "");
1635 color = colorValue.split(",");
1636 if (color.size() != 3) {
1637 warnPigment << "Invalid HSL color definition : " << colorInfo;
1638 return false;
1639 }
1640 }
1641
1642 float hue = color[0].toFloat() / 359;
1643 float saturation = color[1].toFloat() / 100;
1644 float lightness = color[2].toFloat() / 100;
1645
1646 if (hue < 0.0 || hue > 1.0) {
1647 warnPigment << "Invalid hue parameter : " << colorInfo;
1648 return false;
1649 }
1650
1651 if (saturation < 0.0 || saturation > 1.0) {
1652 warnPigment << "Invalid saturation parameter : " << colorInfo;
1653 return false;
1654 }
1655
1656 if (lightness < 0.0 || lightness > 1.0) {
1657 warnPigment << "Invalid lightness parameter : " << colorInfo;
1658 return false;
1659 }
1660
1661 qColor = QColor::fromHslF(hue, saturation, lightness);
1662
1663 }
1664 else if (colorValue.startsWith("#")) {
1665 if (colorValue.size() == 9) {
1666 // Convert the CSS format #RRGGBBAA to #RRGGBB
1667 // Due to QColor's 8 digits format being #AARRGGBB and that we do not load the alpha channel
1668 colorValue.truncate(7);
1669 }
1670
1671 qColor = QColor(colorValue);
1672 }
1673 else {
1674 warnPigment << "Unknown color declaration : " << colorInfo;
1675 return false;
1676 }
1677
1678 if (!qColor.isValid()) {
1679 warnPigment << "Invalid color definition : " << colorInfo;
1680 return false;
1681 }
1682
1683 swatch.setColor(KoColor(qColor, KoColorSpaceRegistry::instance()->rgb8()));
1684
1685 global()->addSwatch(swatch);
1686 }
1687
1688 return true;
1689}
rgba palette[MAX_PALETTE]
Definition palette.c:35

References KoColorSpaceRegistry::instance(), palette, KisSwatch::setColor(), KisSwatch::setName(), and warnPigment.

◆ loadGpl()

bool KoColorSet::Private::loadGpl ( )

Definition at line 1377 of file KoColorSet.cpp.

1378{
1379 if (data.isEmpty() || data.isNull() || data.length() < 50) {
1380 warnPigment << "Illegal Gimp palette file: " << colorSet->filename();
1381 return false;
1382 }
1383
1384 quint32 index = 0;
1385
1386 QStringList lines = readAllLinesSafe(&data);
1387
1388 if (lines.size() < 3) {
1389 warnPigment << "Not enough lines in palette file: " << colorSet->filename();
1390 return false;
1391 }
1392
1393 QString columnsText;
1394 qint32 r, g, b;
1395 KisSwatch swatch;
1396
1397 // Read name
1398 if (!lines[0].startsWith("GIMP") || !lines[1].toLower().contains("name")) {
1399 warnPigment << "Illegal Gimp palette file: " << colorSet->filename();
1400 return false;
1401 }
1402
1403 // translated name will be in a tooltip, here don't translate
1404 colorSet->setName(lines[1].split(":")[1].trimmed());
1405
1406 index = 2;
1407
1408 // Read columns
1409 int columns = 0;
1410 if (lines[index].toLower().contains("columns")) {
1411 columnsText = lines[index].split(":")[1].trimmed();
1412 columns = columnsText.toInt();
1414 warnPigment << "Refusing to set unreasonable number of columns (" << columns << ") in GIMP Palette file " << colorSet->filename() << " - using maximum number of allowed columns instead";
1415 global()->setColumnCount(MAXIMUM_ALLOWED_COLUMNS);
1416 }
1417 else {
1418 global()->setColumnCount(columns);
1419 }
1420 index = 3;
1421 }
1422
1423
1424 for (qint32 i = index; i < lines.size(); i++) {
1425 if (lines[i].startsWith('#')) {
1426 comment += lines[i].mid(1).trimmed() + ' ';
1427 } else if (!lines[i].isEmpty()) {
1428 QStringList a = lines[i].replace('\t', ' ').split(' ', Qt::SkipEmptyParts);
1429
1430 if (a.count() < 3) {
1431 continue;
1432 }
1433
1434 r = qBound(0, a[0].toInt(), 255);
1435 g = qBound(0, a[1].toInt(), 255);
1436 b = qBound(0, a[2].toInt(), 255);
1437
1438 swatch.setColor(KoColor(QColor(r, g, b), KoColorSpaceRegistry::instance()->rgb8()));
1439
1440 for (int i = 0; i != 3; i++) {
1441 a.pop_front();
1442 }
1443 QString name = a.join(" ");
1444 swatch.setName(name.isEmpty() || name == "Untitled" ? i18n("Untitled") : name);
1445
1446 global()->addSwatch(swatch);
1447 }
1448 }
1449 return true;
1450}
const int MAXIMUM_ALLOWED_COLUMNS
QList< KoSubpath * > split(const KoPathShape &path)
int toInt(const QString &str, bool *ok=nullptr)

References KoColorSet::comment(), KoColorSpaceRegistry::instance(), MAXIMUM_ALLOWED_COLUMNS, KoResource::name, KisSwatch::setColor(), KisSwatch::setName(), and warnPigment.

◆ loadKpl()

bool KoColorSet::Private::loadKpl ( )

Definition at line 1789 of file KoColorSet.cpp.

1790{
1791 QBuffer buf(&data);
1792 buf.open(QBuffer::ReadOnly);
1793
1794 QScopedPointer<KoStore> store(
1796 "application/x-krita-palette",
1797 KoStore::Zip));
1798 if (!store || store->bad()) {
1799 return false;
1800 }
1801
1802 if (store->hasFile("profiles.xml") && !loadKplProfiles(store)) {
1803 return false;
1804 }
1805
1806 if (!loadKplColorset(store)) {
1807 return false;
1808 }
1809
1810 buf.close();
1811 return true;
1812}
bool loadKplColorset(QScopedPointer< KoStore > &store)
bool loadKplProfiles(QScopedPointer< KoStore > &store)
@ Read
Definition KoStore.h:29
@ Zip
Definition KoStore.h:30
static KoStore * createStore(const QString &fileName, Mode mode, const QByteArray &appIdentification=QByteArray(), Backend backend=Auto, bool writeMimetype=true)
Definition KoStore.cpp:39

References KoStore::createStore(), KoStore::Read, and KoStore::Zip.

◆ loadKplColorset()

bool KoColorSet::Private::loadKplColorset ( QScopedPointer< KoStore > & store)
private

Definition at line 1747 of file KoColorSet.cpp.

1748{
1749 if (!store->open("colorset.xml")) {
1750 return false;
1751 }
1752
1753 QByteArray bytes = store->read(store->size());
1754 store->close();
1755
1756 QDomDocument doc;
1757 if (!doc.setContent(bytes)) {
1758 return false;
1759 }
1760
1761 QDomElement root = doc.documentElement();
1762 colorSet->setName(root.attribute(KPL_PALETTE_NAME_ATTR));
1763 QString version = root.attribute(KPL_VERSION_ATTR);
1764 comment = root.attribute(KPL_PALETTE_COMMENT_ATTR);
1765
1766 int desiredColumnCount = root.attribute(KPL_PALETTE_COLUMN_COUNT_ATTR).toInt();
1767 if (desiredColumnCount > MAXIMUM_ALLOWED_COLUMNS) {
1768 warnPigment << "Refusing to set unreasonable number of columns (" << desiredColumnCount
1769 << ") in KPL palette file " << colorSet->filename()
1770 << " - setting maximum allowed column count instead.";
1772 } else {
1773 colorSet->setColumnCount(desiredColumnCount);
1774 }
1775
1777
1778 for (QDomElement g = root.firstChildElement(KPL_GROUP_TAG);
1779 !g.isNull();
1780 g = g.nextSiblingElement(KPL_GROUP_TAG)) {
1781 QString groupName = g.attribute(KPL_GROUP_NAME_ATTR);
1782 colorSet->addGroup(groupName);
1783 loadKplGroup(doc, g, colorSet->getGroup(groupName), version);
1784 }
1785
1786 return true;
1787}
void loadKplGroup(const QDomDocument &doc, const QDomElement &parentElement, KisSwatchGroupSP group, QString version)
static const QString KPL_PALETTE_COMMENT_ATTR
Definition KoColorSet.h:38
static const QString KPL_PALETTE_NAME_ATTR
Definition KoColorSet.h:37
static const QString KPL_PALETTE_COLUMN_COUNT_ATTR
Definition KoColorSet.h:36
static const QString KPL_GROUP_TAG
Definition KoColorSet.h:53
static const QString KPL_GROUP_NAME_ATTR
Definition KoColorSet.h:43
static const QString KPL_VERSION_ATTR
Definition KoColorSet.h:34

References KoColorSet::comment(), KoColorSet::KPL_GROUP_NAME_ATTR, KoColorSet::KPL_GROUP_TAG, KoColorSet::KPL_PALETTE_COLUMN_COUNT_ATTR, KoColorSet::KPL_PALETTE_COMMENT_ATTR, KoColorSet::KPL_PALETTE_NAME_ATTR, KoColorSet::KPL_VERSION_ATTR, MAXIMUM_ALLOWED_COLUMNS, KoResource::version, and warnPigment.

◆ loadKplGroup()

void KoColorSet::Private::loadKplGroup ( const QDomDocument & doc,
const QDomElement & parentElement,
KisSwatchGroupSP group,
QString version )
private

Definition at line 2551 of file KoColorSet.cpp.

2552{
2553 Q_UNUSED(doc);
2554 if (!parentEle.attribute(KPL_GROUP_ROW_COUNT_ATTR).isNull()) {
2555 group->setRowCount(parentEle.attribute(KPL_GROUP_ROW_COUNT_ATTR).toInt());
2556 }
2557 group->setColumnCount(colorSet->columnCount());
2558
2559 for (QDomElement swatchEle = parentEle.firstChildElement(KPL_SWATCH_TAG);
2560 !swatchEle.isNull();
2561 swatchEle = swatchEle.nextSiblingElement(KPL_SWATCH_TAG)) {
2562 QString colorDepthId = swatchEle.attribute(KPL_SWATCH_BITDEPTH_ATTR, Integer8BitsColorDepthID.id());
2563 KisSwatch swatch;
2564
2565 if (version == "1.0" && swatchEle.firstChildElement().tagName() == "Lab") {
2566 // previous version of krita had the values wrong, and scaled everything between 0 to 1,
2567 // but lab requires L = 0-100 and AB = -128-127.
2568 // TODO: write unittest for this.
2569 QDomElement el = swatchEle.firstChildElement();
2570 double L = KisDomUtils::toDouble(el.attribute("L"));
2571 el.setAttribute("L", L*100.0);
2572 double ab = KisDomUtils::toDouble(el.attribute("a"));
2573 if (ab <= .5) {
2574 ab = (0.5 - ab) * 2 * -128.0;
2575 } else {
2576 ab = (ab - 0.5) * 2 * 127.0;
2577 }
2578 el.setAttribute("a", ab);
2579
2580 ab = KisDomUtils::toDouble(el.attribute("b"));
2581 if (ab <= .5) {
2582 ab = (0.5 - ab) * 2 * -128.0;
2583 } else {
2584 ab = (ab - 0.5) * 2 * 127.0;
2585 }
2586 el.setAttribute("b", ab);
2587 swatch.setColor(KoColor::fromXML(el, colorDepthId));
2588 } else {
2589 swatch.setColor(KoColor::fromXML(swatchEle.firstChildElement(), colorDepthId));
2590 }
2591 swatch.setName(swatchEle.attribute(KPL_SWATCH_NAME_ATTR));
2592 swatch.setId(swatchEle.attribute(KPL_SWATCH_ID_ATTR));
2593 swatch.setSpotColor(swatchEle.attribute(KPL_SWATCH_SPOT_ATTR, "false") == "true" ? true : false);
2594 QDomElement positionEle = swatchEle.firstChildElement(KPL_SWATCH_POS_TAG);
2595 if (!positionEle.isNull()) {
2596 int rowNumber = positionEle.attribute(KPL_SWATCH_ROW_ATTR).toInt();
2597 int columnNumber = positionEle.attribute(KPL_SWATCH_COL_ATTR).toInt();
2598 if (columnNumber < 0 ||
2599 columnNumber >= colorSet->columnCount() ||
2600 rowNumber < 0
2601 ) {
2602 warnPigment << "Swatch" << swatch.name()
2603 << "of palette" << colorSet->name()
2604 << "has invalid position.";
2605 continue;
2606 }
2607 group->setSwatch(swatch, columnNumber, rowNumber);
2608 } else {
2609 group->addSwatch(swatch);
2610 }
2611 }
2612
2613 if (parentEle.attribute(KPL_GROUP_ROW_COUNT_ATTR).isNull()
2614 && group->colorCount() > 0
2615 && group->columnCount() > 0
2616 && (group->colorCount() / (group->columnCount()) + 1) < 20) {
2617 group->setRowCount((group->colorCount() / group->columnCount()) + 1);
2618 }
2619
2620}
QString name() const
Definition KisSwatch.h:24
static const QString KPL_SWATCH_TAG
Definition KoColorSet.h:52
static const QString KPL_SWATCH_ROW_ATTR
Definition KoColorSet.h:44
static const QString KPL_SWATCH_COL_ATTR
Definition KoColorSet.h:45
static const QString KPL_SWATCH_POS_TAG
Definition KoColorSet.h:51
static const QString KPL_GROUP_ROW_COUNT_ATTR
Definition KoColorSet.h:35
static const QString KPL_SWATCH_BITDEPTH_ATTR
Definition KoColorSet.h:49
static const QString KPL_SWATCH_SPOT_ATTR
Definition KoColorSet.h:47
static const QString KPL_SWATCH_NAME_ATTR
Definition KoColorSet.h:46
static const QString KPL_SWATCH_ID_ATTR
Definition KoColorSet.h:48
double toDouble(const QString &str, bool *ok=nullptr)

References KoColor::fromXML(), KoID::id(), Integer8BitsColorDepthID, KoColorSet::KPL_GROUP_ROW_COUNT_ATTR, KoColorSet::KPL_SWATCH_BITDEPTH_ATTR, KoColorSet::KPL_SWATCH_COL_ATTR, KoColorSet::KPL_SWATCH_ID_ATTR, KoColorSet::KPL_SWATCH_NAME_ATTR, KoColorSet::KPL_SWATCH_POS_TAG, KoColorSet::KPL_SWATCH_ROW_ATTR, KoColorSet::KPL_SWATCH_SPOT_ATTR, KoColorSet::KPL_SWATCH_TAG, KisSwatch::name(), KisSwatch::setColor(), KisSwatch::setId(), KisSwatch::setName(), KisSwatch::setSpotColor(), KisDomUtils::toDouble(), KoResource::version, and warnPigment.

◆ loadKplProfiles()

bool KoColorSet::Private::loadKplProfiles ( QScopedPointer< KoStore > & store)
private

Definition at line 1713 of file KoColorSet.cpp.

1714{
1715 if (!store->open("profiles.xml")) {
1716 return false;
1717 }
1718
1719 QByteArray bytes = store->read(store->size());
1720 store->close();
1721
1722 QDomDocument doc;
1723 if(!doc.setContent(bytes)) {
1724 return false;
1725 }
1726
1727 QDomElement root = doc.documentElement();
1728 for (QDomElement c = root.firstChildElement(KPL_PALETTE_PROFILE_TAG);
1729 !c.isNull();
1730 c = c.nextSiblingElement(KPL_PALETTE_PROFILE_TAG)) {
1731 QString name = c.attribute(KPL_PALETTE_NAME_ATTR);
1732 QString filename = c.attribute(KPL_PALETTE_FILENAME_ATTR);
1733 QString colorModelId = c.attribute(KPL_COLOR_MODEL_ID_ATTR);
1734 QString colorDepthId = c.attribute(KPL_COLOR_DEPTH_ID_ATTR);
1735
1737 continue;
1738 }
1739
1740 loadColorProfile(store, filename, colorModelId, colorDepthId);
1741 // TODO: What should happen if this fails?
1742 }
1743
1744 return true;
1745}
const KoColorProfile * loadColorProfile(QScopedPointer< KoStore > &store, const QString &path, const QString &modelId, const QString &colorDepthId)
static const QString KPL_COLOR_DEPTH_ID_ATTR
Definition KoColorSet.h:42
static const QString KPL_COLOR_MODEL_ID_ATTR
Definition KoColorSet.h:41
static const QString KPL_PALETTE_PROFILE_TAG
Definition KoColorSet.h:50
static const QString KPL_PALETTE_FILENAME_ATTR
Definition KoColorSet.h:39
const KoColorProfile * profileByName(const QString &name) const

References KoResource::filename, KoColorSpaceRegistry::instance(), KoColorSet::KPL_COLOR_DEPTH_ID_ATTR, KoColorSet::KPL_COLOR_MODEL_ID_ATTR, KoColorSet::KPL_PALETTE_FILENAME_ATTR, KoColorSet::KPL_PALETTE_NAME_ATTR, KoColorSet::KPL_PALETTE_PROFILE_TAG, KoResource::name, and KoColorSpaceRegistry::profileByName().

◆ loadPsp()

bool KoColorSet::Private::loadPsp ( )

Definition at line 1492 of file KoColorSet.cpp.

1493{
1494 QFileInfo info(colorSet->filename());
1495 colorSet->setName(info.completeBaseName());
1496 KisSwatch swatch;
1497 qint32 r, g, b;
1498
1499 QStringList l = readAllLinesSafe(&data);
1500 if (l.size() < 4) return false;
1501 if (l[0] != "JASC-PAL") return false;
1502 if (l[1] != "0100") return false;
1503
1504 int entries = l[2].toInt();
1505
1507
1508 for (int i = 0; i < entries; ++i) {
1509
1510 QStringList a = l[i + 3].replace('\t', ' ').split(' ', Qt::SkipEmptyParts);
1511
1512 if (a.count() != 3) {
1513 continue;
1514 }
1515
1516 r = qBound(0, a[0].toInt(), 255);
1517 g = qBound(0, a[1].toInt(), 255);
1518 b = qBound(0, a[2].toInt(), 255);
1519
1520 swatch.setColor(KoColor(QColor(r, g, b),
1522
1523 QString name = a.join(" ");
1524 swatch.setName(name.isEmpty() ? i18n("Untitled") : name);
1525
1526 global->addSwatch(swatch);
1527 }
1528 return true;
1529}

References KoColorSpaceRegistry::instance(), KoResource::name, KisSwatch::setColor(), and KisSwatch::setName().

◆ loadRiff()

bool KoColorSet::Private::loadRiff ( )

Definition at line 1468 of file KoColorSet.cpp.

1469{
1470 // https://worms2d.info/Palette_file
1471 QFileInfo info(colorSet->filename());
1472 colorSet->setName(info.completeBaseName());
1473 KisSwatch swatch;
1474
1475 RiffHeader header;
1476 memcpy(&header, data.constData(), sizeof(RiffHeader));
1477 header.colorcount = qFromBigEndian(header.colorcount);
1478
1479 for (int i = sizeof(RiffHeader);
1480 (i < (int)(sizeof(RiffHeader) + (header.colorcount * 4)) && i < data.size());
1481 i += 4) {
1482 quint8 r = data[i];
1483 quint8 g = data[i+1];
1484 quint8 b = data[i+2];
1485 swatch.setColor(KoColor(QColor(r, g, b), KoColorSpaceRegistry::instance()->rgb8()));
1486 colorSet->getGlobalGroup()->addSwatch(swatch);
1487 }
1488 return true;
1489}
quint16 colorcount

References RiffHeader::colorcount, KoColorSpaceRegistry::instance(), KoColorSpaceRegistry::rgb8(), and KisSwatch::setColor().

◆ loadSbz()

bool KoColorSet::Private::loadSbz ( )

Definition at line 2192 of file KoColorSet.cpp.

2192 {
2193 QBuffer buf(&data);
2194 buf.open(QBuffer::ReadOnly);
2195
2196 // &buf is a subclass of QIODevice
2197 QScopedPointer<KoStore> store(
2199 "application/x-swatchbook",
2200 KoStore::Zip));
2201 if (!store || store->bad()) {
2202 return false;
2203 }
2204
2205 if (store->hasFile("swatchbook.xml") && !loadSbzSwatchbook(store)) {
2206 return false;
2207 }
2208
2209 buf.close();
2210 return true;
2211}
bool loadSbzSwatchbook(QScopedPointer< KoStore > &store)

References KoStore::createStore(), KoStore::Read, and KoStore::Zip.

◆ loadSbzSwatchbook()

bool KoColorSet::Private::loadSbzSwatchbook ( QScopedPointer< KoStore > & store)
private

Definition at line 1900 of file KoColorSet.cpp.

1901{
1902 if (!store->open("swatchbook.xml")) {
1903 return false;
1904 }
1905
1906 QByteArray bytes = store->read(store->size());
1907 store->close();
1908
1909 dbgPigment << "XML palette: " << colorSet->filename() << ", SwatchBooker format";
1910
1911 QDomDocument doc;
1912#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
1913 int errorLine, errorColumn;
1914 QString errorMessage;
1915 if (!doc.setContent(bytes, &errorMessage, &errorLine, &errorColumn)) {
1916 warnPigment << "Illegal XML palette:" << colorSet->filename();
1917 warnPigment << "Error (line" << errorLine
1918 << ", column" << errorColumn
1919 << "):" << errorMessage;
1920#else
1921 QDomDocument::ParseResult result = doc.setContent(bytes);
1922 if (!result) {
1923 warnPigment << "Illegal XML palette:" << colorSet->filename();
1924 warnPigment << "Error (line" << result.errorLine
1925 << ", column" << result.errorColumn
1926 << "):" << result.errorMessage;
1927#endif
1928 return false;
1929 }
1930
1931 QDomElement root = doc.documentElement(); // SwatchBook
1932
1933 // Start reading properties...
1934 QDomElement metadata = root.firstChildElement("metadata");
1935 if (metadata.isNull()) {
1936 warnPigment << "Palette metadata not found";
1937 return false;
1938 }
1939
1940 QDomElement title = metadata.firstChildElement("dc:title");
1941 QString colorName = title.text();
1942 colorName = colorName.isEmpty() ? i18n("Untitled") : colorName;
1943 colorSet->setName(colorName);
1944 dbgPigment << "Processed name of palette:" << colorSet->name();
1945 // End reading properties
1946
1947 // Also read the swatch book...
1948 QDomElement book = root.firstChildElement("book");
1949 if (book.isNull()) {
1950 warnPigment << "Palette book (swatch composition) not found (line" << root.lineNumber()
1951 << ", column" << root.columnNumber()
1952 << ")";
1953 return false;
1954 }
1955
1956 // Which has lots of "swatch"es (todo: support groups)
1957 QDomElement swatch = book.firstChildElement();
1958 if (swatch.isNull()) {
1959 warnPigment << "Swatches/groups definition not found (line" << book.lineNumber()
1960 << ", column" << book.columnNumber()
1961 << ")";
1962 return false;
1963 }
1964
1965 // Now read colors...
1966 QDomElement materials = root.firstChildElement("materials");
1967 if (materials.isNull()) {
1968 warnPigment << "Materials (color definitions) not found";
1969 return false;
1970 }
1971
1972 // This one has lots of "color" elements
1973 if (materials.firstChildElement("color").isNull()) {
1974 warnPigment << "Color definitions not found (line" << materials.lineNumber()
1975 << ", column" << materials.columnNumber()
1976 << ")";
1977 return false;
1978 }
1979
1980 // We'll store colors here, and as we process swatches
1981 // we'll add them to the palette
1982 QHash<QString, KisSwatch> materialsBook;
1983 QHash<QString, const KoColorSpace*> fileColorSpaces;
1984
1985 // Color processing
1986 store->enterDirectory("profiles"); // Color profiles (icc files) live here
1987 for (QDomElement colorElement = materials.firstChildElement("color");
1988 !colorElement.isNull();
1989 colorElement = colorElement.nextSiblingElement("color")) {
1990 KisSwatch currentEntry;
1991 // Set if color is spot
1992 currentEntry.setSpotColor(colorElement.attribute("usage") == "spot");
1993
1994 // <metadata> inside contains id and name
1995 // one or more <values> define the color
1996 QDomElement currentColorMetadata = colorElement.firstChildElement("metadata");
1997 // Get color name
1998 QDomElement colorTitle = currentColorMetadata.firstChildElement("dc:title");
1999 QDomElement colorId = currentColorMetadata.firstChildElement("dc:identifier");
2000 // Is there an id? (we need that at the very least for identifying a color)
2001 if (colorId.text().isEmpty()) {
2002 warnPigment << "Unidentified color (line" << colorId.lineNumber()
2003 << ", column" << colorId.columnNumber()
2004 << ")";
2005 return false;
2006 }
2007
2008 if (materialsBook.contains(colorId.text())) {
2009 warnPigment << "Duplicated color definition (line" << colorId.lineNumber()
2010 << ", column" << colorId.columnNumber()
2011 << ")";
2012 return false;
2013 }
2014
2015 // Get a valid color name
2016 currentEntry.setId(colorId.text());
2017 currentEntry.setName(colorTitle.text().isEmpty() ? colorId.text() : colorTitle.text());
2018
2019 // Get a valid color definition
2020 if (colorElement.firstChildElement("values").isNull()) {
2021 warnPigment << "Color definitions not found (line" << colorElement.lineNumber()
2022 << ", column" << colorElement.columnNumber()
2023 << ")";
2024 return false;
2025 }
2026
2027 bool status;
2028 bool firstDefinition = false;
2030 const QString colorDepthId = Float32BitsColorDepthID.id();
2031 // Priority: Lab, otherwise the first definition found
2032 for (QDomElement colorValueE = colorElement.firstChildElement("values");
2033 !colorValueE.isNull();
2034 colorValueE = colorValueE.nextSiblingElement("values")) {
2035 QString model = colorValueE.attribute("model");
2036
2037 QString modelId;
2038 const KoColorProfile *profile = nullptr;
2039 if (model == "Lab") {
2040 modelId = LABAColorModelID.id();
2041 } else if (model == "sRGB") {
2042 modelId = RGBAColorModelID.id();
2043 profile = colorSpaceRegistry->rgb8()->profile();
2044 } else if (model == "XYZ") {
2045 modelId = XYZAColorModelID.id();
2046 } else if (model == "CMYK") {
2047 modelId = CMYKAColorModelID.id();
2048 } else if (model == "GRAY") {
2049 modelId = GrayAColorModelID.id();
2050 } else if (model == "RGB") {
2051 modelId = RGBAColorModelID.id();
2052 } else {
2053 warnPigment << "Color space not implemented:" << model
2054 << "(line" << colorValueE.lineNumber()
2055 << ", column "<< colorValueE.columnNumber()
2056 << ")";
2057 continue;
2058 }
2059
2060 const KoColorSpace *colorSpace = colorSpaceRegistry->colorSpace(modelId, colorDepthId, profile);
2061
2062 // The 'space' attribute is the name of the icc file
2063 // sitting in the 'profiles' directory in the zip.
2064 QString space = colorValueE.attribute("space");
2065 if (!space.isEmpty()) {
2066 if (fileColorSpaces.contains(space)) {
2067 colorSpace = fileColorSpaces.value(space);
2068 } else {
2069 // Try loading the profile and add it to the registry
2070 profile = loadColorProfile(store, space, modelId, colorDepthId);
2071 if (profile) {
2072 colorSpace = colorSpaceRegistry->colorSpace(modelId, colorDepthId, profile);
2073 fileColorSpaces.insert(space, colorSpace);
2074 }
2075 }
2076 }
2077
2078 KoColor c(colorSpace);
2079
2080 // sRGB,RGB,HSV,HSL,CMY,CMYK,nCLR: 0 -> 1
2081 // YIQ: Y 0 -> 1 : IQ -0.5 -> 0.5
2082 // Lab: L 0 -> 100 : ab -128 -> 127
2083 // XYZ: 0 -> ~100
2084 QVector<float> channels;
2085 for (const QString &str : colorValueE.text().split(" ")) {
2086 float channelValue = str.toFloat(&status);
2087 if (!status) {
2088 warnPigment << "Invalid float definition (line" << colorValueE.lineNumber()
2089 << ", column" << colorValueE.columnNumber()
2090 << ")";
2091
2092 channelValue = 0;
2093 }
2094
2095 channels.append(channelValue);
2096 }
2097 channels.append(OPACITY_OPAQUE_F); // Alpha channel
2098 colorSpace->fromNormalisedChannelsValue(c.data(), channels);
2099
2100 currentEntry.setColor(c);
2101 firstDefinition = true;
2102
2103 if (model == "Lab") {
2104 break; // Immediately add this one
2105 }
2106 }
2107
2108 if (firstDefinition) {
2109 materialsBook.insert(currentEntry.id(), currentEntry);
2110 } else {
2111 warnPigment << "No supported color spaces for the current color (line" << colorElement.lineNumber()
2112 << ", column "<< colorElement.columnNumber()
2113 << ")";
2114 return false;
2115 }
2116 }
2117
2118 store->leaveDirectory(); // Return to root
2119 // End colors
2120 // Now decide which ones will go into the palette
2121
2123 for(; !swatch.isNull(); swatch = swatch.nextSiblingElement()) {
2124 QString type = swatch.tagName();
2125 if (type.isEmpty() || type.isNull()) {
2126 warnPigment << "Invalid swatch/group definition (no id) (line" << swatch.lineNumber()
2127 << ", column" << swatch.columnNumber()
2128 << ")";
2129 return false;
2130 } else if (type == "swatch") {
2131 QString id = swatch.attribute("material");
2132 if (id.isEmpty() || id.isNull()) {
2133 warnPigment << "Invalid swatch definition (no material id) (line" << swatch.lineNumber()
2134 << ", column" << swatch.columnNumber()
2135 << ")";
2136 return false;
2137 }
2138
2139 if (materialsBook.contains(id)) {
2140 global->addSwatch(materialsBook.value(id));
2141 } else {
2142 warnPigment << "Invalid swatch definition (material not found) (line" << swatch.lineNumber()
2143 << ", column" << swatch.columnNumber()
2144 << ")";
2145 return false;
2146 }
2147 } else if (type == "group") {
2148 QDomElement groupMetadata = swatch.firstChildElement("metadata");
2149 if (groupMetadata.isNull()) {
2150 warnPigment << "Invalid group definition (missing metadata) (line" << groupMetadata.lineNumber()
2151 << ", column" << groupMetadata.columnNumber()
2152 << ")";
2153 return false;
2154 }
2155 QDomElement groupTitle = metadata.firstChildElement("dc:title");
2156 if (groupTitle.isNull()) {
2157 warnPigment << "Invalid group definition (missing title) (line" << groupTitle.lineNumber()
2158 << ", column" << groupTitle.columnNumber()
2159 << ")";
2160 return false;
2161 }
2162 QString currentGroupName = groupTitle.text();
2163 colorSet->addGroup(currentGroupName);
2164
2165 for (QDomElement groupSwatch = swatch.firstChildElement("swatch");
2166 !groupSwatch.isNull();
2167 groupSwatch = groupSwatch.nextSiblingElement("swatch")) {
2168 QString id = groupSwatch.attribute("material");
2169 if (id.isEmpty() || id.isNull()) {
2170 warnPigment << "Invalid swatch definition (no material id) (line" << groupSwatch.lineNumber()
2171 << ", column" << groupSwatch.columnNumber()
2172 << ")";
2173 return false;
2174 }
2175
2176 if (materialsBook.contains(id)) {
2177 colorSet->getGroup(currentGroupName)->addSwatch(materialsBook.value(id));
2178 } else {
2179 warnPigment << "Invalid swatch definition (material not found) (line" << groupSwatch.lineNumber()
2180 << ", column" << groupSwatch.columnNumber()
2181 << ")";
2182 return false;
2183 }
2184 }
2185 }
2186 }
2187 // End palette
2188
2189 return true;
2190}
#define dbgPigment
const KoID Float32BitsColorDepthID("F32", ki18n("32-bit float/channel"))
const KoID XYZAColorModelID("XYZA", ki18n("XYZ/Alpha"))
const KoID RGBAColorModelID("RGBA", ki18n("RGB/Alpha"))
const qreal OPACITY_OPAQUE_F
QString id() const
Definition KisSwatch.h:27
virtual void fromNormalisedChannelsValue(quint8 *pixel, const QVector< float > &values) const =0

References CMYKAColorModelID, KoColorSpaceRegistry::colorSpace(), KoColor::data(), dbgPigment, Float32BitsColorDepthID, KoColorSpace::fromNormalisedChannelsValue(), GrayAColorModelID, KoID::id(), KisSwatch::id(), KoColorSpaceRegistry::instance(), LABAColorModelID, KoResource::metadata, OPACITY_OPAQUE_F, KoColorSpace::profile(), KoColorSpaceRegistry::rgb8(), RGBAColorModelID, KisSwatch::setColor(), KisSwatch::setId(), KisSwatch::setName(), KisSwatch::setSpotColor(), warnPigment, and XYZAColorModelID.

◆ loadScribusXmlPalette()

bool KoColorSet::Private::loadScribusXmlPalette ( KoColorSet * set,
QXmlStreamReader * xml )
private

Definition at line 1187 of file KoColorSet.cpp.

1188{
1189
1190 //1. Get name
1191 QXmlStreamAttributes paletteProperties = xml->attributes();
1192 auto paletteName = paletteProperties.value("Name");
1193 dbgPigment << "Processed name of palette:" << paletteName;
1194 set->setName(paletteName.toString());
1195
1196 //2. Inside the SCRIBUSCOLORS, there are lots of colors. Retrieve them
1197
1198 while(xml->readNextStartElement()) {
1199 auto currentElement = xml->name();
1200 if (currentElement.compare(QString("COLOR"), Qt::CaseInsensitive) == 0) {
1201 scribusParseColor(set, xml);
1202 }
1203 else {
1204 xml->skipCurrentElement();
1205 }
1206 }
1207
1208 if(xml->hasError()) {
1209 return false;
1210 }
1211
1212 return true;
1213}
void scribusParseColor(KoColorSet *set, QXmlStreamReader *xml)

References dbgPigment, and KoResource::setName().

◆ loadXml()

bool KoColorSet::Private::loadXml ( )

Definition at line 2416 of file KoColorSet.cpp.

2416 {
2417 bool res = false;
2418
2419 QXmlStreamReader *xml = new QXmlStreamReader(data);
2420
2421 if (xml->readNextStartElement()) {
2422 auto paletteId = xml->name();
2423 if (paletteId.compare(QString("SCRIBUSCOLORS"), Qt::CaseInsensitive) == 0) { // Scribus
2424 dbgPigment << "XML palette: " << colorSet->filename() << ", Scribus format";
2425 res = loadScribusXmlPalette(colorSet, xml);
2426 }
2427 else {
2428 // Unknown XML format
2429 xml->raiseError("Unknown XML palette format. Expected SCRIBUSCOLORS, found " + paletteId);
2430 }
2431 }
2432
2433 // If there is any error (it should be returned through the stream)
2434 if (xml->hasError() || !res) {
2435 warnPigment << "Illegal XML palette:" << colorSet->filename();
2436 warnPigment << "Error (line"<< xml->lineNumber() << ", column" << xml->columnNumber() << "):" << xml->errorString();
2437 return false;
2438 }
2439 else {
2440 dbgPigment << "XML palette parsed successfully:" << colorSet->filename();
2441 return true;
2442 }
2443}
bool loadScribusXmlPalette(KoColorSet *set, QXmlStreamReader *xml)

References dbgPigment, and warnPigment.

◆ readByte()

quint8 KoColorSet::Private::readByte ( QIODevice * io)
private

Definition at line 1215 of file KoColorSet.cpp.

1216{
1217 quint8 val;
1218 quint64 read = io->read((char*)&val, 1);
1219 if (read != 1) return false;
1220 return val;
1221}

◆ readFloat()

float KoColorSet::Private::readFloat ( QIODevice * io)
private

Definition at line 1238 of file KoColorSet.cpp.

1239{
1240 float val;
1241 quint64 read = io->read((char*)&val, 4);
1242 if (read != 4) return false;
1243 return qFromBigEndian(val);
1244}

◆ readInt()

qint32 KoColorSet::Private::readInt ( QIODevice * io)
private

Definition at line 1230 of file KoColorSet.cpp.

1231{
1232 qint32 val;
1233 quint64 read = io->read((char*)&val, 4);
1234 if (read != 4) return false;
1235 return qFromBigEndian(val);
1236}

◆ readShort()

quint16 KoColorSet::Private::readShort ( QIODevice * io)
private

Definition at line 1223 of file KoColorSet.cpp.

1223 {
1224 quint16 val;
1225 quint64 read = io->read((char*)&val, 2);
1226 if (read != 2) return false;
1227 return qFromBigEndian(val);
1228}

◆ readUnicodeString()

QString KoColorSet::Private::readUnicodeString ( QIODevice * io,
bool sizeIsInt = false )
private

Definition at line 1246 of file KoColorSet.cpp.

1247{
1248 QString unicode;
1249 qint32 size = 0;
1250 if (sizeIsInt) {
1251 size = readInt(io);
1252 } else {
1253 size = readShort(io)-1;
1254 }
1255 if (size>0) {
1256 QByteArray ba = io->read(size*2);
1257 if (ba.size() == int(size)*2) {
1258 QTextCodec *Utf16Codec = QTextCodec::codecForName("UTF-16BE");
1259 unicode = Utf16Codec->toUnicode(ba);
1260 } else {
1261 warnPigment << "Unicode name block is the wrong size" << colorSet->filename();
1262 }
1263 }
1264 if (!sizeIsInt) {
1265 readShort(io); // when the size is quint16, the string is 00 terminated;
1266 }
1267 return unicode.trimmed();
1268}
int size(const Forest< T > &forest)
Definition KisForest.h:1232

References warnPigment.

◆ saveGpl()

bool KoColorSet::Private::saveGpl ( QIODevice * dev) const

Definition at line 1349 of file KoColorSet.cpp.

1350{
1351 Q_ASSERT(dev->isOpen());
1352 Q_ASSERT(dev->isWritable());
1353
1354 QTextStream stream(dev);
1356 stream << "GIMP Palette\nName: " << colorSet->name() << "\nColumns: " << colorSet->columnCount() << "\n#\n";
1357
1359 for (int y = 0; y < global->rowCount(); y++) {
1360 for (int x = 0; x < colorSet->columnCount(); x++) {
1361 if (!global->checkSwatchExists(x, y)) {
1362 continue;
1363 }
1364 const KisSwatch& entry = global->getSwatch(x, y);
1365 QColor c = entry.color().toQColor();
1366 stream << c.red() << " " << c.green() << " " << c.blue() << "\t";
1367 if (entry.name().isEmpty())
1368 stream << "Untitled\n";
1369 else
1370 stream << entry.name() << "\n";
1371 }
1372 }
1373
1374 return true;
1375}
KoColor color() const
Definition KisSwatch.h:30
void toQColor(QColor *c) const
a convenience method for the above.
Definition KoColor.cpp:198
void setUtf8OnStream(QTextStream &stream)

References KisSwatch::color(), KisSwatch::name(), KisPortingUtils::setUtf8OnStream(), and KoColor::toQColor().

◆ saveKpl()

bool KoColorSet::Private::saveKpl ( QIODevice * dev) const

Definition at line 2445 of file KoColorSet.cpp.

2446{
2447 QScopedPointer<KoStore> store(KoStore::createStore(dev, KoStore::Write, "application/x-krita-palette", KoStore::Zip));
2448 if (!store || store->bad()) {
2449 qWarning() << "saveKpl could not create store";
2450 return false;
2451 }
2452
2453 QSet<const KoColorSpace *> colorSpaces;
2454
2455 {
2456 QDomDocument doc;
2457 QDomElement root = doc.createElement(KPL_PALETTE_TAG);
2458 root.setAttribute(KPL_VERSION_ATTR, "2.0");
2459 root.setAttribute(KPL_PALETTE_NAME_ATTR, colorSet->name());
2460 root.setAttribute(KPL_PALETTE_COMMENT_ATTR, comment);
2461 root.setAttribute(KPL_PALETTE_COLUMN_COUNT_ATTR, colorSet->columnCount());
2462 root.setAttribute(KPL_GROUP_ROW_COUNT_ATTR, colorSet->getGlobalGroup()->rowCount());
2463
2465
2466 for (const KisSwatchGroupSP &group : swatchGroups) {
2467 if (group->name() == KoColorSet::GLOBAL_GROUP_NAME) { continue; }
2468 QDomElement gl = doc.createElement(KPL_GROUP_TAG);
2469 gl.setAttribute(KPL_GROUP_NAME_ATTR, group->name());
2470 root.appendChild(gl);
2471 saveKplGroup(doc, gl, group, colorSpaces);
2472 }
2473
2474 doc.appendChild(root);
2475 if (!store->open("colorset.xml")) { return false; }
2476 QByteArray ba = doc.toByteArray();
2477 if (store->write(ba) != ba.size()) { return false; }
2478 if (!store->close()) { return false; }
2479 }
2480
2481 QDomDocument doc;
2482 QDomElement profileElement = doc.createElement("Profiles");
2483
2484 for (const KoColorSpace *colorSpace : colorSpaces) {
2485 QString fn = QFileInfo(colorSpace->profile()->fileName()).fileName();
2486 if (!store->open(fn)) { qWarning() << "Could not open the store for profiles directory"; return false; }
2487 QByteArray profileRawData = colorSpace->profile()->rawData();
2488 if (!store->write(profileRawData)) { qWarning() << "Could not write the profiles data into the store"; return false; }
2489 if (!store->close()) { qWarning() << "Could not close the store for profiles directory"; return false; }
2490 QDomElement el = doc.createElement(KPL_PALETTE_PROFILE_TAG);
2491 el.setAttribute(KPL_PALETTE_FILENAME_ATTR, fn);
2492 el.setAttribute(KPL_PALETTE_NAME_ATTR, colorSpace->profile()->name());
2493 el.setAttribute(KPL_COLOR_MODEL_ID_ATTR, colorSpace->colorModelId().id());
2494 el.setAttribute(KPL_COLOR_DEPTH_ID_ATTR, colorSpace->colorDepthId().id());
2495 profileElement.appendChild(el);
2496
2497 }
2498 doc.appendChild(profileElement);
2499
2500 if (!store->open("profiles.xml")) { qWarning() << "Could not open profiles.xml"; return false; }
2501 QByteArray ba = doc.toByteArray();
2502
2503 int bytesWritten = store->write(ba);
2504 if (bytesWritten != ba.size()) { qWarning() << "Bytes written is wrong" << ba.size(); return false; }
2505
2506 if (!store->close()) { qWarning() << "Could not close the store"; return false; }
2507
2508 bool r = store->finalize();
2509 if (!r) { qWarning() << "Could not finalize the store"; }
2510 return r;
2511}
void saveKplGroup(QDomDocument &doc, QDomElement &groupEle, const KisSwatchGroupSP group, QSet< const KoColorSpace * > &colorSetSet) const
static const QString KPL_PALETTE_TAG
Definition KoColorSet.h:54
@ Write
Definition KoStore.h:29

References KoColorSet::comment(), KoStore::createStore(), KoColorSet::GLOBAL_GROUP_NAME, KoColorSet::KPL_COLOR_DEPTH_ID_ATTR, KoColorSet::KPL_COLOR_MODEL_ID_ATTR, KoColorSet::KPL_GROUP_NAME_ATTR, KoColorSet::KPL_GROUP_ROW_COUNT_ATTR, KoColorSet::KPL_GROUP_TAG, KoColorSet::KPL_PALETTE_COLUMN_COUNT_ATTR, KoColorSet::KPL_PALETTE_COMMENT_ATTR, KoColorSet::KPL_PALETTE_FILENAME_ATTR, KoColorSet::KPL_PALETTE_NAME_ATTR, KoColorSet::KPL_PALETTE_PROFILE_TAG, KoColorSet::KPL_PALETTE_TAG, KoColorSet::KPL_VERSION_ATTR, KoStore::Write, and KoStore::Zip.

◆ saveKplGroup()

void KoColorSet::Private::saveKplGroup ( QDomDocument & doc,
QDomElement & groupEle,
const KisSwatchGroupSP group,
QSet< const KoColorSpace * > & colorSetSet ) const
private

Definition at line 2513 of file KoColorSet.cpp.

2517{
2518 groupEle.setAttribute(KPL_GROUP_ROW_COUNT_ATTR, QString::number(group->rowCount()));
2519
2520 for (const KisSwatchGroup::SwatchInfo &info : group->infoList()) {
2521 const KoColorProfile *profile = info.swatch.color().colorSpace()->profile();
2522 // Only save non-builtin profiles.=
2523 if (!profile->fileName().isEmpty()) {
2524 bool alreadyIncluded = false;
2525 Q_FOREACH(const KoColorSpace* colorSpace, colorSetSet) {
2526 if (colorSpace->profile()->fileName() == profile->fileName()) {
2527 alreadyIncluded = true;
2528 break;
2529 }
2530 }
2531 if(!alreadyIncluded) {
2532 colorSetSet.insert(info.swatch.color().colorSpace());
2533 }
2534 }
2535 QDomElement swatchEle = doc.createElement(KPL_SWATCH_TAG);
2536 swatchEle.setAttribute(KPL_SWATCH_NAME_ATTR, info.swatch.name());
2537 swatchEle.setAttribute(KPL_SWATCH_ID_ATTR, info.swatch.id());
2538 swatchEle.setAttribute(KPL_SWATCH_SPOT_ATTR, info.swatch.spotColor() ? "true" : "false");
2539 swatchEle.setAttribute(KPL_SWATCH_BITDEPTH_ATTR, info.swatch.color().colorSpace()->colorDepthId().id());
2540 info.swatch.color().toXML(doc, swatchEle);
2541
2542 QDomElement positionEle = doc.createElement(KPL_SWATCH_POS_TAG);
2543 positionEle.setAttribute(KPL_SWATCH_ROW_ATTR, info.row);
2544 positionEle.setAttribute(KPL_SWATCH_COL_ATTR, info.column);
2545 swatchEle.appendChild(positionEle);
2546
2547 groupEle.appendChild(swatchEle);
2548 }
2549}

References KoColorProfile::fileName, KoColorSet::KPL_GROUP_ROW_COUNT_ATTR, KoColorSet::KPL_SWATCH_BITDEPTH_ATTR, KoColorSet::KPL_SWATCH_COL_ATTR, KoColorSet::KPL_SWATCH_ID_ATTR, KoColorSet::KPL_SWATCH_NAME_ATTR, KoColorSet::KPL_SWATCH_POS_TAG, KoColorSet::KPL_SWATCH_ROW_ATTR, KoColorSet::KPL_SWATCH_SPOT_ATTR, KoColorSet::KPL_SWATCH_TAG, and KoColorSpace::profile().

◆ scribusParseColor()

void KoColorSet::Private::scribusParseColor ( KoColorSet * set,
QXmlStreamReader * xml )
private

Definition at line 1094 of file KoColorSet.cpp.

1095{
1096 KisSwatch colorEntry;
1097 // It's a color, retrieve it
1098 QXmlStreamAttributes colorProperties = xml->attributes();
1099 auto colorName = colorProperties.value("NAME");
1100 colorEntry.setName(colorName.isEmpty() || colorName.isNull() ? i18n("Untitled") : colorName.toString());
1101
1102 // RGB or CMYK?
1103 if (colorProperties.hasAttribute("RGB")) {
1104 dbgPigment << "Color " << colorProperties.value("NAME") << ", RGB " << colorProperties.value("RGB");
1105
1107 auto colorValue = colorProperties.value("RGB");
1108
1109 if (colorValue.length() != 7 && colorValue.at(0) != '#') { // Color is a hexadecimal number
1110 xml->raiseError("Invalid rgb8 color (malformed): " + colorValue);
1111 return;
1112 } else {
1113 bool rgbOk;
1114 quint32 rgb = colorValue.mid(1).toUInt(&rgbOk, 16);
1115 if (!rgbOk) {
1116 xml->raiseError("Invalid rgb8 color (unable to convert): " + colorValue);
1117 return;
1118 }
1119
1120 quint8 r = rgb >> 16 & 0xff;
1121 quint8 g = rgb >> 8 & 0xff;
1122 quint8 b = rgb & 0xff;
1123
1124 dbgPigment << "Color parsed: "<< r << g << b;
1125
1126 currentColor.data()[0] = r;
1127 currentColor.data()[1] = g;
1128 currentColor.data()[2] = b;
1130 colorEntry.setColor(currentColor);
1131
1132 set->addSwatch(colorEntry);
1133
1134 while(xml->readNextStartElement()) {
1135 //ignore - these are all unknown or the /> element tag
1136 xml->skipCurrentElement();
1137 }
1138 return;
1139 }
1140 }
1141 else if (colorProperties.hasAttribute("CMYK")) {
1142 dbgPigment << "Color " << colorProperties.value("NAME") << ", CMYK " << colorProperties.value("CMYK");
1143
1145 auto colorValue = colorProperties.value("CMYK");
1146
1147 if (colorValue.length() != 9 && colorValue.at(0) != '#') { // Color is a hexadecimal number
1148 xml->raiseError("Invalid cmyk color (malformed): " % colorValue);
1149 return;
1150 }
1151 else {
1152 bool cmykOk;
1153 quint32 cmyk = colorValue.mid(1).toUInt(&cmykOk, 16); // cmyk uses the full 32 bits
1154 if (!cmykOk) {
1155 xml->raiseError("Invalid cmyk color (unable to convert): " % colorValue);
1156 return;
1157 }
1158
1159 quint8 c = cmyk >> 24 & 0xff;
1160 quint8 m = cmyk >> 16 & 0xff;
1161 quint8 y = cmyk >> 8 & 0xff;
1162 quint8 k = cmyk & 0xff;
1163
1164 dbgPigment << "Color parsed: "<< c << m << y << k;
1165
1166 currentColor.data()[0] = c;
1167 currentColor.data()[1] = m;
1168 currentColor.data()[2] = y;
1169 currentColor.data()[3] = k;
1171 colorEntry.setColor(currentColor);
1172
1173 set->addSwatch(colorEntry);
1174
1175 while(xml->readNextStartElement()) {
1176 //ignore - these are all unknown or the /> element tag
1177 xml->skipCurrentElement();
1178 }
1179 return;
1180 }
1181 }
1182 else {
1183 xml->raiseError("Unknown color space for color " + colorEntry.name());
1184 }
1185}
KoColor currentColor(ResourceProvider *provider, ColorRole role)
QString toString(const QString &value)

References KoColorSet::addSwatch(), CMYKAColorModelID, KoColor::data(), dbgPigment, KoID::id(), KoColorSpaceRegistry::instance(), Integer8BitsColorDepthID, KisSwatch::name(), OPACITY_OPAQUE_U8, KisSwatch::setColor(), KisSwatch::setName(), and KoColor::setOpacity().

Friends And Related Symbol Documentation

◆ AddGroupCommand

friend struct AddGroupCommand
friend

Definition at line 73 of file KoColorSet_p.h.

◆ AddSwatchCommand

friend struct AddSwatchCommand
friend

Definition at line 70 of file KoColorSet_p.h.

◆ ChangeGroupNameCommand

friend struct ChangeGroupNameCommand
friend

Definition at line 72 of file KoColorSet_p.h.

◆ ClearCommand

friend struct ClearCommand
friend

Definition at line 75 of file KoColorSet_p.h.

◆ MoveGroupCommand

friend struct MoveGroupCommand
friend

Definition at line 79 of file KoColorSet_p.h.

◆ RemoveGroupCommand

friend struct RemoveGroupCommand
friend

Definition at line 74 of file KoColorSet_p.h.

◆ RemoveSwatchCommand

friend struct RemoveSwatchCommand
friend

Definition at line 71 of file KoColorSet_p.h.

◆ SetColumnCountCommand

friend struct SetColumnCountCommand
friend

Definition at line 76 of file KoColorSet_p.h.

◆ SetCommentCommand

friend struct SetCommentCommand
friend

Definition at line 77 of file KoColorSet_p.h.

◆ SetPaletteTypeCommand

friend struct SetPaletteTypeCommand
friend

Definition at line 78 of file KoColorSet_p.h.

Member Data Documentation

◆ colorSet

KoColorSet* KoColorSet::Private::colorSet {0}

Definition at line 59 of file KoColorSet_p.h.

59{0};

◆ columns

int KoColorSet::Private::columns

Definition at line 66 of file KoColorSet_p.h.

◆ comment

QString KoColorSet::Private::comment

Definition at line 62 of file KoColorSet_p.h.

◆ data

QByteArray KoColorSet::Private::data

Definition at line 61 of file KoColorSet_p.h.

◆ isLocked

bool KoColorSet::Private::isLocked {false}

Definition at line 65 of file KoColorSet_p.h.

65{false};

◆ paletteType

KoColorSet::PaletteType KoColorSet::Private::paletteType {UNKNOWN}

Definition at line 60 of file KoColorSet_p.h.

60{UNKNOWN};

◆ swatchGroups

QList<KisSwatchGroupSP> KoColorSet::Private::swatchGroups

Definition at line 63 of file KoColorSet_p.h.

◆ undoStack

KUndo2Stack KoColorSet::Private::undoStack

Definition at line 64 of file KoColorSet_p.h.


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