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 if (!file.open(QIODevice::ReadOnly)) {
1290 warnPigment << "Cannot load palette" << colorSet->name() << ":" << file.errorString();
1291 return false;
1292 }
1293 data = file.readAll();
1294 file.close();
1295 }
1296
1297 bool res = false;
1299 switch(paletteType) {
1300 case GPL:
1301 res = loadGpl();
1302 break;
1303 case ACT:
1304 res = loadAct();
1305 break;
1306 case RIFF_PAL:
1307 res = loadRiff();
1308 break;
1309 case PSP_PAL:
1310 res = loadPsp();
1311 break;
1312 case ACO:
1313 res = loadAco();
1314 break;
1315 case XML:
1316 res = loadXml();
1317 break;
1318 case KPL:
1319 res = loadKpl();
1320 break;
1321 case SBZ:
1322 res = loadSbz();
1323 break;
1324 case ASE:
1325 res = loadAse();
1326 break;
1327 case ACB:
1328 res = loadAcb();
1329 break;
1330 case CSS:
1331 res = loadCss();
1332 break;
1333 default:
1334 res = false;
1335 }
1336 if (paletteType != KPL) {
1337 int rowCount = global()->colorCount() / global()->columnCount();
1338 if (global()->colorCount() % global()->columnCount() > 0) {
1339 rowCount ++;
1340 }
1341 global()->setRowCount(rowCount);
1342 }
1343 colorSet->setValid(res);
1345
1346 data.clear();
1347 undoStack.clear();
1348
1349 return res;
1350}
#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 2320 of file KoColorSet.cpp.

2321{
2322
2323 QFileInfo info(colorSet->filename());
2324
2325 QBuffer buf(&data);
2326 buf.open(QBuffer::ReadOnly);
2327
2328 QByteArray signature; // should be "8BCB";
2329 signature = buf.read(4);
2330 quint16 version = readShort(&buf);
2331 quint16 bookID = readShort(&buf);
2332 Q_UNUSED(bookID);
2333
2334 if (signature != "8BCB" && version!= 1) {
2335 return false;
2336 }
2337
2339 for (int i = 0; i< 4; i++) {
2340
2341 QString metadataString = readUnicodeString(&buf, true);
2342 if (metadataString.startsWith("\"")) {
2343 metadataString = metadataString.remove(0, 1);
2344 }
2345 if (metadataString.endsWith("\"")) {
2346 metadataString.chop(1);
2347 }
2348 if (metadataString.startsWith("$$$/")) {
2349 if (metadataString.contains("=")) {
2350 metadataString = metadataString.split("=").last();
2351 } else {
2352 metadataString = QString();
2353 }
2354 }
2355 metadata.append(metadataString);
2356 }
2357 QString title = metadata.at(0);
2358 colorSet->setName(title);
2359 QString prefix = metadata.at(1);
2360 QString postfix = metadata.at(2);
2361 QString description = metadata.at(3);
2362 colorSet->setComment(description);
2363
2364 quint16 numColors = readShort(&buf);
2365 quint16 numColumns = readShort(&buf);
2366 numColumns = numColumns > 0 ? numColumns : 8; // overwrite with sane default in case of 0
2367 colorSet->setColumnCount(numColumns);
2368 quint16 numKeyColorPage = readShort(&buf);
2369 Q_UNUSED(numKeyColorPage);
2370 quint16 colorType = readShort(&buf);
2371
2373 if (colorType == 2) {
2374 QString profileName = "U.S. Web Coated (SWOP) v2";
2376 } else if (colorType == 7) {
2378 }
2379
2380 for (quint16 i = 0; i < numColors; i++) {
2381 KisSwatch swatch;
2383 name << prefix;
2384 name << readUnicodeString(&buf, true);
2385 name << postfix;
2386 swatch.setName(name.join(" ").trimmed());
2387 QByteArray key; // should be "8BCB";
2388 key = buf.read(6);
2389 swatch.setId(QString::fromLatin1(key));
2390 swatch.setSpotColor(true);
2391 quint8 c1 = readByte(&buf);
2392 quint8 c2 = readByte(&buf);
2393 quint8 c3 = readByte(&buf);
2394 KoColor c(cs);
2395 if (colorType == 0) {
2396 c.data()[0] = c3;
2397 c.data()[1] = c2;
2398 c.data()[2] = c1;
2399 } else if (colorType == 2) {
2400 quint8 c4 = readByte(&buf);
2401 c.data()[0] = c1;
2402 c.data()[1] = c2;
2403 c.data()[2] = c3;
2404 c.data()[3] = c4;
2405 } else if (colorType == 7) {
2406 c.data()[0] = c1;
2407 c.data()[1] = c2;
2408 c.data()[2] = c3;
2409 }
2410 c.setOpacity(1.0);
2411 swatch.setColor(c);
2412 colorSet->addSwatch(swatch);
2413 }
2414
2415 return true;
2416}
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 1816 of file KoColorSet.cpp.

1817{
1818 QFileInfo info(colorSet->filename());
1819 colorSet->setName(info.completeBaseName());
1820
1821 QBuffer buf(&data);
1822 buf.open(QBuffer::ReadOnly);
1823
1824 quint16 version = readShort(&buf);
1825 quint16 numColors = readShort(&buf);
1826 KisSwatch swatch;
1827
1828 if (version == 1 && buf.size() > 4+numColors*10) {
1829 buf.seek(4+numColors*10);
1830 version = readShort(&buf);
1831 numColors = readShort(&buf);
1832 }
1833
1834 const quint16 quint16_MAX = 65535;
1835
1837
1838 for (int i = 0; i < numColors && !buf.atEnd(); ++i) {
1839
1840 quint16 colorSpace = readShort(&buf);
1841 quint16 ch1 = readShort(&buf);
1842 quint16 ch2 = readShort(&buf);
1843 quint16 ch3 = readShort(&buf);
1844 quint16 ch4 = readShort(&buf);
1845
1846 bool skip = false;
1847 if (colorSpace == 0) { // RGB
1849 KoColor c(KoColorSpaceRegistry::instance()->rgb16(srgb));
1850 reinterpret_cast<quint16*>(c.data())[0] = ch3;
1851 reinterpret_cast<quint16*>(c.data())[1] = ch2;
1852 reinterpret_cast<quint16*>(c.data())[2] = ch1;
1853 c.setOpacity(OPACITY_OPAQUE_U8);
1854 swatch.setColor(c);
1855 }
1856 else if (colorSpace == 1) { // HSB
1857 QColor qc;
1858 qc.setHsvF(ch1 / 65536.0, ch2 / 65536.0, ch3 / 65536.0);
1859 KoColor c(qc, KoColorSpaceRegistry::instance()->rgb16());
1860 c.setOpacity(OPACITY_OPAQUE_U8);
1861 swatch.setColor(c);
1862 }
1863 else if (colorSpace == 2) { // CMYK
1865 reinterpret_cast<quint16*>(c.data())[0] = quint16_MAX - ch1;
1866 reinterpret_cast<quint16*>(c.data())[1] = quint16_MAX - ch2;
1867 reinterpret_cast<quint16*>(c.data())[2] = quint16_MAX - ch3;
1868 reinterpret_cast<quint16*>(c.data())[3] = quint16_MAX - ch4;
1869 c.setOpacity(OPACITY_OPAQUE_U8);
1870 swatch.setColor(c);
1871 }
1872 else if (colorSpace == 7) { // LAB
1874 reinterpret_cast<quint16*>(c.data())[0] = ch3;
1875 reinterpret_cast<quint16*>(c.data())[1] = ch2;
1876 reinterpret_cast<quint16*>(c.data())[2] = ch1;
1878 swatch.setColor(c);
1879 }
1880 else if (colorSpace == 8) { // GRAY
1882 reinterpret_cast<quint16*>(c.data())[0] = ch1 * (quint16_MAX / 10000);
1884 swatch.setColor(c);
1885 }
1886 else {
1887 warnPigment << "Unsupported colorspace in palette" << colorSet->filename() << "(" << colorSpace << ")";
1888 skip = true;
1889 }
1890
1891 if (version == 2) {
1892 QString name = readUnicodeString(&buf, true);
1893 swatch.setName(name);
1894 }
1895 if (!skip) {
1896 group->addSwatch(swatch);
1897 }
1898 }
1899 return true;
1900}
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 1455 of file KoColorSet.cpp.

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

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

◆ loadAse()

bool KoColorSet::Private::loadAse ( )

Definition at line 2215 of file KoColorSet.cpp.

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

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

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

◆ loadCss()

bool KoColorSet::Private::loadCss ( )

Definition at line 1534 of file KoColorSet.cpp.

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

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

1792{
1793 QBuffer buf(&data);
1794 buf.open(QBuffer::ReadOnly);
1795
1796 QScopedPointer<KoStore> store(
1798 "application/x-krita-palette",
1799 KoStore::Zip));
1800 if (!store || store->bad()) {
1801 return false;
1802 }
1803
1804 if (store->hasFile("profiles.xml") && !loadKplProfiles(store)) {
1805 return false;
1806 }
1807
1808 if (!loadKplColorset(store)) {
1809 return false;
1810 }
1811
1812 buf.close();
1813 return true;
1814}
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 1749 of file KoColorSet.cpp.

1750{
1751 if (!store->open("colorset.xml")) {
1752 return false;
1753 }
1754
1755 QByteArray bytes = store->read(store->size());
1756 store->close();
1757
1758 QDomDocument doc;
1759 if (!doc.setContent(bytes)) {
1760 return false;
1761 }
1762
1763 QDomElement root = doc.documentElement();
1764 colorSet->setName(root.attribute(KPL_PALETTE_NAME_ATTR));
1765 QString version = root.attribute(KPL_VERSION_ATTR);
1766 comment = root.attribute(KPL_PALETTE_COMMENT_ATTR);
1767
1768 int desiredColumnCount = root.attribute(KPL_PALETTE_COLUMN_COUNT_ATTR).toInt();
1769 if (desiredColumnCount > MAXIMUM_ALLOWED_COLUMNS) {
1770 warnPigment << "Refusing to set unreasonable number of columns (" << desiredColumnCount
1771 << ") in KPL palette file " << colorSet->filename()
1772 << " - setting maximum allowed column count instead.";
1774 } else {
1775 colorSet->setColumnCount(desiredColumnCount);
1776 }
1777
1779
1780 for (QDomElement g = root.firstChildElement(KPL_GROUP_TAG);
1781 !g.isNull();
1782 g = g.nextSiblingElement(KPL_GROUP_TAG)) {
1783 QString groupName = g.attribute(KPL_GROUP_NAME_ATTR);
1784 colorSet->addGroup(groupName);
1785 loadKplGroup(doc, g, colorSet->getGroup(groupName), version);
1786 }
1787
1788 return true;
1789}
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 2553 of file KoColorSet.cpp.

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

1716{
1717 if (!store->open("profiles.xml")) {
1718 return false;
1719 }
1720
1721 QByteArray bytes = store->read(store->size());
1722 store->close();
1723
1724 QDomDocument doc;
1725 if(!doc.setContent(bytes)) {
1726 return false;
1727 }
1728
1729 QDomElement root = doc.documentElement();
1730 for (QDomElement c = root.firstChildElement(KPL_PALETTE_PROFILE_TAG);
1731 !c.isNull();
1732 c = c.nextSiblingElement(KPL_PALETTE_PROFILE_TAG)) {
1733 QString name = c.attribute(KPL_PALETTE_NAME_ATTR);
1734 QString filename = c.attribute(KPL_PALETTE_FILENAME_ATTR);
1735 QString colorModelId = c.attribute(KPL_COLOR_MODEL_ID_ATTR);
1736 QString colorDepthId = c.attribute(KPL_COLOR_DEPTH_ID_ATTR);
1737
1739 continue;
1740 }
1741
1742 loadColorProfile(store, filename, colorModelId, colorDepthId);
1743 // TODO: What should happen if this fails?
1744 }
1745
1746 return true;
1747}
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 1495 of file KoColorSet.cpp.

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

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

◆ loadRiff()

bool KoColorSet::Private::loadRiff ( )

Definition at line 1471 of file KoColorSet.cpp.

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

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

◆ loadSbz()

bool KoColorSet::Private::loadSbz ( )

Definition at line 2194 of file KoColorSet.cpp.

2194 {
2195 QBuffer buf(&data);
2196 buf.open(QBuffer::ReadOnly);
2197
2198 // &buf is a subclass of QIODevice
2199 QScopedPointer<KoStore> store(
2201 "application/x-swatchbook",
2202 KoStore::Zip));
2203 if (!store || store->bad()) {
2204 return false;
2205 }
2206
2207 if (store->hasFile("swatchbook.xml") && !loadSbzSwatchbook(store)) {
2208 return false;
2209 }
2210
2211 buf.close();
2212 return true;
2213}
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 1902 of file KoColorSet.cpp.

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

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

1353{
1354 Q_ASSERT(dev->isOpen());
1355 Q_ASSERT(dev->isWritable());
1356
1357 QTextStream stream(dev);
1359 stream << "GIMP Palette\nName: " << colorSet->name() << "\nColumns: " << colorSet->columnCount() << "\n#\n";
1360
1362 for (int y = 0; y < global->rowCount(); y++) {
1363 for (int x = 0; x < colorSet->columnCount(); x++) {
1364 if (!global->checkSwatchExists(x, y)) {
1365 continue;
1366 }
1367 const KisSwatch& entry = global->getSwatch(x, y);
1368 QColor c = entry.color().toQColor();
1369 stream << c.red() << " " << c.green() << " " << c.blue() << "\t";
1370 if (entry.name().isEmpty())
1371 stream << "Untitled\n";
1372 else
1373 stream << entry.name() << "\n";
1374 }
1375 }
1376
1377 return true;
1378}
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 2447 of file KoColorSet.cpp.

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

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

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: