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 <quikee@gmail.com>
This commit is contained in:
Tomaž Vajngerl
2023-04-25 13:38:18 +02:00
committed by Tomaž Vajngerl
parent b09c377888
commit 6252959192
5 changed files with 188 additions and 25 deletions
+40 -9
View File
@@ -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)
+1 -1
View File
@@ -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
+34 -8
View File
@@ -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;
}
+4 -4
View File
@@ -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)
+109 -3
View File
@@ -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);