1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 <drawingml/textcharacterproperties.hxx>
21 #include <com/sun/star/lang/Locale.hpp>
22 #include <com/sun/star/awt/FontSlant.hpp>
23 #include <com/sun/star/awt/FontWeight.hpp>
24 #include <com/sun/star/i18n/ScriptType.hpp>
25 #include <comphelper/sequence.hxx>
26 #include <i18nlangtag/languagetag.hxx>
27 #include <i18nlangtag/mslangid.hxx>
28 #include <editeng/escapementitem.hxx>
29 #include <docmodel/uno/UnoComplexColor.hxx>
30 #include <oox/helper/helper.hxx>
31 #include <oox/helper/propertyset.hxx>
32 #include <oox/helper/graphichelper.hxx>
33 #include <oox/core/xmlfilterbase.hxx>
34 #include <oox/drawingml/drawingmltypes.hxx>
35 #include <oox/token/properties.hxx>
36 #include <oox/token/tokens.hxx>
38 using ::oox::core::XmlFilterBase
;
39 using namespace ::com::sun::star
;
40 using namespace ::com::sun::star::uno
;
41 using namespace ::com::sun::star::beans
;
43 namespace oox::drawingml
{
45 void TextCharacterProperties::assignUsed( const TextCharacterProperties
& rSourceProps
)
47 // overwrite all properties existing in rSourceProps
48 maHyperlinkPropertyMap
.assignUsed( rSourceProps
.maHyperlinkPropertyMap
);
49 maLatinFont
.assignIfUsed( rSourceProps
.maLatinFont
);
50 maLatinThemeFont
.assignIfUsed( rSourceProps
.maLatinThemeFont
);
51 maAsianFont
.assignIfUsed( rSourceProps
.maAsianFont
);
52 maAsianThemeFont
.assignIfUsed( rSourceProps
.maAsianThemeFont
);
53 maComplexFont
.assignIfUsed( rSourceProps
.maComplexFont
);
54 maComplexThemeFont
.assignIfUsed( rSourceProps
.maComplexThemeFont
);
55 maSymbolFont
.assignIfUsed( rSourceProps
.maSymbolFont
);
56 maHighlightColor
.assignIfUsed( rSourceProps
.maHighlightColor
);
57 maUnderlineColor
.assignIfUsed( rSourceProps
.maUnderlineColor
);
58 assignIfUsed( moLang
, rSourceProps
.moLang
);
59 assignIfUsed( moHeight
, rSourceProps
.moHeight
);
60 assignIfUsed( moFontScale
, rSourceProps
.moFontScale
);
61 assignIfUsed( moSpacing
, rSourceProps
.moSpacing
);
62 assignIfUsed( moUnderline
, rSourceProps
.moUnderline
);
63 assignIfUsed( moBaseline
, rSourceProps
.moBaseline
);
64 assignIfUsed( moStrikeout
, rSourceProps
.moStrikeout
);
65 assignIfUsed( moCaseMap
, rSourceProps
.moCaseMap
);
66 assignIfUsed( moBold
, rSourceProps
.moBold
);
67 assignIfUsed( moItalic
, rSourceProps
.moItalic
);
68 assignIfUsed( moUnderlineLineFollowText
, rSourceProps
.moUnderlineLineFollowText
);
69 assignIfUsed( moUnderlineFillFollowText
, rSourceProps
.moUnderlineFillFollowText
);
70 assignIfUsed( moTextOutlineProperties
, rSourceProps
.moTextOutlineProperties
);
72 maTextEffectsProperties
= rSourceProps
.maTextEffectsProperties
;
73 mpEffectPropertiesPtr
->assignUsed(*rSourceProps
.mpEffectPropertiesPtr
);
74 maFillProperties
.assignUsed( rSourceProps
.maFillProperties
);
77 void TextCharacterProperties::pushToPropMap( PropertyMap
& rPropMap
, const XmlFilterBase
& rFilter
) const
80 sal_Int16 nFontPitch
= 0;
81 sal_Int16 nFontFamily
= 0;
83 bool bRet
= maLatinFont
.getFontData( aFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
85 // In case there is no direct font, try to look it up as a theme reference.
86 bRet
= maLatinThemeFont
.getFontData( aFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
89 rPropMap
.setProperty( PROP_CharFontName
, aFontName
);
90 rPropMap
.setProperty( PROP_CharFontPitch
, nFontPitch
);
91 rPropMap
.setProperty( PROP_CharFontFamily
, nFontFamily
);
94 bRet
= maAsianFont
.getFontData( aFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
96 bRet
= maAsianThemeFont
.getFontData( aFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
99 rPropMap
.setProperty( PROP_CharFontNameAsian
, aFontName
);
100 rPropMap
.setProperty( PROP_CharFontPitchAsian
, nFontFamily
);
101 rPropMap
.setProperty( PROP_CharFontFamilyAsian
, nFontPitch
);
104 bRet
= maComplexFont
.getFontData( aFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
106 bRet
= maComplexThemeFont
.getFontData( aFontName
, nFontPitch
, nFontFamily
, nullptr, rFilter
);
109 rPropMap
.setProperty( PROP_CharFontNameComplex
, aFontName
);
110 rPropMap
.setProperty( PROP_CharFontPitchComplex
, nFontPitch
);
111 rPropMap
.setProperty( PROP_CharFontFamilyComplex
, nFontFamily
);
114 if ( maFillProperties
.moFillType
.has_value() )
116 Color aColor
= maFillProperties
.getBestSolidColor();
117 bool bContoured
= false;
119 // noFill doesn't exist for characters. Map noFill to 99% transparency
120 if (maFillProperties
.moFillType
.value() == XML_noFill
)
121 aColor
.addTransformation(XML_alpha
, 1000);
123 // tdf#137438 Emulate text outline color/transparency.
124 // If the outline color dominates, then use it as the text color.
125 if (moTextOutlineProperties
.has_value()
126 && moTextOutlineProperties
.value().maLineFill
.moFillType
.has_value()
127 && moTextOutlineProperties
.value().maLineFill
.moFillType
.value() != XML_noFill
)
129 Color aLineColor
= moTextOutlineProperties
.value().maLineFill
.getBestSolidColor();
130 sal_Int16 nLineTransparency
= aLineColor
.getTransparency();
132 // tdf#127696 If the text color is white (and the outline color doesn't dominate),
133 // then this is contoured text in LO.
134 if (nLineTransparency
< aColor
.getTransparency()
135 || (bContoured
= aColor
.getColor(rFilter
.getGraphicHelper()) == COL_WHITE
))
136 aColor
= std::move(aLineColor
);
138 rPropMap
.setProperty(PROP_CharColor
, aColor
.getColor(rFilter
.getGraphicHelper()));
141 model::ComplexColor aComplexColor
= aColor
.getComplexColor();
142 sal_Int32 nToken
= Color::getColorMapToken(aColor
.getSchemeColorName());
145 rFilter
.getGraphicHelper().getSchemeColorToken(nToken
);
146 model::ThemeColorType eThemeColorType
= schemeTokenToThemeColorType(nToken
);
147 aComplexColor
.setThemeColor(eThemeColorType
);
149 rPropMap
.setProperty(PROP_CharComplexColor
, model::color::createXComplexColor(aComplexColor
));
150 rPropMap
.setProperty(PROP_CharContoured
, bContoured
);
152 if (aColor
.hasTransparency())
154 const auto nTransparency
= aColor
.getTransparency();
155 rPropMap
.setProperty(PROP_CharTransparence
, nTransparency
);
157 // WORKAROUND: Fully transparent white has the same value as COL_AUTO, avoid collision
158 if (nTransparency
== 100
159 && aColor
.getColor(rFilter
.getGraphicHelper()).GetRGBColor() == COL_AUTO
.GetRGBColor())
160 rPropMap
.setProperty(PROP_CharColor
, ::Color(ColorTransparency
, 0xFFFFFFFE));
164 if( moLang
.has_value() && !moLang
.value().isEmpty() )
166 LanguageTag
aTag(moLang
.value());
167 lang::Locale
aLocale(aTag
.getLocale());
168 switch(MsLangId::getScriptType(aTag
.getLanguageType()))
170 case css::i18n::ScriptType::LATIN
:
171 rPropMap
.setProperty( PROP_CharLocale
, aLocale
);break;
172 case css::i18n::ScriptType::ASIAN
:
173 rPropMap
.setProperty( PROP_CharLocaleAsian
, aLocale
);break;
174 case css::i18n::ScriptType::COMPLEX
:
175 rPropMap
.setProperty( PROP_CharLocaleComplex
, aLocale
);break;
179 if( moHeight
.has_value() )
181 float fHeight
= GetFontHeight( moHeight
.value() );
182 if (moFontScale
.has_value())
183 fHeight
*= (moFontScale
.value() / 100000);
184 rPropMap
.setProperty( PROP_CharHeight
, fHeight
);
185 rPropMap
.setProperty( PROP_CharHeightAsian
, fHeight
);
186 rPropMap
.setProperty( PROP_CharHeightComplex
, fHeight
);
189 rPropMap
.setProperty( PROP_CharKerning
, static_cast<sal_Int16
>(GetTextSpacingPoint( moSpacing
.value_or( 0 ) )));
191 rPropMap
.setProperty( PROP_CharUnderline
, GetFontUnderline( moUnderline
.value_or( XML_none
) ));
192 rPropMap
.setProperty( PROP_CharStrikeout
, GetFontStrikeout( moStrikeout
.value_or( XML_noStrike
) ));
193 rPropMap
.setProperty( PROP_CharCaseMap
, GetCaseMap( moCaseMap
.value_or( XML_none
) ));
195 if( moBaseline
.has_value() ) {
196 rPropMap
.setProperty( PROP_CharEscapement
, sal_Int16(moBaseline
.value_or( 0 ) / 1000));
197 rPropMap
.setProperty( PROP_CharEscapementHeight
, sal_Int8(DFLT_ESC_PROP
));
199 rPropMap
.setProperty( PROP_CharEscapement
, sal_Int16(0));
200 rPropMap
.setProperty( PROP_CharEscapementHeight
, sal_Int8(100)); // 100%
203 float fWeight
= moBold
.value_or( false ) ? awt::FontWeight::BOLD
: awt::FontWeight::NORMAL
;
204 rPropMap
.setProperty( PROP_CharWeight
, fWeight
);
205 rPropMap
.setProperty( PROP_CharWeightAsian
, fWeight
);
206 rPropMap
.setProperty( PROP_CharWeightComplex
, fWeight
);
208 awt::FontSlant eSlant
= moItalic
.value_or( false ) ? awt::FontSlant_ITALIC
: awt::FontSlant_NONE
;
209 rPropMap
.setProperty( PROP_CharPosture
, eSlant
);
210 rPropMap
.setProperty( PROP_CharPostureAsian
, eSlant
);
211 rPropMap
.setProperty( PROP_CharPostureComplex
, eSlant
);
213 bool bUnderlineFillFollowText
= moUnderlineFillFollowText
.value_or( false );
214 if( moUnderline
.has_value() && maUnderlineColor
.isUsed() && !bUnderlineFillFollowText
)
216 rPropMap
.setProperty( PROP_CharUnderlineHasColor
, true);
217 rPropMap
.setProperty( PROP_CharUnderlineColor
, maUnderlineColor
.getColor( rFilter
.getGraphicHelper() ));
218 model::ComplexColor aComplexColor
= maUnderlineColor
.getComplexColor();
219 rPropMap
.setProperty( PROP_CharUnderlineComplexColor
, model::color::createXComplexColor(aComplexColor
));
223 rPropMap
.setProperty( PROP_CharUnderlineHasColor
, false);
224 rPropMap
.setProperty( PROP_CharUnderlineColor
, sal_Int32(-1));
227 if (maHighlightColor
.isUsed() && maHighlightColor
.getTransparency() != 100)
229 rPropMap
.setProperty(PROP_CharBackColor
, maHighlightColor
.getColor( rFilter
.getGraphicHelper() ));
230 model::ComplexColor aComplexColor
= maHighlightColor
.getComplexColor();
231 rPropMap
.setProperty(PROP_CharBackgroundComplexColor
, model::color::createXComplexColor(aComplexColor
));
234 rPropMap
.setProperty( PROP_CharBackColor
, sal_Int32(-1));
237 static void pushToGrabBag( PropertySet
& rPropSet
, const std::vector
<PropertyValue
>& aVectorOfPropertyValues
)
239 if (!rPropSet
.hasProperty(PROP_CharInteropGrabBag
) || aVectorOfPropertyValues
.empty())
241 Sequence
<PropertyValue
> aGrabBag
;
242 Any aAnyGrabBag
= rPropSet
.getAnyProperty(PROP_CharInteropGrabBag
);
243 aAnyGrabBag
>>= aGrabBag
;
245 rPropSet
.setAnyProperty(PROP_CharInteropGrabBag
, Any(comphelper::concatSequences(aGrabBag
, aVectorOfPropertyValues
)));
248 void TextCharacterProperties::pushToPropSet( PropertySet
& rPropSet
, const XmlFilterBase
& rFilter
) const
250 PropertyMap aPropMap
;
251 pushToPropMap( aPropMap
, rFilter
);
252 rPropSet
.setProperties( aPropMap
);
253 pushToGrabBag(rPropSet
, maTextEffectsProperties
);
256 float TextCharacterProperties::getCharHeightPoints( float fDefault
) const
258 return moHeight
.has_value() ? GetFontHeight( moHeight
.value() ) : fDefault
;
261 } // namespace oox::drawingml
263 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */