CppunitTest_sc_tiledrendering2: move to tiledrendering folder
[LibreOffice.git] / hwpfilter / source / hwpreader.cxx
blob7bc9d4dbf581321fd2218e786a86311bce275591
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <deque>
21 #include <memory>
22 #include <string_view>
24 #include "hwpreader.hxx"
25 #include <cmath>
27 #include <o3tl/safeint.hxx>
28 #include <o3tl/sprintf.hxx>
29 #include <osl/diagnose.h>
30 #include <tools/stream.hxx>
31 #include <basegfx/numeric/ftools.hxx>
32 #include <basegfx/point/b2dpoint.hxx>
33 #include <comphelper/configuration.hxx>
35 #include "fontmap.hxx"
36 #include "formula.h"
37 #include "cspline.h"
38 #include "datecode.h"
40 #include <iostream>
41 #include <locale.h>
42 #include <sal/types.h>
43 #include <rtl/character.hxx>
44 #include <rtl/ustrbuf.hxx>
45 #include <sal/log.hxx>
47 // xmloff/xmlkyd.hxx
48 constexpr OUString sXML_CDATA = u"CDATA"_ustr;
50 namespace
52 double WTI(double x) { return x / 1800.; } // unit => inch
53 double WTMM(double x) { return x / 1800. * 25.4; } // unit => mm
54 int WTSM(double x) { return x / 1800. * 2540; } // unit ==> 1/100 mm
56 constexpr OUString sBeginOfDoc(u"[\uBB38\uC11C\uC758 \uCC98\uC74C]"_ustr);
57 // U+BB38 HANGUL SYLLABLE MUN, U+C11C HANGUL SYLLABLE SEO,
58 // U+C758 HANGUL SYLLABLE YI, U+CC98 HANGUL SYLLABLE CEO,
59 // U+C74C HANGUL SYLLABLE EUM: "Begin of Document"
62 struct HwpReaderPrivate
64 HwpReaderPrivate()
66 bFirstPara = true;
67 bInBody = false;
68 bInHeader = false;
69 nPnPos = 0;
70 pPn = nullptr;
71 pField = nullptr;
73 bool bFirstPara;
74 bool bInBody;
75 bool bInHeader;
76 ShowPageNum *pPn;
77 hchar *pField;
78 int nPnPos;
79 char buf[1024];
82 HwpReader::HwpReader() : mxList(new AttributeListImpl), d(new HwpReaderPrivate)
87 HwpReader::~HwpReader()
91 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportHWP(SvStream &rStream)
93 try
95 std::unique_ptr<HStream> stream(new HStream);
96 byte aData[32768];
98 while (true)
100 std::size_t nRead = rStream.ReadBytes(aData, 32768);
101 if (nRead == 0)
102 break;
103 stream->addData(aData, static_cast<int>(nRead));
106 rtl::Reference<HwpReader> hwpreader(new HwpReader);
107 return hwpreader->importHStream(std::move(stream));
109 catch (...)
112 return false;
115 bool HwpReader::importHStream(std::unique_ptr<HStream> stream)
117 if (hwpfile.ReadHwpFile(std::move(stream)))
118 return false;
120 if (m_rxDocumentHandler.is())
121 m_rxDocumentHandler->startDocument();
123 mxList->addAttribute(u"office:class"_ustr, sXML_CDATA, u"text"_ustr);
124 mxList->addAttribute(u"office:version"_ustr, sXML_CDATA, u"0.9"_ustr);
126 mxList->addAttribute(u"xmlns:office"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/office"_ustr);
127 mxList->addAttribute(u"xmlns:style"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/style"_ustr);
128 mxList->addAttribute(u"xmlns:text"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/text"_ustr);
129 mxList->addAttribute(u"xmlns:table"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/table"_ustr);
130 mxList->addAttribute(u"xmlns:draw"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/drawing"_ustr);
131 mxList->addAttribute(u"xmlns:fo"_ustr, u"CDATA"_ustr, u"http://www.w3.org/1999/XSL/Format"_ustr);
132 mxList->addAttribute(u"xmlns:xlink"_ustr, u"CDATA"_ustr, u"http://www.w3.org/1999/xlink"_ustr);
133 mxList->addAttribute(u"xmlns:dc"_ustr, u"CDATA"_ustr, u"http://purl.org/dc/elements/1.1/"_ustr);
134 mxList->addAttribute(u"xmlns:meta"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/meta"_ustr);
135 mxList->addAttribute(u"xmlns:number"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/datastyle"_ustr);
136 mxList->addAttribute(u"xmlns:svg"_ustr, u"CDATA"_ustr, u"http://www.w3.org/2000/svg"_ustr);
137 mxList->addAttribute(u"xmlns:chart"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/chart"_ustr);
138 mxList->addAttribute(u"xmlns:dr3d"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/dr3d"_ustr);
139 mxList->addAttribute(u"xmlns:math"_ustr, u"CDATA"_ustr, u"http://www.w3.org/1998/Math/MathML"_ustr);
140 mxList->addAttribute(u"xmlns:form"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/form"_ustr);
141 mxList->addAttribute(u"xmlns:script"_ustr, u"CDATA"_ustr, u"http://openoffice.org/2000/script"_ustr);
143 startEl(u"office:document"_ustr);
144 mxList->clear();
146 makeMeta();
147 makeStyles();
148 makeAutoStyles();
149 makeMasterStyles();
150 makeBody();
152 endEl(u"office:document"_ustr);
154 if (m_rxDocumentHandler.is())
155 m_rxDocumentHandler->endDocument();
156 return true;
159 sal_Bool HwpReader::filter(const Sequence< PropertyValue >& rDescriptor)
161 utl::MediaDescriptor aDescriptor(rDescriptor);
162 aDescriptor.addInputStream();
164 Reference< XInputStream > xInputStream(
165 aDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM], UNO_QUERY_THROW);
167 std::unique_ptr<HStream> stream(new HStream);
168 Sequence < sal_Int8 > aBuffer;
169 sal_Int32 nRead, nTotal = 0;
170 while( true )
172 nRead = xInputStream->readBytes(aBuffer, 32768);
173 if( nRead == 0 )
174 break;
175 stream->addData( reinterpret_cast<const byte *>(aBuffer.getConstArray()), nRead );
176 nTotal += nRead;
179 if( nTotal == 0 ) return false;
181 return importHStream(std::move(stream));
185 * make office:body
187 void HwpReader::makeBody()
189 startEl(u"office:body"_ustr);
190 makeTextDecls();
191 HWPPara *hwppara = hwpfile.GetFirstPara();
192 d->bInBody = true;
193 parsePara(hwppara);
194 endEl(u"office:body"_ustr);
195 d->bInBody = false;
200 * make text decls
202 void HwpReader::makeTextDecls()
204 startEl(u"text:sequence-decls"_ustr);
205 mxList->addAttribute(u"text:display-outline-level"_ustr, sXML_CDATA, u"0"_ustr);
206 mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, u"Illustration"_ustr);
207 startEl(u"text:sequence-decl"_ustr);
208 mxList->clear();
209 endEl(u"text:sequence-decl"_ustr);
210 mxList->addAttribute(u"text:display-outline-level"_ustr, sXML_CDATA, u"0"_ustr);
211 mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, u"Table"_ustr);
212 startEl(u"text:sequence-decl"_ustr);
213 mxList->clear();
214 endEl(u"text:sequence-decl"_ustr);
215 mxList->addAttribute(u"text:display-outline-level"_ustr, sXML_CDATA, u"0"_ustr);
216 mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, u"Text"_ustr);
217 startEl(u"text:sequence-decl"_ustr);
218 mxList->clear();
219 endEl(u"text:sequence-decl"_ustr);
220 mxList->addAttribute(u"text:display-outline-level"_ustr, sXML_CDATA, u"0"_ustr);
221 mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, u"Drawing"_ustr);
222 startEl(u"text:sequence-decl"_ustr);
223 mxList->clear();
224 endEl(u"text:sequence-decl"_ustr);
225 endEl(u"text:sequence-decls"_ustr);
230 * make office:meta
231 * Completed
233 void HwpReader::makeMeta()
235 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
237 startEl(u"office:meta"_ustr);
239 if (hwpinfo.summary.title[0])
241 startEl(u"dc:title"_ustr);
242 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.title)));
243 endEl(u"dc:title"_ustr);
246 if (hwpinfo.summary.subject[0])
248 startEl(u"dc:subject"_ustr);
249 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.subject)));
250 endEl(u"dc:subject"_ustr);
253 if (hwpinfo.summary.author[0])
255 startEl(u"meta:initial-creator"_ustr);
256 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.author)));
257 endEl(u"meta:initial-creator"_ustr);
260 if (hwpinfo.summary.date[0])
262 unsigned short *pDate = hwpinfo.summary.date;
263 int year,month,day,hour,minute;
264 int gab = 0;
265 if( rtl::isAsciiDigit( pDate[0] ) && rtl::isAsciiDigit( pDate[1] ) &&
266 rtl::isAsciiDigit( pDate[2] ) && rtl::isAsciiDigit( pDate[3] ))
268 year = (pDate[0]-0x30) * 1000 + (pDate[1]-0x30) * 100 +
269 (pDate[2]-0x30) * 10 + (pDate[3]-0x30);
271 else {
272 year = 0;
274 if( rtl::isAsciiDigit( pDate[6] ))
276 if( rtl::isAsciiDigit( pDate[7] ) )
277 month = (pDate[6] - 0x30) * 10 + (pDate[6+ ++gab]-0x30);
278 else
279 month = (pDate[6] - 0x30);
281 else {
282 month = 0;
284 if( rtl::isAsciiDigit( pDate[9 + gab] ) )
286 if( rtl::isAsciiDigit( pDate[10 + gab])) {
287 day = ( pDate[9 + gab] - 0x30 ) * 10 + (pDate[9+ gab + 1]-0x30);
288 ++gab;
289 } else
290 day = (pDate[9+gab]-0x30);
292 else {
293 day = 0;
295 if( rtl::isAsciiDigit( pDate[17 + gab] ) )
297 if( rtl::isAsciiDigit( pDate[18 + gab])) {
298 hour = ( pDate[17 + gab] - 0x30 ) * 10 + (pDate[17+ gab + 1]-0x30);
299 ++gab;
300 } else
301 hour = (pDate[17+gab]-0x30);
303 else {
304 hour = 0;
306 if( rtl::isAsciiDigit( pDate[20 + gab] ) )
308 if( rtl::isAsciiDigit( pDate[21 + gab])) {
309 minute = ( pDate[20 + gab] - 0x30 ) * 10 + (pDate[20+ gab + 1]-0x30);
310 ++gab;
311 } else
312 minute = (pDate[20+gab]-0x30);
314 else {
315 minute = 0;
317 o3tl::sprintf(d->buf,"%d-%02d-%02dT%02d:%02d:00",year,month,day,hour,minute);
319 startEl(u"meta:creation-date"_ustr);
320 chars( OUString::createFromAscii(d->buf));
321 endEl(u"meta:creation-date"_ustr);
324 if (hwpinfo.summary.keyword[0][0] || hwpinfo.summary.etc[0][0])
326 startEl(u"meta:keywords"_ustr);
327 if (hwpinfo.summary.keyword[0][0])
329 startEl(u"meta:keyword"_ustr);
330 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.keyword[0])));
331 endEl(u"meta:keyword"_ustr);
333 if (hwpinfo.summary.keyword[1][0])
335 startEl(u"meta:keyword"_ustr);
336 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.keyword[1])));
337 endEl(u"meta:keyword"_ustr);
339 if (hwpinfo.summary.etc[0][0])
341 startEl(u"meta:keyword"_ustr);
342 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.etc[0])));
343 endEl(u"meta:keyword"_ustr);
345 if (hwpinfo.summary.etc[1][0])
347 startEl(u"meta:keyword"_ustr);
348 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.etc[1])));
349 endEl(u"meta:keyword"_ustr);
351 if (hwpinfo.summary.etc[2][0])
353 startEl(u"meta:keyword"_ustr);
354 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.etc[2])));
355 endEl(u"meta:keyword"_ustr);
357 endEl(u"meta:keywords"_ustr);
359 endEl(u"office:meta"_ustr);
363 static struct
365 const char *name;
366 bool bMade;
368 ArrowShape[] =
370 { "", false },
371 { "Arrow", false },
372 { "Line Arrow", false },
373 { "Square", false }
376 struct
378 double dots1;
379 double dots2;
380 double distance;
384 const LineStyle[] =
386 { 0.0, 0.0, 0.0 },
388 0.34, 0., 0.272
390 { 0.17, 0., 0.136},
392 0.612, 0.17, 0.136
394 { 0.85, 0.17, 0.136}
397 void HwpReader::makeDrawMiscStyle( HWPDrawingObject *hdo )
399 while( hdo )
401 if( hdo->child )
402 makeDrawMiscStyle( hdo->child.get() );
404 HWPDOProperty *prop = &hdo->property;
405 if( hdo->type == HWPDO_CONTAINER )
407 hdo = hdo->next.get();
408 continue;
411 if( prop->line_pstyle > 0 && prop->line_pstyle < 5 && prop->line_color <= 0xffffff)
413 mxList->addAttribute( u"draw:name"_ustr, sXML_CDATA, "LineType" + OUString::number(hdo->index));
414 mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"round"_ustr);
415 mxList->addAttribute( u"draw:dots1"_ustr, sXML_CDATA, u"1"_ustr);
416 mxList->addAttribute( u"draw:dots1-length"_ustr, sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots1 * WTMM(prop->line_width) ) + "cm");
417 if( prop->line_pstyle == 3 )
419 mxList->addAttribute( u"draw:dots2"_ustr, sXML_CDATA, u"1"_ustr);
420 mxList->addAttribute( u"draw:dots2-length"_ustr, sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width) ) + "cm");
422 else if( prop->line_pstyle == 4 )
424 mxList->addAttribute( u"draw:dots2"_ustr, sXML_CDATA, u"2"_ustr);
425 mxList->addAttribute( u"draw:dots2-length"_ustr, sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width)) + "cm");
427 mxList->addAttribute( u"draw:distance"_ustr, sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].distance * WTMM(prop->line_width)) + "cm");
428 startEl(u"draw:stroke-dash"_ustr);
429 mxList->clear();
430 endEl(u"draw:stroke-dash"_ustr);
433 if( hdo->type == HWPDO_LINE || hdo->type == HWPDO_ARC || hdo->type == HWPDO_FREEFORM ||
434 hdo->type == HWPDO_ADVANCED_ARC )
436 if( prop->line_tstyle > 0 &&
437 o3tl::make_unsigned(prop->line_tstyle) < std::size(ArrowShape) &&
438 !ArrowShape[prop->line_tstyle].bMade )
440 ArrowShape[prop->line_tstyle].bMade = true;
441 mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA,
442 OUString::createFromAscii(ArrowShape[prop->line_tstyle].name));
443 if( prop->line_tstyle == 1 )
445 mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 20 30"_ustr);
446 mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m10 0-10 30h20z"_ustr);
448 else if( prop->line_tstyle == 2 )
450 mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 1122 2243"_ustr);
451 mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z"_ustr);
453 else if( prop->line_tstyle == 3 )
455 mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 30 30"_ustr);
456 mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m0 0h30v30h-30z"_ustr);
458 startEl(u"draw:marker"_ustr);
459 mxList->clear();
460 endEl(u"draw:marker"_ustr);
462 if (prop->line_hstyle > 0 &&
463 o3tl::make_unsigned(prop->line_hstyle) < std::size(ArrowShape) &&
464 !ArrowShape[prop->line_hstyle].bMade)
466 ArrowShape[prop->line_hstyle].bMade = true;
467 mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA,
468 OUString::createFromAscii(ArrowShape[prop->line_hstyle].name));
469 if( prop->line_hstyle == 1 )
471 mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 20 30"_ustr);
472 mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m10 0-10 30h20z"_ustr);
474 else if( prop->line_hstyle == 2 )
476 mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 1122 2243"_ustr);
477 mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z"_ustr);
479 else if( prop->line_hstyle == 3 )
481 mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, u"0 0 20 20"_ustr);
482 mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, u"m0 0h20v20h-20z"_ustr);
484 startEl(u"draw:marker"_ustr);
485 mxList->clear();
486 endEl(u"draw:marker"_ustr);
490 if( hdo->type != HWPDO_LINE )
492 if( prop->flag >> 18 & 0x01 )
494 mxList->addAttribute( u"draw:name"_ustr, sXML_CDATA, "fillimage" + OUString::number(hdo->index));
496 EmPicture *emp = nullptr;
497 if (prop->pictype && strlen(prop->szPatternFile) > 3)
498 emp = hwpfile.GetEmPictureByName(prop->szPatternFile);
499 if (!emp)
501 mxList->addAttribute( u"xlink:href"_ustr, sXML_CDATA,
502 hstr2OUString(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(prop->szPatternFile).c_str())).c_str()));
503 mxList->addAttribute( u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr);
504 mxList->addAttribute( u"xlink:show"_ustr, sXML_CDATA, u"embed"_ustr);
505 mxList->addAttribute( u"xlink:actuate"_ustr, sXML_CDATA, u"onLoad"_ustr);
508 startEl(u"draw:fill-image"_ustr);
509 mxList->clear();
510 if (emp)
512 startEl(u"office:binary-data"_ustr);
513 chars(base64_encode_string(emp->data.data(), emp->size));
514 endEl(u"office:binary-data"_ustr);
516 endEl(u"draw:fill-image"_ustr);
518 /* If there is a gradient, when a bitmap file is present, this is the first. */
519 else if( prop->flag >> 16 & 0x01 ) /* existence gradient */
521 mxList->addAttribute( u"draw:name"_ustr, sXML_CDATA, "Grad" + OUString::number(hdo->index));
522 switch( prop->gstyle )
524 case 1 :
525 if( prop->center_y == 50 )
526 mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"axial"_ustr);
527 else
528 mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"linear"_ustr);
529 break;
530 case 2:
531 case 3:
532 mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"radial"_ustr);
533 break;
534 case 4:
535 mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"square"_ustr);
536 break;
537 default:
538 mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"linear"_ustr);
539 break;
541 mxList->addAttribute( u"draw:cx"_ustr, sXML_CDATA, OUString::number(prop->center_x) + "%");
542 mxList->addAttribute( u"draw:cy"_ustr, sXML_CDATA, OUString::number(prop->center_y) + "%");
544 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
545 int default_color = 0xffffff;
546 if( hwpinfo.back_info.isset )
548 if( hwpinfo.back_info.color[0] > 0 || hwpinfo.back_info.color[1] > 0
549 || hwpinfo.back_info.color[2] > 0 )
550 default_color = hwpinfo.back_info.color[0] << 16 |
551 hwpinfo.back_info.color[1] << 8 | hwpinfo.back_info.color[2];
554 if( prop->fromcolor > 0xffffff )
555 prop->fromcolor = default_color;
556 if( prop->tocolor > 0xffffff )
557 prop->tocolor = default_color;
559 if( prop->gstyle == 1)
561 if( prop->center_y == 100 )
563 mxList->addAttribute( u"draw:start-color"_ustr, sXML_CDATA, rgb2str( prop->tocolor ));
564 mxList->addAttribute( u"draw:end-color"_ustr, sXML_CDATA, rgb2str( prop->fromcolor ));
566 else
568 mxList->addAttribute( u"draw:start-color"_ustr, sXML_CDATA, rgb2str( prop->fromcolor ));
569 mxList->addAttribute( u"draw:end-color"_ustr, sXML_CDATA, rgb2str( prop->tocolor ));
572 else
574 mxList->addAttribute( u"draw:start-color"_ustr, sXML_CDATA,rgb2str( prop->tocolor ));
575 mxList->addAttribute( u"draw:end-color"_ustr, sXML_CDATA,rgb2str( prop->fromcolor ));
577 if( prop->angle > 0 && ( prop->gstyle == 1 || prop->gstyle == 4))
579 auto normangle = prop->angle % 360;
580 int angle = 1800 - normangle * 10;
581 mxList->addAttribute( u"draw:angle"_ustr, sXML_CDATA, OUString::number(angle));
583 startEl(u"draw:gradient"_ustr);
584 mxList->clear();
585 endEl(u"draw:gradient"_ustr);
587 /* hatch */
588 else if( prop->pattern_type >> 24 & 0x01 )
590 int type = prop->pattern_type & 0xffffff;
591 mxList->addAttribute( u"draw:name"_ustr, sXML_CDATA, "Hatch" + OUString::number(hdo->index));
592 if( type < 4 )
593 mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"single"_ustr );
594 else
595 mxList->addAttribute( u"draw:style"_ustr, sXML_CDATA, u"double"_ustr );
596 mxList->addAttribute( u"draw:color"_ustr, sXML_CDATA, rgb2str( static_cast<int32_t>(prop->pattern_color) ));
597 mxList->addAttribute( u"draw:distance"_ustr, sXML_CDATA, u"0.12cm"_ustr);
598 switch( type )
600 case 0 :
601 case 4 :
602 mxList->addAttribute( u"draw:rotation"_ustr, sXML_CDATA, u"0"_ustr);
603 break;
604 case 1 :
605 mxList->addAttribute( u"draw:rotation"_ustr, sXML_CDATA, u"900"_ustr);
606 break;
607 case 2 :
608 mxList->addAttribute( u"draw:rotation"_ustr, sXML_CDATA, u"1350"_ustr);
609 break;
610 case 3 :
611 case 5 :
612 mxList->addAttribute( u"draw:rotation"_ustr, sXML_CDATA, u"450"_ustr);
613 break;
615 startEl(u"draw:hatch"_ustr);
616 mxList->clear();
617 endEl(u"draw:hatch"_ustr);
620 hdo = hdo->next.get();
625 void HwpReader::makeStyles()
627 HWPStyle& hwpstyle = hwpfile.GetHWPStyle();
629 startEl(u"office:styles"_ustr);
631 int i;
632 for (i = 0; i < hwpfile.getFBoxStyleCount(); i++)
634 if( hwpfile.getFBoxStyle(i)->boxtype == 'D' )
636 makeDrawMiscStyle(static_cast<HWPDrawingObject *>(hwpfile.getFBoxStyle(i)->cell) );
640 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, u"Standard"_ustr);
641 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr);
642 mxList->addAttribute(u"style:class"_ustr, sXML_CDATA, u"text"_ustr);
643 startEl(u"style:style"_ustr);
644 mxList->clear();
646 mxList->addAttribute(u"fo:line-height"_ustr, sXML_CDATA, u"160%"_ustr);
647 mxList->addAttribute(u"fo:text-align"_ustr, sXML_CDATA, u"justify"_ustr);
648 startEl(u"style:properties"_ustr);
649 mxList->clear();
650 startEl(u"style:tab-stops"_ustr);
652 for( i = 1 ; i < 40 ; i++)
654 mxList->addAttribute(u"style:position"_ustr, sXML_CDATA,
655 OUString::number( WTI(1000 * i)) + "inch");
656 startEl(u"style:tab-stop"_ustr);
657 mxList->clear();
658 endEl(u"style:tab-stop"_ustr);
660 endEl(u"style:tab-stops"_ustr);
661 endEl(u"style:properties"_ustr);
663 endEl(u"style:style"_ustr);
665 for (int ii = 0; ii < hwpstyle.Num(); ii++)
667 unsigned char *stylename = reinterpret_cast<unsigned char *>(hwpstyle.GetName(ii));
668 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, hstr2OUString(kstr2hstr(stylename).c_str()));
669 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr);
670 mxList->addAttribute(u"style:parent-style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
672 startEl(u"style:style"_ustr);
674 mxList->clear();
676 parseCharShape(hwpstyle.GetCharShape(ii));
677 parseParaShape(hwpstyle.GetParaShape(ii));
679 startEl(u"style:properties"_ustr);
680 mxList->clear();
681 endEl(u"style:properties"_ustr);
683 endEl(u"style:style"_ustr);
687 mxList->addAttribute( u"style:name"_ustr, sXML_CDATA, u"Header"_ustr);
688 mxList->addAttribute( u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr);
689 mxList->addAttribute( u"style:parent-style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
690 mxList->addAttribute( u"style:class"_ustr, sXML_CDATA, u"extra"_ustr);
691 startEl(u"style:style"_ustr);
692 mxList->clear();
693 endEl(u"style:style"_ustr);
697 mxList->addAttribute( u"style:name"_ustr, sXML_CDATA, u"Footer"_ustr);
698 mxList->addAttribute( u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr);
699 mxList->addAttribute( u"style:parent-style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
700 mxList->addAttribute( u"style:class"_ustr, sXML_CDATA, u"extra"_ustr);
701 startEl(u"style:style"_ustr);
702 mxList->clear();
704 endEl(u"style:style"_ustr);
707 if( hwpfile.linenumber > 0)
709 mxList->addAttribute( u"style:name"_ustr, sXML_CDATA, u"Horizontal Line"_ustr);
710 mxList->addAttribute( u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr);
711 mxList->addAttribute( u"style:parent-style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
712 mxList->addAttribute( u"style:class"_ustr, sXML_CDATA, u"html"_ustr);
713 startEl(u"style:style"_ustr);
714 mxList->clear();
715 mxList->addAttribute( u"fo:font-size"_ustr, sXML_CDATA, u"6pt"_ustr);
716 mxList->addAttribute( u"fo:margin-top"_ustr, sXML_CDATA, u"0cm"_ustr);
717 mxList->addAttribute( u"fo:margin-bottom"_ustr, sXML_CDATA, u"0cm"_ustr);
718 mxList->addAttribute( u"style:border-line-width-bottom"_ustr, sXML_CDATA, u"0.02cm 0.035cm 0.002cm"_ustr);
719 mxList->addAttribute( u"fo:padding"_ustr, sXML_CDATA, u"0cm"_ustr);
720 mxList->addAttribute( u"fo:border-bottom"_ustr, sXML_CDATA, u"0.039cm double #808080"_ustr);
721 mxList->addAttribute( u"text:number-lines"_ustr, sXML_CDATA, u"false"_ustr);
722 mxList->addAttribute( u"text:line-number"_ustr, sXML_CDATA, u"0"_ustr);
723 mxList->addAttribute(u"fo:line-height"_ustr, sXML_CDATA, u"100%"_ustr);
724 startEl(u"style:properties"_ustr);
725 mxList->clear();
726 endEl(u"style:properties"_ustr);
727 endEl(u"style:style"_ustr);
730 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
732 mxList->addAttribute(u"text:num-suffix"_ustr, sXML_CDATA, u")"_ustr);
733 mxList->addAttribute(u"text:num-format"_ustr, sXML_CDATA, u"1"_ustr);
734 if( hwpinfo.beginfnnum != 1)
735 mxList->addAttribute(u"text:offset"_ustr, sXML_CDATA, OUString::number(hwpinfo.beginfnnum - 1));
736 startEl(u"text:footnotes-configuration"_ustr);
737 mxList->clear();
738 endEl(u"text:footnotes-configuration"_ustr);
740 endEl(u"office:styles"_ustr);
745 * parse automatic styles from hwpfile
746 * 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.
747 * 1. supports for the styles of paragraph, text, fbox, and page.
749 void HwpReader::makeAutoStyles()
751 int i;
753 startEl(u"office:automatic-styles"_ustr);
755 for (i = 0; i < hwpfile.getParaShapeCount(); i++)
756 makePStyle(hwpfile.getParaShape(i));
758 for (i = 0; i < hwpfile.getCharShapeCount(); i++)
759 makeTStyle(hwpfile.getCharShape(i));
761 for( i = 0 ; i < hwpfile.getTableCount(); i++)
762 makeTableStyle(hwpfile.getTable(i));
764 for (i = 0; i < hwpfile.getFBoxStyleCount(); i++)
766 if( hwpfile.getFBoxStyle(i)->boxtype == 'D' )
767 makeDrawStyle(static_cast<HWPDrawingObject *>(hwpfile.getFBoxStyle(i)->cell), hwpfile.getFBoxStyle(i));
768 else
769 makeFStyle(hwpfile.getFBoxStyle(i));
772 bool bIsLeft = false, bIsMiddle = false, bIsRight = false;
773 for( i = 0 ; i < hwpfile.getPageNumberCount() ; i++ )
775 ShowPageNum *pn = hwpfile.getPageNumber(i);
776 if( pn->where == 7 || pn->where == 8 )
778 bIsLeft = true;
779 bIsRight = true;
781 else if( pn->where == 1 || pn->where == 4 )
783 bIsLeft = true;
785 else if( pn->where == 2 || pn->where == 5 )
787 bIsMiddle = true;
789 else if( pn->where == 3 || pn->where == 6 )
791 bIsRight = true;
795 for( i = 1; i <= 3 ; i++ )
797 if( i == 1 && !bIsLeft )
798 continue;
799 if( i == 2 && !bIsMiddle )
800 continue;
801 if( i == 3 && !bIsRight )
802 continue;
803 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "PNPara" + OUString::number(i));
804 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr);
805 mxList->addAttribute(u"style:parent-style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
806 startEl(u"style:style"_ustr);
807 mxList->clear();
808 if( i == 1 )
809 mxList->addAttribute(u"fo:text-align"_ustr, sXML_CDATA, u"start"_ustr);
810 else if ( i == 2 )
811 mxList->addAttribute(u"fo:text-align"_ustr, sXML_CDATA, u"center"_ustr);
812 else if ( i == 3 )
813 mxList->addAttribute(u"fo:text-align"_ustr, sXML_CDATA, u"end"_ustr);
814 startEl(u"style:properties"_ustr);
815 mxList->clear();
816 endEl(u"style:properties"_ustr);
817 endEl(u"style:style"_ustr);
819 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "PNBox" + OUString::number(i));
820 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr);
821 startEl(u"style:style"_ustr);
822 mxList->clear();
824 mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA, u"0cm"_ustr);
825 mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA, u"0cm"_ustr);
826 mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"run-through"_ustr);
827 mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"from-top"_ustr);
828 mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"paragraph"_ustr);
830 if( i == 1 )
831 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"left"_ustr);
832 else if ( i == 2 )
833 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"center"_ustr);
834 else if ( i == 3 )
835 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"right"_ustr);
836 mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr);
837 mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA, u"0cm"_ustr);
838 mxList->addAttribute(u"stylefamily"_ustr, sXML_CDATA, u"graphics"_ustr);
839 startEl(u"style:properties"_ustr);
840 mxList->clear();
841 endEl(u"style:properties"_ustr);
842 endEl(u"style:style"_ustr);
845 for (i = 0; i < hwpfile.getDateFormatCount(); i++)
846 makeDateFormat(hwpfile.getDateCode(i));
848 makePageStyle();
850 endEl(u"office:automatic-styles"_ustr);
853 namespace {
855 struct PageSetting
857 PageSetting()
859 header = nullptr;
860 header_odd = nullptr;
861 header_even = nullptr;
862 footer = nullptr;
863 footer_odd = nullptr;
864 footer_even = nullptr;
865 pagenumber=nullptr;
866 bIsSet = false;
868 HeaderFooter *header ;
869 HeaderFooter *header_odd ;
870 HeaderFooter *header_even ;
871 HeaderFooter *footer ;
872 HeaderFooter *footer_odd ;
873 HeaderFooter *footer_even ;
874 ShowPageNum *pagenumber;
875 bool bIsSet;
880 void HwpReader::makeMasterStyles()
882 startEl(u"office:master-styles"_ustr);
884 int i;
885 int nMax = hwpfile.getMaxSettedPage();
886 std::vector<PageSetting> aSet(nMax + 1);
888 for( i = 0 ; i < hwpfile.getPageNumberCount() ; i++ )
890 ShowPageNum *pn = hwpfile.getPageNumber(i);
891 aSet[pn->m_nPageNumber].pagenumber = pn;
892 aSet[pn->m_nPageNumber].bIsSet = true;
894 for( i = 0 ; i < hwpfile.getHeaderFooterCount() ; i++ )
896 HeaderFooter* hf = hwpfile.getHeaderFooter(i);
897 aSet[hf->m_nPageNumber].bIsSet = true;
898 if( hf->type == 0 ) // header
900 switch( hf->where )
902 case 0 :
903 aSet[hf->m_nPageNumber].header = hf;
904 aSet[hf->m_nPageNumber].header_even = nullptr;
905 aSet[hf->m_nPageNumber].header_odd = nullptr;
906 break;
907 case 1:
908 aSet[hf->m_nPageNumber].header_even = hf;
909 if( aSet[hf->m_nPageNumber].header )
911 aSet[hf->m_nPageNumber].header_odd =
912 aSet[hf->m_nPageNumber].header;
913 aSet[hf->m_nPageNumber].header = nullptr;
915 break;
916 case 2:
917 aSet[hf->m_nPageNumber].header_odd = hf;
918 if( aSet[hf->m_nPageNumber].header )
920 aSet[hf->m_nPageNumber].header_even =
921 aSet[hf->m_nPageNumber].header;
922 aSet[hf->m_nPageNumber].header = nullptr;
924 break;
927 else // footer
929 switch( hf->where )
931 case 0 :
932 aSet[hf->m_nPageNumber].footer = hf;
933 aSet[hf->m_nPageNumber].footer_even = nullptr;
934 aSet[hf->m_nPageNumber].footer_odd = nullptr;
935 break;
936 case 1:
937 aSet[hf->m_nPageNumber].footer_even = hf;
938 if( aSet[hf->m_nPageNumber].footer )
940 aSet[hf->m_nPageNumber].footer_odd =
941 aSet[hf->m_nPageNumber].footer;
942 aSet[hf->m_nPageNumber].footer = nullptr;
944 break;
945 case 2:
946 aSet[hf->m_nPageNumber].footer_odd = hf;
947 if( aSet[hf->m_nPageNumber].footer )
949 aSet[hf->m_nPageNumber].footer_even =
950 aSet[hf->m_nPageNumber].footer;
951 aSet[hf->m_nPageNumber].footer = nullptr;
953 break;
958 PageSetting *pPrevSet = nullptr;
959 PageSetting *pPage = nullptr;
961 if (nMax > 512 && comphelper::IsFuzzing())
963 SAL_WARN("filter.hwp", "too many pages: " << nMax << " clip to " << 512);
964 nMax = 512;
967 for( i = 1; i <= nMax ; i++ )
969 if( i == 1 )
970 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, u"Standard"_ustr);
971 else
972 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "p" + OUString::number(i));
973 mxList->addAttribute(u"style:page-master-name"_ustr, sXML_CDATA,
974 "pm" + OUString::number(hwpfile.GetPageMasterNum(i)));
975 if( i < nMax )
976 mxList->addAttribute(u"style:next-style-name"_ustr, sXML_CDATA, "p" + OUString::number(i + 1));
977 mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "master" + OUString::number(i));
978 startEl(u"style:master-page"_ustr);
979 mxList->clear();
981 if( aSet[i].bIsSet ) /* If you've changed the current setting */
983 if( !aSet[i].pagenumber ){
984 if( pPrevSet && pPrevSet->pagenumber )
985 aSet[i].pagenumber = pPrevSet->pagenumber;
987 if( aSet[i].pagenumber )
989 if( aSet[i].pagenumber->where == 7 && aSet[i].header )
991 aSet[i].header_even = aSet[i].header;
992 aSet[i].header_odd = aSet[i].header;
993 aSet[i].header = nullptr;
995 if( aSet[i].pagenumber->where == 8 && aSet[i].footer )
997 aSet[i].footer_even = aSet[i].footer;
998 aSet[i].footer_odd = aSet[i].footer;
999 aSet[i].footer = nullptr;
1003 if( !aSet[i].header_even && pPrevSet && pPrevSet->header_even )
1005 aSet[i].header_even = pPrevSet->header_even;
1007 if( !aSet[i].header_odd && pPrevSet && pPrevSet->header_odd )
1009 aSet[i].header_odd = pPrevSet->header_odd;
1011 if( !aSet[i].footer_even && pPrevSet && pPrevSet->footer_even )
1013 aSet[i].footer_even = pPrevSet->footer_even;
1015 if( !aSet[i].footer_odd && pPrevSet && pPrevSet->footer_odd )
1017 aSet[i].footer_odd = pPrevSet->footer_odd;
1020 pPage = &aSet[i];
1021 pPrevSet = &aSet[i];
1023 else if( pPrevSet ) /* If the previous setting exists */
1025 pPage = pPrevSet;
1027 else /* If the previous settings doesn't exist, set to the default settings */
1029 startEl(u"style:header"_ustr);
1030 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
1031 startEl(u"text:p"_ustr);
1032 mxList->clear();
1033 endEl(u"text:p"_ustr);
1034 endEl(u"style:header"_ustr);
1036 startEl(u"style:footer"_ustr);
1037 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
1038 startEl(u"text:p"_ustr);
1039 mxList->clear();
1040 endEl(u"text:p"_ustr);
1041 endEl(u"style:footer"_ustr);
1043 endEl(u"style:master-page"_ustr);
1045 continue;
1047 // header
1048 if( pPage->header )
1050 startEl(u"style:header"_ustr);
1051 if( pPage->pagenumber && pPage->pagenumber->where < 4 )
1053 d->bInHeader = true;
1054 d->pPn = pPage->pagenumber;
1056 if (!pPage->header->plist.empty())
1057 parsePara(pPage->header->plist.front().get());
1058 d->bInHeader = false;
1059 d->pPn = nullptr;
1060 endEl(u"style:header"_ustr);
1062 if( pPage->header_even )
1064 startEl(u"style:header"_ustr);
1065 if( pPage->pagenumber && ( pPage->pagenumber->where < 4
1066 || pPage->pagenumber->where == 7 ) )
1068 d->bInHeader = true;
1069 d->pPn = pPage->pagenumber;
1070 d->nPnPos = 3;
1072 if (!pPage->header_even->plist.empty())
1073 parsePara(pPage->header_even->plist.front().get());
1074 d->bInHeader = false;
1075 d->pPn = nullptr;
1076 d->nPnPos = 0;
1077 endEl(u"style:header"_ustr);
1079 /* Will be the default. */
1080 else if (pPage->header_odd)
1082 startEl(u"style:header"_ustr);
1083 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
1084 startEl(u"text:p"_ustr);
1085 mxList->clear();
1086 if( pPage->pagenumber && ( pPage->pagenumber->where < 4 ||
1087 pPage->pagenumber->where == 7 ) )
1089 d->pPn = pPage->pagenumber;
1090 d->nPnPos = 3;
1091 makeShowPageNum();
1092 d->pPn = nullptr;
1093 d->nPnPos = 0;
1095 endEl(u"text:p"_ustr);
1096 endEl(u"style:header"_ustr);
1098 if( pPage->header_odd )
1100 startEl(u"style:header-left"_ustr);
1101 if( pPage->pagenumber && ( pPage->pagenumber->where < 4
1102 || pPage->pagenumber->where == 7 ) )
1104 d->bInHeader = true;
1105 d->nPnPos = 1;
1106 d->pPn = pPage->pagenumber;
1108 if (!pPage->header_odd->plist.empty())
1109 parsePara(pPage->header_odd->plist.front().get());
1110 d->bInHeader = false;
1111 d->pPn = nullptr;
1112 d->nPnPos = 0;
1113 endEl(u"style:header-left"_ustr);
1115 /* Will be the default. */
1116 else if (pPage->header_even)
1118 startEl(u"style:header-left"_ustr);
1119 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
1120 startEl(u"text:p"_ustr);
1121 mxList->clear();
1122 if( pPage->pagenumber && ( pPage->pagenumber->where < 4 ||
1123 pPage->pagenumber->where == 7 ) )
1125 d->pPn = pPage->pagenumber;
1126 d->nPnPos = 1;
1127 makeShowPageNum();
1128 d->pPn = nullptr;
1129 d->nPnPos = 0;
1131 endEl(u"text:p"_ustr);
1132 endEl(u"style:header-left"_ustr);
1134 if( !pPage->header && !pPage->header_even && !pPage->header_odd )
1136 startEl(u"style:header"_ustr);
1137 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
1138 startEl(u"text:p"_ustr);
1139 mxList->clear();
1140 if( pPage->pagenumber && (pPage->pagenumber->where < 4 ||
1141 pPage->pagenumber->where == 7 ) )
1143 d->pPn = pPage->pagenumber;
1144 makeShowPageNum();
1145 d->pPn = nullptr;
1147 endEl(u"text:p"_ustr);
1148 endEl(u"style:header"_ustr);
1150 // footer
1151 if( pPage->footer )
1153 startEl(u"style:footer"_ustr);
1154 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1155 && pPage->pagenumber->where != 7 )
1157 d->bInHeader = true;
1158 d->pPn = pPage->pagenumber;
1160 if (!pPage->footer->plist.empty())
1161 parsePara(pPage->footer->plist.front().get());
1162 d->bInHeader = false;
1163 d->pPn = nullptr;
1164 endEl(u"style:footer"_ustr);
1166 if( pPage->footer_even )
1168 startEl(u"style:footer"_ustr);
1169 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1170 && pPage->pagenumber->where != 7 )
1172 d->bInHeader = true;
1173 d->pPn = pPage->pagenumber;
1174 d->nPnPos = 3;
1176 if (!pPage->footer_even->plist.empty())
1177 parsePara(pPage->footer_even->plist.front().get());
1178 d->bInHeader = false;
1179 d->pPn = nullptr;
1180 d->nPnPos = 0;
1181 endEl(u"style:footer"_ustr);
1183 /* Will be the default. */
1184 else if (pPage->footer_odd)
1186 startEl(u"style:footer"_ustr);
1187 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
1188 startEl(u"text:p"_ustr);
1189 mxList->clear();
1190 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1191 && pPage->pagenumber->where != 7 )
1193 d->pPn = pPage->pagenumber;
1194 d->nPnPos = 3;
1195 makeShowPageNum();
1196 d->pPn = nullptr;
1197 d->nPnPos = 0;
1199 endEl(u"text:p"_ustr);
1200 endEl(u"style:footer"_ustr);
1202 if( pPage->footer_odd )
1204 startEl(u"style:footer-left"_ustr);
1205 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1206 && pPage->pagenumber->where != 7 )
1208 d->bInHeader = true;
1209 d->pPn = pPage->pagenumber;
1210 d->nPnPos = 1;
1212 if (!pPage->footer_odd->plist.empty())
1213 parsePara(pPage->footer_odd->plist.front().get());
1214 d->bInHeader = false;
1215 d->pPn = nullptr;
1216 d->nPnPos = 0;
1217 endEl(u"style:footer-left"_ustr);
1219 /* Will be the default. */
1220 else if (pPage->footer_even)
1222 startEl(u"style:footer-left"_ustr);
1223 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
1224 startEl(u"text:p"_ustr);
1225 mxList->clear();
1226 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1227 && pPage->pagenumber->where != 7 )
1229 d->pPn = pPage->pagenumber;
1230 d->nPnPos = 1;
1231 makeShowPageNum();
1232 d->pPn = nullptr;
1233 d->nPnPos = 0;
1235 endEl(u"text:p"_ustr);
1236 endEl(u"style:footer-left"_ustr);
1238 if( !pPage->footer && !pPage->footer_even && !pPage->footer_odd )
1240 startEl(u"style:footer"_ustr);
1241 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
1242 startEl(u"text:p"_ustr);
1243 mxList->clear();
1244 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1245 && pPage->pagenumber->where != 7 )
1247 d->pPn = pPage->pagenumber;
1248 makeShowPageNum();
1249 d->pPn = nullptr;
1251 endEl(u"text:p"_ustr);
1252 endEl(u"style:footer"_ustr);
1255 endEl(u"style:master-page"_ustr);
1257 endEl(u"office:master-styles"_ustr);
1262 * Create the properties for text styles.
1263 * 1. fo:font-size, fo:font-family, fo:letter-spacing, fo:color,
1264 * style:text-background-color, fo:font-style, fo:font-weight,
1265 * style:text-underline,style:text-outline,fo:text-shadow,style:text-position
1266 * Support them.
1268 void HwpReader::parseCharShape(CharShape const * cshape)
1270 HWPFont& hwpfont = hwpfile.GetHWPFont();
1272 mxList->addAttribute(u"fo:font-size"_ustr, sXML_CDATA, OUString::number(cshape->size / 25) + "pt");
1273 mxList->addAttribute(u"style:font-size-asian"_ustr, sXML_CDATA, OUString::number(cshape->size / 25) + "pt");
1275 ::std::string const tmp = hstr2ksstr(kstr2hstr(
1276 reinterpret_cast<unsigned char const *>(hwpfont.GetFontName(0, cshape->font))).c_str());
1277 double fRatio = 1.0;
1278 int size = getRepFamilyName(tmp.c_str(), d->buf, fRatio);
1280 mxList->addAttribute(u"fo:font-family"_ustr, sXML_CDATA,
1281 OUString(d->buf, size, RTL_TEXTENCODING_EUC_KR));
1282 mxList->addAttribute(u"style:font-family-asian"_ustr, sXML_CDATA,
1283 OUString(d->buf, size, RTL_TEXTENCODING_EUC_KR));
1285 mxList->addAttribute(u"style:text-scale"_ustr, sXML_CDATA,
1286 OUString::number(static_cast<int>(cshape->ratio * fRatio)) + "%");
1288 double sspace = (cshape->size / 25) * cshape->space / 100.;
1290 if (sspace != 0.)
1292 mxList->addAttribute(u"fo:letter-spacing"_ustr, sXML_CDATA,
1293 OUString::number(sspace) + "pt");
1295 if (cshape->color[1] != 0)
1296 mxList->addAttribute(u"fo:color"_ustr, sXML_CDATA,
1297 hcolor2str(cshape->color[1], 100, true));
1298 if (cshape->shade != 0)
1299 mxList->addAttribute(u"style:text-background-color"_ustr, sXML_CDATA,
1300 hcolor2str(cshape->color[0], cshape->shade));
1301 if (cshape->attr & 0x01)
1303 mxList->addAttribute(u"fo:font-style"_ustr, sXML_CDATA, u"italic"_ustr);
1304 mxList->addAttribute(u"style:font-style-asian"_ustr, sXML_CDATA, u"italic"_ustr);
1306 else{
1307 mxList->addAttribute(u"fo:font-style"_ustr, sXML_CDATA, u"normal"_ustr);
1308 mxList->addAttribute(u"style:font-style-asian"_ustr, sXML_CDATA, u"normal"_ustr);
1310 if (cshape->attr >> 1 & 0x01)
1312 mxList->addAttribute(u"fo:font-weight"_ustr, sXML_CDATA, u"bold"_ustr);
1313 mxList->addAttribute(u"style:font-weight-asian"_ustr, sXML_CDATA, u"bold"_ustr);
1315 else{
1316 mxList->addAttribute(u"fo:font-weight"_ustr, sXML_CDATA, u"normal"_ustr);
1317 mxList->addAttribute(u"style:font-weight-asian"_ustr, sXML_CDATA, u"normal"_ustr);
1319 if (cshape->attr >> 2 & 0x01)
1320 mxList->addAttribute(u"style:text-underline"_ustr, sXML_CDATA, u"single"_ustr);
1321 if (cshape->attr >> 3 & 0x01)
1322 mxList->addAttribute(u"style:text-outline"_ustr, sXML_CDATA, u"true"_ustr);
1323 if (cshape->attr >> 4 & 0x01)
1324 mxList->addAttribute(u"fo:text-shadow"_ustr, sXML_CDATA, u"1pt 1pt"_ustr);
1325 if (cshape->attr >> 5 & 0x01)
1326 mxList->addAttribute(u"style:text-position"_ustr, sXML_CDATA, u"super 58%"_ustr);
1327 if (cshape->attr >> 6 & 0x01)
1328 mxList->addAttribute(u"style:text-position"_ustr, sXML_CDATA, u"sub 58%"_ustr);
1334 * Create the properties that correspond to the real Paragraph.
1335 * 1. fo:margin-left,fo:margin-right,fo:margin-top, fo:margin-bottom,
1336 * fo:text-indent, fo:line-height, fo:text-align, fo:border
1337 * are implemented.
1338 * TODO: Tab Settings => set values of properties only which doesn't have the default value
1340 void HwpReader::parseParaShape(ParaShape const * pshape)
1343 if (pshape->left_margin != 0)
1344 mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA, OUString::number
1345 (WTI(pshape->left_margin )) + "inch");
1346 if (pshape->right_margin != 0)
1347 mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA, OUString::number
1348 (WTI(pshape->right_margin)) + "inch");
1349 if (pshape->pspacing_prev != 0)
1350 mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA, OUString::number
1351 (WTI(pshape->pspacing_prev)) + "inch");
1352 if (pshape->pspacing_next != 0)
1353 mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA, OUString::number
1354 (WTI(pshape->pspacing_next)) + "inch");
1355 if (pshape->indent != 0)
1356 mxList->addAttribute(u"fo:text-indent"_ustr, sXML_CDATA, OUString::number
1357 (WTI(pshape->indent)) + "inch");
1358 if (pshape->lspacing != 0)
1359 mxList->addAttribute(u"fo:line-height"_ustr, sXML_CDATA, OUString::number(pshape->lspacing) + "%");
1361 const char* align = nullptr;
1363 switch (static_cast<int>(pshape->arrange_type))
1365 case 1:
1366 align = "start";
1367 break;
1368 case 2:
1369 align = "end";
1370 break;
1371 case 3:
1372 align = "center";
1373 break;
1374 case 4:
1375 case 5:
1376 case 6:
1377 align = "justify";
1378 break;
1381 if (align)
1382 mxList->addAttribute(u"fo:text-align"_ustr, sXML_CDATA, OUString::createFromAscii(align));
1384 if (pshape->outline)
1385 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA, u"0.002cm solid #000000"_ustr);
1386 if( pshape->shade > 0 )
1388 mxList->addAttribute(u"fo:background-color"_ustr, sXML_CDATA,
1389 hcolor2str(0, pshape->shade));
1392 if( pshape->pagebreak & 0x02 || pshape->pagebreak & 0x04)
1393 mxList->addAttribute(u"fo:break-before"_ustr, sXML_CDATA, u"page"_ustr);
1394 else if( pshape->pagebreak & 0x01 )
1395 mxList->addAttribute(u"fo:break-before"_ustr, sXML_CDATA, u"column"_ustr);
1401 * Make the style of the Paragraph.
1403 void HwpReader::makePStyle(ParaShape const * pshape)
1405 int nscount = pshape->tabs[MAXTABS -1].type;
1406 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "P" + OUString::number(pshape->index));
1407 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"paragraph"_ustr);
1408 startEl(u"style:style"_ustr);
1409 mxList->clear();
1410 parseParaShape(pshape);
1411 if (pshape->cshape)
1412 parseCharShape(pshape->cshape.get());
1413 startEl(u"style:properties"_ustr);
1414 mxList->clear();
1416 if( nscount )
1418 unsigned char tf = 0;
1419 startEl(u"style:tab-stops"_ustr);
1421 int tab_margin = pshape->left_margin + pshape->indent;
1422 if( tab_margin < 0 )
1423 tab_margin = 0;
1424 for( int i = 0 ; i < MAXTABS -1 ; i++)
1426 if( i > 0 && pshape->tabs[i].position == 0. )
1427 break;
1428 if( pshape->tabs[i].position <= tab_margin )
1429 continue;
1430 mxList->addAttribute(u"style:position"_ustr, sXML_CDATA,
1431 OUString::number(WTMM(pshape->tabs[i].position - tab_margin )) + "mm");
1432 if( pshape->tabs[i].type )
1434 tf = 1;
1435 switch(pshape->tabs[i].type)
1437 case 1 :
1438 mxList->addAttribute(u"style:type"_ustr, sXML_CDATA, u"right"_ustr);
1439 break;
1440 case 2:
1441 mxList->addAttribute(u"style:type"_ustr, sXML_CDATA, u"center"_ustr);
1442 break;
1443 case 3:
1444 mxList->addAttribute(u"style:type"_ustr, sXML_CDATA, u"char"_ustr);
1445 mxList->addAttribute(u"style:char"_ustr, sXML_CDATA, u"."_ustr);
1446 break;
1449 if( pshape->tabs[i].dot_continue )
1451 tf = 1;
1452 mxList->addAttribute(u"style:leader-char"_ustr, sXML_CDATA, u"."_ustr);
1454 startEl(u"style:tab-stop"_ustr);
1455 mxList->clear();
1456 endEl(u"style:tab-stop"_ustr);
1458 if( (pshape->tabs[i].position != 1000 * i ) || tf )
1460 if( !--nscount ) break;
1463 endEl(u"style:tab-stops"_ustr);
1465 endEl(u"style:properties"_ustr);
1466 endEl(u"style:style"_ustr);
1471 * Create a style for the page. This includes the header/footer, footnote and more.
1472 * TODO: fo: background-color (no information)
1474 void HwpReader::makePageStyle()
1476 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
1477 int pmCount = hwpfile.getColumnCount();
1479 if (pmCount > 512 && comphelper::IsFuzzing())
1481 SAL_WARN("filter.hwp", "too many pages: " << pmCount << " clip to " << 512);
1482 pmCount = 512;
1485 for( int i = 0 ; i < pmCount ; i++ ){
1486 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "pm" + OUString::number(i + 1));
1487 startEl(u"style:page-master"_ustr);
1488 mxList->clear();
1491 switch( hwpinfo.paper.paper_kind )
1493 case 3: // A4
1494 if( hwpinfo.paper.paper_direction )
1496 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"210mm"_ustr);
1497 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"297mm"_ustr);
1499 else
1501 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"210mm"_ustr);
1502 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"297mm"_ustr);
1504 break;
1505 case 4: // 80 column
1506 if( hwpinfo.paper.paper_direction )
1508 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"8.5inch"_ustr);
1509 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"11inch"_ustr);
1511 else
1513 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"8.5inch"_ustr);
1514 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"11inch"_ustr);
1516 break;
1517 case 5: // B5
1518 if( hwpinfo.paper.paper_direction )
1520 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"176mm"_ustr);
1521 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"250mm"_ustr);
1523 else
1525 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"176mm"_ustr);
1526 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"250mm"_ustr);
1528 break;
1529 case 6: // B4
1530 if( hwpinfo.paper.paper_direction )
1532 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"250mm"_ustr);
1533 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"353mm"_ustr);
1535 else
1537 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"250mm"_ustr);
1538 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"353mm"_ustr);
1540 break;
1541 case 7:
1542 if( hwpinfo.paper.paper_direction )
1544 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"8.5inch"_ustr);
1545 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"14inch"_ustr);
1547 else
1549 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"8.5inch"_ustr);
1550 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"14inch"_ustr);
1552 break;
1553 case 8:
1554 if( hwpinfo.paper.paper_direction )
1556 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"297mm"_ustr);
1557 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"420mm"_ustr);
1559 else
1561 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA, u"297mm"_ustr);
1562 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA, u"420mm"_ustr);
1564 break;
1565 case 0:
1566 case 1:
1567 case 2:
1568 default:
1569 if( hwpinfo.paper.paper_direction )
1571 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA,
1572 OUString::number(WTI(hwpinfo.paper.paper_height)) + "inch");
1573 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA,
1574 OUString::number(WTI(hwpinfo.paper.paper_width)) + "inch");
1576 else
1578 mxList->addAttribute(u"fo:page-width"_ustr,sXML_CDATA,
1579 OUString::number(WTI(hwpinfo.paper.paper_width)) + "inch");
1580 mxList->addAttribute(u"fo:page-height"_ustr,sXML_CDATA,
1581 OUString::number(WTI(hwpinfo.paper.paper_height)) + "inch");
1583 break;
1587 mxList->addAttribute(u"style:print-orientation"_ustr,sXML_CDATA,
1588 OUString::createFromAscii(hwpinfo.paper.paper_direction ? "landscape" : "portrait"));
1589 if( hwpinfo.beginpagenum != 1)
1590 mxList->addAttribute(u"style:first-page-number"_ustr,sXML_CDATA, OUString::number(hwpinfo.beginpagenum));
1592 if( hwpinfo.borderline ){
1593 mxList->addAttribute(u"fo:margin-left"_ustr,sXML_CDATA,
1594 OUString::number(WTI(hwpinfo.paper.left_margin - hwpinfo.bordermargin[0] + hwpinfo.paper.gutter_length)) + "inch");
1595 mxList->addAttribute(u"fo:margin-right"_ustr,sXML_CDATA,
1596 OUString::number(WTI(hwpinfo.paper.right_margin - hwpinfo.bordermargin[1])) + "inch");
1597 mxList->addAttribute(u"fo:margin-top"_ustr,sXML_CDATA,
1598 OUString::number(WTI(hwpinfo.paper.top_margin - hwpinfo.bordermargin[2])) + "inch");
1599 mxList->addAttribute(u"fo:margin-bottom"_ustr,sXML_CDATA,
1600 OUString::number(WTI(hwpinfo.paper.bottom_margin - hwpinfo.bordermargin[3])) + "inch");
1602 else{
1603 mxList->addAttribute(u"fo:margin-left"_ustr,sXML_CDATA,
1604 OUString::number(WTI(hwpinfo.paper.left_margin + hwpinfo.paper.gutter_length)) + "inch");
1605 mxList->addAttribute(u"fo:margin-right"_ustr,sXML_CDATA,
1606 OUString::number(WTI(hwpinfo.paper.right_margin)) + "inch");
1607 mxList->addAttribute(u"fo:margin-top"_ustr,sXML_CDATA,
1608 OUString::number(WTI(hwpinfo.paper.top_margin)) + "inch");
1609 mxList->addAttribute(u"fo:margin-bottom"_ustr,sXML_CDATA,
1610 OUString::number(WTI(hwpinfo.paper.bottom_margin)) + "inch");
1613 switch( hwpinfo.borderline )
1615 case 1:
1616 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
1617 break;
1618 case 3:
1619 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.002cm dotted #000000"_ustr);
1620 break;
1621 case 2:
1622 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
1623 break;
1624 case 4:
1625 mxList->addAttribute(u"style:border-line-width"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
1626 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
1627 break;
1630 mxList->addAttribute(u"fo:padding-left"_ustr, sXML_CDATA,
1631 OUString::number(WTI(hwpinfo.bordermargin[0])) + "inch");
1632 mxList->addAttribute(u"fo:padding-right"_ustr, sXML_CDATA,
1633 OUString::number(WTI(hwpinfo.bordermargin[1])) + "inch");
1634 mxList->addAttribute(u"fo:padding-top"_ustr, sXML_CDATA,
1635 OUString::number(WTI(hwpinfo.bordermargin[2])) + "inch");
1636 mxList->addAttribute(u"fo:padding-bottom"_ustr, sXML_CDATA,
1637 OUString::number(WTI(hwpinfo.bordermargin[3])) + "inch");
1639 /* background color */
1640 if( hwpinfo.back_info.isset )
1642 if( hwpinfo.back_info.color[0] > 0 || hwpinfo.back_info.color[1] > 0
1643 || hwpinfo.back_info.color[2] > 0 ){
1644 mxList->addAttribute(u"fo:background-color"_ustr, sXML_CDATA,
1645 rgb2str(hwpinfo.back_info.color[0],
1646 hwpinfo.back_info.color[1],
1647 hwpinfo.back_info.color[2]));
1651 startEl(u"style:properties"_ustr);
1652 mxList->clear();
1654 /* background image */
1655 if( hwpinfo.back_info.isset && hwpinfo.back_info.type > 0 )
1657 if( hwpinfo.back_info.type == 1 ){
1658 #ifdef _WIN32
1659 mxList->addAttribute("xlink:href", sXML_CDATA,
1660 hstr2OUString(kstr2hstr(reinterpret_cast<uchar const *>(urltowin(hwpinfo.back_info.filename).c_str())).c_str()));
1661 #else
1662 mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA,
1663 hstr2OUString(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(hwpinfo.back_info.filename).c_str())).c_str()));
1664 #endif
1665 mxList->addAttribute(u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr);
1666 mxList->addAttribute(u"xlink:actuate"_ustr, sXML_CDATA, u"onLoad"_ustr);
1668 if( hwpinfo.back_info.flag >= 2)
1669 mxList->addAttribute(u"style:repeat"_ustr, sXML_CDATA, u"stretch"_ustr);
1670 else if( hwpinfo.back_info.flag == 1 ){
1671 mxList->addAttribute(u"style:repeat"_ustr, sXML_CDATA, u"no-repeat"_ustr);
1672 mxList->addAttribute(u"style:position"_ustr, sXML_CDATA, u"center"_ustr);
1674 startEl(u"style:background-image"_ustr);
1676 if( hwpinfo.back_info.type == 2 ){
1677 startEl(u"office:binary-data"_ustr);
1678 mxList->clear();
1679 chars(base64_encode_string(reinterpret_cast<unsigned char*>(hwpinfo.back_info.data.data()), hwpinfo.back_info.size));
1680 endEl(u"office:binary-data"_ustr);
1682 endEl(u"style:background-image"_ustr);
1685 makeColumns( hwpfile.GetColumnDef(i) );
1687 endEl(u"style:properties"_ustr);
1689 /* header style */
1690 startEl(u"style:header-style"_ustr);
1691 mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA,
1692 OUString::number(WTI(hwpinfo.paper.header_length)) + "inch");
1693 mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA, u"0mm"_ustr);
1695 startEl(u"style:properties"_ustr);
1696 mxList->clear();
1697 endEl(u"style:properties"_ustr);
1698 endEl(u"style:header-style"_ustr);
1700 /* footer style */
1701 startEl(u"style:footer-style"_ustr);
1702 mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA,
1703 OUString::number(WTI(hwpinfo.paper.footer_length)) + "inch");
1704 mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA, u"0mm"_ustr);
1705 startEl(u"style:properties"_ustr);
1706 mxList->clear();
1707 endEl(u"style:properties"_ustr);
1708 endEl(u"style:footer-style"_ustr);
1710 /* Footnote style */
1711 startEl(u"style:page-layout-properties"_ustr);
1713 mxList->addAttribute(u"style:distance-before-sep"_ustr, sXML_CDATA,
1714 OUString::number(WTI(hwpinfo.splinetext)) + "inch");
1715 mxList->addAttribute(u"style:distance-after-sep"_ustr, sXML_CDATA,
1716 OUString::number(WTI(hwpinfo.splinefn)) + "inch");
1717 startEl(u"style:properties"_ustr);
1718 mxList->clear();
1719 endEl(u"style:properties"_ustr);
1720 if ( hwpinfo.fnlinetype == 2 )
1721 mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"15cm"_ustr);
1722 else if ( hwpinfo.fnlinetype == 1)
1723 mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"2cm"_ustr);
1724 else if ( hwpinfo.fnlinetype == 3)
1725 mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"0cm"_ustr);
1726 else
1727 mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"5cm"_ustr);
1729 startEl(u"style:footnote-sep"_ustr);
1730 mxList->clear();
1731 endEl(u"style:footnote-sep"_ustr);
1733 endEl(u"style:page-layout-properties"_ustr);
1735 endEl(u"style:page-master"_ustr);
1739 void HwpReader::makeColumns(ColumnDef const *coldef)
1741 if( !coldef ) return;
1742 mxList->addAttribute(u"fo:column-count"_ustr, sXML_CDATA, OUString::number(coldef->ncols));
1743 startEl(u"style:columns"_ustr);
1744 mxList->clear();
1745 if( coldef->separator != 0 )
1747 switch( coldef->separator )
1749 case 1: /* thin line */
1750 mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"0.02mm"_ustr);
1751 [[fallthrough]];
1752 case 3: /* dotted line */
1753 mxList->addAttribute(u"style:style"_ustr, sXML_CDATA, u"dotted"_ustr);
1754 mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"0.02mm"_ustr);
1755 break;
1756 case 2: /* thick line */
1757 case 4: /* double line */
1758 mxList->addAttribute(u"style:width"_ustr, sXML_CDATA, u"0.35mm"_ustr);
1759 break;
1760 case 0: /* None */
1761 default:
1762 mxList->addAttribute(u"style:style"_ustr, sXML_CDATA, u"none"_ustr);
1763 break;
1765 startEl(u"style:column-sep"_ustr);
1766 mxList->clear();
1767 endEl(u"style:column-sep"_ustr);
1769 double spacing = WTI(coldef->spacing)/ 2. ;
1770 for(int ii = 0 ; ii < coldef->ncols ; ii++)
1772 if( ii == 0 )
1773 mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA, u"0mm"_ustr);
1774 else
1775 mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA,
1776 OUString::number( spacing) + "inch");
1777 if( ii == ( coldef->ncols -1) )
1778 mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA,u"0mm"_ustr);
1779 else
1780 mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA,
1781 OUString::number( spacing) + "inch");
1782 startEl(u"style:column"_ustr);
1783 mxList->clear();
1784 endEl(u"style:column"_ustr);
1786 endEl(u"style:columns"_ustr);
1789 void HwpReader::makeTStyle(CharShape const * cshape)
1791 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "T" + OUString::number(cshape->index));
1792 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"text"_ustr);
1793 startEl(u"style:style"_ustr);
1794 mxList->clear();
1795 parseCharShape(cshape);
1796 startEl(u"style:properties"_ustr);
1797 mxList->clear();
1798 endEl(u"style:properties"_ustr);
1799 endEl(u"style:style"_ustr);
1803 void HwpReader::makeTableStyle(Table *tbl)
1805 // table
1806 TxtBox *hbox = tbl->box;
1808 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum));
1809 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA,u"table"_ustr);
1810 startEl(u"style:style"_ustr);
1811 mxList->clear();
1812 mxList->addAttribute(u"style:width"_ustr, sXML_CDATA,
1813 OUString::number(WTMM(hbox->box_xs)) + "mm");
1814 mxList->addAttribute(u"table:align"_ustr, sXML_CDATA,u"left"_ustr);
1815 mxList->addAttribute(u"fo:keep-with-next"_ustr, sXML_CDATA,u"false"_ustr);
1816 startEl(u"style:properties"_ustr);
1817 mxList->clear();
1818 endEl(u"style:properties"_ustr);
1819 endEl(u"style:style"_ustr);
1821 // column
1822 for (size_t i = 0 ; i < tbl->columns.nCount -1 ; i++)
1824 mxList->addAttribute(
1825 u"style:name"_ustr, sXML_CDATA,
1826 "Table" + OUString::number(hbox->style.boxnum) + "."
1827 + OUStringChar(static_cast<char>('A'+i)));
1828 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA,u"table-column"_ustr);
1829 startEl(u"style:style"_ustr);
1830 mxList->clear();
1831 mxList->addAttribute(u"style:column-width"_ustr, sXML_CDATA,
1832 OUString::number(WTMM(tbl->columns.data[i+1] - tbl->columns.data[i])) + "mm");
1833 startEl(u"style:properties"_ustr);
1834 mxList->clear();
1835 endEl(u"style:properties"_ustr);
1836 endEl(u"style:style"_ustr);
1839 // row
1840 for (size_t i = 0 ; i < tbl->rows.nCount -1 ; i++)
1842 mxList->addAttribute(
1843 u"style:name"_ustr, sXML_CDATA,
1844 "Table" + OUString::number(hbox->style.boxnum) + ".row" + OUString::number(i + 1));
1845 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA,u"table-row"_ustr);
1846 startEl(u"style:style"_ustr);
1847 mxList->clear();
1848 mxList->addAttribute(u"style:row-height"_ustr, sXML_CDATA,
1849 OUString::number(WTMM(tbl->rows.data[i+1] - tbl->rows.data[i])) + "mm");
1850 startEl(u"style:properties"_ustr);
1851 mxList->clear();
1852 endEl(u"style:properties"_ustr);
1853 endEl(u"style:style"_ustr);
1856 // cell
1857 for (auto const& tcell : tbl->cells)
1859 mxList->addAttribute(
1860 u"style:name"_ustr, sXML_CDATA,
1861 "Table" + OUString::number(hbox->style.boxnum) + "."
1862 + OUStringChar(char('A'+ tcell->nColumnIndex))
1863 + OUString::number(tcell->nRowIndex +1));
1864 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA,u"table-cell"_ustr);
1865 startEl(u"style:style"_ustr);
1866 mxList->clear();
1867 Cell *cl = tcell->pCell;
1868 if( cl->ver_align == 1 )
1869 mxList->addAttribute(u"fo:vertical-align"_ustr, sXML_CDATA,u"middle"_ustr);
1871 if(cl->linetype[2] == cl->linetype[3] && cl->linetype[2] == cl->linetype[0]
1872 && cl->linetype[2] == cl->linetype[1])
1874 switch( cl->linetype[2] )
1876 case 1: /* A thin solid line */
1877 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1878 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
1879 break;
1880 case 2: /* Bold lines */
1881 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
1882 break;
1883 case 4: /* Double line */
1884 mxList->addAttribute(u"style:border-line-width"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
1885 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
1886 break;
1889 else
1891 switch( cl->linetype[0] )
1893 case 1: /* A thin solid line */
1894 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1895 mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
1896 break;
1897 case 2: /* Bold lines */
1898 mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
1899 break;
1900 case 4: /* Double line */
1901 mxList->addAttribute(u"style:border-line-width-left"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
1902 mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
1903 break;
1905 switch( cl->linetype[1] )
1907 case 1: /* A thin solid line */
1908 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1909 mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
1910 break;
1911 case 2: /* Bold lines */
1912 mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
1913 break;
1914 case 4: /* Double line */
1915 mxList->addAttribute(u"style:border-line-width-right"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
1916 mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
1917 break;
1919 switch( cl->linetype[2] )
1921 case 1: /* A thin solid line */
1922 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1923 mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
1924 break;
1925 case 2: /* Bold lines */
1926 mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
1927 break;
1928 case 4: /* Double line */
1929 mxList->addAttribute(u"style:border-line-width-top"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
1930 mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
1931 break;
1933 switch( cl->linetype[3] )
1935 case 1: /* A thin solid line */
1936 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1937 mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
1938 break;
1939 case 2: /* Bold lines */
1940 mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
1941 break;
1942 case 4: /* Double line */
1943 mxList->addAttribute(u"style:border-line-width-bottom"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
1944 mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
1945 break;
1948 if(cl->shade != 0)
1949 mxList->addAttribute(u"fo:background-color"_ustr, sXML_CDATA,
1950 hcolor2str(sal::static_int_cast<uchar>(cl->color),
1951 sal::static_int_cast<uchar>(cl->shade)));
1953 startEl(u"style:properties"_ustr);
1954 mxList->clear();
1955 endEl(u"style:properties"_ustr);
1957 endEl(u"style:style"_ustr);
1962 void HwpReader::makeDrawStyle( HWPDrawingObject * hdo, FBoxStyle * fstyle)
1964 while( hdo )
1966 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "Draw" + OUString::number(hdo->index));
1967 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr);
1969 startEl(u"style:style"_ustr);
1970 mxList->clear();
1972 switch (fstyle->txtflow)
1974 case 0:
1975 break;
1976 case 1:
1977 mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"run-through"_ustr);
1978 break;
1979 case 2:
1980 mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"dynamic"_ustr);
1981 break;
1983 tools::Long color;
1984 // invisible line
1985 if( hdo->property.line_color > 0xffffff )
1987 mxList->addAttribute(u"draw:stroke"_ustr, sXML_CDATA, u"none"_ustr );
1989 else
1992 if( hdo->property.line_pstyle == 0 )
1993 mxList->addAttribute(u"draw:stroke"_ustr, sXML_CDATA, u"solid"_ustr );
1994 else if( hdo->property.line_pstyle < 5 )
1996 mxList->addAttribute(u"draw:stroke"_ustr, sXML_CDATA, u"dash"_ustr );
1997 mxList->addAttribute(u"draw:stroke-dash"_ustr, sXML_CDATA, "LineType" + OUString::number(hdo->index));
1999 mxList->addAttribute(u"svg:stroke-width"_ustr, sXML_CDATA,
2000 OUString::number( WTMM(hdo->property.line_width)) + "mm");
2001 mxList->addAttribute(u"svg:stroke-color"_ustr, sXML_CDATA,
2002 rgb2str(static_cast<int32_t>(hdo->property.line_color)));
2005 if( hdo->type == HWPDO_LINE || hdo->type == HWPDO_ARC ||
2006 hdo->type == HWPDO_FREEFORM || hdo->type == HWPDO_ADVANCED_ARC )
2009 if( hdo->property.line_tstyle > 0 &&
2010 o3tl::make_unsigned(hdo->property.line_tstyle) < std::size(ArrowShape) )
2012 mxList->addAttribute(u"draw:marker-start"_ustr, sXML_CDATA,
2013 OUString::createFromAscii(ArrowShape[hdo->property.line_tstyle].name) );
2014 if( hdo->property.line_width > 100 )
2015 mxList->addAttribute(u"draw:marker-start-width"_ustr, sXML_CDATA,
2016 OUString::number( WTMM(hdo->property.line_width * 3.0)) + "mm");
2017 else if( hdo->property.line_width > 80 )
2018 mxList->addAttribute(u"draw:marker-start-width"_ustr, sXML_CDATA,
2019 OUString::number( WTMM(hdo->property.line_width * 4.0)) + "mm");
2020 else if( hdo->property.line_width > 60 )
2021 mxList->addAttribute(u"draw:marker-start-width"_ustr, sXML_CDATA,
2022 OUString::number( WTMM(hdo->property.line_width * 5.0)) + "mm");
2023 else if( hdo->property.line_width > 40 )
2024 mxList->addAttribute(u"draw:marker-start-width"_ustr, sXML_CDATA,
2025 OUString::number( WTMM(hdo->property.line_width * 6.0)) + "mm");
2026 else
2027 mxList->addAttribute(u"draw:marker-start-width"_ustr, sXML_CDATA,
2028 OUString::number( WTMM(hdo->property.line_width * 7.0)) + "mm");
2031 if( hdo->property.line_hstyle > 0 &&
2032 o3tl::make_unsigned(hdo->property.line_hstyle) < std::size(ArrowShape) )
2034 mxList->addAttribute(u"draw:marker-end"_ustr, sXML_CDATA,
2035 OUString::createFromAscii(ArrowShape[hdo->property.line_hstyle].name) );
2036 if( hdo->property.line_width > 100 )
2037 mxList->addAttribute(u"draw:marker-end-width"_ustr, sXML_CDATA,
2038 OUString::number( WTMM(hdo->property.line_width * 3.0)) + "mm");
2039 else if( hdo->property.line_width > 80 )
2040 mxList->addAttribute(u"draw:marker-end-width"_ustr, sXML_CDATA,
2041 OUString::number( WTMM(hdo->property.line_width * 4.0)) + "mm");
2042 else if( hdo->property.line_width > 60 )
2043 mxList->addAttribute(u"draw:marker-end-width"_ustr, sXML_CDATA,
2044 OUString::number( WTMM(hdo->property.line_width * 5.0)) + "mm");
2045 else if( hdo->property.line_width > 40 )
2046 mxList->addAttribute(u"draw:marker-end-width"_ustr, sXML_CDATA,
2047 OUString::number( WTMM(hdo->property.line_width * 6.0)) + "mm");
2048 else
2049 mxList->addAttribute(u"draw:marker-end-width"_ustr, sXML_CDATA,
2050 OUString::number( WTMM(hdo->property.line_width * 7.0)) + "mm");
2054 if(hdo->type != HWPDO_LINE )
2056 if( hdo->property.flag >> 19 & 0x01 )
2058 mxList->addAttribute( u"draw:textarea-horizontal-align"_ustr, sXML_CDATA, u"center"_ustr);
2061 color = hdo->property.fill_color;
2063 if( hdo->property.flag >> 18 & 0x01 ) // bitmap pattern
2065 mxList->addAttribute(u"draw:fill"_ustr, sXML_CDATA, u"bitmap"_ustr);
2066 mxList->addAttribute(u"draw:fill-image-name"_ustr, sXML_CDATA,
2067 "fillimage" + OUString::number(hdo->index));
2068 // bitmap resizing
2069 if( hdo->property.flag >> 3 & 0x01 )
2071 mxList->addAttribute(u"style:repeat"_ustr, sXML_CDATA, u"stretch"_ustr);
2073 else
2075 mxList->addAttribute(u"style:repeat"_ustr, sXML_CDATA, u"repeat"_ustr);
2076 mxList->addAttribute(u"draw:fill-image-ref-point"_ustr, sXML_CDATA, u"top-left"_ustr);
2078 if( hdo->property.flag >> 20 & 0x01 )
2080 if( hdo->property.luminance > 0 )
2082 mxList->addAttribute(u"draw:transparency"_ustr, sXML_CDATA,
2083 OUString::number(hdo->property.luminance) + "%");
2088 // Gradation
2089 else if( hdo->property.flag >> 16 & 0x01 )
2091 mxList->addAttribute(u"draw:fill"_ustr, sXML_CDATA, u"gradient"_ustr);
2092 mxList->addAttribute(u"draw:fill-gradient-name"_ustr, sXML_CDATA, "Grad" + OUString::number(hdo->index));
2093 mxList->addAttribute(u"draw:gradient-step-count"_ustr, sXML_CDATA, OUString::number(hdo->property.nstep));
2096 // Hatching
2097 else if( hdo->property.pattern_type >> 24 & 0x01 )
2099 mxList->addAttribute(u"draw:fill"_ustr, sXML_CDATA, u"hatch"_ustr);
2100 mxList->addAttribute(u"draw:fill-hatch-name"_ustr, sXML_CDATA, "Hatch" + OUString::number(hdo->index));
2101 if( color < 0xffffff )
2103 mxList->addAttribute(u"draw:fill-color"_ustr, sXML_CDATA,
2104 rgb2str(static_cast<int32_t>(color)));
2105 mxList->addAttribute(u"draw:fill-hatch-solid"_ustr, sXML_CDATA, u"true"_ustr);
2108 else if( color <= 0xffffff )
2110 mxList->addAttribute(u"draw:fill"_ustr, sXML_CDATA, u"solid"_ustr);
2111 mxList->addAttribute(u"draw:fill-color"_ustr, sXML_CDATA,
2112 rgb2str(static_cast<int32_t>(color)));
2114 else
2115 mxList->addAttribute(u"draw:fill"_ustr, sXML_CDATA, u"none"_ustr);
2118 if( fstyle->anchor_type == CHAR_ANCHOR )
2120 mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"top"_ustr);
2121 mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"baseline"_ustr);
2124 startEl(u"style:properties"_ustr);
2125 mxList->clear();
2126 endEl(u"style:properties"_ustr);
2127 endEl(u"style:style"_ustr);
2129 if( hdo->type == 0 )
2131 makeDrawStyle( hdo->child.get(), fstyle );
2133 hdo = hdo->next.get();
2138 void HwpReader::makeCaptionStyle(FBoxStyle * fstyle)
2140 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "CapBox" + OUString::number(fstyle->boxnum));
2141 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr);
2142 startEl(u"style:style"_ustr);
2143 mxList->clear();
2144 mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA, u"0cm"_ustr);
2145 mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA, u"0cm"_ustr);
2146 mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA, u"0cm"_ustr);
2147 mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA, u"0cm"_ustr);
2148 mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA, u"0cm"_ustr);
2149 switch (fstyle->txtflow)
2151 case 0:
2152 mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"none"_ustr);
2153 break;
2154 case 1:
2155 if( fstyle->boxtype == 'G' )
2156 mxList->addAttribute(u"style:run-through"_ustr, sXML_CDATA, u"background"_ustr);
2157 mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"run-through"_ustr);
2158 break;
2159 case 2:
2160 mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"dynamic"_ustr);
2161 break;
2163 if (fstyle->anchor_type == CHAR_ANCHOR)
2165 mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"top"_ustr);
2166 mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"baseline"_ustr);
2167 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"center"_ustr);
2168 mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr);
2170 else
2173 switch (-(fstyle->xpos))
2175 case 2:
2176 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"right"_ustr);
2177 break;
2178 case 3:
2179 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"center"_ustr);
2180 break;
2181 case 1:
2182 default:
2183 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"from-left"_ustr);
2184 break;
2186 switch (-(fstyle->ypos))
2188 case 2:
2189 mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"bottom"_ustr);
2190 break;
2191 case 3:
2192 mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"middle"_ustr);
2193 break;
2194 case 1:
2195 default:
2196 mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"from-top"_ustr);
2197 break;
2199 if ( fstyle->anchor_type == PARA_ANCHOR )
2201 mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"paragraph"_ustr);
2202 mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr);
2204 else
2206 mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"page-content"_ustr);
2207 mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"page-content"_ustr);
2210 startEl(u"style:properties"_ustr);
2211 mxList->clear();
2212 endEl(u"style:properties"_ustr);
2213 endEl(u"style:style"_ustr);
2214 if( fstyle->boxtype == 'G' )
2216 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "G" + OUString::number(fstyle->boxnum));
2218 else
2220 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "Txtbox" + OUString::number(fstyle->boxnum));
2223 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr);
2224 startEl(u"style:style"_ustr);
2225 mxList->clear();
2227 mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA, u"0cm"_ustr);
2228 mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA, u"0cm"_ustr);
2229 mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA, u"0cm"_ustr);
2230 mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA, u"0cm"_ustr);
2231 mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA, u"0cm"_ustr);
2232 mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"none"_ustr);
2233 mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"from-top"_ustr);
2234 mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"paragraph"_ustr);
2235 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"from-left"_ustr);
2236 mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr);
2237 if (fstyle->boxtype == 'G' && fstyle->cell)
2239 char *cell = static_cast<char *>(fstyle->cell);
2240 mxList->addAttribute(u"draw:luminance"_ustr, sXML_CDATA, OUString::number(cell[0]) + "%");
2241 mxList->addAttribute(u"draw:contrast"_ustr, sXML_CDATA, OUString::number(cell[1]) + "%");
2242 if( cell[2] == 0 )
2243 mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"standard"_ustr);
2244 else if( cell[2] == 1 )
2245 mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"greyscale"_ustr);
2246 else if( cell[2] == 2 )
2247 mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"mono"_ustr);
2249 else if (fstyle->cell)
2251 Cell *cell = static_cast<Cell *>(fstyle->cell);
2252 if(cell->linetype[0] == cell->linetype[1] &&
2253 cell->linetype[0] == cell->linetype[2] &&
2254 cell->linetype[0] == cell->linetype[3])
2256 switch( cell->linetype[0] )
2258 case 0:
2259 mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA,u"0mm"_ustr);
2260 break;
2261 case 1: /* A thin solid line */
2262 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2263 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
2264 break;
2265 case 2: /* Bold lines */
2266 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
2267 break;
2268 case 4: /* Double line */
2269 mxList->addAttribute(u"style:border-line-width"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
2270 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
2271 break;
2274 else
2276 switch( cell->linetype[0] )
2278 case 1: /* A thin solid line */
2279 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2280 mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
2281 break;
2282 case 2: /* Bold lines */
2283 mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
2284 break;
2285 case 4: /* Double line */
2286 mxList->addAttribute(u"style:border-line-width-left"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
2287 mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
2288 break;
2290 switch( cell->linetype[1] )
2292 case 1: /* A thin solid line */
2293 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2294 mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
2295 break;
2296 case 2: /* Bold lines */
2297 mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
2298 break;
2299 case 4: /* Double line */
2300 mxList->addAttribute(u"style:border-line-width-right"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
2301 mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
2302 break;
2304 switch( cell->linetype[2] )
2306 case 1: /* A thin solid line */
2307 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2308 mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
2309 break;
2310 case 2: /* Bold lines */
2311 mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
2312 break;
2313 case 4: /* Double line */
2314 mxList->addAttribute(u"style:border-line-width-top"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
2315 mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
2316 break;
2318 switch( cell->linetype[3] )
2320 case 1: /* A thin solid line */
2321 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2322 mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
2323 break;
2324 case 2: /* Bold lines */
2325 mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
2326 break;
2327 case 4: /* Double line */
2328 mxList->addAttribute(u"style:border-line-width-bottom"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
2329 mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
2330 break;
2333 if(cell->shade != 0)
2334 mxList->addAttribute(u"fo:background-color"_ustr, sXML_CDATA, hcolor2str(
2335 sal::static_int_cast<uchar>(cell->color),
2336 sal::static_int_cast<uchar>(cell->shade)));
2338 startEl(u"style:properties"_ustr);
2339 mxList->clear();
2340 endEl(u"style:properties"_ustr);
2341 endEl(u"style:style"_ustr);
2346 * Create a style for the Floating objects.
2348 void HwpReader::makeFStyle(FBoxStyle * fstyle)
2350 /* caption exist */
2351 if( ( fstyle->boxtype == 'G' || fstyle->boxtype == 'X' ) && fstyle->cap_len > 0 )
2353 makeCaptionStyle(fstyle);
2354 return;
2356 switch( fstyle->boxtype )
2358 case 'X' : // txtbox
2359 case 'E' : // equation
2360 case 'B' : // button
2361 case 'O' : // other
2362 case 'T' : // table
2363 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "Txtbox" + OUString::number(fstyle->boxnum));
2364 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr);
2365 break;
2366 case 'G' : // graphics
2367 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "G" + OUString::number(fstyle->boxnum));
2368 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA, u"graphics"_ustr);
2369 break;
2370 case 'L' : // line TODO : all
2371 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "L" + OUString::number(fstyle->boxnum));
2372 mxList->addAttribute( u"style:family"_ustr , sXML_CDATA , u"paragraph"_ustr );
2373 break;
2376 startEl(u"style:style"_ustr);
2377 mxList->clear();
2379 if ( fstyle->boxtype == 'T')
2381 mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA, u"0cm"_ustr);
2384 if( fstyle->boxtype != 'G' || fstyle->cap_len <= 0 )
2386 mxList->addAttribute(u"fo:margin-left"_ustr, sXML_CDATA,
2387 OUString::number(WTMM(fstyle->margin[0][0]) ) + "mm");
2388 mxList->addAttribute(u"fo:margin-right"_ustr, sXML_CDATA,
2389 OUString::number(WTMM(fstyle->margin[0][1])) + "mm");
2390 mxList->addAttribute(u"fo:margin-top"_ustr, sXML_CDATA,
2391 OUString::number(WTMM(fstyle->margin[0][2])) + "mm");
2392 mxList->addAttribute(u"fo:margin-bottom"_ustr, sXML_CDATA,
2393 OUString::number(WTMM(fstyle->margin[0][3])) + "mm");
2396 switch (fstyle->txtflow)
2398 case 0:
2399 mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"none"_ustr);
2400 break;
2401 case 1:
2402 if( fstyle->boxtype == 'G' || fstyle->boxtype == 'B' || fstyle->boxtype == 'O')
2403 mxList->addAttribute(u"style:run-through"_ustr, sXML_CDATA, u"background"_ustr);
2404 mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"run-through"_ustr);
2405 break;
2406 case 2:
2407 mxList->addAttribute(u"style:wrap"_ustr, sXML_CDATA, u"dynamic"_ustr);
2408 break;
2410 if (fstyle->anchor_type == CHAR_ANCHOR)
2412 mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"top"_ustr);
2413 mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"baseline"_ustr);
2414 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"center"_ustr);
2415 mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr);
2417 else
2420 switch (-(fstyle->xpos))
2422 case 2:
2423 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"right"_ustr);
2424 break;
2425 case 3:
2426 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"center"_ustr);
2427 break;
2428 case 1:
2429 default:
2430 mxList->addAttribute(u"style:horizontal-pos"_ustr, sXML_CDATA, u"from-left"_ustr);
2431 break;
2433 switch (-(fstyle->ypos))
2435 case 2:
2436 mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"bottom"_ustr);
2437 break;
2438 case 3:
2439 mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"middle"_ustr);
2440 break;
2441 case 1:
2442 default:
2443 mxList->addAttribute(u"style:vertical-pos"_ustr, sXML_CDATA, u"from-top"_ustr);
2444 break;
2446 if ( fstyle->anchor_type == PARA_ANCHOR )
2448 mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"paragraph"_ustr);
2449 mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"paragraph"_ustr);
2451 else
2453 mxList->addAttribute(u"style:vertical-rel"_ustr, sXML_CDATA, u"page-content"_ustr);
2454 mxList->addAttribute(u"style:horizontal-rel"_ustr, sXML_CDATA, u"page-content"_ustr);
2457 if (fstyle->cell && (fstyle->boxtype == 'X' || fstyle->boxtype == 'B'))
2459 Cell *cell = static_cast<Cell *>(fstyle->cell);
2460 if(cell->linetype[0] == cell->linetype[1] &&
2461 cell->linetype[0] == cell->linetype[2] &&
2462 cell->linetype[0] == cell->linetype[3])
2464 switch( cell->linetype[0] )
2466 case 0:
2467 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA, u"none"_ustr);
2468 break;
2469 case 1: /* A thin solid line */
2470 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2471 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
2472 break;
2473 case 2: /* Bold lines */
2474 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
2475 break;
2476 case 4: /* Double line */
2477 mxList->addAttribute(u"style:border-line-width"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
2478 mxList->addAttribute(u"fo:border"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
2479 break;
2482 else
2484 switch( cell->linetype[0] )
2486 case 1: /* A thin solid line */
2487 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2488 mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
2489 break;
2490 case 2: /* Bold lines */
2491 mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
2492 break;
2493 case 4: /* Double line */
2494 mxList->addAttribute(u"style:border-line-width-left"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
2495 mxList->addAttribute(u"fo:border-left"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
2496 break;
2498 switch( cell->linetype[1] )
2500 case 1: /* A thin solid line */
2501 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2502 mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
2503 break;
2504 case 2: /* Bold lines */
2505 mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
2506 break;
2507 case 4: /* Double line */
2508 mxList->addAttribute(u"style:border-line-width-right"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
2509 mxList->addAttribute(u"fo:border-right"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
2510 break;
2512 switch( cell->linetype[2] )
2514 case 1: /* A thin solid line */
2515 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2516 mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
2517 break;
2518 case 2: /* Bold lines */
2519 mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
2520 break;
2521 case 4: /* Double line */
2522 mxList->addAttribute(u"style:border-line-width-top"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
2523 mxList->addAttribute(u"fo:border-top"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
2524 break;
2526 switch( cell->linetype[3] )
2528 case 1: /* A thin solid line */
2529 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2530 mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.002cm solid #000000"_ustr);
2531 break;
2532 case 2: /* Bold lines */
2533 mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.035cm solid #000000"_ustr);
2534 break;
2535 case 4: /* Double line */
2536 mxList->addAttribute(u"style:border-line-width-bottom"_ustr, sXML_CDATA,u"0.002cm 0.035cm 0.002cm"_ustr);
2537 mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.039cm double #000000"_ustr);
2538 break;
2542 if( cell->linetype[0] == 0 && cell->linetype[1] == 0 &&
2543 cell->linetype[2] == 0 && cell->linetype[3] == 0 ){
2544 mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA,u"0mm"_ustr);
2546 else{
2547 mxList->addAttribute(u"fo:padding-left"_ustr, sXML_CDATA,
2548 OUString::number(WTMM(fstyle->margin[1][0])) + "mm");
2549 mxList->addAttribute(u"fo:padding-right"_ustr, sXML_CDATA,
2550 OUString::number(WTMM(fstyle->margin[1][1])) + "mm");
2551 mxList->addAttribute(u"fo:padding-top"_ustr, sXML_CDATA,
2552 OUString::number(WTMM(fstyle->margin[1][2])) + "mm");
2553 mxList->addAttribute(u"fo:padding-bottom"_ustr, sXML_CDATA,
2554 OUString::number(WTMM(fstyle->margin[1][3])) + "mm");
2556 if(cell->shade != 0)
2557 mxList->addAttribute(u"fo:background-color"_ustr, sXML_CDATA,
2558 hcolor2str(
2559 sal::static_int_cast<uchar>(cell->color),
2560 sal::static_int_cast<uchar>(cell->shade)));
2562 else if( fstyle->boxtype == 'E' )
2564 mxList->addAttribute(u"fo:padding"_ustr, sXML_CDATA,u"0mm"_ustr);
2566 else if( fstyle->boxtype == 'L' )
2568 mxList->addAttribute( u"style:border-line-width-bottom"_ustr, sXML_CDATA, u"0.02mm 0.35mm 0.02mm"_ustr);
2569 mxList->addAttribute(u"fo:border-bottom"_ustr, sXML_CDATA,u"0.039cm double #808080"_ustr);
2571 else if( fstyle->boxtype == 'G' && fstyle->cell )
2573 if( fstyle->margin[1][0] || fstyle->margin[1][1] || fstyle->margin[1][2] || fstyle->margin[1][3] ){
2574 OUString clip = "rect(" +
2575 OUString::number(WTMM(-fstyle->margin[1][0]) ) + "mm " +
2576 OUString::number(WTMM(-fstyle->margin[1][1]) ) + "mm " +
2577 OUString::number(WTMM(-fstyle->margin[1][2]) ) + "mm " +
2578 OUString::number(WTMM(-fstyle->margin[1][3]) ) + "mm)";
2579 mxList->addAttribute(u"style:mirror"_ustr, sXML_CDATA, u"none"_ustr);
2580 mxList->addAttribute(u"fo:clip"_ustr, sXML_CDATA, clip);
2582 char *cell = static_cast<char *>(fstyle->cell);
2583 mxList->addAttribute(u"draw:luminance"_ustr, sXML_CDATA, OUString::number(cell[0]) + "%");
2584 mxList->addAttribute(u"draw:contrast"_ustr, sXML_CDATA, OUString::number(cell[1]) + "%");
2585 if( cell[2] == 0 )
2586 mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"standard"_ustr);
2587 else if( cell[2] == 1 )
2588 mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"greyscale"_ustr);
2589 else if( cell[2] == 2 )
2590 mxList->addAttribute(u"draw:color-mode"_ustr, sXML_CDATA, u"mono"_ustr);
2593 startEl(u"style:properties"_ustr);
2594 mxList->clear();
2595 endEl(u"style:properties"_ustr);
2596 endEl(u"style:style"_ustr);
2600 OUString HwpReader::getTStyleName(int index)
2602 return "T" + OUString::number(index);
2606 OUString HwpReader::getPStyleName(int index)
2608 return "P" + OUString::number(index);
2612 void HwpReader::makeChars(hchar_string & rStr)
2614 chars(fromHcharStringToOUString(rStr));
2615 rStr.clear();
2620 * If no special characters in the paragraph and all characters use the same CharShape
2622 void HwpReader::make_text_p0(HWPPara * para, bool bParaStart)
2624 hchar_string str;
2625 int res;
2626 hchar dest[3];
2627 unsigned char firstspace = 0;
2628 if( !bParaStart)
2630 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA,
2631 getPStyleName(para->GetParaShape().index));
2632 startEl(u"text:p"_ustr);
2633 mxList->clear();
2635 if( d->bFirstPara && d->bInBody )
2637 mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, sBeginOfDoc);
2638 startEl(u"text:bookmark"_ustr);
2639 mxList->clear();
2640 endEl(u"text:bookmark"_ustr);
2641 d->bFirstPara = false;
2643 if( d->bInHeader )
2645 makeShowPageNum();
2646 d->bInHeader = false;
2648 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA,
2649 getTStyleName(para->cshape->index));
2650 startEl(u"text:span"_ustr);
2651 mxList->clear();
2653 for (const auto& box : para->hhstr)
2655 if (!box->hh)
2656 break;
2658 if (box->hh == CH_SPACE && !firstspace)
2660 makeChars(str);
2661 startEl(u"text:s"_ustr);
2662 endEl(u"text:s"_ustr);
2664 else if (box->hh == CH_END_PARA)
2666 makeChars(str);
2667 endEl(u"text:span"_ustr);
2668 endEl(u"text:p"_ustr);
2669 break;
2671 else
2673 if (box->hh == CH_SPACE)
2674 firstspace = 0;
2675 else
2676 firstspace = 1;
2677 res = hcharconv(box->hh, dest, UNICODE);
2678 for( int j = 0 ; j < res; j++ )
2680 str.push_back(dest[j]);
2688 * There is no special characters in the paragraph, but characters use different CharShapes
2690 void HwpReader::make_text_p1(HWPPara * para,bool bParaStart)
2692 hchar_string str;
2693 int res;
2694 hchar dest[3];
2695 int curr = para->cshape->index;
2696 unsigned char firstspace = 0;
2698 if( !bParaStart )
2700 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA,
2701 getPStyleName(para->GetParaShape().index));
2702 startEl(u"text:p"_ustr);
2703 mxList->clear();
2705 if( d->bFirstPara && d->bInBody )
2707 /* for HWP's Bookmark */
2708 mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, sBeginOfDoc);
2709 startEl(u"text:bookmark"_ustr);
2710 mxList->clear();
2711 endEl(u"text:bookmark"_ustr);
2712 d->bFirstPara = false;
2714 if( d->bInHeader )
2716 makeShowPageNum();
2717 d->bInHeader = false;
2719 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA,
2720 getTStyleName(curr));
2721 startEl(u"text:span"_ustr);
2722 mxList->clear();
2724 int n = 0;
2725 for (const auto& box : para->hhstr)
2727 if (!box->hh)
2728 break;
2730 if (para->GetCharShape(n)->index != curr)
2732 makeChars(str);
2733 endEl(u"text:span"_ustr);
2734 curr = para->GetCharShape(n)->index;
2735 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA,
2736 getTStyleName(curr));
2737 startEl(u"text:span"_ustr);
2738 mxList->clear();
2740 if (box->hh == CH_SPACE && !firstspace)
2742 makeChars(str);
2743 startEl(u"text:s"_ustr);
2744 endEl(u"text:s"_ustr);
2746 else if (box->hh == CH_END_PARA)
2748 makeChars(str);
2749 endEl(u"text:span"_ustr);
2750 endEl(u"text:p"_ustr);
2751 break;
2753 else
2755 if( box->hh < CH_SPACE )
2756 continue;
2757 if (box->hh == CH_SPACE)
2758 firstspace = 0;
2759 else
2760 firstspace = 1;
2761 res = hcharconv(box->hh, dest, UNICODE);
2762 for( int j = 0 ; j < res; j++ )
2764 str.push_back(dest[j]);
2767 n += box->WSize();
2773 * Special characters are in the paragraph and characters use different CharShapes
2775 void HwpReader::make_text_p3(HWPPara * para,bool bParaStart)
2777 hchar_string str;
2778 int res;
2779 hchar dest[3];
2780 unsigned char firstspace = 0;
2781 bool pstart = bParaStart;
2782 bool tstart = false;
2783 bool infield = false;
2785 const auto STARTP = [this, para, &pstart]()
2787 mxList->addAttribute(u"text:style-name"_ustr, u"CDATA"_ustr,
2788 getPStyleName(para->GetParaShape().index));
2789 startEl(u"text:p"_ustr);
2790 mxList->clear();
2791 pstart = true;
2793 const auto STARTT = [this, para, &tstart](int pos)
2795 auto curr = para->GetCharShape(pos > 0 ? pos - 1 : 0)->index;
2796 mxList->addAttribute(u"text:style-name"_ustr, u"CDATA"_ustr, getTStyleName(curr));
2797 startEl(u"text:span"_ustr);
2798 mxList->clear();
2799 tstart = true;
2801 const auto ENDP = [this, &pstart]()
2803 endEl(u"text:p"_ustr);
2804 pstart = false;
2806 const auto ENDT = [this, &tstart]()
2808 endEl(u"text:span"_ustr);
2809 tstart = false;
2812 if( d->bFirstPara && d->bInBody )
2814 if ( !pstart ) {
2815 STARTP();
2817 mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, sBeginOfDoc);
2818 startEl(u"text:bookmark"_ustr);
2819 mxList->clear();
2820 endEl(u"text:bookmark"_ustr);
2821 d->bFirstPara = false;
2823 if( d->bInHeader )
2825 if ( !pstart ) {
2826 STARTP();
2828 makeShowPageNum();
2829 d->bInHeader = false;
2832 int n = 0;
2833 for (const auto& box : para->hhstr)
2835 if (!box->hh)
2836 break;
2838 if (box->hh == CH_END_PARA)
2840 if (!str.empty())
2842 if( !pstart ){ STARTP(); }
2843 if( !tstart ){ STARTT(n);}
2844 makeChars(str);
2846 if( tstart ){ ENDT();}
2847 if( !pstart ){ STARTP(); }
2848 if( pstart ){ ENDP(); }
2849 break;
2851 else if (box->hh == CH_SPACE && !firstspace)
2853 if( !pstart ) {STARTP(); }
2854 if( !tstart ) {STARTT(n);}
2855 makeChars(str);
2856 startEl(u"text:s"_ustr);
2857 mxList->clear();
2858 endEl(u"text:s"_ustr);
2860 else if (box->hh >= CH_SPACE)
2862 if( n > 0 )
2863 if( para->GetCharShape(n)->index != para->GetCharShape(n-1)->index && !infield )
2865 if( !pstart ) {STARTP(); }
2866 if( !tstart ) {STARTT(n);}
2867 makeChars(str);
2868 ENDT();
2870 if (box->hh == CH_SPACE)
2871 firstspace = 0;
2872 else
2873 firstspace = 1;
2874 res = hcharconv(box->hh, dest, UNICODE);
2875 for( int j = 0 ; j < res; j++ )
2877 str.push_back(dest[j]);
2880 else if (box->hh == CH_FIELD)
2882 FieldCode *hbox = static_cast<FieldCode*>(box.get());
2883 if( hbox->location_info == 1)
2885 if( !pstart ) {STARTP(); }
2886 if( !tstart ) {STARTT(n);}
2887 makeChars(str);
2888 firstspace = 1;
2889 if( hbox->type[0] == 4 && hbox->type[1] == 0 )
2891 d->pField = hbox->str3.get();
2893 else{
2894 makeFieldCode(str, hbox);
2896 infield = true;
2898 else
2900 firstspace = 1;
2901 if( hbox->type[0] == 4 && hbox->type[1] == 0 )
2903 makeFieldCode(str, hbox);
2904 d->pField = nullptr;
2906 infield = false;
2907 str.clear();
2910 else
2912 switch (box->hh)
2914 case CH_BOOKMARK:
2915 if( !pstart ) {STARTP(); }
2916 if( !tstart ) {STARTT(n);}
2917 makeChars(str);
2918 makeBookmark(static_cast<Bookmark*>(box.get()));
2919 break;
2920 case CH_DATE_FORM: // 7
2921 break;
2922 case CH_DATE_CODE: // 8
2923 if( !pstart ) {STARTP(); }
2924 if( !tstart ) {STARTT(n);}
2925 makeChars(str);
2926 makeDateCode(static_cast<DateCode*>(box.get()));
2927 break;
2928 case CH_TAB: // 9
2929 if( !pstart ) {STARTP(); }
2930 if (!str.empty())
2932 if( !tstart ) {STARTT(n);}
2933 makeChars(str);
2935 makeTab();
2936 break;
2937 case CH_TEXT_BOX: /* 10 - ordered by Table/text box/formula/button/hypertext */
2939 /* produce tables first, and treat formula as being in text:p. */
2940 TxtBox *hbox = static_cast<TxtBox*>(box.get());
2942 if( hbox->style.anchor_type == 0 )
2944 if( !pstart ) {STARTP(); }
2945 if( !tstart ) {STARTT(n);}
2946 makeChars(str);
2948 else
2950 if( !pstart ) {STARTP(); }
2951 if (!str.empty())
2953 if( !tstart ) {STARTT(n);}
2954 makeChars(str);
2956 if( tstart ) {ENDT();}
2958 switch (hbox->type)
2960 case TBL_TYPE: // table
2961 case TXT_TYPE: // text box
2962 case EQU_TYPE: // formula
2963 makeTextBox(hbox);
2964 break;
2965 case BUTTON_TYPE: // text button
2966 case HYPERTEXT_TYPE: // hypertext
2967 makeHyperText(hbox);
2968 break;
2970 break;
2972 case CH_PICTURE: // 11
2974 Picture *hbox = static_cast<Picture*>(box.get());
2975 if( hbox->style.anchor_type == 0 )
2977 if( !pstart ) {STARTP(); }
2978 if( !tstart ) {STARTT(n);}
2979 makeChars(str);
2981 else
2983 if( !pstart ) {STARTP(); }
2984 if (!str.empty())
2986 if( !tstart ) {STARTT(n);}
2987 makeChars(str);
2989 if( tstart ) {ENDT();}
2991 makePicture(hbox);
2992 break;
2994 case CH_LINE: // 14
2996 if (!str.empty())
2998 if( !pstart ) {STARTP();}
2999 if( !tstart ) {STARTT(n);}
3000 makeChars(str);
3002 if( tstart ) {ENDT();}
3003 if( pstart ) {ENDP();}
3004 makeLine();
3005 pstart = true;
3006 break;
3008 case CH_HIDDEN: // 15
3009 if( !pstart ) {STARTP();}
3010 if( !tstart ) {STARTT(n);}
3011 makeChars(str);
3012 makeHidden(static_cast<Hidden*>(box.get()));
3013 break;
3014 case CH_FOOTNOTE: // 17
3015 if( !pstart ) {STARTP();}
3016 if( !tstart ) {STARTT(n);}
3017 makeChars(str);
3018 makeFootnote(static_cast<Footnote*>(box.get()));
3019 break;
3020 case CH_AUTO_NUM: // 18
3021 if( !pstart ) {STARTP();}
3022 if( !tstart ) {STARTT(n);}
3023 makeChars(str);
3024 makeAutoNum(static_cast<AutoNum*>(box.get()));
3025 break;
3026 case CH_NEW_NUM: // 19 -skip
3027 break;
3028 case CH_PAGE_NUM_CTRL: // 21
3029 break;
3030 case CH_MAIL_MERGE: // 22
3031 if( !pstart ) {STARTP();}
3032 if( !tstart ) {STARTT(n);}
3033 makeChars(str);
3034 makeMailMerge(static_cast<MailMerge*>(box.get()));
3035 break;
3036 case CH_COMPOSE: /* 23 - overlapping letters */
3037 break;
3038 case CH_HYPHEN: // 24
3039 break;
3040 case CH_TOC_MARK: /* 25 Need to fix below 3 */
3041 if( !pstart ) {STARTP();}
3042 if( !tstart ) {STARTT(n);}
3043 makeChars(str);
3044 break;
3045 case CH_INDEX_MARK: // 26
3046 if( !pstart ) {STARTP();}
3047 if( !tstart ) {STARTT(n);}
3048 makeChars(str);
3049 break;
3050 case CH_OUTLINE: // 28
3051 if( !pstart ) {STARTP();}
3052 if( !tstart ) {STARTT(n);}
3053 makeChars(str);
3054 makeOutline(static_cast<Outline *>(box.get()));
3055 break;
3056 case CH_FIXED_SPACE:
3057 case CH_KEEP_SPACE:
3058 str.push_back(0x0020);
3059 break;
3062 n += box->WSize();
3067 void HwpReader::makeFieldCode(hchar_string const & rStr, FieldCode const *hbox)
3069 /* Push frame */
3070 if( hbox->type[0] == 4 && hbox->type[1] == 0 )
3072 mxList->addAttribute(u"text:placeholder-type"_ustr, sXML_CDATA, u"text"_ustr);
3073 if (d->pField)
3074 mxList->addAttribute(u"text:description"_ustr, sXML_CDATA, hstr2OUString(d->pField));
3075 startEl(u"text:placeholder"_ustr);
3076 mxList->clear();
3077 chars( fromHcharStringToOUString(rStr) );
3078 endEl(u"text:placeholder"_ustr);
3080 /* Document Summary */
3081 else if( hbox->type[0] == 3 && hbox->type[1] == 0 )
3083 const OUString uStr3 = hstr2OUString(hbox->str3.get());
3084 if (uStr3 == "title")
3086 startEl(u"text:title"_ustr);
3087 chars( hstr2OUString(hbox->str2.get()) );
3088 endEl(u"text:title"_ustr);
3090 else if (uStr3 == "subject")
3092 startEl(u"text:subject"_ustr);
3093 chars( hstr2OUString(hbox->str2.get()) );
3094 endEl(u"text:subject"_ustr);
3096 else if (uStr3 == "author")
3098 startEl(u"text:author-name"_ustr);
3099 chars( hstr2OUString(hbox->str2.get()) );
3100 endEl(u"text:author-name"_ustr);
3102 else if (uStr3 == "keywords")
3104 startEl(u"text:keywords"_ustr);
3105 chars( hstr2OUString(hbox->str2.get()) );
3106 endEl(u"text:keywords"_ustr);
3109 /* Personal Information */
3110 else if( hbox->type[0] == 3 && hbox->type[1] == 1 )
3112 const OUString uStr3 = hstr2OUString(hbox->str3.get());
3113 if (uStr3 == "User")
3115 startEl(u"text:sender-lastname"_ustr);
3116 chars( hstr2OUString(hbox->str2.get()) );
3117 endEl(u"text:sender-lastname"_ustr);
3119 else if (uStr3 == "Company")
3121 startEl(u"text:sender-company"_ustr);
3122 chars( hstr2OUString(hbox->str2.get()) );
3123 endEl(u"text:sender-company"_ustr);
3125 else if (uStr3 == "Position")
3127 startEl(u"text:sender-title"_ustr);
3128 chars( hstr2OUString(hbox->str2.get()) );
3129 endEl(u"text:sender-title"_ustr);
3131 else if (uStr3 == "Division")
3133 startEl(u"text:sender-position"_ustr);
3134 chars( hstr2OUString(hbox->str2.get()) );
3135 endEl(u"text:sender-position"_ustr);
3137 else if (uStr3 == "Fax")
3139 startEl(u"text:sender-fax"_ustr);
3140 chars( hstr2OUString(hbox->str2.get()) );
3141 endEl(u"text:sender-fax"_ustr);
3143 else if (uStr3 == "Pager")
3145 startEl(u"text:phone-private"_ustr);
3146 chars( hstr2OUString(hbox->str2.get()) );
3147 endEl(u"text:phone-private"_ustr);
3149 else if (uStr3 == "E-mail")
3151 startEl(u"text:sender-email"_ustr);
3152 chars( hstr2OUString(hbox->str2.get()) );
3153 endEl(u"text:sender-email"_ustr);
3155 else if (uStr3 == "Zipcode(office)")
3157 startEl(u"text:sender-postal-code"_ustr);
3158 chars( hstr2OUString(hbox->str2.get()) );
3159 endEl(u"text:sender-postal-code"_ustr);
3161 else if (uStr3 == "Phone(office)")
3163 startEl(u"text:sender-phone-work"_ustr);
3164 chars( hstr2OUString(hbox->str2.get()) );
3165 endEl(u"text:sender-phone-work"_ustr);
3167 else if (uStr3 == "Address(office)")
3169 startEl(u"text:sender-street"_ustr);
3170 chars( hstr2OUString(hbox->str2.get()) );
3171 endEl(u"text:sender-street"_ustr);
3175 else if( hbox->type[0] == 3 && hbox->type[1] == 2 ) /* creation date */
3177 if( hbox->m_pDate )
3178 mxList->addAttribute(u"style:data-style-name"_ustr, sXML_CDATA, "N" + OUString::number(hbox->m_pDate->key));
3179 startEl(u"text:creation-date"_ustr);
3180 mxList->clear();
3181 chars( hstr2OUString(hbox->str2.get()) );
3182 endEl(u"text:creation-date"_ustr);
3188 * Completed
3189 * In LibreOffice, refer bookmarks as reference, but hwp doesn't have the sort of feature.
3191 void HwpReader::makeBookmark(Bookmark const * hbox)
3193 if (hbox->type == 0)
3195 mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, hstr2OUString(hbox->id));
3196 startEl(u"text:bookmark"_ustr);
3197 mxList->clear();
3198 endEl(u"text:bookmark"_ustr);
3200 else if (hbox->type == 1) /* Block bookmarks days begin and end there if */
3202 mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, hstr2OUString(hbox->id));
3203 startEl(u"text:bookmark-start"_ustr);
3204 mxList->clear();
3205 endEl(u"text:bookmark-start"_ustr);
3207 else if (hbox->type == 2)
3209 mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, hstr2OUString(hbox->id));
3210 startEl(u"text:bookmark-end"_ustr);
3211 mxList->clear();
3212 endEl(u"text:bookmark-end"_ustr);
3217 void HwpReader::makeDateFormat(DateCode * hbox)
3219 mxList->addAttribute(u"style:name"_ustr, sXML_CDATA, "N" + OUString::number(hbox->key));
3220 mxList->addAttribute(u"style:family"_ustr, sXML_CDATA,u"data-style"_ustr);
3221 mxList->addAttribute(u"number:language"_ustr, sXML_CDATA,u"ko"_ustr);
3222 mxList->addAttribute(u"number:country"_ustr, sXML_CDATA,u"KR"_ustr);
3224 startEl(u"number:date-style"_ustr);
3225 mxList->clear();
3227 bool add_zero = false;
3228 int zero_check = 0;
3229 hbox->format[DATE_SIZE -1] = 0;
3231 const hchar *fmt = hbox->format[0] ? hbox->format : defaultform;
3233 for( ; *fmt ; fmt++ )
3235 if( zero_check == 1 )
3237 zero_check = 0;
3239 else
3240 add_zero = false;
3242 switch( *fmt )
3244 case '0':
3245 zero_check = 1;
3246 add_zero = true;
3247 break;
3248 case '1':
3249 mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr);
3250 startEl(u"number:year"_ustr);
3251 mxList->clear();
3252 endEl(u"number:year"_ustr);
3253 break;
3254 case '!':
3255 startEl(u"number:year"_ustr);
3256 mxList->clear();
3257 endEl(u"number:year"_ustr);
3258 break;
3259 case '2':
3260 if( add_zero )
3261 mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr);
3262 startEl(u"number:month"_ustr);
3263 mxList->clear();
3264 endEl(u"number:month"_ustr);
3265 break;
3266 case '@':
3267 mxList->addAttribute(u"number:textual"_ustr, sXML_CDATA, u"true"_ustr);
3268 startEl(u"number:month"_ustr);
3269 mxList->clear();
3270 endEl(u"number:month"_ustr);
3271 break;
3272 case '*':
3273 mxList->addAttribute(u"number:textual"_ustr, sXML_CDATA, u"true"_ustr);
3274 mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr);
3275 startEl(u"number:month"_ustr);
3276 mxList->clear();
3277 endEl(u"number:month"_ustr);
3278 break;
3279 case '3':
3280 if( add_zero )
3281 mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr);
3282 startEl(u"number:day"_ustr);
3283 mxList->clear();
3284 endEl(u"number:day"_ustr);
3285 break;
3286 case '#':
3287 if( add_zero )
3288 mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr);
3289 startEl(u"number:day"_ustr);
3290 mxList->clear();
3291 endEl(u"number:day"_ustr);
3292 switch( hbox->date[DateCode::DAY] % 10)
3294 case 1:
3295 startEl(u"number:text"_ustr);
3296 chars(u"st"_ustr);
3297 endEl(u"number:text"_ustr);
3298 break;
3299 case 2:
3300 startEl(u"number:text"_ustr);
3301 chars(u"nd"_ustr);
3302 endEl(u"number:text"_ustr);
3303 break;
3304 case 3:
3305 startEl(u"number:text"_ustr);
3306 chars(u"rd"_ustr);
3307 endEl(u"number:text"_ustr);
3308 break;
3309 default:
3310 startEl(u"number:text"_ustr);
3311 chars(u"th"_ustr);
3312 endEl(u"number:text"_ustr);
3313 break;
3315 break;
3316 case '4':
3317 case '$':
3318 if( add_zero )
3319 mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr);
3320 startEl(u"number:hours"_ustr);
3321 mxList->clear();
3322 endEl(u"number:hours"_ustr);
3323 break;
3324 case '5':
3325 case '%':
3326 if( add_zero )
3327 mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr);
3328 startEl(u"number:minutes"_ustr);
3329 mxList->clear();
3330 endEl(u"number:minutes"_ustr);
3331 break;
3332 case '_':
3333 mxList->addAttribute(u"number:style"_ustr, sXML_CDATA, u"long"_ustr);
3334 [[fallthrough]];
3335 case '6':
3336 case '^':
3337 startEl(u"number:day-of-week"_ustr);
3338 mxList->clear();
3339 endEl(u"number:day-of-week"_ustr);
3340 break;
3341 case '7':
3342 case '&':
3343 case '+':
3344 startEl(u"number:am-pm"_ustr);
3345 mxList->clear();
3346 endEl(u"number:am-pm"_ustr);
3347 break;
3348 case '~': // Chinese Locale
3349 break;
3350 default:
3351 hchar sbuf[2];
3352 sbuf[0] = *fmt;
3353 sbuf[1] = 0;
3354 startEl(u"number:text"_ustr);
3355 chars(hstr2OUString(sbuf));
3356 endEl(u"number:text"_ustr);
3357 break;
3360 mxList->clear();
3361 endEl(u"number:date-style"_ustr);
3365 void HwpReader::makeDateCode(DateCode * hbox)
3367 mxList->addAttribute(u"style:data-style-name"_ustr, sXML_CDATA, "N" + OUString::number(hbox->key));
3368 startEl(u"text:date"_ustr);
3369 mxList->clear();
3370 hchar_string const boxstr = hbox->GetString();
3371 chars(hstr2OUString(boxstr.c_str()));
3372 endEl(u"text:date"_ustr);
3376 void HwpReader::makeTab()
3378 startEl(u"text:tab-stop"_ustr);
3379 endEl(u"text:tab-stop"_ustr);
3383 void HwpReader::makeTable(TxtBox * hbox)
3385 mxList->addAttribute(u"table:name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum));
3386 mxList->addAttribute(u"table:style-name"_ustr, sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum));
3387 startEl(u"table:table"_ustr);
3388 mxList->clear();
3390 Table *tbl = hbox->m_pTable;
3391 // column
3392 for (size_t i = 0 ; i < tbl->columns.nCount -1 ; i++)
3394 mxList->addAttribute(
3395 u"table:style-name"_ustr, sXML_CDATA,
3396 "Table" + OUString::number(hbox->style.boxnum) + "."
3397 + OUStringChar(static_cast<char>('A'+i)));
3398 startEl(u"table:table-column"_ustr);
3399 mxList->clear();
3400 endEl(u"table:table-column"_ustr);
3403 // cell
3404 int j = -1, k = -1;
3405 for (auto const& tcell : tbl->cells)
3407 if( tcell->nRowIndex > j )
3409 if( j > k )
3411 endEl(u"table:table-row"_ustr);
3412 k = j;
3414 // row
3415 mxList->addAttribute(
3416 u"table:style-name"_ustr, sXML_CDATA,
3417 "Table" + OUString::number(hbox->style.boxnum) + ".row"
3418 + OUString::number(tcell->nRowIndex + 1));
3419 startEl(u"table:table-row"_ustr);
3420 mxList->clear();
3421 j = tcell->nRowIndex;
3424 mxList->addAttribute(
3425 u"table:style-name"_ustr, sXML_CDATA,
3426 "Table" + OUString::number(hbox->style.boxnum) + "."
3427 + OUStringChar(char('A'+ tcell->nColumnIndex))
3428 + OUString::number(tcell->nRowIndex +1));
3429 if( tcell->nColumnSpan > 1 )
3430 mxList->addAttribute(u"table:number-columns-spanned"_ustr, sXML_CDATA, OUString::number(tcell->nColumnSpan));
3431 if( tcell->nRowSpan > 1 )
3432 mxList->addAttribute(u"table:number-rows-spanned"_ustr, sXML_CDATA, OUString::number(tcell->nRowSpan));
3433 mxList->addAttribute(u"table:value-type"_ustr, sXML_CDATA,u"string"_ustr);
3434 if( tcell->pCell->protect )
3435 mxList->addAttribute(u"table:protected"_ustr, sXML_CDATA,u"true"_ustr);
3436 startEl(u"table:table-cell"_ustr);
3437 mxList->clear();
3438 TxtBox::plist_t& rVec = hbox->plists[tcell->pCell->key];
3439 if (!rVec.empty())
3440 parsePara(rVec.front().get());
3441 endEl(u"table:table-cell"_ustr);
3443 endEl(u"table:table-row"_ustr);
3444 endEl(u"table:table"_ustr);
3449 * Parses the text boxes and tables.
3450 * 1. draw: style-name, draw: name, text: anchor-type, svg: width,
3451 * Fo: min-height, svg: x, svg: y
3452 * TODO: fo:background-color <= no idea whether the value of color setting->style is in it or not
3454 void HwpReader::makeTextBox(TxtBox * hbox)
3456 if( hbox->style.cap_len > 0 && hbox->type == TXT_TYPE)
3458 mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "CapBox" + OUString::number(hbox->style.boxnum));
3459 mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, "CaptionBox" + OUString::number(hbox->style.boxnum));
3460 mxList->addAttribute(u"draw:z-index"_ustr, sXML_CDATA, OUString::number(hbox->zorder));
3461 switch (hbox->style.anchor_type)
3463 case CHAR_ANCHOR:
3464 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr);
3465 break;
3466 case PARA_ANCHOR:
3467 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr);
3468 break;
3469 case PAGE_ANCHOR:
3470 case PAPER_ANCHOR:
3472 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"page"_ustr);
3473 mxList->addAttribute(u"text:anchor-page-number"_ustr, sXML_CDATA, OUString::number(hbox->pgno + 1));
3474 break;
3477 if (hbox->style.anchor_type != CHAR_ANCHOR)
3479 mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA,
3480 OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
3481 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA,
3482 OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
3484 mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA,
3485 OUString::number(WTMM( hbox->box_xs + hbox->cap_xs )) + "mm");
3486 mxList->addAttribute(u"fo:min-height"_ustr, sXML_CDATA,
3487 OUString::number(WTMM( hbox->box_ys + hbox->cap_ys )) + "mm");
3488 startEl(u"draw:text-box"_ustr);
3489 mxList->clear();
3490 if (!hbox->caption.empty() && hbox->cap_pos % 2) /* The caption is on the top */
3492 parsePara(hbox->caption.front().get());
3494 mxList->addAttribute( u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
3495 startEl(u"text:p"_ustr);
3496 mxList->clear();
3498 else{
3499 mxList->addAttribute(u"draw:z-index"_ustr, sXML_CDATA, OUString::number(hbox->zorder));
3502 mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "Txtbox" + OUString::number(hbox->style.boxnum));
3503 mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, "Frame" + OUString::number(hbox->style.boxnum));
3505 if( hbox->style.cap_len <= 0 || hbox->type != TXT_TYPE )
3507 int x = 0;
3508 int y = 0;
3509 switch (hbox->style.anchor_type)
3511 case CHAR_ANCHOR:
3512 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr);
3513 break;
3514 case PARA_ANCHOR:
3515 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr);
3516 break;
3517 case PAGE_ANCHOR:
3518 case PAPER_ANCHOR:
3520 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"page"_ustr);
3521 mxList->addAttribute(u"text:anchor-page-number"_ustr, sXML_CDATA, OUString::number(hbox->pgno + 1));
3522 break;
3525 if( hbox->style.anchor_type != CHAR_ANCHOR )
3527 x += hbox->style.margin[0][0];
3528 y += hbox->style.margin[0][2];
3530 mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA,
3531 OUString::number(WTMM( hbox->pgx + x )) + "mm");
3532 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA,
3533 OUString::number(WTMM( hbox->pgy + y )) + "mm");
3535 else
3537 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr);
3538 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, u"0cm"_ustr);
3540 mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA,
3541 OUString::number(WTMM( hbox->box_xs )) + "mm");
3542 if( hbox->style.cap_len > 0 && hbox->type != TXT_TYPE)
3543 mxList->addAttribute(u"fo:min-height"_ustr, sXML_CDATA,
3544 OUString::number(WTMM( hbox->box_ys + hbox->cap_ys)) + "mm");
3545 else
3546 mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA,
3547 OUString::number(WTMM(hbox->box_ys )) + "mm");
3549 if( hbox->type != EQU_TYPE )
3551 startEl(u"draw:text-box"_ustr);
3552 mxList->clear();
3553 /* If captions are present and it is on the top */
3554 if (hbox->style.cap_len > 0 && (hbox->cap_pos % 2) && hbox->type == TBL_TYPE && !hbox->caption.empty())
3556 parsePara(hbox->caption.front().get());
3558 if( hbox->type == TBL_TYPE) // Is Table
3560 makeTable(hbox);
3562 else if (!hbox->plists[0].empty()) // Is TextBox
3564 parsePara(hbox->plists[0].front().get());
3566 /* If captions are present and it is on the bottom */
3567 if (hbox->style.cap_len > 0 && !(hbox->cap_pos % 2) && hbox->type == TBL_TYPE && !hbox->caption.empty())
3569 parsePara(hbox->caption.front().get());
3571 endEl(u"draw:text-box"_ustr);
3572 // Caption exist and it is text-box
3573 if( hbox->style.cap_len > 0 && hbox->type == TXT_TYPE)
3575 endEl(u"text:p"_ustr);
3576 if (!(hbox->cap_pos % 2) && !hbox->caption.empty())
3578 parsePara(hbox->caption.front().get());
3580 endEl(u"draw:text-box"_ustr);
3583 else // is Formula
3585 startEl(u"draw:object"_ustr);
3586 mxList->clear();
3587 makeFormula(hbox);
3588 endEl(u"draw:object"_ustr);
3594 * It must be converted into MathML.
3597 void HwpReader::makeFormula(TxtBox * hbox)
3599 char mybuf[3000];
3600 HWPPara* pPar;
3602 hchar dest[3];
3603 size_t l = 0;
3605 pPar = hbox->plists[0].empty() ? nullptr : hbox->plists[0].front().get();
3606 while( pPar )
3608 for (const auto& box : pPar->hhstr)
3610 if (!box->hh)
3611 break;
3613 if (l >= sizeof(mybuf)-7)
3614 break;
3615 int res = hcharconv(box->hh, dest, UNICODE);
3616 for( int j = 0 ; j < res; j++ ){
3617 int c = dest[j];
3618 if( c < 32 )
3619 c = ' ';
3620 if( c < 256 )
3621 mybuf[l++] = sal::static_int_cast<char>(c);
3622 else
3624 mybuf[l++] = sal::static_int_cast<char>((c >> 8) & 0xff);
3625 mybuf[l++] = sal::static_int_cast<char>(c & 0xff);
3629 if (l >= sizeof(mybuf)-7)
3630 break;
3631 mybuf[l++] = '\n';
3632 pPar = pPar->Next();
3634 mybuf[l] = '\0';
3636 Formula form( mybuf );
3637 form.setDocumentHandler(m_rxDocumentHandler);
3638 form.setAttributeListImpl(mxList.get());
3639 form.parse();
3643 * Read the platform information. if the platform is Linux or Solaris, it needs to change
3644 * C: \ => Home, D: \ => changed to root (/). Because HWP uses DOS emulator.
3647 void HwpReader::makeHyperText(TxtBox * hbox)
3649 HyperText *hypert = hwpfile.GetHyperText();
3650 if( !hypert ) return;
3652 if (hypert->filename[0] != '\0') {
3653 ::std::string const tmp = hstr2ksstr(hypert->bookmark);
3654 ::std::string const tmp2 = hstr2ksstr(kstr2hstr(
3655 #ifdef _WIN32
3656 reinterpret_cast<uchar const *>(urltowin(reinterpret_cast<char *>(hypert->filename)).c_str())).c_str());
3657 #else
3658 reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hypert->filename)).c_str())).c_str());
3659 #endif
3660 mxList->addAttribute(u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr);
3661 if (!tmp.empty() && strcmp(tmp.c_str(), "[HTML]")) {
3662 ::std::string tmp3(tmp2);
3663 tmp3.push_back('#');
3664 tmp3.append(tmp);
3665 mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA,
3666 OUString(tmp3.c_str(), tmp3.size()+1, RTL_TEXTENCODING_EUC_KR));
3668 else{
3669 mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA,
3670 OUString(tmp2.c_str(), tmp2.size()+1, RTL_TEXTENCODING_EUC_KR));
3674 else
3676 mxList->addAttribute(u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr);
3677 ::std::string tmp;
3678 tmp.push_back('#');
3679 tmp.append(hstr2ksstr(hypert->bookmark));
3680 mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA,
3681 OUString(tmp.c_str(), tmp.size()+1, RTL_TEXTENCODING_EUC_KR));
3683 startEl(u"draw:a"_ustr);
3684 mxList->clear();
3685 makeTextBox(hbox);
3686 endEl(u"draw:a"_ustr);
3691 * Read the platform information. if the platform is Linux or Solaris, it needs to change
3692 * C: \ => Home, D: \ => changed to root (/). Because HWP uses DOS emulator.
3695 void HwpReader::makePicture(Picture * hbox)
3697 switch (hbox->pictype)
3699 case PICTYPE_OLE:
3700 case PICTYPE_EMBED:
3701 case PICTYPE_FILE:
3703 if( hbox->style.cap_len > 0 )
3705 mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA,
3706 "CapBox" + OUString::number(hbox->style.boxnum));
3707 mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, "CaptionBox" + OUString::number(hbox->style.boxnum));
3708 mxList->addAttribute(u"draw:z-index"_ustr, sXML_CDATA, OUString::number(hbox->zorder));
3709 switch (hbox->style.anchor_type)
3711 case CHAR_ANCHOR:
3712 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr);
3713 break;
3714 case PARA_ANCHOR:
3715 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr);
3716 break;
3717 case PAGE_ANCHOR:
3718 case PAPER_ANCHOR:
3720 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"page"_ustr);
3721 mxList->addAttribute(u"text:anchor-page-number"_ustr, sXML_CDATA,
3722 OUString::number(hbox->pgno + 1));
3723 break;
3726 if (hbox->style.anchor_type != CHAR_ANCHOR)
3728 mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA,
3729 OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
3730 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA,
3731 OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
3733 mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA,
3734 OUString::number(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1] )) + "mm");
3735 mxList->addAttribute(u"fo:min-height"_ustr, sXML_CDATA,
3736 OUString::number(WTMM( hbox->box_ys + hbox->style.margin[1][2] + hbox->style.margin[1][3] + hbox->cap_ys )) + "mm");
3737 startEl(u"draw:text-box"_ustr);
3738 mxList->clear();
3739 if (!hbox->caption.empty() && hbox->cap_pos % 2) /* Caption is on the top */
3741 parsePara(hbox->caption.front().get());
3743 mxList->addAttribute( u"text:style-name"_ustr, sXML_CDATA, u"Standard"_ustr);
3744 startEl(u"text:p"_ustr);
3745 mxList->clear();
3747 if( hbox->ishyper )
3749 mxList->addAttribute(u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr);
3750 #ifdef _WIN32
3751 if( hbox->follow[4] != 0 )
3752 mxList->addAttribute("xlink:href", sXML_CDATA, hstr2OUString(kstr2hstr(hbox->follow.data() + 4).c_str()));
3753 else
3754 mxList->addAttribute("xlink:href", sXML_CDATA, hstr2OUString(kstr2hstr(hbox->follow.data() + 5).c_str()));
3755 #else
3756 if( hbox->follow[4] != 0 )
3757 mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA,
3758 hstr2OUString(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hbox->follow.data() + 4)).c_str())).c_str()));
3759 else
3760 mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA,
3761 hstr2OUString(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hbox->follow.data() + 5)).c_str())).c_str()));
3762 #endif
3763 startEl(u"draw:a"_ustr);
3764 mxList->clear();
3766 mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "G" + OUString::number(hbox->style.boxnum));
3767 mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, "Image" + OUString::number(hbox->style.boxnum));
3769 if( hbox->style.cap_len <= 0 )
3771 mxList->addAttribute(u"draw:z-index"_ustr, sXML_CDATA, OUString::number(hbox->zorder));
3772 switch (hbox->style.anchor_type)
3774 case CHAR_ANCHOR:
3775 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr);
3776 break;
3777 case PARA_ANCHOR:
3778 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr);
3779 break;
3780 case PAGE_ANCHOR:
3781 case PAPER_ANCHOR:
3783 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"page"_ustr);
3784 mxList->addAttribute(u"text:anchor-page-number"_ustr, sXML_CDATA,
3785 OUString::number(hbox->pgno + 1));
3786 break;
3789 if (hbox->style.anchor_type != CHAR_ANCHOR)
3791 mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA,
3792 OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
3793 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA,
3794 OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
3797 else
3799 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr);
3800 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, u"0cm"_ustr);
3802 mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA,
3803 OUString::number(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1])) + "mm");
3804 mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA,
3805 OUString::number(WTMM( hbox->box_ys + hbox->style.margin[1][2] + hbox->style.margin[1][3])) + "mm");
3807 if ( hbox->pictype == PICTYPE_FILE ){
3808 #ifdef _WIN32
3809 sprintf(d->buf, "file:///%s", hbox->picinfo.picun.path );
3810 mxList->addAttribute("xlink:href", sXML_CDATA, hstr2OUString(kstr2hstr(reinterpret_cast<uchar *>(d->buf)).c_str()));
3811 #else
3812 mxList->addAttribute(u"xlink:href"_ustr, sXML_CDATA,
3813 hstr2OUString(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(hbox->picinfo.picun.path).c_str())).c_str()));
3814 #endif
3815 mxList->addAttribute(u"xlink:type"_ustr, sXML_CDATA, u"simple"_ustr);
3816 mxList->addAttribute(u"xlink:show"_ustr, sXML_CDATA, u"embed"_ustr);
3817 mxList->addAttribute(u"xlink:actuate"_ustr, sXML_CDATA, u"onLoad"_ustr);
3820 if( hbox->pictype == PICTYPE_OLE )
3821 startEl(u"draw:object-ole"_ustr);
3822 else
3823 startEl(u"draw:image"_ustr);
3824 mxList->clear();
3825 if (hbox->pictype == PICTYPE_EMBED || hbox->pictype == PICTYPE_OLE)
3827 startEl(u"office:binary-data"_ustr);
3828 mxList->clear();
3829 if( hbox->pictype == PICTYPE_EMBED ){
3830 EmPicture *emp = hwpfile.GetEmPicture(hbox);
3831 if( emp )
3833 chars(base64_encode_string(emp->data.data(), emp->size));
3836 else{
3837 if( hwpfile.oledata ){
3838 #ifdef _WIN32
3839 LPSTORAGE srcsto;
3840 LPUNKNOWN pObj;
3841 wchar_t pathname[200];
3843 MultiByteToWideChar(CP_ACP, 0, hbox->picinfo.picembed.embname, -1, pathname, 200);
3844 int rc = hwpfile.oledata->pis->OpenStorage(pathname, nullptr,
3845 STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, nullptr, 0, &srcsto);
3846 if (rc != S_OK) {
3847 chars("");
3849 else{
3850 rc = OleLoad(srcsto, IID_IUnknown, nullptr, reinterpret_cast<LPVOID*>(&pObj));
3851 if( rc != S_OK ){
3852 srcsto->Release();
3853 chars("");
3855 else{
3856 chars(base64_encode_string(reinterpret_cast<uchar*>(pObj), strlen(reinterpret_cast<char*>(pObj))));
3857 pObj->Release();
3858 srcsto->Release();
3861 #else
3862 chars(u""_ustr);
3863 #endif
3866 endEl(u"office:binary-data"_ustr);
3868 if( hbox->pictype == PICTYPE_OLE )
3869 endEl(u"draw:object-ole"_ustr);
3870 else
3871 endEl(u"draw:image"_ustr);
3872 if( hbox->ishyper )
3874 endEl(u"draw:a"_ustr);
3876 if( hbox->style.cap_len > 0 )
3878 endEl(u"text:p"_ustr);
3879 if (!hbox->caption.empty() && !(hbox->cap_pos % 2)) /* Caption is at the bottom, */
3881 parsePara(hbox->caption.front().get());
3883 endEl(u"draw:text-box"_ustr);
3885 break;
3887 case PICTYPE_DRAW:
3888 if( hbox->picinfo.picdraw.zorder > 0 )
3889 mxList->addAttribute(u"draw:z-index"_ustr, sXML_CDATA,
3890 OUString::number(hbox->picinfo.picdraw.zorder + 10000));
3891 makePictureDRAW(hbox->picinfo.picdraw.hdo, hbox);
3892 break;
3893 case PICTYPE_UNKNOWN:
3894 break;
3898 void HwpReader::makePictureDRAW(HWPDrawingObject *drawobj, const Picture* hbox)
3900 bool bIsRotate = false;
3902 while (drawobj)
3904 mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "Draw" + OUString::number(drawobj->index));
3905 int a = 0;
3906 int b = 0;
3908 switch (hbox->style.anchor_type)
3910 case CHAR_ANCHOR:
3911 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"as-char"_ustr);
3912 break;
3913 case PARA_ANCHOR:
3914 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr);
3915 break;
3916 case PAGE_ANCHOR:
3917 case PAPER_ANCHOR:
3919 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
3920 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"page"_ustr);
3921 mxList->addAttribute(u"text:anchor-page-number"_ustr, sXML_CDATA, OUString::number(hbox->pgno + 1));
3922 a = hwpinfo.paper.left_margin;
3923 b = hwpinfo.paper.top_margin + hwpinfo.paper.header_length;
3924 break;
3928 if (drawobj->type == HWPDO_CONTAINER)
3930 startEl(u"draw:g"_ustr);
3931 mxList->clear();
3932 makePictureDRAW(drawobj->child.get(), hbox);
3933 endEl(u"draw:g"_ustr);
3935 else
3937 double x = hbox->pgx;
3938 double y = hbox->pgy;
3940 bIsRotate = false;
3941 if( (drawobj->property.flag & HWPDO_FLAG_ROTATION) &&
3942 (drawobj->property.parall.pt[0].y != drawobj->property.parall.pt[1].y) &&
3943 //(drawobj->type == HWPDO_RECT || drawobj->type == HWPDO_ADVANCED_ELLIPSE || drawobj->type == HWPDO_ADVANCED_ARC )
3944 (drawobj->type == HWPDO_RECT || drawobj->type == HWPDO_ADVANCED_ELLIPSE )
3948 int i;
3949 ZZParall& pal = drawobj->property.parall;
3951 basegfx::B2DPoint pt[3], r_pt[3];
3952 for(i = 0 ; i < 3 ; i++ ){
3953 basegfx::B2DPoint rot_origin(drawobj->property.rot_originx, drawobj->property.rot_originy);
3954 pt[i].setX(pal.pt[i].x - rot_origin.getX());
3955 /* Convert to a physical coordinate */
3956 pt[i].setY(-(pal.pt[i].y - rot_origin.getY()));
3959 double skewX;
3961 /* 2 - rotation angle calculation */
3962 double rotate = atan2(pt[1].getY() - pt[0].getY(), pt[1].getX() - pt[0].getX());
3964 for( i = 0 ; i < 3 ; i++){
3965 r_pt[i].setX(pt[i].getX() * cos(-rotate) - pt[i].getY() * sin(-rotate));
3966 r_pt[i].setY(pt[i].getY() * cos(-rotate) + pt[i].getX() * sin(-rotate));
3969 /* 4 - Calculation of reflex angle */
3970 if (r_pt[2].getY() == r_pt[1].getY())
3971 skewX = 0;
3972 else
3973 skewX = atan((r_pt[2].getX() - r_pt[1].getX()) / (r_pt[2].getY() - r_pt[1].getY()));
3974 if( skewX >= M_PI_2 )
3975 skewX -= M_PI;
3976 if( skewX <= -M_PI_2 )
3977 skewX += M_PI;
3979 OUString trans;
3980 if( skewX != 0.0 && rotate != 0.0 ){
3981 trans = "skewX (" + OUString::number(skewX)
3982 + ") rotate (" + OUString::number(rotate)
3983 + ") translate (" + OUString::number(WTMM(x + a + drawobj->offset2.x + pal.pt[0].x)) + "mm "
3984 + OUString::number(WTMM(y + b + drawobj->offset2.y + pal.pt[0].y)) + "mm)";
3985 bIsRotate = true;
3987 else if( skewX != 0.0 ){
3988 trans = "skewX (" + OUString::number(skewX)
3989 + ") translate (" + OUString::number(WTMM(x + a + drawobj->offset2.x + pal.pt[0].x)) + "mm "
3990 + OUString::number(WTMM(y + b + drawobj->offset2.y + pal.pt[0].y)) + "mm)";
3991 bIsRotate = true;
3993 else if( rotate != 0.0 ){
3994 trans = "rotate (" + OUString::number(rotate)
3995 + ") translate (" + OUString::number(WTMM(x + a + drawobj->offset2.x + pal.pt[0].x)) + "mm "
3996 + OUString::number(WTMM(y + b + drawobj->offset2.y + pal.pt[0].y)) + "mm)";
3997 bIsRotate = true;
3999 if( bIsRotate ){
4000 drawobj->extent.w = static_cast<int>(std::hypot(pt[1].getX() - pt[0].getX(), pt[1].getY() - pt[0].getY()));
4001 drawobj->extent.h = static_cast<int>(std::hypot(pt[2].getX() - pt[1].getX(), pt[2].getY() - pt[1].getY()));
4002 mxList->addAttribute(u"draw:transform"_ustr, sXML_CDATA, trans);
4005 switch (drawobj->type)
4007 case HWPDO_LINE: /* Line-starting coordinates, ending coordinates. */
4008 if( drawobj->u.line_arc.flip & 0x01 )
4010 mxList->addAttribute(u"svg:x1"_ustr, sXML_CDATA,
4011 OUString::number (WTMM(x + a + drawobj->offset2.x + drawobj->extent.w)) + "mm");
4012 mxList->addAttribute(u"svg:x2"_ustr, sXML_CDATA,
4013 OUString::number (WTMM( x + a + drawobj->offset2.x )) + "mm");
4015 else
4017 mxList->addAttribute(u"svg:x1"_ustr, sXML_CDATA,
4018 OUString::number (WTMM( x + a + drawobj->offset2.x )) + "mm");
4019 mxList->addAttribute(u"svg:x2"_ustr, sXML_CDATA,
4020 OUString::number (WTMM(x + a + drawobj->offset2.x + drawobj->extent.w)) + "mm");
4022 if( drawobj->u.line_arc.flip & 0x02 )
4024 mxList->addAttribute(u"svg:y1"_ustr, sXML_CDATA,
4025 OUString::number (WTMM( y + b + drawobj->offset2.y + drawobj->extent.h ) ) + "mm");
4026 mxList->addAttribute(u"svg:y2"_ustr, sXML_CDATA,
4027 OUString::number (WTMM( y + b + drawobj->offset2.y )) + "mm");
4029 else
4031 mxList->addAttribute(u"svg:y1"_ustr, sXML_CDATA,
4032 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4033 mxList->addAttribute(u"svg:y2"_ustr, sXML_CDATA,
4034 OUString::number (WTMM(y + b + drawobj->offset2.y + drawobj->extent.h)) + "mm");
4037 startEl(u"draw:line"_ustr);
4038 mxList->clear();
4039 endEl(u"draw:line"_ustr);
4040 break;
4041 case HWPDO_RECT: /* rectangle - the starting position, vertical/horizontal */
4042 if( !bIsRotate )
4044 mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA,
4045 OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
4046 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA,
4047 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4049 mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA,
4050 OUString::number (WTMM( drawobj->extent.w )) + "mm");
4051 mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA,
4052 OUString::number (WTMM( drawobj->extent.h )) + "mm");
4053 if( drawobj->property.flag & 0x01 )
4055 int value = drawobj->extent.w < drawobj->extent.h ?
4056 drawobj->extent.w : drawobj->extent.h ;
4057 mxList->addAttribute(u"draw:corner-radius"_ustr, sXML_CDATA,
4058 OUString::number (WTMM( value/10 )) + "mm");
4060 else if( drawobj->property.flag & 0x04 )
4062 int value = drawobj->extent.w < drawobj->extent.h ?
4063 drawobj->extent.w : drawobj->extent.h ;
4064 mxList->addAttribute(u"draw:corner-radius"_ustr, sXML_CDATA,
4065 OUString::number (WTMM( value / 2)) + "mm");
4068 startEl(u"draw:rect"_ustr);
4069 mxList->clear();
4070 if( (drawobj->property.flag & HWPDO_FLAG_AS_TEXTBOX) &&
4071 drawobj->property.pPara ) // As Textbox
4073 HWPPara *pPara = drawobj->property.pPara;
4074 //parsePara(pPara);
4075 while(pPara)
4077 make_text_p1( pPara, false );
4078 pPara = pPara->Next();
4081 endEl(u"draw:rect"_ustr);
4082 break;
4083 case HWPDO_ELLIPSE: /* Ellipse - the starting position, vertical/horizontal */
4084 case HWPDO_ADVANCED_ELLIPSE: /* modified ellipse */
4086 if( !bIsRotate )
4088 mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA,
4089 OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
4090 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA,
4091 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4094 mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA,
4095 OUString::number (WTMM( drawobj->extent.w )) + "mm");
4096 mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA,
4097 OUString::number (WTMM( drawobj->extent.h )) + "mm");
4098 if( drawobj->type == HWPDO_ADVANCED_ELLIPSE ){
4099 if (drawobj->u.arc.radial[0].x != drawobj->u.arc.radial[1].x ||
4100 drawobj->u.arc.radial[0].y != drawobj->u.arc.radial[1].y) {
4102 int Cx, Cy;
4103 if (!o3tl::checked_add(drawobj->offset2.x, drawobj->extent.w, Cx) &&
4104 !o3tl::checked_add(drawobj->offset2.y, drawobj->extent.h, Cy))
4106 Cx /= 2;
4107 Cy /= 2;
4109 double start_angle = calcAngle( Cx, Cy, drawobj->u.arc.radial[0].x, drawobj->u.arc.radial[0].y );
4110 double end_angle = calcAngle( Cx, Cy, drawobj->u.arc.radial[1].x, drawobj->u.arc.radial[1].y );
4111 if( drawobj->property.fill_color < 0xffffff )
4112 mxList->addAttribute(u"draw:kind"_ustr, sXML_CDATA, u"section"_ustr);
4113 else
4114 mxList->addAttribute(u"draw:kind"_ustr, sXML_CDATA, u"arc"_ustr);
4115 mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, OUString::number(start_angle ));
4116 mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, OUString::number(end_angle));
4120 startEl(u"draw:ellipse"_ustr);
4121 mxList->clear();
4122 if( drawobj->property.flag >> 19 & 0x01 &&
4123 drawobj->property.pPara ) // As Textbox
4125 HWPPara *pPara = drawobj->property.pPara;
4126 //parsePara(pPara);
4127 while(pPara)
4129 make_text_p1( pPara, false );
4130 pPara = pPara->Next();
4133 endEl(u"draw:ellipse"_ustr);
4134 break;
4137 case HWPDO_ARC: /* Arc */
4138 case HWPDO_ADVANCED_ARC:
4140 /* If it is the arc, LibreOffice assumes the size as the entire ellipse size */
4141 uint flip = drawobj->u.line_arc.flip;
4142 if( !bIsRotate )
4144 if( ( flip == 0 || flip == 2 ) && drawobj->type == HWPDO_ARC)
4145 mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA,
4146 OUString::number (WTMM( x + a + drawobj->offset2.x - drawobj->extent.w)) + "mm");
4147 else
4148 mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA,
4149 OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
4150 if( ( flip == 0 || flip == 1 ) && drawobj->type == HWPDO_ARC)
4151 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA,
4152 OUString::number (WTMM( y + b + drawobj->offset2.y - drawobj->extent.h)) + "mm");
4153 else
4154 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA,
4155 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4158 mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA,
4159 OUString::number (WTMM( drawobj->extent.w * 2)) + "mm");
4160 mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA,
4161 OUString::number (WTMM( drawobj->extent.h * 2)) + "mm");
4162 if( drawobj->property.flag & HWPDO_FLAG_DRAW_PIE ||
4163 drawobj->property.fill_color < 0xffffff )
4164 mxList->addAttribute(u"draw:kind"_ustr, sXML_CDATA, u"section"_ustr);
4165 else
4166 mxList->addAttribute(u"draw:kind"_ustr, sXML_CDATA, u"arc"_ustr);
4168 if( drawobj->type == HWPDO_ADVANCED_ARC ){
4169 double start_angle, end_angle;
4170 ZZParall& pal = drawobj->property.parall;
4172 start_angle = atan2(pal.pt[0].y - pal.pt[1].y,pal.pt[1].x - pal.pt[0].x );
4173 end_angle = atan2(pal.pt[2].y - pal.pt[1].y, pal.pt[1].x - pal.pt[2].x);
4175 if( ( start_angle > end_angle ) && (start_angle - end_angle < M_PI ))
4176 std::swap( start_angle, end_angle );
4177 mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, OUString::number(basegfx::rad2deg(start_angle)));
4178 mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, OUString::number(basegfx::rad2deg(end_angle)));
4181 else
4183 if( drawobj->u.line_arc.flip == 0 )
4185 mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, u"270"_ustr);
4186 mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, u"0"_ustr);
4188 else if( drawobj->u.line_arc.flip == 1 )
4190 mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, u"180"_ustr);
4191 mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, u"270"_ustr);
4193 else if( drawobj->u.line_arc.flip == 2 )
4195 mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, u"0"_ustr);
4196 mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, u"90"_ustr);
4198 else
4200 mxList->addAttribute(u"draw:start-angle"_ustr, sXML_CDATA, u"90"_ustr);
4201 mxList->addAttribute(u"draw:end-angle"_ustr, sXML_CDATA, u"180"_ustr);
4204 startEl(u"draw:ellipse"_ustr);
4205 mxList->clear();
4206 if( drawobj->property.flag >> 19 & 0x01 &&
4207 drawobj->property.pPara ) // As Textbox
4209 HWPPara *pPara = drawobj->property.pPara;
4210 //parsePara(pPara);
4211 while(pPara)
4213 make_text_p1( pPara, false );
4214 pPara = pPara->Next();
4217 endEl(u"draw:ellipse"_ustr);
4218 break;
4221 case HWPDO_CURVE: /* Curve: converts to polygons. */
4223 bool bIsNatural = true;
4224 if( drawobj->property.flag >> 5 & 0x01){
4225 bIsNatural = false;
4227 if( !bIsRotate )
4229 mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA,
4230 OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
4231 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA,
4232 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4234 mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA,
4235 OUString::number (WTMM( drawobj->extent.w )) + "mm");
4236 mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA,
4237 OUString::number (WTMM( drawobj->extent.h )) + "mm");
4238 mxList->addAttribute(
4239 u"svg:viewBox"_ustr, sXML_CDATA,
4240 "0 0 " + OUString::number(WTSM(drawobj->extent.w)) + " "
4241 + OUString::number(WTSM(drawobj->extent.h)));
4243 OUStringBuffer oustr;
4245 if ((drawobj->u.freeform.npt > 2) &&
4246 (o3tl::make_unsigned(drawobj->u.freeform.npt) <
4247 (::std::numeric_limits<int>::max() / sizeof(double))))
4249 int n, i;
4250 n = drawobj->u.freeform.npt;
4252 std::unique_ptr<double[]> xarr( new double[n+1] );
4253 std::unique_ptr<double[]> yarr( new double[n+1] );
4254 std::unique_ptr<double[]> tarr( new double[n+1] );
4256 std::unique_ptr<double[]> xb;
4257 std::unique_ptr<double[]> yb;
4259 std::unique_ptr<double[]> carr;
4260 std::unique_ptr<double[]> darr;
4263 for( i = 0 ; i < n ; i++ ){
4264 xarr[i] = drawobj->u.freeform.pt[i].x;
4265 yarr[i] = drawobj->u.freeform.pt[i].y;
4266 tarr[i] = i;
4268 xarr[n] = xarr[0];
4269 yarr[n] = yarr[0];
4270 tarr[n] = n;
4272 if( !bIsNatural ){
4273 PeriodicSpline(n, tarr.get(), xarr.get(), xb, carr, darr);
4274 // prevent memory leak
4275 carr.reset();
4276 darr.reset();
4277 PeriodicSpline(n, tarr.get(), yarr.get(), yb, carr, darr);
4279 else{
4280 NaturalSpline(n, tarr.get(), xarr.get(), xb, carr, darr);
4281 // prevent memory leak
4282 carr.reset();
4283 darr.reset();
4284 NaturalSpline(n, tarr.get(), yarr.get(), yb, carr, darr);
4287 oustr.append(
4288 "M" + OUString::number(WTSM(xarr[0])) + " "
4289 + OUString::number(WTSM(yarr[0])) + "C"
4290 + OUString::number(WTSM(xarr[0] + xb[0]/3)) + " "
4291 + OUString::number(WTSM(yarr[0] + yb[0]/3)));
4293 for( i = 1 ; i < n ; i++ ){
4294 if( i == n -1 ){
4295 oustr.append(
4296 " " + OUString::number(WTSM(xarr[i] - xb[i]/3)) + " "
4297 + OUString::number(WTSM(yarr[i] - yb[i]/3)) + " "
4298 + OUString::number(WTSM(xarr[i])) + " "
4299 + OUString::number(WTSM(yarr[i])) + "z");
4301 else{
4302 oustr.append(
4303 " " + OUString::number(WTSM(xarr[i] - xb[i]/3)) + " "
4304 + OUString::number(WTSM(yarr[i] - yb[i]/3)) + " "
4305 + OUString::number(WTSM(xarr[i])) + " "
4306 + OUString::number(WTSM(yarr[i])) + " "
4307 + OUString::number(WTSM(xarr[i] + xb[i]/3)) + " "
4308 + OUString::number(WTSM(yarr[i] + yb[i]/3)));
4313 mxList->addAttribute(u"svg:d"_ustr, sXML_CDATA, oustr.makeStringAndClear());
4315 startEl(u"draw:path"_ustr);
4316 mxList->clear();
4317 // As Textbox
4318 if( drawobj->property.flag >> 19 & 0x01 && drawobj->property.pPara )
4320 HWPPara *pPara = drawobj->property.pPara;
4321 while(pPara)
4323 make_text_p1( pPara, false );
4324 pPara = pPara->Next();
4327 endEl(u"draw:path"_ustr);
4328 break;
4330 case HWPDO_CLOSED_FREEFORM:
4331 case HWPDO_FREEFORM: /* polygon */
4333 bool bIsPolygon = false;
4335 mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA,
4336 OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
4337 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA,
4338 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4340 mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA,
4341 OUString::number (WTMM( drawobj->extent.w )) + "mm");
4342 mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA,
4343 OUString::number (WTMM( drawobj->extent.h )) + "mm");
4345 mxList->addAttribute(u"svg:viewBox"_ustr, sXML_CDATA, "0 0 " + OUString::number(WTSM(drawobj->extent.w)) + " " + OUString::number(WTSM(drawobj->extent.h)));
4347 OUStringBuffer oustr;
4349 if (drawobj->u.freeform.npt > 0)
4351 oustr.append(
4352 OUString::number(WTSM(drawobj->u.freeform.pt[0].x)) + ","
4353 + OUString::number(WTSM(drawobj->u.freeform.pt[0].y)));
4354 int i;
4355 for (i = 1; i < drawobj->u.freeform.npt ; i++)
4357 oustr.append(
4358 " " + OUString::number(WTSM(drawobj->u.freeform.pt[i].x)) + ","
4359 + OUString::number(WTSM(drawobj->u.freeform.pt[i].y)));
4361 if( drawobj->u.freeform.pt[0].x == drawobj->u.freeform.pt[i-1].x &&
4362 drawobj->u.freeform.pt[0].y == drawobj->u.freeform.pt[i-1].y )
4364 bIsPolygon = true;
4367 mxList->addAttribute(u"draw:points"_ustr, sXML_CDATA, oustr.makeStringAndClear());
4369 if( drawobj->property.fill_color <= 0xffffff ||
4370 drawobj->property.pattern_type != 0)
4372 bIsPolygon = true;
4375 if(bIsPolygon)
4377 startEl(u"draw:polygon"_ustr);
4378 mxList->clear();
4379 if( drawobj->property.flag >> 19 & 0x01 &&
4380 // As Textbox
4381 drawobj->property.pPara )
4383 HWPPara *pPara = drawobj->property.pPara;
4384 // parsePara(pPara);
4385 while(pPara)
4387 make_text_p1( pPara, false );
4388 pPara = pPara->Next();
4391 endEl(u"draw:polygon"_ustr);
4393 else
4395 startEl(u"draw:polyline"_ustr);
4396 mxList->clear();
4397 if( drawobj->property.flag >> 19 & 0x01 &&
4398 // As Textbox
4399 drawobj->property.pPara )
4401 HWPPara *pPara = drawobj->property.pPara;
4402 //parsePara(pPara);
4403 while(pPara)
4405 make_text_p1( pPara, false );
4406 pPara = pPara->Next();
4409 endEl(u"draw:polyline"_ustr);
4411 break;
4413 case HWPDO_TEXTBOX:
4414 if( !bIsRotate )
4416 mxList->addAttribute(u"svg:x"_ustr, sXML_CDATA,
4417 OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
4418 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA,
4419 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4421 mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA,
4422 OUString::number (WTMM( drawobj->extent.w )) + "mm");
4423 mxList->addAttribute(u"svg:height"_ustr, sXML_CDATA,
4424 OUString::number (WTMM( drawobj->extent.h )) + "mm");
4425 if( drawobj->property.flag & 0x01 )
4427 int value = drawobj->extent.w < drawobj->extent.h ?
4428 drawobj->extent.w : drawobj->extent.h ;
4429 mxList->addAttribute(u"draw:corner-radius"_ustr, sXML_CDATA,
4430 OUString::number (WTMM( value/10 )) + "mm");
4432 else if( drawobj->property.flag & 0x04 )
4434 int value = drawobj->extent.w < drawobj->extent.h ?
4435 drawobj->extent.w : drawobj->extent.h ;
4436 mxList->addAttribute(u"draw:corner-radius"_ustr, sXML_CDATA,
4437 OUString::number (WTMM( value / 2)) + "mm");
4440 startEl(u"draw:text-box"_ustr);
4441 mxList->clear();
4443 HWPPara *pPara = drawobj->u.textbox.h;
4444 //parsePara(pPara);
4445 while(pPara)
4447 make_text_p1( pPara, false );
4448 pPara = pPara->Next();
4451 endEl(u"draw:text-box"_ustr);
4452 break;
4455 mxList->clear();
4456 drawobj = drawobj->next.get();
4460 void HwpReader::makeLine()
4462 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, u"Horizontal Line"_ustr);
4463 startEl(u"text:p"_ustr);
4464 mxList->clear();
4468 * Input-comment-hidden description: shows a hidden explanation to the users.
4469 * Parse out only strings, but it may contain paragraphs.
4471 void HwpReader::makeHidden(Hidden * hbox)
4473 hchar_string str;
4474 int res;
4475 hchar dest[3];
4477 mxList->addAttribute(u"text:condition"_ustr, sXML_CDATA, u""_ustr);
4478 mxList->addAttribute(u"text:string-value"_ustr, sXML_CDATA, u""_ustr);
4479 startEl(u"text:hidden-text"_ustr);
4480 mxList->clear();
4481 HWPPara *para = !hbox->plist.empty() ? hbox->plist.front().get() : nullptr;
4483 while (para)
4485 for (const auto& box : para->hhstr)
4487 if (!box->hh)
4488 break;
4490 res = hcharconv(box->hh, dest, UNICODE);
4491 for( int j = 0 ; j < res ; j++ )
4493 str.push_back(dest[j]);
4496 para = para->Next();
4498 makeChars(str);
4499 endEl(u"text:hidden-text"_ustr);
4504 * Converts footnote to text:footnote, endnote to text:endnote
4506 void HwpReader::makeFootnote(Footnote * hbox)
4508 if (hbox->type)
4510 mxList->addAttribute(u"text:id"_ustr, sXML_CDATA, "edn" + OUString::number(hbox->number));
4511 startEl(u"text:endnote"_ustr);
4512 mxList->clear();
4513 mxList->addAttribute(u"text:label"_ustr, sXML_CDATA, OUString::number(hbox->number));
4514 startEl(u"text:endnote-citation"_ustr);
4515 mxList->clear();
4516 chars(OUString::number(hbox->number));
4517 endEl(u"text:endnote-citation"_ustr);
4518 startEl(u"text:endnote-body"_ustr);
4519 if (!hbox->plist.empty())
4520 parsePara(hbox->plist.front().get());
4521 endEl(u"text:endnote-body"_ustr);
4522 endEl(u"text:endnote"_ustr);
4524 else
4526 mxList->addAttribute(u"text:id"_ustr, sXML_CDATA, "ftn" + OUString::number(hbox->number));
4527 startEl(u"text:footnote"_ustr);
4528 mxList->clear();
4529 mxList->addAttribute(u"text:label"_ustr, sXML_CDATA, OUString::number(hbox->number));
4530 startEl(u"text:footnote-citation"_ustr);
4531 mxList->clear();
4532 chars(OUString::number(hbox->number));
4533 endEl(u"text:footnote-citation"_ustr);
4534 startEl(u"text:footnote-body"_ustr);
4535 if (!hbox->plist.empty())
4536 parsePara(hbox->plist.front().get());
4537 endEl(u"text:footnote-body"_ustr);
4538 endEl(u"text:footnote"_ustr);
4544 * page/footnote/endnote/picture/table/formula number
4546 void HwpReader::makeAutoNum(AutoNum const * hbox)
4548 switch (hbox->type)
4550 case PGNUM_AUTO:
4551 startEl(u"text:page-number"_ustr);
4552 chars(OUString::number(hbox->number));
4553 endEl(u"text:page-number"_ustr);
4554 break;
4555 case FNNUM_AUTO:
4556 break;
4557 case ENNUM_AUTO:
4558 break;
4559 case EQUNUM_AUTO:
4560 case PICNUM_AUTO:
4561 mxList->addAttribute(u"text:ref-name"_ustr,sXML_CDATA, "refIllustration" + OUString::number(hbox->number));
4562 mxList->addAttribute(u"text:name"_ustr,sXML_CDATA, u"Illustration"_ustr);
4563 mxList->addAttribute(u"style:num-format"_ustr,sXML_CDATA, u"1"_ustr);
4564 startEl(u"text:sequence"_ustr);
4565 chars(OUString::number(hbox->number));
4566 endEl(u"text:sequence"_ustr);
4567 break;
4568 case TBLNUM_AUTO:
4569 mxList->addAttribute(u"text:ref-name"_ustr,sXML_CDATA, "refTable" + OUString::number(hbox->number));
4570 mxList->addAttribute(u"text:name"_ustr,sXML_CDATA, u"Table"_ustr);
4571 mxList->addAttribute(u"style:num-format"_ustr,sXML_CDATA, u"1"_ustr);
4572 startEl(u"text:sequence"_ustr);
4573 chars(OUString::number(hbox->number));
4574 endEl(u"text:sequence"_ustr);
4575 break;
4580 void HwpReader::makeShowPageNum()
4582 ShowPageNum *hbox = d->pPn;
4583 int nPos = 0;
4584 if( hbox->where == 1 || hbox->where == 4 )
4585 nPos = 1;
4586 else if( hbox->where == 2 || hbox->where == 5 )
4587 nPos = 2;
4588 else if( hbox->where == 3 || hbox->where == 6 )
4589 nPos = 3;
4590 else /* should not exist in this case. */
4592 if( d->nPnPos == 1 )
4593 nPos = 1;
4594 else if( d->nPnPos == 3 )
4595 nPos = 3;
4598 mxList->addAttribute(u"draw:style-name"_ustr, sXML_CDATA, "PNBox" + OUString::number(nPos));
4599 mxList->addAttribute(u"draw:name"_ustr, sXML_CDATA, "PageNumber" + OUString::number(nPos));
4600 mxList->addAttribute(u"text:anchor-type"_ustr, sXML_CDATA, u"paragraph"_ustr);
4601 mxList->addAttribute(u"svg:y"_ustr, sXML_CDATA, u"0cm"_ustr);
4602 mxList->addAttribute(u"svg:width"_ustr, sXML_CDATA, u"2.0cm"_ustr);
4603 mxList->addAttribute(u"fo:min-height"_ustr, sXML_CDATA, u"0.5cm"_ustr);
4604 startEl(u"draw:text-box"_ustr);
4605 mxList->clear();
4607 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA, "PNPara" + OUString::number(nPos));
4608 startEl(u"text:p"_ustr);
4609 mxList->clear();
4610 if( hbox->shape > 2 )
4611 chars(u"- "_ustr);
4612 if( hbox->shape % 3 == 0 )
4613 mxList->addAttribute(u"style:num-format"_ustr, sXML_CDATA, u"1"_ustr);
4614 else if( hbox->shape % 3 == 1 )
4615 mxList->addAttribute(u"style:num-format"_ustr, sXML_CDATA, u"I"_ustr);
4616 else
4617 mxList->addAttribute(u"style:num-format"_ustr, sXML_CDATA, u"i"_ustr);
4618 mxList->addAttribute(u"text:select-page"_ustr, sXML_CDATA, u"current"_ustr);
4619 startEl(u"text:page-number"_ustr);
4620 mxList->clear();
4621 chars(u"2"_ustr);
4622 endEl(u"text:page-number"_ustr);
4623 if( hbox->shape > 2 )
4624 chars(u" -"_ustr);
4625 endEl(u"text:p"_ustr);
4626 endEl(u"draw:text-box"_ustr);
4631 * mail merge operation using hwp addressbook and hwp data form.
4632 * not support operation in OO writer.
4634 void HwpReader::makeMailMerge(MailMerge *)
4636 hchar_string const boxstr = MailMerge::GetString();
4637 chars(hstr2OUString(boxstr.c_str()));
4641 void HwpReader::makeOutline(Outline const * hbox)
4643 if( hbox->kind == 1 )
4644 chars( hbox->GetUnicode() );
4648 void HwpReader::parsePara(HWPPara * para)
4650 bool bParaStart = false;
4651 while (para)
4653 if( para->nch == 1)
4655 if( !bParaStart )
4657 mxList->addAttribute(u"text:style-name"_ustr, sXML_CDATA,
4658 getPStyleName(para->GetParaShape().index));
4659 startEl(u"text:p"_ustr);
4660 mxList->clear();
4662 if( d->bFirstPara && d->bInBody )
4664 /* for HWP's Bookmark */
4665 mxList->addAttribute(u"text:name"_ustr, sXML_CDATA, sBeginOfDoc);
4666 startEl(u"text:bookmark"_ustr);
4667 mxList->clear();
4668 endEl(u"text:bookmark"_ustr);
4669 d->bFirstPara = false;
4671 if( d->bInHeader )
4673 makeShowPageNum();
4674 d->bInHeader = false;
4677 endEl(u"text:p"_ustr);
4679 else
4681 if (!para->ctrlflag)
4683 if (para->contain_cshape)
4684 make_text_p1(para, bParaStart);
4685 else
4686 make_text_p0(para, bParaStart);
4688 else
4689 make_text_p3(para, bParaStart);
4691 bParaStart = false;
4692 para = para->Next();
4697 void HwpReader::startEl(const OUString& el)
4699 if (m_rxDocumentHandler)
4700 m_rxDocumentHandler->startElement(el, mxList);
4704 void HwpReader::endEl(const OUString& el)
4706 if (m_rxDocumentHandler)
4707 m_rxDocumentHandler->endElement(el);
4711 void HwpReader::chars(const OUString& s)
4713 if (m_rxDocumentHandler)
4714 m_rxDocumentHandler->characters(s);
4718 namespace
4721 constexpr OUStringLiteral IMPLEMENTATION_NAME = u"com.sun.comp.hwpimport.HwpImportFilter";
4722 constexpr OUString SERVICE_NAME1 = u"com.sun.star.document.ImportFilter"_ustr;
4723 constexpr OUString SERVICE_NAME2 = u"com.sun.star.document.ExtendedTypeDetection"_ustr;
4725 class HwpImportFilter : public WeakImplHelper< XFilter, XImporter, XServiceInfo, XExtendedFilterDetection >
4727 public:
4728 explicit HwpImportFilter(const Reference< XComponentContext >& );
4730 public:
4731 // XFilter
4732 virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& aDescriptor ) override;
4733 virtual void SAL_CALL cancel() override;
4735 // XImporter
4736 virtual void SAL_CALL setTargetDocument( const Reference< XComponent >& xDoc) override;
4738 // XServiceInfo
4739 OUString SAL_CALL getImplementationName() override;
4740 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
4741 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
4743 //XExtendedFilterDetection
4744 virtual OUString SAL_CALL detect( css::uno::Sequence< css::beans::PropertyValue >& rDescriptor ) override;
4746 private:
4747 rtl::Reference< HwpReader > rFilter;
4748 Reference< XImporter > rImporter;
4752 HwpImportFilter::HwpImportFilter(const Reference< XComponentContext >& rxContext)
4754 Reference<XDocumentHandler> xHandler(rxContext->getServiceManager()->createInstanceWithContext(WRITER_IMPORTER_NAME, rxContext), UNO_QUERY);
4756 rFilter = new HwpReader;
4757 rFilter->setDocumentHandler( xHandler );
4759 rImporter.set(xHandler, UNO_QUERY);
4762 sal_Bool HwpImportFilter::filter( const Sequence< PropertyValue >& aDescriptor )
4764 // delegate to IchitaroImporter
4765 return rFilter->filter( aDescriptor );
4768 void HwpImportFilter::cancel()
4770 rFilter->cancel();
4773 void HwpImportFilter::setTargetDocument( const Reference< XComponent >& xDoc )
4775 // delegate
4776 rImporter->setTargetDocument( xDoc );
4779 OUString HwpImportFilter::getImplementationName()
4781 return IMPLEMENTATION_NAME;
4784 sal_Bool HwpImportFilter::supportsService( const OUString& ServiceName )
4786 return cppu::supportsService(this, ServiceName);
4789 //XExtendedFilterDetection
4790 OUString HwpImportFilter::detect( css::uno::Sequence< css::beans::PropertyValue >& rDescriptor )
4792 OUString sTypeName;
4794 utl::MediaDescriptor aDescriptor(rDescriptor);
4795 aDescriptor.addInputStream();
4797 Reference< XInputStream > xInputStream(
4798 aDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM], UNO_QUERY);
4800 if (xInputStream.is())
4802 Sequence< sal_Int8 > aData;
4803 sal_Int32 nLen = HWPIDLen;
4804 if (
4805 nLen == xInputStream->readBytes(aData, nLen) &&
4806 detect_hwp_version(reinterpret_cast<const char*>(aData.getConstArray()))
4809 sTypeName = "writer_MIZI_Hwp_97";
4813 return sTypeName;
4816 Sequence< OUString> HwpImportFilter::getSupportedServiceNames()
4818 return { SERVICE_NAME1, SERVICE_NAME2 };
4823 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
4824 hwpfilter_HwpImportFilter_get_implementation(
4825 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
4827 return cppu::acquire(new HwpImportFilter(context));
4831 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */