summaryrefslogtreecommitdiffstats
path: root/hwpfilter/source/hwpreader.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'hwpfilter/source/hwpreader.cxx')
-rw-r--r--hwpfilter/source/hwpreader.cxx4816
1 files changed, 4816 insertions, 0 deletions
diff --git a/hwpfilter/source/hwpreader.cxx b/hwpfilter/source/hwpreader.cxx
new file mode 100644
index 000000000..87c2e6412
--- /dev/null
+++ b/hwpfilter/source/hwpreader.cxx
@@ -0,0 +1,4816 @@
+/* -*- 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 <deque>
+#include <memory>
+#include <string_view>
+
+#include "hwpreader.hxx"
+#include <cmath>
+
+#include <o3tl/safeint.hxx>
+#include <osl/diagnose.h>
+#include <tools/stream.hxx>
+#include <basegfx/numeric/ftools.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+#include <unotools/configmgr.hxx>
+
+#include "fontmap.hxx"
+#include "formula.h"
+#include "cspline.h"
+#include "datecode.h"
+
+#include <iostream>
+#include <locale.h>
+#include <sal/types.h>
+#include <rtl/character.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <sal/log.hxx>
+
+// xmloff/xmlkyd.hxx
+constexpr OUStringLiteral sXML_CDATA = u"CDATA";
+
+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 OUStringLiteral sBeginOfDoc(u"[\uBB38\uC11C\uC758 \uCC98\uC74C]");
+ // 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<HStream> 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<int>(nRead));
+ }
+
+ rtl::Reference<HwpReader> hwpreader(new HwpReader);
+ return hwpreader->importHStream(std::move(stream));
+ }
+ catch (...)
+ {
+ }
+ return false;
+}
+
+bool HwpReader::importHStream(std::unique_ptr<HStream> stream)
+{
+ if (hwpfile.ReadHwpFile(std::move(stream)))
+ return false;
+
+ if (m_rxDocumentHandler.is())
+ m_rxDocumentHandler->startDocument();
+
+ mxList->addAttribute("office:class", sXML_CDATA, "text");
+ mxList->addAttribute("office:version", sXML_CDATA, "0.9");
+
+ mxList->addAttribute("xmlns:office", "CDATA", "http://openoffice.org/2000/office");
+ mxList->addAttribute("xmlns:style", "CDATA", "http://openoffice.org/2000/style");
+ mxList->addAttribute("xmlns:text", "CDATA", "http://openoffice.org/2000/text");
+ mxList->addAttribute("xmlns:table", "CDATA", "http://openoffice.org/2000/table");
+ mxList->addAttribute("xmlns:draw", "CDATA", "http://openoffice.org/2000/drawing");
+ mxList->addAttribute("xmlns:fo", "CDATA", "http://www.w3.org/1999/XSL/Format");
+ mxList->addAttribute("xmlns:xlink", "CDATA", "http://www.w3.org/1999/xlink");
+ mxList->addAttribute("xmlns:dc", "CDATA", "http://purl.org/dc/elements/1.1/");
+ mxList->addAttribute("xmlns:meta", "CDATA", "http://openoffice.org/2000/meta");
+ mxList->addAttribute("xmlns:number", "CDATA", "http://openoffice.org/2000/datastyle");
+ mxList->addAttribute("xmlns:svg", "CDATA", "http://www.w3.org/2000/svg");
+ mxList->addAttribute("xmlns:chart", "CDATA", "http://openoffice.org/2000/chart");
+ mxList->addAttribute("xmlns:dr3d", "CDATA", "http://openoffice.org/2000/dr3d");
+ mxList->addAttribute("xmlns:math", "CDATA", "http://www.w3.org/1998/Math/MathML");
+ mxList->addAttribute("xmlns:form", "CDATA", "http://openoffice.org/2000/form");
+ mxList->addAttribute("xmlns:script", "CDATA", "http://openoffice.org/2000/script");
+
+ startEl("office:document");
+ mxList->clear();
+
+ makeMeta();
+ makeStyles();
+ makeAutoStyles();
+ makeMasterStyles();
+ makeBody();
+
+ endEl("office:document");
+
+ 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<HStream> 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<const byte *>(aBuffer.getConstArray()), nRead );
+ nTotal += nRead;
+ }
+
+ if( nTotal == 0 ) return false;
+
+ return importHStream(std::move(stream));
+}
+
+/**
+ * make office:body
+ */
+void HwpReader::makeBody()
+{
+ startEl("office:body");
+ makeTextDecls();
+ HWPPara *hwppara = hwpfile.GetFirstPara();
+ d->bInBody = true;
+ parsePara(hwppara);
+ endEl("office:body");
+ d->bInBody = false;
+}
+
+
+/**
+ * make text decls
+ */
+void HwpReader::makeTextDecls()
+{
+ startEl("text:sequence-decls");
+ mxList->addAttribute("text:display-outline-level", sXML_CDATA, "0");
+ mxList->addAttribute("text:name", sXML_CDATA, "Illustration");
+ startEl("text:sequence-decl");
+ mxList->clear();
+ endEl("text:sequence-decl");
+ mxList->addAttribute("text:display-outline-level", sXML_CDATA, "0");
+ mxList->addAttribute("text:name", sXML_CDATA, "Table");
+ startEl("text:sequence-decl");
+ mxList->clear();
+ endEl("text:sequence-decl");
+ mxList->addAttribute("text:display-outline-level", sXML_CDATA, "0");
+ mxList->addAttribute("text:name", sXML_CDATA, "Text");
+ startEl("text:sequence-decl");
+ mxList->clear();
+ endEl("text:sequence-decl");
+ mxList->addAttribute("text:display-outline-level", sXML_CDATA, "0");
+ mxList->addAttribute("text:name", sXML_CDATA, "Drawing");
+ startEl("text:sequence-decl");
+ mxList->clear();
+ endEl("text:sequence-decl");
+ endEl("text:sequence-decls");
+}
+
+
+/**
+ * make office:meta
+ * Completed
+ */
+void HwpReader::makeMeta()
+{
+ HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
+
+ startEl("office:meta");
+
+ if (hwpinfo.summary.title[0])
+ {
+ startEl("dc:title");
+ chars(hstr2OUString(hwpinfo.summary.title));
+ endEl("dc:title");
+ }
+
+ if (hwpinfo.summary.subject[0])
+ {
+ startEl("dc:subject");
+ chars(hstr2OUString(hwpinfo.summary.subject));
+ endEl("dc:subject");
+ }
+
+ if (hwpinfo.summary.author[0])
+ {
+ startEl("meta:initial-creator");
+ chars(hstr2OUString(hwpinfo.summary.author));
+ endEl("meta:initial-creator");
+ }
+
+ 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;
+ }
+ sprintf(d->buf,"%d-%02d-%02dT%02d:%02d:00",year,month,day,hour,minute);
+
+ startEl("meta:creation-date");
+ chars( OUString::createFromAscii(d->buf));
+ endEl("meta:creation-date");
+ }
+
+ if (hwpinfo.summary.keyword[0][0] || hwpinfo.summary.etc[0][0])
+ {
+ startEl("meta:keywords");
+ if (hwpinfo.summary.keyword[0][0])
+ {
+ startEl("meta:keyword");
+ chars(hstr2OUString(hwpinfo.summary.keyword[0]));
+ endEl("meta:keyword");
+ }
+ if (hwpinfo.summary.keyword[1][0])
+ {
+ startEl("meta:keyword");
+ chars(hstr2OUString(hwpinfo.summary.keyword[1]));
+ endEl("meta:keyword");
+ }
+ if (hwpinfo.summary.etc[0][0])
+ {
+ startEl("meta:keyword");
+ chars(hstr2OUString(hwpinfo.summary.etc[0]));
+ endEl("meta:keyword");
+ }
+ if (hwpinfo.summary.etc[1][0])
+ {
+ startEl("meta:keyword");
+ chars(hstr2OUString(hwpinfo.summary.etc[1]));
+ endEl("meta:keyword");
+ }
+ if (hwpinfo.summary.etc[2][0])
+ {
+ startEl("meta:keyword");
+ chars(hstr2OUString(hwpinfo.summary.etc[2]));
+ endEl("meta:keyword");
+ }
+ endEl("meta:keywords");
+ }
+ endEl("office:meta");
+}
+
+
+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( "draw:name", sXML_CDATA, "LineType" + OUString::number(hdo->index));
+ mxList->addAttribute( "draw:style", sXML_CDATA, "round");
+ mxList->addAttribute( "draw:dots1", sXML_CDATA, "1");
+ mxList->addAttribute( "draw:dots1-length", sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots1 * WTMM(prop->line_width) ) + "cm");
+ if( prop->line_pstyle == 3 )
+ {
+ mxList->addAttribute( "draw:dots2", sXML_CDATA, "1");
+ mxList->addAttribute( "draw:dots2-length", sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width) ) + "cm");
+ }
+ else if( prop->line_pstyle == 4 )
+ {
+ mxList->addAttribute( "draw:dots2", sXML_CDATA, "2");
+ mxList->addAttribute( "draw:dots2-length", sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width)) + "cm");
+ }
+ mxList->addAttribute( "draw:distance", sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].distance * WTMM(prop->line_width)) + "cm");
+ startEl("draw:stroke-dash");
+ mxList->clear();
+ endEl("draw:stroke-dash");
+ }
+
+ 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("draw:name", sXML_CDATA,
+ OUString::createFromAscii(ArrowShape[prop->line_tstyle].name));
+ if( prop->line_tstyle == 1 )
+ {
+ mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 20 30");
+ mxList->addAttribute("svg:d", sXML_CDATA, "m10 0-10 30h20z");
+ }
+ else if( prop->line_tstyle == 2 )
+ {
+ mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 1122 2243");
+ mxList->addAttribute("svg:d", sXML_CDATA, "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");
+ }
+ else if( prop->line_tstyle == 3 )
+ {
+ mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 30 30");
+ mxList->addAttribute("svg:d", sXML_CDATA, "m0 0h30v30h-30z");
+ }
+ startEl("draw:marker");
+ mxList->clear();
+ endEl("draw:marker");
+ }
+ 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("draw:name", sXML_CDATA,
+ OUString::createFromAscii(ArrowShape[prop->line_hstyle].name));
+ if( prop->line_hstyle == 1 )
+ {
+ mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 20 30");
+ mxList->addAttribute("svg:d", sXML_CDATA, "m10 0-10 30h20z");
+ }
+ else if( prop->line_hstyle == 2 )
+ {
+ mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 1122 2243");
+ mxList->addAttribute("svg:d", sXML_CDATA, "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");
+ }
+ else if( prop->line_hstyle == 3 )
+ {
+ mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 20 20");
+ mxList->addAttribute("svg:d", sXML_CDATA, "m0 0h20v20h-20z");
+ }
+ startEl("draw:marker");
+ mxList->clear();
+ endEl("draw:marker");
+ }
+ }
+
+ if( hdo->type != HWPDO_LINE )
+ {
+ if( prop->flag >> 18 & 0x01 )
+ {
+ mxList->addAttribute( "draw:name", 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( "xlink:href", sXML_CDATA,
+ hstr2OUString(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(prop->szPatternFile).c_str())).c_str()));
+ mxList->addAttribute( "xlink:type", sXML_CDATA, "simple");
+ mxList->addAttribute( "xlink:show", sXML_CDATA, "embed");
+ mxList->addAttribute( "xlink:actuate", sXML_CDATA, "onLoad");
+ }
+
+ startEl("draw:fill-image");
+ mxList->clear();
+ if (emp)
+ {
+ startEl("office:binary-data");
+ chars(base64_encode_string(emp->data.get(), emp->size));
+ endEl("office:binary-data");
+ }
+ endEl("draw:fill-image");
+ }
+/* 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( "draw:name", sXML_CDATA, "Grad" + OUString::number(hdo->index));
+ switch( prop->gstyle )
+ {
+ case 1 :
+ if( prop->center_y == 50 )
+ mxList->addAttribute( "draw:style", sXML_CDATA, "axial");
+ else
+ mxList->addAttribute( "draw:style", sXML_CDATA, "linear");
+ break;
+ case 2:
+ case 3:
+ mxList->addAttribute( "draw:style", sXML_CDATA, "radial");
+ break;
+ case 4:
+ mxList->addAttribute( "draw:style", sXML_CDATA, "square");
+ break;
+ default:
+ mxList->addAttribute( "draw:style", sXML_CDATA, "linear");
+ break;
+ }
+ mxList->addAttribute( "draw:cx", sXML_CDATA, OUString::number(prop->center_x) + "%");
+ mxList->addAttribute( "draw:cy", 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( "draw:start-color", sXML_CDATA, rgb2str( prop->tocolor ));
+ mxList->addAttribute( "draw:end-color", sXML_CDATA, rgb2str( prop->fromcolor ));
+ }
+ else
+ {
+ mxList->addAttribute( "draw:start-color", sXML_CDATA, rgb2str( prop->fromcolor ));
+ mxList->addAttribute( "draw:end-color", sXML_CDATA, rgb2str( prop->tocolor ));
+ }
+ }
+ else
+ {
+ mxList->addAttribute( "draw:start-color", sXML_CDATA,rgb2str( prop->tocolor ));
+ mxList->addAttribute( "draw:end-color", sXML_CDATA,rgb2str( prop->fromcolor ));
+ }
+ if( prop->angle > 0 && ( prop->gstyle == 1 || prop->gstyle == 4))
+ {
+ int angle = 1800 - prop->angle * 10;
+ mxList->addAttribute( "draw:angle", sXML_CDATA, OUString::number(angle));
+ }
+ startEl("draw:gradient");
+ mxList->clear();
+ endEl("draw:gradient");
+ }
+ /* hatch */
+ else if( prop->pattern_type >> 24 & 0x01 )
+ {
+ int type = prop->pattern_type & 0xffffff;
+ mxList->addAttribute( "draw:name", sXML_CDATA, "Hatch" + OUString::number(hdo->index));
+ if( type < 4 )
+ mxList->addAttribute( "draw:style", sXML_CDATA, "single" );
+ else
+ mxList->addAttribute( "draw:style", sXML_CDATA, "double" );
+ mxList->addAttribute( "draw:color", sXML_CDATA, rgb2str( static_cast<int32_t>(prop->pattern_color) ));
+ mxList->addAttribute( "draw:distance", sXML_CDATA, "0.12cm");
+ switch( type )
+ {
+ case 0 :
+ case 4 :
+ mxList->addAttribute( "draw:rotation", sXML_CDATA, "0");
+ break;
+ case 1 :
+ mxList->addAttribute( "draw:rotation", sXML_CDATA, "900");
+ break;
+ case 2 :
+ mxList->addAttribute( "draw:rotation", sXML_CDATA, "1350");
+ break;
+ case 3 :
+ case 5 :
+ mxList->addAttribute( "draw:rotation", sXML_CDATA, "450");
+ break;
+ }
+ startEl("draw:hatch");
+ mxList->clear();
+ endEl("draw:hatch");
+ }
+ }
+ hdo = hdo->next.get();
+ }
+}
+
+
+void HwpReader::makeStyles()
+{
+ HWPStyle& hwpstyle = hwpfile.GetHWPStyle();
+
+ startEl("office:styles");
+
+ int i;
+ for (i = 0; i < hwpfile.getFBoxStyleCount(); i++)
+ {
+ if( hwpfile.getFBoxStyle(i)->boxtype == 'D' )
+ {
+ makeDrawMiscStyle(static_cast<HWPDrawingObject *>(hwpfile.getFBoxStyle(i)->cell) );
+ }
+ }
+
+ mxList->addAttribute("style:name", sXML_CDATA, "Standard");
+ mxList->addAttribute("style:family", sXML_CDATA, "paragraph");
+ mxList->addAttribute("style:class", sXML_CDATA, "text");
+ startEl("style:style");
+ mxList->clear();
+
+ mxList->addAttribute("fo:line-height", sXML_CDATA, "160%");
+ mxList->addAttribute("fo:text-align", sXML_CDATA, "justify");
+ startEl("style:properties");
+ mxList->clear();
+ startEl("style:tab-stops");
+
+ for( i = 1 ; i < 40 ; i++)
+ {
+ mxList->addAttribute("style:position", sXML_CDATA,
+ OUString::number( WTI(1000 * i)) + "inch");
+ startEl("style:tab-stop");
+ mxList->clear();
+ endEl("style:tab-stop");
+ }
+ endEl("style:tab-stops");
+ endEl("style:properties");
+
+ endEl("style:style");
+
+ for (int ii = 0; ii < hwpstyle.Num(); ii++)
+ {
+ unsigned char *stylename = reinterpret_cast<unsigned char *>(hwpstyle.GetName(ii));
+ mxList->addAttribute("style:name", sXML_CDATA, hstr2OUString(kstr2hstr(stylename).c_str()));
+ mxList->addAttribute("style:family", sXML_CDATA, "paragraph");
+ mxList->addAttribute("style:parent-style-name", sXML_CDATA, "Standard");
+
+ startEl("style:style");
+
+ mxList->clear();
+
+ parseCharShape(hwpstyle.GetCharShape(ii));
+ parseParaShape(hwpstyle.GetParaShape(ii));
+
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+
+ endEl("style:style");
+ }
+
+ {
+ mxList->addAttribute( "style:name", sXML_CDATA, "Header");
+ mxList->addAttribute( "style:family", sXML_CDATA, "paragraph");
+ mxList->addAttribute( "style:parent-style-name", sXML_CDATA, "Standard");
+ mxList->addAttribute( "style:class", sXML_CDATA, "extra");
+ startEl("style:style");
+ mxList->clear();
+ endEl("style:style");
+ }
+
+ {
+ mxList->addAttribute( "style:name", sXML_CDATA, "Footer");
+ mxList->addAttribute( "style:family", sXML_CDATA, "paragraph");
+ mxList->addAttribute( "style:parent-style-name", sXML_CDATA, "Standard");
+ mxList->addAttribute( "style:class", sXML_CDATA, "extra");
+ startEl("style:style");
+ mxList->clear();
+
+ endEl("style:style");
+ }
+
+ if( hwpfile.linenumber > 0)
+ {
+ mxList->addAttribute( "style:name", sXML_CDATA, "Horizontal Line");
+ mxList->addAttribute( "style:family", sXML_CDATA, "paragraph");
+ mxList->addAttribute( "style:parent-style-name", sXML_CDATA, "Standard");
+ mxList->addAttribute( "style:class", sXML_CDATA, "html");
+ startEl("style:style");
+ mxList->clear();
+ mxList->addAttribute( "fo:font-size", sXML_CDATA, "6pt");
+ mxList->addAttribute( "fo:margin-top", sXML_CDATA, "0cm");
+ mxList->addAttribute( "fo:margin-bottom", sXML_CDATA, "0cm");
+ mxList->addAttribute( "style:border-line-width-bottom", sXML_CDATA, "0.02cm 0.035cm 0.002cm");
+ mxList->addAttribute( "fo:padding", sXML_CDATA, "0cm");
+ mxList->addAttribute( "fo:border-bottom", sXML_CDATA, "0.039cm double #808080");
+ mxList->addAttribute( "text:number-lines", sXML_CDATA, "false");
+ mxList->addAttribute( "text:line-number", sXML_CDATA, "0");
+ mxList->addAttribute("fo:line-height", sXML_CDATA, "100%");
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:style");
+ }
+
+ HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
+
+ mxList->addAttribute("text:num-suffix", sXML_CDATA, ")");
+ mxList->addAttribute("text:num-format", sXML_CDATA, "1");
+ if( hwpinfo.beginfnnum != 1)
+ mxList->addAttribute("text:offset", sXML_CDATA, OUString::number(hwpinfo.beginfnnum - 1));
+ startEl("text:footnotes-configuration");
+ mxList->clear();
+ endEl("text:footnotes-configuration");
+
+ endEl("office:styles");
+}
+
+
+/**
+ * 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("office:automatic-styles");
+
+ 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<HWPDrawingObject *>(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("style:name", sXML_CDATA, "PNPara" + OUString::number(i));
+ mxList->addAttribute("style:family", sXML_CDATA, "paragraph");
+ mxList->addAttribute("style:parent-style-name", sXML_CDATA, "Standard");
+ startEl("style:style");
+ mxList->clear();
+ if( i == 1 )
+ mxList->addAttribute("fo:text-align", sXML_CDATA, "start");
+ else if ( i == 2 )
+ mxList->addAttribute("fo:text-align", sXML_CDATA, "center");
+ else if ( i == 3 )
+ mxList->addAttribute("fo:text-align", sXML_CDATA, "end");
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:style");
+
+ mxList->addAttribute("style:name", sXML_CDATA, "PNBox" + OUString::number(i));
+ mxList->addAttribute("style:family", sXML_CDATA, "graphics");
+ startEl("style:style");
+ mxList->clear();
+
+ mxList->addAttribute("fo:margin-top", sXML_CDATA, "0cm");
+ mxList->addAttribute("fo:margin-bottom", sXML_CDATA, "0cm");
+ mxList->addAttribute("style:wrap", sXML_CDATA, "run-through");
+ mxList->addAttribute("style:vertical-pos", sXML_CDATA, "from-top");
+ mxList->addAttribute("style:vertical-rel", sXML_CDATA, "paragraph");
+
+ if( i == 1 )
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "left");
+ else if ( i == 2 )
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "center");
+ else if ( i == 3 )
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "right");
+ mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
+ mxList->addAttribute("fo:padding", sXML_CDATA, "0cm");
+ mxList->addAttribute("stylefamily", sXML_CDATA, "graphics");
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:style");
+ }
+
+ for (i = 0; i < hwpfile.getDateFormatCount(); i++)
+ makeDateFormat(hwpfile.getDateCode(i));
+
+ makePageStyle();
+
+ endEl("office:automatic-styles");
+}
+
+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("office:master-styles");
+
+ int i;
+ int nMax = hwpfile.getMaxSettedPage();
+ std::vector<PageSetting> 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 > SAL_MAX_UINT16 && utl::ConfigManager::IsFuzzing())
+ {
+ SAL_WARN("filter.hwp", "too many pages: " << nMax << " clip to " << SAL_MAX_UINT16);
+ nMax = SAL_MAX_UINT16;
+ }
+
+ for( i = 1; i <= nMax ; i++ )
+ {
+ if( i == 1 )
+ mxList->addAttribute("style:name", sXML_CDATA, "Standard");
+ else
+ mxList->addAttribute("style:name", sXML_CDATA, "p" + OUString::number(i));
+ mxList->addAttribute("style:page-master-name", sXML_CDATA,
+ "pm" + OUString::number(hwpfile.GetPageMasterNum(i)));
+ if( i < nMax )
+ mxList->addAttribute("style:next-style-name", sXML_CDATA, "p" + OUString::number(i + 1));
+ mxList->addAttribute("draw:style-name", sXML_CDATA, "master" + OUString::number(i));
+ startEl("style:master-page");
+ 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("style:header");
+ mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
+ startEl("text:p");
+ mxList->clear();
+ endEl("text:p");
+ endEl("style:header");
+
+ startEl("style:footer");
+ mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
+ startEl("text:p");
+ mxList->clear();
+ endEl("text:p");
+ endEl("style:footer");
+
+ endEl("style:master-page");
+
+ continue;
+ }
+// header
+ if( pPage->header )
+ {
+ startEl("style:header");
+ 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("style:header");
+ }
+ if( pPage->header_even )
+ {
+ startEl("style:header");
+ 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("style:header");
+ }
+ /* Will be the default. */
+ else if (pPage->header_odd)
+ {
+ startEl("style:header");
+ mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
+ startEl("text:p");
+ 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("text:p");
+ endEl("style:header");
+ }
+ if( pPage->header_odd )
+ {
+ startEl("style:header-left");
+ 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("style:header-left");
+ }
+ /* Will be the default. */
+ else if (pPage->header_even)
+ {
+ startEl("style:header-left");
+ mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
+ startEl("text:p");
+ 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("text:p");
+ endEl("style:header-left");
+ }
+ if( !pPage->header && !pPage->header_even && !pPage->header_odd )
+ {
+ startEl("style:header");
+ mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
+ startEl("text:p");
+ mxList->clear();
+ if( pPage->pagenumber && (pPage->pagenumber->where < 4 ||
+ pPage->pagenumber->where == 7 ) )
+ {
+ d->pPn = pPage->pagenumber;
+ makeShowPageNum();
+ d->pPn = nullptr;
+ }
+ endEl("text:p");
+ endEl("style:header");
+ }
+// footer
+ if( pPage->footer )
+ {
+ startEl("style:footer");
+ 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("style:footer");
+ }
+ if( pPage->footer_even )
+ {
+ startEl("style:footer");
+ 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("style:footer");
+ }
+ /* Will be the default. */
+ else if (pPage->footer_odd)
+ {
+ startEl("style:footer");
+ mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
+ startEl("text:p");
+ 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("text:p");
+ endEl("style:footer");
+ }
+ if( pPage->footer_odd )
+ {
+ startEl("style:footer-left");
+ 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("style:footer-left");
+ }
+ /* Will be the default. */
+ else if (pPage->footer_even)
+ {
+ startEl("style:footer-left");
+ mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
+ startEl("text:p");
+ 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("text:p");
+ endEl("style:footer-left");
+ }
+ if( !pPage->footer && !pPage->footer_even && !pPage->footer_odd )
+ {
+ startEl("style:footer");
+ mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
+ startEl("text:p");
+ mxList->clear();
+ if( pPage->pagenumber && pPage->pagenumber->where >= 4
+ && pPage->pagenumber->where != 7 )
+ {
+ d->pPn = pPage->pagenumber;
+ makeShowPageNum();
+ d->pPn = nullptr;
+ }
+ endEl("text:p");
+ endEl("style:footer");
+ }
+
+ endEl("style:master-page");
+ }
+ endEl("office:master-styles");
+}
+
+
+/**
+ * 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("fo:font-size", sXML_CDATA, OUString::number(cshape->size / 25) + "pt");
+ mxList->addAttribute("style:font-size-asian", sXML_CDATA, OUString::number(cshape->size / 25) + "pt");
+
+ ::std::string const tmp = hstr2ksstr(kstr2hstr(
+ reinterpret_cast<unsigned char const *>(hwpfont.GetFontName(0, cshape->font[0]))).c_str());
+ double fRatio = 1.0;
+ int size = getRepFamilyName(tmp.c_str(), d->buf, fRatio);
+
+ mxList->addAttribute("fo:font-family", sXML_CDATA,
+ OUString(d->buf, size, RTL_TEXTENCODING_EUC_KR));
+ mxList->addAttribute("style:font-family-asian", sXML_CDATA,
+ OUString(d->buf, size, RTL_TEXTENCODING_EUC_KR));
+
+ mxList->addAttribute("style:text-scale", sXML_CDATA,
+ OUString::number(static_cast<int>(cshape->ratio[0] * fRatio)) + "%");
+
+ double sspace = (cshape->size / 25) * cshape->space[0] / 100.;
+
+ if (sspace != 0.)
+ {
+ mxList->addAttribute("fo:letter-spacing", sXML_CDATA,
+ OUString::number(sspace) + "pt");
+ }
+ if (cshape->color[1] != 0)
+ mxList->addAttribute("fo:color", sXML_CDATA,
+ hcolor2str(cshape->color[1], 100, true));
+ if (cshape->shade != 0)
+ mxList->addAttribute("style:text-background-color", sXML_CDATA,
+ hcolor2str(cshape->color[0], cshape->shade));
+ if (cshape->attr & 0x01)
+ {
+ mxList->addAttribute("fo:font-style", sXML_CDATA, "italic");
+ mxList->addAttribute("style:font-style-asian", sXML_CDATA, "italic");
+ }
+ else{
+ mxList->addAttribute("fo:font-style", sXML_CDATA, "normal");
+ mxList->addAttribute("style:font-style-asian", sXML_CDATA, "normal");
+ }
+ if (cshape->attr >> 1 & 0x01)
+ {
+ mxList->addAttribute("fo:font-weight", sXML_CDATA, "bold");
+ mxList->addAttribute("style:font-weight-asian", sXML_CDATA, "bold");
+ }
+ else{
+ mxList->addAttribute("fo:font-weight", sXML_CDATA, "normal");
+ mxList->addAttribute("style:font-weight-asian", sXML_CDATA, "normal");
+ }
+ if (cshape->attr >> 2 & 0x01)
+ mxList->addAttribute("style:text-underline", sXML_CDATA, "single");
+ if (cshape->attr >> 3 & 0x01)
+ mxList->addAttribute("style:text-outline", sXML_CDATA, "true");
+ if (cshape->attr >> 4 & 0x01)
+ mxList->addAttribute("fo:text-shadow", sXML_CDATA, "1pt 1pt");
+ if (cshape->attr >> 5 & 0x01)
+ mxList->addAttribute("style:text-position", sXML_CDATA, "super 58%");
+ if (cshape->attr >> 6 & 0x01)
+ mxList->addAttribute("style:text-position", sXML_CDATA, "sub 58%");
+
+}
+
+
+/**
+ * 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("fo:margin-left", sXML_CDATA, OUString::number
+ (WTI(pshape->left_margin )) + "inch");
+ if (pshape->right_margin != 0)
+ mxList->addAttribute("fo:margin-right", sXML_CDATA, OUString::number
+ (WTI(pshape->right_margin)) + "inch");
+ if (pshape->pspacing_prev != 0)
+ mxList->addAttribute("fo:margin-top", sXML_CDATA, OUString::number
+ (WTI(pshape->pspacing_prev)) + "inch");
+ if (pshape->pspacing_next != 0)
+ mxList->addAttribute("fo:margin-bottom", sXML_CDATA, OUString::number
+ (WTI(pshape->pspacing_next)) + "inch");
+ if (pshape->indent != 0)
+ mxList->addAttribute("fo:text-indent", sXML_CDATA, OUString::number
+ (WTI(pshape->indent)) + "inch");
+ if (pshape->lspacing != 0)
+ mxList->addAttribute("fo:line-height", sXML_CDATA, OUString::number(pshape->lspacing) + "%");
+
+ const char* align = nullptr;
+
+ switch (static_cast<int>(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("fo:text-align", sXML_CDATA, OUString::createFromAscii(align));
+
+ if (pshape->outline)
+ mxList->addAttribute("fo:border", sXML_CDATA, "0.002cm solid #000000");
+ if( pshape->shade > 0 )
+ {
+ mxList->addAttribute("fo:background-color", sXML_CDATA,
+ hcolor2str(0, pshape->shade));
+ }
+
+ if( pshape->pagebreak & 0x02 || pshape->pagebreak & 0x04)
+ mxList->addAttribute("fo:break-before", sXML_CDATA, "page");
+ else if( pshape->pagebreak & 0x01 )
+ mxList->addAttribute("fo:break-before", sXML_CDATA, "column");
+
+}
+
+
+/**
+ * Make the style of the Paragraph.
+ */
+void HwpReader::makePStyle(ParaShape const * pshape)
+{
+ int nscount = pshape->tabs[MAXTABS -1].type;
+ mxList->addAttribute("style:name", sXML_CDATA, "P" + OUString::number(pshape->index));
+ mxList->addAttribute("style:family", sXML_CDATA, "paragraph");
+ startEl("style:style");
+ mxList->clear();
+ parseParaShape(pshape);
+ if (pshape->cshape)
+ parseCharShape(pshape->cshape.get());
+ startEl("style:properties");
+ mxList->clear();
+
+ if( nscount )
+ {
+ unsigned char tf = 0;
+ startEl("style:tab-stops");
+
+ 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("style:position", 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("style:type", sXML_CDATA, "right");
+ break;
+ case 2:
+ mxList->addAttribute("style:type", sXML_CDATA, "center");
+ break;
+ case 3:
+ mxList->addAttribute("style:type", sXML_CDATA, "char");
+ mxList->addAttribute("style:char", sXML_CDATA, ".");
+ break;
+ }
+ }
+ if( pshape->tabs[i].dot_continue )
+ {
+ tf = 1;
+ mxList->addAttribute("style:leader-char", sXML_CDATA, ".");
+ }
+ startEl("style:tab-stop");
+ mxList->clear();
+ endEl("style:tab-stop");
+
+ if( (pshape->tabs[i].position != 1000 * i ) || tf )
+ {
+ if( !--nscount ) break;
+ }
+ }
+ endEl("style:tab-stops");
+ }
+ endEl("style:properties");
+ endEl("style:style");
+}
+
+
+/**
+ * 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();
+
+ for( int i = 0 ; i < pmCount ; i++ ){
+ mxList->addAttribute("style:name", sXML_CDATA, "pm" + OUString::number(i + 1));
+ startEl("style:page-master");
+ mxList->clear();
+
+
+ switch( hwpinfo.paper.paper_kind )
+ {
+ case 3: // A4
+ if( hwpinfo.paper.paper_direction )
+ {
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "210mm");
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "297mm");
+ }
+ else
+ {
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "210mm");
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "297mm");
+ }
+ break;
+ case 4: // 80 column
+ if( hwpinfo.paper.paper_direction )
+ {
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "8.5inch");
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "11inch");
+ }
+ else
+ {
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "8.5inch");
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "11inch");
+ }
+ break;
+ case 5: // B5
+ if( hwpinfo.paper.paper_direction )
+ {
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "176mm");
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "250mm");
+ }
+ else
+ {
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "176mm");
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "250mm");
+ }
+ break;
+ case 6: // B4
+ if( hwpinfo.paper.paper_direction )
+ {
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "250mm");
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "353mm");
+ }
+ else
+ {
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "250mm");
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "353mm");
+ }
+ break;
+ case 7:
+ if( hwpinfo.paper.paper_direction )
+ {
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "8.5inch");
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "14inch");
+ }
+ else
+ {
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "8.5inch");
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "14inch");
+ }
+ break;
+ case 8:
+ if( hwpinfo.paper.paper_direction )
+ {
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "297mm");
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "420mm");
+ }
+ else
+ {
+ mxList->addAttribute("fo:page-width",sXML_CDATA, "297mm");
+ mxList->addAttribute("fo:page-height",sXML_CDATA, "420mm");
+ }
+ break;
+ case 0:
+ case 1:
+ case 2:
+ default:
+ if( hwpinfo.paper.paper_direction )
+ {
+ mxList->addAttribute("fo:page-width",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.paper_height)) + "inch");
+ mxList->addAttribute("fo:page-height",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.paper_width)) + "inch");
+ }
+ else
+ {
+ mxList->addAttribute("fo:page-width",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.paper_width)) + "inch");
+ mxList->addAttribute("fo:page-height",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.paper_height)) + "inch");
+ }
+ break;
+
+ }
+
+ mxList->addAttribute("style:print-orientation",sXML_CDATA,
+ OUString::createFromAscii(hwpinfo.paper.paper_direction ? "landscape" : "portrait"));
+ if( hwpinfo.beginpagenum != 1)
+ mxList->addAttribute("style:first-page-number",sXML_CDATA, OUString::number(hwpinfo.beginpagenum));
+
+ if( hwpinfo.borderline ){
+ mxList->addAttribute("fo:margin-left",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.left_margin - hwpinfo.bordermargin[0] + hwpinfo.paper.gutter_length)) + "inch");
+ mxList->addAttribute("fo:margin-right",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.right_margin - hwpinfo.bordermargin[1])) + "inch");
+ mxList->addAttribute("fo:margin-top",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.top_margin - hwpinfo.bordermargin[2])) + "inch");
+ mxList->addAttribute("fo:margin-bottom",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.bottom_margin - hwpinfo.bordermargin[3])) + "inch");
+ }
+ else{
+ mxList->addAttribute("fo:margin-left",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.left_margin + hwpinfo.paper.gutter_length)) + "inch");
+ mxList->addAttribute("fo:margin-right",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.right_margin)) + "inch");
+ mxList->addAttribute("fo:margin-top",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.top_margin)) + "inch");
+ mxList->addAttribute("fo:margin-bottom",sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.bottom_margin)) + "inch");
+ }
+
+ switch( hwpinfo.borderline )
+ {
+ case 1:
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 3:
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.002cm dotted #000000");
+ break;
+ case 2:
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4:
+ mxList->addAttribute("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+
+ mxList->addAttribute("fo:padding-left", sXML_CDATA,
+ OUString::number(WTI(hwpinfo.bordermargin[0])) + "inch");
+ mxList->addAttribute("fo:padding-right", sXML_CDATA,
+ OUString::number(WTI(hwpinfo.bordermargin[1])) + "inch");
+ mxList->addAttribute("fo:padding-top", sXML_CDATA,
+ OUString::number(WTI(hwpinfo.bordermargin[2])) + "inch");
+ mxList->addAttribute("fo:padding-bottom", 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("fo:background-color", sXML_CDATA,
+ rgb2str(hwpinfo.back_info.color[0],
+ hwpinfo.back_info.color[1],
+ hwpinfo.back_info.color[2]));
+ }
+ }
+
+ startEl("style:properties");
+ 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<uchar const *>(urltowin(hwpinfo.back_info.filename).c_str())).c_str()));
+#else
+ mxList->addAttribute("xlink:href", sXML_CDATA,
+ hstr2OUString(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(hwpinfo.back_info.filename).c_str())).c_str()));
+#endif
+ mxList->addAttribute("xlink:type", sXML_CDATA, "simple");
+ mxList->addAttribute("xlink:actuate", sXML_CDATA, "onLoad");
+ }
+ if( hwpinfo.back_info.flag >= 2)
+ mxList->addAttribute("style:repeat", sXML_CDATA, "stretch");
+ else if( hwpinfo.back_info.flag == 1 ){
+ mxList->addAttribute("style:repeat", sXML_CDATA, "no-repeat");
+ mxList->addAttribute("style:position", sXML_CDATA, "center");
+ }
+ startEl("style:background-image");
+
+ if( hwpinfo.back_info.type == 2 ){
+ startEl("office:binary-data");
+ mxList->clear();
+ chars(base64_encode_string(reinterpret_cast<unsigned char*>(hwpinfo.back_info.data.data()), hwpinfo.back_info.size));
+ endEl("office:binary-data");
+ }
+ endEl("style:background-image");
+ }
+
+ makeColumns( hwpfile.GetColumnDef(i) );
+
+ endEl("style:properties");
+
+ /* header style */
+ startEl("style:header-style");
+ mxList->addAttribute("svg:height", sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.header_length)) + "inch");
+ mxList->addAttribute("fo:margin-bottom", sXML_CDATA, "0mm");
+
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:header-style");
+
+ /* footer style */
+ startEl("style:footer-style");
+ mxList->addAttribute("svg:height", sXML_CDATA,
+ OUString::number(WTI(hwpinfo.paper.footer_length)) + "inch");
+ mxList->addAttribute("fo:margin-top", sXML_CDATA, "0mm");
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:footer-style");
+
+ /* Footnote style */
+ startEl("style:page-layout-properties");
+
+ mxList->addAttribute("style:distance-before-sep", sXML_CDATA,
+ OUString::number(WTI(hwpinfo.splinetext)) + "inch");
+ mxList->addAttribute("style:distance-after-sep", sXML_CDATA,
+ OUString::number(WTI(hwpinfo.splinefn)) + "inch");
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ if ( hwpinfo.fnlinetype == 2 )
+ mxList->addAttribute("style:width", sXML_CDATA, "15cm");
+ else if ( hwpinfo.fnlinetype == 1)
+ mxList->addAttribute("style:width", sXML_CDATA, "2cm");
+ else if ( hwpinfo.fnlinetype == 3)
+ mxList->addAttribute("style:width", sXML_CDATA, "0cm");
+ else
+ mxList->addAttribute("style:width", sXML_CDATA, "5cm");
+
+ startEl("style:footnote-sep");
+ mxList->clear();
+ endEl("style:footnote-sep");
+
+ endEl("style:page-layout-properties");
+
+ endEl("style:page-master");
+ }
+}
+
+void HwpReader::makeColumns(ColumnDef const *coldef)
+{
+ if( !coldef ) return;
+ mxList->addAttribute("fo:column-count", sXML_CDATA, OUString::number(coldef->ncols));
+ startEl("style:columns");
+ mxList->clear();
+ if( coldef->separator != 0 )
+ {
+ switch( coldef->separator )
+ {
+ case 1: /* thin line */
+ mxList->addAttribute("style:width", sXML_CDATA, "0.02mm");
+ [[fallthrough]];
+ case 3: /* dotted line */
+ mxList->addAttribute("style:style", sXML_CDATA, "dotted");
+ mxList->addAttribute("style:width", sXML_CDATA, "0.02mm");
+ break;
+ case 2: /* thick line */
+ case 4: /* double line */
+ mxList->addAttribute("style:width", sXML_CDATA, "0.35mm");
+ break;
+ case 0: /* None */
+ default:
+ mxList->addAttribute("style:style", sXML_CDATA, "none");
+ break;
+ }
+ startEl("style:column-sep");
+ mxList->clear();
+ endEl("style:column-sep");
+ }
+ double spacing = WTI(coldef->spacing)/ 2. ;
+ for(int ii = 0 ; ii < coldef->ncols ; ii++)
+ {
+ if( ii == 0 )
+ mxList->addAttribute("fo:margin-left", sXML_CDATA, "0mm");
+ else
+ mxList->addAttribute("fo:margin-left", sXML_CDATA,
+ OUString::number( spacing) + "inch");
+ if( ii == ( coldef->ncols -1) )
+ mxList->addAttribute("fo:margin-right", sXML_CDATA,"0mm");
+ else
+ mxList->addAttribute("fo:margin-right", sXML_CDATA,
+ OUString::number( spacing) + "inch");
+ startEl("style:column");
+ mxList->clear();
+ endEl("style:column");
+ }
+ endEl("style:columns");
+}
+
+void HwpReader::makeTStyle(CharShape const * cshape)
+{
+ mxList->addAttribute("style:name", sXML_CDATA, "T" + OUString::number(cshape->index));
+ mxList->addAttribute("style:family", sXML_CDATA, "text");
+ startEl("style:style");
+ mxList->clear();
+ parseCharShape(cshape);
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:style");
+}
+
+
+void HwpReader::makeTableStyle(Table *tbl)
+{
+// table
+ TxtBox *hbox = tbl->box;
+
+ mxList->addAttribute("style:name", sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum));
+ mxList->addAttribute("style:family", sXML_CDATA,"table");
+ startEl("style:style");
+ mxList->clear();
+ mxList->addAttribute("style:width", sXML_CDATA,
+ OUString::number(WTMM(hbox->box_xs)) + "mm");
+ mxList->addAttribute("table:align", sXML_CDATA,"left");
+ mxList->addAttribute("fo:keep-with-next", sXML_CDATA,"false");
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:style");
+
+// column
+ for (size_t i = 0 ; i < tbl->columns.nCount -1 ; i++)
+ {
+ sprintf(d->buf,"Table%d.%c",hbox->style.boxnum, static_cast<char>('A'+i));
+ mxList->addAttribute("style:name", sXML_CDATA, OUString::createFromAscii(d->buf));
+ mxList->addAttribute("style:family", sXML_CDATA,"table-column");
+ startEl("style:style");
+ mxList->clear();
+ mxList->addAttribute("style:column-width", sXML_CDATA,
+ OUString::number(WTMM(tbl->columns.data[i+1] - tbl->columns.data[i])) + "mm");
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:style");
+ }
+
+// row
+ for (size_t i = 0 ; i < tbl->rows.nCount -1 ; i++)
+ {
+ sprintf(d->buf,"Table%d.row%" SAL_PRI_SIZET "u",hbox->style.boxnum, i + 1);
+ mxList->addAttribute("style:name", sXML_CDATA, OUString::createFromAscii(d->buf));
+ mxList->addAttribute("style:family", sXML_CDATA,"table-row");
+ startEl("style:style");
+ mxList->clear();
+ mxList->addAttribute("style:row-height", sXML_CDATA,
+ OUString::number(WTMM(tbl->rows.data[i+1] - tbl->rows.data[i])) + "mm");
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:style");
+ }
+
+// cell
+ for (auto const& tcell : tbl->cells)
+ {
+ sprintf(d->buf,"Table%d.%c%d",hbox->style.boxnum, 'A'+ tcell->nColumnIndex, tcell->nRowIndex +1);
+ mxList->addAttribute("style:name", sXML_CDATA, OUString::createFromAscii(d->buf));
+ mxList->addAttribute("style:family", sXML_CDATA,"table-cell");
+ startEl("style:style");
+ mxList->clear();
+ Cell *cl = tcell->pCell;
+ if( cl->ver_align == 1 )
+ mxList->addAttribute("fo:vertical-align", sXML_CDATA,"middle");
+
+ 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("fo:border", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ }
+ else
+ {
+ switch( cl->linetype[0] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-left", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ switch( cl->linetype[1] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-right", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ switch( cl->linetype[2] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-top", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ switch( cl->linetype[3] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ }
+ if(cl->shade != 0)
+ mxList->addAttribute("fo:background-color", sXML_CDATA,
+ hcolor2str(sal::static_int_cast<uchar>(cl->color),
+ sal::static_int_cast<uchar>(cl->shade)));
+
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+
+ endEl("style:style");
+ }
+}
+
+
+void HwpReader::makeDrawStyle( HWPDrawingObject * hdo, FBoxStyle * fstyle)
+{
+ while( hdo )
+ {
+ mxList->addAttribute("style:name", sXML_CDATA, "Draw" + OUString::number(hdo->index));
+ mxList->addAttribute("style:family", sXML_CDATA, "graphics");
+
+ startEl("style:style");
+ mxList->clear();
+
+ switch (fstyle->txtflow)
+ {
+ case 0:
+ break;
+ case 1:
+ mxList->addAttribute("style:wrap", sXML_CDATA, "run-through");
+ break;
+ case 2:
+ mxList->addAttribute("style:wrap", sXML_CDATA, "dynamic");
+ break;
+ }
+ tools::Long color;
+// invisible line
+ if( hdo->property.line_color > 0xffffff )
+ {
+ mxList->addAttribute("draw:stroke", sXML_CDATA, "none" );
+ }
+ else
+ {
+
+ if( hdo->property.line_pstyle == 0 )
+ mxList->addAttribute("draw:stroke", sXML_CDATA, "solid" );
+ else if( hdo->property.line_pstyle < 5 )
+ {
+ mxList->addAttribute("draw:stroke", sXML_CDATA, "dash" );
+ mxList->addAttribute("draw:stroke-dash", sXML_CDATA, "LineType" + OUString::number(hdo->index));
+ }
+ mxList->addAttribute("svg:stroke-width", sXML_CDATA,
+ OUString::number( WTMM(hdo->property.line_width)) + "mm");
+ mxList->addAttribute("svg:stroke-color", sXML_CDATA,
+ rgb2str(static_cast<int32_t>(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("draw:marker-start", sXML_CDATA,
+ OUString::createFromAscii(ArrowShape[hdo->property.line_tstyle].name) );
+ if( hdo->property.line_width > 100 )
+ mxList->addAttribute("draw:marker-start-width", sXML_CDATA,
+ OUString::number( WTMM(hdo->property.line_width * 3)) + "mm");
+ else if( hdo->property.line_width > 80 )
+ mxList->addAttribute("draw:marker-start-width", sXML_CDATA,
+ OUString::number( WTMM(hdo->property.line_width * 4)) + "mm");
+ else if( hdo->property.line_width > 60 )
+ mxList->addAttribute("draw:marker-start-width", sXML_CDATA,
+ OUString::number( WTMM(hdo->property.line_width * 5)) + "mm");
+ else if( hdo->property.line_width > 40 )
+ mxList->addAttribute("draw:marker-start-width", sXML_CDATA,
+ OUString::number( WTMM(hdo->property.line_width * 6)) + "mm");
+ else
+ mxList->addAttribute("draw:marker-start-width", sXML_CDATA,
+ OUString::number( WTMM(hdo->property.line_width * 7)) + "mm");
+ }
+
+ if( hdo->property.line_hstyle > 0 &&
+ o3tl::make_unsigned(hdo->property.line_hstyle) < std::size(ArrowShape) )
+ {
+ mxList->addAttribute("draw:marker-end", sXML_CDATA,
+ OUString::createFromAscii(ArrowShape[hdo->property.line_hstyle].name) );
+ if( hdo->property.line_width > 100 )
+ mxList->addAttribute("draw:marker-end-width", sXML_CDATA,
+ OUString::number( WTMM(hdo->property.line_width * 3)) + "mm");
+ else if( hdo->property.line_width > 80 )
+ mxList->addAttribute("draw:marker-end-width", sXML_CDATA,
+ OUString::number( WTMM(hdo->property.line_width * 4)) + "mm");
+ else if( hdo->property.line_width > 60 )
+ mxList->addAttribute("draw:marker-end-width", sXML_CDATA,
+ OUString::number( WTMM(hdo->property.line_width * 5)) + "mm");
+ else if( hdo->property.line_width > 40 )
+ mxList->addAttribute("draw:marker-end-width", sXML_CDATA,
+ OUString::number( WTMM(hdo->property.line_width * 6)) + "mm");
+ else
+ mxList->addAttribute("draw:marker-end-width", sXML_CDATA,
+ OUString::number( WTMM(hdo->property.line_width * 7)) + "mm");
+ }
+ }
+
+ if(hdo->type != HWPDO_LINE )
+ {
+ if( hdo->property.flag >> 19 & 0x01 )
+ {
+ mxList->addAttribute( "draw:textarea-horizontal-align", sXML_CDATA, "center");
+ }
+
+ color = hdo->property.fill_color;
+
+ if( hdo->property.flag >> 18 & 0x01 ) // bitmap pattern
+ {
+ mxList->addAttribute("draw:fill", sXML_CDATA, "bitmap");
+ mxList->addAttribute("draw:fill-image-name", sXML_CDATA,
+ "fillimage" + OUString::number(hdo->index));
+ // bitmap resizing
+ if( hdo->property.flag >> 3 & 0x01 )
+ {
+ mxList->addAttribute("style:repeat", sXML_CDATA, "stretch");
+ }
+ else
+ {
+ mxList->addAttribute("style:repeat", sXML_CDATA, "repeat");
+ mxList->addAttribute("draw:fill-image-ref-point", sXML_CDATA, "top-left");
+ }
+ if( hdo->property.flag >> 20 & 0x01 )
+ {
+ if( hdo->property.luminance > 0 )
+ {
+ mxList->addAttribute("draw:transparency", sXML_CDATA,
+ OUString::number(hdo->property.luminance) + "%");
+ }
+ }
+
+ }
+ // Gradation
+ else if( hdo->property.flag >> 16 & 0x01 )
+ {
+ mxList->addAttribute("draw:fill", sXML_CDATA, "gradient");
+ mxList->addAttribute("draw:fill-gradient-name", sXML_CDATA, "Grad" + OUString::number(hdo->index));
+ mxList->addAttribute("draw:gradient-step-count", sXML_CDATA, OUString::number(hdo->property.nstep));
+
+ }
+ // Hatching
+ else if( hdo->property.pattern_type >> 24 & 0x01 )
+ {
+ mxList->addAttribute("draw:fill", sXML_CDATA, "hatch");
+ mxList->addAttribute("draw:fill-hatch-name", sXML_CDATA, "Hatch" + OUString::number(hdo->index));
+ if( color < 0xffffff )
+ {
+ mxList->addAttribute("draw:fill-color", sXML_CDATA,
+ rgb2str(static_cast<int32_t>(color)));
+ mxList->addAttribute("draw:fill-hatch-solid", sXML_CDATA, "true");
+ }
+ }
+ else if( color <= 0xffffff )
+ {
+ mxList->addAttribute("draw:fill", sXML_CDATA, "solid");
+ mxList->addAttribute("draw:fill-color", sXML_CDATA,
+ rgb2str(static_cast<int32_t>(color)));
+ }
+ else
+ mxList->addAttribute("draw:fill", sXML_CDATA, "none");
+ }
+
+ if( fstyle->anchor_type == CHAR_ANCHOR )
+ {
+ mxList->addAttribute("style:vertical-pos", sXML_CDATA, "top");
+ mxList->addAttribute("style:vertical-rel", sXML_CDATA, "baseline");
+ }
+
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:style");
+
+ if( hdo->type == 0 )
+ {
+ makeDrawStyle( hdo->child.get(), fstyle );
+ }
+ hdo = hdo->next.get();
+ }
+}
+
+
+void HwpReader::makeCaptionStyle(FBoxStyle * fstyle)
+{
+ mxList->addAttribute("style:name", sXML_CDATA, "CapBox" + OUString::number(fstyle->boxnum));
+ mxList->addAttribute("style:family", sXML_CDATA, "graphics");
+ startEl("style:style");
+ mxList->clear();
+ mxList->addAttribute("fo:margin-left", sXML_CDATA, "0cm");
+ mxList->addAttribute("fo:margin-right", sXML_CDATA, "0cm");
+ mxList->addAttribute("fo:margin-top", sXML_CDATA, "0cm");
+ mxList->addAttribute("fo:margin-bottom", sXML_CDATA, "0cm");
+ mxList->addAttribute("fo:padding", sXML_CDATA, "0cm");
+ switch (fstyle->txtflow)
+ {
+ case 0:
+ mxList->addAttribute("style:wrap", sXML_CDATA, "none");
+ break;
+ case 1:
+ if( fstyle->boxtype == 'G' )
+ mxList->addAttribute("style:run-through", sXML_CDATA, "background");
+ mxList->addAttribute("style:wrap", sXML_CDATA, "run-through");
+ break;
+ case 2:
+ mxList->addAttribute("style:wrap", sXML_CDATA, "dynamic");
+ break;
+ }
+ if (fstyle->anchor_type == CHAR_ANCHOR)
+ {
+ mxList->addAttribute("style:vertical-pos", sXML_CDATA, "top");
+ mxList->addAttribute("style:vertical-rel", sXML_CDATA, "baseline");
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "center");
+ mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
+ }
+ else
+ {
+
+ switch (-(fstyle->xpos))
+ {
+ case 2:
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "right");
+ break;
+ case 3:
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "center");
+ break;
+ case 1:
+ default:
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "from-left");
+ break;
+ }
+ switch (-(fstyle->ypos))
+ {
+ case 2:
+ mxList->addAttribute("style:vertical-pos", sXML_CDATA, "bottom");
+ break;
+ case 3:
+ mxList->addAttribute("style:vertical-pos", sXML_CDATA, "middle");
+ break;
+ case 1:
+ default:
+ mxList->addAttribute("style:vertical-pos", sXML_CDATA, "from-top");
+ break;
+ }
+ if ( fstyle->anchor_type == PARA_ANCHOR )
+ {
+ mxList->addAttribute("style:vertical-rel", sXML_CDATA, "paragraph");
+ mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
+ }
+ else
+ {
+ mxList->addAttribute("style:vertical-rel", sXML_CDATA, "page-content");
+ mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "page-content");
+ }
+ }
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:style");
+ if( fstyle->boxtype == 'G' )
+ {
+ mxList->addAttribute("style:name", sXML_CDATA, "G" + OUString::number(fstyle->boxnum));
+ }
+ else
+ {
+ mxList->addAttribute("style:name", sXML_CDATA, "Txtbox" + OUString::number(fstyle->boxnum));
+ }
+
+ mxList->addAttribute("style:family", sXML_CDATA, "graphics");
+ startEl("style:style");
+ mxList->clear();
+
+ mxList->addAttribute("fo:margin-left", sXML_CDATA, "0cm");
+ mxList->addAttribute("fo:margin-right", sXML_CDATA, "0cm");
+ mxList->addAttribute("fo:margin-top", sXML_CDATA, "0cm");
+ mxList->addAttribute("fo:margin-bottom", sXML_CDATA, "0cm");
+ mxList->addAttribute("fo:padding", sXML_CDATA, "0cm");
+ mxList->addAttribute("style:wrap", sXML_CDATA, "none");
+ mxList->addAttribute("style:vertical-pos", sXML_CDATA, "from-top");
+ mxList->addAttribute("style:vertical-rel", sXML_CDATA, "paragraph");
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "from-left");
+ mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
+ if (fstyle->boxtype == 'G' && fstyle->cell)
+ {
+ char *cell = static_cast<char *>(fstyle->cell);
+ mxList->addAttribute("draw:luminance", sXML_CDATA, OUString::number(cell[0]) + "%");
+ mxList->addAttribute("draw:contrast", sXML_CDATA, OUString::number(cell[1]) + "%");
+ if( cell[2] == 0 )
+ mxList->addAttribute("draw:color-mode", sXML_CDATA, "standard");
+ else if( cell[2] == 1 )
+ mxList->addAttribute("draw:color-mode", sXML_CDATA, "greyscale");
+ else if( cell[2] == 2 )
+ mxList->addAttribute("draw:color-mode", sXML_CDATA, "mono");
+ }
+ else if (fstyle->cell)
+ {
+ Cell *cell = static_cast<Cell *>(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("fo:padding", sXML_CDATA,"0mm");
+ break;
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ }
+ else
+ {
+ switch( cell->linetype[0] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-left", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ switch( cell->linetype[1] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-right", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ switch( cell->linetype[2] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-top", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ switch( cell->linetype[3] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ }
+ if(cell->shade != 0)
+ mxList->addAttribute("fo:background-color", sXML_CDATA, hcolor2str(
+ sal::static_int_cast<uchar>(cell->color),
+ sal::static_int_cast<uchar>(cell->shade)));
+ }
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:style");
+}
+
+
+/**
+ * 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("style:name", sXML_CDATA, "Txtbox" + OUString::number(fstyle->boxnum));
+ mxList->addAttribute("style:family", sXML_CDATA, "graphics");
+ break;
+ case 'G' : // graphics
+ mxList->addAttribute("style:name", sXML_CDATA, "G" + OUString::number(fstyle->boxnum));
+ mxList->addAttribute("style:family", sXML_CDATA, "graphics");
+ break;
+ case 'L' : // line TODO : all
+ mxList->addAttribute("style:name", sXML_CDATA, "L" + OUString::number(fstyle->boxnum));
+ mxList->addAttribute( "style:family" , sXML_CDATA , "paragraph" );
+ break;
+ }
+
+ startEl("style:style");
+ mxList->clear();
+
+ if ( fstyle->boxtype == 'T')
+ {
+ mxList->addAttribute("fo:padding", sXML_CDATA, "0cm");
+ }
+
+ if( fstyle->boxtype != 'G' || fstyle->cap_len <= 0 )
+ {
+ mxList->addAttribute("fo:margin-left", sXML_CDATA,
+ OUString::number(WTMM(fstyle->margin[0][0]) ) + "mm");
+ mxList->addAttribute("fo:margin-right", sXML_CDATA,
+ OUString::number(WTMM(fstyle->margin[0][1])) + "mm");
+ mxList->addAttribute("fo:margin-top", sXML_CDATA,
+ OUString::number(WTMM(fstyle->margin[0][2])) + "mm");
+ mxList->addAttribute("fo:margin-bottom", sXML_CDATA,
+ OUString::number(WTMM(fstyle->margin[0][3])) + "mm");
+ }
+
+ switch (fstyle->txtflow)
+ {
+ case 0:
+ mxList->addAttribute("style:wrap", sXML_CDATA, "none");
+ break;
+ case 1:
+ if( fstyle->boxtype == 'G' || fstyle->boxtype == 'B' || fstyle->boxtype == 'O')
+ mxList->addAttribute("style:run-through", sXML_CDATA, "background");
+ mxList->addAttribute("style:wrap", sXML_CDATA, "run-through");
+ break;
+ case 2:
+ mxList->addAttribute("style:wrap", sXML_CDATA, "dynamic");
+ break;
+ }
+ if (fstyle->anchor_type == CHAR_ANCHOR)
+ {
+ mxList->addAttribute("style:vertical-pos", sXML_CDATA, "top");
+ mxList->addAttribute("style:vertical-rel", sXML_CDATA, "baseline");
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "center");
+ mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
+ }
+ else
+ {
+
+ switch (-(fstyle->xpos))
+ {
+ case 2:
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "right");
+ break;
+ case 3:
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "center");
+ break;
+ case 1:
+ default:
+ mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "from-left");
+ break;
+ }
+ switch (-(fstyle->ypos))
+ {
+ case 2:
+ mxList->addAttribute("style:vertical-pos", sXML_CDATA, "bottom");
+ break;
+ case 3:
+ mxList->addAttribute("style:vertical-pos", sXML_CDATA, "middle");
+ break;
+ case 1:
+ default:
+ mxList->addAttribute("style:vertical-pos", sXML_CDATA, "from-top");
+ break;
+ }
+ if ( fstyle->anchor_type == PARA_ANCHOR )
+ {
+ mxList->addAttribute("style:vertical-rel", sXML_CDATA, "paragraph");
+ mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
+ }
+ else
+ {
+ mxList->addAttribute("style:vertical-rel", sXML_CDATA, "page-content");
+ mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "page-content");
+ }
+ }
+ if (fstyle->cell && (fstyle->boxtype == 'X' || fstyle->boxtype == 'B'))
+ {
+ Cell *cell = static_cast<Cell *>(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("fo:border", sXML_CDATA, "none");
+ break;
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ }
+ else
+ {
+ switch( cell->linetype[0] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-left", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ switch( cell->linetype[1] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-right", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ switch( cell->linetype[2] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-top", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ switch( cell->linetype[3] )
+ {
+ case 1: /* A thin solid line */
+ case 3: /* Dotted line -> LibreOffice, there is no dotted line */
+ mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
+ break;
+ case 2: /* Bold lines */
+ mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
+ break;
+ case 4: /* Double line */
+ mxList->addAttribute("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
+ mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
+ break;
+ }
+ }
+
+ if( cell->linetype[0] == 0 && cell->linetype[1] == 0 &&
+ cell->linetype[2] == 0 && cell->linetype[3] == 0 ){
+ mxList->addAttribute("fo:padding", sXML_CDATA,"0mm");
+ }
+ else{
+ mxList->addAttribute("fo:padding-left", sXML_CDATA,
+ OUString::number(WTMM(fstyle->margin[1][0])) + "mm");
+ mxList->addAttribute("fo:padding-right", sXML_CDATA,
+ OUString::number(WTMM(fstyle->margin[1][1])) + "mm");
+ mxList->addAttribute("fo:padding-top", sXML_CDATA,
+ OUString::number(WTMM(fstyle->margin[1][2])) + "mm");
+ mxList->addAttribute("fo:padding-bottom", sXML_CDATA,
+ OUString::number(WTMM(fstyle->margin[1][3])) + "mm");
+ }
+ if(cell->shade != 0)
+ mxList->addAttribute("fo:background-color", sXML_CDATA,
+ hcolor2str(
+ sal::static_int_cast<uchar>(cell->color),
+ sal::static_int_cast<uchar>(cell->shade)));
+ }
+ else if( fstyle->boxtype == 'E' )
+ {
+ mxList->addAttribute("fo:padding", sXML_CDATA,"0mm");
+ }
+ else if( fstyle->boxtype == 'L' )
+ {
+ mxList->addAttribute( "style:border-line-width-bottom", sXML_CDATA, "0.02mm 0.35mm 0.02mm");
+ mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.039cm double #808080");
+ }
+ 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("style:mirror", sXML_CDATA, "none");
+ mxList->addAttribute("fo:clip", sXML_CDATA, clip);
+ }
+ char *cell = static_cast<char *>(fstyle->cell);
+ mxList->addAttribute("draw:luminance", sXML_CDATA, OUString::number(cell[0]) + "%");
+ mxList->addAttribute("draw:contrast", sXML_CDATA, OUString::number(cell[1]) + "%");
+ if( cell[2] == 0 )
+ mxList->addAttribute("draw:color-mode", sXML_CDATA, "standard");
+ else if( cell[2] == 1 )
+ mxList->addAttribute("draw:color-mode", sXML_CDATA, "greyscale");
+ else if( cell[2] == 2 )
+ mxList->addAttribute("draw:color-mode", sXML_CDATA, "mono");
+
+ }
+ startEl("style:properties");
+ mxList->clear();
+ endEl("style:properties");
+ endEl("style:style");
+}
+
+
+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("text:style-name", sXML_CDATA,
+ getPStyleName(para->GetParaShape().index));
+ startEl("text:p");
+ mxList->clear();
+ }
+ if( d->bFirstPara && d->bInBody )
+ {
+ mxList->addAttribute("text:name", sXML_CDATA, sBeginOfDoc);
+ startEl("text:bookmark");
+ mxList->clear();
+ endEl("text:bookmark");
+ d->bFirstPara = false;
+ }
+ if( d->bInHeader )
+ {
+ makeShowPageNum();
+ d->bInHeader = false;
+ }
+ mxList->addAttribute("text:style-name", sXML_CDATA,
+ getTStyleName(para->cshape->index));
+ startEl("text:span");
+ mxList->clear();
+
+ int n = 0;
+ while (n < para->nch)
+ {
+ const auto& box = para->hhstr[n];
+
+ if (!box->hh)
+ break;
+
+ if (box->hh == CH_SPACE && !firstspace)
+ {
+ makeChars(str);
+ startEl("text:s");
+ endEl("text:s");
+ }
+ else if (box->hh == CH_END_PARA)
+ {
+ makeChars(str);
+ endEl("text:span");
+ endEl("text:p");
+ 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]);
+ }
+ }
+ n += box->WSize();
+ }
+}
+
+
+/*
+ * 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 n;
+ int res;
+ hchar dest[3];
+ int curr = para->cshape->index;
+ unsigned char firstspace = 0;
+
+ if( !bParaStart )
+ {
+ mxList->addAttribute("text:style-name", sXML_CDATA,
+ getPStyleName(para->GetParaShape().index));
+ startEl("text:p");
+ mxList->clear();
+ }
+ if( d->bFirstPara && d->bInBody )
+ {
+/* for HWP's Bookmark */
+ mxList->addAttribute("text:name", sXML_CDATA, sBeginOfDoc);
+ startEl("text:bookmark");
+ mxList->clear();
+ endEl("text:bookmark");
+ d->bFirstPara = false;
+ }
+ if( d->bInHeader )
+ {
+ makeShowPageNum();
+ d->bInHeader = false;
+ }
+ mxList->addAttribute("text:style-name", sXML_CDATA,
+ getTStyleName(curr));
+ startEl("text:span");
+ mxList->clear();
+
+ for (n = 0; n < para->nch && para->hhstr[n]->hh;
+ n += para->hhstr[n]->WSize())
+ {
+ if (para->GetCharShape(n)->index != curr)
+ {
+ makeChars(str);
+ endEl("text:span");
+ curr = para->GetCharShape(n)->index;
+ mxList->addAttribute("text:style-name", sXML_CDATA,
+ getTStyleName(curr));
+ startEl("text:span");
+ mxList->clear();
+ }
+ if (para->hhstr[n]->hh == CH_SPACE && !firstspace)
+ {
+ makeChars(str);
+ startEl("text:s");
+ endEl("text:s");
+ }
+ else if (para->hhstr[n]->hh == CH_END_PARA)
+ {
+ makeChars(str);
+ endEl("text:span");
+ endEl("text:p");
+ break;
+ }
+ else
+ {
+ if( para->hhstr[n]->hh < CH_SPACE )
+ continue;
+ if (para->hhstr[n]->hh == CH_SPACE)
+ firstspace = 0;
+ else
+ firstspace = 1;
+ res = hcharconv(para->hhstr[n]->hh, dest, UNICODE);
+ for( int j = 0 ; j < res; j++ )
+ {
+ str.push_back(dest[j]);
+ }
+ }
+ }
+}
+
+
+/**
+ * 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("text:style-name", "CDATA",
+ getPStyleName(para->GetParaShape().index));
+ startEl("text:p");
+ mxList->clear();
+ pstart = true;
+ };
+ const auto STARTT = [this, para, &tstart](int pos)
+ {
+ auto curr = para->GetCharShape(pos > 0 ? pos - 1 : 0)->index;
+ mxList->addAttribute("text:style-name", "CDATA", getTStyleName(curr));
+ startEl("text:span");
+ mxList->clear();
+ tstart = true;
+ };
+ const auto ENDP = [this, &pstart]()
+ {
+ endEl("text:p");
+ pstart = false;
+ };
+ const auto ENDT = [this, &tstart]()
+ {
+ endEl("text:span");
+ tstart = false;
+ };
+
+ if( d->bFirstPara && d->bInBody )
+ {
+ if ( !pstart ) {
+ STARTP();
+ }
+ mxList->addAttribute("text:name", sXML_CDATA, sBeginOfDoc);
+ startEl("text:bookmark");
+ mxList->clear();
+ endEl("text:bookmark");
+ d->bFirstPara = false;
+ }
+ if( d->bInHeader )
+ {
+ if ( !pstart ) {
+ STARTP();
+ }
+ makeShowPageNum();
+ d->bInHeader = false;
+ }
+
+ int n = 0;
+ while (n < para->nch)
+ {
+ const auto& box = para->hhstr[n];
+
+ 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("text:s");
+ mxList->clear();
+ endEl("text:s");
+ }
+ 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<FieldCode*>(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<Bookmark*>(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<DateCode*>(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<TxtBox*>(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<Picture*>(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<Hidden*>(box.get()));
+ break;
+ case CH_FOOTNOTE: // 17
+ if( !pstart ) {STARTP();}
+ if( !tstart ) {STARTT(n);}
+ makeChars(str);
+ makeFootnote(static_cast<Footnote*>(box.get()));
+ break;
+ case CH_AUTO_NUM: // 18
+ if( !pstart ) {STARTP();}
+ if( !tstart ) {STARTT(n);}
+ makeChars(str);
+ makeAutoNum(static_cast<AutoNum*>(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<MailMerge*>(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<Outline *>(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("text:placeholder-type", sXML_CDATA, "text");
+ if (d->pField)
+ mxList->addAttribute("text:description", sXML_CDATA, hstr2OUString(d->pField));
+ startEl("text:placeholder");
+ mxList->clear();
+ chars( fromHcharStringToOUString(rStr) );
+ endEl("text:placeholder");
+ }
+/* Document Summary */
+ else if( hbox->type[0] == 3 && hbox->type[1] == 0 )
+ {
+ const OUString uStr3 = hstr2OUString(hbox->str3.get());
+ if (uStr3 == "title")
+ {
+ startEl("text:title");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:title");
+ }
+ else if (uStr3 == "subject")
+ {
+ startEl("text:subject");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:subject");
+ }
+ else if (uStr3 == "author")
+ {
+ startEl("text:author-name");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:author-name");
+ }
+ else if (uStr3 == "keywords")
+ {
+ startEl("text:keywords");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:keywords");
+ }
+ }
+/* Personal Information */
+ else if( hbox->type[0] == 3 && hbox->type[1] == 1 )
+ {
+ const OUString uStr3 = hstr2OUString(hbox->str3.get());
+ if (uStr3 == "User")
+ {
+ startEl("text:sender-lastname");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:sender-lastname");
+ }
+ else if (uStr3 == "Company")
+ {
+ startEl("text:sender-company");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:sender-company");
+ }
+ else if (uStr3 == "Position")
+ {
+ startEl("text:sender-title");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:sender-title");
+ }
+ else if (uStr3 == "Division")
+ {
+ startEl("text:sender-position");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:sender-position");
+ }
+ else if (uStr3 == "Fax")
+ {
+ startEl("text:sender-fax");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:sender-fax");
+ }
+ else if (uStr3 == "Pager")
+ {
+ startEl("text:phone-private");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:phone-private");
+ }
+ else if (uStr3 == "E-mail")
+ {
+ startEl("text:sender-email");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:sender-email");
+ }
+ else if (uStr3 == "Zipcode(office)")
+ {
+ startEl("text:sender-postal-code");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:sender-postal-code");
+ }
+ else if (uStr3 == "Phone(office)")
+ {
+ startEl("text:sender-phone-work");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:sender-phone-work");
+ }
+ else if (uStr3 == "Address(office)")
+ {
+ startEl("text:sender-street");
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:sender-street");
+ }
+
+ }
+ else if( hbox->type[0] == 3 && hbox->type[1] == 2 ) /* creation date */
+ {
+ if( hbox->m_pDate )
+ mxList->addAttribute("style:data-style-name", sXML_CDATA, "N" + OUString::number(hbox->m_pDate->key));
+ startEl("text:creation-date");
+ mxList->clear();
+ chars( hstr2OUString(hbox->str2.get()) );
+ endEl("text:creation-date");
+ }
+}
+
+
+/**
+ * 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("text:name", sXML_CDATA, hstr2OUString(hbox->id));
+ startEl("text:bookmark");
+ mxList->clear();
+ endEl("text:bookmark");
+ }
+ else if (hbox->type == 1) /* Block bookmarks days begin and end there if */
+ {
+ mxList->addAttribute("text:name", sXML_CDATA, hstr2OUString(hbox->id));
+ startEl("text:bookmark-start");
+ mxList->clear();
+ endEl("text:bookmark-start");
+ }
+ else if (hbox->type == 2)
+ {
+ mxList->addAttribute("text:name", sXML_CDATA, hstr2OUString(hbox->id));
+ startEl("text:bookmark-end");
+ mxList->clear();
+ endEl("text:bookmark-end");
+ }
+}
+
+
+void HwpReader::makeDateFormat(DateCode * hbox)
+{
+ mxList->addAttribute("style:name", sXML_CDATA, "N" + OUString::number(hbox->key));
+ mxList->addAttribute("style:family", sXML_CDATA,"data-style");
+ mxList->addAttribute("number:language", sXML_CDATA,"ko");
+ mxList->addAttribute("number:country", sXML_CDATA,"KR");
+
+ startEl("number:date-style");
+ 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("number:style", sXML_CDATA, "long");
+ startEl("number:year");
+ mxList->clear();
+ endEl("number:year");
+ break;
+ case '!':
+ startEl("number:year");
+ mxList->clear();
+ endEl("number:year");
+ break;
+ case '2':
+ if( add_zero )
+ mxList->addAttribute("number:style", sXML_CDATA, "long");
+ startEl("number:month");
+ mxList->clear();
+ endEl("number:month");
+ break;
+ case '@':
+ mxList->addAttribute("number:textual", sXML_CDATA, "true");
+ startEl("number:month");
+ mxList->clear();
+ endEl("number:month");
+ break;
+ case '*':
+ mxList->addAttribute("number:textual", sXML_CDATA, "true");
+ mxList->addAttribute("number:style", sXML_CDATA, "long");
+ startEl("number:month");
+ mxList->clear();
+ endEl("number:month");
+ break;
+ case '3':
+ if( add_zero )
+ mxList->addAttribute("number:style", sXML_CDATA, "long");
+ startEl("number:day");
+ mxList->clear();
+ endEl("number:day");
+ break;
+ case '#':
+ if( add_zero )
+ mxList->addAttribute("number:style", sXML_CDATA, "long");
+ startEl("number:day");
+ mxList->clear();
+ endEl("number:day");
+ switch( hbox->date[DateCode::DAY] % 10)
+ {
+ case 1:
+ startEl("number:text");
+ chars("st");
+ endEl("number:text");
+ break;
+ case 2:
+ startEl("number:text");
+ chars("nd");
+ endEl("number:text");
+ break;
+ case 3:
+ startEl("number:text");
+ chars("rd");
+ endEl("number:text");
+ break;
+ default:
+ startEl("number:text");
+ chars("th");
+ endEl("number:text");
+ break;
+ }
+ break;
+ case '4':
+ case '$':
+ if( add_zero )
+ mxList->addAttribute("number:style", sXML_CDATA, "long");
+ startEl("number:hours");
+ mxList->clear();
+ endEl("number:hours");
+ break;
+ case '5':
+ case '%':
+ if( add_zero )
+ mxList->addAttribute("number:style", sXML_CDATA, "long");
+ startEl("number:minutes");
+ mxList->clear();
+ endEl("number:minutes");
+ break;
+ case '_':
+ mxList->addAttribute("number:style", sXML_CDATA, "long");
+ [[fallthrough]];
+ case '6':
+ case '^':
+ startEl("number:day-of-week");
+ mxList->clear();
+ endEl("number:day-of-week");
+ break;
+ case '7':
+ case '&':
+ case '+':
+ startEl("number:am-pm");
+ mxList->clear();
+ endEl("number:am-pm");
+ break;
+ case '~': // Chinese Locale
+ break;
+ default:
+ hchar sbuf[2];
+ sbuf[0] = *fmt;
+ sbuf[1] = 0;
+ startEl("number:text");
+ chars(hstr2OUString(sbuf));
+ endEl("number:text");
+ break;
+ }
+ }
+ mxList->clear();
+ endEl("number:date-style");
+}
+
+
+void HwpReader::makeDateCode(DateCode * hbox)
+{
+ mxList->addAttribute("style:data-style-name", sXML_CDATA, "N" + OUString::number(hbox->key));
+ startEl("text:date");
+ mxList->clear();
+ hchar_string const boxstr = hbox->GetString();
+ chars(hstr2OUString(boxstr.c_str()));
+ endEl("text:date");
+}
+
+
+void HwpReader::makeTab()
+{
+ startEl("text:tab-stop");
+ endEl("text:tab-stop");
+}
+
+
+void HwpReader::makeTable(TxtBox * hbox)
+{
+ mxList->addAttribute("table:name", sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum));
+ mxList->addAttribute("table:style-name", sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum));
+ startEl("table:table");
+ mxList->clear();
+
+ Table *tbl = hbox->m_pTable;
+// column
+ for (size_t i = 0 ; i < tbl->columns.nCount -1 ; i++)
+ {
+ sprintf(d->buf,"Table%d.%c",hbox->style.boxnum, static_cast<char>('A'+i));
+ mxList->addAttribute("table:style-name", sXML_CDATA, OUString::createFromAscii(d->buf));
+ startEl("table:table-column");
+ mxList->clear();
+ endEl("table:table-column");
+ }
+
+// cell
+ int j = -1, k = -1;
+ for (auto const& tcell : tbl->cells)
+ {
+ if( tcell->nRowIndex > j )
+ {
+ if( j > k )
+ {
+ endEl("table:table-row");
+ k = j;
+ }
+// row
+ sprintf(d->buf,"Table%d.row%d",hbox->style.boxnum, tcell->nRowIndex + 1);
+ mxList->addAttribute("table:style-name", sXML_CDATA, OUString::createFromAscii(d->buf));
+ startEl("table:table-row");
+ mxList->clear();
+ j = tcell->nRowIndex;
+ }
+
+ sprintf(d->buf,"Table%d.%c%d",hbox->style.boxnum, 'A'+ tcell->nColumnIndex, tcell->nRowIndex +1);
+ mxList->addAttribute("table:style-name", sXML_CDATA, OUString::createFromAscii(d->buf));
+ if( tcell->nColumnSpan > 1 )
+ mxList->addAttribute("table:number-columns-spanned", sXML_CDATA, OUString::number(tcell->nColumnSpan));
+ if( tcell->nRowSpan > 1 )
+ mxList->addAttribute("table:number-rows-spanned", sXML_CDATA, OUString::number(tcell->nRowSpan));
+ mxList->addAttribute("table:value-type", sXML_CDATA,"string");
+ if( tcell->pCell->protect )
+ mxList->addAttribute("table:protected", sXML_CDATA,"true");
+ startEl("table:table-cell");
+ mxList->clear();
+ TxtBox::plist_t& rVec = hbox->plists[tcell->pCell->key];
+ if (!rVec.empty())
+ parsePara(rVec.front().get());
+ endEl("table:table-cell");
+ }
+ endEl("table:table-row");
+ endEl("table:table");
+}
+
+
+/**
+ * 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("draw:style-name", sXML_CDATA, "CapBox" + OUString::number(hbox->style.boxnum));
+ mxList->addAttribute("draw:name", sXML_CDATA, "CaptionBox" + OUString::number(hbox->style.boxnum));
+ mxList->addAttribute("draw:z-index", sXML_CDATA, OUString::number(hbox->zorder));
+ switch (hbox->style.anchor_type)
+ {
+ case CHAR_ANCHOR:
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "as-char");
+ break;
+ case PARA_ANCHOR:
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
+ break;
+ case PAGE_ANCHOR:
+ case PAPER_ANCHOR:
+ {
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "page");
+ mxList->addAttribute("text:anchor-page-number", sXML_CDATA, OUString::number(hbox->pgno + 1));
+ break;
+ }
+ }
+ if (hbox->style.anchor_type != CHAR_ANCHOR)
+ {
+ mxList->addAttribute("svg:x", sXML_CDATA,
+ OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
+ mxList->addAttribute("svg:y", sXML_CDATA,
+ OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
+ }
+ mxList->addAttribute("svg:width", sXML_CDATA,
+ OUString::number(WTMM( hbox->box_xs + hbox->cap_xs )) + "mm");
+ mxList->addAttribute("fo:min-height", sXML_CDATA,
+ OUString::number(WTMM( hbox->box_ys + hbox->cap_ys )) + "mm");
+ startEl("draw:text-box");
+ mxList->clear();
+ if (!hbox->caption.empty() && hbox->cap_pos % 2) /* The caption is on the top */
+ {
+ parsePara(hbox->caption.front().get());
+ }
+ mxList->addAttribute( "text:style-name", sXML_CDATA, "Standard");
+ startEl("text:p");
+ mxList->clear();
+ }
+ else{
+ mxList->addAttribute("draw:z-index", sXML_CDATA, OUString::number(hbox->zorder));
+ }
+
+ mxList->addAttribute("draw:style-name", sXML_CDATA, "Txtbox" + OUString::number(hbox->style.boxnum));
+ mxList->addAttribute("draw:name", 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("text:anchor-type", sXML_CDATA, "as-char");
+ break;
+ case PARA_ANCHOR:
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
+ break;
+ case PAGE_ANCHOR:
+ case PAPER_ANCHOR:
+ {
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "page");
+ mxList->addAttribute("text:anchor-page-number", 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("svg:x", sXML_CDATA,
+ OUString::number(WTMM( hbox->pgx + x )) + "mm");
+ mxList->addAttribute("svg:y", sXML_CDATA,
+ OUString::number(WTMM( hbox->pgy + y )) + "mm");
+ }
+ else
+ {
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "as-char");
+ mxList->addAttribute("svg:y", sXML_CDATA, "0cm");
+ }
+ mxList->addAttribute("svg:width", sXML_CDATA,
+ OUString::number(WTMM( hbox->box_xs )) + "mm");
+ if( hbox->style.cap_len > 0 && hbox->type != TXT_TYPE)
+ mxList->addAttribute("fo:min-height", sXML_CDATA,
+ OUString::number(WTMM( hbox->box_ys + hbox->cap_ys)) + "mm");
+ else
+ mxList->addAttribute("svg:height", sXML_CDATA,
+ OUString::number(WTMM(hbox->box_ys )) + "mm");
+
+ if( hbox->type != EQU_TYPE )
+ {
+ startEl("draw:text-box");
+ 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("draw:text-box");
+// Caption exist and it is text-box
+ if( hbox->style.cap_len > 0 && hbox->type == TXT_TYPE)
+ {
+ endEl("text:p");
+ if (!(hbox->cap_pos % 2) && !hbox->caption.empty())
+ {
+ parsePara(hbox->caption.front().get());
+ }
+ endEl("draw:text-box");
+ }
+ }
+ else // is Formula
+ {
+ startEl("draw:object");
+ mxList->clear();
+ makeFormula(hbox);
+ endEl("draw:object");
+ }
+}
+
+
+/**
+ * It must be converted into MathML.
+ *
+ */
+void HwpReader::makeFormula(TxtBox * hbox)
+{
+ char mybuf[3000];
+ HWPPara* pPar;
+
+ int n, c, res;
+ hchar dest[3];
+ size_t l = 0;
+
+ pPar = hbox->plists[0].empty() ? nullptr : hbox->plists[0].front().get();
+ while( pPar )
+ {
+ for( n = 0; n < pPar->nch && pPar->hhstr.count(n) && pPar->hhstr[n]->hh;
+ n += pPar->hhstr[n]->WSize() )
+ {
+ if (l >= sizeof(mybuf)-7)
+ break;
+ res = hcharconv(pPar->hhstr[n]->hh, dest, UNICODE);
+ for( int j = 0 ; j < res; j++ ){
+ c = dest[j];
+ if( c < 32 )
+ c = ' ';
+ if( c < 256 )
+ mybuf[l++] = sal::static_int_cast<char>(c);
+ else
+ {
+ mybuf[l++] = sal::static_int_cast<char>((c >> 8) & 0xff);
+ mybuf[l++] = sal::static_int_cast<char>(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<uchar const *>(urltowin(reinterpret_cast<char *>(hypert->filename)).c_str())).c_str());
+#else
+ reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hypert->filename)).c_str())).c_str());
+#endif
+ mxList->addAttribute("xlink:type", sXML_CDATA, "simple");
+ if (!tmp.empty() && strcmp(tmp.c_str(), "[HTML]")) {
+ ::std::string tmp3(tmp2);
+ tmp3.push_back('#');
+ tmp3.append(tmp);
+ mxList->addAttribute("xlink:href", sXML_CDATA,
+ OUString(tmp3.c_str(), tmp3.size()+1, RTL_TEXTENCODING_EUC_KR));
+ }
+ else{
+ mxList->addAttribute("xlink:href", sXML_CDATA,
+ OUString(tmp2.c_str(), tmp2.size()+1, RTL_TEXTENCODING_EUC_KR));
+
+ }
+ }
+ else
+ {
+ mxList->addAttribute("xlink:type", sXML_CDATA, "simple");
+ ::std::string tmp;
+ tmp.push_back('#');
+ tmp.append(hstr2ksstr(hypert->bookmark));
+ mxList->addAttribute("xlink:href", sXML_CDATA,
+ OUString(tmp.c_str(), tmp.size()+1, RTL_TEXTENCODING_EUC_KR));
+ }
+ startEl("draw:a");
+ mxList->clear();
+ makeTextBox(hbox);
+ endEl("draw:a");
+}
+
+
+/**
+ * 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("draw:style-name", sXML_CDATA,
+ "CapBox" + OUString::number(hbox->style.boxnum));
+ mxList->addAttribute("draw:name", sXML_CDATA, "CaptionBox" + OUString::number(hbox->style.boxnum));
+ mxList->addAttribute("draw:z-index", sXML_CDATA, OUString::number(hbox->zorder));
+ switch (hbox->style.anchor_type)
+ {
+ case CHAR_ANCHOR:
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "as-char");
+ break;
+ case PARA_ANCHOR:
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
+ break;
+ case PAGE_ANCHOR:
+ case PAPER_ANCHOR:
+ {
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "page");
+ mxList->addAttribute("text:anchor-page-number", sXML_CDATA,
+ OUString::number(hbox->pgno + 1));
+ break;
+ }
+ }
+ if (hbox->style.anchor_type != CHAR_ANCHOR)
+ {
+ mxList->addAttribute("svg:x", sXML_CDATA,
+ OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
+ mxList->addAttribute("svg:y", sXML_CDATA,
+ OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
+ }
+ mxList->addAttribute("svg:width", sXML_CDATA,
+ OUString::number(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1] )) + "mm");
+ mxList->addAttribute("fo:min-height", sXML_CDATA,
+ OUString::number(WTMM( hbox->box_ys + hbox->style.margin[1][2] + hbox->style.margin[1][3] + hbox->cap_ys )) + "mm");
+ startEl("draw:text-box");
+ mxList->clear();
+ if (!hbox->caption.empty() && hbox->cap_pos % 2) /* Caption is on the top */
+ {
+ parsePara(hbox->caption.front().get());
+ }
+ mxList->addAttribute( "text:style-name", sXML_CDATA, "Standard");
+ startEl("text:p");
+ mxList->clear();
+ }
+ if( hbox->ishyper )
+ {
+ mxList->addAttribute("xlink:type", sXML_CDATA, "simple");
+#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("xlink:href", sXML_CDATA,
+ hstr2OUString(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hbox->follow.data() + 4)).c_str())).c_str()));
+ else
+ mxList->addAttribute("xlink:href", sXML_CDATA,
+ hstr2OUString(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hbox->follow.data() + 5)).c_str())).c_str()));
+#endif
+ startEl("draw:a");
+ mxList->clear();
+ }
+ mxList->addAttribute("draw:style-name", sXML_CDATA, "G" + OUString::number(hbox->style.boxnum));
+ mxList->addAttribute("draw:name", sXML_CDATA, "Image" + OUString::number(hbox->style.boxnum));
+
+ if( hbox->style.cap_len <= 0 )
+ {
+ mxList->addAttribute("draw:z-index", sXML_CDATA, OUString::number(hbox->zorder));
+ switch (hbox->style.anchor_type)
+ {
+ case CHAR_ANCHOR:
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "as-char");
+ break;
+ case PARA_ANCHOR:
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
+ break;
+ case PAGE_ANCHOR:
+ case PAPER_ANCHOR:
+ {
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "page");
+ mxList->addAttribute("text:anchor-page-number", sXML_CDATA,
+ OUString::number(hbox->pgno + 1));
+ break;
+ }
+ }
+ if (hbox->style.anchor_type != CHAR_ANCHOR)
+ {
+ mxList->addAttribute("svg:x", sXML_CDATA,
+ OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
+ mxList->addAttribute("svg:y", sXML_CDATA,
+ OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
+ }
+ }
+ else
+ {
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "as-char");
+ mxList->addAttribute("svg:y", sXML_CDATA, "0cm");
+ }
+ mxList->addAttribute("svg:width", sXML_CDATA,
+ OUString::number(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1])) + "mm");
+ mxList->addAttribute("svg:height", 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<uchar *>(d->buf)).c_str()));
+#else
+ mxList->addAttribute("xlink:href", sXML_CDATA,
+ hstr2OUString(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(hbox->picinfo.picun.path).c_str())).c_str()));
+#endif
+ mxList->addAttribute("xlink:type", sXML_CDATA, "simple");
+ mxList->addAttribute("xlink:show", sXML_CDATA, "embed");
+ mxList->addAttribute("xlink:actuate", sXML_CDATA, "onLoad");
+ }
+
+ if( hbox->pictype == PICTYPE_OLE )
+ startEl("draw:object-ole");
+ else
+ startEl("draw:image");
+ mxList->clear();
+ if (hbox->pictype == PICTYPE_EMBED || hbox->pictype == PICTYPE_OLE)
+ {
+ startEl("office:binary-data");
+ mxList->clear();
+ if( hbox->pictype == PICTYPE_EMBED ){
+ EmPicture *emp = hwpfile.GetEmPicture(hbox);
+ if( emp )
+ {
+ chars(base64_encode_string(emp->data.get(), emp->size));
+ }
+ }
+ else{
+ if( hwpfile.oledata ){
+#ifdef _WIN32
+ LPSTORAGE srcsto;
+ LPUNKNOWN pObj;
+ wchar_t pathname[200];
+
+ MultiByteToWideChar(CP_ACP, 0, hbox->picinfo.picole.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<LPVOID*>(&pObj));
+ if( rc != S_OK ){
+ srcsto->Release();
+ chars("");
+ }
+ else{
+ chars(base64_encode_string(reinterpret_cast<uchar*>(pObj), strlen(reinterpret_cast<char*>(pObj))));
+ pObj->Release();
+ srcsto->Release();
+ }
+ }
+#else
+ chars("");
+#endif
+ }
+ }
+ endEl("office:binary-data");
+ }
+ if( hbox->pictype == PICTYPE_OLE )
+ endEl("draw:object-ole");
+ else
+ endEl("draw:image");
+ if( hbox->ishyper )
+ {
+ endEl("draw:a");
+ }
+ if( hbox->style.cap_len > 0 )
+ {
+ endEl("text:p");
+ if (!hbox->caption.empty() && !(hbox->cap_pos % 2)) /* Caption is at the bottom, */
+ {
+ parsePara(hbox->caption.front().get());
+ }
+ endEl("draw:text-box");
+ }
+ break;
+ }
+ case PICTYPE_DRAW:
+ if( hbox->picinfo.picdraw.zorder > 0 )
+ mxList->addAttribute("draw:z-index", 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("draw:style-name", sXML_CDATA, "Draw" + OUString::number(drawobj->index));
+ int a = 0;
+ int b = 0;
+
+ switch (hbox->style.anchor_type)
+ {
+ case CHAR_ANCHOR:
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "as-char");
+ break;
+ case PARA_ANCHOR:
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
+ break;
+ case PAGE_ANCHOR:
+ case PAPER_ANCHOR:
+ {
+ HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "page");
+ mxList->addAttribute("text:anchor-page-number", 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("draw:g");
+ mxList->clear();
+ makePictureDRAW(drawobj->child.get(), hbox);
+ endEl("draw:g");
+ }
+ 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<int>(std::hypot(pt[1].getX() - pt[0].getX(), pt[1].getY() - pt[0].getY()));
+ drawobj->extent.h = static_cast<int>(std::hypot(pt[2].getX() - pt[1].getX(), pt[2].getY() - pt[1].getY()));
+ mxList->addAttribute("draw:transform", sXML_CDATA, trans);
+ }
+ }
+ switch (drawobj->type)
+ {
+ case HWPDO_LINE: /* Line-starting coordinates, ending coordinates. */
+ if( drawobj->u.line_arc.flip & 0x01 )
+ {
+ mxList->addAttribute("svg:x1", sXML_CDATA,
+ OUString::number (WTMM(x + a + drawobj->offset2.x + drawobj->extent.w)) + "mm");
+ mxList->addAttribute("svg:x2", sXML_CDATA,
+ OUString::number (WTMM( x + a + drawobj->offset2.x )) + "mm");
+ }
+ else
+ {
+ mxList->addAttribute("svg:x1", sXML_CDATA,
+ OUString::number (WTMM( x + a + drawobj->offset2.x )) + "mm");
+ mxList->addAttribute("svg:x2", sXML_CDATA,
+ OUString::number (WTMM(x + a + drawobj->offset2.x + drawobj->extent.w)) + "mm");
+ }
+ if( drawobj->u.line_arc.flip & 0x02 )
+ {
+ mxList->addAttribute("svg:y1", sXML_CDATA,
+ OUString::number (WTMM( y + b + drawobj->offset2.y + drawobj->extent.h ) ) + "mm");
+ mxList->addAttribute("svg:y2", sXML_CDATA,
+ OUString::number (WTMM( y + b + drawobj->offset2.y )) + "mm");
+ }
+ else
+ {
+ mxList->addAttribute("svg:y1", sXML_CDATA,
+ OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
+ mxList->addAttribute("svg:y2", sXML_CDATA,
+ OUString::number (WTMM(y + b + drawobj->offset2.y + drawobj->extent.h)) + "mm");
+ }
+
+ startEl("draw:line");
+ mxList->clear();
+ endEl("draw:line");
+ break;
+ case HWPDO_RECT: /* rectangle - the starting position, vertical/horizontal */
+ if( !bIsRotate )
+ {
+ mxList->addAttribute("svg:x", sXML_CDATA,
+ OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
+ mxList->addAttribute("svg:y", sXML_CDATA,
+ OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
+ }
+ mxList->addAttribute("svg:width", sXML_CDATA,
+ OUString::number (WTMM( drawobj->extent.w )) + "mm");
+ mxList->addAttribute("svg:height", 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("draw:corner-radius", 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("draw:corner-radius", sXML_CDATA,
+ OUString::number (WTMM( value / 2)) + "mm");
+ }
+
+ startEl("draw:rect");
+ 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("draw:rect");
+ break;
+ case HWPDO_ELLIPSE: /* Ellipse - the starting position, vertical/horizontal */
+ case HWPDO_ADVANCED_ELLIPSE: /* modified ellipse */
+ {
+ if( !bIsRotate )
+ {
+ mxList->addAttribute("svg:x", sXML_CDATA,
+ OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
+ mxList->addAttribute("svg:y", sXML_CDATA,
+ OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
+ }
+
+ mxList->addAttribute("svg:width", sXML_CDATA,
+ OUString::number (WTMM( drawobj->extent.w )) + "mm");
+ mxList->addAttribute("svg:height", 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("draw:kind", sXML_CDATA, "section");
+ else
+ mxList->addAttribute("draw:kind", sXML_CDATA, "arc");
+ mxList->addAttribute("draw:start-angle", sXML_CDATA, OUString::number(start_angle ));
+ mxList->addAttribute("draw:end-angle", sXML_CDATA, OUString::number(end_angle));
+ }
+ }
+ }
+ startEl("draw:ellipse");
+ 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("draw:ellipse");
+ 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("svg:x", sXML_CDATA,
+ OUString::number (WTMM( x + a + drawobj->offset2.x - drawobj->extent.w)) + "mm");
+ else
+ mxList->addAttribute("svg:x", sXML_CDATA,
+ OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
+ if( ( flip == 0 || flip == 1 ) && drawobj->type == HWPDO_ARC)
+ mxList->addAttribute("svg:y", sXML_CDATA,
+ OUString::number (WTMM( y + b + drawobj->offset2.y - drawobj->extent.h)) + "mm");
+ else
+ mxList->addAttribute("svg:y", sXML_CDATA,
+ OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
+ }
+
+ mxList->addAttribute("svg:width", sXML_CDATA,
+ OUString::number (WTMM( drawobj->extent.w * 2)) + "mm");
+ mxList->addAttribute("svg:height", 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("draw:kind", sXML_CDATA, "section");
+ else
+ mxList->addAttribute("draw:kind", sXML_CDATA, "arc");
+
+ 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 )){
+ double tmp_angle = start_angle;
+ start_angle = end_angle;
+ end_angle = tmp_angle;
+ }
+ mxList->addAttribute("draw:start-angle", sXML_CDATA, OUString::number(basegfx::rad2deg(start_angle)));
+ mxList->addAttribute("draw:end-angle", sXML_CDATA, OUString::number(basegfx::rad2deg(end_angle)));
+
+ }
+ else
+ {
+ if( drawobj->u.line_arc.flip == 0 )
+ {
+ mxList->addAttribute("draw:start-angle", sXML_CDATA, "270");
+ mxList->addAttribute("draw:end-angle", sXML_CDATA, "0");
+ }
+ else if( drawobj->u.line_arc.flip == 1 )
+ {
+ mxList->addAttribute("draw:start-angle", sXML_CDATA, "180");
+ mxList->addAttribute("draw:end-angle", sXML_CDATA, "270");
+ }
+ else if( drawobj->u.line_arc.flip == 2 )
+ {
+ mxList->addAttribute("draw:start-angle", sXML_CDATA, "0");
+ mxList->addAttribute("draw:end-angle", sXML_CDATA, "90");
+ }
+ else
+ {
+ mxList->addAttribute("draw:start-angle", sXML_CDATA, "90");
+ mxList->addAttribute("draw:end-angle", sXML_CDATA, "180");
+ }
+ }
+ startEl("draw:ellipse");
+ 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("draw:ellipse");
+ break;
+
+ }
+ case HWPDO_CURVE: /* Curve: converts to polygons. */
+ {
+ bool bIsNatural = true;
+ if( drawobj->property.flag >> 5 & 0x01){
+ bIsNatural = false;
+ }
+ if( !bIsRotate )
+ {
+ mxList->addAttribute("svg:x", sXML_CDATA,
+ OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
+ mxList->addAttribute("svg:y", sXML_CDATA,
+ OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
+ }
+ mxList->addAttribute("svg:width", sXML_CDATA,
+ OUString::number (WTMM( drawobj->extent.w )) + "mm");
+ mxList->addAttribute("svg:height", sXML_CDATA,
+ OUString::number (WTMM( drawobj->extent.h )) + "mm");
+ sprintf(d->buf, "0 0 %d %d", WTSM(drawobj->extent.w) , WTSM(drawobj->extent.h) );
+ mxList->addAttribute("svg:viewBox", sXML_CDATA, OUString::createFromAscii(d->buf));
+
+ OUStringBuffer oustr;
+
+ if ((drawobj->u.freeform.npt > 2) &&
+ (o3tl::make_unsigned(drawobj->u.freeform.npt) <
+ (::std::numeric_limits<int>::max() / sizeof(double))))
+ {
+ int n, i;
+ n = drawobj->u.freeform.npt;
+
+ std::unique_ptr<double[]> xarr( new double[n+1] );
+ std::unique_ptr<double[]> yarr( new double[n+1] );
+ std::unique_ptr<double[]> tarr( new double[n+1] );
+
+ std::unique_ptr<double[]> xb;
+ std::unique_ptr<double[]> yb;
+
+ std::unique_ptr<double[]> carr;
+ std::unique_ptr<double[]> 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);
+ }
+
+ sprintf(d->buf, "M%d %dC%d %d", WTSM(xarr[0]), WTSM(yarr[0]),
+ WTSM(xarr[0] + xb[0]/3), WTSM(yarr[0] + yb[0]/3) );
+ oustr.appendAscii(d->buf);
+
+ for( i = 1 ; i < n ; i++ ){
+ if( i == n -1 ){
+ sprintf(d->buf, " %d %d %d %dz",
+ WTSM(xarr[i] - xb[i]/3), WTSM(yarr[i] - yb[i]/3),
+ WTSM(xarr[i]), WTSM(yarr[i]) );
+ }
+ else{
+ sprintf(d->buf, " %d %d %d %d %d %d",
+ WTSM(xarr[i] - xb[i]/3), WTSM(yarr[i] - yb[i]/3),
+ WTSM(xarr[i]), WTSM(yarr[i]),
+ WTSM(xarr[i] + xb[i]/3), WTSM(yarr[i] + yb[i]/3) );
+ }
+
+ oustr.appendAscii(d->buf);
+ }
+ }
+
+ mxList->addAttribute("svg:d", sXML_CDATA, oustr.makeStringAndClear());
+
+ startEl("draw:path");
+ 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("draw:path");
+ break;
+ }
+ case HWPDO_CLOSED_FREEFORM:
+ case HWPDO_FREEFORM: /* polygon */
+ {
+ bool bIsPolygon = false;
+
+ mxList->addAttribute("svg:x", sXML_CDATA,
+ OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
+ mxList->addAttribute("svg:y", sXML_CDATA,
+ OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
+
+ mxList->addAttribute("svg:width", sXML_CDATA,
+ OUString::number (WTMM( drawobj->extent.w )) + "mm");
+ mxList->addAttribute("svg:height", sXML_CDATA,
+ OUString::number (WTMM( drawobj->extent.h )) + "mm");
+
+ sprintf(d->buf, "0 0 %d %d", WTSM(drawobj->extent.w), WTSM(drawobj->extent.h));
+ mxList->addAttribute("svg:viewBox", sXML_CDATA, OUString::createFromAscii(d->buf));
+
+ OUStringBuffer oustr;
+
+ if (drawobj->u.freeform.npt > 0)
+ {
+ sprintf(d->buf, "%d,%d", WTSM(drawobj->u.freeform.pt[0].x), WTSM(drawobj->u.freeform.pt[0].y));
+ oustr.appendAscii(d->buf);
+ int i;
+ for (i = 1; i < drawobj->u.freeform.npt ; i++)
+ {
+ sprintf(d->buf, " %d,%d",
+ WTSM(drawobj->u.freeform.pt[i].x),
+ WTSM(drawobj->u.freeform.pt[i].y));
+ oustr.appendAscii(d->buf);
+ }
+ 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("draw:points", sXML_CDATA, oustr.makeStringAndClear());
+
+ if( drawobj->property.fill_color <= 0xffffff ||
+ drawobj->property.pattern_type != 0)
+ {
+ bIsPolygon = true;
+ }
+
+ if(bIsPolygon)
+ {
+ startEl("draw:polygon");
+ 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("draw:polygon");
+ }
+ else
+ {
+ startEl("draw:polyline");
+ 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("draw:polyline");
+ }
+ break;
+ }
+ case HWPDO_TEXTBOX:
+ if( !bIsRotate )
+ {
+ mxList->addAttribute("svg:x", sXML_CDATA,
+ OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
+ mxList->addAttribute("svg:y", sXML_CDATA,
+ OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
+ }
+ mxList->addAttribute("svg:width", sXML_CDATA,
+ OUString::number (WTMM( drawobj->extent.w )) + "mm");
+ mxList->addAttribute("svg:height", 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("draw:corner-radius", 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("draw:corner-radius", sXML_CDATA,
+ OUString::number (WTMM( value / 2)) + "mm");
+ }
+
+ startEl("draw:text-box");
+ mxList->clear();
+
+ HWPPara *pPara = drawobj->u.textbox.h;
+ //parsePara(pPara);
+ while(pPara)
+ {
+ make_text_p1( pPara, false );
+ pPara = pPara->Next();
+ }
+
+ endEl("draw:text-box");
+ break;
+ }
+ }
+ mxList->clear();
+ drawobj = drawobj->next.get();
+ }
+}
+
+void HwpReader::makeLine()
+{
+ mxList->addAttribute("text:style-name", sXML_CDATA, "Horizontal Line");
+ startEl("text:p");
+ 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("text:condition", sXML_CDATA, "");
+ mxList->addAttribute("text:string-value", sXML_CDATA, "");
+ startEl("text:hidden-text");
+ mxList->clear();
+ HWPPara *para = !hbox->plist.empty() ? hbox->plist.front().get() : nullptr;
+
+ while (para)
+ {
+ for (int n = 0; n < para->nch && para->hhstr.count(n) && para->hhstr[n]->hh;
+ n += para->hhstr[n]->WSize())
+ {
+ res = hcharconv(para->hhstr[n]->hh, dest, UNICODE);
+ for( int j = 0 ; j < res ; j++ )
+ {
+ str.push_back(dest[j]);
+ }
+ }
+ para = para->Next();
+ }
+ makeChars(str);
+ endEl("text:hidden-text");
+}
+
+
+/**
+ * Converts footnote to text:footnote, endnote to text:endnote
+ */
+void HwpReader::makeFootnote(Footnote * hbox)
+{
+ if (hbox->type)
+ {
+ mxList->addAttribute("text:id", sXML_CDATA, "edn" + OUString::number(hbox->number));
+ startEl("text:endnote");
+ mxList->clear();
+ mxList->addAttribute("text:label", sXML_CDATA, OUString::number(hbox->number));
+ startEl("text:endnote-citation");
+ mxList->clear();
+ chars(OUString::number(hbox->number));
+ endEl("text:endnote-citation");
+ startEl("text:endnote-body");
+ if (!hbox->plist.empty())
+ parsePara(hbox->plist.front().get());
+ endEl("text:endnote-body");
+ endEl("text:endnote");
+ }
+ else
+ {
+ mxList->addAttribute("text:id", sXML_CDATA, "ftn" + OUString::number(hbox->number));
+ startEl("text:footnote");
+ mxList->clear();
+ mxList->addAttribute("text:label", sXML_CDATA, OUString::number(hbox->number));
+ startEl("text:footnote-citation");
+ mxList->clear();
+ chars(OUString::number(hbox->number));
+ endEl("text:footnote-citation");
+ startEl("text:footnote-body");
+ if (!hbox->plist.empty())
+ parsePara(hbox->plist.front().get());
+ endEl("text:footnote-body");
+ endEl("text:footnote");
+ }
+}
+
+
+/**
+ * page/footnote/endnote/picture/table/formula number
+ */
+void HwpReader::makeAutoNum(AutoNum const * hbox)
+{
+ switch (hbox->type)
+ {
+ case PGNUM_AUTO:
+ startEl("text:page-number");
+ chars(OUString::number(hbox->number));
+ endEl("text:page-number");
+ break;
+ case FNNUM_AUTO:
+ break;
+ case ENNUM_AUTO:
+ break;
+ case EQUNUM_AUTO:
+ case PICNUM_AUTO:
+ mxList->addAttribute("text:ref-name",sXML_CDATA, "refIllustration" + OUString::number(hbox->number));
+ mxList->addAttribute("text:name",sXML_CDATA, "Illustration");
+ mxList->addAttribute("style:num-format",sXML_CDATA, "1");
+ startEl("text:sequence");
+ chars(OUString::number(hbox->number));
+ endEl("text:sequence");
+ break;
+ case TBLNUM_AUTO:
+ mxList->addAttribute("text:ref-name",sXML_CDATA, "refTable" + OUString::number(hbox->number));
+ mxList->addAttribute("text:name",sXML_CDATA, "Table");
+ mxList->addAttribute("style:num-format",sXML_CDATA, "1");
+ startEl("text:sequence");
+ chars(OUString::number(hbox->number));
+ endEl("text:sequence");
+ 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("draw:style-name", sXML_CDATA, "PNBox" + OUString::number(nPos));
+ mxList->addAttribute("draw:name", sXML_CDATA, "PageNumber" + OUString::number(nPos));
+ mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
+ mxList->addAttribute("svg:y", sXML_CDATA, "0cm");
+ mxList->addAttribute("svg:width", sXML_CDATA, "2.0cm");
+ mxList->addAttribute("fo:min-height", sXML_CDATA, "0.5cm");
+ startEl("draw:text-box");
+ mxList->clear();
+
+ mxList->addAttribute("text:style-name", sXML_CDATA, "PNPara" + OUString::number(nPos));
+ startEl("text:p");
+ mxList->clear();
+ if( hbox->shape > 2 )
+ chars("- ");
+ if( hbox->shape % 3 == 0 )
+ mxList->addAttribute("style:num-format", sXML_CDATA, "1");
+ else if( hbox->shape % 3 == 1 )
+ mxList->addAttribute("style:num-format", sXML_CDATA, "I");
+ else
+ mxList->addAttribute("style:num-format", sXML_CDATA, "i");
+ mxList->addAttribute("text:select-page", sXML_CDATA, "current");
+ startEl("text:page-number");
+ mxList->clear();
+ chars("2");
+ endEl("text:page-number");
+ if( hbox->shape > 2 )
+ chars(" -");
+ endEl("text:p");
+ endEl("draw:text-box");
+}
+
+
+/**
+ * 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("text:style-name", sXML_CDATA,
+ getPStyleName(para->GetParaShape().index));
+ startEl("text:p");
+ mxList->clear();
+ }
+ if( d->bFirstPara && d->bInBody )
+ {
+/* for HWP's Bookmark */
+ mxList->addAttribute("text:name", sXML_CDATA, sBeginOfDoc);
+ startEl("text:bookmark");
+ mxList->clear();
+ endEl("text:bookmark");
+ d->bFirstPara = false;
+ }
+ if( d->bInHeader )
+ {
+ makeShowPageNum();
+ d->bInHeader = false;
+ }
+
+ endEl("text:p");
+ }
+ 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 OUStringLiteral SERVICE_NAME1 = u"com.sun.star.document.ImportFilter";
+constexpr OUStringLiteral SERVICE_NAME2 = u"com.sun.star.document.ExtendedTypeDetection";
+
+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:
+ Reference< XFilter > rFilter;
+ Reference< XImporter > rImporter;
+};
+
+
+HwpImportFilter::HwpImportFilter(const Reference< XComponentContext >& rxContext)
+{
+ try {
+ Reference< XDocumentHandler > xHandler( rxContext->getServiceManager()->createInstanceWithContext( WRITER_IMPORTER_NAME, rxContext ), UNO_QUERY );
+
+ rtl::Reference<HwpReader> p = new HwpReader;
+ p->setDocumentHandler( xHandler );
+
+ Reference< XImporter > xImporter( xHandler, UNO_QUERY );
+ rImporter = xImporter;
+ rFilter = p;
+ }
+ catch( Exception & )
+ {
+ printf(" fail to instantiate %s\n", OUString(WRITER_IMPORTER_NAME).toUtf8().getStr() );
+ exit( 1 );
+ }
+}
+
+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<const char*>(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<css::uno::Any> const&)
+{
+ return cppu::acquire(new HwpImportFilter(context));
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */