Bump version to 24.04.3.4
[LibreOffice.git] / hwpfilter / source / hwpreader.cxx
blob972ebcdcd9d5e8cda6d7095f2a83af993aad341c
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 <unotools/configmgr.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("office:class", sXML_CDATA, "text");
124 mxList->addAttribute("office:version", sXML_CDATA, "0.9");
126 mxList->addAttribute("xmlns:office", "CDATA", "http://openoffice.org/2000/office");
127 mxList->addAttribute("xmlns:style", "CDATA", "http://openoffice.org/2000/style");
128 mxList->addAttribute("xmlns:text", "CDATA", "http://openoffice.org/2000/text");
129 mxList->addAttribute("xmlns:table", "CDATA", "http://openoffice.org/2000/table");
130 mxList->addAttribute("xmlns:draw", "CDATA", "http://openoffice.org/2000/drawing");
131 mxList->addAttribute("xmlns:fo", "CDATA", "http://www.w3.org/1999/XSL/Format");
132 mxList->addAttribute("xmlns:xlink", "CDATA", "http://www.w3.org/1999/xlink");
133 mxList->addAttribute("xmlns:dc", "CDATA", "http://purl.org/dc/elements/1.1/");
134 mxList->addAttribute("xmlns:meta", "CDATA", "http://openoffice.org/2000/meta");
135 mxList->addAttribute("xmlns:number", "CDATA", "http://openoffice.org/2000/datastyle");
136 mxList->addAttribute("xmlns:svg", "CDATA", "http://www.w3.org/2000/svg");
137 mxList->addAttribute("xmlns:chart", "CDATA", "http://openoffice.org/2000/chart");
138 mxList->addAttribute("xmlns:dr3d", "CDATA", "http://openoffice.org/2000/dr3d");
139 mxList->addAttribute("xmlns:math", "CDATA", "http://www.w3.org/1998/Math/MathML");
140 mxList->addAttribute("xmlns:form", "CDATA", "http://openoffice.org/2000/form");
141 mxList->addAttribute("xmlns:script", "CDATA", "http://openoffice.org/2000/script");
143 startEl("office:document");
144 mxList->clear();
146 makeMeta();
147 makeStyles();
148 makeAutoStyles();
149 makeMasterStyles();
150 makeBody();
152 endEl("office:document");
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("office:body");
190 makeTextDecls();
191 HWPPara *hwppara = hwpfile.GetFirstPara();
192 d->bInBody = true;
193 parsePara(hwppara);
194 endEl("office:body");
195 d->bInBody = false;
200 * make text decls
202 void HwpReader::makeTextDecls()
204 startEl("text:sequence-decls");
205 mxList->addAttribute("text:display-outline-level", sXML_CDATA, "0");
206 mxList->addAttribute("text:name", sXML_CDATA, "Illustration");
207 startEl("text:sequence-decl");
208 mxList->clear();
209 endEl("text:sequence-decl");
210 mxList->addAttribute("text:display-outline-level", sXML_CDATA, "0");
211 mxList->addAttribute("text:name", sXML_CDATA, "Table");
212 startEl("text:sequence-decl");
213 mxList->clear();
214 endEl("text:sequence-decl");
215 mxList->addAttribute("text:display-outline-level", sXML_CDATA, "0");
216 mxList->addAttribute("text:name", sXML_CDATA, "Text");
217 startEl("text:sequence-decl");
218 mxList->clear();
219 endEl("text:sequence-decl");
220 mxList->addAttribute("text:display-outline-level", sXML_CDATA, "0");
221 mxList->addAttribute("text:name", sXML_CDATA, "Drawing");
222 startEl("text:sequence-decl");
223 mxList->clear();
224 endEl("text:sequence-decl");
225 endEl("text:sequence-decls");
230 * make office:meta
231 * Completed
233 void HwpReader::makeMeta()
235 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
237 startEl("office:meta");
239 if (hwpinfo.summary.title[0])
241 startEl("dc:title");
242 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.title)));
243 endEl("dc:title");
246 if (hwpinfo.summary.subject[0])
248 startEl("dc:subject");
249 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.subject)));
250 endEl("dc:subject");
253 if (hwpinfo.summary.author[0])
255 startEl("meta:initial-creator");
256 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.author)));
257 endEl("meta:initial-creator");
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("meta:creation-date");
320 chars( OUString::createFromAscii(d->buf));
321 endEl("meta:creation-date");
324 if (hwpinfo.summary.keyword[0][0] || hwpinfo.summary.etc[0][0])
326 startEl("meta:keywords");
327 if (hwpinfo.summary.keyword[0][0])
329 startEl("meta:keyword");
330 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.keyword[0])));
331 endEl("meta:keyword");
333 if (hwpinfo.summary.keyword[1][0])
335 startEl("meta:keyword");
336 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.keyword[1])));
337 endEl("meta:keyword");
339 if (hwpinfo.summary.etc[0][0])
341 startEl("meta:keyword");
342 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.etc[0])));
343 endEl("meta:keyword");
345 if (hwpinfo.summary.etc[1][0])
347 startEl("meta:keyword");
348 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.etc[1])));
349 endEl("meta:keyword");
351 if (hwpinfo.summary.etc[2][0])
353 startEl("meta:keyword");
354 chars(hstr2OUString(reinterpret_cast<hchar *>(hwpinfo.summary.etc[2])));
355 endEl("meta:keyword");
357 endEl("meta:keywords");
359 endEl("office:meta");
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( "draw:name", sXML_CDATA, "LineType" + OUString::number(hdo->index));
414 mxList->addAttribute( "draw:style", sXML_CDATA, "round");
415 mxList->addAttribute( "draw:dots1", sXML_CDATA, "1");
416 mxList->addAttribute( "draw:dots1-length", sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots1 * WTMM(prop->line_width) ) + "cm");
417 if( prop->line_pstyle == 3 )
419 mxList->addAttribute( "draw:dots2", sXML_CDATA, "1");
420 mxList->addAttribute( "draw:dots2-length", sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width) ) + "cm");
422 else if( prop->line_pstyle == 4 )
424 mxList->addAttribute( "draw:dots2", sXML_CDATA, "2");
425 mxList->addAttribute( "draw:dots2-length", sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width)) + "cm");
427 mxList->addAttribute( "draw:distance", sXML_CDATA, OUString::number( LineStyle[prop->line_pstyle].distance * WTMM(prop->line_width)) + "cm");
428 startEl("draw:stroke-dash");
429 mxList->clear();
430 endEl("draw:stroke-dash");
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("draw:name", sXML_CDATA,
442 OUString::createFromAscii(ArrowShape[prop->line_tstyle].name));
443 if( prop->line_tstyle == 1 )
445 mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 20 30");
446 mxList->addAttribute("svg:d", sXML_CDATA, "m10 0-10 30h20z");
448 else if( prop->line_tstyle == 2 )
450 mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 1122 2243");
451 mxList->addAttribute("svg:d", sXML_CDATA, "m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z");
453 else if( prop->line_tstyle == 3 )
455 mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 30 30");
456 mxList->addAttribute("svg:d", sXML_CDATA, "m0 0h30v30h-30z");
458 startEl("draw:marker");
459 mxList->clear();
460 endEl("draw:marker");
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("draw:name", sXML_CDATA,
468 OUString::createFromAscii(ArrowShape[prop->line_hstyle].name));
469 if( prop->line_hstyle == 1 )
471 mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 20 30");
472 mxList->addAttribute("svg:d", sXML_CDATA, "m10 0-10 30h20z");
474 else if( prop->line_hstyle == 2 )
476 mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 1122 2243");
477 mxList->addAttribute("svg:d", sXML_CDATA, "m0 2108v17 17l12 42 30 34 38 21 43 4 29-8 30-21 25-26 13-34 343-1532 339 1520 13 42 29 34 39 21 42 4 42-12 34-30 21-42v-39-12l-4 4-440-1998-9-42-25-39-38-25-43-8-42 8-38 25-26 39-8 42z");
479 else if( prop->line_hstyle == 3 )
481 mxList->addAttribute("svg:viewBox", sXML_CDATA, "0 0 20 20");
482 mxList->addAttribute("svg:d", sXML_CDATA, "m0 0h20v20h-20z");
484 startEl("draw:marker");
485 mxList->clear();
486 endEl("draw:marker");
490 if( hdo->type != HWPDO_LINE )
492 if( prop->flag >> 18 & 0x01 )
494 mxList->addAttribute( "draw:name", 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( "xlink:href", sXML_CDATA,
502 hstr2OUString(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(prop->szPatternFile).c_str())).c_str()));
503 mxList->addAttribute( "xlink:type", sXML_CDATA, "simple");
504 mxList->addAttribute( "xlink:show", sXML_CDATA, "embed");
505 mxList->addAttribute( "xlink:actuate", sXML_CDATA, "onLoad");
508 startEl("draw:fill-image");
509 mxList->clear();
510 if (emp)
512 startEl("office:binary-data");
513 chars(base64_encode_string(emp->data.data(), emp->size));
514 endEl("office:binary-data");
516 endEl("draw:fill-image");
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( "draw:name", sXML_CDATA, "Grad" + OUString::number(hdo->index));
522 switch( prop->gstyle )
524 case 1 :
525 if( prop->center_y == 50 )
526 mxList->addAttribute( "draw:style", sXML_CDATA, "axial");
527 else
528 mxList->addAttribute( "draw:style", sXML_CDATA, "linear");
529 break;
530 case 2:
531 case 3:
532 mxList->addAttribute( "draw:style", sXML_CDATA, "radial");
533 break;
534 case 4:
535 mxList->addAttribute( "draw:style", sXML_CDATA, "square");
536 break;
537 default:
538 mxList->addAttribute( "draw:style", sXML_CDATA, "linear");
539 break;
541 mxList->addAttribute( "draw:cx", sXML_CDATA, OUString::number(prop->center_x) + "%");
542 mxList->addAttribute( "draw:cy", 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( "draw:start-color", sXML_CDATA, rgb2str( prop->tocolor ));
564 mxList->addAttribute( "draw:end-color", sXML_CDATA, rgb2str( prop->fromcolor ));
566 else
568 mxList->addAttribute( "draw:start-color", sXML_CDATA, rgb2str( prop->fromcolor ));
569 mxList->addAttribute( "draw:end-color", sXML_CDATA, rgb2str( prop->tocolor ));
572 else
574 mxList->addAttribute( "draw:start-color", sXML_CDATA,rgb2str( prop->tocolor ));
575 mxList->addAttribute( "draw:end-color", 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( "draw:angle", sXML_CDATA, OUString::number(angle));
583 startEl("draw:gradient");
584 mxList->clear();
585 endEl("draw:gradient");
587 /* hatch */
588 else if( prop->pattern_type >> 24 & 0x01 )
590 int type = prop->pattern_type & 0xffffff;
591 mxList->addAttribute( "draw:name", sXML_CDATA, "Hatch" + OUString::number(hdo->index));
592 if( type < 4 )
593 mxList->addAttribute( "draw:style", sXML_CDATA, "single" );
594 else
595 mxList->addAttribute( "draw:style", sXML_CDATA, "double" );
596 mxList->addAttribute( "draw:color", sXML_CDATA, rgb2str( static_cast<int32_t>(prop->pattern_color) ));
597 mxList->addAttribute( "draw:distance", sXML_CDATA, "0.12cm");
598 switch( type )
600 case 0 :
601 case 4 :
602 mxList->addAttribute( "draw:rotation", sXML_CDATA, "0");
603 break;
604 case 1 :
605 mxList->addAttribute( "draw:rotation", sXML_CDATA, "900");
606 break;
607 case 2 :
608 mxList->addAttribute( "draw:rotation", sXML_CDATA, "1350");
609 break;
610 case 3 :
611 case 5 :
612 mxList->addAttribute( "draw:rotation", sXML_CDATA, "450");
613 break;
615 startEl("draw:hatch");
616 mxList->clear();
617 endEl("draw:hatch");
620 hdo = hdo->next.get();
625 void HwpReader::makeStyles()
627 HWPStyle& hwpstyle = hwpfile.GetHWPStyle();
629 startEl("office:styles");
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("style:name", sXML_CDATA, "Standard");
641 mxList->addAttribute("style:family", sXML_CDATA, "paragraph");
642 mxList->addAttribute("style:class", sXML_CDATA, "text");
643 startEl("style:style");
644 mxList->clear();
646 mxList->addAttribute("fo:line-height", sXML_CDATA, "160%");
647 mxList->addAttribute("fo:text-align", sXML_CDATA, "justify");
648 startEl("style:properties");
649 mxList->clear();
650 startEl("style:tab-stops");
652 for( i = 1 ; i < 40 ; i++)
654 mxList->addAttribute("style:position", sXML_CDATA,
655 OUString::number( WTI(1000 * i)) + "inch");
656 startEl("style:tab-stop");
657 mxList->clear();
658 endEl("style:tab-stop");
660 endEl("style:tab-stops");
661 endEl("style:properties");
663 endEl("style:style");
665 for (int ii = 0; ii < hwpstyle.Num(); ii++)
667 unsigned char *stylename = reinterpret_cast<unsigned char *>(hwpstyle.GetName(ii));
668 mxList->addAttribute("style:name", sXML_CDATA, hstr2OUString(kstr2hstr(stylename).c_str()));
669 mxList->addAttribute("style:family", sXML_CDATA, "paragraph");
670 mxList->addAttribute("style:parent-style-name", sXML_CDATA, "Standard");
672 startEl("style:style");
674 mxList->clear();
676 parseCharShape(hwpstyle.GetCharShape(ii));
677 parseParaShape(hwpstyle.GetParaShape(ii));
679 startEl("style:properties");
680 mxList->clear();
681 endEl("style:properties");
683 endEl("style:style");
687 mxList->addAttribute( "style:name", sXML_CDATA, "Header");
688 mxList->addAttribute( "style:family", sXML_CDATA, "paragraph");
689 mxList->addAttribute( "style:parent-style-name", sXML_CDATA, "Standard");
690 mxList->addAttribute( "style:class", sXML_CDATA, "extra");
691 startEl("style:style");
692 mxList->clear();
693 endEl("style:style");
697 mxList->addAttribute( "style:name", sXML_CDATA, "Footer");
698 mxList->addAttribute( "style:family", sXML_CDATA, "paragraph");
699 mxList->addAttribute( "style:parent-style-name", sXML_CDATA, "Standard");
700 mxList->addAttribute( "style:class", sXML_CDATA, "extra");
701 startEl("style:style");
702 mxList->clear();
704 endEl("style:style");
707 if( hwpfile.linenumber > 0)
709 mxList->addAttribute( "style:name", sXML_CDATA, "Horizontal Line");
710 mxList->addAttribute( "style:family", sXML_CDATA, "paragraph");
711 mxList->addAttribute( "style:parent-style-name", sXML_CDATA, "Standard");
712 mxList->addAttribute( "style:class", sXML_CDATA, "html");
713 startEl("style:style");
714 mxList->clear();
715 mxList->addAttribute( "fo:font-size", sXML_CDATA, "6pt");
716 mxList->addAttribute( "fo:margin-top", sXML_CDATA, "0cm");
717 mxList->addAttribute( "fo:margin-bottom", sXML_CDATA, "0cm");
718 mxList->addAttribute( "style:border-line-width-bottom", sXML_CDATA, "0.02cm 0.035cm 0.002cm");
719 mxList->addAttribute( "fo:padding", sXML_CDATA, "0cm");
720 mxList->addAttribute( "fo:border-bottom", sXML_CDATA, "0.039cm double #808080");
721 mxList->addAttribute( "text:number-lines", sXML_CDATA, "false");
722 mxList->addAttribute( "text:line-number", sXML_CDATA, "0");
723 mxList->addAttribute("fo:line-height", sXML_CDATA, "100%");
724 startEl("style:properties");
725 mxList->clear();
726 endEl("style:properties");
727 endEl("style:style");
730 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
732 mxList->addAttribute("text:num-suffix", sXML_CDATA, ")");
733 mxList->addAttribute("text:num-format", sXML_CDATA, "1");
734 if( hwpinfo.beginfnnum != 1)
735 mxList->addAttribute("text:offset", sXML_CDATA, OUString::number(hwpinfo.beginfnnum - 1));
736 startEl("text:footnotes-configuration");
737 mxList->clear();
738 endEl("text:footnotes-configuration");
740 endEl("office:styles");
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("office:automatic-styles");
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("style:name", sXML_CDATA, "PNPara" + OUString::number(i));
804 mxList->addAttribute("style:family", sXML_CDATA, "paragraph");
805 mxList->addAttribute("style:parent-style-name", sXML_CDATA, "Standard");
806 startEl("style:style");
807 mxList->clear();
808 if( i == 1 )
809 mxList->addAttribute("fo:text-align", sXML_CDATA, "start");
810 else if ( i == 2 )
811 mxList->addAttribute("fo:text-align", sXML_CDATA, "center");
812 else if ( i == 3 )
813 mxList->addAttribute("fo:text-align", sXML_CDATA, "end");
814 startEl("style:properties");
815 mxList->clear();
816 endEl("style:properties");
817 endEl("style:style");
819 mxList->addAttribute("style:name", sXML_CDATA, "PNBox" + OUString::number(i));
820 mxList->addAttribute("style:family", sXML_CDATA, "graphics");
821 startEl("style:style");
822 mxList->clear();
824 mxList->addAttribute("fo:margin-top", sXML_CDATA, "0cm");
825 mxList->addAttribute("fo:margin-bottom", sXML_CDATA, "0cm");
826 mxList->addAttribute("style:wrap", sXML_CDATA, "run-through");
827 mxList->addAttribute("style:vertical-pos", sXML_CDATA, "from-top");
828 mxList->addAttribute("style:vertical-rel", sXML_CDATA, "paragraph");
830 if( i == 1 )
831 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "left");
832 else if ( i == 2 )
833 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "center");
834 else if ( i == 3 )
835 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "right");
836 mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
837 mxList->addAttribute("fo:padding", sXML_CDATA, "0cm");
838 mxList->addAttribute("stylefamily", sXML_CDATA, "graphics");
839 startEl("style:properties");
840 mxList->clear();
841 endEl("style:properties");
842 endEl("style:style");
845 for (i = 0; i < hwpfile.getDateFormatCount(); i++)
846 makeDateFormat(hwpfile.getDateCode(i));
848 makePageStyle();
850 endEl("office:automatic-styles");
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("office:master-styles");
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 && utl::ConfigManager::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("style:name", sXML_CDATA, "Standard");
971 else
972 mxList->addAttribute("style:name", sXML_CDATA, "p" + OUString::number(i));
973 mxList->addAttribute("style:page-master-name", sXML_CDATA,
974 "pm" + OUString::number(hwpfile.GetPageMasterNum(i)));
975 if( i < nMax )
976 mxList->addAttribute("style:next-style-name", sXML_CDATA, "p" + OUString::number(i + 1));
977 mxList->addAttribute("draw:style-name", sXML_CDATA, "master" + OUString::number(i));
978 startEl("style:master-page");
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("style:header");
1030 mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
1031 startEl("text:p");
1032 mxList->clear();
1033 endEl("text:p");
1034 endEl("style:header");
1036 startEl("style:footer");
1037 mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
1038 startEl("text:p");
1039 mxList->clear();
1040 endEl("text:p");
1041 endEl("style:footer");
1043 endEl("style:master-page");
1045 continue;
1047 // header
1048 if( pPage->header )
1050 startEl("style:header");
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("style:header");
1062 if( pPage->header_even )
1064 startEl("style:header");
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("style:header");
1079 /* Will be the default. */
1080 else if (pPage->header_odd)
1082 startEl("style:header");
1083 mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
1084 startEl("text:p");
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("text:p");
1096 endEl("style:header");
1098 if( pPage->header_odd )
1100 startEl("style:header-left");
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("style:header-left");
1115 /* Will be the default. */
1116 else if (pPage->header_even)
1118 startEl("style:header-left");
1119 mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
1120 startEl("text:p");
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("text:p");
1132 endEl("style:header-left");
1134 if( !pPage->header && !pPage->header_even && !pPage->header_odd )
1136 startEl("style:header");
1137 mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
1138 startEl("text:p");
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("text:p");
1148 endEl("style:header");
1150 // footer
1151 if( pPage->footer )
1153 startEl("style:footer");
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("style:footer");
1166 if( pPage->footer_even )
1168 startEl("style:footer");
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("style:footer");
1183 /* Will be the default. */
1184 else if (pPage->footer_odd)
1186 startEl("style:footer");
1187 mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
1188 startEl("text:p");
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("text:p");
1200 endEl("style:footer");
1202 if( pPage->footer_odd )
1204 startEl("style:footer-left");
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("style:footer-left");
1219 /* Will be the default. */
1220 else if (pPage->footer_even)
1222 startEl("style:footer-left");
1223 mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
1224 startEl("text:p");
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("text:p");
1236 endEl("style:footer-left");
1238 if( !pPage->footer && !pPage->footer_even && !pPage->footer_odd )
1240 startEl("style:footer");
1241 mxList->addAttribute("text:style-name", sXML_CDATA, "Standard");
1242 startEl("text:p");
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("text:p");
1252 endEl("style:footer");
1255 endEl("style:master-page");
1257 endEl("office:master-styles");
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("fo:font-size", sXML_CDATA, OUString::number(cshape->size / 25) + "pt");
1273 mxList->addAttribute("style:font-size-asian", 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("fo:font-family", sXML_CDATA,
1281 OUString(d->buf, size, RTL_TEXTENCODING_EUC_KR));
1282 mxList->addAttribute("style:font-family-asian", sXML_CDATA,
1283 OUString(d->buf, size, RTL_TEXTENCODING_EUC_KR));
1285 mxList->addAttribute("style:text-scale", 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("fo:letter-spacing", sXML_CDATA,
1293 OUString::number(sspace) + "pt");
1295 if (cshape->color[1] != 0)
1296 mxList->addAttribute("fo:color", sXML_CDATA,
1297 hcolor2str(cshape->color[1], 100, true));
1298 if (cshape->shade != 0)
1299 mxList->addAttribute("style:text-background-color", sXML_CDATA,
1300 hcolor2str(cshape->color[0], cshape->shade));
1301 if (cshape->attr & 0x01)
1303 mxList->addAttribute("fo:font-style", sXML_CDATA, "italic");
1304 mxList->addAttribute("style:font-style-asian", sXML_CDATA, "italic");
1306 else{
1307 mxList->addAttribute("fo:font-style", sXML_CDATA, "normal");
1308 mxList->addAttribute("style:font-style-asian", sXML_CDATA, "normal");
1310 if (cshape->attr >> 1 & 0x01)
1312 mxList->addAttribute("fo:font-weight", sXML_CDATA, "bold");
1313 mxList->addAttribute("style:font-weight-asian", sXML_CDATA, "bold");
1315 else{
1316 mxList->addAttribute("fo:font-weight", sXML_CDATA, "normal");
1317 mxList->addAttribute("style:font-weight-asian", sXML_CDATA, "normal");
1319 if (cshape->attr >> 2 & 0x01)
1320 mxList->addAttribute("style:text-underline", sXML_CDATA, "single");
1321 if (cshape->attr >> 3 & 0x01)
1322 mxList->addAttribute("style:text-outline", sXML_CDATA, "true");
1323 if (cshape->attr >> 4 & 0x01)
1324 mxList->addAttribute("fo:text-shadow", sXML_CDATA, "1pt 1pt");
1325 if (cshape->attr >> 5 & 0x01)
1326 mxList->addAttribute("style:text-position", sXML_CDATA, "super 58%");
1327 if (cshape->attr >> 6 & 0x01)
1328 mxList->addAttribute("style:text-position", sXML_CDATA, "sub 58%");
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("fo:margin-left", sXML_CDATA, OUString::number
1345 (WTI(pshape->left_margin )) + "inch");
1346 if (pshape->right_margin != 0)
1347 mxList->addAttribute("fo:margin-right", sXML_CDATA, OUString::number
1348 (WTI(pshape->right_margin)) + "inch");
1349 if (pshape->pspacing_prev != 0)
1350 mxList->addAttribute("fo:margin-top", sXML_CDATA, OUString::number
1351 (WTI(pshape->pspacing_prev)) + "inch");
1352 if (pshape->pspacing_next != 0)
1353 mxList->addAttribute("fo:margin-bottom", sXML_CDATA, OUString::number
1354 (WTI(pshape->pspacing_next)) + "inch");
1355 if (pshape->indent != 0)
1356 mxList->addAttribute("fo:text-indent", sXML_CDATA, OUString::number
1357 (WTI(pshape->indent)) + "inch");
1358 if (pshape->lspacing != 0)
1359 mxList->addAttribute("fo:line-height", 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("fo:text-align", sXML_CDATA, OUString::createFromAscii(align));
1384 if (pshape->outline)
1385 mxList->addAttribute("fo:border", sXML_CDATA, "0.002cm solid #000000");
1386 if( pshape->shade > 0 )
1388 mxList->addAttribute("fo:background-color", sXML_CDATA,
1389 hcolor2str(0, pshape->shade));
1392 if( pshape->pagebreak & 0x02 || pshape->pagebreak & 0x04)
1393 mxList->addAttribute("fo:break-before", sXML_CDATA, "page");
1394 else if( pshape->pagebreak & 0x01 )
1395 mxList->addAttribute("fo:break-before", sXML_CDATA, "column");
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("style:name", sXML_CDATA, "P" + OUString::number(pshape->index));
1407 mxList->addAttribute("style:family", sXML_CDATA, "paragraph");
1408 startEl("style:style");
1409 mxList->clear();
1410 parseParaShape(pshape);
1411 if (pshape->cshape)
1412 parseCharShape(pshape->cshape.get());
1413 startEl("style:properties");
1414 mxList->clear();
1416 if( nscount )
1418 unsigned char tf = 0;
1419 startEl("style:tab-stops");
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("style:position", 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("style:type", sXML_CDATA, "right");
1439 break;
1440 case 2:
1441 mxList->addAttribute("style:type", sXML_CDATA, "center");
1442 break;
1443 case 3:
1444 mxList->addAttribute("style:type", sXML_CDATA, "char");
1445 mxList->addAttribute("style:char", sXML_CDATA, ".");
1446 break;
1449 if( pshape->tabs[i].dot_continue )
1451 tf = 1;
1452 mxList->addAttribute("style:leader-char", sXML_CDATA, ".");
1454 startEl("style:tab-stop");
1455 mxList->clear();
1456 endEl("style:tab-stop");
1458 if( (pshape->tabs[i].position != 1000 * i ) || tf )
1460 if( !--nscount ) break;
1463 endEl("style:tab-stops");
1465 endEl("style:properties");
1466 endEl("style:style");
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 && utl::ConfigManager::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("style:name", sXML_CDATA, "pm" + OUString::number(i + 1));
1487 startEl("style:page-master");
1488 mxList->clear();
1491 switch( hwpinfo.paper.paper_kind )
1493 case 3: // A4
1494 if( hwpinfo.paper.paper_direction )
1496 mxList->addAttribute("fo:page-height",sXML_CDATA, "210mm");
1497 mxList->addAttribute("fo:page-width",sXML_CDATA, "297mm");
1499 else
1501 mxList->addAttribute("fo:page-width",sXML_CDATA, "210mm");
1502 mxList->addAttribute("fo:page-height",sXML_CDATA, "297mm");
1504 break;
1505 case 4: // 80 column
1506 if( hwpinfo.paper.paper_direction )
1508 mxList->addAttribute("fo:page-height",sXML_CDATA, "8.5inch");
1509 mxList->addAttribute("fo:page-width",sXML_CDATA, "11inch");
1511 else
1513 mxList->addAttribute("fo:page-width",sXML_CDATA, "8.5inch");
1514 mxList->addAttribute("fo:page-height",sXML_CDATA, "11inch");
1516 break;
1517 case 5: // B5
1518 if( hwpinfo.paper.paper_direction )
1520 mxList->addAttribute("fo:page-height",sXML_CDATA, "176mm");
1521 mxList->addAttribute("fo:page-width",sXML_CDATA, "250mm");
1523 else
1525 mxList->addAttribute("fo:page-width",sXML_CDATA, "176mm");
1526 mxList->addAttribute("fo:page-height",sXML_CDATA, "250mm");
1528 break;
1529 case 6: // B4
1530 if( hwpinfo.paper.paper_direction )
1532 mxList->addAttribute("fo:page-height",sXML_CDATA, "250mm");
1533 mxList->addAttribute("fo:page-width",sXML_CDATA, "353mm");
1535 else
1537 mxList->addAttribute("fo:page-width",sXML_CDATA, "250mm");
1538 mxList->addAttribute("fo:page-height",sXML_CDATA, "353mm");
1540 break;
1541 case 7:
1542 if( hwpinfo.paper.paper_direction )
1544 mxList->addAttribute("fo:page-height",sXML_CDATA, "8.5inch");
1545 mxList->addAttribute("fo:page-width",sXML_CDATA, "14inch");
1547 else
1549 mxList->addAttribute("fo:page-width",sXML_CDATA, "8.5inch");
1550 mxList->addAttribute("fo:page-height",sXML_CDATA, "14inch");
1552 break;
1553 case 8:
1554 if( hwpinfo.paper.paper_direction )
1556 mxList->addAttribute("fo:page-height",sXML_CDATA, "297mm");
1557 mxList->addAttribute("fo:page-width",sXML_CDATA, "420mm");
1559 else
1561 mxList->addAttribute("fo:page-width",sXML_CDATA, "297mm");
1562 mxList->addAttribute("fo:page-height",sXML_CDATA, "420mm");
1564 break;
1565 case 0:
1566 case 1:
1567 case 2:
1568 default:
1569 if( hwpinfo.paper.paper_direction )
1571 mxList->addAttribute("fo:page-width",sXML_CDATA,
1572 OUString::number(WTI(hwpinfo.paper.paper_height)) + "inch");
1573 mxList->addAttribute("fo:page-height",sXML_CDATA,
1574 OUString::number(WTI(hwpinfo.paper.paper_width)) + "inch");
1576 else
1578 mxList->addAttribute("fo:page-width",sXML_CDATA,
1579 OUString::number(WTI(hwpinfo.paper.paper_width)) + "inch");
1580 mxList->addAttribute("fo:page-height",sXML_CDATA,
1581 OUString::number(WTI(hwpinfo.paper.paper_height)) + "inch");
1583 break;
1587 mxList->addAttribute("style:print-orientation",sXML_CDATA,
1588 OUString::createFromAscii(hwpinfo.paper.paper_direction ? "landscape" : "portrait"));
1589 if( hwpinfo.beginpagenum != 1)
1590 mxList->addAttribute("style:first-page-number",sXML_CDATA, OUString::number(hwpinfo.beginpagenum));
1592 if( hwpinfo.borderline ){
1593 mxList->addAttribute("fo:margin-left",sXML_CDATA,
1594 OUString::number(WTI(hwpinfo.paper.left_margin - hwpinfo.bordermargin[0] + hwpinfo.paper.gutter_length)) + "inch");
1595 mxList->addAttribute("fo:margin-right",sXML_CDATA,
1596 OUString::number(WTI(hwpinfo.paper.right_margin - hwpinfo.bordermargin[1])) + "inch");
1597 mxList->addAttribute("fo:margin-top",sXML_CDATA,
1598 OUString::number(WTI(hwpinfo.paper.top_margin - hwpinfo.bordermargin[2])) + "inch");
1599 mxList->addAttribute("fo:margin-bottom",sXML_CDATA,
1600 OUString::number(WTI(hwpinfo.paper.bottom_margin - hwpinfo.bordermargin[3])) + "inch");
1602 else{
1603 mxList->addAttribute("fo:margin-left",sXML_CDATA,
1604 OUString::number(WTI(hwpinfo.paper.left_margin + hwpinfo.paper.gutter_length)) + "inch");
1605 mxList->addAttribute("fo:margin-right",sXML_CDATA,
1606 OUString::number(WTI(hwpinfo.paper.right_margin)) + "inch");
1607 mxList->addAttribute("fo:margin-top",sXML_CDATA,
1608 OUString::number(WTI(hwpinfo.paper.top_margin)) + "inch");
1609 mxList->addAttribute("fo:margin-bottom",sXML_CDATA,
1610 OUString::number(WTI(hwpinfo.paper.bottom_margin)) + "inch");
1613 switch( hwpinfo.borderline )
1615 case 1:
1616 mxList->addAttribute("fo:border", sXML_CDATA,"0.002cm solid #000000");
1617 break;
1618 case 3:
1619 mxList->addAttribute("fo:border", sXML_CDATA,"0.002cm dotted #000000");
1620 break;
1621 case 2:
1622 mxList->addAttribute("fo:border", sXML_CDATA,"0.035cm solid #000000");
1623 break;
1624 case 4:
1625 mxList->addAttribute("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1626 mxList->addAttribute("fo:border", sXML_CDATA,"0.039cm double #000000");
1627 break;
1630 mxList->addAttribute("fo:padding-left", sXML_CDATA,
1631 OUString::number(WTI(hwpinfo.bordermargin[0])) + "inch");
1632 mxList->addAttribute("fo:padding-right", sXML_CDATA,
1633 OUString::number(WTI(hwpinfo.bordermargin[1])) + "inch");
1634 mxList->addAttribute("fo:padding-top", sXML_CDATA,
1635 OUString::number(WTI(hwpinfo.bordermargin[2])) + "inch");
1636 mxList->addAttribute("fo:padding-bottom", 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("fo:background-color", sXML_CDATA,
1645 rgb2str(hwpinfo.back_info.color[0],
1646 hwpinfo.back_info.color[1],
1647 hwpinfo.back_info.color[2]));
1651 startEl("style:properties");
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("xlink:href", sXML_CDATA,
1663 hstr2OUString(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(hwpinfo.back_info.filename).c_str())).c_str()));
1664 #endif
1665 mxList->addAttribute("xlink:type", sXML_CDATA, "simple");
1666 mxList->addAttribute("xlink:actuate", sXML_CDATA, "onLoad");
1668 if( hwpinfo.back_info.flag >= 2)
1669 mxList->addAttribute("style:repeat", sXML_CDATA, "stretch");
1670 else if( hwpinfo.back_info.flag == 1 ){
1671 mxList->addAttribute("style:repeat", sXML_CDATA, "no-repeat");
1672 mxList->addAttribute("style:position", sXML_CDATA, "center");
1674 startEl("style:background-image");
1676 if( hwpinfo.back_info.type == 2 ){
1677 startEl("office:binary-data");
1678 mxList->clear();
1679 chars(base64_encode_string(reinterpret_cast<unsigned char*>(hwpinfo.back_info.data.data()), hwpinfo.back_info.size));
1680 endEl("office:binary-data");
1682 endEl("style:background-image");
1685 makeColumns( hwpfile.GetColumnDef(i) );
1687 endEl("style:properties");
1689 /* header style */
1690 startEl("style:header-style");
1691 mxList->addAttribute("svg:height", sXML_CDATA,
1692 OUString::number(WTI(hwpinfo.paper.header_length)) + "inch");
1693 mxList->addAttribute("fo:margin-bottom", sXML_CDATA, "0mm");
1695 startEl("style:properties");
1696 mxList->clear();
1697 endEl("style:properties");
1698 endEl("style:header-style");
1700 /* footer style */
1701 startEl("style:footer-style");
1702 mxList->addAttribute("svg:height", sXML_CDATA,
1703 OUString::number(WTI(hwpinfo.paper.footer_length)) + "inch");
1704 mxList->addAttribute("fo:margin-top", sXML_CDATA, "0mm");
1705 startEl("style:properties");
1706 mxList->clear();
1707 endEl("style:properties");
1708 endEl("style:footer-style");
1710 /* Footnote style */
1711 startEl("style:page-layout-properties");
1713 mxList->addAttribute("style:distance-before-sep", sXML_CDATA,
1714 OUString::number(WTI(hwpinfo.splinetext)) + "inch");
1715 mxList->addAttribute("style:distance-after-sep", sXML_CDATA,
1716 OUString::number(WTI(hwpinfo.splinefn)) + "inch");
1717 startEl("style:properties");
1718 mxList->clear();
1719 endEl("style:properties");
1720 if ( hwpinfo.fnlinetype == 2 )
1721 mxList->addAttribute("style:width", sXML_CDATA, "15cm");
1722 else if ( hwpinfo.fnlinetype == 1)
1723 mxList->addAttribute("style:width", sXML_CDATA, "2cm");
1724 else if ( hwpinfo.fnlinetype == 3)
1725 mxList->addAttribute("style:width", sXML_CDATA, "0cm");
1726 else
1727 mxList->addAttribute("style:width", sXML_CDATA, "5cm");
1729 startEl("style:footnote-sep");
1730 mxList->clear();
1731 endEl("style:footnote-sep");
1733 endEl("style:page-layout-properties");
1735 endEl("style:page-master");
1739 void HwpReader::makeColumns(ColumnDef const *coldef)
1741 if( !coldef ) return;
1742 mxList->addAttribute("fo:column-count", sXML_CDATA, OUString::number(coldef->ncols));
1743 startEl("style:columns");
1744 mxList->clear();
1745 if( coldef->separator != 0 )
1747 switch( coldef->separator )
1749 case 1: /* thin line */
1750 mxList->addAttribute("style:width", sXML_CDATA, "0.02mm");
1751 [[fallthrough]];
1752 case 3: /* dotted line */
1753 mxList->addAttribute("style:style", sXML_CDATA, "dotted");
1754 mxList->addAttribute("style:width", sXML_CDATA, "0.02mm");
1755 break;
1756 case 2: /* thick line */
1757 case 4: /* double line */
1758 mxList->addAttribute("style:width", sXML_CDATA, "0.35mm");
1759 break;
1760 case 0: /* None */
1761 default:
1762 mxList->addAttribute("style:style", sXML_CDATA, "none");
1763 break;
1765 startEl("style:column-sep");
1766 mxList->clear();
1767 endEl("style:column-sep");
1769 double spacing = WTI(coldef->spacing)/ 2. ;
1770 for(int ii = 0 ; ii < coldef->ncols ; ii++)
1772 if( ii == 0 )
1773 mxList->addAttribute("fo:margin-left", sXML_CDATA, "0mm");
1774 else
1775 mxList->addAttribute("fo:margin-left", sXML_CDATA,
1776 OUString::number( spacing) + "inch");
1777 if( ii == ( coldef->ncols -1) )
1778 mxList->addAttribute("fo:margin-right", sXML_CDATA,"0mm");
1779 else
1780 mxList->addAttribute("fo:margin-right", sXML_CDATA,
1781 OUString::number( spacing) + "inch");
1782 startEl("style:column");
1783 mxList->clear();
1784 endEl("style:column");
1786 endEl("style:columns");
1789 void HwpReader::makeTStyle(CharShape const * cshape)
1791 mxList->addAttribute("style:name", sXML_CDATA, "T" + OUString::number(cshape->index));
1792 mxList->addAttribute("style:family", sXML_CDATA, "text");
1793 startEl("style:style");
1794 mxList->clear();
1795 parseCharShape(cshape);
1796 startEl("style:properties");
1797 mxList->clear();
1798 endEl("style:properties");
1799 endEl("style:style");
1803 void HwpReader::makeTableStyle(Table *tbl)
1805 // table
1806 TxtBox *hbox = tbl->box;
1808 mxList->addAttribute("style:name", sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum));
1809 mxList->addAttribute("style:family", sXML_CDATA,"table");
1810 startEl("style:style");
1811 mxList->clear();
1812 mxList->addAttribute("style:width", sXML_CDATA,
1813 OUString::number(WTMM(hbox->box_xs)) + "mm");
1814 mxList->addAttribute("table:align", sXML_CDATA,"left");
1815 mxList->addAttribute("fo:keep-with-next", sXML_CDATA,"false");
1816 startEl("style:properties");
1817 mxList->clear();
1818 endEl("style:properties");
1819 endEl("style:style");
1821 // column
1822 for (size_t i = 0 ; i < tbl->columns.nCount -1 ; i++)
1824 mxList->addAttribute(
1825 "style:name", sXML_CDATA,
1826 "Table" + OUString::number(hbox->style.boxnum) + "."
1827 + OUStringChar(static_cast<char>('A'+i)));
1828 mxList->addAttribute("style:family", sXML_CDATA,"table-column");
1829 startEl("style:style");
1830 mxList->clear();
1831 mxList->addAttribute("style:column-width", sXML_CDATA,
1832 OUString::number(WTMM(tbl->columns.data[i+1] - tbl->columns.data[i])) + "mm");
1833 startEl("style:properties");
1834 mxList->clear();
1835 endEl("style:properties");
1836 endEl("style:style");
1839 // row
1840 for (size_t i = 0 ; i < tbl->rows.nCount -1 ; i++)
1842 mxList->addAttribute(
1843 "style:name", sXML_CDATA,
1844 "Table" + OUString::number(hbox->style.boxnum) + ".row" + OUString::number(i + 1));
1845 mxList->addAttribute("style:family", sXML_CDATA,"table-row");
1846 startEl("style:style");
1847 mxList->clear();
1848 mxList->addAttribute("style:row-height", sXML_CDATA,
1849 OUString::number(WTMM(tbl->rows.data[i+1] - tbl->rows.data[i])) + "mm");
1850 startEl("style:properties");
1851 mxList->clear();
1852 endEl("style:properties");
1853 endEl("style:style");
1856 // cell
1857 for (auto const& tcell : tbl->cells)
1859 mxList->addAttribute(
1860 "style:name", sXML_CDATA,
1861 "Table" + OUString::number(hbox->style.boxnum) + "."
1862 + OUStringChar(char('A'+ tcell->nColumnIndex))
1863 + OUString::number(tcell->nRowIndex +1));
1864 mxList->addAttribute("style:family", sXML_CDATA,"table-cell");
1865 startEl("style:style");
1866 mxList->clear();
1867 Cell *cl = tcell->pCell;
1868 if( cl->ver_align == 1 )
1869 mxList->addAttribute("fo:vertical-align", sXML_CDATA,"middle");
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("fo:border", sXML_CDATA,"0.002cm solid #000000");
1879 break;
1880 case 2: /* Bold lines */
1881 mxList->addAttribute("fo:border", sXML_CDATA,"0.035cm solid #000000");
1882 break;
1883 case 4: /* Double line */
1884 mxList->addAttribute("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1885 mxList->addAttribute("fo:border", sXML_CDATA,"0.039cm double #000000");
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("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
1896 break;
1897 case 2: /* Bold lines */
1898 mxList->addAttribute("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
1899 break;
1900 case 4: /* Double line */
1901 mxList->addAttribute("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1902 mxList->addAttribute("fo:border-left", sXML_CDATA,"0.039cm double #000000");
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("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
1910 break;
1911 case 2: /* Bold lines */
1912 mxList->addAttribute("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
1913 break;
1914 case 4: /* Double line */
1915 mxList->addAttribute("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1916 mxList->addAttribute("fo:border-right", sXML_CDATA,"0.039cm double #000000");
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("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
1924 break;
1925 case 2: /* Bold lines */
1926 mxList->addAttribute("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
1927 break;
1928 case 4: /* Double line */
1929 mxList->addAttribute("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1930 mxList->addAttribute("fo:border-top", sXML_CDATA,"0.039cm double #000000");
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("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
1938 break;
1939 case 2: /* Bold lines */
1940 mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
1941 break;
1942 case 4: /* Double line */
1943 mxList->addAttribute("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1944 mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
1945 break;
1948 if(cl->shade != 0)
1949 mxList->addAttribute("fo:background-color", sXML_CDATA,
1950 hcolor2str(sal::static_int_cast<uchar>(cl->color),
1951 sal::static_int_cast<uchar>(cl->shade)));
1953 startEl("style:properties");
1954 mxList->clear();
1955 endEl("style:properties");
1957 endEl("style:style");
1962 void HwpReader::makeDrawStyle( HWPDrawingObject * hdo, FBoxStyle * fstyle)
1964 while( hdo )
1966 mxList->addAttribute("style:name", sXML_CDATA, "Draw" + OUString::number(hdo->index));
1967 mxList->addAttribute("style:family", sXML_CDATA, "graphics");
1969 startEl("style:style");
1970 mxList->clear();
1972 switch (fstyle->txtflow)
1974 case 0:
1975 break;
1976 case 1:
1977 mxList->addAttribute("style:wrap", sXML_CDATA, "run-through");
1978 break;
1979 case 2:
1980 mxList->addAttribute("style:wrap", sXML_CDATA, "dynamic");
1981 break;
1983 tools::Long color;
1984 // invisible line
1985 if( hdo->property.line_color > 0xffffff )
1987 mxList->addAttribute("draw:stroke", sXML_CDATA, "none" );
1989 else
1992 if( hdo->property.line_pstyle == 0 )
1993 mxList->addAttribute("draw:stroke", sXML_CDATA, "solid" );
1994 else if( hdo->property.line_pstyle < 5 )
1996 mxList->addAttribute("draw:stroke", sXML_CDATA, "dash" );
1997 mxList->addAttribute("draw:stroke-dash", sXML_CDATA, "LineType" + OUString::number(hdo->index));
1999 mxList->addAttribute("svg:stroke-width", sXML_CDATA,
2000 OUString::number( WTMM(hdo->property.line_width)) + "mm");
2001 mxList->addAttribute("svg:stroke-color", 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("draw:marker-start", sXML_CDATA,
2013 OUString::createFromAscii(ArrowShape[hdo->property.line_tstyle].name) );
2014 if( hdo->property.line_width > 100 )
2015 mxList->addAttribute("draw:marker-start-width", sXML_CDATA,
2016 OUString::number( WTMM(hdo->property.line_width * 3)) + "mm");
2017 else if( hdo->property.line_width > 80 )
2018 mxList->addAttribute("draw:marker-start-width", sXML_CDATA,
2019 OUString::number( WTMM(hdo->property.line_width * 4)) + "mm");
2020 else if( hdo->property.line_width > 60 )
2021 mxList->addAttribute("draw:marker-start-width", sXML_CDATA,
2022 OUString::number( WTMM(hdo->property.line_width * 5)) + "mm");
2023 else if( hdo->property.line_width > 40 )
2024 mxList->addAttribute("draw:marker-start-width", sXML_CDATA,
2025 OUString::number( WTMM(hdo->property.line_width * 6)) + "mm");
2026 else
2027 mxList->addAttribute("draw:marker-start-width", sXML_CDATA,
2028 OUString::number( WTMM(hdo->property.line_width * 7)) + "mm");
2031 if( hdo->property.line_hstyle > 0 &&
2032 o3tl::make_unsigned(hdo->property.line_hstyle) < std::size(ArrowShape) )
2034 mxList->addAttribute("draw:marker-end", sXML_CDATA,
2035 OUString::createFromAscii(ArrowShape[hdo->property.line_hstyle].name) );
2036 if( hdo->property.line_width > 100 )
2037 mxList->addAttribute("draw:marker-end-width", sXML_CDATA,
2038 OUString::number( WTMM(hdo->property.line_width * 3)) + "mm");
2039 else if( hdo->property.line_width > 80 )
2040 mxList->addAttribute("draw:marker-end-width", sXML_CDATA,
2041 OUString::number( WTMM(hdo->property.line_width * 4)) + "mm");
2042 else if( hdo->property.line_width > 60 )
2043 mxList->addAttribute("draw:marker-end-width", sXML_CDATA,
2044 OUString::number( WTMM(hdo->property.line_width * 5)) + "mm");
2045 else if( hdo->property.line_width > 40 )
2046 mxList->addAttribute("draw:marker-end-width", sXML_CDATA,
2047 OUString::number( WTMM(hdo->property.line_width * 6)) + "mm");
2048 else
2049 mxList->addAttribute("draw:marker-end-width", sXML_CDATA,
2050 OUString::number( WTMM(hdo->property.line_width * 7)) + "mm");
2054 if(hdo->type != HWPDO_LINE )
2056 if( hdo->property.flag >> 19 & 0x01 )
2058 mxList->addAttribute( "draw:textarea-horizontal-align", sXML_CDATA, "center");
2061 color = hdo->property.fill_color;
2063 if( hdo->property.flag >> 18 & 0x01 ) // bitmap pattern
2065 mxList->addAttribute("draw:fill", sXML_CDATA, "bitmap");
2066 mxList->addAttribute("draw:fill-image-name", sXML_CDATA,
2067 "fillimage" + OUString::number(hdo->index));
2068 // bitmap resizing
2069 if( hdo->property.flag >> 3 & 0x01 )
2071 mxList->addAttribute("style:repeat", sXML_CDATA, "stretch");
2073 else
2075 mxList->addAttribute("style:repeat", sXML_CDATA, "repeat");
2076 mxList->addAttribute("draw:fill-image-ref-point", sXML_CDATA, "top-left");
2078 if( hdo->property.flag >> 20 & 0x01 )
2080 if( hdo->property.luminance > 0 )
2082 mxList->addAttribute("draw:transparency", sXML_CDATA,
2083 OUString::number(hdo->property.luminance) + "%");
2088 // Gradation
2089 else if( hdo->property.flag >> 16 & 0x01 )
2091 mxList->addAttribute("draw:fill", sXML_CDATA, "gradient");
2092 mxList->addAttribute("draw:fill-gradient-name", sXML_CDATA, "Grad" + OUString::number(hdo->index));
2093 mxList->addAttribute("draw:gradient-step-count", sXML_CDATA, OUString::number(hdo->property.nstep));
2096 // Hatching
2097 else if( hdo->property.pattern_type >> 24 & 0x01 )
2099 mxList->addAttribute("draw:fill", sXML_CDATA, "hatch");
2100 mxList->addAttribute("draw:fill-hatch-name", sXML_CDATA, "Hatch" + OUString::number(hdo->index));
2101 if( color < 0xffffff )
2103 mxList->addAttribute("draw:fill-color", sXML_CDATA,
2104 rgb2str(static_cast<int32_t>(color)));
2105 mxList->addAttribute("draw:fill-hatch-solid", sXML_CDATA, "true");
2108 else if( color <= 0xffffff )
2110 mxList->addAttribute("draw:fill", sXML_CDATA, "solid");
2111 mxList->addAttribute("draw:fill-color", sXML_CDATA,
2112 rgb2str(static_cast<int32_t>(color)));
2114 else
2115 mxList->addAttribute("draw:fill", sXML_CDATA, "none");
2118 if( fstyle->anchor_type == CHAR_ANCHOR )
2120 mxList->addAttribute("style:vertical-pos", sXML_CDATA, "top");
2121 mxList->addAttribute("style:vertical-rel", sXML_CDATA, "baseline");
2124 startEl("style:properties");
2125 mxList->clear();
2126 endEl("style:properties");
2127 endEl("style:style");
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("style:name", sXML_CDATA, "CapBox" + OUString::number(fstyle->boxnum));
2141 mxList->addAttribute("style:family", sXML_CDATA, "graphics");
2142 startEl("style:style");
2143 mxList->clear();
2144 mxList->addAttribute("fo:margin-left", sXML_CDATA, "0cm");
2145 mxList->addAttribute("fo:margin-right", sXML_CDATA, "0cm");
2146 mxList->addAttribute("fo:margin-top", sXML_CDATA, "0cm");
2147 mxList->addAttribute("fo:margin-bottom", sXML_CDATA, "0cm");
2148 mxList->addAttribute("fo:padding", sXML_CDATA, "0cm");
2149 switch (fstyle->txtflow)
2151 case 0:
2152 mxList->addAttribute("style:wrap", sXML_CDATA, "none");
2153 break;
2154 case 1:
2155 if( fstyle->boxtype == 'G' )
2156 mxList->addAttribute("style:run-through", sXML_CDATA, "background");
2157 mxList->addAttribute("style:wrap", sXML_CDATA, "run-through");
2158 break;
2159 case 2:
2160 mxList->addAttribute("style:wrap", sXML_CDATA, "dynamic");
2161 break;
2163 if (fstyle->anchor_type == CHAR_ANCHOR)
2165 mxList->addAttribute("style:vertical-pos", sXML_CDATA, "top");
2166 mxList->addAttribute("style:vertical-rel", sXML_CDATA, "baseline");
2167 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "center");
2168 mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
2170 else
2173 switch (-(fstyle->xpos))
2175 case 2:
2176 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "right");
2177 break;
2178 case 3:
2179 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "center");
2180 break;
2181 case 1:
2182 default:
2183 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "from-left");
2184 break;
2186 switch (-(fstyle->ypos))
2188 case 2:
2189 mxList->addAttribute("style:vertical-pos", sXML_CDATA, "bottom");
2190 break;
2191 case 3:
2192 mxList->addAttribute("style:vertical-pos", sXML_CDATA, "middle");
2193 break;
2194 case 1:
2195 default:
2196 mxList->addAttribute("style:vertical-pos", sXML_CDATA, "from-top");
2197 break;
2199 if ( fstyle->anchor_type == PARA_ANCHOR )
2201 mxList->addAttribute("style:vertical-rel", sXML_CDATA, "paragraph");
2202 mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
2204 else
2206 mxList->addAttribute("style:vertical-rel", sXML_CDATA, "page-content");
2207 mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "page-content");
2210 startEl("style:properties");
2211 mxList->clear();
2212 endEl("style:properties");
2213 endEl("style:style");
2214 if( fstyle->boxtype == 'G' )
2216 mxList->addAttribute("style:name", sXML_CDATA, "G" + OUString::number(fstyle->boxnum));
2218 else
2220 mxList->addAttribute("style:name", sXML_CDATA, "Txtbox" + OUString::number(fstyle->boxnum));
2223 mxList->addAttribute("style:family", sXML_CDATA, "graphics");
2224 startEl("style:style");
2225 mxList->clear();
2227 mxList->addAttribute("fo:margin-left", sXML_CDATA, "0cm");
2228 mxList->addAttribute("fo:margin-right", sXML_CDATA, "0cm");
2229 mxList->addAttribute("fo:margin-top", sXML_CDATA, "0cm");
2230 mxList->addAttribute("fo:margin-bottom", sXML_CDATA, "0cm");
2231 mxList->addAttribute("fo:padding", sXML_CDATA, "0cm");
2232 mxList->addAttribute("style:wrap", sXML_CDATA, "none");
2233 mxList->addAttribute("style:vertical-pos", sXML_CDATA, "from-top");
2234 mxList->addAttribute("style:vertical-rel", sXML_CDATA, "paragraph");
2235 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "from-left");
2236 mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
2237 if (fstyle->boxtype == 'G' && fstyle->cell)
2239 char *cell = static_cast<char *>(fstyle->cell);
2240 mxList->addAttribute("draw:luminance", sXML_CDATA, OUString::number(cell[0]) + "%");
2241 mxList->addAttribute("draw:contrast", sXML_CDATA, OUString::number(cell[1]) + "%");
2242 if( cell[2] == 0 )
2243 mxList->addAttribute("draw:color-mode", sXML_CDATA, "standard");
2244 else if( cell[2] == 1 )
2245 mxList->addAttribute("draw:color-mode", sXML_CDATA, "greyscale");
2246 else if( cell[2] == 2 )
2247 mxList->addAttribute("draw:color-mode", sXML_CDATA, "mono");
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("fo:padding", sXML_CDATA,"0mm");
2260 break;
2261 case 1: /* A thin solid line */
2262 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2263 mxList->addAttribute("fo:border", sXML_CDATA,"0.002cm solid #000000");
2264 break;
2265 case 2: /* Bold lines */
2266 mxList->addAttribute("fo:border", sXML_CDATA,"0.035cm solid #000000");
2267 break;
2268 case 4: /* Double line */
2269 mxList->addAttribute("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2270 mxList->addAttribute("fo:border", sXML_CDATA,"0.039cm double #000000");
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("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
2281 break;
2282 case 2: /* Bold lines */
2283 mxList->addAttribute("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
2284 break;
2285 case 4: /* Double line */
2286 mxList->addAttribute("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2287 mxList->addAttribute("fo:border-left", sXML_CDATA,"0.039cm double #000000");
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("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
2295 break;
2296 case 2: /* Bold lines */
2297 mxList->addAttribute("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
2298 break;
2299 case 4: /* Double line */
2300 mxList->addAttribute("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2301 mxList->addAttribute("fo:border-right", sXML_CDATA,"0.039cm double #000000");
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("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
2309 break;
2310 case 2: /* Bold lines */
2311 mxList->addAttribute("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
2312 break;
2313 case 4: /* Double line */
2314 mxList->addAttribute("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2315 mxList->addAttribute("fo:border-top", sXML_CDATA,"0.039cm double #000000");
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("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
2323 break;
2324 case 2: /* Bold lines */
2325 mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
2326 break;
2327 case 4: /* Double line */
2328 mxList->addAttribute("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2329 mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
2330 break;
2333 if(cell->shade != 0)
2334 mxList->addAttribute("fo:background-color", sXML_CDATA, hcolor2str(
2335 sal::static_int_cast<uchar>(cell->color),
2336 sal::static_int_cast<uchar>(cell->shade)));
2338 startEl("style:properties");
2339 mxList->clear();
2340 endEl("style:properties");
2341 endEl("style:style");
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("style:name", sXML_CDATA, "Txtbox" + OUString::number(fstyle->boxnum));
2364 mxList->addAttribute("style:family", sXML_CDATA, "graphics");
2365 break;
2366 case 'G' : // graphics
2367 mxList->addAttribute("style:name", sXML_CDATA, "G" + OUString::number(fstyle->boxnum));
2368 mxList->addAttribute("style:family", sXML_CDATA, "graphics");
2369 break;
2370 case 'L' : // line TODO : all
2371 mxList->addAttribute("style:name", sXML_CDATA, "L" + OUString::number(fstyle->boxnum));
2372 mxList->addAttribute( "style:family" , sXML_CDATA , "paragraph" );
2373 break;
2376 startEl("style:style");
2377 mxList->clear();
2379 if ( fstyle->boxtype == 'T')
2381 mxList->addAttribute("fo:padding", sXML_CDATA, "0cm");
2384 if( fstyle->boxtype != 'G' || fstyle->cap_len <= 0 )
2386 mxList->addAttribute("fo:margin-left", sXML_CDATA,
2387 OUString::number(WTMM(fstyle->margin[0][0]) ) + "mm");
2388 mxList->addAttribute("fo:margin-right", sXML_CDATA,
2389 OUString::number(WTMM(fstyle->margin[0][1])) + "mm");
2390 mxList->addAttribute("fo:margin-top", sXML_CDATA,
2391 OUString::number(WTMM(fstyle->margin[0][2])) + "mm");
2392 mxList->addAttribute("fo:margin-bottom", sXML_CDATA,
2393 OUString::number(WTMM(fstyle->margin[0][3])) + "mm");
2396 switch (fstyle->txtflow)
2398 case 0:
2399 mxList->addAttribute("style:wrap", sXML_CDATA, "none");
2400 break;
2401 case 1:
2402 if( fstyle->boxtype == 'G' || fstyle->boxtype == 'B' || fstyle->boxtype == 'O')
2403 mxList->addAttribute("style:run-through", sXML_CDATA, "background");
2404 mxList->addAttribute("style:wrap", sXML_CDATA, "run-through");
2405 break;
2406 case 2:
2407 mxList->addAttribute("style:wrap", sXML_CDATA, "dynamic");
2408 break;
2410 if (fstyle->anchor_type == CHAR_ANCHOR)
2412 mxList->addAttribute("style:vertical-pos", sXML_CDATA, "top");
2413 mxList->addAttribute("style:vertical-rel", sXML_CDATA, "baseline");
2414 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "center");
2415 mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
2417 else
2420 switch (-(fstyle->xpos))
2422 case 2:
2423 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "right");
2424 break;
2425 case 3:
2426 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "center");
2427 break;
2428 case 1:
2429 default:
2430 mxList->addAttribute("style:horizontal-pos", sXML_CDATA, "from-left");
2431 break;
2433 switch (-(fstyle->ypos))
2435 case 2:
2436 mxList->addAttribute("style:vertical-pos", sXML_CDATA, "bottom");
2437 break;
2438 case 3:
2439 mxList->addAttribute("style:vertical-pos", sXML_CDATA, "middle");
2440 break;
2441 case 1:
2442 default:
2443 mxList->addAttribute("style:vertical-pos", sXML_CDATA, "from-top");
2444 break;
2446 if ( fstyle->anchor_type == PARA_ANCHOR )
2448 mxList->addAttribute("style:vertical-rel", sXML_CDATA, "paragraph");
2449 mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "paragraph");
2451 else
2453 mxList->addAttribute("style:vertical-rel", sXML_CDATA, "page-content");
2454 mxList->addAttribute("style:horizontal-rel", sXML_CDATA, "page-content");
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("fo:border", sXML_CDATA, "none");
2468 break;
2469 case 1: /* A thin solid line */
2470 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2471 mxList->addAttribute("fo:border", sXML_CDATA,"0.002cm solid #000000");
2472 break;
2473 case 2: /* Bold lines */
2474 mxList->addAttribute("fo:border", sXML_CDATA,"0.035cm solid #000000");
2475 break;
2476 case 4: /* Double line */
2477 mxList->addAttribute("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2478 mxList->addAttribute("fo:border", sXML_CDATA,"0.039cm double #000000");
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("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
2489 break;
2490 case 2: /* Bold lines */
2491 mxList->addAttribute("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
2492 break;
2493 case 4: /* Double line */
2494 mxList->addAttribute("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2495 mxList->addAttribute("fo:border-left", sXML_CDATA,"0.039cm double #000000");
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("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
2503 break;
2504 case 2: /* Bold lines */
2505 mxList->addAttribute("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
2506 break;
2507 case 4: /* Double line */
2508 mxList->addAttribute("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2509 mxList->addAttribute("fo:border-right", sXML_CDATA,"0.039cm double #000000");
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("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
2517 break;
2518 case 2: /* Bold lines */
2519 mxList->addAttribute("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
2520 break;
2521 case 4: /* Double line */
2522 mxList->addAttribute("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2523 mxList->addAttribute("fo:border-top", sXML_CDATA,"0.039cm double #000000");
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("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
2531 break;
2532 case 2: /* Bold lines */
2533 mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
2534 break;
2535 case 4: /* Double line */
2536 mxList->addAttribute("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2537 mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
2538 break;
2542 if( cell->linetype[0] == 0 && cell->linetype[1] == 0 &&
2543 cell->linetype[2] == 0 && cell->linetype[3] == 0 ){
2544 mxList->addAttribute("fo:padding", sXML_CDATA,"0mm");
2546 else{
2547 mxList->addAttribute("fo:padding-left", sXML_CDATA,
2548 OUString::number(WTMM(fstyle->margin[1][0])) + "mm");
2549 mxList->addAttribute("fo:padding-right", sXML_CDATA,
2550 OUString::number(WTMM(fstyle->margin[1][1])) + "mm");
2551 mxList->addAttribute("fo:padding-top", sXML_CDATA,
2552 OUString::number(WTMM(fstyle->margin[1][2])) + "mm");
2553 mxList->addAttribute("fo:padding-bottom", sXML_CDATA,
2554 OUString::number(WTMM(fstyle->margin[1][3])) + "mm");
2556 if(cell->shade != 0)
2557 mxList->addAttribute("fo:background-color", 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("fo:padding", sXML_CDATA,"0mm");
2566 else if( fstyle->boxtype == 'L' )
2568 mxList->addAttribute( "style:border-line-width-bottom", sXML_CDATA, "0.02mm 0.35mm 0.02mm");
2569 mxList->addAttribute("fo:border-bottom", sXML_CDATA,"0.039cm double #808080");
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("style:mirror", sXML_CDATA, "none");
2580 mxList->addAttribute("fo:clip", sXML_CDATA, clip);
2582 char *cell = static_cast<char *>(fstyle->cell);
2583 mxList->addAttribute("draw:luminance", sXML_CDATA, OUString::number(cell[0]) + "%");
2584 mxList->addAttribute("draw:contrast", sXML_CDATA, OUString::number(cell[1]) + "%");
2585 if( cell[2] == 0 )
2586 mxList->addAttribute("draw:color-mode", sXML_CDATA, "standard");
2587 else if( cell[2] == 1 )
2588 mxList->addAttribute("draw:color-mode", sXML_CDATA, "greyscale");
2589 else if( cell[2] == 2 )
2590 mxList->addAttribute("draw:color-mode", sXML_CDATA, "mono");
2593 startEl("style:properties");
2594 mxList->clear();
2595 endEl("style:properties");
2596 endEl("style:style");
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("text:style-name", sXML_CDATA,
2631 getPStyleName(para->GetParaShape().index));
2632 startEl("text:p");
2633 mxList->clear();
2635 if( d->bFirstPara && d->bInBody )
2637 mxList->addAttribute("text:name", sXML_CDATA, sBeginOfDoc);
2638 startEl("text:bookmark");
2639 mxList->clear();
2640 endEl("text:bookmark");
2641 d->bFirstPara = false;
2643 if( d->bInHeader )
2645 makeShowPageNum();
2646 d->bInHeader = false;
2648 mxList->addAttribute("text:style-name", sXML_CDATA,
2649 getTStyleName(para->cshape->index));
2650 startEl("text:span");
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("text:s");
2662 endEl("text:s");
2664 else if (box->hh == CH_END_PARA)
2666 makeChars(str);
2667 endEl("text:span");
2668 endEl("text:p");
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("text:style-name", sXML_CDATA,
2701 getPStyleName(para->GetParaShape().index));
2702 startEl("text:p");
2703 mxList->clear();
2705 if( d->bFirstPara && d->bInBody )
2707 /* for HWP's Bookmark */
2708 mxList->addAttribute("text:name", sXML_CDATA, sBeginOfDoc);
2709 startEl("text:bookmark");
2710 mxList->clear();
2711 endEl("text:bookmark");
2712 d->bFirstPara = false;
2714 if( d->bInHeader )
2716 makeShowPageNum();
2717 d->bInHeader = false;
2719 mxList->addAttribute("text:style-name", sXML_CDATA,
2720 getTStyleName(curr));
2721 startEl("text:span");
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("text:span");
2734 curr = para->GetCharShape(n)->index;
2735 mxList->addAttribute("text:style-name", sXML_CDATA,
2736 getTStyleName(curr));
2737 startEl("text:span");
2738 mxList->clear();
2740 if (box->hh == CH_SPACE && !firstspace)
2742 makeChars(str);
2743 startEl("text:s");
2744 endEl("text:s");
2746 else if (box->hh == CH_END_PARA)
2748 makeChars(str);
2749 endEl("text:span");
2750 endEl("text:p");
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("text:style-name", "CDATA",
2788 getPStyleName(para->GetParaShape().index));
2789 startEl("text:p");
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("text:style-name", "CDATA", getTStyleName(curr));
2797 startEl("text:span");
2798 mxList->clear();
2799 tstart = true;
2801 const auto ENDP = [this, &pstart]()
2803 endEl("text:p");
2804 pstart = false;
2806 const auto ENDT = [this, &tstart]()
2808 endEl("text:span");
2809 tstart = false;
2812 if( d->bFirstPara && d->bInBody )
2814 if ( !pstart ) {
2815 STARTP();
2817 mxList->addAttribute("text:name", sXML_CDATA, sBeginOfDoc);
2818 startEl("text:bookmark");
2819 mxList->clear();
2820 endEl("text:bookmark");
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("text:s");
2857 mxList->clear();
2858 endEl("text:s");
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("text:placeholder-type", sXML_CDATA, "text");
3073 if (d->pField)
3074 mxList->addAttribute("text:description", sXML_CDATA, hstr2OUString(d->pField));
3075 startEl("text:placeholder");
3076 mxList->clear();
3077 chars( fromHcharStringToOUString(rStr) );
3078 endEl("text:placeholder");
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("text:title");
3087 chars( hstr2OUString(hbox->str2.get()) );
3088 endEl("text:title");
3090 else if (uStr3 == "subject")
3092 startEl("text:subject");
3093 chars( hstr2OUString(hbox->str2.get()) );
3094 endEl("text:subject");
3096 else if (uStr3 == "author")
3098 startEl("text:author-name");
3099 chars( hstr2OUString(hbox->str2.get()) );
3100 endEl("text:author-name");
3102 else if (uStr3 == "keywords")
3104 startEl("text:keywords");
3105 chars( hstr2OUString(hbox->str2.get()) );
3106 endEl("text:keywords");
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("text:sender-lastname");
3116 chars( hstr2OUString(hbox->str2.get()) );
3117 endEl("text:sender-lastname");
3119 else if (uStr3 == "Company")
3121 startEl("text:sender-company");
3122 chars( hstr2OUString(hbox->str2.get()) );
3123 endEl("text:sender-company");
3125 else if (uStr3 == "Position")
3127 startEl("text:sender-title");
3128 chars( hstr2OUString(hbox->str2.get()) );
3129 endEl("text:sender-title");
3131 else if (uStr3 == "Division")
3133 startEl("text:sender-position");
3134 chars( hstr2OUString(hbox->str2.get()) );
3135 endEl("text:sender-position");
3137 else if (uStr3 == "Fax")
3139 startEl("text:sender-fax");
3140 chars( hstr2OUString(hbox->str2.get()) );
3141 endEl("text:sender-fax");
3143 else if (uStr3 == "Pager")
3145 startEl("text:phone-private");
3146 chars( hstr2OUString(hbox->str2.get()) );
3147 endEl("text:phone-private");
3149 else if (uStr3 == "E-mail")
3151 startEl("text:sender-email");
3152 chars( hstr2OUString(hbox->str2.get()) );
3153 endEl("text:sender-email");
3155 else if (uStr3 == "Zipcode(office)")
3157 startEl("text:sender-postal-code");
3158 chars( hstr2OUString(hbox->str2.get()) );
3159 endEl("text:sender-postal-code");
3161 else if (uStr3 == "Phone(office)")
3163 startEl("text:sender-phone-work");
3164 chars( hstr2OUString(hbox->str2.get()) );
3165 endEl("text:sender-phone-work");
3167 else if (uStr3 == "Address(office)")
3169 startEl("text:sender-street");
3170 chars( hstr2OUString(hbox->str2.get()) );
3171 endEl("text:sender-street");
3175 else if( hbox->type[0] == 3 && hbox->type[1] == 2 ) /* creation date */
3177 if( hbox->m_pDate )
3178 mxList->addAttribute("style:data-style-name", sXML_CDATA, "N" + OUString::number(hbox->m_pDate->key));
3179 startEl("text:creation-date");
3180 mxList->clear();
3181 chars( hstr2OUString(hbox->str2.get()) );
3182 endEl("text:creation-date");
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("text:name", sXML_CDATA, hstr2OUString(hbox->id));
3196 startEl("text:bookmark");
3197 mxList->clear();
3198 endEl("text:bookmark");
3200 else if (hbox->type == 1) /* Block bookmarks days begin and end there if */
3202 mxList->addAttribute("text:name", sXML_CDATA, hstr2OUString(hbox->id));
3203 startEl("text:bookmark-start");
3204 mxList->clear();
3205 endEl("text:bookmark-start");
3207 else if (hbox->type == 2)
3209 mxList->addAttribute("text:name", sXML_CDATA, hstr2OUString(hbox->id));
3210 startEl("text:bookmark-end");
3211 mxList->clear();
3212 endEl("text:bookmark-end");
3217 void HwpReader::makeDateFormat(DateCode * hbox)
3219 mxList->addAttribute("style:name", sXML_CDATA, "N" + OUString::number(hbox->key));
3220 mxList->addAttribute("style:family", sXML_CDATA,"data-style");
3221 mxList->addAttribute("number:language", sXML_CDATA,"ko");
3222 mxList->addAttribute("number:country", sXML_CDATA,"KR");
3224 startEl("number:date-style");
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("number:style", sXML_CDATA, "long");
3250 startEl("number:year");
3251 mxList->clear();
3252 endEl("number:year");
3253 break;
3254 case '!':
3255 startEl("number:year");
3256 mxList->clear();
3257 endEl("number:year");
3258 break;
3259 case '2':
3260 if( add_zero )
3261 mxList->addAttribute("number:style", sXML_CDATA, "long");
3262 startEl("number:month");
3263 mxList->clear();
3264 endEl("number:month");
3265 break;
3266 case '@':
3267 mxList->addAttribute("number:textual", sXML_CDATA, "true");
3268 startEl("number:month");
3269 mxList->clear();
3270 endEl("number:month");
3271 break;
3272 case '*':
3273 mxList->addAttribute("number:textual", sXML_CDATA, "true");
3274 mxList->addAttribute("number:style", sXML_CDATA, "long");
3275 startEl("number:month");
3276 mxList->clear();
3277 endEl("number:month");
3278 break;
3279 case '3':
3280 if( add_zero )
3281 mxList->addAttribute("number:style", sXML_CDATA, "long");
3282 startEl("number:day");
3283 mxList->clear();
3284 endEl("number:day");
3285 break;
3286 case '#':
3287 if( add_zero )
3288 mxList->addAttribute("number:style", sXML_CDATA, "long");
3289 startEl("number:day");
3290 mxList->clear();
3291 endEl("number:day");
3292 switch( hbox->date[DateCode::DAY] % 10)
3294 case 1:
3295 startEl("number:text");
3296 chars("st");
3297 endEl("number:text");
3298 break;
3299 case 2:
3300 startEl("number:text");
3301 chars("nd");
3302 endEl("number:text");
3303 break;
3304 case 3:
3305 startEl("number:text");
3306 chars("rd");
3307 endEl("number:text");
3308 break;
3309 default:
3310 startEl("number:text");
3311 chars("th");
3312 endEl("number:text");
3313 break;
3315 break;
3316 case '4':
3317 case '$':
3318 if( add_zero )
3319 mxList->addAttribute("number:style", sXML_CDATA, "long");
3320 startEl("number:hours");
3321 mxList->clear();
3322 endEl("number:hours");
3323 break;
3324 case '5':
3325 case '%':
3326 if( add_zero )
3327 mxList->addAttribute("number:style", sXML_CDATA, "long");
3328 startEl("number:minutes");
3329 mxList->clear();
3330 endEl("number:minutes");
3331 break;
3332 case '_':
3333 mxList->addAttribute("number:style", sXML_CDATA, "long");
3334 [[fallthrough]];
3335 case '6':
3336 case '^':
3337 startEl("number:day-of-week");
3338 mxList->clear();
3339 endEl("number:day-of-week");
3340 break;
3341 case '7':
3342 case '&':
3343 case '+':
3344 startEl("number:am-pm");
3345 mxList->clear();
3346 endEl("number:am-pm");
3347 break;
3348 case '~': // Chinese Locale
3349 break;
3350 default:
3351 hchar sbuf[2];
3352 sbuf[0] = *fmt;
3353 sbuf[1] = 0;
3354 startEl("number:text");
3355 chars(hstr2OUString(sbuf));
3356 endEl("number:text");
3357 break;
3360 mxList->clear();
3361 endEl("number:date-style");
3365 void HwpReader::makeDateCode(DateCode * hbox)
3367 mxList->addAttribute("style:data-style-name", sXML_CDATA, "N" + OUString::number(hbox->key));
3368 startEl("text:date");
3369 mxList->clear();
3370 hchar_string const boxstr = hbox->GetString();
3371 chars(hstr2OUString(boxstr.c_str()));
3372 endEl("text:date");
3376 void HwpReader::makeTab()
3378 startEl("text:tab-stop");
3379 endEl("text:tab-stop");
3383 void HwpReader::makeTable(TxtBox * hbox)
3385 mxList->addAttribute("table:name", sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum));
3386 mxList->addAttribute("table:style-name", sXML_CDATA, "Table" + OUString::number(hbox->style.boxnum));
3387 startEl("table:table");
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 "table:style-name", sXML_CDATA,
3396 "Table" + OUString::number(hbox->style.boxnum) + "."
3397 + OUStringChar(static_cast<char>('A'+i)));
3398 startEl("table:table-column");
3399 mxList->clear();
3400 endEl("table:table-column");
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("table:table-row");
3412 k = j;
3414 // row
3415 mxList->addAttribute(
3416 "table:style-name", sXML_CDATA,
3417 "Table" + OUString::number(hbox->style.boxnum) + ".row"
3418 + OUString::number(tcell->nRowIndex + 1));
3419 startEl("table:table-row");
3420 mxList->clear();
3421 j = tcell->nRowIndex;
3424 mxList->addAttribute(
3425 "table:style-name", 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("table:number-columns-spanned", sXML_CDATA, OUString::number(tcell->nColumnSpan));
3431 if( tcell->nRowSpan > 1 )
3432 mxList->addAttribute("table:number-rows-spanned", sXML_CDATA, OUString::number(tcell->nRowSpan));
3433 mxList->addAttribute("table:value-type", sXML_CDATA,"string");
3434 if( tcell->pCell->protect )
3435 mxList->addAttribute("table:protected", sXML_CDATA,"true");
3436 startEl("table:table-cell");
3437 mxList->clear();
3438 TxtBox::plist_t& rVec = hbox->plists[tcell->pCell->key];
3439 if (!rVec.empty())
3440 parsePara(rVec.front().get());
3441 endEl("table:table-cell");
3443 endEl("table:table-row");
3444 endEl("table:table");
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("draw:style-name", sXML_CDATA, "CapBox" + OUString::number(hbox->style.boxnum));
3459 mxList->addAttribute("draw:name", sXML_CDATA, "CaptionBox" + OUString::number(hbox->style.boxnum));
3460 mxList->addAttribute("draw:z-index", sXML_CDATA, OUString::number(hbox->zorder));
3461 switch (hbox->style.anchor_type)
3463 case CHAR_ANCHOR:
3464 mxList->addAttribute("text:anchor-type", sXML_CDATA, "as-char");
3465 break;
3466 case PARA_ANCHOR:
3467 mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
3468 break;
3469 case PAGE_ANCHOR:
3470 case PAPER_ANCHOR:
3472 mxList->addAttribute("text:anchor-type", sXML_CDATA, "page");
3473 mxList->addAttribute("text:anchor-page-number", sXML_CDATA, OUString::number(hbox->pgno + 1));
3474 break;
3477 if (hbox->style.anchor_type != CHAR_ANCHOR)
3479 mxList->addAttribute("svg:x", sXML_CDATA,
3480 OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
3481 mxList->addAttribute("svg:y", sXML_CDATA,
3482 OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
3484 mxList->addAttribute("svg:width", sXML_CDATA,
3485 OUString::number(WTMM( hbox->box_xs + hbox->cap_xs )) + "mm");
3486 mxList->addAttribute("fo:min-height", sXML_CDATA,
3487 OUString::number(WTMM( hbox->box_ys + hbox->cap_ys )) + "mm");
3488 startEl("draw:text-box");
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( "text:style-name", sXML_CDATA, "Standard");
3495 startEl("text:p");
3496 mxList->clear();
3498 else{
3499 mxList->addAttribute("draw:z-index", sXML_CDATA, OUString::number(hbox->zorder));
3502 mxList->addAttribute("draw:style-name", sXML_CDATA, "Txtbox" + OUString::number(hbox->style.boxnum));
3503 mxList->addAttribute("draw:name", 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("text:anchor-type", sXML_CDATA, "as-char");
3513 break;
3514 case PARA_ANCHOR:
3515 mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
3516 break;
3517 case PAGE_ANCHOR:
3518 case PAPER_ANCHOR:
3520 mxList->addAttribute("text:anchor-type", sXML_CDATA, "page");
3521 mxList->addAttribute("text:anchor-page-number", 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("svg:x", sXML_CDATA,
3531 OUString::number(WTMM( hbox->pgx + x )) + "mm");
3532 mxList->addAttribute("svg:y", sXML_CDATA,
3533 OUString::number(WTMM( hbox->pgy + y )) + "mm");
3535 else
3537 mxList->addAttribute("text:anchor-type", sXML_CDATA, "as-char");
3538 mxList->addAttribute("svg:y", sXML_CDATA, "0cm");
3540 mxList->addAttribute("svg:width", sXML_CDATA,
3541 OUString::number(WTMM( hbox->box_xs )) + "mm");
3542 if( hbox->style.cap_len > 0 && hbox->type != TXT_TYPE)
3543 mxList->addAttribute("fo:min-height", sXML_CDATA,
3544 OUString::number(WTMM( hbox->box_ys + hbox->cap_ys)) + "mm");
3545 else
3546 mxList->addAttribute("svg:height", sXML_CDATA,
3547 OUString::number(WTMM(hbox->box_ys )) + "mm");
3549 if( hbox->type != EQU_TYPE )
3551 startEl("draw:text-box");
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("draw:text-box");
3572 // Caption exist and it is text-box
3573 if( hbox->style.cap_len > 0 && hbox->type == TXT_TYPE)
3575 endEl("text:p");
3576 if (!(hbox->cap_pos % 2) && !hbox->caption.empty())
3578 parsePara(hbox->caption.front().get());
3580 endEl("draw:text-box");
3583 else // is Formula
3585 startEl("draw:object");
3586 mxList->clear();
3587 makeFormula(hbox);
3588 endEl("draw:object");
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("xlink:type", sXML_CDATA, "simple");
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("xlink:href", sXML_CDATA,
3666 OUString(tmp3.c_str(), tmp3.size()+1, RTL_TEXTENCODING_EUC_KR));
3668 else{
3669 mxList->addAttribute("xlink:href", sXML_CDATA,
3670 OUString(tmp2.c_str(), tmp2.size()+1, RTL_TEXTENCODING_EUC_KR));
3674 else
3676 mxList->addAttribute("xlink:type", sXML_CDATA, "simple");
3677 ::std::string tmp;
3678 tmp.push_back('#');
3679 tmp.append(hstr2ksstr(hypert->bookmark));
3680 mxList->addAttribute("xlink:href", sXML_CDATA,
3681 OUString(tmp.c_str(), tmp.size()+1, RTL_TEXTENCODING_EUC_KR));
3683 startEl("draw:a");
3684 mxList->clear();
3685 makeTextBox(hbox);
3686 endEl("draw:a");
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("draw:style-name", sXML_CDATA,
3706 "CapBox" + OUString::number(hbox->style.boxnum));
3707 mxList->addAttribute("draw:name", sXML_CDATA, "CaptionBox" + OUString::number(hbox->style.boxnum));
3708 mxList->addAttribute("draw:z-index", sXML_CDATA, OUString::number(hbox->zorder));
3709 switch (hbox->style.anchor_type)
3711 case CHAR_ANCHOR:
3712 mxList->addAttribute("text:anchor-type", sXML_CDATA, "as-char");
3713 break;
3714 case PARA_ANCHOR:
3715 mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
3716 break;
3717 case PAGE_ANCHOR:
3718 case PAPER_ANCHOR:
3720 mxList->addAttribute("text:anchor-type", sXML_CDATA, "page");
3721 mxList->addAttribute("text:anchor-page-number", sXML_CDATA,
3722 OUString::number(hbox->pgno + 1));
3723 break;
3726 if (hbox->style.anchor_type != CHAR_ANCHOR)
3728 mxList->addAttribute("svg:x", sXML_CDATA,
3729 OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
3730 mxList->addAttribute("svg:y", sXML_CDATA,
3731 OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
3733 mxList->addAttribute("svg:width", sXML_CDATA,
3734 OUString::number(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1] )) + "mm");
3735 mxList->addAttribute("fo:min-height", 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("draw:text-box");
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( "text:style-name", sXML_CDATA, "Standard");
3744 startEl("text:p");
3745 mxList->clear();
3747 if( hbox->ishyper )
3749 mxList->addAttribute("xlink:type", sXML_CDATA, "simple");
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("xlink:href", 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("xlink:href", 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("draw:a");
3764 mxList->clear();
3766 mxList->addAttribute("draw:style-name", sXML_CDATA, "G" + OUString::number(hbox->style.boxnum));
3767 mxList->addAttribute("draw:name", sXML_CDATA, "Image" + OUString::number(hbox->style.boxnum));
3769 if( hbox->style.cap_len <= 0 )
3771 mxList->addAttribute("draw:z-index", sXML_CDATA, OUString::number(hbox->zorder));
3772 switch (hbox->style.anchor_type)
3774 case CHAR_ANCHOR:
3775 mxList->addAttribute("text:anchor-type", sXML_CDATA, "as-char");
3776 break;
3777 case PARA_ANCHOR:
3778 mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
3779 break;
3780 case PAGE_ANCHOR:
3781 case PAPER_ANCHOR:
3783 mxList->addAttribute("text:anchor-type", sXML_CDATA, "page");
3784 mxList->addAttribute("text:anchor-page-number", sXML_CDATA,
3785 OUString::number(hbox->pgno + 1));
3786 break;
3789 if (hbox->style.anchor_type != CHAR_ANCHOR)
3791 mxList->addAttribute("svg:x", sXML_CDATA,
3792 OUString::number(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
3793 mxList->addAttribute("svg:y", sXML_CDATA,
3794 OUString::number(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
3797 else
3799 mxList->addAttribute("text:anchor-type", sXML_CDATA, "as-char");
3800 mxList->addAttribute("svg:y", sXML_CDATA, "0cm");
3802 mxList->addAttribute("svg:width", sXML_CDATA,
3803 OUString::number(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1])) + "mm");
3804 mxList->addAttribute("svg:height", 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("xlink:href", sXML_CDATA,
3813 hstr2OUString(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(hbox->picinfo.picun.path).c_str())).c_str()));
3814 #endif
3815 mxList->addAttribute("xlink:type", sXML_CDATA, "simple");
3816 mxList->addAttribute("xlink:show", sXML_CDATA, "embed");
3817 mxList->addAttribute("xlink:actuate", sXML_CDATA, "onLoad");
3820 if( hbox->pictype == PICTYPE_OLE )
3821 startEl("draw:object-ole");
3822 else
3823 startEl("draw:image");
3824 mxList->clear();
3825 if (hbox->pictype == PICTYPE_EMBED || hbox->pictype == PICTYPE_OLE)
3827 startEl("office:binary-data");
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.picole.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("");
3863 #endif
3866 endEl("office:binary-data");
3868 if( hbox->pictype == PICTYPE_OLE )
3869 endEl("draw:object-ole");
3870 else
3871 endEl("draw:image");
3872 if( hbox->ishyper )
3874 endEl("draw:a");
3876 if( hbox->style.cap_len > 0 )
3878 endEl("text:p");
3879 if (!hbox->caption.empty() && !(hbox->cap_pos % 2)) /* Caption is at the bottom, */
3881 parsePara(hbox->caption.front().get());
3883 endEl("draw:text-box");
3885 break;
3887 case PICTYPE_DRAW:
3888 if( hbox->picinfo.picdraw.zorder > 0 )
3889 mxList->addAttribute("draw:z-index", 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("draw:style-name", 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("text:anchor-type", sXML_CDATA, "as-char");
3912 break;
3913 case PARA_ANCHOR:
3914 mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
3915 break;
3916 case PAGE_ANCHOR:
3917 case PAPER_ANCHOR:
3919 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
3920 mxList->addAttribute("text:anchor-type", sXML_CDATA, "page");
3921 mxList->addAttribute("text:anchor-page-number", 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("draw:g");
3931 mxList->clear();
3932 makePictureDRAW(drawobj->child.get(), hbox);
3933 endEl("draw:g");
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("draw:transform", 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("svg:x1", sXML_CDATA,
4011 OUString::number (WTMM(x + a + drawobj->offset2.x + drawobj->extent.w)) + "mm");
4012 mxList->addAttribute("svg:x2", sXML_CDATA,
4013 OUString::number (WTMM( x + a + drawobj->offset2.x )) + "mm");
4015 else
4017 mxList->addAttribute("svg:x1", sXML_CDATA,
4018 OUString::number (WTMM( x + a + drawobj->offset2.x )) + "mm");
4019 mxList->addAttribute("svg:x2", 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("svg:y1", sXML_CDATA,
4025 OUString::number (WTMM( y + b + drawobj->offset2.y + drawobj->extent.h ) ) + "mm");
4026 mxList->addAttribute("svg:y2", sXML_CDATA,
4027 OUString::number (WTMM( y + b + drawobj->offset2.y )) + "mm");
4029 else
4031 mxList->addAttribute("svg:y1", sXML_CDATA,
4032 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4033 mxList->addAttribute("svg:y2", sXML_CDATA,
4034 OUString::number (WTMM(y + b + drawobj->offset2.y + drawobj->extent.h)) + "mm");
4037 startEl("draw:line");
4038 mxList->clear();
4039 endEl("draw:line");
4040 break;
4041 case HWPDO_RECT: /* rectangle - the starting position, vertical/horizontal */
4042 if( !bIsRotate )
4044 mxList->addAttribute("svg:x", sXML_CDATA,
4045 OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
4046 mxList->addAttribute("svg:y", sXML_CDATA,
4047 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4049 mxList->addAttribute("svg:width", sXML_CDATA,
4050 OUString::number (WTMM( drawobj->extent.w )) + "mm");
4051 mxList->addAttribute("svg:height", 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("draw:corner-radius", 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("draw:corner-radius", sXML_CDATA,
4065 OUString::number (WTMM( value / 2)) + "mm");
4068 startEl("draw:rect");
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("draw:rect");
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("svg:x", sXML_CDATA,
4089 OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
4090 mxList->addAttribute("svg:y", sXML_CDATA,
4091 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4094 mxList->addAttribute("svg:width", sXML_CDATA,
4095 OUString::number (WTMM( drawobj->extent.w )) + "mm");
4096 mxList->addAttribute("svg:height", 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("draw:kind", sXML_CDATA, "section");
4113 else
4114 mxList->addAttribute("draw:kind", sXML_CDATA, "arc");
4115 mxList->addAttribute("draw:start-angle", sXML_CDATA, OUString::number(start_angle ));
4116 mxList->addAttribute("draw:end-angle", sXML_CDATA, OUString::number(end_angle));
4120 startEl("draw:ellipse");
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("draw:ellipse");
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("svg:x", sXML_CDATA,
4146 OUString::number (WTMM( x + a + drawobj->offset2.x - drawobj->extent.w)) + "mm");
4147 else
4148 mxList->addAttribute("svg:x", 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("svg:y", sXML_CDATA,
4152 OUString::number (WTMM( y + b + drawobj->offset2.y - drawobj->extent.h)) + "mm");
4153 else
4154 mxList->addAttribute("svg:y", sXML_CDATA,
4155 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4158 mxList->addAttribute("svg:width", sXML_CDATA,
4159 OUString::number (WTMM( drawobj->extent.w * 2)) + "mm");
4160 mxList->addAttribute("svg:height", 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("draw:kind", sXML_CDATA, "section");
4165 else
4166 mxList->addAttribute("draw:kind", sXML_CDATA, "arc");
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("draw:start-angle", sXML_CDATA, OUString::number(basegfx::rad2deg(start_angle)));
4178 mxList->addAttribute("draw:end-angle", sXML_CDATA, OUString::number(basegfx::rad2deg(end_angle)));
4181 else
4183 if( drawobj->u.line_arc.flip == 0 )
4185 mxList->addAttribute("draw:start-angle", sXML_CDATA, "270");
4186 mxList->addAttribute("draw:end-angle", sXML_CDATA, "0");
4188 else if( drawobj->u.line_arc.flip == 1 )
4190 mxList->addAttribute("draw:start-angle", sXML_CDATA, "180");
4191 mxList->addAttribute("draw:end-angle", sXML_CDATA, "270");
4193 else if( drawobj->u.line_arc.flip == 2 )
4195 mxList->addAttribute("draw:start-angle", sXML_CDATA, "0");
4196 mxList->addAttribute("draw:end-angle", sXML_CDATA, "90");
4198 else
4200 mxList->addAttribute("draw:start-angle", sXML_CDATA, "90");
4201 mxList->addAttribute("draw:end-angle", sXML_CDATA, "180");
4204 startEl("draw:ellipse");
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("draw:ellipse");
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("svg:x", sXML_CDATA,
4230 OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
4231 mxList->addAttribute("svg:y", sXML_CDATA,
4232 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4234 mxList->addAttribute("svg:width", sXML_CDATA,
4235 OUString::number (WTMM( drawobj->extent.w )) + "mm");
4236 mxList->addAttribute("svg:height", sXML_CDATA,
4237 OUString::number (WTMM( drawobj->extent.h )) + "mm");
4238 mxList->addAttribute(
4239 "svg:viewBox", 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("svg:d", sXML_CDATA, oustr.makeStringAndClear());
4315 startEl("draw:path");
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("draw:path");
4328 break;
4330 case HWPDO_CLOSED_FREEFORM:
4331 case HWPDO_FREEFORM: /* polygon */
4333 bool bIsPolygon = false;
4335 mxList->addAttribute("svg:x", sXML_CDATA,
4336 OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
4337 mxList->addAttribute("svg:y", sXML_CDATA,
4338 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4340 mxList->addAttribute("svg:width", sXML_CDATA,
4341 OUString::number (WTMM( drawobj->extent.w )) + "mm");
4342 mxList->addAttribute("svg:height", sXML_CDATA,
4343 OUString::number (WTMM( drawobj->extent.h )) + "mm");
4345 mxList->addAttribute("svg:viewBox", 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("draw:points", 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("draw:polygon");
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("draw:polygon");
4393 else
4395 startEl("draw:polyline");
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("draw:polyline");
4411 break;
4413 case HWPDO_TEXTBOX:
4414 if( !bIsRotate )
4416 mxList->addAttribute("svg:x", sXML_CDATA,
4417 OUString::number (WTMM( x + a + drawobj->offset2.x)) + "mm");
4418 mxList->addAttribute("svg:y", sXML_CDATA,
4419 OUString::number (WTMM( y + b + drawobj->offset2.y)) + "mm");
4421 mxList->addAttribute("svg:width", sXML_CDATA,
4422 OUString::number (WTMM( drawobj->extent.w )) + "mm");
4423 mxList->addAttribute("svg:height", 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("draw:corner-radius", 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("draw:corner-radius", sXML_CDATA,
4437 OUString::number (WTMM( value / 2)) + "mm");
4440 startEl("draw:text-box");
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("draw:text-box");
4452 break;
4455 mxList->clear();
4456 drawobj = drawobj->next.get();
4460 void HwpReader::makeLine()
4462 mxList->addAttribute("text:style-name", sXML_CDATA, "Horizontal Line");
4463 startEl("text:p");
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("text:condition", sXML_CDATA, "");
4478 mxList->addAttribute("text:string-value", sXML_CDATA, "");
4479 startEl("text:hidden-text");
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("text:hidden-text");
4504 * Converts footnote to text:footnote, endnote to text:endnote
4506 void HwpReader::makeFootnote(Footnote * hbox)
4508 if (hbox->type)
4510 mxList->addAttribute("text:id", sXML_CDATA, "edn" + OUString::number(hbox->number));
4511 startEl("text:endnote");
4512 mxList->clear();
4513 mxList->addAttribute("text:label", sXML_CDATA, OUString::number(hbox->number));
4514 startEl("text:endnote-citation");
4515 mxList->clear();
4516 chars(OUString::number(hbox->number));
4517 endEl("text:endnote-citation");
4518 startEl("text:endnote-body");
4519 if (!hbox->plist.empty())
4520 parsePara(hbox->plist.front().get());
4521 endEl("text:endnote-body");
4522 endEl("text:endnote");
4524 else
4526 mxList->addAttribute("text:id", sXML_CDATA, "ftn" + OUString::number(hbox->number));
4527 startEl("text:footnote");
4528 mxList->clear();
4529 mxList->addAttribute("text:label", sXML_CDATA, OUString::number(hbox->number));
4530 startEl("text:footnote-citation");
4531 mxList->clear();
4532 chars(OUString::number(hbox->number));
4533 endEl("text:footnote-citation");
4534 startEl("text:footnote-body");
4535 if (!hbox->plist.empty())
4536 parsePara(hbox->plist.front().get());
4537 endEl("text:footnote-body");
4538 endEl("text:footnote");
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("text:page-number");
4552 chars(OUString::number(hbox->number));
4553 endEl("text:page-number");
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("text:ref-name",sXML_CDATA, "refIllustration" + OUString::number(hbox->number));
4562 mxList->addAttribute("text:name",sXML_CDATA, "Illustration");
4563 mxList->addAttribute("style:num-format",sXML_CDATA, "1");
4564 startEl("text:sequence");
4565 chars(OUString::number(hbox->number));
4566 endEl("text:sequence");
4567 break;
4568 case TBLNUM_AUTO:
4569 mxList->addAttribute("text:ref-name",sXML_CDATA, "refTable" + OUString::number(hbox->number));
4570 mxList->addAttribute("text:name",sXML_CDATA, "Table");
4571 mxList->addAttribute("style:num-format",sXML_CDATA, "1");
4572 startEl("text:sequence");
4573 chars(OUString::number(hbox->number));
4574 endEl("text:sequence");
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("draw:style-name", sXML_CDATA, "PNBox" + OUString::number(nPos));
4599 mxList->addAttribute("draw:name", sXML_CDATA, "PageNumber" + OUString::number(nPos));
4600 mxList->addAttribute("text:anchor-type", sXML_CDATA, "paragraph");
4601 mxList->addAttribute("svg:y", sXML_CDATA, "0cm");
4602 mxList->addAttribute("svg:width", sXML_CDATA, "2.0cm");
4603 mxList->addAttribute("fo:min-height", sXML_CDATA, "0.5cm");
4604 startEl("draw:text-box");
4605 mxList->clear();
4607 mxList->addAttribute("text:style-name", sXML_CDATA, "PNPara" + OUString::number(nPos));
4608 startEl("text:p");
4609 mxList->clear();
4610 if( hbox->shape > 2 )
4611 chars("- ");
4612 if( hbox->shape % 3 == 0 )
4613 mxList->addAttribute("style:num-format", sXML_CDATA, "1");
4614 else if( hbox->shape % 3 == 1 )
4615 mxList->addAttribute("style:num-format", sXML_CDATA, "I");
4616 else
4617 mxList->addAttribute("style:num-format", sXML_CDATA, "i");
4618 mxList->addAttribute("text:select-page", sXML_CDATA, "current");
4619 startEl("text:page-number");
4620 mxList->clear();
4621 chars("2");
4622 endEl("text:page-number");
4623 if( hbox->shape > 2 )
4624 chars(" -");
4625 endEl("text:p");
4626 endEl("draw:text-box");
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("text:style-name", sXML_CDATA,
4658 getPStyleName(para->GetParaShape().index));
4659 startEl("text:p");
4660 mxList->clear();
4662 if( d->bFirstPara && d->bInBody )
4664 /* for HWP's Bookmark */
4665 mxList->addAttribute("text:name", sXML_CDATA, sBeginOfDoc);
4666 startEl("text:bookmark");
4667 mxList->clear();
4668 endEl("text:bookmark");
4669 d->bFirstPara = false;
4671 if( d->bInHeader )
4673 makeShowPageNum();
4674 d->bInHeader = false;
4677 endEl("text:p");
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 Reference< XFilter > rFilter;
4748 Reference< XImporter > rImporter;
4752 HwpImportFilter::HwpImportFilter(const Reference< XComponentContext >& rxContext)
4754 try {
4755 Reference< XDocumentHandler > xHandler( rxContext->getServiceManager()->createInstanceWithContext( WRITER_IMPORTER_NAME, rxContext ), UNO_QUERY );
4757 rtl::Reference<HwpReader> p = new HwpReader;
4758 p->setDocumentHandler( xHandler );
4760 Reference< XImporter > xImporter( xHandler, UNO_QUERY );
4761 rImporter = xImporter;
4762 rFilter = p;
4764 catch( Exception & )
4766 printf(" fail to instantiate %s\n", WRITER_IMPORTER_NAME.toUtf8().getStr() );
4767 exit( 1 );
4771 sal_Bool HwpImportFilter::filter( const Sequence< PropertyValue >& aDescriptor )
4773 // delegate to IchitaroImporter
4774 return rFilter->filter( aDescriptor );
4777 void HwpImportFilter::cancel()
4779 rFilter->cancel();
4782 void HwpImportFilter::setTargetDocument( const Reference< XComponent >& xDoc )
4784 // delegate
4785 rImporter->setTargetDocument( xDoc );
4788 OUString HwpImportFilter::getImplementationName()
4790 return IMPLEMENTATION_NAME;
4793 sal_Bool HwpImportFilter::supportsService( const OUString& ServiceName )
4795 return cppu::supportsService(this, ServiceName);
4798 //XExtendedFilterDetection
4799 OUString HwpImportFilter::detect( css::uno::Sequence< css::beans::PropertyValue >& rDescriptor )
4801 OUString sTypeName;
4803 utl::MediaDescriptor aDescriptor(rDescriptor);
4804 aDescriptor.addInputStream();
4806 Reference< XInputStream > xInputStream(
4807 aDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM], UNO_QUERY);
4809 if (xInputStream.is())
4811 Sequence< sal_Int8 > aData;
4812 sal_Int32 nLen = HWPIDLen;
4813 if (
4814 nLen == xInputStream->readBytes(aData, nLen) &&
4815 detect_hwp_version(reinterpret_cast<const char*>(aData.getConstArray()))
4818 sTypeName = "writer_MIZI_Hwp_97";
4822 return sTypeName;
4825 Sequence< OUString> HwpImportFilter::getSupportedServiceNames()
4827 return { SERVICE_NAME1, SERVICE_NAME2 };
4832 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
4833 hwpfilter_HwpImportFilter_get_implementation(
4834 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
4836 return cppu::acquire(new HwpImportFilter(context));
4840 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */