summaryrefslogtreecommitdiffstats
path: root/svx/source/tbxctrls/Palette.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'svx/source/tbxctrls/Palette.cxx')
-rw-r--r--svx/source/tbxctrls/Palette.cxx383
1 files changed, 383 insertions, 0 deletions
diff --git a/svx/source/tbxctrls/Palette.cxx b/svx/source/tbxctrls/Palette.cxx
new file mode 100644
index 0000000000..b3f1965de3
--- /dev/null
+++ b/svx/source/tbxctrls/Palette.cxx
@@ -0,0 +1,383 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <svx/Palette.hxx>
+#include <tools/stream.hxx>
+
+#include <palettes.hxx>
+#include <utility>
+
+Palette::~Palette()
+{
+}
+
+PaletteASE::~PaletteASE()
+{
+}
+
+PaletteASE::PaletteASE( OUString aFPath, OUString aFName ) :
+ mbValidPalette( false ),
+ maFPath (std::move( aFPath )),
+ maASEPaletteName (std::move( aFName ))
+{
+ LoadPalette();
+}
+
+void PaletteASE::LoadColorSet(SvxColorValueSet& rColorSet)
+{
+ rColorSet.Clear();
+ int nIx = 1;
+ for (const auto& rColor : maColors)
+ {
+ rColorSet.InsertItem(nIx, rColor.m_aColor, rColor.m_aName);
+ ++nIx;
+ }
+}
+
+const OUString& PaletteASE::GetName()
+{
+ return maASEPaletteName;
+}
+
+const OUString& PaletteASE::GetPath()
+{
+ return maFPath;
+}
+
+bool PaletteASE::IsValid()
+{
+ return mbValidPalette;
+}
+
+// CMYK values from 0 to 1
+// TODO: Deduplicate me (taken from core/cui/source/dialogs/colorpicker.cxx)
+static void lcl_CMYKtoRGB( float fCyan, float fMagenta, float fYellow, float fKey, float& dR, float& dG, float& dB )
+{
+ fCyan = (fCyan * ( 1.0 - fKey )) + fKey;
+ fMagenta = (fMagenta * ( 1.0 - fKey )) + fKey;
+ fYellow = (fYellow * ( 1.0 - fKey )) + fKey;
+
+ dR = std::clamp( 1.0 - fCyan, 0.0, 1.0 );
+ dG = std::clamp( 1.0 - fMagenta, 0.0, 1.0 );
+ dB = std::clamp( 1.0 - fYellow, 0.0, 1.0 );
+}
+
+void PaletteASE::LoadPalette()
+{
+ SvFileStream aFile(maFPath, StreamMode::READ);
+ aFile.SetEndian(SvStreamEndian::BIG);
+
+ // Verify magic first 4 characters
+ char cMagic[5] = {0};
+ if ((aFile.ReadBytes(cMagic, 4) != 4) || (strncmp(cMagic, "ASEF", 4) != 0))
+ {
+ mbValidPalette = false;
+ return;
+ }
+
+ // Ignore the version number
+ aFile.SeekRel(4);
+
+ sal_uInt32 nBlocks = 0;
+ aFile.ReadUInt32(nBlocks);
+ for (sal_uInt32 nI = 0; nI < nBlocks; nI++) {
+ sal_uInt32 nChunkType = 0;
+ aFile.ReadUInt32(nChunkType);
+ // End chunk
+ if (nChunkType == 0)
+ break;
+
+ // Grab chunk size, name length
+ sal_uInt16 nChunkSize = 0;
+ sal_uInt16 nChars = 0;
+ aFile.ReadUInt16(nChunkSize);
+ aFile.ReadUInt16(nChars);
+
+ OUString aPaletteName("");
+ if (nChars > 1)
+ aPaletteName = read_uInt16s_ToOUString(aFile, nChars);
+ else
+ aFile.SeekRel(2);
+
+ if (nChunkType == 0xC0010000)
+ {
+ // Got a start chunk, so set palette name
+ maASEPaletteName = aPaletteName;
+ // Is there color data? (shouldn't happen in a start block, but check anyway)
+ if (nChunkSize > ((nChars * 2) + 2))
+ aPaletteName.clear();
+ else
+ continue;
+ }
+
+ char cColorModel[5] = {0};
+ aFile.ReadBytes(cColorModel, 4);
+ OString aColorModel(cColorModel);
+ // r, g, and b are floats ranging from 0 to 1
+ float r = 0, g = 0, b = 0;
+
+ if (aColorModel.equalsIgnoreAsciiCase("cmyk"))
+ {
+ float c = 0, m = 0, y = 0, k = 0;
+ aFile.ReadFloat(c);
+ aFile.ReadFloat(m);
+ aFile.ReadFloat(y);
+ aFile.ReadFloat(k);
+ lcl_CMYKtoRGB(c, m, y, k, r, g, b);
+ }
+ else if (aColorModel.equalsIgnoreAsciiCase("rgb "))
+ {
+ aFile.ReadFloat(r);
+ aFile.ReadFloat(g);
+ aFile.ReadFloat(b);
+ }
+ else if (aColorModel.equalsIgnoreAsciiCase("gray"))
+ {
+ float nVal = 0;
+ aFile.ReadFloat(nVal);
+ r = g = b = nVal;
+ }
+ else
+ {
+ float nL = 0, nA = 0, nB = 0;
+ aFile.ReadFloat(nL);
+ aFile.ReadFloat(nA);
+ aFile.ReadFloat(nB);
+ // TODO: How to convert LAB to RGB?
+ r = g = b = 0;
+ }
+
+ // Ignore color type
+ aFile.SeekRel(2);
+ maColors.emplace_back(Color(r * 255, g * 255, b * 255), aPaletteName);
+ }
+
+ mbValidPalette = true;
+}
+
+Palette* PaletteASE::Clone() const
+{
+ return new PaletteASE(*this);
+}
+
+// PaletteGPL ------------------------------------------------------------------
+
+static OString lcl_getToken(OStringBuffer& rStr, sal_Int32& index);
+
+PaletteGPL::PaletteGPL( OUString aFPath, OUString aFName ) :
+ mbLoadedPalette( false ),
+ mbValidPalette( false ),
+ maFName(std::move( aFName )),
+ maFPath(std::move( aFPath ))
+{
+ LoadPaletteHeader();
+}
+
+PaletteGPL::~PaletteGPL()
+{
+}
+
+const OUString& PaletteGPL::GetName()
+{
+ return maGPLPaletteName;
+}
+
+const OUString& PaletteGPL::GetPath()
+{
+ return maFPath;
+}
+
+void PaletteGPL::LoadColorSet(SvxColorValueSet& rColorSet)
+{
+ LoadPalette();
+
+ rColorSet.Clear();
+ int nIx = 1;
+ for (const auto& rColor : maColors)
+ {
+ rColorSet.InsertItem(nIx, rColor.m_aColor, rColor.m_aName);
+ ++nIx;
+ }
+}
+
+bool PaletteGPL::IsValid()
+{
+ return mbValidPalette;
+}
+
+bool PaletteGPL::ReadPaletteHeader(SvFileStream& rFileStream)
+{
+ OString aLine;
+ OString aPaletteName;
+
+ rFileStream.ReadLine(aLine);
+ if( !aLine.startsWith("GIMP Palette") ) return false;
+ rFileStream.ReadLine(aLine);
+ if( aLine.startsWith("Name: ", &aPaletteName) )
+ {
+ maGPLPaletteName = OStringToOUString(aPaletteName, RTL_TEXTENCODING_ASCII_US);
+ rFileStream.ReadLine(aLine);
+ if( aLine.startsWith("Columns: "))
+ rFileStream.ReadLine(aLine); // we can ignore this
+ }
+ else
+ {
+ maGPLPaletteName = maFName;
+ }
+ return true;
+}
+
+void PaletteGPL::LoadPaletteHeader()
+{
+ SvFileStream aFile(maFPath, StreamMode::READ);
+ mbValidPalette = ReadPaletteHeader( aFile );
+}
+
+void PaletteGPL::LoadPalette()
+{
+ if( mbLoadedPalette ) return;
+ mbLoadedPalette = true;
+
+ // TODO add error handling!!!
+ SvFileStream aFile(maFPath, StreamMode::READ);
+ mbValidPalette = ReadPaletteHeader( aFile );
+
+ if( !mbValidPalette ) return;
+
+ OStringBuffer aLine;
+ do {
+ if (aLine.isEmpty())
+ continue;
+
+ if (aLine[0] != '#' && aLine[0] != '\n')
+ {
+ // TODO check if r,g,b are 0<= x <=255, or just clamp?
+ sal_Int32 nIndex = 0;
+ OString token;
+
+ token = lcl_getToken(aLine, nIndex);
+ if(token.isEmpty() || nIndex == -1) continue;
+ sal_Int32 r = token.toInt32();
+
+ token = lcl_getToken(aLine, nIndex);
+ if(token.isEmpty() || nIndex == -1) continue;
+ sal_Int32 g = token.toInt32();
+
+ token = lcl_getToken(aLine, nIndex);
+ if(token.isEmpty()) continue;
+ sal_Int32 b = token.toInt32();
+
+ std::string_view name;
+ if(nIndex != -1)
+ name = std::string_view(aLine).substr(nIndex);
+
+ maColors.emplace_back(
+ Color(r, g, b),
+ OStringToOUString(name, RTL_TEXTENCODING_ASCII_US));
+ }
+ } while (aFile.ReadLine(aLine));
+}
+
+Palette* PaletteGPL::Clone() const
+{
+ return new PaletteGPL(*this);
+}
+
+// finds first token in rStr from index, separated by whitespace
+// returns position of next token in index
+static OString lcl_getToken(OStringBuffer& rStr, sal_Int32& index)
+{
+ sal_Int32 substart, toklen = 0;
+ OUString aWhitespaceChars( " \n\t" );
+
+ while(index < rStr.getLength() &&
+ aWhitespaceChars.indexOf( rStr[index] ) != -1)
+ ++index;
+ if(index == rStr.getLength())
+ {
+ index = -1;
+ return OString();
+ }
+ substart = index;
+
+ //counts length of token
+ while(index < rStr.getLength() &&
+ aWhitespaceChars.indexOf( rStr[index] ) == -1 )
+ {
+ ++index;
+ ++toklen;
+ }
+
+ //counts to position of next token
+ while(index < rStr.getLength() &&
+ aWhitespaceChars.indexOf( rStr[index] ) != -1 )
+ ++index;
+ if(index == rStr.getLength())
+ index = -1;
+
+ return OString(std::string_view(rStr).substr(substart, toklen));
+}
+
+// PaletteSOC ------------------------------------------------------------------
+
+PaletteSOC::PaletteSOC( OUString aFPath, OUString aFName ) :
+ mbLoadedPalette( false ),
+ maFPath(std::move( aFPath )),
+ maSOCPaletteName(std::move( aFName ))
+{
+}
+
+PaletteSOC::~PaletteSOC()
+{
+}
+
+const OUString& PaletteSOC::GetName()
+{
+ return maSOCPaletteName;
+}
+
+const OUString& PaletteSOC::GetPath()
+{
+ return maFPath;
+}
+
+void PaletteSOC::LoadColorSet(SvxColorValueSet& rColorSet)
+{
+ if( !mbLoadedPalette )
+ {
+ mbLoadedPalette = true;
+ mpColorList = XPropertyList::AsColorList(XPropertyList::CreatePropertyListFromURL(XPropertyListType::Color, maFPath));
+ (void)mpColorList->Load();
+ }
+ rColorSet.Clear();
+ if( mpColorList.is() )
+ rColorSet.addEntriesForXColorList( *mpColorList );
+}
+
+bool PaletteSOC::IsValid()
+{
+ return true;
+}
+
+Palette* PaletteSOC::Clone() const
+{
+ return new PaletteSOC(*this);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */