include/docmodel/theme/FormatScheme.hxx | 49 +++++++++--- include/oox/export/ThemeExport.hxx | 5 - include/oox/export/drawingml.hxx | 3 oox/source/drawingml/misccontexts.cxx | 42 ++++++++-- oox/source/export/ThemeExport.cxx | 13 ++- oox/source/export/drawingml.cxx | 126 ++++++++++++++++++++++++++++++- sd/source/filter/eppt/pptx-epptooxml.cxx | 2 7 files changed, 215 insertions(+), 25 deletions(-)
New commits: commit 6252959192c07973af698ce30fa67b1a29e4871e Author: Tomaž Vajngerl <[email protected]> AuthorDate: Wed Apr 12 11:18:42 2023 +0900 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Tue Apr 25 13:38:18 2023 +0200 oox: add support for theme import and export of blip effects This adds support for (most) blip effects import, export and the document model. Change-Id: Iec15f4de22c31268019fa1a60432e40ae8f03635 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150262 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <[email protected]> diff --git a/include/docmodel/theme/FormatScheme.hxx b/include/docmodel/theme/FormatScheme.hxx index 420d5c1b7584..fb65d24d2ba8 100644 --- a/include/docmodel/theme/FormatScheme.hxx +++ b/include/docmodel/theme/FormatScheme.hxx @@ -311,12 +311,49 @@ enum class RectangleAlignment constexpr sal_uInt16 RECTANGLE_ALIGNMENT_COUNT = static_cast<sal_uInt16>(RectangleAlignment::BottomRight) + 1; -enum class ColorEffectType +enum class BlipEffectType { None, + AlphaBiLevel, + AlphaCeiling, + AlphaFloor, + AlphaInverse, + AlphaModulate, + AlphaModulateFixed, + AlphaReplace, BiLevel, + Blur, + ColorChange, + ColorReplace, + DuoTone, + FillOverlay, Grayscale, - ColorChange + HSL, + Luminance, + Tint, +}; + +class BlipEffect +{ +public: + BlipEffectType meType = BlipEffectType::None; + + sal_Int32 mnThreshold = 0; // AlphaBiLevel, BiLevel + ColorDefinition maColor1; // AlphaInverse, ColorReplace, DuoTone, ColorChange (from) + ColorDefinition maColor2; // DuoTone, ColorChange (to) + sal_Int32 mnAmount = 0; // AlphaModulateFixed, Tint + sal_Int32 mnRadius = 0; // Blur + bool mbGrow = false; // Blur + sal_Int32 mnAlpha = 0; // AlphaReplace + bool mbUseAlpha = false; // ColorChange + sal_Int32 mnHue = 0; // HSL, Tint + sal_Int32 mnSaturation = 0; // HSL + sal_Int32 mnLuminance = 0; // HSL + sal_Int32 mnBrightness = 0; // Luminance + sal_Int32 mnContrast = 0; // Luminance + + ColorDefinition& getColorFrom() { return maColor1; } + ColorDefinition& getColorTo() { return maColor2; } }; class DOCMODEL_DLLPUBLIC BlipFill : public Fill @@ -335,13 +372,7 @@ public: RectangleAlignment meTileAlignment = RectangleAlignment::TopLeft; css::uno::Reference<css::graphic::XGraphic> mxGraphic; - - ColorEffectType meColorEffectType = ColorEffectType::None; - - sal_Int32 mnBiLevelThreshold = 0; - ColorDefinition maColorFrom; - ColorDefinition maColorTo; - bool mbUseAlpha = false; + std::vector<BlipEffect> maBlipEffects; BlipFill() : Fill(FillType::Blip) diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx index c9cf16cb1463..6cba4b06b6e0 100644 --- a/include/oox/export/drawingml.hxx +++ b/include/oox/export/drawingml.hxx @@ -264,7 +264,7 @@ public: {} OUString writeToStorage(Graphic const& rGraphic, bool bRelPathToMedia = false); - OUString writeBlip(Graphic const& rGraphic , bool bRelPathToMedia = false); + OUString writeBlip(Graphic const& rGraphic, std::vector<model::BlipEffect> const& rEffects, bool bRelPathToMedia = false); }; class OOX_DLLPUBLIC DrawingML diff --git a/oox/source/drawingml/misccontexts.cxx b/oox/source/drawingml/misccontexts.cxx index bf3ec6e4fb03..26df16a17553 100644 --- a/oox/source/drawingml/misccontexts.cxx +++ b/oox/source/drawingml/misccontexts.cxx @@ -253,8 +253,9 @@ ColorChangeContext::ColorChangeContext( ContextHandler2Helper const & rParent, mbUseAlpha = rAttribs.getBool( XML_useA, true ); if (mpBlipFill) { - mpBlipFill->meColorEffectType = model::ColorEffectType::ColorChange; - mpBlipFill->mbUseAlpha = mbUseAlpha; + auto& rEffect = mpBlipFill->maBlipEffects.emplace_back(); + rEffect.meType = model::BlipEffectType::ColorChange; + rEffect.mbUseAlpha = mbUseAlpha; } } @@ -272,11 +273,17 @@ ContextHandlerRef ColorChangeContext::onCreateContext( { case A_TOKEN(clrFrom): if (mpBlipFill) - pColorDefinition = &mpBlipFill->maColorFrom; + { + auto& rEffect = mpBlipFill->maBlipEffects.back(); + pColorDefinition = &rEffect.getColorFrom(); + } return new ColorContext(*this, mrBlipProps.maColorChangeFrom, pColorDefinition); case A_TOKEN(clrTo): if (mpBlipFill) - pColorDefinition = &mpBlipFill->maColorTo; + { + auto& rEffect = mpBlipFill->maBlipEffects.back(); + pColorDefinition = &rEffect.getColorTo(); + } return new ColorContext(*this, mrBlipProps.maColorChangeTo, pColorDefinition); } return nullptr; @@ -325,12 +332,16 @@ ContextHandlerRef BlipContext::onCreateContext( { case A_TOKEN( biLevel ): { - mrBlipProps.moBiLevelThreshold = rAttribs.getInteger( XML_thresh ); + sal_Int32 nTreshold = rAttribs.getInteger(XML_thresh, 0); + + mrBlipProps.moBiLevelThreshold = nTreshold; mrBlipProps.moColorEffect = getBaseToken(nElement); + if (mpBlipFill) { - mpBlipFill->meColorEffectType = model::ColorEffectType::BiLevel; - mpBlipFill->mnBiLevelThreshold = rAttribs.getInteger(XML_thresh, 0); + auto& rEffect = mpBlipFill->maBlipEffects.emplace_back(); + rEffect.meType = model::BlipEffectType::BiLevel; + rEffect.mnThreshold = nTreshold; } } break; @@ -340,7 +351,8 @@ ContextHandlerRef BlipContext::onCreateContext( mrBlipProps.moColorEffect = getBaseToken( nElement ); if (mpBlipFill) { - mpBlipFill->meColorEffectType = model::ColorEffectType::Grayscale; + auto& rEffect = mpBlipFill->maBlipEffects.emplace_back(); + rEffect.meType = model::BlipEffectType::Grayscale; } } break; @@ -360,11 +372,25 @@ ContextHandlerRef BlipContext::onCreateContext( { mrBlipProps.moBrightness = rAttribs.getInteger( XML_bright ); mrBlipProps.moContrast = rAttribs.getInteger( XML_contrast ); + + if (mpBlipFill) + { + auto& rEffect = mpBlipFill->maBlipEffects.emplace_back(); + rEffect.meType = model::BlipEffectType::Luminance; + rEffect.mnBrightness = rAttribs.getInteger(XML_bright, 0); + rEffect.mnContrast = rAttribs.getInteger(XML_contrast, 0); + } } break; case A_TOKEN( alphaModFix ): { mrBlipProps.moAlphaModFix = rAttribs.getInteger(XML_amt); + if (mpBlipFill) + { + auto& rEffect = mpBlipFill->maBlipEffects.emplace_back(); + rEffect.meType = model::BlipEffectType::AlphaModulateFixed; + rEffect.mnAmount = rAttribs.getInteger(XML_amt, 100 * 1000); + } } break; } diff --git a/oox/source/export/ThemeExport.cxx b/oox/source/export/ThemeExport.cxx index 16da603fa14c..88ff2d6364fc 100644 --- a/oox/source/export/ThemeExport.cxx +++ b/oox/source/export/ThemeExport.cxx @@ -581,13 +581,13 @@ OString convertRectangleAlignment(model::RectangleAlignment eFlipMode) } } // end anonymous ns -void ThemeExport::writeBlip(model::BlipFill const& rBlipFil) +void ThemeExport::writeBlip(model::BlipFill const& rBlipFill) { - if (!rBlipFil.mxGraphic.is()) + if (!rBlipFill.mxGraphic.is()) return; oox::drawingml::GraphicExport aExporter(mpFS, mpFilterBase, meDocumentType); - Graphic aGraphic(rBlipFil.mxGraphic); - aExporter.writeBlip(aGraphic, false); + Graphic aGraphic(rBlipFill.mxGraphic); + aExporter.writeBlip(aGraphic, rBlipFill.maBlipEffects, false); } void ThemeExport::writeBlipFill(model::BlipFill const& rBlipFill) diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index f58e76eda95e..aaad66b4d083 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -1475,7 +1475,7 @@ const char* DrawingML::GetRelationCompPrefix() const return getRelationCompPrefix(meDocumentType); } -OUString GraphicExport::writeBlip(Graphic const& rGraphic , bool bRelPathToMedia) +OUString GraphicExport::writeBlip(Graphic const& rGraphic, std::vector<model::BlipEffect> const& rEffects, bool bRelPathToMedia) { OUString sRelId; @@ -1483,8 +1483,114 @@ OUString GraphicExport::writeBlip(Graphic const& rGraphic , bool bRelPathToMedia mpFS->startElementNS(XML_a, XML_blip, FSNS(XML_r, XML_embed), sRelId); - //WriteImageBrightnessContrastTransparence(rXPropSet); - //WriteArtisticEffect(rXPropSet); + for (auto const& rEffect : rEffects) + { + switch (rEffect.meType) + { + case model::BlipEffectType::AlphaBiLevel: + { + mpFS->singleElementNS(XML_a, XML_alphaBiLevel, XML_thresh, OString::number(rEffect.mnThreshold)); + } + break; + case model::BlipEffectType::AlphaCeiling: + { + mpFS->singleElementNS(XML_a, XML_alphaCeiling); + } + break; + case model::BlipEffectType::AlphaFloor: + { + mpFS->singleElementNS(XML_a, XML_alphaFloor); + } + break; + case model::BlipEffectType::AlphaInverse: + { + mpFS->singleElementNS(XML_a, XML_alphaInv); + // TODO: export rEffect.maColor1 + } + break; + case model::BlipEffectType::AlphaModulate: + { + mpFS->singleElementNS(XML_a, XML_alphaMod); + // TODO + } + break; + case model::BlipEffectType::AlphaModulateFixed: + { + mpFS->singleElementNS(XML_a, XML_alphaModFix, XML_amt, OString::number(rEffect.mnAmount)); + } + break; + case model::BlipEffectType::AlphaReplace: + { + mpFS->singleElementNS(XML_a, XML_alphaRepl, XML_a, OString::number(rEffect.mnAlpha)); + } + break; + case model::BlipEffectType::BiLevel: + { + mpFS->singleElementNS(XML_a, XML_biLevel, XML_thresh, OString::number(rEffect.mnThreshold)); + } + break; + case model::BlipEffectType::Blur: + { + mpFS->singleElementNS(XML_a, XML_blur, + XML_rad, OString::number(rEffect.mnRadius), + XML_grow, rEffect.mbGrow ? "1" : "0"); + } + break; + case model::BlipEffectType::ColorChange: + { + mpFS->startElementNS(XML_a, XML_clrChange, XML_useA, rEffect.mbUseAlpha ? "1" : "0"); + mpFS->endElementNS(XML_a, XML_clrChange); + } + break; + case model::BlipEffectType::ColorReplace: + { + mpFS->startElementNS(XML_a, XML_clrRepl); + mpFS->endElementNS(XML_a, XML_clrRepl); + } + break; + case model::BlipEffectType::DuoTone: + { + mpFS->startElementNS(XML_a, XML_duotone); + mpFS->endElementNS(XML_a, XML_duotone); + } + break; + case model::BlipEffectType::FillOverlay: + { + mpFS->singleElementNS(XML_a, XML_fillOverlay); + } + break; + case model::BlipEffectType::Grayscale: + { + mpFS->singleElementNS(XML_a, XML_grayscl); + } + break; + case model::BlipEffectType::HSL: + { + mpFS->singleElementNS(XML_a, XML_hsl, + XML_hue, OString::number(rEffect.mnHue), + XML_sat, OString::number(rEffect.mnSaturation), + XML_lum, OString::number(rEffect.mnLuminance)); + } + break; + case model::BlipEffectType::Luminance: + { + mpFS->singleElementNS(XML_a, XML_lum, + XML_bright, OString::number(rEffect.mnBrightness), + XML_contrast, OString::number(rEffect.mnContrast)); + } + break; + case model::BlipEffectType::Tint: + { + mpFS->singleElementNS(XML_a, XML_tint, + XML_hue, OString::number(rEffect.mnHue), + XML_amt, OString::number(rEffect.mnAmount)); + } + break; + + default: + break; + } + } mpFS->endElementNS(XML_a, XML_blip); commit b09c377888e2e75859fff37fdf9408065eb522d6 Author: Tomaž Vajngerl <[email protected]> AuthorDate: Tue Apr 11 19:24:25 2023 +0900 Commit: Tomaž Vajngerl <[email protected]> CommitDate: Tue Apr 25 13:38:05 2023 +0200 oox: write graphic (blip) in ThemeExport - BlipFill Share the graphic writing from DrawingML class, which needed a bit of refactoring and use it when writing the BlipFill when exporting a theme with ThemeExport. Change-Id: I89bf3be98f607b7641d231982af2f7a5e2c3d3a8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150261 Tested-by: Tomaž Vajngerl <[email protected]> Reviewed-by: Tomaž Vajngerl <[email protected]> diff --git a/include/oox/export/ThemeExport.hxx b/include/oox/export/ThemeExport.hxx index 50eb9f47cf81..766d6dfd8a0c 100644 --- a/include/oox/export/ThemeExport.hxx +++ b/include/oox/export/ThemeExport.hxx @@ -36,10 +36,11 @@ class OOX_DLLPUBLIC ThemeExport { private: oox::core::XmlFilterBase* mpFilterBase; + oox::drawingml::DocumentType meDocumentType; sax_fastparser::FSHelperPtr mpFS; public: - ThemeExport(oox::core::XmlFilterBase* pFilterBase); + ThemeExport(oox::core::XmlFilterBase* pFilterBase, oox::drawingml::DocumentType eDocumentType); void write(OUString const& rPath, model::Theme const& rTheme); @@ -53,7 +54,7 @@ private: void writeBackgroundFillStyle(model::FillStyle const& rFillStyle); void writeFillStyle(model::FillStyle const& rFillStyle); void writeBlipFill(model::BlipFill const& rBlipFill); - static void writeBlip(model::BlipFill const& rBlipFil); + void writeBlip(model::BlipFill const& rBlipFill); void writePatternFill(model::PatternFill const& rPatternFill); void writeGradientFill(model::GradientFill const& rGradientFill); void writeSolidFill(model::SolidFill const& rSolidFill); diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx index 82deea172ef7..c9cf16cb1463 100644 --- a/include/oox/export/drawingml.hxx +++ b/include/oox/export/drawingml.hxx @@ -263,7 +263,8 @@ public: , meDocumentType(eDocumentType) {} - OUString write(const Graphic& rGraphic, bool bRelPathToMedia); + OUString writeToStorage(Graphic const& rGraphic, bool bRelPathToMedia = false); + OUString writeBlip(Graphic const& rGraphic , bool bRelPathToMedia = false); }; class OOX_DLLPUBLIC DrawingML diff --git a/oox/source/export/ThemeExport.cxx b/oox/source/export/ThemeExport.cxx index 8f00058e0bb1..16da603fa14c 100644 --- a/oox/source/export/ThemeExport.cxx +++ b/oox/source/export/ThemeExport.cxx @@ -34,8 +34,10 @@ void writeRelativeRectangle(sax_fastparser::FSHelperPtr pFS, sal_Int32 nToken, } } // end anonymous namespace -ThemeExport::ThemeExport(oox::core::XmlFilterBase* pFilterBase) +ThemeExport::ThemeExport(oox::core::XmlFilterBase* pFilterBase, + oox::drawingml::DocumentType eDocumentType) : mpFilterBase(pFilterBase) + , meDocumentType(eDocumentType) { } @@ -579,7 +581,14 @@ OString convertRectangleAlignment(model::RectangleAlignment eFlipMode) } } // end anonymous ns -void ThemeExport::writeBlip(model::BlipFill const& /*rBlipFil*/) {} +void ThemeExport::writeBlip(model::BlipFill const& rBlipFil) +{ + if (!rBlipFil.mxGraphic.is()) + return; + oox::drawingml::GraphicExport aExporter(mpFS, mpFilterBase, meDocumentType); + Graphic aGraphic(rBlipFil.mxGraphic); + aExporter.writeBlip(aGraphic, false); +} void ThemeExport::writeBlipFill(model::BlipFill const& rBlipFill) { diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index 97c5210d95f6..f58e76eda95e 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -1475,7 +1475,23 @@ const char* DrawingML::GetRelationCompPrefix() const return getRelationCompPrefix(meDocumentType); } -OUString GraphicExport::write(const Graphic& rGraphic , bool bRelPathToMedia) +OUString GraphicExport::writeBlip(Graphic const& rGraphic , bool bRelPathToMedia) +{ + OUString sRelId; + + sRelId = writeToStorage(rGraphic, bRelPathToMedia); + + mpFS->startElementNS(XML_a, XML_blip, FSNS(XML_r, XML_embed), sRelId); + + //WriteImageBrightnessContrastTransparence(rXPropSet); + //WriteArtisticEffect(rXPropSet); + + mpFS->endElementNS(XML_a, XML_blip); + + return sRelId; +} + +OUString GraphicExport::writeToStorage(const Graphic& rGraphic , bool bRelPathToMedia) { GfxLink aLink = rGraphic.GetGfxLink (); BitmapChecksum aChecksum = rGraphic.GetChecksum(); @@ -1608,7 +1624,7 @@ OUString GraphicExport::write(const Graphic& rGraphic , bool bRelPathToMedia) OUString DrawingML::WriteImage( const Graphic& rGraphic , bool bRelPathToMedia ) { GraphicExport exporter(mpFS, mpFB, meDocumentType); - return exporter.write(rGraphic, bRelPathToMedia); + return exporter.writeToStorage(rGraphic, bRelPathToMedia); } void DrawingML::WriteMediaNonVisualProperties(const css::uno::Reference<css::drawing::XShape>& xShape) diff --git a/sd/source/filter/eppt/pptx-epptooxml.cxx b/sd/source/filter/eppt/pptx-epptooxml.cxx index a8dca7463fdd..023f29dc82c6 100644 --- a/sd/source/filter/eppt/pptx-epptooxml.cxx +++ b/sd/source/filter/eppt/pptx-epptooxml.cxx @@ -2000,7 +2000,7 @@ void PowerPointExport::WriteTheme(sal_Int32 nThemeNum, model::Theme* pTheme) return; OUString sThemePath = "ppt/theme/theme" + OUString::number(nThemeNum + 1) + ".xml"; - oox::ThemeExport aThemeExport(this); + oox::ThemeExport aThemeExport(this, DOCUMENT_PPTX); aThemeExport.write(sThemePath, *pTheme); }
