/src/libreoffice/oox/source/drawingml/textcharacterproperties.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
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/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
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 . |
18 | | */ |
19 | | |
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> |
37 | | |
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; |
42 | | |
43 | | namespace oox::drawingml { |
44 | | |
45 | | void TextCharacterProperties::assignUsed( const TextCharacterProperties& rSourceProps ) |
46 | 9.57M | { |
47 | | // overwrite all properties existing in rSourceProps |
48 | 9.57M | maHyperlinkPropertyMap.assignUsed( rSourceProps.maHyperlinkPropertyMap ); |
49 | 9.57M | maLatinFont.assignIfUsed( rSourceProps.maLatinFont ); |
50 | 9.57M | maLatinThemeFont.assignIfUsed( rSourceProps.maLatinThemeFont ); |
51 | 9.57M | maAsianFont.assignIfUsed( rSourceProps.maAsianFont ); |
52 | 9.57M | maAsianThemeFont.assignIfUsed( rSourceProps.maAsianThemeFont ); |
53 | 9.57M | maComplexFont.assignIfUsed( rSourceProps.maComplexFont ); |
54 | 9.57M | maComplexThemeFont.assignIfUsed( rSourceProps.maComplexThemeFont ); |
55 | 9.57M | maSymbolFont.assignIfUsed( rSourceProps.maSymbolFont ); |
56 | 9.57M | maHighlightColor.assignIfUsed( rSourceProps.maHighlightColor ); |
57 | 9.57M | maHighlightOOXColor.assignIfUsed( rSourceProps.maHighlightOOXColor ); |
58 | 9.57M | maUnderlineColor.assignIfUsed( rSourceProps.maUnderlineColor ); |
59 | 9.57M | assignIfUsed( moLang, rSourceProps.moLang ); |
60 | 9.57M | assignIfUsed( moHeight, rSourceProps.moHeight ); |
61 | 9.57M | assignIfUsed( moFontScale, rSourceProps.moFontScale); |
62 | 9.57M | assignIfUsed( moSpacing, rSourceProps.moSpacing ); |
63 | 9.57M | assignIfUsed( moUnderline, rSourceProps.moUnderline ); |
64 | 9.57M | assignIfUsed( moBaseline, rSourceProps.moBaseline ); |
65 | 9.57M | assignIfUsed( moStrikeout, rSourceProps.moStrikeout ); |
66 | 9.57M | assignIfUsed( moCaseMap, rSourceProps.moCaseMap ); |
67 | 9.57M | assignIfUsed( moBold, rSourceProps.moBold ); |
68 | 9.57M | assignIfUsed( moItalic, rSourceProps.moItalic ); |
69 | 9.57M | assignIfUsed( moUnderlineLineFollowText, rSourceProps.moUnderlineLineFollowText ); |
70 | 9.57M | assignIfUsed( moUnderlineFillFollowText, rSourceProps.moUnderlineFillFollowText ); |
71 | 9.57M | assignIfUsed( moTextOutlineProperties, rSourceProps.moTextOutlineProperties); |
72 | | |
73 | 9.57M | maTextEffectsProperties = rSourceProps.maTextEffectsProperties; |
74 | 9.57M | mpEffectPropertiesPtr->assignUsed(*rSourceProps.mpEffectPropertiesPtr); |
75 | 9.57M | maFillProperties.assignUsed( rSourceProps.maFillProperties ); |
76 | 9.57M | } |
77 | | |
78 | | void TextCharacterProperties::pushToPropMap( PropertyMap& rPropMap, const XmlFilterBase& rFilter ) const |
79 | 430k | { |
80 | 430k | OUString aFontName; |
81 | 430k | sal_Int16 nFontPitch = 0; |
82 | 430k | sal_Int16 nFontFamily = 0; |
83 | | |
84 | 430k | bool bRet = maLatinFont.getFontData( aFontName, nFontPitch, nFontFamily, nullptr, rFilter ); |
85 | 430k | if (!bRet) |
86 | | // In case there is no direct font, try to look it up as a theme reference. |
87 | 244k | bRet = maLatinThemeFont.getFontData( aFontName, nFontPitch, nFontFamily, nullptr, rFilter ); |
88 | 430k | if (bRet) |
89 | 185k | { |
90 | 185k | rPropMap.setProperty( PROP_CharFontName, aFontName); |
91 | 185k | rPropMap.setProperty( PROP_CharFontPitch, nFontPitch); |
92 | 185k | rPropMap.setProperty( PROP_CharFontFamily, nFontFamily); |
93 | 185k | } |
94 | | |
95 | 430k | bRet = maAsianFont.getFontData( aFontName, nFontPitch, nFontFamily, nullptr, rFilter ); |
96 | 430k | if (!bRet) |
97 | 410k | bRet = maAsianThemeFont.getFontData( aFontName, nFontPitch, nFontFamily, nullptr, rFilter ); |
98 | 430k | if (bRet) |
99 | 19.6k | { |
100 | 19.6k | rPropMap.setProperty( PROP_CharFontNameAsian, aFontName); |
101 | 19.6k | rPropMap.setProperty( PROP_CharFontPitchAsian, nFontFamily); |
102 | 19.6k | rPropMap.setProperty( PROP_CharFontFamilyAsian, nFontPitch); |
103 | 19.6k | } |
104 | | |
105 | 430k | bRet = maComplexFont.getFontData( aFontName, nFontPitch, nFontFamily, nullptr, rFilter ); |
106 | 430k | if (!bRet) |
107 | 426k | bRet = maComplexThemeFont.getFontData( aFontName, nFontPitch, nFontFamily, nullptr, rFilter ); |
108 | 430k | if (bRet) |
109 | 3.59k | { |
110 | 3.59k | rPropMap.setProperty( PROP_CharFontNameComplex, aFontName); |
111 | 3.59k | rPropMap.setProperty( PROP_CharFontPitchComplex, nFontPitch); |
112 | 3.59k | rPropMap.setProperty( PROP_CharFontFamilyComplex, nFontFamily); |
113 | 3.59k | } |
114 | | |
115 | 430k | if ( maFillProperties.moFillType.has_value() ) |
116 | 202k | { |
117 | 202k | Color aOOXColor = maFillProperties.getBestSolidColor(); |
118 | 202k | bool bContoured = false; |
119 | | |
120 | | // noFill doesn't exist for characters. Map noFill to 99% transparency |
121 | 202k | if (maFillProperties.moFillType.value() == XML_noFill) |
122 | 0 | aOOXColor.addTransformation(XML_alpha, 1000); |
123 | | |
124 | | // tdf#137438 Emulate text outline color/transparency. |
125 | | // If the outline color dominates, then use it as the text color. |
126 | 202k | if (moTextOutlineProperties.has_value() |
127 | 2.41k | && moTextOutlineProperties.value().maLineFill.moFillType.has_value() |
128 | 2.33k | && moTextOutlineProperties.value().maLineFill.moFillType.value() != XML_noFill) |
129 | 3 | { |
130 | 3 | Color aLineColor = moTextOutlineProperties.value().maLineFill.getBestSolidColor(); |
131 | 3 | sal_Int16 nLineTransparency = aLineColor.getTransparency(); |
132 | | |
133 | | // tdf#127696 If the text color is white (and the outline color doesn't dominate), |
134 | | // then this is contoured text in LO. |
135 | 3 | if (nLineTransparency < aOOXColor.getTransparency() |
136 | 3 | || (bContoured = aOOXColor.getColor(rFilter.getGraphicHelper()) == COL_WHITE)) |
137 | 2 | aOOXColor = std::move(aLineColor); |
138 | 3 | } |
139 | 202k | rPropMap.setProperty(PROP_CharColor, aOOXColor.getColor(rFilter.getGraphicHelper())); |
140 | | |
141 | | // set theme color |
142 | 202k | model::ComplexColor aComplexColor = aOOXColor.getComplexColor(); |
143 | 202k | sal_Int32 nToken = Color::getColorMapToken(aOOXColor.getSchemeColorName()); |
144 | 202k | if (nToken != -1) |
145 | 157k | { |
146 | 157k | rFilter.getGraphicHelper().getSchemeColorToken(nToken); |
147 | 157k | model::ThemeColorType eThemeColorType = schemeTokenToThemeColorType(nToken); |
148 | 157k | aComplexColor.setThemeColor(eThemeColorType); |
149 | 157k | } |
150 | 202k | rPropMap.setProperty(PROP_CharComplexColor, model::color::createXComplexColor(aComplexColor)); |
151 | 202k | rPropMap.setProperty(PROP_CharContoured, bContoured); |
152 | | |
153 | 202k | if (aOOXColor.hasTransparency()) |
154 | 0 | { |
155 | 0 | const auto nTransparency = aOOXColor.getTransparency(); |
156 | 0 | rPropMap.setProperty(PROP_CharTransparence, nTransparency); |
157 | | |
158 | | // WORKAROUND: Fully transparent white has the same value as COL_AUTO, avoid collision |
159 | 0 | if (nTransparency == 100 |
160 | 0 | && aOOXColor.getColor(rFilter.getGraphicHelper()).GetRGBColor() == COL_AUTO.GetRGBColor()) |
161 | 0 | rPropMap.setProperty(PROP_CharColor, ::Color(ColorTransparency, 0xFFFFFFFE)); |
162 | 0 | } |
163 | 202k | } |
164 | | |
165 | 430k | if( moLang.has_value() && !moLang.value().isEmpty() ) |
166 | 107k | { |
167 | 107k | LanguageTag aTag(moLang.value()); |
168 | 107k | lang::Locale aLocale(aTag.getLocale()); |
169 | 107k | switch(MsLangId::getScriptType(aTag.getLanguageType())) |
170 | 107k | { |
171 | 103k | case css::i18n::ScriptType::LATIN: |
172 | 103k | rPropMap.setProperty( PROP_CharLocale, aLocale);break; |
173 | 2.83k | case css::i18n::ScriptType::ASIAN: |
174 | 2.83k | rPropMap.setProperty( PROP_CharLocaleAsian, aLocale);break; |
175 | 681 | case css::i18n::ScriptType::COMPLEX: |
176 | 681 | rPropMap.setProperty( PROP_CharLocaleComplex, aLocale);break; |
177 | 107k | } |
178 | 107k | } |
179 | | |
180 | 430k | if( moHeight.has_value() ) |
181 | 200k | { |
182 | 200k | float fHeight = GetFontHeight( moHeight.value() ); |
183 | 200k | if (moFontScale.has_value()) |
184 | 0 | fHeight *= (moFontScale.value() / 100000); |
185 | 200k | rPropMap.setProperty( PROP_CharHeight, fHeight); |
186 | 200k | rPropMap.setProperty( PROP_CharHeightAsian, fHeight); |
187 | 200k | rPropMap.setProperty( PROP_CharHeightComplex, fHeight); |
188 | 200k | } |
189 | | |
190 | 430k | rPropMap.setProperty( PROP_CharKerning, static_cast<sal_Int16>(GetTextSpacingPoint( moSpacing.value_or( 0 ) ))); |
191 | | |
192 | 430k | rPropMap.setProperty( PROP_CharUnderline, GetFontUnderline( moUnderline.value_or( XML_none ) )); |
193 | 430k | rPropMap.setProperty( PROP_CharStrikeout, GetFontStrikeout( moStrikeout.value_or( XML_noStrike ) )); |
194 | 430k | rPropMap.setProperty( PROP_CharCaseMap, GetCaseMap( moCaseMap.value_or( XML_none ) )); |
195 | | |
196 | 430k | if( moBaseline.has_value() ) { |
197 | 8 | rPropMap.setProperty( PROP_CharEscapement, sal_Int16(moBaseline.value_or( 0 ) / 1000)); |
198 | 8 | rPropMap.setProperty( PROP_CharEscapementHeight, sal_Int8(DFLT_ESC_PROP)); |
199 | 430k | } else { |
200 | 430k | rPropMap.setProperty( PROP_CharEscapement, sal_Int16(0)); |
201 | 430k | rPropMap.setProperty( PROP_CharEscapementHeight, sal_Int8(100)); // 100% |
202 | 430k | } |
203 | | |
204 | 430k | float fWeight = moBold.value_or( false ) ? awt::FontWeight::BOLD : awt::FontWeight::NORMAL; |
205 | 430k | rPropMap.setProperty( PROP_CharWeight, fWeight); |
206 | 430k | rPropMap.setProperty( PROP_CharWeightAsian, fWeight); |
207 | 430k | rPropMap.setProperty( PROP_CharWeightComplex, fWeight); |
208 | | |
209 | 430k | awt::FontSlant eSlant = moItalic.value_or( false ) ? awt::FontSlant_ITALIC : awt::FontSlant_NONE; |
210 | 430k | rPropMap.setProperty( PROP_CharPosture, eSlant); |
211 | 430k | rPropMap.setProperty( PROP_CharPostureAsian, eSlant); |
212 | 430k | rPropMap.setProperty( PROP_CharPostureComplex, eSlant); |
213 | | |
214 | 430k | bool bUnderlineFillFollowText = moUnderlineFillFollowText.value_or( false ); |
215 | 430k | if( moUnderline.has_value() && maUnderlineColor.isUsed() && !bUnderlineFillFollowText ) |
216 | 36 | { |
217 | 36 | rPropMap.setProperty( PROP_CharUnderlineHasColor, true); |
218 | 36 | rPropMap.setProperty( PROP_CharUnderlineColor, maUnderlineColor.getRGBColor()); |
219 | 36 | rPropMap.setProperty( PROP_CharUnderlineComplexColor, model::color::createXComplexColor(maUnderlineColor)); |
220 | 36 | } |
221 | 430k | else |
222 | 430k | { |
223 | 430k | rPropMap.setProperty( PROP_CharUnderlineHasColor, false); |
224 | 430k | rPropMap.setProperty( PROP_CharUnderlineColor, sal_Int32(-1)); |
225 | 430k | } |
226 | | |
227 | 430k | if (maHighlightColor.isUsed() && !maHighlightColor.isTransparent()) |
228 | 0 | { |
229 | 0 | rPropMap.setProperty(PROP_CharBackColor, maHighlightOOXColor.getColor( rFilter.getGraphicHelper() )); |
230 | 0 | rPropMap.setProperty(PROP_CharBackgroundComplexColor, model::color::createXComplexColor(maHighlightColor)); |
231 | 0 | } |
232 | 430k | else |
233 | 430k | rPropMap.setProperty( PROP_CharBackColor, sal_Int32(-1)); |
234 | 430k | } |
235 | | |
236 | | static void pushToGrabBag( PropertySet& rPropSet, const std::vector<PropertyValue>& aVectorOfPropertyValues ) |
237 | 430k | { |
238 | 430k | if (!rPropSet.hasProperty(PROP_CharInteropGrabBag) || aVectorOfPropertyValues.empty()) |
239 | 430k | return; |
240 | 0 | Sequence<PropertyValue> aGrabBag; |
241 | 0 | Any aAnyGrabBag = rPropSet.getAnyProperty(PROP_CharInteropGrabBag); |
242 | 0 | aAnyGrabBag >>= aGrabBag; |
243 | |
|
244 | 0 | rPropSet.setAnyProperty(PROP_CharInteropGrabBag, Any(comphelper::concatSequences(aGrabBag, aVectorOfPropertyValues))); |
245 | 0 | } |
246 | | |
247 | | void TextCharacterProperties::pushToPropSet( PropertySet& rPropSet, const XmlFilterBase& rFilter ) const |
248 | 430k | { |
249 | 430k | PropertyMap aPropMap; |
250 | 430k | pushToPropMap( aPropMap, rFilter ); |
251 | 430k | rPropSet.setProperties( aPropMap ); |
252 | 430k | pushToGrabBag(rPropSet, maTextEffectsProperties); |
253 | 430k | } |
254 | | |
255 | | float TextCharacterProperties::getCharHeightPoints( float fDefault ) const |
256 | 16.0k | { |
257 | 16.0k | return moHeight.has_value() ? GetFontHeight( moHeight.value() ) : fDefault; |
258 | 16.0k | } |
259 | | |
260 | | } // namespace oox::drawingml |
261 | | |
262 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |