Line data Source code
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 : #include <ConversionHelper.hxx>
20 : #include <com/sun/star/table/BorderLine2.hpp>
21 : #include <com/sun/star/table/BorderLineStyle.hpp>
22 : #include <com/sun/star/lang/Locale.hpp>
23 : #include <com/sun/star/text/HoriOrientation.hpp>
24 : #include <com/sun/star/style/NumberingType.hpp>
25 : #include <editeng/borderline.hxx>
26 : #include <ooxml/resourceids.hxx>
27 : #include <rtl/ustrbuf.hxx>
28 : #include <tools/color.hxx>
29 : #include <algorithm>
30 : #include <functional>
31 :
32 : using namespace com::sun::star;
33 : using namespace com::sun::star::table::BorderLineStyle;
34 :
35 : namespace writerfilter {
36 : namespace dmapper{
37 : namespace ConversionHelper{
38 :
39 : const sal_Int16 API_LINE_SOLID = 0;
40 : const sal_Int16 API_LINE_DOTTED = 1;
41 : const sal_Int16 API_LINE_DASHED = 2;
42 :
43 : #define TWIP_TO_MM100(TWIP) ((TWIP) >= 0 ? (((TWIP)*127L+36L)/72L) : (((TWIP)*127L-36L)/72L))
44 :
45 0 : sal_Int32 MakeBorderLine( sal_Int32 nSprmValue, table::BorderLine2& rToFill )
46 : {
47 : //TODO: Lines are always solid
48 : //Border
49 : //borders are defined as:
50 : // 0x XX XX XX XX
51 : // || || || ||
52 : // || || || ---- Line width in 1/8 pt
53 : // || || ||
54 : // || || ------- Line type: 0 - none 1 - single ... 25 - engrave 3D and 64 - 230 page borders
55 : // || ||
56 : // || ---------- Line color
57 : // ||
58 : // ------------- seven bits line space
59 : // -------------- first bit: with shading
60 0 : sal_Int16 nLineThicknessTwip = (sal_Int16)((nSprmValue & 0xff) * 20)/8L ;
61 0 : sal_Int32 nLineType = ((nSprmValue & 0xff00) >> 8);
62 0 : sal_Int32 nLineColor = (nSprmValue & 0xff0000)>>16;
63 0 : sal_Int32 nLineDistance = (((nSprmValue & 0x3f000000)>>24) * 2540 + 36)/72L;
64 0 : MakeBorderLine( nLineThicknessTwip, nLineType, nLineColor, rToFill, false);
65 0 : return nLineDistance;
66 : }
67 2615 : void MakeBorderLine( sal_Int32 nLineThickness, sal_Int32 nLineType,
68 : sal_Int32 nLineColor,
69 : table::BorderLine2& rToFill, bool bIsOOXML )
70 : {
71 : static const sal_Int32 aBorderDefColor[] =
72 : {
73 : // The first item means automatic color (COL_AUTO), but we
74 : // do not use it anyway (see the next statement) .-)
75 : 0, COL_BLACK, COL_LIGHTBLUE, COL_LIGHTCYAN, COL_LIGHTGREEN,
76 : COL_LIGHTMAGENTA, COL_LIGHTRED, COL_YELLOW, COL_WHITE, COL_BLUE,
77 : COL_CYAN, COL_GREEN, COL_MAGENTA, COL_RED, COL_BROWN, COL_GRAY,
78 : COL_LIGHTGRAY
79 : };
80 : //no auto color for borders
81 2615 : if(!nLineColor)
82 1585 : ++nLineColor;
83 2615 : if(!bIsOOXML && sal::static_int_cast<sal_uInt32>(nLineColor) < SAL_N_ELEMENTS(aBorderDefColor))
84 0 : nLineColor = aBorderDefColor[nLineColor];
85 :
86 : // Map to our border types, we should use of one equal line
87 : // thickness, or one of smaller thickness. If too small we
88 : // can make the defecit up in additional white space or
89 : // object size
90 : ::editeng::SvxBorderStyle const nLineStyle(
91 2615 : ::editeng::ConvertBorderStyleFromWord(nLineType));
92 2615 : rToFill.LineStyle = nLineStyle;
93 : double const fConverted( (NONE == nLineStyle) ? 0.0 :
94 : ::editeng::ConvertBorderWidthFromWord(nLineStyle, nLineThickness,
95 2615 : nLineType));
96 2615 : rToFill.LineWidth = convertTwipToMM100(fConverted);
97 2615 : rToFill.Color = nLineColor;
98 2615 : }
99 :
100 : namespace {
101 1 : void lcl_SwapQuotesInField(OUString &rFmt)
102 : {
103 : //Swap unescaped " and ' with ' and "
104 1 : sal_Int32 nLen = rFmt.getLength();
105 1 : OUStringBuffer aBuffer( rFmt.getStr() );
106 1 : const sal_Unicode* pFmt = rFmt.getStr();
107 12 : for (sal_Int32 nI = 0; nI < nLen; ++nI)
108 : {
109 11 : if ((pFmt[nI] == '\"') && (!nI || pFmt[nI-1] != '\\'))
110 0 : aBuffer[nI] = '\'';
111 11 : else if ((pFmt[nI] == '\'') && (!nI || pFmt[nI-1] != '\\'))
112 0 : aBuffer[nI] = '\"';
113 : }
114 1 : rFmt = aBuffer.makeStringAndClear();
115 1 : }
116 0 : bool lcl_IsNotAM(OUString& rFmt, sal_Int32 nPos)
117 : {
118 : return (
119 0 : (nPos == rFmt.getLength() - 1) ||
120 : (
121 0 : (rFmt[nPos+1] != 'M') &&
122 0 : (rFmt[nPos+1] != 'm')
123 : )
124 0 : );
125 : }
126 : }
127 :
128 1 : OUString ConvertMSFormatStringToSO(
129 : const OUString& rFormat, lang::Locale& rLocale, bool bHijri)
130 : {
131 1 : OUString sFormat(rFormat);
132 1 : lcl_SwapQuotesInField(sFormat);
133 :
134 : //#102782#, #102815#, #108341# & #111944# have to work at the same time :-)
135 1 : bool bForceJapanese(false);
136 1 : bool bForceNatNum(false);
137 1 : sal_Int32 nLen = sFormat.getLength();
138 1 : sal_Int32 nI = 0;
139 : // const sal_Unicode* pFormat = sFormat.getStr();
140 2 : OUStringBuffer aNewFormat( sFormat );
141 13 : while (nI < nLen)
142 : {
143 11 : if (aNewFormat[nI] == '\\')
144 0 : nI++;
145 11 : else if (aNewFormat[nI] == '\"')
146 : {
147 0 : ++nI;
148 : //While not at the end and not at an unescaped end quote
149 0 : while ((nI < nLen) && (!(aNewFormat[nI] == '\"') && (aNewFormat[nI-1] != '\\')))
150 0 : ++nI;
151 : }
152 : else //normal unquoted section
153 : {
154 11 : sal_Unicode nChar = aNewFormat[nI];
155 11 : if (nChar == 'O')
156 : {
157 0 : aNewFormat[nI] = 'M';
158 0 : bForceNatNum = true;
159 : }
160 11 : else if (nChar == 'o')
161 : {
162 0 : aNewFormat[nI] = 'm';
163 0 : bForceNatNum = true;
164 : }
165 11 : else if ((nChar == 'A') && lcl_IsNotAM(sFormat, nI))
166 : {
167 0 : aNewFormat[nI] = 'D';
168 0 : bForceNatNum = true;
169 : }
170 11 : else if ((nChar == 'g') || (nChar == 'G'))
171 0 : bForceJapanese = true;
172 11 : else if ((nChar == 'a') && lcl_IsNotAM(sFormat, nI))
173 0 : bForceJapanese = true;
174 11 : else if (nChar == 'E')
175 : {
176 0 : if ((nI != nLen-1) && (aNewFormat[nI+1] == 'E'))
177 : {
178 : //todo: this cannot be the right way to replace a part of the string!
179 0 : aNewFormat[nI] = 'Y';
180 0 : aNewFormat[nI + 1] = 'Y';
181 0 : aNewFormat.insert(nI + 2, "YY");
182 0 : nLen+=2;
183 0 : nI+=3;
184 : }
185 0 : bForceJapanese = true;
186 : }
187 11 : else if (nChar == 'e')
188 : {
189 0 : if ((nI != nLen-1) && (aNewFormat[nI+1] == 'e'))
190 : {
191 : //todo: this cannot be the right way to replace a part of the string!
192 0 : aNewFormat[nI] = 'y';
193 0 : aNewFormat[nI + 1] = 'y';
194 0 : aNewFormat.insert(nI + 2, "yy");
195 0 : nLen+=2;
196 0 : nI+=3;
197 : }
198 0 : bForceJapanese = true;
199 : }
200 11 : else if (nChar == '/')
201 : {
202 : // MM We have to escape '/' in case it's used as a char
203 : //todo: this cannot be the right way to replace a part of the string!
204 0 : aNewFormat[nI] = '\\';
205 0 : aNewFormat.insert(nI + 1, "/");
206 0 : nI++;
207 0 : nLen++;
208 : }
209 : }
210 11 : ++nI;
211 : }
212 :
213 1 : if (bForceNatNum)
214 0 : bForceJapanese = true;
215 :
216 1 : if (bForceJapanese)
217 : {
218 0 : rLocale.Language = "ja";
219 0 : rLocale.Country = "JP";
220 : }
221 :
222 1 : if (bForceNatNum)
223 : {
224 0 : aNewFormat.insert( 0, "[NatNum1][$-411]");
225 : }
226 :
227 1 : if (bHijri)
228 : {
229 0 : aNewFormat.insert( 0, "[~hijri]");
230 : }
231 2 : return aNewFormat.makeStringAndClear();
232 :
233 : }
234 :
235 :
236 16473 : sal_Int32 convertTwipToMM100(sal_Int32 _t)
237 : {
238 16473 : return TWIP_TO_MM100( _t );
239 : }
240 :
241 :
242 122 : sal_Int32 convertEMUToMM100(sal_Int32 _t)
243 : {
244 122 : return _t / 360;
245 : }
246 :
247 : /*-------------------------------------------------------------------------
248 : contains a color from 0xTTRRGGBB to 0xTTRRGGBB
249 : -----------------------------------------------------------------------*/
250 0 : sal_Int32 ConvertColor(sal_Int32 nWordColor)
251 : {
252 : sal_uInt8
253 0 : r(static_cast<sal_uInt8>(nWordColor&0xFF)),
254 0 : g(static_cast<sal_uInt8>(((nWordColor)>>8)&0xFF)),
255 0 : b(static_cast<sal_uInt8>((nWordColor>>16)&0xFF)),
256 0 : t(static_cast<sal_uInt8>((nWordColor>>24)&0xFF));
257 0 : sal_Int32 nRet = (t<<24) + (r<<16) + (g<<8) + b;
258 0 : return nRet;
259 : }
260 :
261 :
262 34 : sal_Int16 convertTableJustification( sal_Int32 nIntValue )
263 : {
264 34 : sal_Int16 nOrient = text::HoriOrientation::LEFT_AND_WIDTH;
265 34 : switch( nIntValue )
266 : {
267 16 : case 1 : nOrient = text::HoriOrientation::CENTER; break;
268 0 : case 2 : nOrient = text::HoriOrientation::RIGHT; break;
269 : case 0 :
270 : //no break
271 : default:;
272 :
273 : }
274 34 : return nOrient;
275 : }
276 :
277 1183 : sal_Int16 ConvertNumberingType(sal_Int32 nNFC)
278 : {
279 : sal_Int16 nRet;
280 1183 : switch(nNFC)
281 : {
282 : case NS_ooxml::LN_Value_ST_NumberFormat_decimal:
283 : case 0:
284 483 : nRet = style::NumberingType::ARABIC;
285 483 : break;
286 : case NS_ooxml::LN_Value_ST_NumberFormat_upperRoman:
287 : case 1:
288 1 : nRet = style::NumberingType::ROMAN_UPPER;
289 1 : break;
290 : case NS_ooxml::LN_Value_ST_NumberFormat_lowerRoman:
291 : case 2:
292 215 : nRet = style::NumberingType::ROMAN_LOWER;
293 215 : break;
294 : case 3:
295 0 : nRet = style::NumberingType::CHARS_UPPER_LETTER_N;
296 0 : break;
297 : case 4:
298 0 : nRet = style::NumberingType::CHARS_LOWER_LETTER_N;
299 0 : break;
300 : case 5:
301 0 : nRet = style::NumberingType::ARABIC;
302 0 : break;//ORDINAL
303 : case NS_ooxml::LN_Value_ST_NumberFormat_bullet:
304 : case 23:
305 : case 25:
306 333 : nRet = style::NumberingType::CHAR_SPECIAL;
307 333 : break;
308 : case NS_ooxml::LN_Value_ST_NumberFormat_none:
309 : case 255:
310 46 : nRet = style::NumberingType::NUMBER_NONE;
311 46 : break;
312 : case NS_ooxml::LN_Value_ST_NumberFormat_upperLetter:
313 2 : nRet = style::NumberingType::CHARS_UPPER_LETTER;
314 2 : break;
315 : case NS_ooxml::LN_Value_ST_NumberFormat_lowerLetter:
316 103 : nRet = style::NumberingType::CHARS_LOWER_LETTER;
317 103 : break;
318 : case NS_ooxml::LN_Value_ST_NumberFormat_iroha:
319 0 : nRet = style::NumberingType::IROHA_HALFWIDTH_JA;
320 0 : break;
321 : case NS_ooxml::LN_Value_ST_NumberFormat_irohaFullWidth:
322 0 : nRet = style::NumberingType::IROHA_FULLWIDTH_JA;
323 0 : break;
324 : case NS_ooxml::LN_Value_ST_NumberFormat_aiueo:
325 0 : nRet = style::NumberingType::AIU_HALFWIDTH_JA;
326 0 : break;
327 : case NS_ooxml::LN_Value_ST_NumberFormat_aiueoFullWidth:
328 0 : nRet = style::NumberingType::AIU_FULLWIDTH_JA;
329 0 : break;
330 : case NS_ooxml::LN_Value_ST_NumberFormat_hebrew2:
331 0 : nRet = style::NumberingType::CHARS_HEBREW;
332 0 : break;
333 : case NS_ooxml::LN_Value_ST_NumberFormat_thaiLetters:
334 0 : nRet = style::NumberingType::CHARS_THAI;
335 0 : break;
336 : case NS_ooxml::LN_Value_ST_NumberFormat_russianLower:
337 0 : nRet = style::NumberingType::CHARS_CYRILLIC_LOWER_LETTER_RU;
338 0 : break;
339 : case NS_ooxml::LN_Value_ST_NumberFormat_russianUpper:
340 0 : nRet = style::NumberingType::CHARS_CYRILLIC_UPPER_LETTER_RU;
341 0 : break;
342 : case NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircleChinese:
343 : case NS_ooxml::LN_Value_ST_NumberFormat_ideographEnclosedCircle:
344 0 : nRet = style::NumberingType::CIRCLE_NUMBER;
345 0 : break;
346 : case NS_ooxml::LN_Value_ST_NumberFormat_ideographTraditional:
347 0 : nRet = style::NumberingType::TIAN_GAN_ZH;
348 0 : break;
349 : case NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiac:
350 0 : nRet = style::NumberingType::DI_ZI_ZH;
351 0 : break;
352 : case NS_ooxml::LN_Value_ST_NumberFormat_ganada:
353 0 : nRet = style::NumberingType::HANGUL_SYLLABLE_KO;
354 0 : break;
355 : case NS_ooxml::LN_Value_ST_NumberFormat_chosung:
356 0 : nRet = style::NumberingType::HANGUL_JAMO_KO;
357 0 : break;
358 : case NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital:
359 : case NS_ooxml::LN_Value_ST_NumberFormat_koreanCounting:
360 : case NS_ooxml::LN_Value_ST_NumberFormat_koreanDigital2:
361 0 : nRet = style::NumberingType::NUMBER_HANGUL_KO;
362 0 : break;
363 : case NS_ooxml::LN_Value_ST_NumberFormat_ideographLegalTraditional:
364 0 : nRet = style::NumberingType::NUMBER_UPPER_ZH_TW;
365 0 : break;
366 : case NS_ooxml::LN_Value_ST_NumberFormat_arabicAlpha:
367 0 : nRet = style::NumberingType::CHARS_ARABIC;
368 0 : break;
369 : case NS_ooxml::LN_Value_ST_NumberFormat_hindiVowels:
370 0 : nRet = style::NumberingType::CHARS_NEPALI;
371 0 : break;
372 : case NS_ooxml::LN_Value_ST_NumberFormat_japaneseLegal:
373 0 : nRet = style::NumberingType::NUMBER_TRADITIONAL_JA;
374 0 : break;
375 : case NS_ooxml::LN_Value_ST_NumberFormat_chineseCounting:
376 : case NS_ooxml::LN_Value_ST_NumberFormat_japaneseCounting:
377 : case NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCounting:
378 : case NS_ooxml::LN_Value_ST_NumberFormat_ideographDigital:
379 : case NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand:
380 0 : nRet = style::NumberingType::NUMBER_LOWER_ZH;
381 0 : break;
382 : case NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified:
383 0 : nRet = style::NumberingType::NUMBER_UPPER_ZH;
384 0 : break;
385 0 : default: nRet = style::NumberingType::ARABIC;
386 : }
387 : /* TODO: Lots of additional values are available - some are supported in the I18 framework
388 : NS_ooxml::LN_Value_ST_NumberFormat_ordinal = 91682;
389 : NS_ooxml::LN_Value_ST_NumberFormat_cardinalText = 91683;
390 : NS_ooxml::LN_Value_ST_NumberFormat_ordinalText = 91684;
391 : NS_ooxml::LN_Value_ST_NumberFormat_hex = 91685;
392 : NS_ooxml::LN_Value_ST_NumberFormat_chicago = 91686;
393 : NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth = 91691;
394 : NS_ooxml::LN_Value_ST_NumberFormat_decimalHalfWidth = 91692;
395 : NS_ooxml::LN_Value_ST_NumberFormat_japaneseDigitalTenThousand = 91694;
396 : NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedCircle = 91695;
397 : NS_ooxml::LN_Value_ST_NumberFormat_decimalFullWidth2 = 91696;
398 : NS_ooxml::LN_Value_ST_NumberFormat_decimalZero = 91699;
399 : NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedFullstop = 91703;
400 : NS_ooxml::LN_Value_ST_NumberFormat_decimalEnclosedParen = 91704;
401 : NS_ooxml::LN_Value_ST_NumberFormat_ideographZodiacTraditional = 91709;
402 : NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseCountingThousand = 91712;
403 : NS_ooxml::LN_Value_ST_NumberFormat_taiwaneseDigital = 91713;
404 : NS_ooxml::LN_Value_ST_NumberFormat_chineseLegalSimplified = 91715;
405 : NS_ooxml::LN_Value_ST_NumberFormat_chineseCountingThousand = 91716;
406 : NS_ooxml::LN_Value_ST_NumberFormat_koreanLegal = 91719;
407 : NS_ooxml::LN_Value_ST_NumberFormat_vietnameseCounting = 91721;
408 : NS_ooxml::LN_Value_ST_NumberFormat_numberInDash = 91725;
409 : NS_ooxml::LN_Value_ST_NumberFormat_arabicAbjad:
410 : NS_ooxml::LN_Value_ST_NumberFormat_hebrew1 = 91726;
411 : NS_ooxml::LN_Value_ST_NumberFormat_hindiConsonants = 91731;
412 : NS_ooxml::LN_Value_ST_NumberFormat_hindiNumbers = 91732;
413 : NS_ooxml::LN_Value_ST_NumberFormat_hindiCounting = 91733;
414 : NS_ooxml::LN_Value_ST_NumberFormat_thaiNumbers = 91735;
415 : NS_ooxml::LN_Value_ST_NumberFormat_thaiCounting = 91736;*/
416 1183 : return nRet;
417 : }
418 :
419 :
420 : } // namespace ConversionHelper
421 : } //namespace dmapper
422 24 : } //namespace writerfilter
423 :
424 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|