Avoid potential negative array index access to cached text.
[LibreOffice.git] / writerfilter / source / dmapper / ThemeHandler.cxx
blob1acd7073f69c76ff133d1e893956c60b66b95a42
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
10 #include "ThemeHandler.hxx"
11 #include <i18nlangtag/languagetag.hxx>
12 #include <ooxml/resourceids.hxx>
13 #include <docmodel/theme/Theme.hxx>
15 using namespace com::sun::star;
17 namespace writerfilter::dmapper
19 namespace
21 OUString fromLCIDToScriptTag(LanguageType lang)
23 // conversion list from:
24 // http://blogs.msdn.com/b/officeinteroperability/archive/2013/04/22/office-open-xml-themes-schemes-and-fonts.aspx
25 switch (static_cast<sal_uInt16>(lang))
27 case 0x429: // lidFarsi
28 case 0x401: // lidArabic
29 case 0x801: // lidIraq
30 case 0xc01: // lidEgyptian
31 case 0x1001: // lidLibya
32 case 0x1401: // lidAlgerian
33 case 0x1801: // lidMorocco
34 case 0x1c01: // lidTunisia
35 case 0x2001: // lidOman
36 case 0x2401: // lidYemen
37 case 0x2801: // lidSyria
38 case 0x2c01: // lidJordan
39 case 0x3001: // lidLebanon
40 case 0x3401: // lidKuwait
41 case 0x3801: // lidUAE
42 case 0x3c01: // lidBahrain
43 case 0x4001: // lidQatar
44 case 0x420: // lidUrdu
45 case 0x846: // lidPunjabiPakistan
46 case 0x859: // lidSindhiPakistan
47 case 0x45f: // lidTamazight
48 case 0x460: // lidKashmiri
49 case 0x463: // lidPashto
50 case 0x48c: // lidDari
51 return "Arab";
52 case 0x42b: // lidArmenian
53 return "Armn";
54 case 0x445: // lidBengali
55 case 0x845: // lidBengaliBangladesh
56 case 0x44d: // lidAssamese
57 case 0x458: // lidManipuri
58 return "Beng";
59 case 0x45d: // lidInuktitut
60 return "Cans";
61 case 0x45c: // lidCherokee
62 return "Cher";
63 case 0x419: // lidRussian
64 case 0x402: // lidBulgarian
65 case 0x281a: // lidSerbianCyrillic
66 case 0x422: // lidUkranian
67 case 0x819: // lidRussianMoldavia
68 case 0xc1a: // lidSerbianCyrillicSerbMont
69 case 0x1c1a: // lidSerbianBosniaHerzegovinaCyrillic
70 case 0x201a: // lidBosnianBosniaHerzegovinaCyrillic
71 case 0x301a: // lidSerbianMontenegroCyrillic
72 case 0x423: // lidByelorussian
73 case 0x428: // lidTajik
74 case 0x82c: // lidAzeriCyrillic
75 case 0x42f: // lidMacedonian
76 case 0x43f: // lidKazakh
77 case 0x440: // lidKyrgyz
78 case 0x843: // lidUzbekCyrillic
79 case 0x444: // lidTatar
80 case 0x450: // lidMongolian
81 case 0x46d: // lidBashkir
82 case 0x485: // lidSakha
83 return "Cyrl";
84 case 0x439: // lidHindi
85 case 0x44e: // lidMarathi
86 case 0x44f: // lidSanskrit
87 case 0x457: // lidKonkani
88 case 0x459: // lidSindhi
89 case 0x860: // lidKashmiriIndia
90 case 0x461: // lidNepali
91 case 0x861: // lidNepaliIndia
92 return "Deva";
93 case 0x45e: // lidAmharic
94 case 0x473: // lidTigrignaEthiopic
95 case 0x873: // lidTigrignaEritrea
96 return "Ethi";
97 case 0x437: // lidGeorgian
98 return "Geor";
99 case 0x408: // lidGreek
100 return "Grek";
101 case 0x447: // lidGujarati
102 return "Gujr";
103 case 0x446: // lidPunjabi
104 return "Guru";
105 case 0x412: // lidKoreanExtWansung
106 return "Hang";
107 case 0x804: // lidChineseSimp
108 case 0x1004: // lidSingapore
109 return "Hans";
110 case 0x404: // lidChineseTrad
111 case 0xc04: // lidHongkong
112 case 0x1404: // lidMacau
113 return "Hant";
114 case 0x40d: // lidHebrew
115 case 0x43d: // lidYiddish
116 return "Hebr";
117 case 0x411: // lidJapanese
118 return "Jpan";
119 case 0x453: // lidKhmer
120 return "Khmr";
121 case 0x44b: // lidKannada
122 return "Knda";
123 case 0x454: // lidLao
124 return "Laoo";
125 case 0x409: // lidAmerican
126 case 0xc09: // lidAustralian
127 case 0x809: // lidBritish
128 case 0x1009: // lidEnglishCanadian
129 case 0x403: // lidCatalan
130 case 0x406: // lidDanish
131 case 0x413: // lidDutch
132 case 0x813: // lidDutchBelgian
133 case 0x479: // lidPapiamentu
134 case 0x40b: // lidFinnish
135 case 0x40c: // lidFrench
136 case 0xc0c: // lidFrenchCanadian
137 case 0x407: // lidGerman
138 case 0x807: // lidSwissGerman
139 case 0xc07: // lidAustrianGerman
140 case 0x1007: // lidGermanLuxembourg
141 case 0x1407: // lidGermanLiechtenstein
142 case 0x410: // lidItalian
143 case 0x414: // lidNorskBokmal
144 case 0x814: // lidNorskNynorsk
145 case 0x416: // lidPortBrazil
146 case 0x816: // lidPortIberian
147 case 0x40a: // lidSpanish
148 case 0x41d: // lidSwedish
149 case 0x405: // lidCzech
150 case 0x40e: // lidHungarian
151 case 0x415: // lidPolish
152 case 0x41f: // lidTurkish
153 case 0x42d: // lidBasque
154 case 0x424: // lidSlovenian
155 case 0x426: // lidLatvian
156 case 0x427: // lidLithuanian
157 case 0x418: // lidRomanian
158 case 0x818: // lidRomanianMoldavia
159 case 0x241a: // lidSerbianLatin
160 case 0x41a: // lidCroatian, lidCroat
161 case 0x491: // lidGaelicScots
162 case 0x83c: // lidGaelicIrish
163 case 0x430: // lidSutu
164 case 0x431: // lidTsonga
165 case 0x432: // lidTswana
166 case 0x433: // lidVenda
167 case 0x434: // lidXhosa
168 case 0x435: // lidZulu
169 case 0x436: // lidAfrikaans
170 case 0x425: // lidEstonian
171 case 0x456: // lidGalician
172 case 0x41b: // lidSlovak
173 case 0x1409: // lidEnglishNewZealand
174 case 0x1809: // lidEnglishIreland
175 case 0x1c09: // lidEnglishSouthAfrica
176 case 0x2009: // lidEnglishJamaica
177 case 0x2409: // lidEnglishCaribbean
178 case 0x2809: // lidEnglishBelize
179 case 0x2c09: // lidEnglishTrinidad
180 case 0x3009: // lidEnglishZimbabwe
181 case 0x3409: // lidEnglishPhilippines
182 case 0x3809: // lidEnglishIndonesia
183 case 0x3c09: // lidEnglishHongKong
184 case 0x4009: // lidEnglishIndia
185 case 0x4409: // lidEnglishMalaysia
186 case 0x4809: // lidEnglishSingapore
187 case 0x80a: // lidSpanishMexican, lidMexican
188 case 0xc0a: // lidSpanishModern
189 case 0x100a: // lidGuatemala
190 case 0x140a: // lidCostaRica
191 case 0x180a: // lidPanama
192 case 0x1c0a: // lidDominicanRepublic
193 case 0x200a: // lidSpanishSA, lidVenezuela
194 case 0x240a: // lidColombia
195 case 0x280a: // lidPeru
196 case 0x2c0a: // lidArgentina
197 case 0x300a: // lidEcuador
198 case 0x340a: // lidChile
199 case 0x380a: // lidUruguay
200 case 0x3c0a: // lidParguay
201 case 0x400a: // lidBolivia
202 case 0x440a: // lidElSalvador
203 case 0x480a: // lidHonduras
204 case 0x4c0a: // lidNicaragua
205 case 0x500a: // lidPuertoRico
206 case 0x540a: // lidSpanishUS
207 case 0x80c: // lidFrenchBelgian
208 case 0x100c: // lidFrenchSwiss
209 case 0x140c: // lidFrenchLuxembourg
210 case 0x180c: // lidFrenchMonaco
211 case 0x1c0c: // lidFrenchWestIndies
212 case 0x200c: // lidFrenchReunion
213 case 0x240c: // lidFrenchCongoDRC, lidFrenchZaire
214 case 0x280c: // lidFrenchSenegal
215 case 0x2c0c: // lidFrenchCameroon
216 case 0x300c: // lidFrenchCotedIvoire
217 case 0x340c: // lidFrenchMali
218 case 0x3c0c: // lidFrenchHaiti
219 case 0x380c: // lidFrenchMorocco
220 case 0x40f: // lidIcelandic
221 case 0x810: // lidItalianSwiss
222 case 0x417: // lidRhaetoRomanic, lidRomanic
223 case 0x81a: // lidSerbianLatinSerbMont, lidCroatSerbo
224 case 0x101a: // lidBosniaHerzegovina
225 case 0x141a: // lidBosnianBosniaHerzegovinaLatin
226 case 0x181a: // lidSerbianBosniaHerzegovinaLatin
227 case 0x2c1a: // lidSerbianMontenegroLatin
228 case 0x41c: // lidAlbanian
229 case 0x81d: // lidSwedishFinland
230 case 0x421: // lidBahasa, lidIndonesian
231 case 0x42c: // lidAzeriLatin
232 case 0x42e: // lidSorbian
233 case 0x82e: // lidLowerSorbian
234 case 0x438: // lidFaeroese
235 case 0x43a: // lidMaltese
236 case 0x43b: // lidSamiLappish
237 case 0x83b: // lidNorthSamiSwe
238 case 0xc3b: // lidNorthernSamiFi
239 case 0x103b: // lidLuleSamiNor
240 case 0x143b: // lidLuleSamiSwe
241 case 0x183b: // lidSouthSamiNor
242 case 0x1c3b: // lidSouthSamiSwe
243 case 0x203b: // lidSkoltSami
244 case 0x243b: // lidInariSami
245 case 0x43e: // lidMalaysian
246 case 0x83e: // lidMalayBrunei
247 case 0x441: // lidSwahili
248 case 0x442: // lidTurkmen
249 case 0x443: // lidUzbekLatin
250 case 0x452: // lidWelsh
251 case 0x85d: // lidInuktitutLatin
252 case 0x85f: // lidTamazightLatin
253 case 0x462: // lidFrisian
254 case 0x464: // lidFilipino
255 case 0x466: // lidEdo
256 case 0x467: // lidFulfulde
257 case 0x468: // lidHausa
258 case 0x469: // lidIbibio
259 case 0x46a: // lidYoruba
260 case 0x46b: // lidQuechuaBol
261 case 0x86b: // lidQuechuaEcu
262 case 0xc6b: // lidQuechuaPe
263 case 0x46c: // lidSesothoSaLeboa
264 case 0x46e: // lidLuxembourgish
265 case 0x46f: // lidGreenlandic
266 case 0x470: // lidIgbo
267 case 0x471: // lidKanuri
268 case 0x472: // lidOromo
269 case 0x474: // lidGuarani
270 case 0x475: // lidHawaiian
271 case 0x476: // lidLatin
272 case 0x477: // lidSomali
273 case 0x47a: // lidMapudungun
274 case 0x47c: // lidMohawk
275 case 0x47e: // lidBreton
276 case 0x481: // lidMaori
277 case 0x482: // lidOccitan
278 case 0x483: // lidCorsican
279 case 0x484: // lidAlsatian
280 case 0x486: // lidKiche
281 case 0x487: // lidKinyarwanda
282 case 0x488: // lidWolof
283 return "Latn";
284 case 0x44c: // lidMalayalam
285 return "Mlym";
286 case 0x850: // lidMongolianMongo
287 return "Mong";
288 case 0x455: // lidBurmese
289 return "Mymr";
290 case 0x448: // lidOriya
291 return "Orya";
292 case 0x45b: // lidSinhalese
293 return "Sinh";
294 case 0x45a: // lidSyriac
295 return "Syrc";
296 case 0x449: // lidTamil
297 return "Taml";
298 case 0x44a: // lidTelugu
299 return "Telu";
300 case 0x465: // lidMaldivian
301 return "Thaa";
302 case 0x41e: // lidThai
303 return "Thai";
304 case 0x451: // lidTibetan
305 case 0x851: // lidBhutanese
306 return "Tibt";
307 case 0x480: // lidUighur
308 return "Uigh";
309 case 0x42a: // lidVietnamese
310 return "Viet";
311 case 0x478: // lidYi
312 return "Yiii";
313 default:
314 return OUString();
318 OUString fromLocaleToScriptTag(const OUString& sLocale)
320 return fromLCIDToScriptTag(LanguageTag::convertToLanguageType(sLocale));
323 OUString resolveMajorMinorTypeFace(model::FontScheme const& rFontSheme, const Id id)
325 switch (id)
327 case NS_ooxml::LN_Value_ST_Theme_majorEastAsia:
328 return rFontSheme.getMajorAsian().maTypeface;
329 case NS_ooxml::LN_Value_ST_Theme_majorBidi:
330 return rFontSheme.getMajorComplex().maTypeface;
331 case NS_ooxml::LN_Value_ST_Theme_majorAscii:
332 case NS_ooxml::LN_Value_ST_Theme_majorHAnsi:
333 return rFontSheme.getMajorLatin().maTypeface;
334 break;
335 case NS_ooxml::LN_Value_ST_Theme_minorEastAsia:
336 return rFontSheme.getMinorAsian().maTypeface;
337 case NS_ooxml::LN_Value_ST_Theme_minorBidi:
338 return rFontSheme.getMinorComplex().maTypeface;
339 case NS_ooxml::LN_Value_ST_Theme_minorAscii:
340 case NS_ooxml::LN_Value_ST_Theme_minorHAnsi:
341 return rFontSheme.getMinorLatin().maTypeface;
342 break;
343 default:
344 break;
346 return OUString();
349 OUString resolveSupplementalFontList(model::FontScheme const& rFontSheme, const Id id,
350 std::u16string_view rLangAsia, std::u16string_view rLangBidi)
352 switch (id)
354 case NS_ooxml::LN_Value_ST_Theme_majorEastAsia:
355 return rFontSheme.findMajorSupplementalTypeface(rLangAsia);
356 case NS_ooxml::LN_Value_ST_Theme_majorBidi:
357 return rFontSheme.findMajorSupplementalTypeface(rLangBidi);
358 case NS_ooxml::LN_Value_ST_Theme_minorEastAsia:
359 return rFontSheme.findMinorSupplementalTypeface(rLangAsia);
360 case NS_ooxml::LN_Value_ST_Theme_minorBidi:
361 return rFontSheme.findMinorSupplementalTypeface(rLangBidi);
362 default:
363 break;
365 return OUString();
368 } // end anonymous namespace
370 ThemeHandler::ThemeHandler(oox::drawingml::ThemePtr const& pTheme,
371 const css::uno::Sequence<css::beans::PropertyValue>& rLangProperties)
372 : mpTheme(pTheme)
374 for (const auto& rProperty : rLangProperties)
376 OUString sLocaleName;
377 rProperty.Value >>= sLocaleName;
378 if (rProperty.Name == "eastAsia")
379 maThemeFontLangEastAsia = fromLocaleToScriptTag(sLocaleName);
380 if (rProperty.Name == "bidi")
381 maThemeFontLangBidi = fromLocaleToScriptTag(sLocaleName);
385 OUString ThemeHandler::getStringForTheme(const Id id)
387 switch (id)
389 case NS_ooxml::LN_Value_ST_Theme_majorEastAsia:
390 return "majorEastAsia";
391 case NS_ooxml::LN_Value_ST_Theme_majorBidi:
392 return "majorBidi";
393 case NS_ooxml::LN_Value_ST_Theme_majorAscii:
394 return "majorAscii";
395 case NS_ooxml::LN_Value_ST_Theme_majorHAnsi:
396 return "majorHAnsi";
397 case NS_ooxml::LN_Value_ST_Theme_minorEastAsia:
398 return "minorEastAsia";
399 case NS_ooxml::LN_Value_ST_Theme_minorBidi:
400 return "minorBidi";
401 case NS_ooxml::LN_Value_ST_Theme_minorAscii:
402 return "minorAscii";
403 case NS_ooxml::LN_Value_ST_Theme_minorHAnsi:
404 return "minorHAnsi";
406 return OUString();
409 OUString ThemeHandler::getFontNameForTheme(const Id id) const
411 auto pModelTheme = mpTheme->getTheme();
412 model::FontScheme const& rFontScheme = pModelTheme->getFontScheme();
413 OUString aSupplementalTypeFace = resolveSupplementalFontList(
414 rFontScheme, id, maThemeFontLangEastAsia, maThemeFontLangBidi);
415 if (!aSupplementalTypeFace.isEmpty())
416 return aSupplementalTypeFace;
417 OUString aTypeFace = resolveMajorMinorTypeFace(rFontScheme, id);
418 return aTypeFace;
421 } //namespace writerfilter
423 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */