File indexing completed on 2025-01-19 13:27:35
0001 /* 0002 * This file is part of Office 2007 Filters for Calligra 0003 * 0004 * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). 0005 * 0006 * Contact: Suresh Chande suresh.chande@nokia.com 0007 * 0008 * This library is free software; you can redistribute it and/or 0009 * modify it under the terms of the GNU Lesser General Public License 0010 * version 2.1 as published by the Free Software Foundation. 0011 * 0012 * This library is distributed in the hope that it will be useful, but 0013 * WITHOUT ANY WARRANTY; without even the implied warranty of 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0015 * Lesser General Public License for more details. 0016 * 0017 * You should have received a copy of the GNU Lesser General Public 0018 * License along with this library; if not, write to the Free Software 0019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 0020 * 02110-1301 USA 0021 * 0022 */ 0023 0024 #include "XlsxUtils.h" 0025 #include "XlsxXmlCommonReader.h" 0026 0027 #include <math.h> 0028 0029 #include <MsooXmlSchemas.h> 0030 #include <MsooXmlUtils.h> 0031 #include <KoXmlWriter.h> 0032 #include <KoCharacterStyle.h> 0033 0034 #undef MSOOXML_CURRENT_NS 0035 #define MSOOXML_CURRENT_CLASS XlsxXmlCommonReader 0036 #define BIND_READ_CLASS MSOOXML_CURRENT_CLASS 0037 0038 #include <MsooXmlReader_p.h> 0039 0040 class XlsxXmlCommonReader::Private 0041 { 0042 public: 0043 Private() { 0044 } 0045 ~Private() { 0046 } 0047 private: 0048 }; 0049 0050 XlsxXmlCommonReader::XlsxXmlCommonReader(KoOdfWriters *writers) 0051 : MSOOXML::MsooXmlReader(writers) 0052 , d(new Private) 0053 { 0054 init(); 0055 } 0056 0057 XlsxXmlCommonReader::~XlsxXmlCommonReader() 0058 { 0059 delete d; 0060 } 0061 0062 void XlsxXmlCommonReader::init() 0063 { 0064 m_currentTextStyleProperties = 0; 0065 } 0066 0067 QColor XlsxXmlCommonReader::tintedColor(const QColor& color, qreal tint) 0068 { 0069 const int HLSMAX = 255; // Used for computing tint 0070 if (tint == 0.0 || !color.isValid()) { 0071 return color; 0072 } 0073 int h, l, s; 0074 color.getHsl(&h, &l, &s); 0075 if (tint < 0.0) { 0076 l = floor( l * (1.0 + tint) ); 0077 } 0078 else { 0079 l = floor( l * (1.0 - tint) + (HLSMAX - HLSMAX * (1.0 - tint)) ); 0080 } 0081 int r, g, b; 0082 color.getRgb(&r, &g, &b); 0083 return QColor(r, g, b, color.alpha()); 0084 } 0085 0086 #undef CURRENT_EL 0087 #define CURRENT_EL t 0088 //! t handler (Text) 0089 /*! ECMA-376, 18.4.12, p. 1914. 0090 This element represents the text content shown as part of a string. 0091 0092 No child elements. 0093 Parent elements: 0094 - is (§18.3.1.53) 0095 - [done] r (§18.4.4) 0096 - rPh (§18.4.6) 0097 - [done] si (§18.4.8) 0098 - text (§18.7.7) 0099 0100 @todo support all child elements 0101 */ 0102 KoFilter::ConversionStatus XlsxXmlCommonReader::read_t() 0103 { 0104 READ_PROLOGUE 0105 while (!atEnd()) { 0106 readNext(); 0107 qCDebug(lcXlsxImport) << *this; 0108 if (isCharacters()) { 0109 body->addTextSpan(text().toString()); 0110 } 0111 BREAK_IF_END_OF(CURRENT_EL) 0112 } 0113 READ_EPILOGUE 0114 } 0115 0116 #undef CURRENT_EL 0117 #define CURRENT_EL r 0118 //! r handler (Rich Text Run) 0119 /*! ECMA-376, 18.4.12, p. 1909. 0120 This element represents a run of rich text. A rich text run is a region of text that share a common set of 0121 properties, such as formatting properties. The properties are defined in the rPr element, and the text displayed 0122 to the user is defined in the Text (t) element. 0123 0124 Parent elements: 0125 - is (§18.3.1.53) 0126 - [done] si (§18.4.8) 0127 - text (§18.7.7) 0128 0129 Child elements: 0130 - [done] rPr (§18.4.7) 0131 - [done] t (§18.4.12) 0132 0133 @todo support all elements 0134 */ 0135 KoFilter::ConversionStatus XlsxXmlCommonReader::read_r() 0136 { 0137 READ_PROLOGUE 0138 0139 m_currentTextStyle = KoGenStyle(KoGenStyle::TextAutoStyle, "text"); 0140 0141 MSOOXML::Utils::XmlWriteBuffer rBuf; 0142 body = rBuf.setWriter(body); 0143 0144 while (!atEnd()) { 0145 readNext(); 0146 BREAK_IF_END_OF(CURRENT_EL) 0147 if (isStartElement()) { 0148 TRY_READ_IF(rPr) 0149 ELSE_TRY_READ_IF(t) 0150 ELSE_WRONG_FORMAT 0151 } 0152 } 0153 0154 body = rBuf.originalWriter(); 0155 0156 body->startElement("text:span", false); 0157 if (!m_currentTextStyle.isEmpty() || !m_currentTextStyle.parentName().isEmpty()) { 0158 const QString currentTextStyleName(mainStyles->insert(m_currentTextStyle)); 0159 body->addAttribute("text:style-name", currentTextStyleName); 0160 } 0161 0162 (void)rBuf.releaseWriter(); 0163 0164 body->endElement(); //text:span 0165 0166 READ_EPILOGUE 0167 } 0168 0169 #undef CURRENT_EL 0170 #define CURRENT_EL rPr 0171 //! rPr handler (Run Properties) 0172 /*! ECMA-376, 18.4.7, p. 1911. 0173 This element represents a set of properties to apply to the contents of this rich text run. 0174 0175 Parent elements: 0176 - [done] r (§18.4.4) 0177 0178 Child elements: 0179 - [done] b §18.8.2 0180 - charset §18.4.1 0181 - [done] color §18.3.1.15 0182 - condense §18.8.12 0183 - extend §18.8.17 0184 - family §18.8.18 0185 - [done] i §18.8.26 0186 - [done] outline §18.4.2 0187 - [done] rFont §18.4.5 0188 - [done] scheme §18.8.35 0189 - shadow §18.8.36 0190 - [done] strike §18.4.10 0191 - [done] sz §18.4.11 0192 - [done] u §18.4.13 0193 - [done] vertAlign §18.4.14 0194 0195 @todo support all child elements 0196 */ 0197 KoFilter::ConversionStatus XlsxXmlCommonReader::read_rPr() 0198 { 0199 READ_PROLOGUE 0200 m_currentTextStyleProperties = new KoCharacterStyle; 0201 0202 m_currentColor = QColor(); 0203 0204 while (!atEnd()) { 0205 readNext(); 0206 BREAK_IF_END_OF(CURRENT_EL) 0207 if (isStartElement()) { 0208 TRY_READ_IF(vertAlign) 0209 ELSE_TRY_READ_IF(sz) 0210 ELSE_TRY_READ_IF(rFont) 0211 ELSE_TRY_READ_IF(color) 0212 ELSE_TRY_READ_IF(u) 0213 ELSE_TRY_READ_IF(i) 0214 ELSE_TRY_READ_IF(b) 0215 ELSE_TRY_READ_IF(strike) 0216 ELSE_TRY_READ_IF(outline) 0217 SKIP_UNKNOWN 0218 //! @todo add ELSE_WRONG_FORMAT 0219 } 0220 } 0221 0222 if (m_currentColor.isValid()) { 0223 m_currentTextStyleProperties->setForeground(QBrush(m_currentColor)); 0224 } 0225 0226 m_currentTextStyleProperties->saveOdf(m_currentTextStyle); 0227 delete m_currentTextStyleProperties; 0228 m_currentTextStyleProperties = 0; 0229 READ_EPILOGUE 0230 } 0231 0232 #undef CURRENT_EL 0233 #define CURRENT_EL vertAlign 0234 //! vertAlign handler (Vertical Alignment) 0235 /*! ECMA-376, 18.4.7, p. 1914. 0236 This element adjusts the vertical position of the text relative to the text's default appearance for this run. 0237 It is used to get 'superscript' or 'subscript' texts, and shall reduce the font size 0238 (if a smaller size is available) accordingly. 0239 0240 Parent elements: 0241 - [done] font (§18.8.22) 0242 - [done] rPr (§18.4.7) 0243 0244 No child elements. 0245 0246 @todo support all elements 0247 */ 0248 KoFilter::ConversionStatus XlsxXmlCommonReader::read_vertAlign() 0249 { 0250 READ_PROLOGUE 0251 const QXmlStreamAttributes attrs(attributes()); 0252 TRY_READ_ATTR_WITHOUT_NS(val) 0253 if (val == "subscript") { 0254 m_currentTextStyleProperties->setVerticalAlignment(QTextCharFormat::AlignSubScript); 0255 } 0256 else if (val == "superscript") { 0257 m_currentTextStyleProperties->setVerticalAlignment(QTextCharFormat::AlignSuperScript); 0258 } 0259 0260 readNext(); 0261 READ_EPILOGUE 0262 } 0263 0264 #undef CURRENT_EL 0265 #define CURRENT_EL sz 0266 //! fontSize 0267 /* 0268 Parent elements: 0269 - [done] font (§18.8.22); 0270 - [done] rPr (§18.4.7) 0271 0272 Child elements: 0273 - none 0274 */ 0275 KoFilter::ConversionStatus XlsxXmlCommonReader::read_sz() 0276 { 0277 READ_PROLOGUE 0278 const QXmlStreamAttributes attrs(attributes()); 0279 TRY_READ_ATTR_WITHOUT_NS(val) 0280 0281 if (!val.isEmpty()) { 0282 m_currentTextStyleProperties->setFontPointSize(val.toDouble()); 0283 } 0284 0285 readNext(); 0286 READ_EPILOGUE 0287 } 0288 0289 #undef CURRENT_EL 0290 #define CURRENT_EL rFont 0291 //! font 0292 /* 0293 Parent elements: 0294 - [done] rPr (§18.4.7) 0295 0296 Child elements: 0297 - none 0298 */ 0299 KoFilter::ConversionStatus XlsxXmlCommonReader::read_rFont() 0300 { 0301 READ_PROLOGUE 0302 const QXmlStreamAttributes attrs(attributes()); 0303 TRY_READ_ATTR_WITHOUT_NS(val) 0304 0305 if (!val.isEmpty()) { 0306 m_currentTextStyle.addProperty("fo:font-family", val); 0307 } 0308 0309 readNext(); 0310 READ_EPILOGUE 0311 } 0312 0313 #undef CURRENT_EL 0314 #define CURRENT_EL i 0315 //! i handler (Italic) 0316 /*! ECMA-376, 18.8.26, p. 1969. 0317 Displays characters in italic font style. 0318 0319 Parent elements: 0320 - [done] font (§18.8.22) 0321 - [done] rPr (§18.4.7) 0322 0323 Child elements: 0324 - none 0325 */ 0326 KoFilter::ConversionStatus XlsxXmlCommonReader::read_i() 0327 { 0328 READ_PROLOGUE 0329 const QXmlStreamAttributes attrs(attributes()); 0330 TRY_READ_ATTR_WITHOUT_NS(val) 0331 const bool italic = MSOOXML::Utils::convertBooleanAttr(val, true); 0332 m_currentTextStyleProperties->setFontItalic(italic); 0333 0334 readNext(); 0335 READ_EPILOGUE 0336 } 0337 0338 #undef CURRENT_EL 0339 #define CURRENT_EL scheme 0340 //! scheme handler (Scheme) 0341 /*! 0342 0343 Parent elements: 0344 - [done] font (§18.8.22) 0345 - [done] rPr (§18.4.7) 0346 0347 Child elements: 0348 - none 0349 */ 0350 KoFilter::ConversionStatus XlsxXmlCommonReader::read_scheme() 0351 { 0352 READ_PROLOGUE 0353 0354 const QXmlStreamAttributes attrs(attributes()); 0355 TRY_READ_ATTR_WITHOUT_NS(val) 0356 QString font; 0357 0358 if (val == "major") { 0359 font = m_themes->fontScheme.majorFonts.latinTypeface; 0360 m_currentTextStyle.addProperty("fo:font-family", font); 0361 } else if (val == "minor") { 0362 font = m_themes->fontScheme.minorFonts.latinTypeface; 0363 m_currentTextStyle.addProperty("fo:font-family", font); 0364 } 0365 0366 readNext(); 0367 READ_EPILOGUE 0368 } 0369 0370 #undef CURRENT_EL 0371 #define CURRENT_EL b 0372 //! b handler (Bold) 0373 /*! ECMA-376, 18.8.2, p. 1947. 0374 Displays characters in bold face font style. 0375 0376 Parent elements: 0377 - [done] font (§18.8.22) 0378 - [done] rPr (§18.4.7) 0379 0380 Child elements: 0381 - none 0382 */ 0383 KoFilter::ConversionStatus XlsxXmlCommonReader::read_b() 0384 { 0385 READ_PROLOGUE 0386 0387 const QXmlStreamAttributes attrs(attributes()); 0388 TRY_READ_ATTR_WITHOUT_NS(val) 0389 const bool bold = MSOOXML::Utils::convertBooleanAttr(val, true); 0390 m_currentTextStyleProperties->setFontWeight(bold ? QFont::Bold : QFont::Normal); 0391 0392 readNext(); 0393 READ_EPILOGUE 0394 } 0395 0396 #undef CURRENT_EL 0397 #define CURRENT_EL outline 0398 //! outline handler (Outline) 0399 /*! 0400 0401 Parent elements: 0402 - [done] font (§18.8.22) 0403 - [done] rPr (§18.4.7) 0404 0405 Child elements: 0406 - none 0407 */ 0408 KoFilter::ConversionStatus XlsxXmlCommonReader::read_outline() 0409 { 0410 READ_PROLOGUE 0411 0412 const QXmlStreamAttributes attrs(attributes()); 0413 TRY_READ_ATTR_WITHOUT_NS(val) 0414 if (val == "1") { 0415 m_currentTextStyleProperties->setTextOutline(QPen(Qt::SolidLine)); 0416 } 0417 0418 readNext(); 0419 READ_EPILOGUE 0420 } 0421 0422 #undef CURRENT_EL 0423 #define CURRENT_EL strike 0424 //! strike handler (Strike Through) 0425 /*! ECMA-376, 18.4.10, p. 1913. 0426 This element draws a strikethrough line through the horizontal middle of the text. 0427 0428 Parent elements: 0429 - [done] font (§18.8.22) 0430 - [done] rPr (§18.4.7) 0431 0432 Child elements: 0433 - none 0434 */ 0435 KoFilter::ConversionStatus XlsxXmlCommonReader::read_strike() 0436 { 0437 READ_PROLOGUE 0438 0439 m_currentTextStyleProperties->setStrikeOutStyle(KoCharacterStyle::SolidLine); 0440 m_currentTextStyleProperties->setStrikeOutType(KoCharacterStyle::SingleLine); 0441 0442 readNext(); 0443 READ_EPILOGUE 0444 } 0445 0446 #undef CURRENT_EL 0447 #define CURRENT_EL u 0448 //! u handler (Underline) 0449 /*! ECMA-376, 18.4.13, p. 1914. 0450 This element represents the underline formatting style. 0451 0452 Parent elements: 0453 - [done] font (§18.8.22) 0454 - [done] rPr (§18.4.7) 0455 0456 Child elements: 0457 - none 0458 */ 0459 KoFilter::ConversionStatus XlsxXmlCommonReader::read_u() 0460 { 0461 READ_PROLOGUE 0462 const QXmlStreamAttributes attrs(attributes()); 0463 0464 TRY_READ_ATTR_WITHOUT_NS(val) 0465 if (!val.isEmpty()) { 0466 MSOOXML::Utils::setupUnderLineStyle(val, m_currentTextStyleProperties); 0467 } 0468 0469 readNext(); 0470 READ_EPILOGUE 0471 } 0472 0473 #undef CURRENT_EL 0474 #define CURRENT_EL color 0475 //! color 0476 /* 0477 Parent elements: 0478 - [done] font (§18.8.22); 0479 - [done] rPr (§18.4.7) 0480 0481 Child elements: 0482 - none 0483 */ 0484 KoFilter::ConversionStatus XlsxXmlCommonReader::read_color() 0485 { 0486 READ_PROLOGUE 0487 const QXmlStreamAttributes attrs(attributes()); 0488 0489 TRY_READ_ATTR_WITHOUT_NS(indexed) 0490 TRY_READ_ATTR_WITHOUT_NS(rgb) 0491 TRY_READ_ATTR_WITHOUT_NS(theme) 0492 TRY_READ_ATTR_WITHOUT_NS(tint) 0493 0494 if (!indexed.isEmpty()) { 0495 int index = indexed.toInt(); 0496 if (index >= 0 && index < 64) { 0497 m_currentColor = QString("#%1").arg(m_colorIndices.at(index)); 0498 } 0499 } 0500 if (!rgb.isEmpty()) { 0501 m_currentColor = QString("#" + rgb.right(rgb.length()-2)); 0502 } 0503 if (!theme.isEmpty()) { 0504 // Xlsx seems to switch these indices 0505 if (theme == "0" ) { 0506 theme = "1"; 0507 } 0508 else if (theme == "1" ) { 0509 theme = "0"; 0510 } 0511 else if (theme == "2") { 0512 theme = "3"; 0513 } 0514 else if (theme == "3") { 0515 theme = "2"; 0516 } 0517 MSOOXML::DrawingMLColorSchemeItemBase *colorItemBase = m_themes->colorScheme.value(theme); 0518 if (colorItemBase) { 0519 m_currentColor = colorItemBase->value(); 0520 } 0521 } 0522 if (!tint.isEmpty()) { 0523 m_currentColor = tintedColor(m_currentColor, tint.toDouble()); 0524 } 0525 0526 readNext(); 0527 READ_EPILOGUE 0528 }