/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ #include #include #include #include "hwpreader.hxx" #include #include #include #include #include #include #include #include #include "fontmap.hxx" #include "formula.h" #include "cspline.h" #include "datecode.h" #include #include #include #include #include #include // xmloff/xmlkyd.hxx constexpr OUString sXML_CDATA = u"CDATA"_ustr; namespace { double WTI(double x) { return x / 1800.; } // unit => inch double WTMM(double x) { return x / 1800. * 25.4; } // unit => mm int WTSM(double x) { return x / 1800. * 2540; } // unit ==> 1/100 mm constexpr OUString sBeginOfDoc(u"[\uBB38\uC11C\uC758 \uCC98\uC74C]"_ustr); // U+BB38 HANGUL SYLLABLE MUN, U+C11C HANGUL SYLLABLE SEO, // U+C758 HANGUL SYLLABLE YI, U+CC98 HANGUL SYLLABLE CEO, // U+C74C HANGUL SYLLABLE EUM: "Begin of Document" } struct HwpReaderPrivate { HwpReaderPrivate() { bFirstPara = true; bInBody = false; bInHeader = false; nPnPos = 0; pPn = nullptr; pField = nullptr; } bool bFirstPara; bool bInBody; bool bInHeader; ShowPageNum *pPn; hchar *pField; int nPnPos; char buf[1024]; }; HwpReader::HwpReader() : mxList(new AttributeListImpl), d(new HwpReaderPrivate) { } HwpReader::~HwpReader() { } extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportHWP(SvStream &rStream) { try { std::unique_ptr stream(new HStream); byte aData[32768]; while (true) { std::size_t nRead = rStream.ReadBytes(aData, 32768); if (nRead == 0) break; stream->addData(aData, static_cast(nRead)); } rtl::Reference hwpreader(new HwpReader); return hwpreader->importHStream(std::move(stream)); } catch (...) { } return false; } bool HwpReader::importHStream(std::unique_ptr stream) { if (hwpfile.ReadHwpFile(std::move(stream))) return false; if (m_rxDocumentHandler.is()) m_rxDocumentHandler->startDocument(); mxList->addAttribute(u"office:class"_ustr, sXML_CDATA, u"text"_ustr); mxList->addAttribute(u"office:version"_ustr, sXML_CDATA, u"0.9"_ustr); mxList->addAttribute(u"xmlns:office"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/office"_ustr); mxList->addAttribute(u"xmlns:style"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/style"_ustr); mxList->addAttribute(u"xmlns:text"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/text"_ustr); mxList->addAttribute(u"xmlns:table"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/table"_ustr); mxList->addAttribute(u"xmlns:draw"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/drawing"_ustr); mxList->addAttribute(u"xmlns:fo"_ustr, u"CDATA"_ustr, u"http://www.w3.org/1999/XSL/Format"_ustr); mxList->addAttribute(u"xmlns:xlink"_ustr, u"CDATA"_ustr, u"http://www.w3.org/1999/xlink"_ustr); mxList->addAttribute(u"xmlns:dc"_ustr, u"CDATA"_ustr, u"http://purl.org/dc/elements/1.1/"_ustr); mxList->addAttribute(u"xmlns:meta"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/meta"_ustr); mxList->addAttribute(u"xmlns:number"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/datastyle"_ustr); mxList->addAttribute(u"xmlns:svg"_ustr, u"CDATA"_ustr, u"http://www.w3.org/2000/svg"_ustr); mxList->addAttribute(u"xmlns:chart"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/chart"_ustr); mxList->addAttribute(u"xmlns:dr3d"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/dr3d"_ustr); mxList->addAttribute(u"xmlns:math"_ustr, u"CDATA"_ustr, u"http://www.w3.org/1998/Math/MathML"_ustr); mxList->addAttribute(u"xmlns:form"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/form"_ustr); mxList->addAttribute(u"xmlns:script"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/script"_ustr); startEl(u"office:document"_ustr); mxList->clear(); makeMeta(); makeStyles(); makeAutoStyles(); makeMasterStyles(); makeBody(); endEl(u"office:document"_ustr); if (m_rxDocumentHandler.is()) m_rxDocumentHandler->endDocument(); return true; } sal_Bool HwpReader::filter(const Sequence< PropertyValue >& rDescriptor) { utl::MediaDescriptor aDescriptor(rDescriptor); aDescriptor.addInputStream(); Reference< XInputStream > xInputStream( aDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM], UNO_QUERY_THROW); std::unique_ptr stream(new HStream); Sequence < sal_Int8 > aBuffer; sal_Int32 nRead, nTotal = 0; while( true ) { nRead = xInputStream->readBytes(aBuffer, 32768); if( nRead == 0 ) break; stream->addData( reinterpret_cast(aBuffer.getConstArray()), nRead ); nTotal += nRead; } if( nTotal == 0 ) return false; return importHStream(std::move(stream)); } /** * make office:body */ void HwpReader::makeBody() { startEl(u"office:body"_ustr); makeTextDecls(); HWPPara *hwppara = hwpfile.GetFirstPara(); d->bInBody = true; parsePara(hwppara); endEl(u"office:body"_ustr); d->bInBody = false; } /** * make text decls */ void HwpReader::makeTextDecls() { startEl(u"text:sequence-decls"_ustr); mxList->addAttribute(u"text:display-outline-level"_ustr, sXML_CDATA, u"0"_ustr); mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, u"Illustration"_ustr); startEl(u"text:sequence-decl"_ustr); mxList->clear(); endEl(u"text:sequence-decl"_ustr); mxList->addAttribute(u"text:display-outline-level"_ustr, sXML_CDATA, u"0"_ustr); mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, u"Table"_ustr); startEl(u"text:sequence-decl"_ustr); mxList->clear(); endEl(u"text:sequence-decl"_ustr); mxList->addAttribute(u"text:display-outline-level"_ustr, sXML_CDATA, u"0"_ustr); mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, u"Text"_ustr); startEl(u"text:sequence-decl"_ustr); mxList->clear(); endEl(u"text:sequence-decl"_ustr); mxList->addAttribute(u"text:display-outline-level"_ustr, sXML_CDATA, u"0"_ustr); mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, u"Drawing"_ustr); startEl(u"text:sequence-decl"_ustr); mxList->clear(); endEl(u"text:sequence-decl"_ustr); endEl(u"text:sequence-decls"_ustr); } /** * make office:meta * Completed */ void HwpReader::makeMeta() { HWPInfo& hwpinfo = hwpfile.GetHWPInfo(); startEl(u"office:meta"_ustr); if (hwpinfo.summary.title[0]) { startEl(u"dc:title"_ustr); chars(hstr2OUString(reinterpret_cast(hwpinfo.summary.title))); endEl(u"dc:title"_ustr); } if (hwpinfo.summary.subject[0]) { startEl(u"dc:subject"_ustr); chars(hstr2OUString(reinterpret_cast(hwpinfo.summary.subject))); endEl(u"dc:subject"_ustr); } if (hwpinfo.summary.author[0]) { startEl(u"meta:initial-creator"_ustr); chars(hstr2OUString(reinterpret_cast(hwpinfo.summary.author))); endEl(u"meta:initial-creator"_ustr); } if (hwpinfo.summary.date[0]) { unsigned short *pDate = hwpinfo.summary.date; int year,month,day,hour,minute; int gab = 0; if( rtl::isAsciiDigit( pDate[0] ) && rtl::isAsciiDigit( pDate[1] ) && rtl::isAsciiDigit( pDate[2] ) && rtl::isAsciiDigit( pDate[3] )) { year = (pDate[0]-0x30) * 1000 + (pDate[1]-0x30) * 100 + (pDate[2]-0x30) * 10 + (pDate[3]-0x30); } else { year = 0; } if( rtl::isAsciiDigit( pDate[6] )) { if( rtl::isAsciiDigit( pDate[7] ) ) month = (pDate[6] - 0x30) * 10 + (pDate[6+ ++gab]-0x30); else month = (pDate[6] - 0x30); } else { month = 0; } if( rtl::isAsciiDigit( pDate[9 + gab] ) ) { if( rtl::isAsciiDigit( pDate[10 + gab])) { day = ( pDate[9 + gab] - 0x30 ) * 10 + (pDate[9+ gab + 1]-0x30); ++gab; } else day = (pDate[9+gab]-0x30); } else { day = 0; } if( rtl::isAsciiDigit( pDate[17 + gab] ) ) { if( rtl::isAsciiDigit( pDate[18 + gab])) { hour = ( pDate[17 + gab] - 0x30 ) * 10 + (pDate[17+ gab + 1]-0x30); ++gab; } else hour = (pDate[17+gab]-0x30); } else { hour = 0; } if( rtl::isAsciiDigit( pDate[20 + gab] ) ) { if( rtl::isAsciiDigit( pDate[21 + gab])) { minute = ( pDate[20 + gab] - 0x30 ) * 10 + (pDate[20+ gab + 1]-0x30); ++gab; } else minute = (pDate[20+gab]-0x30); } else { minute = 0; } o3tl::sprintf(d->buf,"%d-%02d-%02dT%02d:%02d:00",year,month,day,hour,minute); startEl(u"meta:creation-date"_ustr); chars( OUString::createFromAscii(d->buf)); endEl(u"meta:creation-date"_ustr); } if (hwpinfo.summary.keyword[0][0] || hwpinfo.summary.etc[0][0]) { startEl(u"meta:keywords"_ustr); if (hwpinfo.summary.keyword[0][0]) { startEl(u"meta:keyword"_ustr); chars(hstr2OUString(reinterpret_cast(hwpinfo.summary.keyword[0]))); endEl(u"meta:keyword"_ustr); } if (hwpinfo.summary.keyword[1][0]) { startEl(u"meta:keyword"_ustr); chars(hstr2OUString(reinterpret_cast(hwpinfo.summary.keyword[1]))); endEl(u"meta:keyword"_ustr); } if (hwpinfo.summary.etc[0][0]) { startEl(u"meta:keyword"_ustr); chars(hstr2OUString(reinterpret_cast(hwpinfo.summary.etc[0]))); endEl(u"meta:keyword"_ustr); } if (hwpinfo.summary.etc[1][0]) { startEl(u"meta:keyword"_ustr); chars(hstr2OUString(reinterpret_cast(hwpinfo.summary.etc[1]))); endEl(u"meta:keyword"_ustr); } if (hwpinfo.summary.etc[2][0]) { startEl(u"meta:keyword"_ustr); chars(hstr2OUString(reinterpret_cast(hwpinfo.summary.etc[2]))); endEl(u"meta:keyword"_ustr); } endEl(u"meta:keywords"_ustr); } endEl(u"office:meta"_ustr); } static struct { const char *name; bool bMade; } ArrowShape[] = { { "", false }, { "Arrow", false }, { "Line Arrow", false }, { "Square", false } }; struct { double dots1; double dots2; double distance; } const LineStyle[] = { { 0.0, 0.0, 0.0 }, { 0.34, 0., 0.272 }, { 0.17, 0., 0.136}, { 0.612, 0.17, 0.136 }, { 0.85, 0.17, 0.136} }; void HwpReader::makeDrawMiscStyle( HWPDrawingObject *hdo ) { while( hdo ) { if( hdo->child ) makeDrawMiscStyle( hdo->child.get() ); HWPDOProperty *prop = &hdo->property; if( hdo->type == HWPDO_CONTAINER ) { hdo = hdo->next.get(); continue; } if( prop->line_pstyle > 0 && prop->line_pstyle < 5 && prop->line_color <= 0xffffff) { mxList->addAttribute( u"draw:name"_ustr, sXML_CDATA, "LineType" + OUString::number(hdo->index)); mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"round"_ustr); mxList->addAttribute( u"draw:dots1"_ustr, sXML_CDATA, u"1"_ustr); mxList->addAttribute( u"draw:dots1-length"_ustr, sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots1 * WTMM(prop->line_width) ) + "cm"); if( prop->line_pstyle == 3 ) { mxList->addAttribute( u"draw:dots2"_ustr, sXML_CDATA, u"1"_ustr); mxList->addAttribute( u"draw:dots2-length"_ustr, sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width) ) + "cm"); } else if( prop->line_pstyle == 4 ) { mxList->addAttribute( u"draw:dots2"_ustr, sXML_CDATA, u"2"_ustr); mxList->addAttribute( u"draw:dots2-length"_ustr, sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width)) + "cm"); } mxList->addAttribute( u"draw:distance"_ustr, sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].distance * WTMM(prop->line_width)) + "cm"); startEl(u"draw:stroke-dash"_ustr); mxList->clear(); endEl(u"draw:stroke-dash"_ustr); } if( hdo->type == HWPDO_LINE || hdo->type == HWPDO_ARC || hdo->type == HWPDO_FREEFORM || hdo->type == HWPDO_ADVANCED_ARC ) { if( prop->line_tstyle > 0 && o3tl::make_unsigned(prop->line_tstyle) < std::size(ArrowShape) && !ArrowShape[prop->line_tstyle].bMade ) { ArrowShape[prop->line_tstyle].bMade = true; mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, OUString::createFromAscii(ArrowShape[prop->line_tstyle].name)); if( prop->line_tstyle == 1 ) { mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 20 30"_ustr); mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m10 0-10 30h20z"_ustr); } else if( prop->line_tstyle == 2 ) { mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 1122 2243"_ustr); mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z"_ustr); } else if( prop->line_tstyle == 3 ) { mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 30 30"_ustr); mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m0 0h30v30h-30z"_ustr); } startEl(u"draw:marker"_ustr); mxList->clear(); endEl(u"draw:marker"_ustr); } if (prop->line_hstyle > 0 && o3tl::make_unsigned(prop->line_hstyle) < std::size(ArrowShape) && !ArrowShape[prop->line_hstyle].bMade) { ArrowShape[prop->line_hstyle].bMade = true; mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, OUString::createFromAscii(ArrowShape[prop->line_hstyle].name)); if( prop->line_hstyle == 1 ) { mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 20 30"_ustr); mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m10 0-10 30h20z"_ustr); } else if( prop->line_hstyle == 2 ) { mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 1122 2243"_ustr); mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z"_ustr); } else if( prop->line_hstyle == 3 ) { mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 20 20"_ustr); mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m0 0h20v20h-20z"_ustr); } startEl(u"draw:marker"_ustr); mxList->clear(); endEl(u"draw:marker"_ustr); } } if( hdo->type != HWPDO_LINE ) { if( prop->flag >> 18 & 0x01 ) { mxList->addAttribute( u"draw:name"_ustr, sXML_CDATA, "fillimage" + OUString::number(hdo->index)); EmPicture *emp = nullptr; if (prop->pictype && strlen(prop->szPatternFile) > 3) emp = hwpfile.GetEmPictureByName(prop->szPatternFile); if (!emp) { mxList->addAttribute( u"xlink:href"_ustr, sXML_CDATA, hstr2OUString(kstr2hstr( reinterpret_cast(urltounix(prop->szPatternFile).c_str())).c_str())); mxList->addAttribute( u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr); mxList->addAttribute( u"xlink:show"_ustr, sXML_CDATA, u"embed"_ustr); mxList->addAttribute( u"xlink:actuate"_ustr, sXML_CDATA, u"onLoad"_ustr); } startEl(u"draw:fill-image"_ustr); mxList->clear(); if (emp) { startEl(u"office:binary-data"_ustr); chars(base64_encode_string(emp->data.data(), emp->size)); endEl(u"office:binary-data"_ustr); } endEl(u"draw:fill-image"_ustr); } /* If there is a gradient, when a bitmap file is present, this is the first. */ else if( prop->flag >> 16 & 0x01 ) /* existence gradient */ { mxList->addAttribute( u"draw:name"_ustr, sXML_CDATA, "Grad" + OUString::number(hdo->index)); switch( prop->gstyle ) { case 1 : if( prop->center_y == 50 ) mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"axial"_ustr); else mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"linear"_ustr); break; case 2: case 3: mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"radial"_ustr); break; case 4: mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"square"_ustr); break; default: mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"linear"_ustr); break; } mxList->addAttribute( u"draw:cx"_ustr, sXML_CDATA, OUString::number(prop->center_x) + "%"); mxList->addAttribute( u"draw:cy"_ustr, sXML_CDATA, OUString::number(prop->center_y) + "%"); HWPInfo& hwpinfo = hwpfile.GetHWPInfo(); int default_color = 0xffffff; if( hwpinfo.back_info.isset ) { if( hwpinfo.back_info.color[0] > 0 || hwpinfo.back_info.color[1] > 0 || hwpinfo.back_info.color[2] > 0 ) default_color = hwpinfo.back_info.color[0] << 16 | hwpinfo.back_info.color[1] << 8 | hwpinfo.back_info.color[2]; } if( prop->fromcolor > 0xffffff ) prop->fromcolor = default_color; if( prop->tocolor > 0xffffff ) prop->tocolor = default_color; if( prop->gstyle == 1) { if( prop->center_y == 100 ) { mxList->addAttribute( u"draw:start-color"_ustr, sXML_CDATA, rgb2str( prop->tocolor )); mxList->addAttribute( u"draw:end-color"_ustr, sXML_CDATA, rgb2str( prop->fromcolor )); } else { mxList->addAttribute( u"draw:start-color"_ustr, sXML_CDATA, rgb2str( prop->fromcolor )); mxList->addAttribute( u"draw:end-color"_ustr, sXML_CDATA, rgb2str( prop->tocolor )); } } else { mxList->addAttribute( u"draw:start-color"_ustr, sXML_CDATA,rgb2str( prop->tocolor )); mxList->addAttribute( u"draw:end-color"_ustr, sXML_CDATA,rgb2str( prop->fromcolor )); } if( prop->angle > 0 && ( prop->gstyle == 1 || prop->gstyle == 4)) { auto normangle = prop->angle % 360; int angle = 1800 - normangle * 10; mxList->addAttribute( u"draw:angle"_ustr, sXML_CDATA, OUString::number(angle)); } startEl(u"draw:gradient"_ustr); mxList->clear(); endEl(u"draw:gradient"_ustr); } /* hatch */ else if( prop->pattern_type >> 24 & 0x01 ) { int type = prop->pattern_type & 0xffffff; mxList->addAttribute( u"draw:name"_ustr, sXML_CDATA, "Hatch" + OUString::number(hdo->index)); if( type < 4 ) mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"single"_ustr ); else mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"double"_ustr ); mxList->addAttribute( u"draw:color"_ustr, sXML_CDATA, rgb2str( static_cast(prop->pattern_color) )); mxList->addAttribute( u"draw:distance"_ustr, sXML_CDATA, u"0.12cm"_ustr); switch( type ) { case 0 : case 4 : mxList->addAttribute( u"draw:rotation"_ustr, sXML_CDATA, u"0"_ustr); break; case 1 : mxList->addAttribute( u"draw:rotation"_ustr, sXML_CDATA, u"900"_ustr); break; case 2 : mxList->addAttribute( u"draw:rotation"_ustr, sXML_CDATA, u"1350"_ustr); break; case 3 : case 5 : mxList->addAttribute( u"draw:rotation"_ustr, sXML_CDATA, u"450"_ustr); break; } startEl(u"draw:hatch"_ustr); mxList->clear(); endEl(u"draw:hatch"_ustr); } } hdo = hdo->next.get(); } } void HwpReader::makeStyles() { HWPStyle& hwpstyle = hwpfile.GetHWPStyle(); startEl(u"office:styles"_ustr); int i; for (i = 0; i < hwpfile.getFBoxStyleCount(); i++) { if( hwpfile.getFBoxStyle(i)->boxtype == 'D' ) { makeDrawMiscStyle(static_cast(hwpfile.getFBoxStyle(i)->cell) ); } } mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, u"Standard"_ustr); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr); mxList->addAttribute(u"style:class"_ustr, sXML_CDATA, u"text"_ustr); startEl(u"style:style"_ustr); mxList->clear(); mxList->addAttribute(u"fo:line-height"_ustr, sXML_CDATA, u"160%"_ustr); mxList->addAttribute(u"fo:text-align"_ustr, sXML_CDATA, u"justify"_ustr); startEl(u"style:properties"_ustr); mxList->clear(); startEl(u"style:tab-stops"_ustr); for( i = 1 ; i < 40 ; i++) { mxList->addAttribute(u"style:position"_ustr, sXML_CDATA, OUString::number( WTI(1000 * i)) + "inch"); startEl(u"style:tab-stop"_ustr); mxList->clear(); endEl(u"style:tab-stop"_ustr); } endEl(u"style:tab-stops"_ustr); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); for (int ii = 0; ii < hwpstyle.Num(); ii++) { unsigned char *stylename = reinterpret_cast(hwpstyle.GetName(ii)); mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, hstr2OUString(kstr2hstr(stylename).c_str())); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr); mxList->addAttribute(u"style:parent-style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"style:style"_ustr); mxList->clear(); parseCharShape(hwpstyle.GetCharShape(ii)); parseParaShape(hwpstyle.GetParaShape(ii)); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); } { mxList->addAttribute( u"style:name"_ustr, sXML_CDATA, u"Header"_ustr); mxList->addAttribute( u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr); mxList->addAttribute( u"style:parent-style-name"_ustr, sXML_CDATA, u"Standard"_ustr); mxList->addAttribute( u"style:class"_ustr, sXML_CDATA, u"extra"_ustr); startEl(u"style:style"_ustr); mxList->clear(); endEl(u"style:style"_ustr); } { mxList->addAttribute( u"style:name"_ustr, sXML_CDATA, u"Footer"_ustr); mxList->addAttribute( u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr); mxList->addAttribute( u"style:parent-style-name"_ustr, sXML_CDATA, u"Standard"_ustr); mxList->addAttribute( u"style:class"_ustr, sXML_CDATA, u"extra"_ustr); startEl(u"style:style"_ustr); mxList->clear(); endEl(u"style:style"_ustr); } if( hwpfile.linenumber > 0) { mxList->addAttribute( u"style:name"_ustr, sXML_CDATA, u"Horizontal Line"_ustr); mxList->addAttribute( u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr); mxList->addAttribute( u"style:parent-style-name"_ustr, sXML_CDATA, u"Standard"_ustr); mxList->addAttribute( u"style:class"_ustr, sXML_CDATA, u"html"_ustr); startEl(u"style:style"_ustr); mxList->clear(); mxList->addAttribute( u"fo:font-size"_ustr, sXML_CDATA, u"6pt"_ustr); mxList->addAttribute( u"fo:margin-top"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute( u"fo:margin-bottom"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute( u"style:border-line-width-bottom"_ustr, sXML_CDATA, u"0.02cm 0.035cm 0.002cm"_ustr); mxList->addAttribute( u"fo:padding"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute( u"fo:border-bottom"_ustr, sXML_CDATA, u"0.039cm double #808080"_ustr); mxList->addAttribute( u"text:number-lines"_ustr, sXML_CDATA, u"false"_ustr); mxList->addAttribute( u"text:line-number"_ustr, sXML_CDATA, u"0"_ustr); mxList->addAttribute(u"fo:line-height"_ustr, sXML_CDATA, u"100%"_ustr); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); } HWPInfo& hwpinfo = hwpfile.GetHWPInfo(); mxList->addAttribute(u"text:num-suffix"_ustr, sXML_CDATA, u")"_ustr); mxList->addAttribute(u"text:num-format"_ustr, sXML_CDATA, u"1"_ustr); if( hwpinfo.beginfnnum != 1) mxList->addAttribute(u"text:offset"_ustr, sXML_CDATA, OUString::number(hwpinfo.beginfnnum - 1)); startEl(u"text:footnotes-configuration"_ustr); mxList->clear(); endEl(u"text:footnotes-configuration"_ustr); endEl(u"office:styles"_ustr); } /** * parse automatic styles from hwpfile * Define a style that is automatically reflected. For example, defining styles of each paragraph, tables, header, and etc,. at here. In Body, use the defined style. * 1. supports for the styles of paragraph, text, fbox, and page. */ void HwpReader::makeAutoStyles() { int i; startEl(u"office:automatic-styles"_ustr); for (i = 0; i < hwpfile.getParaShapeCount(); i++) makePStyle(hwpfile.getParaShape(i)); for (i = 0; i < hwpfile.getCharShapeCount(); i++) makeTStyle(hwpfile.getCharShape(i)); for( i = 0 ; i < hwpfile.getTableCount(); i++) makeTableStyle(hwpfile.getTable(i)); for (i = 0; i < hwpfile.getFBoxStyleCount(); i++) { if( hwpfile.getFBoxStyle(i)->boxtype == 'D' ) makeDrawStyle(static_cast(hwpfile.getFBoxStyle(i)->cell), hwpfile.getFBoxStyle(i)); else makeFStyle(hwpfile.getFBoxStyle(i)); } bool bIsLeft = false, bIsMiddle = false, bIsRight = false; for( i = 0 ; i < hwpfile.getPageNumberCount() ; i++ ) { ShowPageNum *pn = hwpfile.getPageNumber(i); if( pn->where == 7 || pn->where == 8 ) { bIsLeft = true; bIsRight = true; } else if( pn->where == 1 || pn->where == 4 ) { bIsLeft = true; } else if( pn->where == 2 || pn->where == 5 ) { bIsMiddle = true; } else if( pn->where == 3 || pn->where == 6 ) { bIsRight = true; } } for( i = 1; i <= 3 ; i++ ) { if( i == 1 && !bIsLeft ) continue; if( i == 2 && !bIsMiddle ) continue; if( i == 3 && !bIsRight ) continue; mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "PNPara" + OUString::number(i)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr); mxList->addAttribute(u"style:parent-style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"style:style"_ustr); mxList->clear(); if( i == 1 ) mxList->addAttribute(u"fo:text-align"_ustr, sXML_CDATA, u"start"_ustr); else if ( i == 2 ) mxList->addAttribute(u"fo:text-align"_ustr, sXML_CDATA, u"center"_ustr); else if ( i == 3 ) mxList->addAttribute(u"fo:text-align"_ustr, sXML_CDATA, u"end"_ustr); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "PNBox" + OUString::number(i)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr); startEl(u"style:style"_ustr); mxList->clear(); mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"run-through"_ustr); mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"from-top"_ustr); mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"paragraph"_ustr); if( i == 1 ) mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"left"_ustr); else if ( i == 2 ) mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"center"_ustr); else if ( i == 3 ) mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"right"_ustr); mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr); mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"stylefamily"_ustr, sXML_CDATA, u"graphics"_ustr); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); } for (i = 0; i < hwpfile.getDateFormatCount(); i++) makeDateFormat(hwpfile.getDateCode(i)); makePageStyle(); endEl(u"office:automatic-styles"_ustr); } namespace { struct PageSetting { PageSetting() { header = nullptr; header_odd = nullptr; header_even = nullptr; footer = nullptr; footer_odd = nullptr; footer_even = nullptr; pagenumber=nullptr; bIsSet = false; } HeaderFooter *header ; HeaderFooter *header_odd ; HeaderFooter *header_even ; HeaderFooter *footer ; HeaderFooter *footer_odd ; HeaderFooter *footer_even ; ShowPageNum *pagenumber; bool bIsSet; }; } void HwpReader::makeMasterStyles() { startEl(u"office:master-styles"_ustr); int i; int nMax = hwpfile.getMaxSettedPage(); std::vector aSet(nMax + 1); for( i = 0 ; i < hwpfile.getPageNumberCount() ; i++ ) { ShowPageNum *pn = hwpfile.getPageNumber(i); aSet[pn->m_nPageNumber].pagenumber = pn; aSet[pn->m_nPageNumber].bIsSet = true; } for( i = 0 ; i < hwpfile.getHeaderFooterCount() ; i++ ) { HeaderFooter* hf = hwpfile.getHeaderFooter(i); aSet[hf->m_nPageNumber].bIsSet = true; if( hf->type == 0 ) // header { switch( hf->where ) { case 0 : aSet[hf->m_nPageNumber].header = hf; aSet[hf->m_nPageNumber].header_even = nullptr; aSet[hf->m_nPageNumber].header_odd = nullptr; break; case 1: aSet[hf->m_nPageNumber].header_even = hf; if( aSet[hf->m_nPageNumber].header ) { aSet[hf->m_nPageNumber].header_odd = aSet[hf->m_nPageNumber].header; aSet[hf->m_nPageNumber].header = nullptr; } break; case 2: aSet[hf->m_nPageNumber].header_odd = hf; if( aSet[hf->m_nPageNumber].header ) { aSet[hf->m_nPageNumber].header_even = aSet[hf->m_nPageNumber].header; aSet[hf->m_nPageNumber].header = nullptr; } break; } } else // footer { switch( hf->where ) { case 0 : aSet[hf->m_nPageNumber].footer = hf; aSet[hf->m_nPageNumber].footer_even = nullptr; aSet[hf->m_nPageNumber].footer_odd = nullptr; break; case 1: aSet[hf->m_nPageNumber].footer_even = hf; if( aSet[hf->m_nPageNumber].footer ) { aSet[hf->m_nPageNumber].footer_odd = aSet[hf->m_nPageNumber].footer; aSet[hf->m_nPageNumber].footer = nullptr; } break; case 2: aSet[hf->m_nPageNumber].footer_odd = hf; if( aSet[hf->m_nPageNumber].footer ) { aSet[hf->m_nPageNumber].footer_even = aSet[hf->m_nPageNumber].footer; aSet[hf->m_nPageNumber].footer = nullptr; } break; } } } PageSetting *pPrevSet = nullptr; PageSetting *pPage = nullptr; if (nMax > 512 && comphelper::IsFuzzing()) { SAL_WARN("filter.hwp", "too many pages: " << nMax << " clip to " << 512); nMax = 512; } for( i = 1; i <= nMax ; i++ ) { if( i == 1 ) mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, u"Standard"_ustr); else mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "p" + OUString::number(i)); mxList->addAttribute(u"style:page-master-name"_ustr, sXML_CDATA, "pm" + OUString::number(hwpfile.GetPageMasterNum(i))); if( i < nMax ) mxList->addAttribute(u"style:next-style-name"_ustr, sXML_CDATA, "p" + OUString::number(i + 1)); mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "master" + OUString::number(i)); startEl(u"style:master-page"_ustr); mxList->clear(); if( aSet[i].bIsSet ) /* If you've changed the current setting */ { if( !aSet[i].pagenumber ){ if( pPrevSet && pPrevSet->pagenumber ) aSet[i].pagenumber = pPrevSet->pagenumber; } if( aSet[i].pagenumber ) { if( aSet[i].pagenumber->where == 7 && aSet[i].header ) { aSet[i].header_even = aSet[i].header; aSet[i].header_odd = aSet[i].header; aSet[i].header = nullptr; } if( aSet[i].pagenumber->where == 8 && aSet[i].footer ) { aSet[i].footer_even = aSet[i].footer; aSet[i].footer_odd = aSet[i].footer; aSet[i].footer = nullptr; } } if( !aSet[i].header_even && pPrevSet && pPrevSet->header_even ) { aSet[i].header_even = pPrevSet->header_even; } if( !aSet[i].header_odd && pPrevSet && pPrevSet->header_odd ) { aSet[i].header_odd = pPrevSet->header_odd; } if( !aSet[i].footer_even && pPrevSet && pPrevSet->footer_even ) { aSet[i].footer_even = pPrevSet->footer_even; } if( !aSet[i].footer_odd && pPrevSet && pPrevSet->footer_odd ) { aSet[i].footer_odd = pPrevSet->footer_odd; } pPage = &aSet[i]; pPrevSet = &aSet[i]; } else if( pPrevSet ) /* If the previous setting exists */ { pPage = pPrevSet; } else /* If the previous settings doesn't exist, set to the default settings */ { startEl(u"style:header"_ustr); mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"text:p"_ustr); mxList->clear(); endEl(u"text:p"_ustr); endEl(u"style:header"_ustr); startEl(u"style:footer"_ustr); mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"text:p"_ustr); mxList->clear(); endEl(u"text:p"_ustr); endEl(u"style:footer"_ustr); endEl(u"style:master-page"_ustr); continue; } // header if( pPage->header ) { startEl(u"style:header"_ustr); if( pPage->pagenumber && pPage->pagenumber->where < 4 ) { d->bInHeader = true; d->pPn = pPage->pagenumber; } if (!pPage->header->plist.empty()) parsePara(pPage->header->plist.front().get()); d->bInHeader = false; d->pPn = nullptr; endEl(u"style:header"_ustr); } if( pPage->header_even ) { startEl(u"style:header"_ustr); if( pPage->pagenumber && ( pPage->pagenumber->where < 4 || pPage->pagenumber->where == 7 ) ) { d->bInHeader = true; d->pPn = pPage->pagenumber; d->nPnPos = 3; } if (!pPage->header_even->plist.empty()) parsePara(pPage->header_even->plist.front().get()); d->bInHeader = false; d->pPn = nullptr; d->nPnPos = 0; endEl(u"style:header"_ustr); } /* Will be the default. */ else if (pPage->header_odd) { startEl(u"style:header"_ustr); mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"text:p"_ustr); mxList->clear(); if( pPage->pagenumber && ( pPage->pagenumber->where < 4 || pPage->pagenumber->where == 7 ) ) { d->pPn = pPage->pagenumber; d->nPnPos = 3; makeShowPageNum(); d->pPn = nullptr; d->nPnPos = 0; } endEl(u"text:p"_ustr); endEl(u"style:header"_ustr); } if( pPage->header_odd ) { startEl(u"style:header-left"_ustr); if( pPage->pagenumber && ( pPage->pagenumber->where < 4 || pPage->pagenumber->where == 7 ) ) { d->bInHeader = true; d->nPnPos = 1; d->pPn = pPage->pagenumber; } if (!pPage->header_odd->plist.empty()) parsePara(pPage->header_odd->plist.front().get()); d->bInHeader = false; d->pPn = nullptr; d->nPnPos = 0; endEl(u"style:header-left"_ustr); } /* Will be the default. */ else if (pPage->header_even) { startEl(u"style:header-left"_ustr); mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"text:p"_ustr); mxList->clear(); if( pPage->pagenumber && ( pPage->pagenumber->where < 4 || pPage->pagenumber->where == 7 ) ) { d->pPn = pPage->pagenumber; d->nPnPos = 1; makeShowPageNum(); d->pPn = nullptr; d->nPnPos = 0; } endEl(u"text:p"_ustr); endEl(u"style:header-left"_ustr); } if( !pPage->header && !pPage->header_even && !pPage->header_odd ) { startEl(u"style:header"_ustr); mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"text:p"_ustr); mxList->clear(); if( pPage->pagenumber && (pPage->pagenumber->where < 4 || pPage->pagenumber->where == 7 ) ) { d->pPn = pPage->pagenumber; makeShowPageNum(); d->pPn = nullptr; } endEl(u"text:p"_ustr); endEl(u"style:header"_ustr); } // footer if( pPage->footer ) { startEl(u"style:footer"_ustr); if( pPage->pagenumber && pPage->pagenumber->where >= 4 && pPage->pagenumber->where != 7 ) { d->bInHeader = true; d->pPn = pPage->pagenumber; } if (!pPage->footer->plist.empty()) parsePara(pPage->footer->plist.front().get()); d->bInHeader = false; d->pPn = nullptr; endEl(u"style:footer"_ustr); } if( pPage->footer_even ) { startEl(u"style:footer"_ustr); if( pPage->pagenumber && pPage->pagenumber->where >= 4 && pPage->pagenumber->where != 7 ) { d->bInHeader = true; d->pPn = pPage->pagenumber; d->nPnPos = 3; } if (!pPage->footer_even->plist.empty()) parsePara(pPage->footer_even->plist.front().get()); d->bInHeader = false; d->pPn = nullptr; d->nPnPos = 0; endEl(u"style:footer"_ustr); } /* Will be the default. */ else if (pPage->footer_odd) { startEl(u"style:footer"_ustr); mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"text:p"_ustr); mxList->clear(); if( pPage->pagenumber && pPage->pagenumber->where >= 4 && pPage->pagenumber->where != 7 ) { d->pPn = pPage->pagenumber; d->nPnPos = 3; makeShowPageNum(); d->pPn = nullptr; d->nPnPos = 0; } endEl(u"text:p"_ustr); endEl(u"style:footer"_ustr); } if( pPage->footer_odd ) { startEl(u"style:footer-left"_ustr); if( pPage->pagenumber && pPage->pagenumber->where >= 4 && pPage->pagenumber->where != 7 ) { d->bInHeader = true; d->pPn = pPage->pagenumber; d->nPnPos = 1; } if (!pPage->footer_odd->plist.empty()) parsePara(pPage->footer_odd->plist.front().get()); d->bInHeader = false; d->pPn = nullptr; d->nPnPos = 0; endEl(u"style:footer-left"_ustr); } /* Will be the default. */ else if (pPage->footer_even) { startEl(u"style:footer-left"_ustr); mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"text:p"_ustr); mxList->clear(); if( pPage->pagenumber && pPage->pagenumber->where >= 4 && pPage->pagenumber->where != 7 ) { d->pPn = pPage->pagenumber; d->nPnPos = 1; makeShowPageNum(); d->pPn = nullptr; d->nPnPos = 0; } endEl(u"text:p"_ustr); endEl(u"style:footer-left"_ustr); } if( !pPage->footer && !pPage->footer_even && !pPage->footer_odd ) { startEl(u"style:footer"_ustr); mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"text:p"_ustr); mxList->clear(); if( pPage->pagenumber && pPage->pagenumber->where >= 4 && pPage->pagenumber->where != 7 ) { d->pPn = pPage->pagenumber; makeShowPageNum(); d->pPn = nullptr; } endEl(u"text:p"_ustr); endEl(u"style:footer"_ustr); } endEl(u"style:master-page"_ustr); } endEl(u"office:master-styles"_ustr); } /** * Create the properties for text styles. * 1. fo:font-size, fo:font-family, fo:letter-spacing, fo:color, * style:text-background-color, fo:font-style, fo:font-weight, * style:text-underline,style:text-outline,fo:text-shadow,style:text-position * Support them. */ void HwpReader::parseCharShape(CharShape const * cshape) { HWPFont& hwpfont = hwpfile.GetHWPFont(); mxList->addAttribute(u"fo:font-size"_ustr, sXML_CDATA, OUString::number(cshape->size / 25) + "pt"); mxList->addAttribute(u"style:font-size-asian"_ustr, sXML_CDATA, OUString::number(cshape->size / 25) + "pt"); ::std::string const tmp = hstr2ksstr(kstr2hstr( reinterpret_cast(hwpfont.GetFontName(0, cshape->font))).c_str()); double fRatio = 1.0; int size = getRepFamilyName(tmp.c_str(), d->buf, fRatio); mxList->addAttribute(u"fo:font-family"_ustr, sXML_CDATA, OUString(d->buf, size, RTL_TEXTENCODING_EUC_KR)); mxList->addAttribute(u"style:font-family-asian"_ustr, sXML_CDATA, OUString(d->buf, size, RTL_TEXTENCODING_EUC_KR)); mxList->addAttribute(u"style:text-scale"_ustr, sXML_CDATA, OUString::number(static_cast(cshape->ratio * fRatio)) + "%"); double sspace = (cshape->size / 25) * cshape->space / 100.; if (sspace != 0.) { mxList->addAttribute(u"fo:letter-spacing"_ustr, sXML_CDATA, OUString::number(sspace) + "pt"); } if (cshape->color[1] != 0) mxList->addAttribute(u"fo:color"_ustr, sXML_CDATA, hcolor2str(cshape->color[1], 100, true)); if (cshape->shade != 0) mxList->addAttribute(u"style:text-background-color"_ustr, sXML_CDATA, hcolor2str(cshape->color[0], cshape->shade)); if (cshape->attr & 0x01) { mxList->addAttribute(u"fo:font-style"_ustr, sXML_CDATA, u"italic"_ustr); mxList->addAttribute(u"style:font-style-asian"_ustr, sXML_CDATA, u"italic"_ustr); } else{ mxList->addAttribute(u"fo:font-style"_ustr, sXML_CDATA, u"normal"_ustr); mxList->addAttribute(u"style:font-style-asian"_ustr, sXML_CDATA, u"normal"_ustr); } if (cshape->attr >> 1 & 0x01) { mxList->addAttribute(u"fo:font-weight"_ustr, sXML_CDATA, u"bold"_ustr); mxList->addAttribute(u"style:font-weight-asian"_ustr, sXML_CDATA, u"bold"_ustr); } else{ mxList->addAttribute(u"fo:font-weight"_ustr, sXML_CDATA, u"normal"_ustr); mxList->addAttribute(u"style:font-weight-asian"_ustr, sXML_CDATA, u"normal"_ustr); } if (cshape->attr >> 2 & 0x01) mxList->addAttribute(u"style:text-underline"_ustr, sXML_CDATA, u"single"_ustr); if (cshape->attr >> 3 & 0x01) mxList->addAttribute(u"style:text-outline"_ustr, sXML_CDATA, u"true"_ustr); if (cshape->attr >> 4 & 0x01) mxList->addAttribute(u"fo:text-shadow"_ustr, sXML_CDATA, u"1pt 1pt"_ustr); if (cshape->attr >> 5 & 0x01) mxList->addAttribute(u"style:text-position"_ustr, sXML_CDATA, u"super 58%"_ustr); if (cshape->attr >> 6 & 0x01) mxList->addAttribute(u"style:text-position"_ustr, sXML_CDATA, u"sub 58%"_ustr); } /** * Create the properties that correspond to the real Paragraph. * 1. fo:margin-left,fo:margin-right,fo:margin-top, fo:margin-bottom, * fo:text-indent, fo:line-height, fo:text-align, fo:border * are implemented. * TODO: Tab Settings => set values of properties only which doesn't have the default value */ void HwpReader::parseParaShape(ParaShape const * pshape) { if (pshape->left_margin != 0) mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA, OUString::number (WTI(pshape->left_margin )) + "inch"); if (pshape->right_margin != 0) mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA, OUString::number (WTI(pshape->right_margin)) + "inch"); if (pshape->pspacing_prev != 0) mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA, OUString::number (WTI(pshape->pspacing_prev)) + "inch"); if (pshape->pspacing_next != 0) mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA, OUString::number (WTI(pshape->pspacing_next)) + "inch"); if (pshape->indent != 0) mxList->addAttribute(u"fo:text-indent"_ustr, sXML_CDATA, OUString::number (WTI(pshape->indent)) + "inch"); if (pshape->lspacing != 0) mxList->addAttribute(u"fo:line-height"_ustr, sXML_CDATA, OUString::number(pshape->lspacing) + "%"); const char* align = nullptr; switch (static_cast(pshape->arrange_type)) { case 1: align = "start"; break; case 2: align = "end"; break; case 3: align = "center"; break; case 4: case 5: case 6: align = "justify"; break; } if (align) mxList->addAttribute(u"fo:text-align"_ustr, sXML_CDATA, OUString::createFromAscii(align)); if (pshape->outline) mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA, u"0.002cm solid #000000"_ustr); if( pshape->shade > 0 ) { mxList->addAttribute(u"fo:background-color"_ustr, sXML_CDATA, hcolor2str(0, pshape->shade)); } if( pshape->pagebreak & 0x02 || pshape->pagebreak & 0x04) mxList->addAttribute(u"fo:break-before"_ustr, sXML_CDATA, u"page"_ustr); else if( pshape->pagebreak & 0x01 ) mxList->addAttribute(u"fo:break-before"_ustr, sXML_CDATA, u"column"_ustr); } /** * Make the style of the Paragraph. */ void HwpReader::makePStyle(ParaShape const * pshape) { int nscount = pshape->tabs[MAXTABS -1].type; mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "P" + OUString::number(pshape->index)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr); startEl(u"style:style"_ustr); mxList->clear(); parseParaShape(pshape); if (pshape->cshape) parseCharShape(pshape->cshape.get()); startEl(u"style:properties"_ustr); mxList->clear(); if( nscount ) { unsigned char tf = 0; startEl(u"style:tab-stops"_ustr); int tab_margin = pshape->left_margin + pshape->indent; if( tab_margin < 0 ) tab_margin = 0; for( int i = 0 ; i < MAXTABS -1 ; i++) { if( i > 0 && pshape->tabs[i].position == 0. ) break; if( pshape->tabs[i].position <= tab_margin ) continue; mxList->addAttribute(u"style:position"_ustr, sXML_CDATA, OUString::number(WTMM(pshape->tabs[i].position - tab_margin )) + "mm"); if( pshape->tabs[i].type ) { tf = 1; switch(pshape->tabs[i].type) { case 1 : mxList->addAttribute(u"style:type"_ustr, sXML_CDATA, u"right"_ustr); break; case 2: mxList->addAttribute(u"style:type"_ustr, sXML_CDATA, u"center"_ustr); break; case 3: mxList->addAttribute(u"style:type"_ustr, sXML_CDATA, u"char"_ustr); mxList->addAttribute(u"style:char"_ustr, sXML_CDATA, u"."_ustr); break; } } if( pshape->tabs[i].dot_continue ) { tf = 1; mxList->addAttribute(u"style:leader-char"_ustr, sXML_CDATA, u"."_ustr); } startEl(u"style:tab-stop"_ustr); mxList->clear(); endEl(u"style:tab-stop"_ustr); if( (pshape->tabs[i].position != 1000 * i ) || tf ) { if( !--nscount ) break; } } endEl(u"style:tab-stops"_ustr); } endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); } /** * Create a style for the page. This includes the header/footer, footnote and more. * TODO: fo: background-color (no information) */ void HwpReader::makePageStyle() { HWPInfo& hwpinfo = hwpfile.GetHWPInfo(); int pmCount = hwpfile.getColumnCount(); if (pmCount > 512 && comphelper::IsFuzzing()) { SAL_WARN("filter.hwp", "too many pages: " << pmCount << " clip to " << 512); pmCount = 512; } for( int i = 0 ; i < pmCount ; i++ ){ mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "pm" + OUString::number(i + 1)); startEl(u"style:page-master"_ustr); mxList->clear(); switch( hwpinfo.paper.paper_kind ) { case 3: // A4 if( hwpinfo.paper.paper_direction ) { mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"210mm"_ustr); mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"297mm"_ustr); } else { mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"210mm"_ustr); mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"297mm"_ustr); } break; case 4: // 80 column if( hwpinfo.paper.paper_direction ) { mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"8.5inch"_ustr); mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"11inch"_ustr); } else { mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"8.5inch"_ustr); mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"11inch"_ustr); } break; case 5: // B5 if( hwpinfo.paper.paper_direction ) { mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"176mm"_ustr); mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"250mm"_ustr); } else { mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"176mm"_ustr); mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"250mm"_ustr); } break; case 6: // B4 if( hwpinfo.paper.paper_direction ) { mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"250mm"_ustr); mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"353mm"_ustr); } else { mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"250mm"_ustr); mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"353mm"_ustr); } break; case 7: if( hwpinfo.paper.paper_direction ) { mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"8.5inch"_ustr); mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"14inch"_ustr); } else { mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"8.5inch"_ustr); mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"14inch"_ustr); } break; case 8: if( hwpinfo.paper.paper_direction ) { mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"297mm"_ustr); mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"420mm"_ustr); } else { mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"297mm"_ustr); mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"420mm"_ustr); } break; case 0: case 1: case 2: default: if( hwpinfo.paper.paper_direction ) { mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.paper_height)) + "inch"); mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.paper_width)) + "inch"); } else { mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.paper_width)) + "inch"); mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.paper_height)) + "inch"); } break; } mxList->addAttribute(u"style:print-orientation"_ustr,sXML_CDATA, OUString::createFromAscii(hwpinfo.paper.paper_direction ? "landscape" : "portrait")); if( hwpinfo.beginpagenum != 1) mxList->addAttribute(u"style:first-page-number"_ustr,sXML_CDATA, OUString::number(hwpinfo.beginpagenum)); if( hwpinfo.borderline ){ mxList->addAttribute(u"fo:margin-left"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.left_margin - hwpinfo.bordermargin[0] + hwpinfo.paper.gutter_length)) + "inch"); mxList->addAttribute(u"fo:margin-right"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.right_margin - hwpinfo.bordermargin[1])) + "inch"); mxList->addAttribute(u"fo:margin-top"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.top_margin - hwpinfo.bordermargin[2])) + "inch"); mxList->addAttribute(u"fo:margin-bottom"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.bottom_margin - hwpinfo.bordermargin[3])) + "inch"); } else{ mxList->addAttribute(u"fo:margin-left"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.left_margin + hwpinfo.paper.gutter_length)) + "inch"); mxList->addAttribute(u"fo:margin-right"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.right_margin)) + "inch"); mxList->addAttribute(u"fo:margin-top"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.top_margin)) + "inch"); mxList->addAttribute(u"fo:margin-bottom"_ustr,sXML_CDATA, OUString::number(WTI(hwpinfo.paper.bottom_margin)) + "inch"); } switch( hwpinfo.borderline ) { case 1: mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 3: mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.002cm dotted #000000"_ustr); break; case 2: mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: mxList->addAttribute(u"style:border-line-width"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } mxList->addAttribute(u"fo:padding-left"_ustr, sXML_CDATA, OUString::number(WTI(hwpinfo.bordermargin[0])) + "inch"); mxList->addAttribute(u"fo:padding-right"_ustr, sXML_CDATA, OUString::number(WTI(hwpinfo.bordermargin[1])) + "inch"); mxList->addAttribute(u"fo:padding-top"_ustr, sXML_CDATA, OUString::number(WTI(hwpinfo.bordermargin[2])) + "inch"); mxList->addAttribute(u"fo:padding-bottom"_ustr, sXML_CDATA, OUString::number(WTI(hwpinfo.bordermargin[3])) + "inch"); /* background color */ if( hwpinfo.back_info.isset ) { if( hwpinfo.back_info.color[0] > 0 || hwpinfo.back_info.color[1] > 0 || hwpinfo.back_info.color[2] > 0 ){ mxList->addAttribute(u"fo:background-color"_ustr, sXML_CDATA, rgb2str(hwpinfo.back_info.color[0], hwpinfo.back_info.color[1], hwpinfo.back_info.color[2])); } } startEl(u"style:properties"_ustr); mxList->clear(); /* background image */ if( hwpinfo.back_info.isset && hwpinfo.back_info.type > 0 ) { if( hwpinfo.back_info.type == 1 ){ #ifdef _WIN32 mxList->addAttribute("xlink:href", sXML_CDATA, hstr2OUString(kstr2hstr(reinterpret_cast(urltowin(hwpinfo.back_info.filename).c_str())).c_str())); #else mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA, hstr2OUString(kstr2hstr( reinterpret_cast(urltounix(hwpinfo.back_info.filename).c_str())).c_str())); #endif mxList->addAttribute(u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr); mxList->addAttribute(u"xlink:actuate"_ustr, sXML_CDATA, u"onLoad"_ustr); } if( hwpinfo.back_info.flag >= 2) mxList->addAttribute(u"style:repeat"_ustr, sXML_CDATA, u"stretch"_ustr); else if( hwpinfo.back_info.flag == 1 ){ mxList->addAttribute(u"style:repeat"_ustr, sXML_CDATA, u"no-repeat"_ustr); mxList->addAttribute(u"style:position"_ustr, sXML_CDATA, u"center"_ustr); } startEl(u"style:background-image"_ustr); if( hwpinfo.back_info.type == 2 ){ startEl(u"office:binary-data"_ustr); mxList->clear(); chars(base64_encode_string(reinterpret_cast(hwpinfo.back_info.data.data()), hwpinfo.back_info.size)); endEl(u"office:binary-data"_ustr); } endEl(u"style:background-image"_ustr); } makeColumns( hwpfile.GetColumnDef(i) ); endEl(u"style:properties"_ustr); /* header style */ startEl(u"style:header-style"_ustr); mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA, OUString::number(WTI(hwpinfo.paper.header_length)) + "inch"); mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA, u"0mm"_ustr); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:header-style"_ustr); /* footer style */ startEl(u"style:footer-style"_ustr); mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA, OUString::number(WTI(hwpinfo.paper.footer_length)) + "inch"); mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA, u"0mm"_ustr); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:footer-style"_ustr); /* Footnote style */ startEl(u"style:page-layout-properties"_ustr); mxList->addAttribute(u"style:distance-before-sep"_ustr, sXML_CDATA, OUString::number(WTI(hwpinfo.splinetext)) + "inch"); mxList->addAttribute(u"style:distance-after-sep"_ustr, sXML_CDATA, OUString::number(WTI(hwpinfo.splinefn)) + "inch"); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); if ( hwpinfo.fnlinetype == 2 ) mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"15cm"_ustr); else if ( hwpinfo.fnlinetype == 1) mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"2cm"_ustr); else if ( hwpinfo.fnlinetype == 3) mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"0cm"_ustr); else mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"5cm"_ustr); startEl(u"style:footnote-sep"_ustr); mxList->clear(); endEl(u"style:footnote-sep"_ustr); endEl(u"style:page-layout-properties"_ustr); endEl(u"style:page-master"_ustr); } } void HwpReader::makeColumns(ColumnDef const *coldef) { if( !coldef ) return; mxList->addAttribute(u"fo:column-count"_ustr, sXML_CDATA, OUString::number(coldef->ncols)); startEl(u"style:columns"_ustr); mxList->clear(); if( coldef->separator != 0 ) { switch( coldef->separator ) { case 1: /* thin line */ mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"0.02mm"_ustr); [[fallthrough]]; case 3: /* dotted line */ mxList->addAttribute(u"style:style"_ustr, sXML_CDATA, u"dotted"_ustr); mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"0.02mm"_ustr); break; case 2: /* thick line */ case 4: /* double line */ mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"0.35mm"_ustr); break; case 0: /* None */ default: mxList->addAttribute(u"style:style"_ustr, sXML_CDATA, u"none"_ustr); break; } startEl(u"style:column-sep"_ustr); mxList->clear(); endEl(u"style:column-sep"_ustr); } double spacing = WTI(coldef->spacing)/ 2. ; for(int ii = 0 ; ii < coldef->ncols ; ii++) { if( ii == 0 ) mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA, u"0mm"_ustr); else mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA, OUString::number( spacing) + "inch"); if( ii == ( coldef->ncols -1) ) mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA,u"0mm"_ustr); else mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA, OUString::number( spacing) + "inch"); startEl(u"style:column"_ustr); mxList->clear(); endEl(u"style:column"_ustr); } endEl(u"style:columns"_ustr); } void HwpReader::makeTStyle(CharShape const * cshape) { mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "T" + OUString::number(cshape->index)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"text"_ustr); startEl(u"style:style"_ustr); mxList->clear(); parseCharShape(cshape); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); } void HwpReader::makeTableStyle(Table *tbl) { // table TxtBox *hbox = tbl->box; mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA,u"table"_ustr); startEl(u"style:style"_ustr); mxList->clear(); mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, OUString::number(WTMM(hbox->box_xs)) + "mm"); mxList->addAttribute(u"table:align"_ustr, sXML_CDATA,u"left"_ustr); mxList->addAttribute(u"fo:keep-with-next"_ustr, sXML_CDATA,u"false"_ustr); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); // column for (size_t i = 0 ; i < tbl->columns.nCount -1 ; i++) { mxList->addAttribute( u"style:name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum) + "." + OUStringChar(static_cast('A'+i))); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA,u"table-column"_ustr); startEl(u"style:style"_ustr); mxList->clear(); mxList->addAttribute(u"style:column-width"_ustr, sXML_CDATA, OUString::number(WTMM(tbl->columns.data[i+1] - tbl->columns.data[i])) + "mm"); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); } // row for (size_t i = 0 ; i < tbl->rows.nCount -1 ; i++) { mxList->addAttribute( u"style:name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum) + ".row" + OUString::number(i + 1)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA,u"table-row"_ustr); startEl(u"style:style"_ustr); mxList->clear(); mxList->addAttribute(u"style:row-height"_ustr, sXML_CDATA, OUString::number(WTMM(tbl->rows.data[i+1] - tbl->rows.data[i])) + "mm"); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); } // cell for (auto const& tcell : tbl->cells) { mxList->addAttribute( u"style:name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum) + "." + OUStringChar(char('A'+ tcell->nColumnIndex)) + OUString::number(tcell->nRowIndex +1)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA,u"table-cell"_ustr); startEl(u"style:style"_ustr); mxList->clear(); Cell *cl = tcell->pCell; if( cl->ver_align == 1 ) mxList->addAttribute(u"fo:vertical-align"_ustr, sXML_CDATA,u"middle"_ustr); if(cl->linetype[2] == cl->linetype[3] && cl->linetype[2] == cl->linetype[0] && cl->linetype[2] == cl->linetype[1]) { switch( cl->linetype[2] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } } else { switch( cl->linetype[0] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-left"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } switch( cl->linetype[1] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-right"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } switch( cl->linetype[2] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-top"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } switch( cl->linetype[3] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-bottom"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } } if(cl->shade != 0) mxList->addAttribute(u"fo:background-color"_ustr, sXML_CDATA, hcolor2str(sal::static_int_cast(cl->color), sal::static_int_cast(cl->shade))); startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); } } void HwpReader::makeDrawStyle( HWPDrawingObject * hdo, FBoxStyle * fstyle) { while( hdo ) { mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "Draw" + OUString::number(hdo->index)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr); startEl(u"style:style"_ustr); mxList->clear(); switch (fstyle->txtflow) { case 0: break; case 1: mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"run-through"_ustr); break; case 2: mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"dynamic"_ustr); break; } tools::Long color; // invisible line if( hdo->property.line_color > 0xffffff ) { mxList->addAttribute(u"draw:stroke"_ustr, sXML_CDATA, u"none"_ustr ); } else { if( hdo->property.line_pstyle == 0 ) mxList->addAttribute(u"draw:stroke"_ustr, sXML_CDATA, u"solid"_ustr ); else if( hdo->property.line_pstyle < 5 ) { mxList->addAttribute(u"draw:stroke"_ustr, sXML_CDATA, u"dash"_ustr ); mxList->addAttribute(u"draw:stroke-dash"_ustr, sXML_CDATA, "LineType" + OUString::number(hdo->index)); } mxList->addAttribute(u"svg:stroke-width"_ustr, sXML_CDATA, OUString::number( WTMM(hdo->property.line_width)) + "mm"); mxList->addAttribute(u"svg:stroke-color"_ustr, sXML_CDATA, rgb2str(static_cast(hdo->property.line_color))); } if( hdo->type == HWPDO_LINE || hdo->type == HWPDO_ARC || hdo->type == HWPDO_FREEFORM || hdo->type == HWPDO_ADVANCED_ARC ) { if( hdo->property.line_tstyle > 0 && o3tl::make_unsigned(hdo->property.line_tstyle) < std::size(ArrowShape) ) { mxList->addAttribute(u"draw:marker-start"_ustr, sXML_CDATA, OUString::createFromAscii(ArrowShape[hdo->property.line_tstyle].name) ); if( hdo->property.line_width > 100 ) mxList->addAttribute(u"draw:marker-start-width"_ustr, sXML_CDATA, OUString::number( WTMM(hdo->property.line_width * 3.0)) + "mm"); else if( hdo->property.line_width > 80 ) mxList->addAttribute(u"draw:marker-start-width"_ustr, sXML_CDATA, OUString::number( WTMM(hdo->property.line_width * 4.0)) + "mm"); else if( hdo->property.line_width > 60 ) mxList->addAttribute(u"draw:marker-start-width"_ustr, sXML_CDATA, OUString::number( WTMM(hdo->property.line_width * 5.0)) + "mm"); else if( hdo->property.line_width > 40 ) mxList->addAttribute(u"draw:marker-start-width"_ustr, sXML_CDATA, OUString::number( WTMM(hdo->property.line_width * 6.0)) + "mm"); else mxList->addAttribute(u"draw:marker-start-width"_ustr, sXML_CDATA, OUString::number( WTMM(hdo->property.line_width * 7.0)) + "mm"); } if( hdo->property.line_hstyle > 0 && o3tl::make_unsigned(hdo->property.line_hstyle) < std::size(ArrowShape) ) { mxList->addAttribute(u"draw:marker-end"_ustr, sXML_CDATA, OUString::createFromAscii(ArrowShape[hdo->property.line_hstyle].name) ); if( hdo->property.line_width > 100 ) mxList->addAttribute(u"draw:marker-end-width"_ustr, sXML_CDATA, OUString::number( WTMM(hdo->property.line_width * 3.0)) + "mm"); else if( hdo->property.line_width > 80 ) mxList->addAttribute(u"draw:marker-end-width"_ustr, sXML_CDATA, OUString::number( WTMM(hdo->property.line_width * 4.0)) + "mm"); else if( hdo->property.line_width > 60 ) mxList->addAttribute(u"draw:marker-end-width"_ustr, sXML_CDATA, OUString::number( WTMM(hdo->property.line_width * 5.0)) + "mm"); else if( hdo->property.line_width > 40 ) mxList->addAttribute(u"draw:marker-end-width"_ustr, sXML_CDATA, OUString::number( WTMM(hdo->property.line_width * 6.0)) + "mm"); else mxList->addAttribute(u"draw:marker-end-width"_ustr, sXML_CDATA, OUString::number( WTMM(hdo->property.line_width * 7.0)) + "mm"); } } if(hdo->type != HWPDO_LINE ) { if( hdo->property.flag >> 19 & 0x01 ) { mxList->addAttribute( u"draw:textarea-horizontal-align"_ustr, sXML_CDATA, u"center"_ustr); } color = hdo->property.fill_color; if( hdo->property.flag >> 18 & 0x01 ) // bitmap pattern { mxList->addAttribute(u"draw:fill"_ustr, sXML_CDATA, u"bitmap"_ustr); mxList->addAttribute(u"draw:fill-image-name"_ustr, sXML_CDATA, "fillimage" + OUString::number(hdo->index)); // bitmap resizing if( hdo->property.flag >> 3 & 0x01 ) { mxList->addAttribute(u"style:repeat"_ustr, sXML_CDATA, u"stretch"_ustr); } else { mxList->addAttribute(u"style:repeat"_ustr, sXML_CDATA, u"repeat"_ustr); mxList->addAttribute(u"draw:fill-image-ref-point"_ustr, sXML_CDATA, u"top-left"_ustr); } if( hdo->property.flag >> 20 & 0x01 ) { if( hdo->property.luminance > 0 ) { mxList->addAttribute(u"draw:transparency"_ustr, sXML_CDATA, OUString::number(hdo->property.luminance) + "%"); } } } // Gradation else if( hdo->property.flag >> 16 & 0x01 ) { mxList->addAttribute(u"draw:fill"_ustr, sXML_CDATA, u"gradient"_ustr); mxList->addAttribute(u"draw:fill-gradient-name"_ustr, sXML_CDATA, "Grad" + OUString::number(hdo->index)); mxList->addAttribute(u"draw:gradient-step-count"_ustr, sXML_CDATA, OUString::number(hdo->property.nstep)); } // Hatching else if( hdo->property.pattern_type >> 24 & 0x01 ) { mxList->addAttribute(u"draw:fill"_ustr, sXML_CDATA, u"hatch"_ustr); mxList->addAttribute(u"draw:fill-hatch-name"_ustr, sXML_CDATA, "Hatch" + OUString::number(hdo->index)); if( color < 0xffffff ) { mxList->addAttribute(u"draw:fill-color"_ustr, sXML_CDATA, rgb2str(static_cast(color))); mxList->addAttribute(u"draw:fill-hatch-solid"_ustr, sXML_CDATA, u"true"_ustr); } } else if( color <= 0xffffff ) { mxList->addAttribute(u"draw:fill"_ustr, sXML_CDATA, u"solid"_ustr); mxList->addAttribute(u"draw:fill-color"_ustr, sXML_CDATA, rgb2str(static_cast(color))); } else mxList->addAttribute(u"draw:fill"_ustr, sXML_CDATA, u"none"_ustr); } if( fstyle->anchor_type == CHAR_ANCHOR ) { mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"top"_ustr); mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"baseline"_ustr); } startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); if( hdo->type == 0 ) { makeDrawStyle( hdo->child.get(), fstyle ); } hdo = hdo->next.get(); } } void HwpReader::makeCaptionStyle(FBoxStyle * fstyle) { mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "CapBox" + OUString::number(fstyle->boxnum)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr); startEl(u"style:style"_ustr); mxList->clear(); mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA, u"0cm"_ustr); switch (fstyle->txtflow) { case 0: mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"none"_ustr); break; case 1: if( fstyle->boxtype == 'G' ) mxList->addAttribute(u"style:run-through"_ustr, sXML_CDATA, u"background"_ustr); mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"run-through"_ustr); break; case 2: mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"dynamic"_ustr); break; } if (fstyle->anchor_type == CHAR_ANCHOR) { mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"top"_ustr); mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"baseline"_ustr); mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"center"_ustr); mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr); } else { switch (-(fstyle->xpos)) { case 2: mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"right"_ustr); break; case 3: mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"center"_ustr); break; case 1: default: mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"from-left"_ustr); break; } switch (-(fstyle->ypos)) { case 2: mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"bottom"_ustr); break; case 3: mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"middle"_ustr); break; case 1: default: mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"from-top"_ustr); break; } if ( fstyle->anchor_type == PARA_ANCHOR ) { mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"paragraph"_ustr); mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr); } else { mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"page-content"_ustr); mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"page-content"_ustr); } } startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); if( fstyle->boxtype == 'G' ) { mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "G" + OUString::number(fstyle->boxnum)); } else { mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "Txtbox" + OUString::number(fstyle->boxnum)); } mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr); startEl(u"style:style"_ustr); mxList->clear(); mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"none"_ustr); mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"from-top"_ustr); mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"paragraph"_ustr); mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"from-left"_ustr); mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr); if (fstyle->boxtype == 'G' && fstyle->cell) { char *cell = static_cast(fstyle->cell); mxList->addAttribute(u"draw:luminance"_ustr, sXML_CDATA, OUString::number(cell[0]) + "%"); mxList->addAttribute(u"draw:contrast"_ustr, sXML_CDATA, OUString::number(cell[1]) + "%"); if( cell[2] == 0 ) mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"standard"_ustr); else if( cell[2] == 1 ) mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"greyscale"_ustr); else if( cell[2] == 2 ) mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"mono"_ustr); } else if (fstyle->cell) { Cell *cell = static_cast(fstyle->cell); if(cell->linetype[0] == cell->linetype[1] && cell->linetype[0] == cell->linetype[2] && cell->linetype[0] == cell->linetype[3]) { switch( cell->linetype[0] ) { case 0: mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA,u"0mm"_ustr); break; case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } } else { switch( cell->linetype[0] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-left"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } switch( cell->linetype[1] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-right"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } switch( cell->linetype[2] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-top"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } switch( cell->linetype[3] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-bottom"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } } if(cell->shade != 0) mxList->addAttribute(u"fo:background-color"_ustr, sXML_CDATA, hcolor2str( sal::static_int_cast(cell->color), sal::static_int_cast(cell->shade))); } startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); } /** * Create a style for the Floating objects. */ void HwpReader::makeFStyle(FBoxStyle * fstyle) { /* caption exist */ if( ( fstyle->boxtype == 'G' || fstyle->boxtype == 'X' ) && fstyle->cap_len > 0 ) { makeCaptionStyle(fstyle); return; } switch( fstyle->boxtype ) { case 'X' : // txtbox case 'E' : // equation case 'B' : // button case 'O' : // other case 'T' : // table mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "Txtbox" + OUString::number(fstyle->boxnum)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr); break; case 'G' : // graphics mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "G" + OUString::number(fstyle->boxnum)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr); break; case 'L' : // line TODO : all mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "L" + OUString::number(fstyle->boxnum)); mxList->addAttribute( u"style:family"_ustr , sXML_CDATA , u"paragraph"_ustr ); break; } startEl(u"style:style"_ustr); mxList->clear(); if ( fstyle->boxtype == 'T') { mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA, u"0cm"_ustr); } if( fstyle->boxtype != 'G' || fstyle->cap_len <= 0 ) { mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA, OUString::number(WTMM(fstyle->margin[0][0]) ) + "mm"); mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA, OUString::number(WTMM(fstyle->margin[0][1])) + "mm"); mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA, OUString::number(WTMM(fstyle->margin[0][2])) + "mm"); mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA, OUString::number(WTMM(fstyle->margin[0][3])) + "mm"); } switch (fstyle->txtflow) { case 0: mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"none"_ustr); break; case 1: if( fstyle->boxtype == 'G' || fstyle->boxtype == 'B' || fstyle->boxtype == 'O') mxList->addAttribute(u"style:run-through"_ustr, sXML_CDATA, u"background"_ustr); mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"run-through"_ustr); break; case 2: mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"dynamic"_ustr); break; } if (fstyle->anchor_type == CHAR_ANCHOR) { mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"top"_ustr); mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"baseline"_ustr); mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"center"_ustr); mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr); } else { switch (-(fstyle->xpos)) { case 2: mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"right"_ustr); break; case 3: mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"center"_ustr); break; case 1: default: mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"from-left"_ustr); break; } switch (-(fstyle->ypos)) { case 2: mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"bottom"_ustr); break; case 3: mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"middle"_ustr); break; case 1: default: mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"from-top"_ustr); break; } if ( fstyle->anchor_type == PARA_ANCHOR ) { mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"paragraph"_ustr); mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr); } else { mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"page-content"_ustr); mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"page-content"_ustr); } } if (fstyle->cell && (fstyle->boxtype == 'X' || fstyle->boxtype == 'B')) { Cell *cell = static_cast(fstyle->cell); if(cell->linetype[0] == cell->linetype[1] && cell->linetype[0] == cell->linetype[2] && cell->linetype[0] == cell->linetype[3]) { switch( cell->linetype[0] ) { case 0: mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA, u"none"_ustr); break; case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } } else { switch( cell->linetype[0] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-left"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } switch( cell->linetype[1] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-right"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } switch( cell->linetype[2] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-top"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } switch( cell->linetype[3] ) { case 1: /* A thin solid line */ case 3: /* Dotted line -> LibreOffice, there is no dotted line */ mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr); break; case 2: /* Bold lines */ mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr); break; case 4: /* Double line */ mxList->addAttribute(u"style:border-line-width-bottom"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr); mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr); break; } } if( cell->linetype[0] == 0 && cell->linetype[1] == 0 && cell->linetype[2] == 0 && cell->linetype[3] == 0 ){ mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA,u"0mm"_ustr); } else{ mxList->addAttribute(u"fo:padding-left"_ustr, sXML_CDATA, OUString::number(WTMM(fstyle->margin[1][0])) + "mm"); mxList->addAttribute(u"fo:padding-right"_ustr, sXML_CDATA, OUString::number(WTMM(fstyle->margin[1][1])) + "mm"); mxList->addAttribute(u"fo:padding-top"_ustr, sXML_CDATA, OUString::number(WTMM(fstyle->margin[1][2])) + "mm"); mxList->addAttribute(u"fo:padding-bottom"_ustr, sXML_CDATA, OUString::number(WTMM(fstyle->margin[1][3])) + "mm"); } if(cell->shade != 0) mxList->addAttribute(u"fo:background-color"_ustr, sXML_CDATA, hcolor2str( sal::static_int_cast(cell->color), sal::static_int_cast(cell->shade))); } else if( fstyle->boxtype == 'E' ) { mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA,u"0mm"_ustr); } else if( fstyle->boxtype == 'L' ) { mxList->addAttribute( u"style:border-line-width-bottom"_ustr, sXML_CDATA, u"0.02mm 0.35mm 0.02mm"_ustr); mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.039cm double #808080"_ustr); } else if( fstyle->boxtype == 'G' && fstyle->cell ) { if( fstyle->margin[1][0] || fstyle->margin[1][1] || fstyle->margin[1][2] || fstyle->margin[1][3] ){ OUString clip = "rect(" + OUString::number(WTMM(-fstyle->margin[1][0]) ) + "mm " + OUString::number(WTMM(-fstyle->margin[1][1]) ) + "mm " + OUString::number(WTMM(-fstyle->margin[1][2]) ) + "mm " + OUString::number(WTMM(-fstyle->margin[1][3]) ) + "mm)"; mxList->addAttribute(u"style:mirror"_ustr, sXML_CDATA, u"none"_ustr); mxList->addAttribute(u"fo:clip"_ustr, sXML_CDATA, clip); } char *cell = static_cast(fstyle->cell); mxList->addAttribute(u"draw:luminance"_ustr, sXML_CDATA, OUString::number(cell[0]) + "%"); mxList->addAttribute(u"draw:contrast"_ustr, sXML_CDATA, OUString::number(cell[1]) + "%"); if( cell[2] == 0 ) mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"standard"_ustr); else if( cell[2] == 1 ) mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"greyscale"_ustr); else if( cell[2] == 2 ) mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"mono"_ustr); } startEl(u"style:properties"_ustr); mxList->clear(); endEl(u"style:properties"_ustr); endEl(u"style:style"_ustr); } OUString HwpReader::getTStyleName(int index) { return "T" + OUString::number(index); } OUString HwpReader::getPStyleName(int index) { return "P" + OUString::number(index); } void HwpReader::makeChars(hchar_string & rStr) { chars(fromHcharStringToOUString(rStr)); rStr.clear(); } /** * If no special characters in the paragraph and all characters use the same CharShape */ void HwpReader::make_text_p0(HWPPara * para, bool bParaStart) { hchar_string str; int res; hchar dest[3]; unsigned char firstspace = 0; if( !bParaStart) { mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, getPStyleName(para->GetParaShape().index)); startEl(u"text:p"_ustr); mxList->clear(); } if( d->bFirstPara && d->bInBody ) { mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, sBeginOfDoc); startEl(u"text:bookmark"_ustr); mxList->clear(); endEl(u"text:bookmark"_ustr); d->bFirstPara = false; } if( d->bInHeader ) { makeShowPageNum(); d->bInHeader = false; } mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, getTStyleName(para->cshape->index)); startEl(u"text:span"_ustr); mxList->clear(); for (const auto& box : para->hhstr) { if (!box->hh) break; if (box->hh == CH_SPACE && !firstspace) { makeChars(str); startEl(u"text:s"_ustr); endEl(u"text:s"_ustr); } else if (box->hh == CH_END_PARA) { makeChars(str); endEl(u"text:span"_ustr); endEl(u"text:p"_ustr); break; } else { if (box->hh == CH_SPACE) firstspace = 0; else firstspace = 1; res = hcharconv(box->hh, dest, UNICODE); for( int j = 0 ; j < res; j++ ) { str.push_back(dest[j]); } } } } /* * There is no special characters in the paragraph, but characters use different CharShapes */ void HwpReader::make_text_p1(HWPPara * para,bool bParaStart) { hchar_string str; int res; hchar dest[3]; int curr = para->cshape->index; unsigned char firstspace = 0; if( !bParaStart ) { mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, getPStyleName(para->GetParaShape().index)); startEl(u"text:p"_ustr); mxList->clear(); } if( d->bFirstPara && d->bInBody ) { /* for HWP's Bookmark */ mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, sBeginOfDoc); startEl(u"text:bookmark"_ustr); mxList->clear(); endEl(u"text:bookmark"_ustr); d->bFirstPara = false; } if( d->bInHeader ) { makeShowPageNum(); d->bInHeader = false; } mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, getTStyleName(curr)); startEl(u"text:span"_ustr); mxList->clear(); int n = 0; for (const auto& box : para->hhstr) { if (!box->hh) break; if (para->GetCharShape(n)->index != curr) { makeChars(str); endEl(u"text:span"_ustr); curr = para->GetCharShape(n)->index; mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, getTStyleName(curr)); startEl(u"text:span"_ustr); mxList->clear(); } if (box->hh == CH_SPACE && !firstspace) { makeChars(str); startEl(u"text:s"_ustr); endEl(u"text:s"_ustr); } else if (box->hh == CH_END_PARA) { makeChars(str); endEl(u"text:span"_ustr); endEl(u"text:p"_ustr); break; } else { if( box->hh < CH_SPACE ) continue; if (box->hh == CH_SPACE) firstspace = 0; else firstspace = 1; res = hcharconv(box->hh, dest, UNICODE); for( int j = 0 ; j < res; j++ ) { str.push_back(dest[j]); } } n += box->WSize(); } } /** * Special characters are in the paragraph and characters use different CharShapes */ void HwpReader::make_text_p3(HWPPara * para,bool bParaStart) { hchar_string str; int res; hchar dest[3]; unsigned char firstspace = 0; bool pstart = bParaStart; bool tstart = false; bool infield = false; const auto STARTP = [this, para, &pstart]() { mxList->addAttribute(u"text:style-name"_ustr, u"CDATA"_ustr, getPStyleName(para->GetParaShape().index)); startEl(u"text:p"_ustr); mxList->clear(); pstart = true; }; const auto STARTT = [this, para, &tstart](int pos) { auto curr = para->GetCharShape(pos > 0 ? pos - 1 : 0)->index; mxList->addAttribute(u"text:style-name"_ustr, u"CDATA"_ustr, getTStyleName(curr)); startEl(u"text:span"_ustr); mxList->clear(); tstart = true; }; const auto ENDP = [this, &pstart]() { endEl(u"text:p"_ustr); pstart = false; }; const auto ENDT = [this, &tstart]() { endEl(u"text:span"_ustr); tstart = false; }; if( d->bFirstPara && d->bInBody ) { if ( !pstart ) { STARTP(); } mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, sBeginOfDoc); startEl(u"text:bookmark"_ustr); mxList->clear(); endEl(u"text:bookmark"_ustr); d->bFirstPara = false; } if( d->bInHeader ) { if ( !pstart ) { STARTP(); } makeShowPageNum(); d->bInHeader = false; } int n = 0; for (const auto& box : para->hhstr) { if (!box->hh) break; if (box->hh == CH_END_PARA) { if (!str.empty()) { if( !pstart ){ STARTP(); } if( !tstart ){ STARTT(n);} makeChars(str); } if( tstart ){ ENDT();} if( !pstart ){ STARTP(); } if( pstart ){ ENDP(); } break; } else if (box->hh == CH_SPACE && !firstspace) { if( !pstart ) {STARTP(); } if( !tstart ) {STARTT(n);} makeChars(str); startEl(u"text:s"_ustr); mxList->clear(); endEl(u"text:s"_ustr); } else if (box->hh >= CH_SPACE) { if( n > 0 ) if( para->GetCharShape(n)->index != para->GetCharShape(n-1)->index && !infield ) { if( !pstart ) {STARTP(); } if( !tstart ) {STARTT(n);} makeChars(str); ENDT(); } if (box->hh == CH_SPACE) firstspace = 0; else firstspace = 1; res = hcharconv(box->hh, dest, UNICODE); for( int j = 0 ; j < res; j++ ) { str.push_back(dest[j]); } } else if (box->hh == CH_FIELD) { FieldCode *hbox = static_cast(box.get()); if( hbox->location_info == 1) { if( !pstart ) {STARTP(); } if( !tstart ) {STARTT(n);} makeChars(str); firstspace = 1; if( hbox->type[0] == 4 && hbox->type[1] == 0 ) { d->pField = hbox->str3.get(); } else{ makeFieldCode(str, hbox); } infield = true; } else { firstspace = 1; if( hbox->type[0] == 4 && hbox->type[1] == 0 ) { makeFieldCode(str, hbox); d->pField = nullptr; } infield = false; str.clear(); } } else { switch (box->hh) { case CH_BOOKMARK: if( !pstart ) {STARTP(); } if( !tstart ) {STARTT(n);} makeChars(str); makeBookmark(static_cast(box.get())); break; case CH_DATE_FORM: // 7 break; case CH_DATE_CODE: // 8 if( !pstart ) {STARTP(); } if( !tstart ) {STARTT(n);} makeChars(str); makeDateCode(static_cast(box.get())); break; case CH_TAB: // 9 if( !pstart ) {STARTP(); } if (!str.empty()) { if( !tstart ) {STARTT(n);} makeChars(str); } makeTab(); break; case CH_TEXT_BOX: /* 10 - ordered by Table/text box/formula/button/hypertext */ { /* produce tables first, and treat formula as being in text:p. */ TxtBox *hbox = static_cast(box.get()); if( hbox->style.anchor_type == 0 ) { if( !pstart ) {STARTP(); } if( !tstart ) {STARTT(n);} makeChars(str); } else { if( !pstart ) {STARTP(); } if (!str.empty()) { if( !tstart ) {STARTT(n);} makeChars(str); } if( tstart ) {ENDT();} } switch (hbox->type) { case TBL_TYPE: // table case TXT_TYPE: // text box case EQU_TYPE: // formula makeTextBox(hbox); break; case BUTTON_TYPE: // text button case HYPERTEXT_TYPE: // hypertext makeHyperText(hbox); break; } break; } case CH_PICTURE: // 11 { Picture *hbox = static_cast(box.get()); if( hbox->style.anchor_type == 0 ) { if( !pstart ) {STARTP(); } if( !tstart ) {STARTT(n);} makeChars(str); } else { if( !pstart ) {STARTP(); } if (!str.empty()) { if( !tstart ) {STARTT(n);} makeChars(str); } if( tstart ) {ENDT();} } makePicture(hbox); break; } case CH_LINE: // 14 { if (!str.empty()) { if( !pstart ) {STARTP();} if( !tstart ) {STARTT(n);} makeChars(str); } if( tstart ) {ENDT();} if( pstart ) {ENDP();} makeLine(); pstart = true; break; } case CH_HIDDEN: // 15 if( !pstart ) {STARTP();} if( !tstart ) {STARTT(n);} makeChars(str); makeHidden(static_cast(box.get())); break; case CH_FOOTNOTE: // 17 if( !pstart ) {STARTP();} if( !tstart ) {STARTT(n);} makeChars(str); makeFootnote(static_cast(box.get())); break; case CH_AUTO_NUM: // 18 if( !pstart ) {STARTP();} if( !tstart ) {STARTT(n);} makeChars(str); makeAutoNum(static_cast(box.get())); break; case CH_NEW_NUM: // 19 -skip break; case CH_PAGE_NUM_CTRL: // 21 break; case CH_MAIL_MERGE: // 22 if( !pstart ) {STARTP();} if( !tstart ) {STARTT(n);} makeChars(str); makeMailMerge(static_cast(box.get())); break; case CH_COMPOSE: /* 23 - overlapping letters */ break; case CH_HYPHEN: // 24 break; case CH_TOC_MARK: /* 25 Need to fix below 3 */ if( !pstart ) {STARTP();} if( !tstart ) {STARTT(n);} makeChars(str); break; case CH_INDEX_MARK: // 26 if( !pstart ) {STARTP();} if( !tstart ) {STARTT(n);} makeChars(str); break; case CH_OUTLINE: // 28 if( !pstart ) {STARTP();} if( !tstart ) {STARTT(n);} makeChars(str); makeOutline(static_cast(box.get())); break; case CH_FIXED_SPACE: case CH_KEEP_SPACE: str.push_back(0x0020); break; } } n += box->WSize(); } } void HwpReader::makeFieldCode(hchar_string const & rStr, FieldCode const *hbox) { /* Push frame */ if( hbox->type[0] == 4 && hbox->type[1] == 0 ) { mxList->addAttribute(u"text:placeholder-type"_ustr, sXML_CDATA, u"text"_ustr); if (d->pField) mxList->addAttribute(u"text:description"_ustr, sXML_CDATA, hstr2OUString(d->pField)); startEl(u"text:placeholder"_ustr); mxList->clear(); chars( fromHcharStringToOUString(rStr) ); endEl(u"text:placeholder"_ustr); } /* Document Summary */ else if( hbox->type[0] == 3 && hbox->type[1] == 0 ) { const OUString uStr3 = hstr2OUString(hbox->str3.get()); if (uStr3 == "title") { startEl(u"text:title"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:title"_ustr); } else if (uStr3 == "subject") { startEl(u"text:subject"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:subject"_ustr); } else if (uStr3 == "author") { startEl(u"text:author-name"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:author-name"_ustr); } else if (uStr3 == "keywords") { startEl(u"text:keywords"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:keywords"_ustr); } } /* Personal Information */ else if( hbox->type[0] == 3 && hbox->type[1] == 1 ) { const OUString uStr3 = hstr2OUString(hbox->str3.get()); if (uStr3 == "User") { startEl(u"text:sender-lastname"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:sender-lastname"_ustr); } else if (uStr3 == "Company") { startEl(u"text:sender-company"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:sender-company"_ustr); } else if (uStr3 == "Position") { startEl(u"text:sender-title"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:sender-title"_ustr); } else if (uStr3 == "Division") { startEl(u"text:sender-position"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:sender-position"_ustr); } else if (uStr3 == "Fax") { startEl(u"text:sender-fax"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:sender-fax"_ustr); } else if (uStr3 == "Pager") { startEl(u"text:phone-private"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:phone-private"_ustr); } else if (uStr3 == "E-mail") { startEl(u"text:sender-email"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:sender-email"_ustr); } else if (uStr3 == "Zipcode(office)") { startEl(u"text:sender-postal-code"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:sender-postal-code"_ustr); } else if (uStr3 == "Phone(office)") { startEl(u"text:sender-phone-work"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:sender-phone-work"_ustr); } else if (uStr3 == "Address(office)") { startEl(u"text:sender-street"_ustr); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:sender-street"_ustr); } } else if( hbox->type[0] == 3 && hbox->type[1] == 2 ) /* creation date */ { if( hbox->m_pDate ) mxList->addAttribute(u"style:data-style-name"_ustr, sXML_CDATA, "N" + OUString::number(hbox->m_pDate->key)); startEl(u"text:creation-date"_ustr); mxList->clear(); chars( hstr2OUString(hbox->str2.get()) ); endEl(u"text:creation-date"_ustr); } } /** * Completed * In LibreOffice, refer bookmarks as reference, but hwp doesn't have the sort of feature. */ void HwpReader::makeBookmark(Bookmark const * hbox) { if (hbox->type == 0) { mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, hstr2OUString(hbox->id)); startEl(u"text:bookmark"_ustr); mxList->clear(); endEl(u"text:bookmark"_ustr); } else if (hbox->type == 1) /* Block bookmarks days begin and end there if */ { mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, hstr2OUString(hbox->id)); startEl(u"text:bookmark-start"_ustr); mxList->clear(); endEl(u"text:bookmark-start"_ustr); } else if (hbox->type == 2) { mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, hstr2OUString(hbox->id)); startEl(u"text:bookmark-end"_ustr); mxList->clear(); endEl(u"text:bookmark-end"_ustr); } } void HwpReader::makeDateFormat(DateCode * hbox) { mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "N" + OUString::number(hbox->key)); mxList->addAttribute(u"style:family"_ustr, sXML_CDATA,u"data-style"_ustr); mxList->addAttribute(u"number:language"_ustr, sXML_CDATA,u"ko"_ustr); mxList->addAttribute(u"number:country"_ustr, sXML_CDATA,u"KR"_ustr); startEl(u"number:date-style"_ustr); mxList->clear(); bool add_zero = false; int zero_check = 0; hbox->format[DATE_SIZE -1] = 0; const hchar *fmt = hbox->format[0] ? hbox->format : defaultform; for( ; *fmt ; fmt++ ) { if( zero_check == 1 ) { zero_check = 0; } else add_zero = false; switch( *fmt ) { case '0': zero_check = 1; add_zero = true; break; case '1': mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr); startEl(u"number:year"_ustr); mxList->clear(); endEl(u"number:year"_ustr); break; case '!': startEl(u"number:year"_ustr); mxList->clear(); endEl(u"number:year"_ustr); break; case '2': if( add_zero ) mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr); startEl(u"number:month"_ustr); mxList->clear(); endEl(u"number:month"_ustr); break; case '@': mxList->addAttribute(u"number:textual"_ustr, sXML_CDATA, u"true"_ustr); startEl(u"number:month"_ustr); mxList->clear(); endEl(u"number:month"_ustr); break; case '*': mxList->addAttribute(u"number:textual"_ustr, sXML_CDATA, u"true"_ustr); mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr); startEl(u"number:month"_ustr); mxList->clear(); endEl(u"number:month"_ustr); break; case '3': if( add_zero ) mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr); startEl(u"number:day"_ustr); mxList->clear(); endEl(u"number:day"_ustr); break; case '#': if( add_zero ) mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr); startEl(u"number:day"_ustr); mxList->clear(); endEl(u"number:day"_ustr); switch( hbox->date[DateCode::DAY] % 10) { case 1: startEl(u"number:text"_ustr); chars(u"st"_ustr); endEl(u"number:text"_ustr); break; case 2: startEl(u"number:text"_ustr); chars(u"nd"_ustr); endEl(u"number:text"_ustr); break; case 3: startEl(u"number:text"_ustr); chars(u"rd"_ustr); endEl(u"number:text"_ustr); break; default: startEl(u"number:text"_ustr); chars(u"th"_ustr); endEl(u"number:text"_ustr); break; } break; case '4': case '$': if( add_zero ) mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr); startEl(u"number:hours"_ustr); mxList->clear(); endEl(u"number:hours"_ustr); break; case '5': case '%': if( add_zero ) mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr); startEl(u"number:minutes"_ustr); mxList->clear(); endEl(u"number:minutes"_ustr); break; case '_': mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr); [[fallthrough]]; case '6': case '^': startEl(u"number:day-of-week"_ustr); mxList->clear(); endEl(u"number:day-of-week"_ustr); break; case '7': case '&': case '+': startEl(u"number:am-pm"_ustr); mxList->clear(); endEl(u"number:am-pm"_ustr); break; case '~': // Chinese Locale break; default: hchar sbuf[2]; sbuf[0] = *fmt; sbuf[1] = 0; startEl(u"number:text"_ustr); chars(hstr2OUString(sbuf)); endEl(u"number:text"_ustr); break; } } mxList->clear(); endEl(u"number:date-style"_ustr); } void HwpReader::makeDateCode(DateCode * hbox) { mxList->addAttribute(u"style:data-style-name"_ustr, sXML_CDATA, "N" + OUString::number(hbox->key)); startEl(u"text:date"_ustr); mxList->clear(); hchar_string const boxstr = hbox->GetString(); chars(hstr2OUString(boxstr.c_str())); endEl(u"text:date"_ustr); } void HwpReader::makeTab() { startEl(u"text:tab-stop"_ustr); endEl(u"text:tab-stop"_ustr); } void HwpReader::makeTable(TxtBox * hbox) { mxList->addAttribute(u"table:name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum)); mxList->addAttribute(u"table:style-name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum)); startEl(u"table:table"_ustr); mxList->clear(); Table *tbl = hbox->m_pTable; // column for (size_t i = 0 ; i < tbl->columns.nCount -1 ; i++) { mxList->addAttribute( u"table:style-name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum) + "." + OUStringChar(static_cast('A'+i))); startEl(u"table:table-column"_ustr); mxList->clear(); endEl(u"table:table-column"_ustr); } // cell int j = -1, k = -1; for (auto const& tcell : tbl->cells) { if( tcell->nRowIndex > j ) { if( j > k ) { endEl(u"table:table-row"_ustr); k = j; } // row mxList->addAttribute( u"table:style-name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum) + ".row" + OUString::number(tcell->nRowIndex + 1)); startEl(u"table:table-row"_ustr); mxList->clear(); j = tcell->nRowIndex; } mxList->addAttribute( u"table:style-name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum) + "." + OUStringChar(char('A'+ tcell->nColumnIndex)) + OUString::number(tcell->nRowIndex +1)); if( tcell->nColumnSpan > 1 ) mxList->addAttribute(u"table:number-columns-spanned"_ustr, sXML_CDATA, OUString::number(tcell->nColumnSpan)); if( tcell->nRowSpan > 1 ) mxList->addAttribute(u"table:number-rows-spanned"_ustr, sXML_CDATA, OUString::number(tcell->nRowSpan)); mxList->addAttribute(u"table:value-type"_ustr, sXML_CDATA,u"string"_ustr); if( tcell->pCell->protect ) mxList->addAttribute(u"table:protected"_ustr, sXML_CDATA,u"true"_ustr); startEl(u"table:table-cell"_ustr); mxList->clear(); TxtBox::plist_t& rVec = hbox->plists[tcell->pCell->key]; if (!rVec.empty()) parsePara(rVec.front().get()); endEl(u"table:table-cell"_ustr); } endEl(u"table:table-row"_ustr); endEl(u"table:table"_ustr); } /** * Parses the text boxes and tables. * 1. draw: style-name, draw: name, text: anchor-type, svg: width, * Fo: min-height, svg: x, svg: y * TODO: fo:background-color <= no idea whether the value of color setting->style is in it or not */ void HwpReader::makeTextBox(TxtBox * hbox) { if( hbox->style.cap_len > 0 && hbox->type == TXT_TYPE) { mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "CapBox" + OUString::number(hbox->style.boxnum)); mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, "CaptionBox" + OUString::number(hbox->style.boxnum)); mxList->addAttribute(u"draw:z-index"_ustr, sXML_CDATA, OUString::number(hbox->zorder)); switch (hbox->style.anchor_type) { case CHAR_ANCHOR: mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr); break; case PARA_ANCHOR: mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr); break; case PAGE_ANCHOR: case PAPER_ANCHOR: { mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"page"_ustr); mxList->addAttribute(u"text:anchor-page-number"_ustr, sXML_CDATA, OUString::number(hbox->pgno + 1)); break; } } if (hbox->style.anchor_type != CHAR_ANCHOR) { mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm"); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm"); } mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->box_xs + hbox->cap_xs )) + "mm"); mxList->addAttribute(u"fo:min-height"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->box_ys + hbox->cap_ys )) + "mm"); startEl(u"draw:text-box"_ustr); mxList->clear(); if (!hbox->caption.empty() && hbox->cap_pos % 2) /* The caption is on the top */ { parsePara(hbox->caption.front().get()); } mxList->addAttribute( u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"text:p"_ustr); mxList->clear(); } else{ mxList->addAttribute(u"draw:z-index"_ustr, sXML_CDATA, OUString::number(hbox->zorder)); } mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "Txtbox" + OUString::number(hbox->style.boxnum)); mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, "Frame" + OUString::number(hbox->style.boxnum)); if( hbox->style.cap_len <= 0 || hbox->type != TXT_TYPE ) { int x = 0; int y = 0; switch (hbox->style.anchor_type) { case CHAR_ANCHOR: mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr); break; case PARA_ANCHOR: mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr); break; case PAGE_ANCHOR: case PAPER_ANCHOR: { mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"page"_ustr); mxList->addAttribute(u"text:anchor-page-number"_ustr, sXML_CDATA, OUString::number(hbox->pgno + 1)); break; } } if( hbox->style.anchor_type != CHAR_ANCHOR ) { x += hbox->style.margin[0][0]; y += hbox->style.margin[0][2]; } mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->pgx + x )) + "mm"); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->pgy + y )) + "mm"); } else { mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, u"0cm"_ustr); } mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->box_xs )) + "mm"); if( hbox->style.cap_len > 0 && hbox->type != TXT_TYPE) mxList->addAttribute(u"fo:min-height"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->box_ys + hbox->cap_ys)) + "mm"); else mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA, OUString::number(WTMM(hbox->box_ys )) + "mm"); if( hbox->type != EQU_TYPE ) { startEl(u"draw:text-box"_ustr); mxList->clear(); /* If captions are present and it is on the top */ if (hbox->style.cap_len > 0 && (hbox->cap_pos % 2) && hbox->type == TBL_TYPE && !hbox->caption.empty()) { parsePara(hbox->caption.front().get()); } if( hbox->type == TBL_TYPE) // Is Table { makeTable(hbox); } else if (!hbox->plists[0].empty()) // Is TextBox { parsePara(hbox->plists[0].front().get()); } /* If captions are present and it is on the bottom */ if (hbox->style.cap_len > 0 && !(hbox->cap_pos % 2) && hbox->type == TBL_TYPE && !hbox->caption.empty()) { parsePara(hbox->caption.front().get()); } endEl(u"draw:text-box"_ustr); // Caption exist and it is text-box if( hbox->style.cap_len > 0 && hbox->type == TXT_TYPE) { endEl(u"text:p"_ustr); if (!(hbox->cap_pos % 2) && !hbox->caption.empty()) { parsePara(hbox->caption.front().get()); } endEl(u"draw:text-box"_ustr); } } else // is Formula { startEl(u"draw:object"_ustr); mxList->clear(); makeFormula(hbox); endEl(u"draw:object"_ustr); } } /** * It must be converted into MathML. * */ void HwpReader::makeFormula(TxtBox * hbox) { char mybuf[3000]; HWPPara* pPar; hchar dest[3]; size_t l = 0; pPar = hbox->plists[0].empty() ? nullptr : hbox->plists[0].front().get(); while( pPar ) { for (const auto& box : pPar->hhstr) { if (!box->hh) break; if (l >= sizeof(mybuf)-7) break; int res = hcharconv(box->hh, dest, UNICODE); for( int j = 0 ; j < res; j++ ){ int c = dest[j]; if( c < 32 ) c = ' '; if( c < 256 ) mybuf[l++] = sal::static_int_cast(c); else { mybuf[l++] = sal::static_int_cast((c >> 8) & 0xff); mybuf[l++] = sal::static_int_cast(c & 0xff); } } } if (l >= sizeof(mybuf)-7) break; mybuf[l++] = '\n'; pPar = pPar->Next(); } mybuf[l] = '\0'; Formula form( mybuf ); form.setDocumentHandler(m_rxDocumentHandler); form.setAttributeListImpl(mxList.get()); form.parse(); } /** * Read the platform information. if the platform is Linux or Solaris, it needs to change * C: \ => Home, D: \ => changed to root (/). Because HWP uses DOS emulator. */ void HwpReader::makeHyperText(TxtBox * hbox) { HyperText *hypert = hwpfile.GetHyperText(); if( !hypert ) return; if (hypert->filename[0] != '\0') { ::std::string const tmp = hstr2ksstr(hypert->bookmark); ::std::string const tmp2 = hstr2ksstr(kstr2hstr( #ifdef _WIN32 reinterpret_cast(urltowin(reinterpret_cast(hypert->filename)).c_str())).c_str()); #else reinterpret_cast(urltounix(reinterpret_cast(hypert->filename)).c_str())).c_str()); #endif mxList->addAttribute(u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr); if (!tmp.empty() && strcmp(tmp.c_str(), "[HTML]")) { ::std::string tmp3(tmp2); tmp3.push_back('#'); tmp3.append(tmp); mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA, OUString(tmp3.c_str(), tmp3.size()+1, RTL_TEXTENCODING_EUC_KR)); } else{ mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA, OUString(tmp2.c_str(), tmp2.size()+1, RTL_TEXTENCODING_EUC_KR)); } } else { mxList->addAttribute(u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr); ::std::string tmp; tmp.push_back('#'); tmp.append(hstr2ksstr(hypert->bookmark)); mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA, OUString(tmp.c_str(), tmp.size()+1, RTL_TEXTENCODING_EUC_KR)); } startEl(u"draw:a"_ustr); mxList->clear(); makeTextBox(hbox); endEl(u"draw:a"_ustr); } /** * Read the platform information. if the platform is Linux or Solaris, it needs to change * C: \ => Home, D: \ => changed to root (/). Because HWP uses DOS emulator. */ void HwpReader::makePicture(Picture * hbox) { switch (hbox->pictype) { case PICTYPE_OLE: case PICTYPE_EMBED: case PICTYPE_FILE: { if( hbox->style.cap_len > 0 ) { mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "CapBox" + OUString::number(hbox->style.boxnum)); mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, "CaptionBox" + OUString::number(hbox->style.boxnum)); mxList->addAttribute(u"draw:z-index"_ustr, sXML_CDATA, OUString::number(hbox->zorder)); switch (hbox->style.anchor_type) { case CHAR_ANCHOR: mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr); break; case PARA_ANCHOR: mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr); break; case PAGE_ANCHOR: case PAPER_ANCHOR: { mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"page"_ustr); mxList->addAttribute(u"text:anchor-page-number"_ustr, sXML_CDATA, OUString::number(hbox->pgno + 1)); break; } } if (hbox->style.anchor_type != CHAR_ANCHOR) { mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm"); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm"); } mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1] )) + "mm"); mxList->addAttribute(u"fo:min-height"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->box_ys + hbox->style.margin[1][2] + hbox->style.margin[1][3] + hbox->cap_ys )) + "mm"); startEl(u"draw:text-box"_ustr); mxList->clear(); if (!hbox->caption.empty() && hbox->cap_pos % 2) /* Caption is on the top */ { parsePara(hbox->caption.front().get()); } mxList->addAttribute( u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr); startEl(u"text:p"_ustr); mxList->clear(); } if( hbox->ishyper ) { mxList->addAttribute(u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr); #ifdef _WIN32 if( hbox->follow[4] != 0 ) mxList->addAttribute("xlink:href", sXML_CDATA, hstr2OUString(kstr2hstr(hbox->follow.data() + 4).c_str())); else mxList->addAttribute("xlink:href", sXML_CDATA, hstr2OUString(kstr2hstr(hbox->follow.data() + 5).c_str())); #else if( hbox->follow[4] != 0 ) mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA, hstr2OUString(kstr2hstr(reinterpret_cast(urltounix(reinterpret_cast(hbox->follow.data() + 4)).c_str())).c_str())); else mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA, hstr2OUString(kstr2hstr(reinterpret_cast(urltounix(reinterpret_cast(hbox->follow.data() + 5)).c_str())).c_str())); #endif startEl(u"draw:a"_ustr); mxList->clear(); } mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "G" + OUString::number(hbox->style.boxnum)); mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, "Image" + OUString::number(hbox->style.boxnum)); if( hbox->style.cap_len <= 0 ) { mxList->addAttribute(u"draw:z-index"_ustr, sXML_CDATA, OUString::number(hbox->zorder)); switch (hbox->style.anchor_type) { case CHAR_ANCHOR: mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr); break; case PARA_ANCHOR: mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr); break; case PAGE_ANCHOR: case PAPER_ANCHOR: { mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"page"_ustr); mxList->addAttribute(u"text:anchor-page-number"_ustr, sXML_CDATA, OUString::number(hbox->pgno + 1)); break; } } if (hbox->style.anchor_type != CHAR_ANCHOR) { mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm"); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm"); } } else { mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, u"0cm"_ustr); } mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1])) + "mm"); mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA, OUString::number(WTMM( hbox->box_ys + hbox->style.margin[1][2] + hbox->style.margin[1][3])) + "mm"); if ( hbox->pictype == PICTYPE_FILE ){ #ifdef _WIN32 sprintf(d->buf, "file:///%s", hbox->picinfo.picun.path ); mxList->addAttribute("xlink:href", sXML_CDATA, hstr2OUString(kstr2hstr(reinterpret_cast(d->buf)).c_str())); #else mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA, hstr2OUString(kstr2hstr(reinterpret_cast(urltounix(hbox->picinfo.picun.path).c_str())).c_str())); #endif mxList->addAttribute(u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr); mxList->addAttribute(u"xlink:show"_ustr, sXML_CDATA, u"embed"_ustr); mxList->addAttribute(u"xlink:actuate"_ustr, sXML_CDATA, u"onLoad"_ustr); } if( hbox->pictype == PICTYPE_OLE ) startEl(u"draw:object-ole"_ustr); else startEl(u"draw:image"_ustr); mxList->clear(); if (hbox->pictype == PICTYPE_EMBED || hbox->pictype == PICTYPE_OLE) { startEl(u"office:binary-data"_ustr); mxList->clear(); if( hbox->pictype == PICTYPE_EMBED ){ EmPicture *emp = hwpfile.GetEmPicture(hbox); if( emp ) { chars(base64_encode_string(emp->data.data(), emp->size)); } } else{ if( hwpfile.oledata ){ #ifdef _WIN32 LPSTORAGE srcsto; LPUNKNOWN pObj; wchar_t pathname[200]; MultiByteToWideChar(CP_ACP, 0, hbox->picinfo.picembed.embname, -1, pathname, 200); int rc = hwpfile.oledata->pis->OpenStorage(pathname, nullptr, STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, nullptr, 0, &srcsto); if (rc != S_OK) { chars(""); } else{ rc = OleLoad(srcsto, IID_IUnknown, nullptr, reinterpret_cast(&pObj)); if( rc != S_OK ){ srcsto->Release(); chars(""); } else{ chars(base64_encode_string(reinterpret_cast(pObj), strlen(reinterpret_cast(pObj)))); pObj->Release(); srcsto->Release(); } } #else chars(u""_ustr); #endif } } endEl(u"office:binary-data"_ustr); } if( hbox->pictype == PICTYPE_OLE ) endEl(u"draw:object-ole"_ustr); else endEl(u"draw:image"_ustr); if( hbox->ishyper ) { endEl(u"draw:a"_ustr); } if( hbox->style.cap_len > 0 ) { endEl(u"text:p"_ustr); if (!hbox->caption.empty() && !(hbox->cap_pos % 2)) /* Caption is at the bottom, */ { parsePara(hbox->caption.front().get()); } endEl(u"draw:text-box"_ustr); } break; } case PICTYPE_DRAW: if( hbox->picinfo.picdraw.zorder > 0 ) mxList->addAttribute(u"draw:z-index"_ustr, sXML_CDATA, OUString::number(hbox->picinfo.picdraw.zorder + 10000)); makePictureDRAW(hbox->picinfo.picdraw.hdo, hbox); break; case PICTYPE_UNKNOWN: break; } } void HwpReader::makePictureDRAW(HWPDrawingObject *drawobj, const Picture* hbox) { bool bIsRotate = false; while (drawobj) { mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "Draw" + OUString::number(drawobj->index)); int a = 0; int b = 0; switch (hbox->style.anchor_type) { case CHAR_ANCHOR: mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr); break; case PARA_ANCHOR: mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr); break; case PAGE_ANCHOR: case PAPER_ANCHOR: { HWPInfo& hwpinfo = hwpfile.GetHWPInfo(); mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"page"_ustr); mxList->addAttribute(u"text:anchor-page-number"_ustr, sXML_CDATA, OUString::number(hbox->pgno + 1)); a = hwpinfo.paper.left_margin; b = hwpinfo.paper.top_margin + hwpinfo.paper.header_length; break; } } if (drawobj->type == HWPDO_CONTAINER) { startEl(u"draw:g"_ustr); mxList->clear(); makePictureDRAW(drawobj->child.get(), hbox); endEl(u"draw:g"_ustr); } else { double x = hbox->pgx; double y = hbox->pgy; bIsRotate = false; if( (drawobj->property.flag & HWPDO_FLAG_ROTATION) && (drawobj->property.parall.pt[0].y != drawobj->property.parall.pt[1].y) && //(drawobj->type == HWPDO_RECT || drawobj->type == HWPDO_ADVANCED_ELLIPSE || drawobj->type == HWPDO_ADVANCED_ARC ) (drawobj->type == HWPDO_RECT || drawobj->type == HWPDO_ADVANCED_ELLIPSE ) ) { int i; ZZParall& pal = drawobj->property.parall; basegfx::B2DPoint pt[3], r_pt[3]; for(i = 0 ; i < 3 ; i++ ){ basegfx::B2DPoint rot_origin(drawobj->property.rot_originx, drawobj->property.rot_originy); pt[i].setX(pal.pt[i].x - rot_origin.getX()); /* Convert to a physical coordinate */ pt[i].setY(-(pal.pt[i].y - rot_origin.getY())); } double skewX; /* 2 - rotation angle calculation */ double rotate = atan2(pt[1].getY() - pt[0].getY(), pt[1].getX() - pt[0].getX()); for( i = 0 ; i < 3 ; i++){ r_pt[i].setX(pt[i].getX() * cos(-rotate) - pt[i].getY() * sin(-rotate)); r_pt[i].setY(pt[i].getY() * cos(-rotate) + pt[i].getX() * sin(-rotate)); } /* 4 - Calculation of reflex angle */ if (r_pt[2].getY() == r_pt[1].getY()) skewX = 0; else skewX = atan((r_pt[2].getX() - r_pt[1].getX()) / (r_pt[2].getY() - r_pt[1].getY())); if( skewX >= M_PI_2 ) skewX -= M_PI; if( skewX <= -M_PI_2 ) skewX += M_PI; OUString trans; if( skewX != 0.0 && rotate != 0.0 ){ trans = "skewX (" + OUString::number(skewX) + ") rotate (" + OUString::number(rotate) + ") translate (" + OUString::number(WTMM(x + a + drawobj->offset2.x + pal.pt[0].x)) + "mm " + OUString::number(WTMM(y + b + drawobj->offset2.y + pal.pt[0].y)) + "mm)"; bIsRotate = true; } else if( skewX != 0.0 ){ trans = "skewX (" + OUString::number(skewX) + ") translate (" + OUString::number(WTMM(x + a + drawobj->offset2.x + pal.pt[0].x)) + "mm " + OUString::number(WTMM(y + b + drawobj->offset2.y + pal.pt[0].y)) + "mm)"; bIsRotate = true; } else if( rotate != 0.0 ){ trans = "rotate (" + OUString::number(rotate) + ") translate (" + OUString::number(WTMM(x + a + drawobj->offset2.x + pal.pt[0].x)) + "mm " + OUString::number(WTMM(y + b + drawobj->offset2.y + pal.pt[0].y)) + "mm)"; bIsRotate = true; } if( bIsRotate ){ drawobj->extent.w = static_cast(std::hypot(pt[1].getX() - pt[0].getX(), pt[1].getY() - pt[0].getY())); drawobj->extent.h = static_cast(std::hypot(pt[2].getX() - pt[1].getX(), pt[2].getY() - pt[1].getY())); mxList->addAttribute(u"draw:transform"_ustr, sXML_CDATA, trans); } } switch (drawobj->type) { case HWPDO_LINE: /* Line-starting coordinates, ending coordinates. */ if( drawobj->u.line_arc.flip & 0x01 ) { mxList->addAttribute(u"svg:x1"_ustr, sXML_CDATA, OUString::number (WTMM(x + a + drawobj->offset2.x + drawobj->extent.w)) + "mm"); mxList->addAttribute(u"svg:x2"_ustr, sXML_CDATA, OUString::number (WTMM( x + a + drawobj->offset2.x )) + "mm"); } else { mxList->addAttribute(u"svg:x1"_ustr, sXML_CDATA, OUString::number (WTMM( x + a + drawobj->offset2.x )) + "mm"); mxList->addAttribute(u"svg:x2"_ustr, sXML_CDATA, OUString::number (WTMM(x + a + drawobj->offset2.x + drawobj->extent.w)) + "mm"); } if( drawobj->u.line_arc.flip & 0x02 ) { mxList->addAttribute(u"svg:y1"_ustr, sXML_CDATA, OUString::number (WTMM( y + b + drawobj->offset2.y + drawobj->extent.h ) ) + "mm"); mxList->addAttribute(u"svg:y2"_ustr, sXML_CDATA, OUString::number (WTMM( y + b + drawobj->offset2.y )) + "mm"); } else { mxList->addAttribute(u"svg:y1"_ustr, sXML_CDATA, OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm"); mxList->addAttribute(u"svg:y2"_ustr, sXML_CDATA, OUString::number (WTMM(y + b + drawobj->offset2.y + drawobj->extent.h)) + "mm"); } startEl(u"draw:line"_ustr); mxList->clear(); endEl(u"draw:line"_ustr); break; case HWPDO_RECT: /* rectangle - the starting position, vertical/horizontal */ if( !bIsRotate ) { mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA, OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm"); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm"); } mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.w )) + "mm"); mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.h )) + "mm"); if( drawobj->property.flag & 0x01 ) { int value = drawobj->extent.w < drawobj->extent.h ? drawobj->extent.w : drawobj->extent.h ; mxList->addAttribute(u"draw:corner-radius"_ustr, sXML_CDATA, OUString::number (WTMM( value/10 )) + "mm"); } else if( drawobj->property.flag & 0x04 ) { int value = drawobj->extent.w < drawobj->extent.h ? drawobj->extent.w : drawobj->extent.h ; mxList->addAttribute(u"draw:corner-radius"_ustr, sXML_CDATA, OUString::number (WTMM( value / 2)) + "mm"); } startEl(u"draw:rect"_ustr); mxList->clear(); if( (drawobj->property.flag & HWPDO_FLAG_AS_TEXTBOX) && drawobj->property.pPara ) // As Textbox { HWPPara *pPara = drawobj->property.pPara; //parsePara(pPara); while(pPara) { make_text_p1( pPara, false ); pPara = pPara->Next(); } } endEl(u"draw:rect"_ustr); break; case HWPDO_ELLIPSE: /* Ellipse - the starting position, vertical/horizontal */ case HWPDO_ADVANCED_ELLIPSE: /* modified ellipse */ { if( !bIsRotate ) { mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA, OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm"); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm"); } mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.w )) + "mm"); mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.h )) + "mm"); if( drawobj->type == HWPDO_ADVANCED_ELLIPSE ){ if (drawobj->u.arc.radial[0].x != drawobj->u.arc.radial[1].x || drawobj->u.arc.radial[0].y != drawobj->u.arc.radial[1].y) { int Cx, Cy; if (!o3tl::checked_add(drawobj->offset2.x, drawobj->extent.w, Cx) && !o3tl::checked_add(drawobj->offset2.y, drawobj->extent.h, Cy)) { Cx /= 2; Cy /= 2; double start_angle = calcAngle( Cx, Cy, drawobj->u.arc.radial[0].x, drawobj->u.arc.radial[0].y ); double end_angle = calcAngle( Cx, Cy, drawobj->u.arc.radial[1].x, drawobj->u.arc.radial[1].y ); if( drawobj->property.fill_color < 0xffffff ) mxList->addAttribute(u"draw:kind"_ustr, sXML_CDATA, u"section"_ustr); else mxList->addAttribute(u"draw:kind"_ustr, sXML_CDATA, u"arc"_ustr); mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, OUString::number(start_angle )); mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, OUString::number(end_angle)); } } } startEl(u"draw:ellipse"_ustr); mxList->clear(); if( drawobj->property.flag >> 19 & 0x01 && drawobj->property.pPara ) // As Textbox { HWPPara *pPara = drawobj->property.pPara; //parsePara(pPara); while(pPara) { make_text_p1( pPara, false ); pPara = pPara->Next(); } } endEl(u"draw:ellipse"_ustr); break; } case HWPDO_ARC: /* Arc */ case HWPDO_ADVANCED_ARC: { /* If it is the arc, LibreOffice assumes the size as the entire ellipse size */ uint flip = drawobj->u.line_arc.flip; if( !bIsRotate ) { if( ( flip == 0 || flip == 2 ) && drawobj->type == HWPDO_ARC) mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA, OUString::number (WTMM( x + a + drawobj->offset2.x - drawobj->extent.w)) + "mm"); else mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA, OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm"); if( ( flip == 0 || flip == 1 ) && drawobj->type == HWPDO_ARC) mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, OUString::number (WTMM( y + b + drawobj->offset2.y - drawobj->extent.h)) + "mm"); else mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm"); } mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.w * 2)) + "mm"); mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.h * 2)) + "mm"); if( drawobj->property.flag & HWPDO_FLAG_DRAW_PIE || drawobj->property.fill_color < 0xffffff ) mxList->addAttribute(u"draw:kind"_ustr, sXML_CDATA, u"section"_ustr); else mxList->addAttribute(u"draw:kind"_ustr, sXML_CDATA, u"arc"_ustr); if( drawobj->type == HWPDO_ADVANCED_ARC ){ double start_angle, end_angle; ZZParall& pal = drawobj->property.parall; start_angle = atan2(pal.pt[0].y - pal.pt[1].y,pal.pt[1].x - pal.pt[0].x ); end_angle = atan2(pal.pt[2].y - pal.pt[1].y, pal.pt[1].x - pal.pt[2].x); if( ( start_angle > end_angle ) && (start_angle - end_angle < M_PI )) std::swap( start_angle, end_angle ); mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, OUString::number(basegfx::rad2deg(start_angle))); mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, OUString::number(basegfx::rad2deg(end_angle))); } else { if( drawobj->u.line_arc.flip == 0 ) { mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, u"270"_ustr); mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, u"0"_ustr); } else if( drawobj->u.line_arc.flip == 1 ) { mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, u"180"_ustr); mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, u"270"_ustr); } else if( drawobj->u.line_arc.flip == 2 ) { mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, u"0"_ustr); mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, u"90"_ustr); } else { mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, u"90"_ustr); mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, u"180"_ustr); } } startEl(u"draw:ellipse"_ustr); mxList->clear(); if( drawobj->property.flag >> 19 & 0x01 && drawobj->property.pPara ) // As Textbox { HWPPara *pPara = drawobj->property.pPara; //parsePara(pPara); while(pPara) { make_text_p1( pPara, false ); pPara = pPara->Next(); } } endEl(u"draw:ellipse"_ustr); break; } case HWPDO_CURVE: /* Curve: converts to polygons. */ { bool bIsNatural = true; if( drawobj->property.flag >> 5 & 0x01){ bIsNatural = false; } if( !bIsRotate ) { mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA, OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm"); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm"); } mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.w )) + "mm"); mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.h )) + "mm"); mxList->addAttribute( u"svg:viewBox"_ustr, sXML_CDATA, "0 0 " + OUString::number(WTSM(drawobj->extent.w)) + " " + OUString::number(WTSM(drawobj->extent.h))); OUStringBuffer oustr; if ((drawobj->u.freeform.npt > 2) && (o3tl::make_unsigned(drawobj->u.freeform.npt) < (::std::numeric_limits::max() / sizeof(double)))) { int n, i; n = drawobj->u.freeform.npt; std::unique_ptr xarr( new double[n+1] ); std::unique_ptr yarr( new double[n+1] ); std::unique_ptr tarr( new double[n+1] ); std::unique_ptr xb; std::unique_ptr yb; std::unique_ptr carr; std::unique_ptr darr; for( i = 0 ; i < n ; i++ ){ xarr[i] = drawobj->u.freeform.pt[i].x; yarr[i] = drawobj->u.freeform.pt[i].y; tarr[i] = i; } xarr[n] = xarr[0]; yarr[n] = yarr[0]; tarr[n] = n; if( !bIsNatural ){ PeriodicSpline(n, tarr.get(), xarr.get(), xb, carr, darr); // prevent memory leak carr.reset(); darr.reset(); PeriodicSpline(n, tarr.get(), yarr.get(), yb, carr, darr); } else{ NaturalSpline(n, tarr.get(), xarr.get(), xb, carr, darr); // prevent memory leak carr.reset(); darr.reset(); NaturalSpline(n, tarr.get(), yarr.get(), yb, carr, darr); } oustr.append( "M" + OUString::number(WTSM(xarr[0])) + " " + OUString::number(WTSM(yarr[0])) + "C" + OUString::number(WTSM(xarr[0] + xb[0]/3)) + " " + OUString::number(WTSM(yarr[0] + yb[0]/3))); for( i = 1 ; i < n ; i++ ){ if( i == n -1 ){ oustr.append( " " + OUString::number(WTSM(xarr[i] - xb[i]/3)) + " " + OUString::number(WTSM(yarr[i] - yb[i]/3)) + " " + OUString::number(WTSM(xarr[i])) + " " + OUString::number(WTSM(yarr[i])) + "z"); } else{ oustr.append( " " + OUString::number(WTSM(xarr[i] - xb[i]/3)) + " " + OUString::number(WTSM(yarr[i] - yb[i]/3)) + " " + OUString::number(WTSM(xarr[i])) + " " + OUString::number(WTSM(yarr[i])) + " " + OUString::number(WTSM(xarr[i] + xb[i]/3)) + " " + OUString::number(WTSM(yarr[i] + yb[i]/3))); } } } mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, oustr.makeStringAndClear()); startEl(u"draw:path"_ustr); mxList->clear(); // As Textbox if( drawobj->property.flag >> 19 & 0x01 && drawobj->property.pPara ) { HWPPara *pPara = drawobj->property.pPara; while(pPara) { make_text_p1( pPara, false ); pPara = pPara->Next(); } } endEl(u"draw:path"_ustr); break; } case HWPDO_CLOSED_FREEFORM: case HWPDO_FREEFORM: /* polygon */ { bool bIsPolygon = false; mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA, OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm"); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm"); mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.w )) + "mm"); mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.h )) + "mm"); mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, "0 0 " + OUString::number(WTSM(drawobj->extent.w)) + " " + OUString::number(WTSM(drawobj->extent.h))); OUStringBuffer oustr; if (drawobj->u.freeform.npt > 0) { oustr.append( OUString::number(WTSM(drawobj->u.freeform.pt[0].x)) + "," + OUString::number(WTSM(drawobj->u.freeform.pt[0].y))); int i; for (i = 1; i < drawobj->u.freeform.npt ; i++) { oustr.append( " " + OUString::number(WTSM(drawobj->u.freeform.pt[i].x)) + "," + OUString::number(WTSM(drawobj->u.freeform.pt[i].y))); } if( drawobj->u.freeform.pt[0].x == drawobj->u.freeform.pt[i-1].x && drawobj->u.freeform.pt[0].y == drawobj->u.freeform.pt[i-1].y ) { bIsPolygon = true; } } mxList->addAttribute(u"draw:points"_ustr, sXML_CDATA, oustr.makeStringAndClear()); if( drawobj->property.fill_color <= 0xffffff || drawobj->property.pattern_type != 0) { bIsPolygon = true; } if(bIsPolygon) { startEl(u"draw:polygon"_ustr); mxList->clear(); if( drawobj->property.flag >> 19 & 0x01 && // As Textbox drawobj->property.pPara ) { HWPPara *pPara = drawobj->property.pPara; // parsePara(pPara); while(pPara) { make_text_p1( pPara, false ); pPara = pPara->Next(); } } endEl(u"draw:polygon"_ustr); } else { startEl(u"draw:polyline"_ustr); mxList->clear(); if( drawobj->property.flag >> 19 & 0x01 && // As Textbox drawobj->property.pPara ) { HWPPara *pPara = drawobj->property.pPara; //parsePara(pPara); while(pPara) { make_text_p1( pPara, false ); pPara = pPara->Next(); } } endEl(u"draw:polyline"_ustr); } break; } case HWPDO_TEXTBOX: if( !bIsRotate ) { mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA, OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm"); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm"); } mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.w )) + "mm"); mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA, OUString::number (WTMM( drawobj->extent.h )) + "mm"); if( drawobj->property.flag & 0x01 ) { int value = drawobj->extent.w < drawobj->extent.h ? drawobj->extent.w : drawobj->extent.h ; mxList->addAttribute(u"draw:corner-radius"_ustr, sXML_CDATA, OUString::number (WTMM( value/10 )) + "mm"); } else if( drawobj->property.flag & 0x04 ) { int value = drawobj->extent.w < drawobj->extent.h ? drawobj->extent.w : drawobj->extent.h ; mxList->addAttribute(u"draw:corner-radius"_ustr, sXML_CDATA, OUString::number (WTMM( value / 2)) + "mm"); } startEl(u"draw:text-box"_ustr); mxList->clear(); HWPPara *pPara = drawobj->u.textbox.h; //parsePara(pPara); while(pPara) { make_text_p1( pPara, false ); pPara = pPara->Next(); } endEl(u"draw:text-box"_ustr); break; } } mxList->clear(); drawobj = drawobj->next.get(); } } void HwpReader::makeLine() { mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Horizontal Line"_ustr); startEl(u"text:p"_ustr); mxList->clear(); } /** * Input-comment-hidden description: shows a hidden explanation to the users. * Parse out only strings, but it may contain paragraphs. */ void HwpReader::makeHidden(Hidden * hbox) { hchar_string str; int res; hchar dest[3]; mxList->addAttribute(u"text:condition"_ustr, sXML_CDATA, u""_ustr); mxList->addAttribute(u"text:string-value"_ustr, sXML_CDATA, u""_ustr); startEl(u"text:hidden-text"_ustr); mxList->clear(); HWPPara *para = !hbox->plist.empty() ? hbox->plist.front().get() : nullptr; while (para) { for (const auto& box : para->hhstr) { if (!box->hh) break; res = hcharconv(box->hh, dest, UNICODE); for( int j = 0 ; j < res ; j++ ) { str.push_back(dest[j]); } } para = para->Next(); } makeChars(str); endEl(u"text:hidden-text"_ustr); } /** * Converts footnote to text:footnote, endnote to text:endnote */ void HwpReader::makeFootnote(Footnote * hbox) { if (hbox->type) { mxList->addAttribute(u"text:id"_ustr, sXML_CDATA, "edn" + OUString::number(hbox->number)); startEl(u"text:endnote"_ustr); mxList->clear(); mxList->addAttribute(u"text:label"_ustr, sXML_CDATA, OUString::number(hbox->number)); startEl(u"text:endnote-citation"_ustr); mxList->clear(); chars(OUString::number(hbox->number)); endEl(u"text:endnote-citation"_ustr); startEl(u"text:endnote-body"_ustr); if (!hbox->plist.empty()) parsePara(hbox->plist.front().get()); endEl(u"text:endnote-body"_ustr); endEl(u"text:endnote"_ustr); } else { mxList->addAttribute(u"text:id"_ustr, sXML_CDATA, "ftn" + OUString::number(hbox->number)); startEl(u"text:footnote"_ustr); mxList->clear(); mxList->addAttribute(u"text:label"_ustr, sXML_CDATA, OUString::number(hbox->number)); startEl(u"text:footnote-citation"_ustr); mxList->clear(); chars(OUString::number(hbox->number)); endEl(u"text:footnote-citation"_ustr); startEl(u"text:footnote-body"_ustr); if (!hbox->plist.empty()) parsePara(hbox->plist.front().get()); endEl(u"text:footnote-body"_ustr); endEl(u"text:footnote"_ustr); } } /** * page/footnote/endnote/picture/table/formula number */ void HwpReader::makeAutoNum(AutoNum const * hbox) { switch (hbox->type) { case PGNUM_AUTO: startEl(u"text:page-number"_ustr); chars(OUString::number(hbox->number)); endEl(u"text:page-number"_ustr); break; case FNNUM_AUTO: break; case ENNUM_AUTO: break; case EQUNUM_AUTO: case PICNUM_AUTO: mxList->addAttribute(u"text:ref-name"_ustr,sXML_CDATA, "refIllustration" + OUString::number(hbox->number)); mxList->addAttribute(u"text:name"_ustr,sXML_CDATA, u"Illustration"_ustr); mxList->addAttribute(u"style:num-format"_ustr,sXML_CDATA, u"1"_ustr); startEl(u"text:sequence"_ustr); chars(OUString::number(hbox->number)); endEl(u"text:sequence"_ustr); break; case TBLNUM_AUTO: mxList->addAttribute(u"text:ref-name"_ustr,sXML_CDATA, "refTable" + OUString::number(hbox->number)); mxList->addAttribute(u"text:name"_ustr,sXML_CDATA, u"Table"_ustr); mxList->addAttribute(u"style:num-format"_ustr,sXML_CDATA, u"1"_ustr); startEl(u"text:sequence"_ustr); chars(OUString::number(hbox->number)); endEl(u"text:sequence"_ustr); break; } } void HwpReader::makeShowPageNum() { ShowPageNum *hbox = d->pPn; int nPos = 0; if( hbox->where == 1 || hbox->where == 4 ) nPos = 1; else if( hbox->where == 2 || hbox->where == 5 ) nPos = 2; else if( hbox->where == 3 || hbox->where == 6 ) nPos = 3; else /* should not exist in this case. */ { if( d->nPnPos == 1 ) nPos = 1; else if( d->nPnPos == 3 ) nPos = 3; } mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "PNBox" + OUString::number(nPos)); mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, "PageNumber" + OUString::number(nPos)); mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr); mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, u"0cm"_ustr); mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, u"2.0cm"_ustr); mxList->addAttribute(u"fo:min-height"_ustr, sXML_CDATA, u"0.5cm"_ustr); startEl(u"draw:text-box"_ustr); mxList->clear(); mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, "PNPara" + OUString::number(nPos)); startEl(u"text:p"_ustr); mxList->clear(); if( hbox->shape > 2 ) chars(u"- "_ustr); if( hbox->shape % 3 == 0 ) mxList->addAttribute(u"style:num-format"_ustr, sXML_CDATA, u"1"_ustr); else if( hbox->shape % 3 == 1 ) mxList->addAttribute(u"style:num-format"_ustr, sXML_CDATA, u"I"_ustr); else mxList->addAttribute(u"style:num-format"_ustr, sXML_CDATA, u"i"_ustr); mxList->addAttribute(u"text:select-page"_ustr, sXML_CDATA, u"current"_ustr); startEl(u"text:page-number"_ustr); mxList->clear(); chars(u"2"_ustr); endEl(u"text:page-number"_ustr); if( hbox->shape > 2 ) chars(u" -"_ustr); endEl(u"text:p"_ustr); endEl(u"draw:text-box"_ustr); } /** * mail merge operation using hwp addressbook and hwp data form. * not support operation in OO writer. */ void HwpReader::makeMailMerge(MailMerge *) { hchar_string const boxstr = MailMerge::GetString(); chars(hstr2OUString(boxstr.c_str())); } void HwpReader::makeOutline(Outline const * hbox) { if( hbox->kind == 1 ) chars( hbox->GetUnicode() ); } void HwpReader::parsePara(HWPPara * para) { bool bParaStart = false; while (para) { if( para->nch == 1) { if( !bParaStart ) { mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, getPStyleName(para->GetParaShape().index)); startEl(u"text:p"_ustr); mxList->clear(); } if( d->bFirstPara && d->bInBody ) { /* for HWP's Bookmark */ mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, sBeginOfDoc); startEl(u"text:bookmark"_ustr); mxList->clear(); endEl(u"text:bookmark"_ustr); d->bFirstPara = false; } if( d->bInHeader ) { makeShowPageNum(); d->bInHeader = false; } endEl(u"text:p"_ustr); } else { if (!para->ctrlflag) { if (para->contain_cshape) make_text_p1(para, bParaStart); else make_text_p0(para, bParaStart); } else make_text_p3(para, bParaStart); } bParaStart = false; para = para->Next(); } } void HwpReader::startEl(const OUString& el) { if (m_rxDocumentHandler) m_rxDocumentHandler->startElement(el, mxList); } void HwpReader::endEl(const OUString& el) { if (m_rxDocumentHandler) m_rxDocumentHandler->endElement(el); } void HwpReader::chars(const OUString& s) { if (m_rxDocumentHandler) m_rxDocumentHandler->characters(s); } namespace { constexpr OUStringLiteral IMPLEMENTATION_NAME = u"com.sun.comp.hwpimport.HwpImportFilter"; constexpr OUString SERVICE_NAME1 = u"com.sun.star.document.ImportFilter"_ustr; constexpr OUString SERVICE_NAME2 = u"com.sun.star.document.ExtendedTypeDetection"_ustr; class HwpImportFilter : public WeakImplHelper< XFilter, XImporter, XServiceInfo, XExtendedFilterDetection > { public: explicit HwpImportFilter(const Reference< XComponentContext >& ); public: // XFilter virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& aDescriptor ) override; virtual void SAL_CALL cancel() override; // XImporter virtual void SAL_CALL setTargetDocument( const Reference< XComponent >& xDoc) override; // XServiceInfo OUString SAL_CALL getImplementationName() override; Sequence< OUString > SAL_CALL getSupportedServiceNames() override; sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override; //XExtendedFilterDetection virtual OUString SAL_CALL detect( css::uno::Sequence< css::beans::PropertyValue >& rDescriptor ) override; private: rtl::Reference< HwpReader > rFilter; Reference< XImporter > rImporter; }; HwpImportFilter::HwpImportFilter(const Reference< XComponentContext >& rxContext) { Reference xHandler(rxContext->getServiceManager()->createInstanceWithContext(WRITER_IMPORTER_NAME, rxContext), UNO_QUERY); rFilter = new HwpReader; rFilter->setDocumentHandler( xHandler ); rImporter.set(xHandler, UNO_QUERY); } sal_Bool HwpImportFilter::filter( const Sequence< PropertyValue >& aDescriptor ) { // delegate to IchitaroImporter return rFilter->filter( aDescriptor ); } void HwpImportFilter::cancel() { rFilter->cancel(); } void HwpImportFilter::setTargetDocument( const Reference< XComponent >& xDoc ) { // delegate rImporter->setTargetDocument( xDoc ); } OUString HwpImportFilter::getImplementationName() { return IMPLEMENTATION_NAME; } sal_Bool HwpImportFilter::supportsService( const OUString& ServiceName ) { return cppu::supportsService(this, ServiceName); } //XExtendedFilterDetection OUString HwpImportFilter::detect( css::uno::Sequence< css::beans::PropertyValue >& rDescriptor ) { OUString sTypeName; utl::MediaDescriptor aDescriptor(rDescriptor); aDescriptor.addInputStream(); Reference< XInputStream > xInputStream( aDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM], UNO_QUERY); if (xInputStream.is()) { Sequence< sal_Int8 > aData; sal_Int32 nLen = HWPIDLen; if ( nLen == xInputStream->readBytes(aData, nLen) && detect_hwp_version(reinterpret_cast(aData.getConstArray())) ) { sTypeName = "writer_MIZI_Hwp_97"; } } return sTypeName; } Sequence< OUString> HwpImportFilter::getSupportedServiceNames() { return { SERVICE_NAME1, SERVICE_NAME2 }; } } extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface* hwpfilter_HwpImportFilter_get_implementation( css::uno::XComponentContext* context, css::uno::Sequence const&) { return cppu::acquire(new HwpImportFilter(context)); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */