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