docmodel/Library_docmodel.mk | 1 docmodel/source/color/ComplexColor.cxx | 176 ++++++++++++++++++++++++++++++++ include/docmodel/color/ComplexColor.hxx | 141 +++---------------------- include/tools/XmlWriter.hxx | 4 tools/qa/cppunit/test_xmlwriter.cxx | 18 ++- tools/source/xml/XmlWriter.cxx | 32 ++++- 6 files changed, 237 insertions(+), 135 deletions(-)
New commits: commit ecf75f2637ca34eb8f60a0ad5e722d0d1ed9fc5f Author: Tomaž Vajngerl <[email protected]> AuthorDate: Sat Dec 6 22:55:58 2025 +0900 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Mon Dec 8 04:15:21 2025 +0100 tools: support XmlWriter construction from xmlTextWriterPtr So we can use it in dumpAsXml functions and eventually use it as a replacement to directly using libxml. Change-Id: I204d487b52343f69224fec2fd480657785bc0a69 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195167 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <[email protected]> diff --git a/include/tools/XmlWriter.hxx b/include/tools/XmlWriter.hxx index 8947c16ed1ff..1ad34bcdac0e 100644 --- a/include/tools/XmlWriter.hxx +++ b/include/tools/XmlWriter.hxx @@ -20,6 +20,8 @@ #include <o3tl/concepts.hxx> class SvStream; +struct _xmlTextWriter; +typedef struct _xmlTextWriter* xmlTextWriterPtr; namespace tools { @@ -41,7 +43,7 @@ private: public: XmlWriter(SvStream* pStream); - + XmlWriter(xmlTextWriterPtr pWriter); ~XmlWriter(); bool startDocument(sal_Int32 nIndent = 2, bool bWriteXmlHeader = true); diff --git a/tools/qa/cppunit/test_xmlwriter.cxx b/tools/qa/cppunit/test_xmlwriter.cxx index 6ab22950bf4d..61ce47533f13 100644 --- a/tools/qa/cppunit/test_xmlwriter.cxx +++ b/tools/qa/cppunit/test_xmlwriter.cxx @@ -22,25 +22,35 @@ public: { } - virtual void setUp() override {} + void setUp() override {} void testSimpleRoot(); void testSpecialChars(); void testAttributes(); + void testStartAndEndDocument(); CPPUNIT_TEST_SUITE(XmlWriterTest); CPPUNIT_TEST(testSimpleRoot); CPPUNIT_TEST(testSpecialChars); CPPUNIT_TEST(testAttributes); + CPPUNIT_TEST(testStartAndEndDocument); CPPUNIT_TEST_SUITE_END(); }; +void XmlWriterTest::testStartAndEndDocument() +{ + SvMemoryStream aMemoryStream; + tools::XmlWriter aWriter(&aMemoryStream); + CPPUNIT_ASSERT(aWriter.startDocument()); + CPPUNIT_ASSERT(!aWriter.startDocument()); +} + void XmlWriterTest::testSimpleRoot() { SvMemoryStream aMemoryStream; tools::XmlWriter aWriter(&aMemoryStream); - aWriter.startDocument(0, false); + CPPUNIT_ASSERT(aWriter.startDocument(0, false)); aWriter.startElement("test"); aWriter.endElement(); aWriter.endDocument(); @@ -55,7 +65,7 @@ void XmlWriterTest::testSpecialChars() SvMemoryStream aMemoryStream; tools::XmlWriter aWriter(&aMemoryStream); - aWriter.startDocument(0, false); + CPPUNIT_ASSERT(aWriter.startDocument(0, false)); aWriter.startElement("test"); aWriter.content("<>"); aWriter.endElement(); @@ -71,7 +81,7 @@ void XmlWriterTest::testAttributes() SvMemoryStream aMemoryStream; tools::XmlWriter aWriter(&aMemoryStream); - aWriter.startDocument(0, false); + CPPUNIT_ASSERT(aWriter.startDocument(0, false)); aWriter.startElement("test"); aWriter.attribute("c", std::string_view("c")); aWriter.attribute("d", std::u16string_view(u"d")); diff --git a/tools/source/xml/XmlWriter.cxx b/tools/source/xml/XmlWriter.cxx index 5200c3dcd044..0df0b4e2c19d 100644 --- a/tools/source/xml/XmlWriter.cxx +++ b/tools/source/xml/XmlWriter.cxx @@ -42,16 +42,22 @@ requires(sizeof(T) == sizeof(char)) void attributeBase64_impl(xmlTextWriterPtr w struct XmlWriterImpl { + SvStream* mpStream = nullptr; + xmlTextWriterPtr mpWriter = nullptr; + bool mbWriteXmlHeader = true; + bool mbExternalXmlWriter = false; + XmlWriterImpl(SvStream* pStream) : mpStream(pStream) - , mpWriter(nullptr) - , mbWriteXmlHeader(true) { } - SvStream* mpStream; - xmlTextWriterPtr mpWriter; - bool mbWriteXmlHeader; + XmlWriterImpl(xmlTextWriterPtr pWriter) + : mpWriter(pWriter) + , mbWriteXmlHeader(false) + , mbExternalXmlWriter(true) + { + } }; XmlWriter::XmlWriter(SvStream* pStream) @@ -59,29 +65,41 @@ XmlWriter::XmlWriter(SvStream* pStream) { } +XmlWriter::XmlWriter(xmlTextWriterPtr pWriter) + : mpImpl(std::make_unique<XmlWriterImpl>(pWriter)) +{ +} + XmlWriter::~XmlWriter() { - if (mpImpl && mpImpl->mpWriter != nullptr) + if (mpImpl) endDocument(); } bool XmlWriter::startDocument(sal_Int32 nIndent, bool bWriteXmlHeader) { + if (mpImpl->mpWriter) + return false; + mpImpl->mbWriteXmlHeader = bWriteXmlHeader; xmlCharEncodingHandlerPtr pEncodingHandler = xmlGetCharEncodingHandler(XML_CHAR_ENCODING_UTF8); xmlOutputBufferPtr xmlOutBuffer = xmlOutputBufferCreateIO(funcWriteCallback, funcCloseCallback, mpImpl->mpStream, pEncodingHandler); mpImpl->mpWriter = xmlNewTextWriter(xmlOutBuffer); - if (mpImpl->mpWriter == nullptr) + if (!mpImpl->mpWriter) return false; xmlTextWriterSetIndent(mpImpl->mpWriter, nIndent); if (mpImpl->mbWriteXmlHeader) (void)xmlTextWriterStartDocument(mpImpl->mpWriter, nullptr, "UTF-8", nullptr); + return true; } void XmlWriter::endDocument() { + if (!mpImpl->mpWriter || mpImpl->mbExternalXmlWriter) + return; + if (mpImpl->mbWriteXmlHeader) (void)xmlTextWriterEndDocument(mpImpl->mpWriter); xmlFreeTextWriter(mpImpl->mpWriter); commit 1dbe0aa24f8276fc03da81813c19d980a4463633 Author: Tomaž Vajngerl <[email protected]> AuthorDate: Sat Dec 6 22:00:05 2025 +0900 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Mon Dec 8 04:15:06 2025 +0100 docmodel: add ComplexColor.cxx and move function definitions there No need to be a template only class. Change-Id: I3d73fe18443662205967ce5904233a93d7785164 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/195166 Reviewed-by: Tomaž Vajngerl <[email protected]> Tested-by: Jenkins diff --git a/docmodel/Library_docmodel.mk b/docmodel/Library_docmodel.mk index 1de5c254a110..01e63c4b7e48 100644 --- a/docmodel/Library_docmodel.mk +++ b/docmodel/Library_docmodel.mk @@ -18,6 +18,7 @@ $(eval $(call gb_Library_add_exception_objects,docmodel,\ docmodel/source/theme/ColorSet \ docmodel/source/theme/Theme \ docmodel/source/color/ComplexColorJSON \ + docmodel/source/color/ComplexColor \ docmodel/source/styles/ChartStyle \ docmodel/source/styles/ChartColorStyle \ )) diff --git a/docmodel/source/color/ComplexColor.cxx b/docmodel/source/color/ComplexColor.cxx new file mode 100644 index 000000000000..4b957abad991 --- /dev/null +++ b/docmodel/source/color/ComplexColor.cxx @@ -0,0 +1,176 @@ +/* -*- 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/. + * + */ + +#include <docmodel/color/ComplexColor.hxx> +#include <sal/log.hxx> +#include <tools/color.hxx> +#include <docmodel/theme/ThemeColorType.hxx> +#include <docmodel/color/Transformation.hxx> +#include <o3tl/hash_combine.hxx> + +namespace model +{ +void ComplexColor::addTransformation(Transformation const& rTransform) +{ + maTransformations.push_back(rTransform); +} + +void ComplexColor::removeTransformations(TransformationType eType) +{ + std::erase_if(maTransformations, + [eType](Transformation const& rTransform) { return rTransform.meType == eType; }); +} + +void ComplexColor::setCRGB(sal_Int32 nR, sal_Int32 nG, sal_Int32 nB) +{ + mnComponent1 = nR; + mnComponent2 = nG; + mnComponent3 = nB; + meType = ColorType::CRGB; +} + +void ComplexColor::setRGB(double r, double g, double b) +{ + mnComponent1 = r; + mnComponent2 = g; + mnComponent3 = b; + maFinalColor = ::Color(sal_Int8(r), sal_Int8(g), sal_Int8(b)); + meType = ColorType::RGB; +} + +void ComplexColor::getRGB(double& r, double& g, double& b) +{ + if (meType != ColorType::RGB) + return; + r = mnComponent1; + g = mnComponent2; + b = mnComponent3; +} + +Color ComplexColor::getRGB() const { return Color(mnComponent1, mnComponent2, mnComponent3); } + +void ComplexColor::setColor(Color const& rColor) +{ + mnComponent1 = rColor.GetRed(); + mnComponent2 = rColor.GetGreen(); + mnComponent3 = rColor.GetBlue(); + maFinalColor = rColor; + meType = ColorType::RGB; +} + +void ComplexColor::setRGB(sal_Int32 nRGB) +{ + ::Color aColor(ColorTransparency, nRGB); + setColor(aColor); +} + +void ComplexColor::setHSL(sal_Int32 nH, sal_Int32 nS, sal_Int32 nL) +{ + mnComponent1 = nH; + mnComponent2 = nS; + mnComponent3 = nL; + meType = ColorType::HSL; +} + +void ComplexColor::setSystemColor(SystemColorType eSystemColorType, sal_Int32 nRGB) +{ + maLastColor = ::Color(ColorTransparency, nRGB); + meSystemColorType = eSystemColorType; + meType = ColorType::System; +} + +bool ComplexColor::isOpaque() const +{ + for (const Transformation& t : maTransformations) + { + if (t.meType == model::TransformationType::Alpha && t.mnValue != 10000) + { + return false; + } + } + return true; +} + +bool ComplexColor::isTransparent() const +{ + for (const Transformation& t : maTransformations) + { + if (t.meType == model::TransformationType::Alpha && t.mnValue == 0) + { + return true; + } + } + return false; +} + +void ComplexColor::setThemeColor(ThemeColorType eType) +{ + meThemeColorType = eType; + meType = ColorType::Theme; +} + +bool ComplexColor::operator==(const ComplexColor& rComplexColor) const +{ + return meType == rComplexColor.meType && mnComponent1 == rComplexColor.mnComponent1 + && mnComponent2 == rComplexColor.mnComponent2 + && mnComponent3 == rComplexColor.mnComponent3 + && meSystemColorType == rComplexColor.meSystemColorType + && maLastColor == rComplexColor.maLastColor + && meThemeColorType == rComplexColor.meThemeColorType + && maTransformations.size() == rComplexColor.maTransformations.size() + && std::equal(maTransformations.begin(), maTransformations.end(), + rComplexColor.maTransformations.begin()); +} + +Color ComplexColor::applyTransformations(Color const& rColor) const +{ + Color aColor(rColor); + + for (auto const& rTransform : maTransformations) + { + switch (rTransform.meType) + { + case TransformationType::Tint: + aColor.ApplyTintOrShade(rTransform.mnValue); + break; + case TransformationType::Shade: + aColor.ApplyTintOrShade(-rTransform.mnValue); + break; + case TransformationType::LumMod: + aColor.ApplyLumModOff(rTransform.mnValue, 0); + break; + case TransformationType::LumOff: + aColor.ApplyLumModOff(10000, rTransform.mnValue); + break; + default: + break; + } + } + return aColor; +} + +std::size_t ComplexColor::getHash() const +{ + std::size_t seed = 0; + o3tl::hash_combine(seed, meType); + o3tl::hash_combine(seed, mnComponent1); + o3tl::hash_combine(seed, mnComponent2); + o3tl::hash_combine(seed, mnComponent3); + o3tl::hash_combine(seed, meSystemColorType); + o3tl::hash_combine(seed, sal_uInt32(maLastColor)); + for (auto const& rTransform : maTransformations) + o3tl::hash_combine(seed, rTransform); + o3tl::hash_combine(seed, sal_uInt32(maFinalColor)); + return seed; +} + +} // end of namespace model + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/docmodel/color/ComplexColor.hxx b/include/docmodel/color/ComplexColor.hxx index e57530936bda..0333b128fadf 100644 --- a/include/docmodel/color/ComplexColor.hxx +++ b/include/docmodel/color/ComplexColor.hxx @@ -142,17 +142,9 @@ public: maTransformations = rTransformations; } - void addTransformation(Transformation const& rTransform) - { - maTransformations.push_back(rTransform); - } + void addTransformation(Transformation const& rTransform); - void removeTransformations(TransformationType eType) - { - std::erase_if(maTransformations, [eType](Transformation const& rTransform) { - return rTransform.meType == eType; - }); - } + void removeTransformations(TransformationType eType); void clearTransformations() { maTransformations.clear(); } @@ -160,137 +152,40 @@ public: double getGreen() const { return mnComponent2; } double getBlue() const { return mnComponent3; } - void setCRGB(sal_Int32 nR, sal_Int32 nG, sal_Int32 nB) - { - mnComponent1 = nR; - mnComponent2 = nG; - mnComponent3 = nB; - meType = ColorType::CRGB; - } + void setCRGB(sal_Int32 nR, sal_Int32 nG, sal_Int32 nB); - Color getRGB() const { return Color(mnComponent1, mnComponent2, mnComponent3); } + void setRGB(double r, double g, double b); - void setColor(Color const& rColor) - { - mnComponent1 = rColor.GetRed(); - mnComponent2 = rColor.GetGreen(); - mnComponent3 = rColor.GetBlue(); - maFinalColor = rColor; - meType = ColorType::RGB; - } + void getRGB(double& r, double& g, double& b); - void setRGB(sal_Int32 nRGB) - { - ::Color aColor(ColorTransparency, nRGB); - setColor(aColor); - } + Color getRGB() const; - void setHSL(sal_Int32 nH, sal_Int32 nS, sal_Int32 nL) - { - mnComponent1 = nH; - mnComponent2 = nS; - mnComponent3 = nL; - meType = ColorType::HSL; - } + void setColor(Color const& rColor); - void setSystemColor(SystemColorType eSystemColorType, sal_Int32 nRGB) - { - maLastColor = ::Color(ColorTransparency, nRGB); - meSystemColorType = eSystemColorType; - meType = ColorType::System; - } + void setRGB(sal_Int32 nRGB); - bool isOpaque() const - { - for (const Transformation& t : maTransformations) - { - if (t.meType == model::TransformationType::Alpha && t.mnValue != 10000) - { - return false; - } - } - return true; - } + void setHSL(sal_Int32 nH, sal_Int32 nS, sal_Int32 nL); - bool isTransparent() const - { - for (const Transformation& t : maTransformations) - { - if (t.meType == model::TransformationType::Alpha && t.mnValue == 0) - { - return true; - } - } - return false; - } + void setSystemColor(SystemColorType eSystemColorType, sal_Int32 nRGB); + + bool isOpaque() const; + + bool isTransparent() const; void setThemePlaceholder() { meType = ColorType::Placeholder; } - void setThemeColor(ThemeColorType eType) - { - meThemeColorType = eType; - meType = ColorType::Theme; - } + void setThemeColor(ThemeColorType eType); - bool operator==(const ComplexColor& rComplexColor) const - { - return meType == rComplexColor.meType && mnComponent1 == rComplexColor.mnComponent1 - && mnComponent2 == rComplexColor.mnComponent2 - && mnComponent3 == rComplexColor.mnComponent3 - && meSystemColorType == rComplexColor.meSystemColorType - && maLastColor == rComplexColor.maLastColor - && meThemeColorType == rComplexColor.meThemeColorType - && maTransformations.size() == rComplexColor.maTransformations.size() - && std::equal(maTransformations.begin(), maTransformations.end(), - rComplexColor.maTransformations.begin()); - } + bool operator==(const ComplexColor& rComplexColor) const; /** Applies the defined transformations to the input color */ - Color applyTransformations(Color const& rColor) const - { - Color aColor(rColor); - - for (auto const& rTransform : maTransformations) - { - switch (rTransform.meType) - { - case TransformationType::Tint: - aColor.ApplyTintOrShade(rTransform.mnValue); - break; - case TransformationType::Shade: - aColor.ApplyTintOrShade(-rTransform.mnValue); - break; - case TransformationType::LumMod: - aColor.ApplyLumModOff(rTransform.mnValue, 0); - break; - case TransformationType::LumOff: - aColor.ApplyLumModOff(10000, rTransform.mnValue); - break; - default: - break; - } - } - return aColor; - } + Color applyTransformations(Color const& rColor) const; void setFinalColor(Color const& rColor) { maFinalColor = rColor; } Color const& getFinalColor() const { return maFinalColor; } - std::size_t getHash() const - { - std::size_t seed = 0; - o3tl::hash_combine(seed, meType); - o3tl::hash_combine(seed, mnComponent1); - o3tl::hash_combine(seed, mnComponent2); - o3tl::hash_combine(seed, mnComponent3); - o3tl::hash_combine(seed, meSystemColorType); - o3tl::hash_combine(seed, sal_uInt32(maLastColor)); - for (auto const& rTransform : maTransformations) - o3tl::hash_combine(seed, rTransform); - o3tl::hash_combine(seed, sal_uInt32(maFinalColor)); - return seed; - } + std::size_t getHash() const; static model::ComplexColor createRGB(Color const& rColor) {
