tdf#160404 tdf#160535 tdf#160536 - sc improve sheet protection
[LibreOffice.git] / svx / source / tbxctrls / Palette.cxx
blob29158cbfcac852cc598af2a659cfffad7d11958b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <svx/Palette.hxx>
21 #include <tools/stream.hxx>
23 #include <palettes.hxx>
24 #include <utility>
26 Palette::~Palette()
30 PaletteASE::~PaletteASE()
34 PaletteASE::PaletteASE( OUString aFPath, OUString aFName ) :
35 mbValidPalette( false ),
36 maFPath (std::move( aFPath )),
37 maASEPaletteName (std::move( aFName ))
39 LoadPalette();
42 void PaletteASE::LoadColorSet(SvxColorValueSet& rColorSet)
44 rColorSet.Clear();
45 int nIx = 1;
46 for (const auto& rColor : maColors)
48 rColorSet.InsertItem(nIx, rColor.m_aColor, rColor.m_aName);
49 ++nIx;
53 const OUString& PaletteASE::GetName()
55 return maASEPaletteName;
58 const OUString& PaletteASE::GetPath()
60 return maFPath;
63 bool PaletteASE::IsValid()
65 return mbValidPalette;
68 // CMYK values from 0 to 1
69 // TODO: Deduplicate me (taken from core/cui/source/dialogs/colorpicker.cxx)
70 static void lcl_CMYKtoRGB( float fCyan, float fMagenta, float fYellow, float fKey, float& dR, float& dG, float& dB )
72 fCyan = (fCyan * ( 1.0 - fKey )) + fKey;
73 fMagenta = (fMagenta * ( 1.0 - fKey )) + fKey;
74 fYellow = (fYellow * ( 1.0 - fKey )) + fKey;
76 dR = std::clamp( 1.0 - fCyan, 0.0, 1.0 );
77 dG = std::clamp( 1.0 - fMagenta, 0.0, 1.0 );
78 dB = std::clamp( 1.0 - fYellow, 0.0, 1.0 );
81 // This function based on code under ALv2 - Copyright 2013 István Ujj-Mészáros
82 // credit Avisek Das and István Ujj-Mészáros
83 static void lcl_XYZtoRGB( float fX, float fY, float fZ, float& dR, float& dG, float& dB)
85 // Observer = 2°, Illuminant = D65
86 fX = fX / 100;
87 fY = fY / 100;
88 fZ = fZ / 100;
90 // X from 0 to 95.047
91 dR = fX * 3.2406 + fY * -1.5372 + fZ * -0.4986;
92 // Y from 0 to 100.000
93 dG = fX * -0.9689 + fY * 1.8758 + fZ * 0.0415;
94 // Z from 0 to 108.883
95 dB = fX * 0.0557 + fY * -0.2040 + fZ * 1.0570;
97 if (dR > 0.0031308)
99 dR = 1.055 * (std::pow(dR, 0.41666667)) - 0.055;
101 else
103 dR = 12.92 * dR;
106 if (dG > 0.0031308)
108 dG = 1.055 * (std::pow(dG, 0.41666667)) - 0.055;
110 else
112 dG = 12.92 * dG;
115 if (dB > 0.0031308)
117 dB = 1.055 * (std::pow(dB, 0.41666667)) - 0.055;
119 else
121 dB = 12.92 * dB;
123 dR *= 255;
124 dG *= 255;
125 dB *= 255;
128 // This function based on code under ALv2 - Copyright 2013 István Ujj-Mészáros
129 // credit Avisek Das and István Ujj-Mészáros
130 static void lcl_LABtoXYZ( float fL, float fa, float fb, float& dX, float& dY, float& dZ)
132 dY = (fL + 16) / 116;
133 dX = (fa / 500) + dY;
134 dZ = dY - (fb / 200);
136 if (std::pow(dY, 3) > 0.008856)
138 dY = std::pow(dY, 3);
140 else
142 dY = (dY - 0.137931034) / 7.787;
145 if (std::pow(dX, 3) > 0.008856)
147 dX = std::pow(dX, 3);
149 else
151 dX = (dX - 0.137931034) / 7.787;
154 if (std::pow(dZ, 3) > 0.008856)
156 dZ = std::pow(dZ, 3);
158 else
160 dZ = (dZ - 0.137931034) / 7.787;
163 // Observer = 2°, Illuminant = D65
164 dX = 95.047 * dX;
165 dY = 100.000 * dY;
166 dZ = 108.883 * dZ;
169 static void lcl_LABtoRGB( float fL, float fa, float fb, float& dR, float& dG, float& dB)
171 float x, y, z;
172 lcl_LABtoXYZ(fL, fa, fb, x, y, z);
174 lcl_XYZtoRGB(x, y, z, dR, dG, dB);
177 void PaletteASE::LoadPalette()
179 SvFileStream aFile(maFPath, StreamMode::READ);
180 aFile.SetEndian(SvStreamEndian::BIG);
182 // Verify magic first 4 characters
183 char cMagic[5] = {0};
184 if ((aFile.ReadBytes(cMagic, 4) != 4) || (strncmp(cMagic, "ASEF", 4) != 0))
186 mbValidPalette = false;
187 return;
190 // Ignore the version number
191 aFile.SeekRel(4);
193 sal_uInt32 nBlocks = 0;
194 aFile.ReadUInt32(nBlocks);
195 for (sal_uInt32 nI = 0; nI < nBlocks; nI++) {
196 sal_uInt32 nChunkType = 0;
197 aFile.ReadUInt32(nChunkType);
198 // End chunk
199 if (nChunkType == 0)
200 break;
202 // Grab chunk size, name length
203 sal_uInt16 nChunkSize = 0;
204 sal_uInt16 nChars = 0;
205 aFile.ReadUInt16(nChunkSize);
206 aFile.ReadUInt16(nChars);
208 OUString aPaletteName(u""_ustr);
209 if (nChars > 1)
210 aPaletteName = read_uInt16s_ToOUString(aFile, nChars);
211 else
212 aFile.SeekRel(2);
214 if (nChunkType == 0xC0010000)
216 // Got a start chunk, so set palette name
217 maASEPaletteName = aPaletteName;
218 // Is there color data? (shouldn't happen in a start block, but check anyway)
219 if (nChunkSize > ((nChars * 2) + 2))
220 aPaletteName.clear();
221 else
222 continue;
225 char cColorModel[5] = {0};
226 aFile.ReadBytes(cColorModel, 4);
227 OString aColorModel(cColorModel);
228 // r, g, and b are floats ranging from 0 to 1
229 float r = 0, g = 0, b = 0;
231 if (aColorModel.equalsIgnoreAsciiCase("cmyk"))
233 float c = 0, m = 0, y = 0, k = 0;
234 aFile.ReadFloat(c);
235 aFile.ReadFloat(m);
236 aFile.ReadFloat(y);
237 aFile.ReadFloat(k);
238 lcl_CMYKtoRGB(c, m, y, k, r, g, b);
240 else if (aColorModel.equalsIgnoreAsciiCase("rgb "))
242 aFile.ReadFloat(r);
243 aFile.ReadFloat(g);
244 aFile.ReadFloat(b);
246 else if (aColorModel.equalsIgnoreAsciiCase("gray"))
248 float nVal = 0;
249 aFile.ReadFloat(nVal);
250 r = g = b = nVal;
252 else if (aColorModel.equalsIgnoreAsciiCase("LAB "))
254 float fL = 0, fA = 0, fB = 0;
255 aFile.ReadFloat(fL);
256 aFile.ReadFloat(fA);
257 aFile.ReadFloat(fB);
258 lcl_LABtoRGB(fL, fA, fB, r, g, b);
261 // Ignore color type
262 aFile.SeekRel(2);
263 maColors.emplace_back(Color(r * 255, g * 255, b * 255), aPaletteName);
266 mbValidPalette = true;
269 Palette* PaletteASE::Clone() const
271 return new PaletteASE(*this);
274 // PaletteGPL ------------------------------------------------------------------
276 static OString lcl_getToken(OStringBuffer& rStr, sal_Int32& index);
278 PaletteGPL::PaletteGPL( OUString aFPath, OUString aFName ) :
279 mbLoadedPalette( false ),
280 mbValidPalette( false ),
281 maFName(std::move( aFName )),
282 maFPath(std::move( aFPath ))
284 LoadPaletteHeader();
287 PaletteGPL::~PaletteGPL()
291 const OUString& PaletteGPL::GetName()
293 return maGPLPaletteName;
296 const OUString& PaletteGPL::GetPath()
298 return maFPath;
301 void PaletteGPL::LoadColorSet(SvxColorValueSet& rColorSet)
303 LoadPalette();
305 rColorSet.Clear();
306 int nIx = 1;
307 for (const auto& rColor : maColors)
309 rColorSet.InsertItem(nIx, rColor.m_aColor, rColor.m_aName);
310 ++nIx;
314 bool PaletteGPL::IsValid()
316 return mbValidPalette;
319 bool PaletteGPL::ReadPaletteHeader(SvFileStream& rFileStream)
321 OString aLine;
322 std::string_view aPaletteName;
324 rFileStream.ReadLine(aLine);
325 if( !aLine.startsWith("GIMP Palette") ) return false;
326 rFileStream.ReadLine(aLine);
327 if( aLine.startsWith("Name: ", &aPaletteName) )
329 maGPLPaletteName = OStringToOUString(aPaletteName, RTL_TEXTENCODING_ASCII_US);
330 rFileStream.ReadLine(aLine);
331 if( aLine.startsWith("Columns: "))
332 rFileStream.ReadLine(aLine); // we can ignore this
334 else
336 maGPLPaletteName = maFName;
338 return true;
341 void PaletteGPL::LoadPaletteHeader()
343 SvFileStream aFile(maFPath, StreamMode::READ);
344 mbValidPalette = ReadPaletteHeader( aFile );
347 void PaletteGPL::LoadPalette()
349 if( mbLoadedPalette ) return;
350 mbLoadedPalette = true;
352 // TODO add error handling!!!
353 SvFileStream aFile(maFPath, StreamMode::READ);
354 mbValidPalette = ReadPaletteHeader( aFile );
356 if( !mbValidPalette ) return;
358 OStringBuffer aLine;
359 do {
360 if (aLine.isEmpty())
361 continue;
363 if (aLine[0] != '#' && aLine[0] != '\n')
365 // TODO check if r,g,b are 0<= x <=255, or just clamp?
366 sal_Int32 nIndex = 0;
367 OString token;
369 token = lcl_getToken(aLine, nIndex);
370 if(token.isEmpty() || nIndex == -1) continue;
371 sal_Int32 r = token.toInt32();
373 token = lcl_getToken(aLine, nIndex);
374 if(token.isEmpty() || nIndex == -1) continue;
375 sal_Int32 g = token.toInt32();
377 token = lcl_getToken(aLine, nIndex);
378 if(token.isEmpty()) continue;
379 sal_Int32 b = token.toInt32();
381 std::string_view name;
382 if(nIndex != -1)
383 name = std::string_view(aLine).substr(nIndex);
385 maColors.emplace_back(
386 Color(r, g, b),
387 OStringToOUString(name, RTL_TEXTENCODING_ASCII_US));
389 } while (aFile.ReadLine(aLine));
392 Palette* PaletteGPL::Clone() const
394 return new PaletteGPL(*this);
397 // finds first token in rStr from index, separated by whitespace
398 // returns position of next token in index
399 static OString lcl_getToken(OStringBuffer& rStr, sal_Int32& index)
401 sal_Int32 substart, toklen = 0;
402 OUString aWhitespaceChars( u" \n\t"_ustr );
404 while(index < rStr.getLength() &&
405 aWhitespaceChars.indexOf( rStr[index] ) != -1)
406 ++index;
407 if(index == rStr.getLength())
409 index = -1;
410 return OString();
412 substart = index;
414 //counts length of token
415 while(index < rStr.getLength() &&
416 aWhitespaceChars.indexOf( rStr[index] ) == -1 )
418 ++index;
419 ++toklen;
422 //counts to position of next token
423 while(index < rStr.getLength() &&
424 aWhitespaceChars.indexOf( rStr[index] ) != -1 )
425 ++index;
426 if(index == rStr.getLength())
427 index = -1;
429 return OString(std::string_view(rStr).substr(substart, toklen));
432 // PaletteSOC ------------------------------------------------------------------
434 PaletteSOC::PaletteSOC( OUString aFPath, OUString aFName ) :
435 mbLoadedPalette( false ),
436 maFPath(std::move( aFPath )),
437 maSOCPaletteName(std::move( aFName ))
441 PaletteSOC::~PaletteSOC()
445 const OUString& PaletteSOC::GetName()
447 return maSOCPaletteName;
450 const OUString& PaletteSOC::GetPath()
452 return maFPath;
455 void PaletteSOC::LoadColorSet(SvxColorValueSet& rColorSet)
457 if( !mbLoadedPalette )
459 mbLoadedPalette = true;
460 mpColorList = XPropertyList::AsColorList(XPropertyList::CreatePropertyListFromURL(XPropertyListType::Color, maFPath));
461 (void)mpColorList->Load();
463 rColorSet.Clear();
464 if( mpColorList.is() )
465 rColorSet.addEntriesForXColorList( *mpColorList );
468 bool PaletteSOC::IsValid()
470 return true;
473 Palette* PaletteSOC::Clone() const
475 return new PaletteSOC(*this);
478 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */