nss: upgrade to release 3.73
[LibreOffice.git] / hwpfilter / source / hwpreader.cxx
blob4cf69e28603fe453fe7bbe3328b35996f2e7fd94
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>
23 #include "hwpreader.hxx"
24 #include <math.h>
26 #include <o3tl/safeint.hxx>
27 #include <osl/diagnose.h>
28 #include <tools/stream.hxx>
30 #include "fontmap.hxx"
31 #include "formula.h"
32 #include "cspline.h"
33 #include "datecode.h"
35 #include <iostream>
36 #include <locale.h>
37 #include <sal/types.h>
38 #include <rtl/ustrbuf.hxx>
40 // To be shorten source code by realking
41 #define hconv(x) hstr2ucsstr(x).c_str()
42 #define ascii(x) OUString::createFromAscii(x)
43 #define rstartEl(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->startElement(x,y); } while(false)
44 #define rendEl(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->endElement(x); } while(false)
45 #define rchars(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(x); } while(false)
46 #define padd(x,y,z) mxList->addAttribute(x,y,z)
47 #define Double2Str(x) OUString::number(x)
48 #define WTI(x) (static_cast<double>(x) / 1800.) // unit => inch
49 #define WTMM(x) (static_cast<double>(x) / 1800. * 25.4) // unit => mm
50 #define WTSM(x) (static_cast<int>((x) / 1800. * 2540)) // unit ==> 1/100 mm
52 #define PI 3.14159265358979323846
54 // xmloff/xmlkyd.hxx
55 #define sXML_CDATA "CDATA"
57 #define STARTP padd( "text:style-name", "CDATA", ascii(getPStyleName((para->GetParaShape()).index,buf))); \
58 rstartEl( "text:p",mxList.get() ); \
59 mxList->clear(); \
60 pstart = true
61 #define STARTT \
62 curr = para->GetCharShape(n > 0 ? n-1 : 0)->index; \
63 padd( "text:style-name", "CDATA" , ascii( getTStyleName(curr, buf) ) ); \
64 rstartEl( "text:span",mxList.get() ); \
65 mxList->clear(); \
66 tstart = true
67 #define ENDP \
68 rendEl("text:p"); \
69 pstart = false
70 #define ENDT \
71 rendEl("text:span"); \
72 tstart = false
74 static hchar *field = nullptr;
75 static char buf[1024];
77 namespace
80 template<typename T>
81 struct Free
83 void operator()(T* const ptr)
85 free(ptr);
91 struct HwpReaderPrivate
93 HwpReaderPrivate()
95 bFirstPara = true;
96 bInBody = false;
97 bInHeader = false;
98 nPnPos = 0;
99 pPn = nullptr;
102 bool bFirstPara;
103 bool bInBody;
104 bool bInHeader;
105 ShowPageNum *pPn;
106 int nPnPos;
109 HwpReader::HwpReader() : mxList(new AttributeListImpl), d(new HwpReaderPrivate)
114 HwpReader::~HwpReader()
118 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportHWP(SvStream &rStream)
122 std::unique_ptr<HStream> stream(new HStream);
123 byte aData[32768];
125 while (true)
127 std::size_t nRead = rStream.ReadBytes(aData, 32768);
128 if (nRead == 0)
129 break;
130 stream->addData(aData, static_cast<int>(nRead));
133 HWPFile hwpfile;
134 if (hwpfile.ReadHwpFile(std::move(stream)))
135 return false;
137 catch (...)
139 return false;
141 return true;
144 sal_Bool HwpReader::filter(const Sequence< PropertyValue >& rDescriptor)
146 utl::MediaDescriptor aDescriptor(rDescriptor);
147 aDescriptor.addInputStream();
149 Reference< XInputStream > xInputStream(
150 aDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM()], UNO_QUERY_THROW);
152 std::unique_ptr<HStream> stream(new HStream);
153 Sequence < sal_Int8 > aBuffer;
154 sal_Int32 nRead, nTotal = 0;
155 while( true )
157 nRead = xInputStream->readBytes(aBuffer, 32768);
158 if( nRead == 0 )
159 break;
160 stream->addData( reinterpret_cast<const byte *>(aBuffer.getConstArray()), nRead );
161 nTotal += nRead;
164 if( nTotal == 0 ) return false;
166 if (hwpfile.ReadHwpFile(std::move(stream)))
167 return false;
169 if (m_rxDocumentHandler.is())
170 m_rxDocumentHandler->startDocument();
172 padd("office:class", sXML_CDATA, "text");
173 padd("office:version", sXML_CDATA, "0.9");
175 padd("xmlns:office", "CDATA", "http://openoffice.org/2000/office");
176 padd("xmlns:style", "CDATA", "http://openoffice.org/2000/style");
177 padd("xmlns:text", "CDATA", "http://openoffice.org/2000/text");
178 padd("xmlns:table", "CDATA", "http://openoffice.org/2000/table");
179 padd("xmlns:draw", "CDATA", "http://openoffice.org/2000/drawing");
180 padd("xmlns:fo", "CDATA", "http://www.w3.org/1999/XSL/Format");
181 padd("xmlns:xlink", "CDATA", "http://www.w3.org/1999/xlink");
182 padd("xmlns:dc", "CDATA", "http://purl.org/dc/elements/1.1/");
183 padd("xmlns:meta", "CDATA", "http://openoffice.org/2000/meta");
184 padd("xmlns:number", "CDATA", "http://openoffice.org/2000/datastyle");
185 padd("xmlns:svg", "CDATA", "http://www.w3.org/2000/svg");
186 padd("xmlns:chart", "CDATA", "http://openoffice.org/2000/chart");
187 padd("xmlns:dr3d", "CDATA", "http://openoffice.org/2000/dr3d");
188 padd("xmlns:math", "CDATA", "http://www.w3.org/1998/Math/MathML");
189 padd("xmlns:form", "CDATA", "http://openoffice.org/2000/form");
190 padd("xmlns:script", "CDATA", "http://openoffice.org/2000/script");
192 rstartEl("office:document", mxList.get());
193 mxList->clear();
195 makeMeta();
196 makeStyles();
197 makeAutoStyles();
198 makeMasterStyles();
199 makeBody();
201 rendEl("office:document");
203 if (m_rxDocumentHandler.is())
204 m_rxDocumentHandler->endDocument();
205 return true;
210 * make office:body
212 void HwpReader::makeBody()
214 rstartEl("office:body", mxList.get());
215 makeTextDecls();
216 HWPPara *hwppara = hwpfile.GetFirstPara();
217 d->bInBody = true;
218 parsePara(hwppara);
219 rendEl("office:body");
220 d->bInBody = false;
225 * make text decls
227 void HwpReader::makeTextDecls()
229 rstartEl("text:sequence-decls", mxList.get());
230 padd("text:display-outline-level", sXML_CDATA, "0");
231 padd("text:name", sXML_CDATA, "Illustration");
232 rstartEl("text:sequence-decl", mxList.get());
233 mxList->clear();
234 rendEl("text:sequence-decl");
235 padd("text:display-outline-level", sXML_CDATA, "0");
236 padd("text:name", sXML_CDATA, "Table");
237 rstartEl("text:sequence-decl", mxList.get());
238 mxList->clear();
239 rendEl("text:sequence-decl");
240 padd("text:display-outline-level", sXML_CDATA, "0");
241 padd("text:name", sXML_CDATA, "Text");
242 rstartEl("text:sequence-decl", mxList.get());
243 mxList->clear();
244 rendEl("text:sequence-decl");
245 padd("text:display-outline-level", sXML_CDATA, "0");
246 padd("text:name", sXML_CDATA, "Drawing");
247 rstartEl("text:sequence-decl", mxList.get());
248 mxList->clear();
249 rendEl("text:sequence-decl");
250 rendEl("text:sequence-decls");
254 #define ISNUMBER(x) ( (x) <= 0x39 && (x) >= 0x30 )
256 * make office:meta
257 * Completed
259 void HwpReader::makeMeta()
261 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
263 rstartEl("office:meta", mxList.get());
265 if (hwpinfo.summary.title[0])
267 rstartEl("dc:title", mxList.get());
268 rchars(fromHcharStringToOUString(hstr2ucsstr(hwpinfo.summary.title)));
269 rendEl("dc:title");
272 if (hwpinfo.summary.subject[0])
274 rstartEl("dc:subject", mxList.get());
275 rchars(fromHcharStringToOUString(hstr2ucsstr(hwpinfo.summary.subject)));
276 rendEl("dc:subject");
279 if (hwpinfo.summary.author[0])
281 rstartEl("meta:initial-creator", mxList.get());
282 rchars(fromHcharStringToOUString(hstr2ucsstr(hwpinfo.summary.author)));
283 rendEl("meta:initial-creator");
286 if (hwpinfo.summary.date[0])
288 unsigned short *pDate = hwpinfo.summary.date;
289 int year,month,day,hour,minute;
290 int gab = 0;
291 if( ISNUMBER( pDate[0] ) && ISNUMBER( pDate[1] ) &&
292 ISNUMBER( pDate[2] ) && ISNUMBER( pDate[3] ))
294 year = (pDate[0]-0x30) * 1000 + (pDate[1]-0x30) * 100 +
295 (pDate[2]-0x30) * 10 + (pDate[3]-0x30);
297 else {
298 year = 0;
300 if( ISNUMBER( pDate[6] ))
302 if( ISNUMBER( pDate[7] ) )
303 month = (pDate[6] - 0x30) * 10 + (pDate[6+ ++gab]-0x30);
304 else
305 month = (pDate[6] - 0x30);
307 else {
308 month = 0;
310 if( ISNUMBER( pDate[9 + gab] ) )
312 if( ISNUMBER( pDate[10 + gab])) {
313 day = ( pDate[9 + gab] - 0x30 ) * 10 + (pDate[9+ gab + 1]-0x30);
314 ++gab;
315 } else
316 day = (pDate[9+gab]-0x30);
318 else {
319 day = 0;
321 if( ISNUMBER( pDate[17 + gab] ) )
323 if( ISNUMBER( pDate[18 + gab])) {
324 hour = ( pDate[17 + gab] - 0x30 ) * 10 + (pDate[17+ gab + 1]-0x30);
325 ++gab;
326 } else
327 hour = (pDate[17+gab]-0x30);
329 else {
330 hour = 0;
332 if( ISNUMBER( pDate[20 + gab] ) )
334 if( ISNUMBER( pDate[21 + gab])) {
335 minute = ( pDate[20 + gab] - 0x30 ) * 10 + (pDate[20+ gab + 1]-0x30);
336 ++gab;
337 } else
338 minute = (pDate[20+gab]-0x30);
340 else {
341 minute = 0;
343 sprintf(buf,"%d-%02d-%02dT%02d:%02d:00",year,month,day,hour,minute);
345 rstartEl( "meta:creation-date", mxList.get() );
346 rchars( ascii(buf));
347 rendEl( "meta:creation-date" );
350 if (hwpinfo.summary.keyword[0][0] || hwpinfo.summary.etc[0][0])
352 rstartEl("meta:keywords", mxList.get());
353 if (hwpinfo.summary.keyword[0][0])
355 rstartEl("meta:keyword", mxList.get());
356 rchars(fromHcharStringToOUString(hstr2ucsstr(hwpinfo.summary.keyword[0])));
357 rendEl("meta:keyword");
359 if (hwpinfo.summary.keyword[1][0])
361 rstartEl("meta:keyword", mxList.get());
362 rchars(fromHcharStringToOUString(hstr2ucsstr(hwpinfo.summary.keyword[1])));
363 rendEl("meta:keyword");
365 if (hwpinfo.summary.etc[0][0])
367 rstartEl("meta:keyword", mxList.get());
368 rchars(fromHcharStringToOUString(hstr2ucsstr(hwpinfo.summary.etc[0])));
369 rendEl("meta:keyword");
371 if (hwpinfo.summary.etc[1][0])
373 rstartEl("meta:keyword", mxList.get());
374 rchars(fromHcharStringToOUString(hstr2ucsstr(hwpinfo.summary.etc[1])));
375 rendEl("meta:keyword");
377 if (hwpinfo.summary.etc[2][0])
379 rstartEl("meta:keyword", mxList.get());
380 rchars(fromHcharStringToOUString(hstr2ucsstr(hwpinfo.summary.etc[2])));
381 rendEl("meta:keyword");
383 rendEl("meta:keywords");
385 rendEl("office:meta");
389 static struct
391 const char *name;
392 bool bMade;
394 ArrowShape[] =
396 { "", false },
397 { "Arrow", false },
398 { "Line Arrow", false },
399 { "Square", false }
402 struct
404 double dots1;
405 double dots2;
406 double distance;
410 const LineStyle[] =
412 { 0.0, 0.0, 0.0 },
414 0.34, 0., 0.272
416 { 0.17, 0., 0.136},
418 0.612, 0.17, 0.136
420 { 0.85, 0.17, 0.136}
423 void HwpReader::makeDrawMiscStyle( HWPDrawingObject *hdo )
425 while( hdo )
427 if( hdo->child )
428 makeDrawMiscStyle( hdo->child.get() );
430 HWPDOProperty *prop = &hdo->property;
431 if( hdo->type == HWPDO_CONTAINER )
433 hdo = hdo->next.get();
434 continue;
437 if( prop->line_pstyle > 0 && prop->line_pstyle < 5 && prop->line_color <= 0xffffff)
439 padd( "draw:name", sXML_CDATA, ascii(Int2Str(hdo->index, "LineType%d", buf)));
440 padd( "draw:style", sXML_CDATA, "round");
441 padd( "draw:dots1", sXML_CDATA, "1");
442 padd( "draw:dots1-length", sXML_CDATA, Double2Str( LineStyle[prop->line_pstyle].dots1 * WTMM(prop->line_width) ) + "cm");
443 if( prop->line_pstyle == 3 )
445 padd( "draw:dots2", sXML_CDATA, "1");
446 padd( "draw:dots2-length", sXML_CDATA, Double2Str( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width) ) + "cm");
448 else if( prop->line_pstyle == 4 )
450 padd( "draw:dots2", sXML_CDATA, "2");
451 padd( "draw:dots2-length", sXML_CDATA, Double2Str( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width)) + "cm");
453 padd( "draw:distance", sXML_CDATA, Double2Str( LineStyle[prop->line_pstyle].distance * WTMM(prop->line_width)) + "cm");
454 rstartEl( "draw:stroke-dash", mxList.get());
455 mxList->clear();
456 rendEl( "draw:stroke-dash" );
459 if( hdo->type == HWPDO_LINE || hdo->type == HWPDO_ARC || hdo->type == HWPDO_FREEFORM ||
460 hdo->type == HWPDO_ADVANCED_ARC )
462 if( prop->line_tstyle && !ArrowShape[prop->line_tstyle].bMade )
464 ArrowShape[prop->line_tstyle].bMade = true;
465 padd("draw:name", sXML_CDATA,
466 ascii(ArrowShape[prop->line_tstyle].name));
467 if( prop->line_tstyle == 1 )
469 padd("svg:viewBox", sXML_CDATA, "0 0 20 30");
470 padd("svg:d", sXML_CDATA, "m10 0-10 30h20z");
472 else if( prop->line_tstyle == 2 )
474 padd("svg:viewBox", sXML_CDATA, "0 0 1122 2243");
475 padd("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");
477 else if( prop->line_tstyle == 3 )
479 padd("svg:viewBox", sXML_CDATA, "0 0 30 30");
480 padd("svg:d", sXML_CDATA, "m0 0h30v30h-30z");
482 rstartEl("draw:marker", mxList.get());
483 mxList->clear();
484 rendEl("draw:marker");
486 if( prop->line_hstyle && !ArrowShape[prop->line_hstyle].bMade)
488 ArrowShape[prop->line_hstyle].bMade = true;
489 padd("draw:name", sXML_CDATA,
490 ascii(ArrowShape[prop->line_hstyle].name));
491 if( prop->line_hstyle == 1 )
493 padd("svg:viewBox", sXML_CDATA, "0 0 20 30");
494 padd("svg:d", sXML_CDATA, "m10 0-10 30h20z");
496 else if( prop->line_hstyle == 2 )
498 padd("svg:viewBox", sXML_CDATA, "0 0 1122 2243");
499 padd("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");
501 else if( prop->line_hstyle == 3 )
503 padd("svg:viewBox", sXML_CDATA, "0 0 20 20");
504 padd("svg:d", sXML_CDATA, "m0 0h20v20h-20z");
506 rstartEl("draw:marker", mxList.get());
507 mxList->clear();
508 rendEl("draw:marker");
512 if( hdo->type != HWPDO_LINE )
514 if( prop->flag >> 18 & 0x01 )
516 padd( "draw:name", sXML_CDATA, ascii(Int2Str(hdo->index, "fillimage%d", buf)));
517 if( !prop->pictype )
519 padd( "xlink:href", sXML_CDATA,
520 fromHcharStringToOUString(hstr2ucsstr(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(prop->szPatternFile).c_str())).c_str())));
522 else
524 EmPicture *emp = nullptr;
525 if ( strlen( prop->szPatternFile ) > 3)
526 emp = hwpfile.GetEmPictureByName(prop->szPatternFile);
527 if( emp )
529 char filename[128+17+9];
530 char dirname[128];
531 int fd;
532 #ifdef _WIN32
533 GetTempPathA(sizeof(dirname), dirname);
534 sprintf(filename, "%s%s",dirname, emp->name);
535 if( (fd = open( filename , _O_CREAT | _O_WRONLY | _O_BINARY , 0666)) >= 0 )
536 #else
537 strcpy(dirname, "/tmp/");
538 sprintf(filename, "%s%s", dirname, emp->name);
539 if( (fd = open( filename , O_CREAT | O_WRONLY , 0666)) >= 0 )
540 #endif
542 size_t nWritten = write(fd, emp->data.get(), emp->size);
543 OSL_VERIFY(nWritten == emp->size);
544 close(fd);
546 #ifdef _WIN32
547 int j;
548 for(j = 0 ; j < static_cast<int>(strlen( dirname )) ; j++)
550 if( dirname[j] == '\\' ) buf[j] = '/';
551 else buf[j] = dirname[j];
553 buf[j] = '\0';
554 sprintf(filename, "file:///%s%s",buf, emp->name );
555 #else
556 sprintf(filename, "file://%s%s",dirname, emp->name );
557 #endif
558 padd( "xlink:href", sXML_CDATA, ascii(filename));
560 else
562 padd( "xlink:href", sXML_CDATA,
563 fromHcharStringToOUString(hstr2ucsstr(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(prop->szPatternFile).c_str())).c_str())));
567 padd( "xlink:type", sXML_CDATA, "simple");
568 padd( "xlink:show", sXML_CDATA, "embed");
569 padd( "xlink:actuate", sXML_CDATA, "onLoad");
571 rstartEl( "draw:fill-image", mxList.get());
572 mxList->clear();
573 rendEl( "draw:fill-image");
575 /* If there is a gradient, when a bitmap file is present, this is the first. */
576 else if( prop->flag >> 16 & 0x01 ) /* existence gradient */
578 padd( "draw:name", sXML_CDATA, ascii(Int2Str(hdo->index, "Grad%d", buf)));
579 switch( prop->gstyle )
581 case 1 :
582 if( prop->center_y == 50 )
583 padd( "draw:style", sXML_CDATA, "axial");
584 else
585 padd( "draw:style", sXML_CDATA, "linear");
586 break;
587 case 2:
588 case 3:
589 padd( "draw:style", sXML_CDATA, "radial");
590 break;
591 case 4:
592 padd( "draw:style", sXML_CDATA, "square");
593 break;
594 default:
595 padd( "draw:style", sXML_CDATA, "linear");
596 break;
598 padd( "draw:cx", sXML_CDATA,ascii(Int2Str(prop->center_x, "%d%%", buf)));
599 padd( "draw:cy", sXML_CDATA,ascii(Int2Str(prop->center_y, "%d%%", buf)));
601 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
602 int default_color = 0xffffff;
603 if( hwpinfo.back_info.isset )
605 if( hwpinfo.back_info.color[0] > 0 || hwpinfo.back_info.color[1] > 0
606 || hwpinfo.back_info.color[2] > 0 )
607 default_color = hwpinfo.back_info.color[0] << 16 |
608 hwpinfo.back_info.color[1] << 8 | hwpinfo.back_info.color[2];
611 if( prop->fromcolor > 0xffffff )
612 prop->fromcolor = default_color;
613 if( prop->tocolor > 0xffffff )
614 prop->tocolor = default_color;
616 if( prop->gstyle == 1)
618 if( prop->center_y == 100 )
620 sprintf( buf, "#%02x%02x%02x", prop->tocolor & 0xff,
621 (prop->tocolor >> 8) & 0xff, (prop->tocolor >>16) & 0xff );
622 padd( "draw:start-color", sXML_CDATA, ascii( buf ));
623 sprintf( buf, "#%02x%02x%02x", prop->fromcolor & 0xff,
624 (prop->fromcolor >> 8) & 0xff, (prop->fromcolor >>16) & 0xff );
625 padd( "draw:end-color", sXML_CDATA, ascii( buf ));
627 else
629 sprintf( buf, "#%02x%02x%02x", prop->fromcolor & 0xff,
630 (prop->fromcolor >> 8) & 0xff, (prop->fromcolor >>16) & 0xff );
631 padd( "draw:start-color", sXML_CDATA, ascii( buf ));
632 sprintf( buf, "#%02x%02x%02x", prop->tocolor & 0xff,
633 (prop->tocolor >> 8) & 0xff, (prop->tocolor >>16) & 0xff );
634 padd( "draw:end-color", sXML_CDATA, ascii( buf ));
637 else
639 sprintf( buf, "#%02x%02x%02x", prop->tocolor & 0xff,
640 (prop->tocolor >> 8) & 0xff, (prop->tocolor >>16) & 0xff );
641 padd( "draw:start-color", sXML_CDATA,ascii( buf ));
643 sprintf( buf, "#%02x%02x%02x", prop->fromcolor & 0xff,
644 (prop->fromcolor >> 8) & 0xff, (prop->fromcolor >>16) & 0xff );
645 padd( "draw:end-color", sXML_CDATA,ascii( buf ));
647 if( prop->angle > 0 && ( prop->gstyle == 1 || prop->gstyle == 4))
649 int angle = 1800 - prop->angle * 10;
650 padd( "draw:angle", sXML_CDATA,
651 ascii(Int2Str( angle, "%d", buf)));
653 rstartEl( "draw:gradient", mxList.get() );
654 mxList->clear();
655 rendEl( "draw:gradient");
657 /* hatch */
658 else if( prop->pattern_type >> 24 & 0x01 )
660 int type = prop->pattern_type & 0xffffff;
661 padd( "draw:name", sXML_CDATA,
662 ascii(Int2Str(hdo->index, "Hatch%d", buf)));
663 if( type < 4 )
664 padd( "draw:style", sXML_CDATA, "single" );
665 else
666 padd( "draw:style", sXML_CDATA, "double" );
667 sprintf( buf, "#%02x%02x%02x",
668 sal_uInt16(prop->pattern_color & 0xff),
669 sal_uInt16((prop->pattern_color >> 8) & 0xff),
670 sal_uInt16((prop->pattern_color >>16) & 0xff) );
671 padd( "draw:color", sXML_CDATA, ascii( buf ));
672 padd( "draw:distance", sXML_CDATA, "0.12cm");
673 switch( type )
675 case 0 :
676 case 4 :
677 padd( "draw:rotation", sXML_CDATA, "0");
678 break;
679 case 1 :
680 padd( "draw:rotation", sXML_CDATA, "900");
681 break;
682 case 2 :
683 padd( "draw:rotation", sXML_CDATA, "1350");
684 break;
685 case 3 :
686 case 5 :
687 padd( "draw:rotation", sXML_CDATA, "450");
688 break;
690 rstartEl( "draw:hatch", mxList.get());
691 mxList->clear();
692 rendEl( "draw:hatch");
695 hdo = hdo->next.get();
700 void HwpReader::makeStyles()
702 HWPStyle& hwpstyle = hwpfile.GetHWPStyle();
704 rstartEl("office:styles", mxList.get());
706 int i;
707 for (i = 0; i < hwpfile.getFBoxStyleCount(); i++)
709 if( hwpfile.getFBoxStyle(i)->boxtype == 'D' )
711 makeDrawMiscStyle(static_cast<HWPDrawingObject *>(hwpfile.getFBoxStyle(i)->cell) );
715 padd("style:name", sXML_CDATA, "Standard");
716 padd("style:family", sXML_CDATA, "paragraph");
717 padd("style:class", sXML_CDATA, "text");
718 rstartEl("style:style", mxList.get());
719 mxList->clear();
721 padd("fo:line-height", sXML_CDATA, "160%");
722 padd("fo:text-align", sXML_CDATA, "justify");
723 rstartEl("style:properties", mxList.get());
724 mxList->clear();
725 rstartEl("style:tab-stops", mxList.get());
727 for( i = 1 ; i < 40 ; i++)
729 padd("style:position", sXML_CDATA,
730 Double2Str( WTI(1000 * i)) + "inch");
731 rstartEl("style:tab-stop", mxList.get());
732 mxList->clear();
733 rendEl("style:tab-stop");
735 rendEl("style:tab-stops");
736 rendEl("style:properties");
738 rendEl("style:style");
740 for (int ii = 0; ii < hwpstyle.Num(); ii++)
742 unsigned char *stylename = reinterpret_cast<unsigned char *>(hwpstyle.GetName(ii));
743 padd("style:name", sXML_CDATA, fromHcharStringToOUString(hstr2ucsstr(kstr2hstr(stylename).c_str())));
744 padd("style:family", sXML_CDATA, "paragraph");
745 padd("style:parent-style-name", sXML_CDATA, "Standard");
747 rstartEl("style:style", mxList.get());
749 mxList->clear();
751 parseCharShape(hwpstyle.GetCharShape(ii));
752 parseParaShape(hwpstyle.GetParaShape(ii));
754 rstartEl("style:properties", mxList.get());
755 mxList->clear();
756 rendEl("style:properties");
758 rendEl("style:style");
762 padd( "style:name", sXML_CDATA, "Header");
763 padd( "style:family", sXML_CDATA, "paragraph");
764 padd( "style:parent-style-name", sXML_CDATA, "Standard");
765 padd( "style:class", sXML_CDATA, "extra");
766 rstartEl("style:style", mxList.get());
767 mxList->clear();
768 rendEl("style:style");
772 padd( "style:name", sXML_CDATA, "Footer");
773 padd( "style:family", sXML_CDATA, "paragraph");
774 padd( "style:parent-style-name", sXML_CDATA, "Standard");
775 padd( "style:class", sXML_CDATA, "extra");
776 rstartEl("style:style", mxList.get());
777 mxList->clear();
779 rendEl("style:style");
782 if( hwpfile.linenumber > 0)
784 padd( "style:name", sXML_CDATA, "Horizontal Line");
785 padd( "style:family", sXML_CDATA, "paragraph");
786 padd( "style:parent-style-name", sXML_CDATA, "Standard");
787 padd( "style:class", sXML_CDATA, "html");
788 rstartEl( "style:style", mxList.get());
789 mxList->clear();
790 padd( "fo:font-size", sXML_CDATA, "6pt");
791 padd( "fo:margin-top", sXML_CDATA, "0cm");
792 padd( "fo:margin-bottom", sXML_CDATA, "0cm");
793 padd( "style:border-line-width-bottom", sXML_CDATA, "0.02cm 0.035cm 0.002cm");
794 padd( "fo:padding", sXML_CDATA, "0cm");
795 padd( "fo:border-bottom", sXML_CDATA, "0.039cm double #808080");
796 padd( "text:number-lines", sXML_CDATA, "false");
797 padd( "text:line-number", sXML_CDATA, "0");
798 padd("fo:line-height", sXML_CDATA, "100%");
799 rstartEl( "style:properties", mxList.get());
800 mxList->clear();
801 rendEl( "style:properties");
802 rendEl( "style:style");
805 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
807 padd("text:num-suffix", sXML_CDATA, ")");
808 padd("text:num-format", sXML_CDATA, "1");
809 if( hwpinfo.beginfnnum != 1)
810 padd("text:offset", sXML_CDATA, ascii(Int2Str(hwpinfo.beginfnnum -1, "%d", buf)));
811 rstartEl("text:footnotes-configuration", mxList.get());
812 mxList->clear();
813 rendEl("text:footnotes-configuration");
815 rendEl("office:styles");
820 * parse automatic styles from hwpfile
821 * 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.
822 * 1. supports for the styles of paragraph, text, fbox, and page.
824 void HwpReader::makeAutoStyles()
826 int i;
828 rstartEl("office:automatic-styles", mxList.get());
830 for (i = 0; i < hwpfile.getParaShapeCount(); i++)
831 makePStyle(hwpfile.getParaShape(i));
833 for (i = 0; i < hwpfile.getCharShapeCount(); i++)
834 makeTStyle(hwpfile.getCharShape(i));
836 for( i = 0 ; i < hwpfile.getTableCount(); i++)
837 makeTableStyle(hwpfile.getTable(i));
839 for (i = 0; i < hwpfile.getFBoxStyleCount(); i++)
841 if( hwpfile.getFBoxStyle(i)->boxtype == 'D' )
842 makeDrawStyle(static_cast<HWPDrawingObject *>(hwpfile.getFBoxStyle(i)->cell), hwpfile.getFBoxStyle(i));
843 else
844 makeFStyle(hwpfile.getFBoxStyle(i));
847 bool bIsLeft = false, bIsMiddle = false, bIsRight = false;
848 for( i = 0 ; i < hwpfile.getPageNumberCount() ; i++ )
850 ShowPageNum *pn = hwpfile.getPageNumber(i);
851 if( pn->where == 7 || pn->where == 8 )
853 bIsLeft = true;
854 bIsRight = true;
856 else if( pn->where == 1 || pn->where == 4 )
858 bIsLeft = true;
860 else if( pn->where == 2 || pn->where == 5 )
862 bIsMiddle = true;
864 else if( pn->where == 3 || pn->where == 6 )
866 bIsRight = true;
870 for( i = 1; i <= 3 ; i++ )
872 if( i == 1 && !bIsLeft )
873 continue;
874 if( i == 2 && !bIsMiddle )
875 continue;
876 if( i == 3 && !bIsRight )
877 continue;
878 padd("style:name", sXML_CDATA,
879 ascii(Int2Str(i,"PNPara%d", buf)));
880 padd("style:family", sXML_CDATA, "paragraph");
881 padd("style:parent-style-name", sXML_CDATA, "Standard");
882 rstartEl("style:style", mxList.get());
883 mxList->clear();
884 if( i == 1 )
885 padd("fo:text-align", sXML_CDATA, "start");
886 else if ( i == 2 )
887 padd("fo:text-align", sXML_CDATA, "center");
888 else if ( i == 3 )
889 padd("fo:text-align", sXML_CDATA, "end");
890 rstartEl("style:properties", mxList.get());
891 mxList->clear();
892 rendEl( "style:properties");
893 rendEl( "style:style");
895 padd("style:name", sXML_CDATA, ascii(Int2Str(i,"PNBox%d",buf)));
896 padd("style:family", sXML_CDATA, "graphics");
897 rstartEl("style:style", mxList.get());
898 mxList->clear();
900 padd("fo:margin-top", sXML_CDATA, "0cm");
901 padd("fo:margin-bottom", sXML_CDATA, "0cm");
902 padd("style:wrap", sXML_CDATA, "run-through");
903 padd("style:vertical-pos", sXML_CDATA, "from-top");
904 padd("style:vertical-rel", sXML_CDATA, "paragraph");
906 if( i == 1 )
907 padd("style:horizontal-pos", sXML_CDATA, "left");
908 else if ( i == 2 )
909 padd("style:horizontal-pos", sXML_CDATA, "center");
910 else if ( i == 3 )
911 padd("style:horizontal-pos", sXML_CDATA, "right");
912 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
913 padd("fo:padding", sXML_CDATA, "0cm");
914 padd("stylefamily", sXML_CDATA, "graphics");
915 rstartEl("style:properties", mxList.get());
916 mxList->clear();
917 rendEl("style:properties");
918 rendEl("style:style");
921 for (i = 0; i < hwpfile.getDateFormatCount(); i++)
922 makeDateFormat(hwpfile.getDateCode(i));
924 makePageStyle();
926 rendEl("office:automatic-styles");
929 namespace {
931 struct PageSetting
933 PageSetting()
935 header = nullptr;
936 header_odd = nullptr;
937 header_even = nullptr;
938 footer = nullptr;
939 footer_odd = nullptr;
940 footer_even = nullptr;
941 pagenumber=nullptr;
942 bIsSet = false;
944 HeaderFooter *header ;
945 HeaderFooter *header_odd ;
946 HeaderFooter *header_even ;
947 HeaderFooter *footer ;
948 HeaderFooter *footer_odd ;
949 HeaderFooter *footer_even ;
950 ShowPageNum *pagenumber;
951 bool bIsSet;
956 void HwpReader::makeMasterStyles()
958 rstartEl("office:master-styles", mxList.get());
960 int i;
961 int nMax = hwpfile.getMaxSettedPage();
962 std::deque<PageSetting> aSet(nMax + 1);
964 for( i = 0 ; i < hwpfile.getPageNumberCount() ; i++ )
966 ShowPageNum *pn = hwpfile.getPageNumber(i);
967 aSet[pn->m_nPageNumber].pagenumber = pn;
968 aSet[pn->m_nPageNumber].bIsSet = true;
970 for( i = 0 ; i < hwpfile.getHeaderFooterCount() ; i++ )
972 HeaderFooter* hf = hwpfile.getHeaderFooter(i);
973 aSet[hf->m_nPageNumber].bIsSet = true;
974 if( hf->type == 0 ) // header
976 switch( hf->where )
978 case 0 :
979 aSet[hf->m_nPageNumber].header = hf;
980 aSet[hf->m_nPageNumber].header_even = nullptr;
981 aSet[hf->m_nPageNumber].header_odd = nullptr;
982 break;
983 case 1:
984 aSet[hf->m_nPageNumber].header_even = hf;
985 if( aSet[hf->m_nPageNumber].header )
987 aSet[hf->m_nPageNumber].header_odd =
988 aSet[hf->m_nPageNumber].header;
989 aSet[hf->m_nPageNumber].header = nullptr;
991 break;
992 case 2:
993 aSet[hf->m_nPageNumber].header_odd = hf;
994 if( aSet[hf->m_nPageNumber].header )
996 aSet[hf->m_nPageNumber].header_even =
997 aSet[hf->m_nPageNumber].header;
998 aSet[hf->m_nPageNumber].header = nullptr;
1000 break;
1003 else // footer
1005 switch( hf->where )
1007 case 0 :
1008 aSet[hf->m_nPageNumber].footer = hf;
1009 aSet[hf->m_nPageNumber].footer_even = nullptr;
1010 aSet[hf->m_nPageNumber].footer_odd = nullptr;
1011 break;
1012 case 1:
1013 aSet[hf->m_nPageNumber].footer_even = hf;
1014 if( aSet[hf->m_nPageNumber].footer )
1016 aSet[hf->m_nPageNumber].footer_odd =
1017 aSet[hf->m_nPageNumber].footer;
1018 aSet[hf->m_nPageNumber].footer = nullptr;
1020 break;
1021 case 2:
1022 aSet[hf->m_nPageNumber].footer_odd = hf;
1023 if( aSet[hf->m_nPageNumber].footer )
1025 aSet[hf->m_nPageNumber].footer_even =
1026 aSet[hf->m_nPageNumber].footer;
1027 aSet[hf->m_nPageNumber].footer = nullptr;
1029 break;
1034 PageSetting *pPrevSet = nullptr;
1035 PageSetting *pPage = nullptr;
1037 for( i = 1; i <= nMax ; i++ )
1039 if( i == 1 )
1040 padd("style:name", sXML_CDATA, "Standard");
1041 else
1042 padd("style:name", sXML_CDATA,
1043 ascii(Int2Str(i, "p%d", buf)));
1044 padd("style:page-master-name", sXML_CDATA,
1045 ascii(Int2Str(hwpfile.GetPageMasterNum(i), "pm%d", buf)));
1046 if( i < nMax )
1047 padd("style:next-style-name", sXML_CDATA,
1048 ascii(Int2Str(i+1, "p%d", buf)));
1049 padd("draw:style-name", sXML_CDATA,
1050 ascii(Int2Str(i, "master%d", buf)));
1051 rstartEl("style:master-page", mxList.get());
1052 mxList->clear();
1054 if( aSet[i].bIsSet ) /* If you've changed the current setting */
1056 if( !aSet[i].pagenumber ){
1057 if( pPrevSet && pPrevSet->pagenumber )
1058 aSet[i].pagenumber = pPrevSet->pagenumber;
1060 if( aSet[i].pagenumber )
1062 if( aSet[i].pagenumber->where == 7 && aSet[i].header )
1064 aSet[i].header_even = aSet[i].header;
1065 aSet[i].header_odd = aSet[i].header;
1066 aSet[i].header = nullptr;
1068 if( aSet[i].pagenumber->where == 8 && aSet[i].footer )
1070 aSet[i].footer_even = aSet[i].footer;
1071 aSet[i].footer_odd = aSet[i].footer;
1072 aSet[i].footer = nullptr;
1076 if( !aSet[i].header_even && pPrevSet && pPrevSet->header_even )
1078 aSet[i].header_even = pPrevSet->header_even;
1080 if( !aSet[i].header_odd && pPrevSet && pPrevSet->header_odd )
1082 aSet[i].header_odd = pPrevSet->header_odd;
1084 if( !aSet[i].footer_even && pPrevSet && pPrevSet->footer_even )
1086 aSet[i].footer_even = pPrevSet->footer_even;
1088 if( !aSet[i].footer_odd && pPrevSet && pPrevSet->footer_odd )
1090 aSet[i].footer_odd = pPrevSet->footer_odd;
1093 pPage = &aSet[i];
1094 pPrevSet = &aSet[i];
1096 else if( pPrevSet ) /* If the previous setting exists */
1098 pPage = pPrevSet;
1100 else /* If the previous settings doesn't exist, set to the default settings */
1102 rstartEl("style:header", mxList.get());
1103 padd("text:style-name", sXML_CDATA, "Standard");
1104 rstartEl("text:p", mxList.get());
1105 mxList->clear();
1106 rendEl("text:p");
1107 rendEl("style:header");
1109 rstartEl("style:footer", mxList.get());
1110 padd("text:style-name", sXML_CDATA, "Standard");
1111 rstartEl("text:p", mxList.get());
1112 mxList->clear();
1113 rendEl("text:p");
1114 rendEl("style:footer");
1116 rendEl("style:master-page");
1118 continue;
1120 // header
1121 if( pPage->header )
1123 rstartEl("style:header", mxList.get());
1124 if( pPage->pagenumber && pPage->pagenumber->where < 4 )
1126 d->bInHeader = true;
1127 d->pPn = pPage->pagenumber;
1129 parsePara(pPage->header->plist.front().get());
1130 d->bInHeader = false;
1131 d->pPn = nullptr;
1132 rendEl("style:header");
1134 if( pPage->header_even )
1136 rstartEl("style:header", mxList.get());
1137 if( pPage->pagenumber && ( pPage->pagenumber->where < 4
1138 || pPage->pagenumber->where == 7 ) )
1140 d->bInHeader = true;
1141 d->pPn = pPage->pagenumber;
1142 d->nPnPos = 3;
1144 parsePara(pPage->header_even->plist.front().get());
1145 d->bInHeader = false;
1146 d->pPn = nullptr;
1147 d->nPnPos = 0;
1148 rendEl("style:header");
1150 /* Will be the default. */
1151 else if (pPage->header_odd)
1153 rstartEl("style:header", mxList.get());
1154 padd("text:style-name", sXML_CDATA, "Standard");
1155 rstartEl("text:p", mxList.get());
1156 mxList->clear();
1157 if( pPage->pagenumber && ( pPage->pagenumber->where < 4 ||
1158 pPage->pagenumber->where == 7 ) )
1160 d->pPn = pPage->pagenumber;
1161 d->nPnPos = 3;
1162 makeShowPageNum();
1163 d->pPn = nullptr;
1164 d->nPnPos = 0;
1166 rendEl("text:p");
1167 rendEl("style:header");
1169 if( pPage->header_odd )
1171 rstartEl("style:header-left", mxList.get());
1172 if( pPage->pagenumber && ( pPage->pagenumber->where < 4
1173 || pPage->pagenumber->where == 7 ) )
1175 d->bInHeader = true;
1176 d->nPnPos = 1;
1177 d->pPn = pPage->pagenumber;
1179 parsePara(pPage->header_odd->plist.front().get());
1180 d->bInHeader = false;
1181 d->pPn = nullptr;
1182 d->nPnPos = 0;
1183 rendEl("style:header-left");
1185 /* Will be the default. */
1186 else if (pPage->header_even)
1188 rstartEl("style:header-left", mxList.get());
1189 padd("text:style-name", sXML_CDATA, "Standard");
1190 rstartEl("text:p", mxList.get());
1191 mxList->clear();
1192 if( pPage->pagenumber && ( pPage->pagenumber->where < 4 ||
1193 pPage->pagenumber->where == 7 ) )
1195 d->pPn = pPage->pagenumber;
1196 d->nPnPos = 1;
1197 makeShowPageNum();
1198 d->pPn = nullptr;
1199 d->nPnPos = 0;
1201 rendEl("text:p");
1202 rendEl("style:header-left");
1204 if( !pPage->header && !pPage->header_even && !pPage->header_odd )
1206 rstartEl("style:header", mxList.get());
1207 padd("text:style-name", sXML_CDATA, "Standard");
1208 rstartEl("text:p", mxList.get());
1209 mxList->clear();
1210 if( pPage->pagenumber && (pPage->pagenumber->where < 4 ||
1211 pPage->pagenumber->where == 7 ) )
1213 d->pPn = pPage->pagenumber;
1214 makeShowPageNum();
1215 d->pPn = nullptr;
1217 rendEl("text:p");
1218 rendEl("style:header");
1220 // footer
1221 if( pPage->footer )
1223 rstartEl("style:footer", mxList.get());
1224 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1225 && pPage->pagenumber->where != 7 )
1227 d->bInHeader = true;
1228 d->pPn = pPage->pagenumber;
1230 parsePara(pPage->footer->plist.front().get());
1231 d->bInHeader = false;
1232 d->pPn = nullptr;
1233 rendEl("style:footer");
1235 if( pPage->footer_even )
1237 rstartEl("style:footer", mxList.get());
1238 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1239 && pPage->pagenumber->where != 7 )
1241 d->bInHeader = true;
1242 d->pPn = pPage->pagenumber;
1243 d->nPnPos = 3;
1245 parsePara(pPage->footer_even->plist.front().get());
1246 d->bInHeader = false;
1247 d->pPn = nullptr;
1248 d->nPnPos = 0;
1249 rendEl("style:footer");
1251 /* Will be the default. */
1252 else if (pPage->footer_odd)
1254 rstartEl("style:footer", mxList.get());
1255 padd("text:style-name", sXML_CDATA, "Standard");
1256 rstartEl("text:p", mxList.get());
1257 mxList->clear();
1258 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1259 && pPage->pagenumber->where != 7 )
1261 d->pPn = pPage->pagenumber;
1262 d->nPnPos = 3;
1263 makeShowPageNum();
1264 d->pPn = nullptr;
1265 d->nPnPos = 0;
1267 rendEl("text:p");
1268 rendEl("style:footer");
1270 if( pPage->footer_odd )
1272 rstartEl("style:footer-left", mxList.get());
1273 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1274 && pPage->pagenumber->where != 7 )
1276 d->bInHeader = true;
1277 d->pPn = pPage->pagenumber;
1278 d->nPnPos = 1;
1280 parsePara(pPage->footer_odd->plist.front().get());
1281 d->bInHeader = false;
1282 d->pPn = nullptr;
1283 d->nPnPos = 0;
1284 rendEl("style:footer-left");
1286 /* Will be the default. */
1287 else if (pPage->footer_even)
1289 rstartEl("style:footer-left", mxList.get());
1290 padd("text:style-name", sXML_CDATA, "Standard");
1291 rstartEl("text:p", mxList.get());
1292 mxList->clear();
1293 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1294 && pPage->pagenumber->where != 7 )
1296 d->pPn = pPage->pagenumber;
1297 d->nPnPos = 1;
1298 makeShowPageNum();
1299 d->pPn = nullptr;
1300 d->nPnPos = 0;
1302 rendEl("text:p");
1303 rendEl("style:footer-left");
1305 if( !pPage->footer && !pPage->footer_even && !pPage->footer_odd )
1307 rstartEl("style:footer", mxList.get());
1308 padd("text:style-name", sXML_CDATA, "Standard");
1309 rstartEl("text:p", mxList.get());
1310 mxList->clear();
1311 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1312 && pPage->pagenumber->where != 7 )
1314 d->pPn = pPage->pagenumber;
1315 makeShowPageNum();
1316 d->pPn = nullptr;
1318 rendEl("text:p");
1319 rendEl("style:footer");
1322 rendEl("style:master-page");
1324 rendEl("office:master-styles");
1329 * Create the properties for text styles.
1330 * 1. fo:font-size, fo:font-family, fo:letter-spacing, fo:color,
1331 * style:text-background-color, fo:font-style, fo:font-weight,
1332 * style:text-underline,style:text-outline,fo:text-shadow,style:text-position
1333 * Support them.
1335 void HwpReader::parseCharShape(CharShape const * cshape)
1337 HWPFont& hwpfont = hwpfile.GetHWPFont();
1339 padd("fo:font-size", sXML_CDATA,
1340 ascii(Int2Str(cshape->size / 25, "%dpt", buf)));
1341 padd("style:font-size-asian", sXML_CDATA,
1342 ascii(Int2Str(cshape->size / 25, "%dpt", buf)));
1344 ::std::string const tmp = hstr2ksstr(kstr2hstr(
1345 reinterpret_cast<unsigned char const *>(hwpfont.GetFontName(0, cshape->font[0]))).c_str());
1346 double fRatio = 1.0;
1347 int size = getRepFamilyName(tmp.c_str(), buf, fRatio);
1349 padd("fo:font-family", sXML_CDATA,
1350 OUString(buf, size, RTL_TEXTENCODING_EUC_KR));
1351 padd("style:font-family-asian", sXML_CDATA,
1352 OUString(buf, size, RTL_TEXTENCODING_EUC_KR));
1354 padd("style:text-scale", sXML_CDATA,
1355 ascii(Int2Str(static_cast<int>(cshape->ratio[0] * fRatio), "%d%%", buf)));
1357 double sspace = (cshape->size / 25) * cshape->space[0] / 100.;
1359 if (sspace != 0.)
1361 padd("fo:letter-spacing", sXML_CDATA,
1362 Double2Str(sspace) + "pt");
1364 if (cshape->color[1] != 0)
1365 padd("fo:color", sXML_CDATA,
1366 ascii(hcolor2str(cshape->color[1], 100, buf, true)));
1367 if (cshape->shade != 0)
1368 padd("style:text-background-color", sXML_CDATA,
1369 ascii(hcolor2str(cshape->color[0], cshape->shade, buf)));
1370 if (cshape->attr & 0x01)
1372 padd("fo:font-style", sXML_CDATA, "italic");
1373 padd("style:font-style-asian", sXML_CDATA, "italic");
1375 else{
1376 padd("fo:font-style", sXML_CDATA, "normal");
1377 padd("style:font-style-asian", sXML_CDATA, "normal");
1379 if (cshape->attr >> 1 & 0x01)
1381 padd("fo:font-weight", sXML_CDATA, "bold");
1382 padd("style:font-weight-asian", sXML_CDATA, "bold");
1384 else{
1385 padd("fo:font-weight", sXML_CDATA, "normal");
1386 padd("style:font-weight-asian", sXML_CDATA, "normal");
1388 if (cshape->attr >> 2 & 0x01)
1389 padd("style:text-underline", sXML_CDATA, "single");
1390 if (cshape->attr >> 3 & 0x01)
1391 padd("style:text-outline", sXML_CDATA, "true");
1392 if (cshape->attr >> 4 & 0x01)
1393 padd("fo:text-shadow", sXML_CDATA, "1pt 1pt");
1394 if (cshape->attr >> 5 & 0x01)
1395 padd("style:text-position", sXML_CDATA, "super 58%");
1396 if (cshape->attr >> 6 & 0x01)
1397 padd("style:text-position", sXML_CDATA, "sub 58%");
1403 * Create the properties that correspond to the real Paragraph.
1404 * 1. fo:margin-left,fo:margin-right,fo:margin-top, fo:margin-bottom,
1405 * fo:text-indent, fo:line-height, fo:text-align, fo:border
1406 * are implemented.
1407 * TODO: Tab Settings => set values of properties only which doesn't have the default value
1409 void HwpReader::parseParaShape(ParaShape const * pshape)
1412 if (pshape->left_margin != 0)
1413 padd("fo:margin-left", sXML_CDATA, Double2Str
1414 (WTI(pshape->left_margin )) + "inch");
1415 if (pshape->right_margin != 0)
1416 padd("fo:margin-right", sXML_CDATA, Double2Str
1417 (WTI(pshape->right_margin)) + "inch");
1418 if (pshape->pspacing_prev != 0)
1419 padd("fo:margin-top", sXML_CDATA, Double2Str
1420 (WTI(pshape->pspacing_prev)) + "inch");
1421 if (pshape->pspacing_next != 0)
1422 padd("fo:margin-bottom", sXML_CDATA, Double2Str
1423 (WTI(pshape->pspacing_next)) + "inch");
1424 if (pshape->indent != 0)
1425 padd("fo:text-indent", sXML_CDATA, Double2Str
1426 (WTI(pshape->indent)) + "inch");
1427 if (pshape->lspacing != 0)
1428 padd("fo:line-height", sXML_CDATA,
1429 ascii(Int2Str (pshape->lspacing, "%d%%", buf)));
1431 unsigned char set_align = 0;
1433 switch (static_cast<int>(pshape->arrange_type))
1435 case 1:
1436 strcpy(buf, "start");
1437 set_align = 1;
1438 break;
1439 case 2:
1440 strcpy(buf, "end");
1441 set_align = 1;
1442 break;
1443 case 3:
1444 strcpy(buf, "center");
1445 set_align = 1;
1446 break;
1447 case 4:
1448 case 5:
1449 case 6:
1450 strcpy(buf, "justify");
1451 set_align = 1;
1452 break;
1455 if (set_align)
1456 padd("fo:text-align", sXML_CDATA, ascii(buf));
1458 if (pshape->outline)
1459 padd("fo:border", sXML_CDATA, "0.002cm solid #000000");
1460 if( pshape->shade > 0 )
1462 padd("fo:background-color", sXML_CDATA,
1463 ascii(hcolor2str(0, pshape->shade, buf)));
1466 if( pshape->pagebreak & 0x02 || pshape->pagebreak & 0x04)
1467 padd("fo:break-before", sXML_CDATA, "page");
1468 else if( pshape->pagebreak & 0x01 )
1469 padd("fo:break-before", sXML_CDATA, "column");
1475 * Make the style of the Paragraph.
1477 void HwpReader::makePStyle(ParaShape const * pshape)
1479 int nscount = pshape->tabs[MAXTABS -1].type;
1480 padd("style:name", sXML_CDATA,
1481 ascii(Int2Str(pshape->index, "P%d", buf)));
1482 padd("style:family", sXML_CDATA, "paragraph");
1483 rstartEl("style:style", mxList.get());
1484 mxList->clear();
1485 parseParaShape(pshape);
1486 parseCharShape(pshape->cshape.get());
1487 rstartEl("style:properties", mxList.get());
1488 mxList->clear();
1490 if( nscount )
1492 unsigned char tf = 0;
1493 rstartEl("style:tab-stops",mxList.get());
1495 int tab_margin = pshape->left_margin + pshape->indent;
1496 if( tab_margin < 0 )
1497 tab_margin = 0;
1498 for( int i = 0 ; i < MAXTABS -1 ; i++)
1500 if( i > 0 && pshape->tabs[i].position == 0. )
1501 break;
1502 if( pshape->tabs[i].position <= tab_margin )
1503 continue;
1504 padd("style:position", sXML_CDATA,
1505 Double2Str(WTMM(pshape->tabs[i].position - tab_margin )) + "mm");
1506 if( pshape->tabs[i].type )
1508 tf = 1;
1509 switch(pshape->tabs[i].type)
1511 case 1 :
1512 padd("style:type", sXML_CDATA, "right");
1513 break;
1514 case 2:
1515 padd("style:type", sXML_CDATA, "center");
1516 break;
1517 case 3:
1518 padd("style:type", sXML_CDATA, "char");
1519 padd("style:char", sXML_CDATA, ".");
1520 break;
1523 if( pshape->tabs[i].dot_continue )
1525 tf = 1;
1526 padd("style:leader-char", sXML_CDATA, ".");
1528 rstartEl( "style:tab-stop", mxList.get());
1529 mxList->clear();
1530 rendEl( "style:tab-stop" );
1532 if( (pshape->tabs[i].position != 1000 * i ) || tf )
1534 if( !--nscount ) break;
1537 rendEl( "style:tab-stops");
1539 rendEl("style:properties");
1540 rendEl("style:style");
1545 * Create a style for the page. This includes the header/footer, footnote and more.
1546 * TODO: fo: background-color (no information)
1548 void HwpReader::makePageStyle()
1550 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
1551 int pmCount = hwpfile.getColumnCount();
1553 for( int i = 0 ; i < pmCount ; i++ ){
1554 padd("style:name", sXML_CDATA, ascii(Int2Str(i + 1, "pm%d", buf)));
1555 rstartEl("style:page-master",mxList.get());
1556 mxList->clear();
1559 switch( hwpinfo.paper.paper_kind )
1561 case 3: // A4
1562 if( hwpinfo.paper.paper_direction )
1564 padd("fo:page-height",sXML_CDATA, "210mm");
1565 padd("fo:page-width",sXML_CDATA, "297mm");
1567 else
1569 padd("fo:page-width",sXML_CDATA, "210mm");
1570 padd("fo:page-height",sXML_CDATA, "297mm");
1572 break;
1573 case 4: // 80 column
1574 if( hwpinfo.paper.paper_direction )
1576 padd("fo:page-height",sXML_CDATA, "8.5inch");
1577 padd("fo:page-width",sXML_CDATA, "11inch");
1579 else
1581 padd("fo:page-width",sXML_CDATA, "8.5inch");
1582 padd("fo:page-height",sXML_CDATA, "11inch");
1584 break;
1585 case 5: // B5
1586 if( hwpinfo.paper.paper_direction )
1588 padd("fo:page-height",sXML_CDATA, "176mm");
1589 padd("fo:page-width",sXML_CDATA, "250mm");
1591 else
1593 padd("fo:page-width",sXML_CDATA, "176mm");
1594 padd("fo:page-height",sXML_CDATA, "250mm");
1596 break;
1597 case 6: // B4
1598 if( hwpinfo.paper.paper_direction )
1600 padd("fo:page-height",sXML_CDATA, "250mm");
1601 padd("fo:page-width",sXML_CDATA, "353mm");
1603 else
1605 padd("fo:page-width",sXML_CDATA, "250mm");
1606 padd("fo:page-height",sXML_CDATA, "353mm");
1608 break;
1609 case 7:
1610 if( hwpinfo.paper.paper_direction )
1612 padd("fo:page-height",sXML_CDATA, "8.5inch");
1613 padd("fo:page-width",sXML_CDATA, "14inch");
1615 else
1617 padd("fo:page-width",sXML_CDATA, "8.5inch");
1618 padd("fo:page-height",sXML_CDATA, "14inch");
1620 break;
1621 case 8:
1622 if( hwpinfo.paper.paper_direction )
1624 padd("fo:page-height",sXML_CDATA, "297mm");
1625 padd("fo:page-width",sXML_CDATA, "420mm");
1627 else
1629 padd("fo:page-width",sXML_CDATA, "297mm");
1630 padd("fo:page-height",sXML_CDATA, "420mm");
1632 break;
1633 case 0:
1634 case 1:
1635 case 2:
1636 default:
1637 if( hwpinfo.paper.paper_direction )
1639 padd("fo:page-width",sXML_CDATA,
1640 Double2Str(WTI(hwpinfo.paper.paper_height)) + "inch");
1641 padd("fo:page-height",sXML_CDATA,
1642 Double2Str(WTI(hwpinfo.paper.paper_width)) + "inch");
1644 else
1646 padd("fo:page-width",sXML_CDATA,
1647 Double2Str(WTI(hwpinfo.paper.paper_width)) + "inch");
1648 padd("fo:page-height",sXML_CDATA,
1649 Double2Str(WTI(hwpinfo.paper.paper_height)) + "inch");
1651 break;
1655 padd("style:print-orientation",sXML_CDATA,
1656 ascii(hwpinfo.paper.paper_direction ? "landscape" : "portrait"));
1657 if( hwpinfo.beginpagenum != 1)
1658 padd("style:first-page-number",sXML_CDATA,
1659 ascii(Int2Str(hwpinfo.beginpagenum, "%d", buf)));
1661 if( hwpinfo.borderline ){
1662 padd("fo:margin-left",sXML_CDATA,
1663 Double2Str(WTI(hwpinfo.paper.left_margin - hwpinfo.bordermargin[0] + hwpinfo.paper.gutter_length)) + "inch");
1664 padd("fo:margin-right",sXML_CDATA,
1665 Double2Str(WTI(hwpinfo.paper.right_margin - hwpinfo.bordermargin[1])) + "inch");
1666 padd("fo:margin-top",sXML_CDATA,
1667 Double2Str(WTI(hwpinfo.paper.top_margin - hwpinfo.bordermargin[2])) + "inch");
1668 padd("fo:margin-bottom",sXML_CDATA,
1669 Double2Str(WTI(hwpinfo.paper.bottom_margin - hwpinfo.bordermargin[3])) + "inch");
1671 else{
1672 padd("fo:margin-left",sXML_CDATA,
1673 Double2Str(WTI(hwpinfo.paper.left_margin + hwpinfo.paper.gutter_length)) + "inch");
1674 padd("fo:margin-right",sXML_CDATA,
1675 Double2Str(WTI(hwpinfo.paper.right_margin)) + "inch");
1676 padd("fo:margin-top",sXML_CDATA,
1677 Double2Str(WTI(hwpinfo.paper.top_margin)) + "inch");
1678 padd("fo:margin-bottom",sXML_CDATA,
1679 Double2Str(WTI(hwpinfo.paper.bottom_margin)) + "inch");
1682 switch( hwpinfo.borderline )
1684 case 1:
1685 padd("fo:border", sXML_CDATA,"0.002cm solid #000000");
1686 break;
1687 case 3:
1688 padd("fo:border", sXML_CDATA,"0.002cm dotted #000000");
1689 break;
1690 case 2:
1691 padd("fo:border", sXML_CDATA,"0.035cm solid #000000");
1692 break;
1693 case 4:
1694 padd("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1695 padd("fo:border", sXML_CDATA,"0.039cm double #000000");
1696 break;
1699 padd("fo:padding-left", sXML_CDATA,
1700 Double2Str(WTI(hwpinfo.bordermargin[0])) + "inch");
1701 padd("fo:padding-right", sXML_CDATA,
1702 Double2Str(WTI(hwpinfo.bordermargin[1])) + "inch");
1703 padd("fo:padding-top", sXML_CDATA,
1704 Double2Str(WTI(hwpinfo.bordermargin[2])) + "inch");
1705 padd("fo:padding-bottom", sXML_CDATA,
1706 Double2Str(WTI(hwpinfo.bordermargin[3])) + "inch");
1708 /* background color */
1709 if( hwpinfo.back_info.isset )
1711 if( hwpinfo.back_info.color[0] > 0 || hwpinfo.back_info.color[1] > 0
1712 || hwpinfo.back_info.color[2] > 0 ){
1713 sprintf(buf,"#%02x%02x%02x",hwpinfo.back_info.color[0],
1714 hwpinfo.back_info.color[1],hwpinfo.back_info.color[2] );
1715 padd("fo:background-color", sXML_CDATA, ascii(buf));
1719 rstartEl("style:properties",mxList.get());
1720 mxList->clear();
1722 /* background image */
1723 if( hwpinfo.back_info.isset && hwpinfo.back_info.type > 0 )
1725 if( hwpinfo.back_info.type == 1 ){
1726 #ifdef _WIN32
1727 padd("xlink:href", sXML_CDATA,
1728 fromHcharStringToOUString(hstr2ucsstr(kstr2hstr(reinterpret_cast<uchar const *>(urltowin(hwpinfo.back_info.filename).c_str())).c_str())));
1729 #else
1730 padd("xlink:href", sXML_CDATA,
1731 fromHcharStringToOUString(hstr2ucsstr(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(hwpinfo.back_info.filename).c_str())).c_str())));
1732 #endif
1733 padd("xlink:type", sXML_CDATA, "simple");
1734 padd("xlink:actuate", sXML_CDATA, "onLoad");
1736 if( hwpinfo.back_info.flag >= 2)
1737 padd("style:repeat", sXML_CDATA, "stretch");
1738 else if( hwpinfo.back_info.flag == 1 ){
1739 padd("style:repeat", sXML_CDATA, "no-repeat");
1740 padd("style:position", sXML_CDATA, "center");
1742 rstartEl("style:background-image",mxList.get());
1744 if( hwpinfo.back_info.type == 2 ){
1745 rstartEl("office:binary-data", mxList.get());
1746 mxList->clear();
1747 std::shared_ptr<char> pStr(base64_encode_string(reinterpret_cast<unsigned char *>(hwpinfo.back_info.data.data()), hwpinfo.back_info.size ), Free<char>());
1748 rchars(ascii(pStr.get()));
1749 rendEl("office:binary-data");
1751 rendEl("style:background-image");
1754 makeColumns( hwpfile.GetColumnDef(i) );
1756 rendEl("style:properties");
1758 /* header style */
1759 rstartEl("style:header-style", mxList.get());
1760 padd("svg:height", sXML_CDATA,
1761 Double2Str(WTI(hwpinfo.paper.header_length)) + "inch");
1762 padd("fo:margin-bottom", sXML_CDATA, "0mm");
1764 rstartEl("style:properties",mxList.get());
1765 mxList->clear();
1766 rendEl("style:properties");
1767 rendEl("style:header-style");
1769 /* footer style */
1770 rstartEl("style:footer-style", mxList.get());
1771 padd("svg:height", sXML_CDATA,
1772 Double2Str(WTI(hwpinfo.paper.footer_length)) + "inch");
1773 padd("fo:margin-top", sXML_CDATA, "0mm");
1774 rstartEl("style:properties",mxList.get());
1775 mxList->clear();
1776 rendEl("style:properties");
1777 rendEl("style:footer-style");
1779 /* Footnote style */
1780 rstartEl("style:page-layout-properties", mxList.get());
1782 padd("style:distance-before-sep", sXML_CDATA,
1783 Double2Str(WTI(hwpinfo.splinetext)) + "inch");
1784 padd("style:distance-after-sep", sXML_CDATA,
1785 Double2Str(WTI(hwpinfo.splinefn)) + "inch");
1786 rstartEl("style:properties",mxList.get());
1787 mxList->clear();
1788 rendEl("style:properties");
1789 if ( hwpinfo.fnlinetype == 2 )
1790 padd("style:width", sXML_CDATA, "15cm");
1791 else if ( hwpinfo.fnlinetype == 1)
1792 padd("style:width", sXML_CDATA, "2cm");
1793 else if ( hwpinfo.fnlinetype == 3)
1794 padd("style:width", sXML_CDATA, "0cm");
1795 else
1796 padd("style:width", sXML_CDATA, "5cm");
1798 rstartEl("style:footnote-sep",mxList.get());
1799 mxList->clear();
1800 rendEl("style:footnote-sep");
1802 rendEl("style:page-layout-properties");
1804 rendEl("style:page-master");
1808 void HwpReader::makeColumns(ColumnDef const *coldef)
1810 if( !coldef ) return;
1811 padd("fo:column-count", sXML_CDATA, ascii(Int2Str(coldef->ncols, "%d", buf)));
1812 rstartEl("style:columns",mxList.get());
1813 mxList->clear();
1814 if( coldef->separator != 0 )
1816 switch( coldef->separator )
1818 case 1: /* thin line */
1819 padd("style:width", sXML_CDATA, "0.02mm");
1820 [[fallthrough]];
1821 case 3: /* dotted line */
1822 padd("style:style", sXML_CDATA, "dotted");
1823 padd("style:width", sXML_CDATA, "0.02mm");
1824 break;
1825 case 2: /* thick line */
1826 case 4: /* double line */
1827 padd("style:width", sXML_CDATA, "0.35mm");
1828 break;
1829 case 0: /* None */
1830 default:
1831 padd("style:style", sXML_CDATA, "none");
1832 break;
1834 rstartEl("style:column-sep",mxList.get());
1835 mxList->clear();
1836 rendEl("style:column-sep");
1838 double spacing = WTI(coldef->spacing)/ 2. ;
1839 for(int ii = 0 ; ii < coldef->ncols ; ii++)
1841 if( ii == 0 )
1842 padd("fo:margin-left", sXML_CDATA, "0mm");
1843 else
1844 padd("fo:margin-left", sXML_CDATA,
1845 Double2Str( spacing) + "inch");
1846 if( ii == ( coldef->ncols -1) )
1847 padd("fo:margin-right", sXML_CDATA,"0mm");
1848 else
1849 padd("fo:margin-right", sXML_CDATA,
1850 Double2Str( spacing) + "inch");
1851 rstartEl("style:column",mxList.get());
1852 mxList->clear();
1853 rendEl("style:column");
1855 rendEl("style:columns");
1858 void HwpReader::makeTStyle(CharShape const * cshape)
1860 padd("style:name", sXML_CDATA,
1861 ascii(Int2Str(cshape->index, "T%d", buf)));
1862 padd("style:family", sXML_CDATA, "text");
1863 rstartEl("style:style", mxList.get());
1864 mxList->clear();
1865 parseCharShape(cshape);
1866 rstartEl("style:properties", mxList.get());
1867 mxList->clear();
1868 rendEl("style:properties");
1869 rendEl("style:style");
1873 void HwpReader::makeTableStyle(Table *tbl)
1875 // table
1876 TxtBox *hbox = tbl->box;
1878 padd("style:name", sXML_CDATA,
1879 ascii(Int2Str(hbox->style.boxnum, "Table%d", buf)));
1880 padd("style:family", sXML_CDATA,"table");
1881 rstartEl("style:style", mxList.get());
1882 mxList->clear();
1883 padd("style:width", sXML_CDATA,
1884 Double2Str(WTMM(hbox->box_xs)) + "mm");
1885 padd("table:align", sXML_CDATA,"left");
1886 padd("fo:keep-with-next", sXML_CDATA,"false");
1887 rstartEl("style:properties", mxList.get());
1888 mxList->clear();
1889 rendEl("style:properties");
1890 rendEl("style:style");
1892 // column
1893 for (size_t i = 0 ; i < tbl->columns.nCount -1 ; i++)
1895 sprintf(buf,"Table%d.%c",hbox->style.boxnum, static_cast<char>('A'+i));
1896 padd("style:name", sXML_CDATA, ascii( buf ));
1897 padd("style:family", sXML_CDATA,"table-column");
1898 rstartEl("style:style", mxList.get());
1899 mxList->clear();
1900 padd("style:column-width", sXML_CDATA,
1901 Double2Str(WTMM(tbl->columns.data[i+1] - tbl->columns.data[i])) + "mm");
1902 rstartEl("style:properties", mxList.get());
1903 mxList->clear();
1904 rendEl("style:properties");
1905 rendEl("style:style");
1908 // row
1909 for (size_t i = 0 ; i < tbl->rows.nCount -1 ; i++)
1911 sprintf(buf,"Table%d.row%" SAL_PRI_SIZET "u",hbox->style.boxnum, i + 1);
1912 padd("style:name", sXML_CDATA, ascii( buf ));
1913 padd("style:family", sXML_CDATA,"table-row");
1914 rstartEl("style:style", mxList.get());
1915 mxList->clear();
1916 padd("style:row-height", sXML_CDATA,
1917 Double2Str(WTMM(tbl->rows.data[i+1] - tbl->rows.data[i])) + "mm");
1918 rstartEl("style:properties", mxList.get());
1919 mxList->clear();
1920 rendEl("style:properties");
1921 rendEl("style:style");
1924 // cell
1925 for (auto const& tcell : tbl->cells)
1927 sprintf(buf,"Table%d.%c%d",hbox->style.boxnum, 'A'+ tcell->nColumnIndex, tcell->nRowIndex +1);
1928 padd("style:name", sXML_CDATA, ascii( buf ));
1929 padd("style:family", sXML_CDATA,"table-cell");
1930 rstartEl("style:style", mxList.get());
1931 mxList->clear();
1932 Cell *cl = tcell->pCell;
1933 if( cl->ver_align == 1 )
1934 padd("fo:vertical-align", sXML_CDATA,"middle");
1936 if(cl->linetype[2] == cl->linetype[3] && cl->linetype[2] == cl->linetype[0]
1937 && cl->linetype[2] == cl->linetype[1])
1939 switch( cl->linetype[2] )
1941 case 1: /* A thin solid line */
1942 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1943 padd("fo:border", sXML_CDATA,"0.002cm solid #000000");
1944 break;
1945 case 2: /* Bold lines */
1946 padd("fo:border", sXML_CDATA,"0.035cm solid #000000");
1947 break;
1948 case 4: /* Double line */
1949 padd("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1950 padd("fo:border", sXML_CDATA,"0.039cm double #000000");
1951 break;
1954 else
1956 switch( cl->linetype[0] )
1958 case 1: /* A thin solid line */
1959 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1960 padd("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
1961 break;
1962 case 2: /* Bold lines */
1963 padd("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
1964 break;
1965 case 4: /* Double line */
1966 padd("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1967 padd("fo:border-left", sXML_CDATA,"0.039cm double #000000");
1968 break;
1970 switch( cl->linetype[1] )
1972 case 1: /* A thin solid line */
1973 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1974 padd("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
1975 break;
1976 case 2: /* Bold lines */
1977 padd("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
1978 break;
1979 case 4: /* Double line */
1980 padd("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1981 padd("fo:border-right", sXML_CDATA,"0.039cm double #000000");
1982 break;
1984 switch( cl->linetype[2] )
1986 case 1: /* A thin solid line */
1987 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1988 padd("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
1989 break;
1990 case 2: /* Bold lines */
1991 padd("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
1992 break;
1993 case 4: /* Double line */
1994 padd("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1995 padd("fo:border-top", sXML_CDATA,"0.039cm double #000000");
1996 break;
1998 switch( cl->linetype[3] )
2000 case 1: /* A thin solid line */
2001 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2002 padd("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
2003 break;
2004 case 2: /* Bold lines */
2005 padd("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
2006 break;
2007 case 4: /* Double line */
2008 padd("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2009 padd("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
2010 break;
2013 if(cl->shade != 0)
2014 padd("fo:background-color", sXML_CDATA,
2015 ascii(hcolor2str(sal::static_int_cast<uchar>(cl->color),
2016 sal::static_int_cast<uchar>(cl->shade), buf)));
2018 rstartEl("style:properties", mxList.get());
2019 mxList->clear();
2020 rendEl("style:properties");
2022 rendEl("style:style");
2027 void HwpReader::makeDrawStyle( HWPDrawingObject * hdo, FBoxStyle * fstyle)
2029 while( hdo )
2031 padd("style:name", sXML_CDATA,
2032 ascii(Int2Str(hdo->index, "Draw%d", buf)));
2033 padd("style:family", sXML_CDATA, "graphics");
2035 rstartEl("style:style", mxList.get());
2036 mxList->clear();
2038 switch (fstyle->txtflow)
2040 case 0:
2041 break;
2042 case 1:
2043 padd("style:wrap", sXML_CDATA, "run-through");
2044 break;
2045 case 2:
2046 padd("style:wrap", sXML_CDATA, "dynamic");
2047 break;
2049 tools::Long color;
2050 // invisible line
2051 if( hdo->property.line_color > 0xffffff )
2053 padd("draw:stroke", sXML_CDATA, "none" );
2055 else
2058 if( hdo->property.line_pstyle == 0 )
2059 padd("draw:stroke", sXML_CDATA, "solid" );
2060 else if( hdo->property.line_pstyle < 5 )
2062 padd("draw:stroke", sXML_CDATA, "dash" );
2063 padd("draw:stroke-dash", sXML_CDATA,
2064 ascii(Int2Str(hdo->index, "LineType%d", buf)));
2066 padd("svg:stroke-width", sXML_CDATA,
2067 Double2Str( WTMM(hdo->property.line_width)) + "mm");
2068 color = hdo->property.line_color;
2069 sprintf( buf, "#%02x%02x%02x",
2070 sal_uInt16(color & 0xff),
2071 sal_uInt16((color >> 8) & 0xff),
2072 sal_uInt16((color >>16) & 0xff) );
2073 padd("svg:stroke-color", sXML_CDATA, ascii( buf) );
2076 if( hdo->type == HWPDO_LINE || hdo->type == HWPDO_ARC ||
2077 hdo->type == HWPDO_FREEFORM || hdo->type == HWPDO_ADVANCED_ARC )
2080 if( hdo->property.line_tstyle > 0 )
2082 padd("draw:marker-start", sXML_CDATA,
2083 ascii(ArrowShape[hdo->property.line_tstyle].name) );
2084 if( hdo->property.line_width > 100 )
2085 padd("draw:marker-start-width", sXML_CDATA,
2086 Double2Str( WTMM(hdo->property.line_width * 3)) + "mm");
2087 else if( hdo->property.line_width > 80 )
2088 padd("draw:marker-start-width", sXML_CDATA,
2089 Double2Str( WTMM(hdo->property.line_width * 4)) + "mm");
2090 else if( hdo->property.line_width > 60 )
2091 padd("draw:marker-start-width", sXML_CDATA,
2092 Double2Str( WTMM(hdo->property.line_width * 5)) + "mm");
2093 else if( hdo->property.line_width > 40 )
2094 padd("draw:marker-start-width", sXML_CDATA,
2095 Double2Str( WTMM(hdo->property.line_width * 6)) + "mm");
2096 else
2097 padd("draw:marker-start-width", sXML_CDATA,
2098 Double2Str( WTMM(hdo->property.line_width * 7)) + "mm");
2101 if( hdo->property.line_hstyle > 0 )
2103 padd("draw:marker-end", sXML_CDATA,
2104 ascii(ArrowShape[hdo->property.line_hstyle].name) );
2105 if( hdo->property.line_width > 100 )
2106 padd("draw:marker-end-width", sXML_CDATA,
2107 Double2Str( WTMM(hdo->property.line_width * 3)) + "mm");
2108 else if( hdo->property.line_width > 80 )
2109 padd("draw:marker-end-width", sXML_CDATA,
2110 Double2Str( WTMM(hdo->property.line_width * 4)) + "mm");
2111 else if( hdo->property.line_width > 60 )
2112 padd("draw:marker-end-width", sXML_CDATA,
2113 Double2Str( WTMM(hdo->property.line_width * 5)) + "mm");
2114 else if( hdo->property.line_width > 40 )
2115 padd("draw:marker-end-width", sXML_CDATA,
2116 Double2Str( WTMM(hdo->property.line_width * 6)) + "mm");
2117 else
2118 padd("draw:marker-end-width", sXML_CDATA,
2119 Double2Str( WTMM(hdo->property.line_width * 7)) + "mm");
2123 if(hdo->type != HWPDO_LINE )
2125 if( hdo->property.flag >> 19 & 0x01 )
2127 padd( "draw:textarea-horizontal-align", sXML_CDATA, "center");
2130 color = hdo->property.fill_color;
2132 if( hdo->property.flag >> 18 & 0x01 ) // bitmap pattern
2134 padd("draw:fill", sXML_CDATA, "bitmap");
2135 padd("draw:fill-image-name", sXML_CDATA,
2136 ascii(Int2Str(hdo->index, "fillimage%d", buf)));
2137 // bitmap resizing
2138 if( hdo->property.flag >> 3 & 0x01 )
2140 padd("style:repeat", sXML_CDATA, "stretch");
2142 else
2144 padd("style:repeat", sXML_CDATA, "repeat");
2145 padd("draw:fill-image-ref-point", sXML_CDATA, "top-left");
2147 if( hdo->property.flag >> 20 & 0x01 )
2149 if( hdo->property.luminance > 0 )
2151 padd("draw:transparency", sXML_CDATA,
2152 ascii(Int2Str(hdo->property.luminance, "%d%%", buf)));
2157 // Gradation
2158 else if( hdo->property.flag >> 16 & 0x01 )
2160 padd("draw:fill", sXML_CDATA, "gradient");
2161 padd("draw:fill-gradient-name", sXML_CDATA,
2162 ascii(Int2Str(hdo->index, "Grad%d", buf)));
2163 padd("draw:gradient-step-count", sXML_CDATA,
2164 ascii(Int2Str(hdo->property.nstep, "%d", buf)));
2167 // Hatching
2168 else if( hdo->property.pattern_type >> 24 & 0x01 )
2170 padd("draw:fill", sXML_CDATA, "hatch");
2171 padd("draw:fill-hatch-name", sXML_CDATA,
2172 ascii(Int2Str(hdo->index, "Hatch%d", buf)));
2173 if( color < 0xffffff )
2175 sprintf( buf, "#%02x%02x%02x",
2176 sal_uInt16(color & 0xff),
2177 sal_uInt16((color >> 8) & 0xff),
2178 sal_uInt16((color >>16) & 0xff) );
2179 padd("draw:fill-color", sXML_CDATA, ascii( buf) );
2180 padd("draw:fill-hatch-solid", sXML_CDATA, "true");
2183 else if( color <= 0xffffff )
2185 padd("draw:fill", sXML_CDATA, "solid");
2186 sprintf( buf, "#%02x%02x%02x",
2187 sal_uInt16(color & 0xff),
2188 sal_uInt16((color >> 8) & 0xff),
2189 sal_uInt16((color >>16) & 0xff) );
2190 padd("draw:fill-color", sXML_CDATA, ascii( buf) );
2192 else
2193 padd("draw:fill", sXML_CDATA, "none");
2196 if( fstyle->anchor_type == CHAR_ANCHOR )
2198 padd("style:vertical-pos", sXML_CDATA, "top");
2199 padd("style:vertical-rel", sXML_CDATA, "baseline");
2202 rstartEl("style:properties", mxList.get());
2203 mxList->clear();
2204 rendEl("style:properties");
2205 rendEl("style:style");
2207 if( hdo->type == 0 )
2209 makeDrawStyle( hdo->child.get(), fstyle );
2211 hdo = hdo->next.get();
2216 void HwpReader::makeCaptionStyle(FBoxStyle * fstyle)
2218 padd("style:name", sXML_CDATA,
2219 ascii(Int2Str(fstyle->boxnum, "CapBox%d", buf)));
2220 padd("style:family", sXML_CDATA, "graphics");
2221 rstartEl("style:style", mxList.get());
2222 mxList->clear();
2223 padd("fo:margin-left", sXML_CDATA, "0cm");
2224 padd("fo:margin-right", sXML_CDATA, "0cm");
2225 padd("fo:margin-top", sXML_CDATA, "0cm");
2226 padd("fo:margin-bottom", sXML_CDATA, "0cm");
2227 padd("fo:padding", sXML_CDATA, "0cm");
2228 switch (fstyle->txtflow)
2230 case 0:
2231 padd("style:wrap", sXML_CDATA, "none");
2232 break;
2233 case 1:
2234 if( fstyle->boxtype == 'G' )
2235 padd("style:run-through", sXML_CDATA, "background");
2236 padd("style:wrap", sXML_CDATA, "run-through");
2237 break;
2238 case 2:
2239 padd("style:wrap", sXML_CDATA, "dynamic");
2240 break;
2242 if (fstyle->anchor_type == CHAR_ANCHOR)
2244 padd("style:vertical-pos", sXML_CDATA, "top");
2245 padd("style:vertical-rel", sXML_CDATA, "baseline");
2246 padd("style:horizontal-pos", sXML_CDATA, "center");
2247 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
2249 else
2252 switch (-(fstyle->xpos))
2254 case 2:
2255 padd("style:horizontal-pos", sXML_CDATA, "right");
2256 break;
2257 case 3:
2258 padd("style:horizontal-pos", sXML_CDATA, "center");
2259 break;
2260 case 1:
2261 default:
2262 padd("style:horizontal-pos", sXML_CDATA, "from-left");
2263 break;
2265 switch (-(fstyle->ypos))
2267 case 2:
2268 padd("style:vertical-pos", sXML_CDATA, "bottom");
2269 break;
2270 case 3:
2271 padd("style:vertical-pos", sXML_CDATA, "middle");
2272 break;
2273 case 1:
2274 default:
2275 padd("style:vertical-pos", sXML_CDATA, "from-top");
2276 break;
2278 if ( fstyle->anchor_type == PARA_ANCHOR )
2280 padd("style:vertical-rel", sXML_CDATA, "paragraph");
2281 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
2283 else
2285 padd("style:vertical-rel", sXML_CDATA, "page-content");
2286 padd("style:horizontal-rel", sXML_CDATA, "page-content");
2289 rstartEl("style:properties", mxList.get());
2290 mxList->clear();
2291 rendEl("style:properties");
2292 rendEl("style:style");
2293 if( fstyle->boxtype == 'G' )
2295 padd("style:name", sXML_CDATA,
2296 ascii(Int2Str(fstyle->boxnum, "G%d", buf)));
2298 else
2300 padd("style:name", sXML_CDATA,
2301 ascii(Int2Str(fstyle->boxnum, "Txtbox%d", buf)));
2304 padd("style:family", sXML_CDATA, "graphics");
2305 rstartEl("style:style", mxList.get());
2306 mxList->clear();
2308 padd("fo:margin-left", sXML_CDATA, "0cm");
2309 padd("fo:margin-right", sXML_CDATA, "0cm");
2310 padd("fo:margin-top", sXML_CDATA, "0cm");
2311 padd("fo:margin-bottom", sXML_CDATA, "0cm");
2312 padd("fo:padding", sXML_CDATA, "0cm");
2313 padd("style:wrap", sXML_CDATA, "none");
2314 padd("style:vertical-pos", sXML_CDATA, "from-top");
2315 padd("style:vertical-rel", sXML_CDATA, "paragraph");
2316 padd("style:horizontal-pos", sXML_CDATA, "from-left");
2317 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
2318 if( fstyle->boxtype == 'G' )
2320 char *cell = static_cast<char *>(fstyle->cell);
2321 padd("draw:luminance", sXML_CDATA,
2322 ascii(Int2Str(cell[0], "%d%%", buf)));
2323 padd("draw:contrast", sXML_CDATA,
2324 ascii(Int2Str(cell[1], "%d%%", buf)));
2325 if( cell[2] == 0 )
2326 padd("draw:color-mode", sXML_CDATA, "standard");
2327 else if( cell[2] == 1 )
2328 padd("draw:color-mode", sXML_CDATA, "greyscale");
2329 else if( cell[2] == 2 )
2330 padd("draw:color-mode", sXML_CDATA, "mono");
2332 else
2334 Cell *cell = static_cast<Cell *>(fstyle->cell);
2335 if(cell->linetype[0] == cell->linetype[1] &&
2336 cell->linetype[0] == cell->linetype[2] &&
2337 cell->linetype[0] == cell->linetype[3])
2339 switch( cell->linetype[0] )
2341 case 0:
2342 padd("fo:padding", sXML_CDATA,"0mm");
2343 break;
2344 case 1: /* A thin solid line */
2345 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2346 padd("fo:border", sXML_CDATA,"0.002cm solid #000000");
2347 break;
2348 case 2: /* Bold lines */
2349 padd("fo:border", sXML_CDATA,"0.035cm solid #000000");
2350 break;
2351 case 4: /* Double line */
2352 padd("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2353 padd("fo:border", sXML_CDATA,"0.039cm double #000000");
2354 break;
2357 else
2359 switch( cell->linetype[0] )
2361 case 1: /* A thin solid line */
2362 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2363 padd("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
2364 break;
2365 case 2: /* Bold lines */
2366 padd("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
2367 break;
2368 case 4: /* Double line */
2369 padd("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2370 padd("fo:border-left", sXML_CDATA,"0.039cm double #000000");
2371 break;
2373 switch( cell->linetype[1] )
2375 case 1: /* A thin solid line */
2376 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2377 padd("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
2378 break;
2379 case 2: /* Bold lines */
2380 padd("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
2381 break;
2382 case 4: /* Double line */
2383 padd("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2384 padd("fo:border-right", sXML_CDATA,"0.039cm double #000000");
2385 break;
2387 switch( cell->linetype[2] )
2389 case 1: /* A thin solid line */
2390 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2391 padd("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
2392 break;
2393 case 2: /* Bold lines */
2394 padd("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
2395 break;
2396 case 4: /* Double line */
2397 padd("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2398 padd("fo:border-top", sXML_CDATA,"0.039cm double #000000");
2399 break;
2401 switch( cell->linetype[3] )
2403 case 1: /* A thin solid line */
2404 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2405 padd("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
2406 break;
2407 case 2: /* Bold lines */
2408 padd("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
2409 break;
2410 case 4: /* Double line */
2411 padd("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2412 padd("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
2413 break;
2416 if(cell->shade != 0)
2417 padd("fo:background-color", sXML_CDATA, ascii(hcolor2str(
2418 sal::static_int_cast<uchar>(cell->color),
2419 sal::static_int_cast<uchar>(cell->shade), buf)));
2421 rstartEl("style:properties", mxList.get());
2422 mxList->clear();
2423 rendEl("style:properties");
2424 rendEl("style:style");
2429 * Create a style for the Floating objects.
2431 void HwpReader::makeFStyle(FBoxStyle * fstyle)
2433 /* caption exist */
2434 if( ( fstyle->boxtype == 'G' || fstyle->boxtype == 'X' ) && fstyle->cap_len > 0 )
2436 makeCaptionStyle(fstyle);
2437 return;
2439 switch( fstyle->boxtype )
2441 case 'X' : // txtbox
2442 case 'E' : // equation
2443 case 'B' : // button
2444 case 'O' : // other
2445 case 'T' : // table
2446 padd("style:name", sXML_CDATA,
2447 ascii(Int2Str(fstyle->boxnum, "Txtbox%d", buf)));
2448 padd("style:family", sXML_CDATA, "graphics");
2449 break;
2450 case 'G' : // graphics
2451 padd("style:name", sXML_CDATA,
2452 ascii(Int2Str(fstyle->boxnum, "G%d", buf)));
2453 padd("style:family", sXML_CDATA, "graphics");
2454 break;
2455 case 'L' : // line TODO : all
2456 padd("style:name", sXML_CDATA,
2457 ascii(Int2Str(fstyle->boxnum, "L%d", buf)));
2458 padd( "style:family" , sXML_CDATA , "paragraph" );
2459 break;
2462 rstartEl("style:style", mxList.get());
2463 mxList->clear();
2465 if ( fstyle->boxtype == 'T')
2467 padd("fo:padding", sXML_CDATA, "0cm");
2470 if( fstyle->boxtype != 'G' || fstyle->cap_len <= 0 )
2472 padd("fo:margin-left", sXML_CDATA,
2473 Double2Str(WTMM(fstyle->margin[0][0]) ) + "mm");
2474 padd("fo:margin-right", sXML_CDATA,
2475 Double2Str(WTMM(fstyle->margin[0][1])) + "mm");
2476 padd("fo:margin-top", sXML_CDATA,
2477 Double2Str(WTMM(fstyle->margin[0][2])) + "mm");
2478 padd("fo:margin-bottom", sXML_CDATA,
2479 Double2Str(WTMM(fstyle->margin[0][3])) + "mm");
2482 switch (fstyle->txtflow)
2484 case 0:
2485 padd("style:wrap", sXML_CDATA, "none");
2486 break;
2487 case 1:
2488 if( fstyle->boxtype == 'G' || fstyle->boxtype == 'B' || fstyle->boxtype == 'O')
2489 padd("style:run-through", sXML_CDATA, "background");
2490 padd("style:wrap", sXML_CDATA, "run-through");
2491 break;
2492 case 2:
2493 padd("style:wrap", sXML_CDATA, "dynamic");
2494 break;
2496 if (fstyle->anchor_type == CHAR_ANCHOR)
2498 padd("style:vertical-pos", sXML_CDATA, "top");
2499 padd("style:vertical-rel", sXML_CDATA, "baseline");
2500 padd("style:horizontal-pos", sXML_CDATA, "center");
2501 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
2503 else
2506 switch (-(fstyle->xpos))
2508 case 2:
2509 padd("style:horizontal-pos", sXML_CDATA, "right");
2510 break;
2511 case 3:
2512 padd("style:horizontal-pos", sXML_CDATA, "center");
2513 break;
2514 case 1:
2515 default:
2516 padd("style:horizontal-pos", sXML_CDATA, "from-left");
2517 break;
2519 switch (-(fstyle->ypos))
2521 case 2:
2522 padd("style:vertical-pos", sXML_CDATA, "bottom");
2523 break;
2524 case 3:
2525 padd("style:vertical-pos", sXML_CDATA, "middle");
2526 break;
2527 case 1:
2528 default:
2529 padd("style:vertical-pos", sXML_CDATA, "from-top");
2530 break;
2532 if ( fstyle->anchor_type == PARA_ANCHOR )
2534 padd("style:vertical-rel", sXML_CDATA, "paragraph");
2535 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
2537 else
2539 padd("style:vertical-rel", sXML_CDATA, "page-content");
2540 padd("style:horizontal-rel", sXML_CDATA, "page-content");
2543 if( fstyle->boxtype == 'X' || fstyle->boxtype == 'B' )
2545 Cell *cell = static_cast<Cell *>(fstyle->cell);
2546 if(cell->linetype[0] == cell->linetype[1] &&
2547 cell->linetype[0] == cell->linetype[2] &&
2548 cell->linetype[0] == cell->linetype[3])
2550 switch( cell->linetype[0] )
2552 case 0:
2553 padd("fo:border", sXML_CDATA, "none");
2554 break;
2555 case 1: /* A thin solid line */
2556 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2557 padd("fo:border", sXML_CDATA,"0.002cm solid #000000");
2558 break;
2559 case 2: /* Bold lines */
2560 padd("fo:border", sXML_CDATA,"0.035cm solid #000000");
2561 break;
2562 case 4: /* Double line */
2563 padd("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2564 padd("fo:border", sXML_CDATA,"0.039cm double #000000");
2565 break;
2568 else
2570 switch( cell->linetype[0] )
2572 case 1: /* A thin solid line */
2573 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2574 padd("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
2575 break;
2576 case 2: /* Bold lines */
2577 padd("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
2578 break;
2579 case 4: /* Double line */
2580 padd("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2581 padd("fo:border-left", sXML_CDATA,"0.039cm double #000000");
2582 break;
2584 switch( cell->linetype[1] )
2586 case 1: /* A thin solid line */
2587 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2588 padd("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
2589 break;
2590 case 2: /* Bold lines */
2591 padd("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
2592 break;
2593 case 4: /* Double line */
2594 padd("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2595 padd("fo:border-right", sXML_CDATA,"0.039cm double #000000");
2596 break;
2598 switch( cell->linetype[2] )
2600 case 1: /* A thin solid line */
2601 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2602 padd("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
2603 break;
2604 case 2: /* Bold lines */
2605 padd("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
2606 break;
2607 case 4: /* Double line */
2608 padd("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2609 padd("fo:border-top", sXML_CDATA,"0.039cm double #000000");
2610 break;
2612 switch( cell->linetype[3] )
2614 case 1: /* A thin solid line */
2615 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2616 padd("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
2617 break;
2618 case 2: /* Bold lines */
2619 padd("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
2620 break;
2621 case 4: /* Double line */
2622 padd("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2623 padd("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
2624 break;
2628 if( cell->linetype[0] == 0 && cell->linetype[1] == 0 &&
2629 cell->linetype[2] == 0 && cell->linetype[3] == 0 ){
2630 padd("fo:padding", sXML_CDATA,"0mm");
2632 else{
2633 padd("fo:padding-left", sXML_CDATA,
2634 Double2Str(WTMM(fstyle->margin[1][0])) + "mm");
2635 padd("fo:padding-right", sXML_CDATA,
2636 Double2Str(WTMM(fstyle->margin[1][1])) + "mm");
2637 padd("fo:padding-top", sXML_CDATA,
2638 Double2Str(WTMM(fstyle->margin[1][2])) + "mm");
2639 padd("fo:padding-bottom", sXML_CDATA,
2640 Double2Str(WTMM(fstyle->margin[1][3])) + "mm");
2642 if(cell->shade != 0)
2643 padd("fo:background-color", sXML_CDATA,
2644 ascii(hcolor2str(
2645 sal::static_int_cast<uchar>(cell->color),
2646 sal::static_int_cast<uchar>(cell->shade),
2647 buf)));
2649 else if( fstyle->boxtype == 'E' )
2651 padd("fo:padding", sXML_CDATA,"0mm");
2653 else if( fstyle->boxtype == 'L' )
2655 padd( "style:border-line-width-bottom", sXML_CDATA, "0.02mm 0.35mm 0.02mm");
2656 padd("fo:border-bottom", sXML_CDATA,"0.039cm double #808080");
2658 else if( fstyle->boxtype == 'G' )
2660 if( fstyle->margin[1][0] || fstyle->margin[1][1] || fstyle->margin[1][2] || fstyle->margin[1][3] ){
2661 OUString clip = "rect(" +
2662 Double2Str(WTMM(-fstyle->margin[1][0]) ) + "mm " +
2663 Double2Str(WTMM(-fstyle->margin[1][1]) ) + "mm " +
2664 Double2Str(WTMM(-fstyle->margin[1][2]) ) + "mm " +
2665 Double2Str(WTMM(-fstyle->margin[1][3]) ) + "mm)";
2666 padd("style:mirror", sXML_CDATA, "none");
2667 padd("fo:clip", sXML_CDATA, clip);
2669 char *cell = static_cast<char *>(fstyle->cell);
2670 padd("draw:luminance", sXML_CDATA,
2671 ascii(Int2Str(cell[0], "%d%%", buf)));
2672 padd("draw:contrast", sXML_CDATA,
2673 ascii(Int2Str(cell[1], "%d%%", buf)));
2674 if( cell[2] == 0 )
2675 padd("draw:color-mode", sXML_CDATA, "standard");
2676 else if( cell[2] == 1 )
2677 padd("draw:color-mode", sXML_CDATA, "greyscale");
2678 else if( cell[2] == 2 )
2679 padd("draw:color-mode", sXML_CDATA, "mono");
2682 rstartEl("style:properties", mxList.get());
2683 mxList->clear();
2684 rendEl("style:properties");
2685 rendEl("style:style");
2689 char *HwpReader::getTStyleName(int index, char *_buf)
2691 return Int2Str(index, "T%d", _buf);
2695 char *HwpReader::getPStyleName(int index, char *_buf)
2697 return Int2Str(index, "P%d", _buf);
2701 void HwpReader::makeChars(hchar_string & rStr)
2703 rchars(fromHcharStringToOUString(rStr));
2704 rStr.clear();
2709 * If no special characters in the paragraph and all characters use the same CharShape
2711 void HwpReader::make_text_p0(HWPPara * para, bool bParaStart)
2713 hchar_string str;
2714 int n;
2715 int res;
2716 hchar dest[3];
2717 unsigned char firstspace = 0;
2718 if( !bParaStart)
2720 padd("text:style-name", sXML_CDATA,
2721 ascii(getPStyleName(para->GetParaShape().index, buf)));
2722 rstartEl("text:p", mxList.get());
2723 mxList->clear();
2725 if( d->bFirstPara && d->bInBody )
2727 strcpy(
2728 buf,
2729 "[\xEB\xAC\xB8\xEC\x84\x9C\xEC\x9D\x98 \xEC\xB2\x98\xEC\x9D\x8C]");
2730 // U+BB38 HANGUL SYLLABLE MUN, U+C11C HANGUL SYLLABLE SEO,
2731 // U+C758 HANGUL SYLLABLE YI, U+CC98 HANGUL SYLLABLE CEO,
2732 // U+C74C HANGUL SYLLABLE EUM: "Begin of Document"
2733 padd("text:name", sXML_CDATA, OUString(buf, strlen(buf), RTL_TEXTENCODING_UTF8));
2734 rstartEl("text:bookmark", mxList.get());
2735 mxList->clear();
2736 rendEl("text:bookmark");
2737 d->bFirstPara = false;
2739 if( d->bInHeader )
2741 makeShowPageNum();
2742 d->bInHeader = false;
2744 padd("text:style-name", sXML_CDATA,
2745 ascii(getTStyleName(para->cshape->index, buf)));
2746 rstartEl("text:span", mxList.get());
2747 mxList->clear();
2749 for (n = 0; n < para->nch && para->hhstr[n]->hh;
2750 n += para->hhstr[n]->WSize())
2752 if (para->hhstr[n]->hh == CH_SPACE && !firstspace)
2754 makeChars(str);
2755 rstartEl("text:s", mxList.get());
2756 rendEl("text:s");
2758 else if (para->hhstr[n]->hh == CH_END_PARA)
2760 makeChars(str);
2761 rendEl("text:span");
2762 rendEl("text:p");
2763 break;
2765 else
2767 if (para->hhstr[n]->hh == CH_SPACE)
2768 firstspace = 0;
2769 else
2770 firstspace = 1;
2771 res = hcharconv(para->hhstr[n]->hh, dest, UNICODE);
2772 for( int j = 0 ; j < res; j++ )
2774 str.push_back(dest[j]);
2782 * There is no special characters in the paragraph, but characters use different CharShapes
2784 void HwpReader::make_text_p1(HWPPara * para,bool bParaStart)
2786 hchar_string str;
2787 int n;
2788 int res;
2789 hchar dest[3];
2790 int curr = para->cshape->index;
2791 unsigned char firstspace = 0;
2793 if( !bParaStart )
2795 padd("text:style-name", sXML_CDATA,
2796 ascii(getPStyleName(para->GetParaShape().index, buf)));
2797 rstartEl("text:p", mxList.get());
2798 mxList->clear();
2800 if( d->bFirstPara && d->bInBody )
2802 /* for HWP's Bookmark */
2803 strcpy(
2804 buf,
2805 "[\xEB\xAC\xB8\xEC\x84\x9C\xEC\x9D\x98 \xEC\xB2\x98\xEC\x9D\x8C]");
2806 // U+BB38 HANGUL SYLLABLE MUN, U+C11C HANGUL SYLLABLE SEO,
2807 // U+C758 HANGUL SYLLABLE YI, U+CC98 HANGUL SYLLABLE CEO,
2808 // U+C74C HANGUL SYLLABLE EUM: "Begin of Document"
2809 padd("text:name", sXML_CDATA, OUString(buf, strlen(buf), RTL_TEXTENCODING_UTF8));
2810 rstartEl("text:bookmark", mxList.get());
2811 mxList->clear();
2812 rendEl("text:bookmark");
2813 d->bFirstPara = false;
2815 if( d->bInHeader )
2817 makeShowPageNum();
2818 d->bInHeader = false;
2820 padd("text:style-name", sXML_CDATA,
2821 ascii(getTStyleName(curr, buf)));
2822 rstartEl("text:span", mxList.get());
2823 mxList->clear();
2825 for (n = 0; n < para->nch && para->hhstr[n]->hh;
2826 n += para->hhstr[n]->WSize())
2828 if (para->GetCharShape(n)->index != curr)
2830 makeChars(str);
2831 rendEl("text:span");
2832 curr = para->GetCharShape(n)->index;
2833 padd("text:style-name", sXML_CDATA,
2834 ascii(getTStyleName(curr, buf)));
2835 rstartEl("text:span", mxList.get());
2836 mxList->clear();
2838 if (para->hhstr[n]->hh == CH_SPACE && !firstspace)
2840 makeChars(str);
2841 rstartEl("text:s", mxList.get());
2842 rendEl("text:s");
2844 else if (para->hhstr[n]->hh == CH_END_PARA)
2846 makeChars(str);
2847 rendEl("text:span");
2848 rendEl("text:p");
2849 break;
2851 else
2853 if( para->hhstr[n]->hh < CH_SPACE )
2854 continue;
2855 if (para->hhstr[n]->hh == CH_SPACE)
2856 firstspace = 0;
2857 else
2858 firstspace = 1;
2859 res = hcharconv(para->hhstr[n]->hh, dest, UNICODE);
2860 for( int j = 0 ; j < res; j++ )
2862 str.push_back(dest[j]);
2870 * Special characters are in the paragraph and characters use different CharShapes
2872 void HwpReader::make_text_p3(HWPPara * para,bool bParaStart)
2874 hchar_string str;
2875 int n, res;
2876 hchar dest[3];
2877 unsigned char firstspace = 0;
2878 bool pstart = bParaStart;
2879 bool tstart = false;
2880 bool infield = false;
2881 int curr;
2882 if( d->bFirstPara && d->bInBody )
2884 if ( !pstart ) {
2885 STARTP;
2887 strcpy(
2888 buf,
2889 "[\xEB\xAC\xB8\xEC\x84\x9C\xEC\x9D\x98 \xEC\xB2\x98\xEC\x9D\x8C]");
2890 // U+BB38 HANGUL SYLLABLE MUN, U+C11C HANGUL SYLLABLE SEO,
2891 // U+C758 HANGUL SYLLABLE YI, U+CC98 HANGUL SYLLABLE CEO,
2892 // U+C74C HANGUL SYLLABLE EUM: "Begin of Document"
2893 padd("text:name", sXML_CDATA, OUString(buf, strlen(buf), RTL_TEXTENCODING_UTF8));
2894 rstartEl("text:bookmark", mxList.get());
2895 mxList->clear();
2896 rendEl("text:bookmark");
2897 d->bFirstPara = false;
2899 if( d->bInHeader )
2901 if ( !pstart ) {
2902 STARTP;
2904 makeShowPageNum();
2905 d->bInHeader = false;
2908 for (n = 0; n < para->nch && para->hhstr[n]->hh;
2909 n += para->hhstr[n]->WSize())
2911 if( para->hhstr[n]->hh == CH_END_PARA )
2913 if (!str.empty())
2915 if( !pstart ){ STARTP;}
2916 if( !tstart ){ STARTT;}
2917 makeChars(str);
2919 if( tstart ){ ENDT;}
2920 if( !pstart ){ STARTP;}
2921 if( pstart ){ ENDP;}
2922 break;
2924 else if( para->hhstr[n]->hh == CH_SPACE && !firstspace)
2926 if( !pstart ) {STARTP;}
2927 if( !tstart ) {STARTT;}
2928 makeChars(str);
2929 rstartEl("text:s", mxList.get());
2930 mxList->clear();
2931 rendEl("text:s");
2933 else if ( para->hhstr[n]->hh >= CH_SPACE )
2935 if( n > 0 )
2936 if( para->GetCharShape(n)->index != para->GetCharShape(n-1)->index && !infield )
2938 if( !pstart ) {STARTP;}
2939 if( !tstart ) {STARTT;}
2940 makeChars(str);
2941 ENDT;
2943 if( para->hhstr[n]->hh == CH_SPACE )
2944 firstspace = 0;
2945 else
2946 firstspace = 1;
2947 res = hcharconv(para->hhstr[n]->hh, dest, UNICODE);
2948 for( int j = 0 ; j < res; j++ )
2950 str.push_back(dest[j]);
2953 else if (para->hhstr[n]->hh == CH_FIELD)
2955 FieldCode *hbox = static_cast<FieldCode*>(para->hhstr[n].get());
2956 if( hbox->location_info == 1)
2958 if( !pstart ) {STARTP;}
2959 if( !tstart ) {STARTT;}
2960 makeChars(str);
2961 firstspace = 1;
2962 if( hbox->type[0] == 4 && hbox->type[1] == 0 )
2964 field = hbox->str3.get();
2966 else{
2967 makeFieldCode(str, hbox);
2969 infield = true;
2971 else
2973 firstspace = 1;
2974 if( hbox->type[0] == 4 && hbox->type[1] == 0 )
2976 makeFieldCode(str, hbox);
2977 field = nullptr;
2979 infield = false;
2980 str.clear();
2983 else
2985 switch (para->hhstr[n]->hh)
2987 case CH_BOOKMARK:
2988 if( !pstart ) {STARTP;}
2989 if( !tstart ) {STARTT;}
2990 makeChars(str);
2991 makeBookmark(static_cast<Bookmark*>(para->hhstr[n].get()));
2992 break;
2993 case CH_DATE_FORM: // 7
2994 break;
2995 case CH_DATE_CODE: // 8
2996 if( !pstart ) {STARTP;}
2997 if( !tstart ) {STARTT;}
2998 makeChars(str);
2999 makeDateCode(static_cast<DateCode*>(para->hhstr[n].get()));
3000 break;
3001 case CH_TAB: // 9
3002 if( !pstart ) {STARTP;}
3003 if (!str.empty())
3005 if( !tstart ) {STARTT;}
3006 makeChars(str);
3008 makeTab();
3009 break;
3010 case CH_TEXT_BOX: /* 10 - ordered by Table/text box/formula/button/hypertext */
3012 /* produce tables first, and treat formula as being in text:p. */
3013 TxtBox *hbox = static_cast<TxtBox*>(para->hhstr[n].get());
3015 if( hbox->style.anchor_type == 0 )
3017 if( !pstart ) {STARTP;}
3018 if( !tstart ) {STARTT;}
3019 makeChars(str);
3021 else
3023 if( !pstart ) {STARTP;}
3024 if (!str.empty())
3026 if( !tstart ) {STARTT;}
3027 makeChars(str);
3029 if( tstart ) {ENDT;}
3031 switch (hbox->type)
3033 case TBL_TYPE: // table
3034 case TXT_TYPE: // text box
3035 case EQU_TYPE: // formula
3036 makeTextBox(hbox);
3037 break;
3038 case BUTTON_TYPE: // text button
3039 case HYPERTEXT_TYPE: // hypertext
3040 makeHyperText(hbox);
3041 break;
3043 break;
3045 case CH_PICTURE: // 11
3047 Picture *hbox = static_cast<Picture*>(para->hhstr[n].get());
3048 if( hbox->style.anchor_type == 0 )
3050 if( !pstart ) {STARTP;}
3051 if( !tstart ) {STARTT;}
3052 makeChars(str);
3054 else
3056 if( !pstart ) {STARTP;}
3057 if (!str.empty())
3059 if( !tstart ) {STARTT;}
3060 makeChars(str);
3062 if( tstart ) {ENDT;}
3064 makePicture(hbox);
3065 break;
3067 case CH_LINE: // 14
3069 if (!str.empty())
3071 if( !pstart ) {STARTP;}
3072 if( !tstart ) {STARTT;}
3073 makeChars(str);
3075 if( tstart ) {ENDT;}
3076 if( pstart ) {ENDP;}
3077 makeLine();
3078 pstart = true;
3079 break;
3081 case CH_HIDDEN: // 15
3082 if( !pstart ) {STARTP;}
3083 if( !tstart ) {STARTT;}
3084 makeChars(str);
3085 makeHidden(static_cast<Hidden*>(para->hhstr[n].get()));
3086 break;
3087 case CH_FOOTNOTE: // 17
3088 if( !pstart ) {STARTP;}
3089 if( !tstart ) {STARTT;}
3090 makeChars(str);
3091 makeFootnote(static_cast<Footnote*>(para->hhstr[n].get()));
3092 break;
3093 case CH_AUTO_NUM: // 18
3094 if( !pstart ) {STARTP;}
3095 if( !tstart ) {STARTT;}
3096 makeChars(str);
3097 makeAutoNum(static_cast<AutoNum*>(para->hhstr[n].get()));
3098 break;
3099 case CH_NEW_NUM: // 19 -skip
3100 break;
3101 case CH_PAGE_NUM_CTRL: // 21
3102 break;
3103 case CH_MAIL_MERGE: // 22
3104 if( !pstart ) {STARTP;}
3105 if( !tstart ) {STARTT;}
3106 makeChars(str);
3107 makeMailMerge(static_cast<MailMerge*>(para->hhstr[n].get()));
3108 break;
3109 case CH_COMPOSE: /* 23 - overlapping letters */
3110 break;
3111 case CH_HYPHEN: // 24
3112 break;
3113 case CH_TOC_MARK: /* 25 Need to fix below 3 */
3114 if( !pstart ) {STARTP;}
3115 if( !tstart ) {STARTT;}
3116 makeChars(str);
3117 break;
3118 case CH_INDEX_MARK: // 26
3119 if( !pstart ) {STARTP;}
3120 if( !tstart ) {STARTT;}
3121 makeChars(str);
3122 break;
3123 case CH_OUTLINE: // 28
3124 if( !pstart ) {STARTP;}
3125 if( !tstart ) {STARTT;}
3126 makeChars(str);
3127 makeOutline(static_cast<Outline *>(para->hhstr[n].get()));
3128 break;
3129 case CH_FIXED_SPACE:
3130 case CH_KEEP_SPACE:
3131 str.push_back(0x0020);
3132 break;
3139 void HwpReader::makeFieldCode(hchar_string const & rStr, FieldCode const *hbox)
3141 /* Push frame */
3142 if( hbox->type[0] == 4 && hbox->type[1] == 0 )
3144 padd("text:placeholder-type", sXML_CDATA, "text");
3145 if( field )
3146 padd("text:description", sXML_CDATA, fromHcharStringToOUString(hstr2ucsstr(field)));
3147 rstartEl( "text:placeholder", mxList.get());
3148 mxList->clear();
3149 rchars( fromHcharStringToOUString(rStr) );
3150 rendEl( "text:placeholder" );
3152 /* Document Summary */
3153 else if( hbox->type[0] == 3 && hbox->type[1] == 0 )
3155 if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "title")
3157 rstartEl( "text:title", mxList.get() );
3158 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3159 rendEl( "text:title" );
3161 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "subject")
3163 rstartEl( "text:subject", mxList.get() );
3164 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3165 rendEl( "text:subject" );
3167 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "author")
3169 rstartEl( "text:author-name", mxList.get() );
3170 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3171 rendEl( "text:author-name" );
3173 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "keywords")
3175 rstartEl( "text:keywords", mxList.get() );
3176 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3177 rendEl( "text:keywords" );
3180 /* Personal Information */
3181 else if( hbox->type[0] == 3 && hbox->type[1] == 1 )
3183 if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "User")
3185 rstartEl( "text:sender-lastname", mxList.get() );
3186 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3187 rendEl( "text:sender-lastname" );
3189 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Company")
3191 rstartEl( "text:sender-company", mxList.get() );
3192 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3193 rendEl( "text:sender-company" );
3195 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Position")
3197 rstartEl( "text:sender-title", mxList.get() );
3198 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3199 rendEl( "text:sender-title" );
3201 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Division")
3203 rstartEl( "text:sender-position", mxList.get() );
3204 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3205 rendEl( "text:sender-position" );
3207 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Fax")
3209 rstartEl( "text:sender-fax", mxList.get() );
3210 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3211 rendEl( "text:sender-fax" );
3213 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Pager")
3215 rstartEl( "text:phone-private", mxList.get() );
3216 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3217 rendEl( "text:phone-private" );
3219 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "E-mail")
3221 rstartEl( "text:sender-email", mxList.get() );
3222 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3223 rendEl( "text:sender-email" );
3225 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Zipcode(office)")
3227 rstartEl( "text:sender-postal-code", mxList.get() );
3228 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3229 rendEl( "text:sender-postal-code" );
3231 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Phone(office)")
3233 rstartEl( "text:sender-phone-work", mxList.get() );
3234 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3235 rendEl( "text:sender-phone-work" );
3237 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Address(office)")
3239 rstartEl( "text:sender-street", mxList.get() );
3240 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3241 rendEl( "text:sender-street" );
3245 else if( hbox->type[0] == 3 && hbox->type[1] == 2 ) /* creation date */
3247 if( hbox->m_pDate )
3248 padd("style:data-style-name", sXML_CDATA,
3249 ascii(Int2Str(hbox->m_pDate->key, "N%d", buf)));
3250 rstartEl( "text:creation-date", mxList.get() );
3251 mxList->clear();
3252 rchars( fromHcharStringToOUString(hstr2ucsstr(hbox->str2.get())) );
3253 rendEl( "text:creation-date" );
3259 * Completed
3260 * In LibreOffice, refer bookmarks as reference, but hwp doesn't have the sort of feature.
3262 void HwpReader::makeBookmark(Bookmark const * hbox)
3264 if (hbox->type == 0)
3266 padd("text:name", sXML_CDATA, fromHcharStringToOUString(hstr2ucsstr(hbox->id)));
3267 rstartEl("text:bookmark", mxList.get());
3268 mxList->clear();
3269 rendEl("text:bookmark");
3271 else if (hbox->type == 1) /* Block bookmarks days begin and end there if */
3273 padd("text:name", sXML_CDATA, fromHcharStringToOUString(hstr2ucsstr(hbox->id)));
3274 rstartEl("text:bookmark-start", mxList.get());
3275 mxList->clear();
3276 rendEl("text:bookmark-start");
3278 else if (hbox->type == 2)
3280 padd("text:name", sXML_CDATA, fromHcharStringToOUString(hstr2ucsstr(hbox->id)));
3281 rstartEl("text:bookmark-end", mxList.get());
3282 mxList->clear();
3283 rendEl("text:bookmark-end");
3288 void HwpReader::makeDateFormat(DateCode * hbox)
3290 padd("style:name", sXML_CDATA,
3291 ascii(Int2Str(hbox->key, "N%d", buf)));
3292 padd("style:family", sXML_CDATA,"data-style");
3293 padd("number:language", sXML_CDATA,"ko");
3294 padd("number:country", sXML_CDATA,"KR");
3296 rstartEl("number:date-style", mxList.get());
3297 mxList->clear();
3299 bool add_zero = false;
3300 int zero_check = 0;
3301 hbox->format[DATE_SIZE -1] = 0;
3303 const hchar *fmt = hbox->format[0] ? hbox->format : defaultform;
3305 for( ; *fmt ; fmt++ )
3307 if( zero_check == 1 )
3309 zero_check = 0;
3311 else
3312 add_zero = false;
3314 switch( *fmt )
3316 case '0':
3317 zero_check = 1;
3318 add_zero = true;
3319 break;
3320 case '1':
3321 padd("number:style", sXML_CDATA, "long");
3322 rstartEl("number:year", mxList.get());
3323 mxList->clear();
3324 rendEl("number:year");
3325 break;
3326 case '!':
3327 rstartEl("number:year", mxList.get());
3328 mxList->clear();
3329 rendEl("number:year");
3330 break;
3331 case '2':
3332 if( add_zero )
3333 padd("number:style", sXML_CDATA, "long");
3334 rstartEl("number:month", mxList.get());
3335 mxList->clear();
3336 rendEl("number:month");
3337 break;
3338 case '@':
3339 padd("number:textual", sXML_CDATA, "true");
3340 rstartEl("number:month", mxList.get());
3341 mxList->clear();
3342 rendEl("number:month");
3343 break;
3344 case '*':
3345 padd("number:textual", sXML_CDATA, "true");
3346 padd("number:style", sXML_CDATA, "long");
3347 rstartEl("number:month", mxList.get());
3348 mxList->clear();
3349 rendEl("number:month");
3350 break;
3351 case '3':
3352 if( add_zero )
3353 padd("number:style", sXML_CDATA, "long");
3354 rstartEl("number:day", mxList.get());
3355 mxList->clear();
3356 rendEl("number:day");
3357 break;
3358 case '#':
3359 if( add_zero )
3360 padd("number:style", sXML_CDATA, "long");
3361 rstartEl("number:day", mxList.get());
3362 mxList->clear();
3363 rendEl("number:day");
3364 switch( hbox->date[DateCode::DAY] % 10)
3366 case 1:
3367 rstartEl("number:text", mxList.get());
3368 rchars("st");
3369 rendEl("number:text");
3370 break;
3371 case 2:
3372 rstartEl("number:text", mxList.get());
3373 rchars("nd");
3374 rendEl("number:text");
3375 break;
3376 case 3:
3377 rstartEl("number:text", mxList.get());
3378 rchars("rd");
3379 rendEl("number:text");
3380 break;
3381 default:
3382 rstartEl("number:text", mxList.get());
3383 rchars("th");
3384 rendEl("number:text");
3385 break;
3387 break;
3388 case '4':
3389 case '$':
3390 if( add_zero )
3391 padd("number:style", sXML_CDATA, "long");
3392 rstartEl("number:hours", mxList.get());
3393 mxList->clear();
3394 rendEl("number:hours");
3395 break;
3396 case '5':
3397 case '%':
3398 if( add_zero )
3399 padd("number:style", sXML_CDATA, "long");
3400 rstartEl("number:minutes", mxList.get());
3401 mxList->clear();
3402 rendEl("number:minutes");
3403 break;
3404 case '_':
3405 padd("number:style", sXML_CDATA, "long");
3406 [[fallthrough]];
3407 case '6':
3408 case '^':
3409 rstartEl("number:day-of-week", mxList.get());
3410 mxList->clear();
3411 rendEl("number:day-of-week");
3412 break;
3413 case '7':
3414 case '&':
3415 case '+':
3416 rstartEl("number:am-pm", mxList.get());
3417 mxList->clear();
3418 rendEl("number:am-pm");
3419 break;
3420 case '~': // Chinese Locale
3421 break;
3422 default:
3423 hchar sbuf[2];
3424 sbuf[0] = *fmt;
3425 sbuf[1] = 0;
3426 rstartEl("number:text", mxList.get());
3427 rchars(fromHcharStringToOUString(hstr2ucsstr(sbuf)));
3428 rendEl("number:text");
3429 break;
3432 mxList->clear();
3433 rendEl("number:date-style");
3437 void HwpReader::makeDateCode(DateCode * hbox)
3439 padd("style:data-style-name", sXML_CDATA,
3440 ascii(Int2Str(hbox->key, "N%d", buf)));
3441 rstartEl( "text:date", mxList.get() );
3442 mxList->clear();
3443 hchar_string const boxstr = hbox->GetString();
3444 rchars(fromHcharStringToOUString(hstr2ucsstr(boxstr.c_str())));
3445 rendEl( "text:date" );
3449 void HwpReader::makeTab()
3451 rstartEl("text:tab-stop", mxList.get());
3452 rendEl("text:tab-stop");
3456 void HwpReader::makeTable(TxtBox * hbox)
3458 padd("table:name", sXML_CDATA,
3459 ascii(Int2Str(hbox->style.boxnum, "Table%d", buf)));
3460 padd("table:style-name", sXML_CDATA,
3461 ascii(Int2Str(hbox->style.boxnum, "Table%d", buf)));
3462 rstartEl("table:table", mxList.get());
3463 mxList->clear();
3465 Table *tbl = hbox->m_pTable;
3466 // column
3467 for (size_t i = 0 ; i < tbl->columns.nCount -1 ; i++)
3469 sprintf(buf,"Table%d.%c",hbox->style.boxnum, static_cast<char>('A'+i));
3470 padd("table:style-name", sXML_CDATA, ascii( buf ));
3471 rstartEl("table:table-column", mxList.get());
3472 mxList->clear();
3473 rendEl("table:table-column");
3476 // cell
3477 int j = -1, k = -1;
3478 for (auto const& tcell : tbl->cells)
3480 if( tcell->nRowIndex > j )
3482 if( j > k )
3484 rendEl("table:table-row");
3485 k = j;
3487 // row
3488 sprintf(buf,"Table%d.row%d",hbox->style.boxnum, tcell->nRowIndex + 1);
3489 padd("table:style-name", sXML_CDATA, ascii( buf ));
3490 rstartEl("table:table-row", mxList.get());
3491 mxList->clear();
3492 j = tcell->nRowIndex;
3495 sprintf(buf,"Table%d.%c%d",hbox->style.boxnum, 'A'+ tcell->nColumnIndex, tcell->nRowIndex +1);
3496 padd("table:style-name", sXML_CDATA, ascii( buf ));
3497 if( tcell->nColumnSpan > 1 )
3498 padd("table:number-columns-spanned", sXML_CDATA,
3499 ascii(Int2Str(tcell->nColumnSpan, "%d", buf)));
3500 if( tcell->nRowSpan > 1 )
3501 padd("table:number-rows-spanned", sXML_CDATA,
3502 ascii(Int2Str(tcell->nRowSpan, "%d", buf)));
3503 padd("table:value-type", sXML_CDATA,"string");
3504 if( tcell->pCell->protect )
3505 padd("table:protected", sXML_CDATA,"true");
3506 rstartEl("table:table-cell", mxList.get());
3507 mxList->clear();
3508 parsePara(hbox->plists[tcell->pCell->key].front().get());
3509 rendEl("table:table-cell");
3511 rendEl("table:table-row");
3512 rendEl("table:table");
3517 * Parses the text boxes and tables.
3518 * 1. draw: style-name, draw: name, text: anchor-type, svg: width,
3519 * Fo: min-height, svg: x, svg: y
3520 * TODO: fo:background-color <= no idea whether the value of color setting->style is in it or not
3522 void HwpReader::makeTextBox(TxtBox * hbox)
3524 if( hbox->style.cap_len > 0 && hbox->type == TXT_TYPE)
3526 padd("draw:style-name", sXML_CDATA,
3527 ascii(Int2Str(hbox->style.boxnum, "CapBox%d", buf)));
3528 padd("draw:name", sXML_CDATA,
3529 ascii(Int2Str(hbox->style.boxnum, "CaptionBox%d", buf)));
3530 padd("draw:z-index", sXML_CDATA,
3531 ascii(Int2Str(hbox->zorder, "%d", buf)));
3532 switch (hbox->style.anchor_type)
3534 case CHAR_ANCHOR:
3535 padd("text:anchor-type", sXML_CDATA, "as-char");
3536 break;
3537 case PARA_ANCHOR:
3538 padd("text:anchor-type", sXML_CDATA, "paragraph");
3539 break;
3540 case PAGE_ANCHOR:
3541 case PAPER_ANCHOR:
3543 padd("text:anchor-type", sXML_CDATA, "page");
3544 padd("text:anchor-page-number", sXML_CDATA,
3545 ascii(Int2Str(hbox->pgno +1, "%d", buf)));
3546 break;
3549 if (hbox->style.anchor_type != CHAR_ANCHOR)
3551 padd("svg:x", sXML_CDATA,
3552 Double2Str(WTMM( ( hbox->pgx + hbox->style.margin[0][0] ) )) + "mm");
3553 padd("svg:y", sXML_CDATA,
3554 Double2Str(WTMM( ( hbox->pgy + hbox->style.margin[0][2] ) )) + "mm");
3556 padd("svg:width", sXML_CDATA,
3557 Double2Str(WTMM(( hbox->box_xs + hbox->cap_xs) )) + "mm");
3558 padd("fo:min-height", sXML_CDATA,
3559 Double2Str(WTMM(( hbox->box_ys + hbox->cap_ys) )) + "mm");
3560 rstartEl("draw:text-box", mxList.get());
3561 mxList->clear();
3562 if( hbox->cap_pos % 2 ) /* The caption is on the top */
3564 parsePara(hbox->caption.front().get());
3566 padd( "text:style-name", sXML_CDATA, "Standard");
3567 rstartEl("text:p", mxList.get());
3568 mxList->clear();
3570 else{
3571 padd("draw:z-index", sXML_CDATA,
3572 ascii(Int2Str(hbox->zorder, "%d", buf)));
3575 padd("draw:style-name", sXML_CDATA,
3576 ascii(Int2Str(hbox->style.boxnum, "Txtbox%d", buf)));
3577 padd("draw:name", sXML_CDATA,
3578 ascii(Int2Str(hbox->style.boxnum, "Frame%d", buf)));
3580 if( hbox->style.cap_len <= 0 || hbox->type != TXT_TYPE )
3582 int x = 0;
3583 int y = 0;
3584 switch (hbox->style.anchor_type)
3586 case CHAR_ANCHOR:
3587 padd("text:anchor-type", sXML_CDATA, "as-char");
3588 break;
3589 case PARA_ANCHOR:
3590 padd("text:anchor-type", sXML_CDATA, "paragraph");
3591 break;
3592 case PAGE_ANCHOR:
3593 case PAPER_ANCHOR:
3595 padd("text:anchor-type", sXML_CDATA, "page");
3596 padd("text:anchor-page-number", sXML_CDATA,
3597 ascii(Int2Str(hbox->pgno +1, "%d", buf)));
3598 break;
3601 if( hbox->style.anchor_type != CHAR_ANCHOR )
3603 x += hbox->style.margin[0][0];
3604 y += hbox->style.margin[0][2];
3606 padd("svg:x", sXML_CDATA,
3607 Double2Str(WTMM( hbox->pgx + x )) + "mm");
3608 padd("svg:y", sXML_CDATA,
3609 Double2Str(WTMM( hbox->pgy + y )) + "mm");
3611 else
3613 padd("text:anchor-type", sXML_CDATA, "as-char");
3614 padd("svg:y", sXML_CDATA, "0cm");
3616 padd("svg:width", sXML_CDATA,
3617 Double2Str(WTMM( hbox->box_xs )) + "mm");
3618 if( hbox->style.cap_len > 0 && hbox->type != TXT_TYPE)
3619 padd("fo:min-height", sXML_CDATA,
3620 Double2Str(WTMM( hbox->box_ys + hbox->cap_ys)) + "mm");
3621 else
3622 padd("svg:height", sXML_CDATA,
3623 Double2Str(WTMM(hbox->box_ys )) + "mm");
3625 if( hbox->type != EQU_TYPE )
3627 rstartEl("draw:text-box", mxList.get());
3628 mxList->clear();
3629 /* If captions are present and it is on the top */
3630 if( hbox->style.cap_len > 0 && (hbox->cap_pos % 2) && hbox->type == TBL_TYPE )
3632 parsePara(hbox->caption.front().get());
3634 if( hbox->type == TBL_TYPE) // Is Table
3636 makeTable(hbox);
3638 else // Is TextBox
3640 parsePara(hbox->plists[0].front().get());
3642 /* If captions are present and it is on the bottom */
3643 if( hbox->style.cap_len > 0 && !(hbox->cap_pos % 2) && hbox->type == TBL_TYPE)
3645 parsePara(hbox->caption.front().get());
3647 rendEl("draw:text-box");
3648 // Caption exist and it is text-box
3649 if( hbox->style.cap_len > 0 && hbox->type == TXT_TYPE)
3651 rendEl( "text:p");
3652 if( !(hbox->cap_pos % 2))
3654 parsePara(hbox->caption.front().get());
3656 rendEl( "draw:text-box");
3659 else // is Formula
3661 rstartEl("draw:object", mxList.get());
3662 mxList->clear();
3663 makeFormula(hbox);
3664 rendEl("draw:object");
3670 * It must be converted into MathML.
3673 void HwpReader::makeFormula(TxtBox * hbox)
3675 char mybuf[3000];
3676 HWPPara* pPar;
3678 int n, c, res;
3679 hchar dest[3];
3680 size_t l = 0;
3682 pPar = hbox->plists[0].front().get();
3683 while( pPar )
3685 for( n = 0; n < pPar->nch && pPar->hhstr[n]->hh;
3686 n += pPar->hhstr[n]->WSize() )
3688 if (l >= sizeof(mybuf)-7)
3689 break;
3690 res = hcharconv(pPar->hhstr[n]->hh, dest, UNICODE);
3691 for( int j = 0 ; j < res; j++ ){
3692 c = dest[j];
3693 if( c < 32 )
3694 c = ' ';
3695 if( c < 256 )
3696 mybuf[l++] = sal::static_int_cast<char>(c);
3697 else
3699 mybuf[l++] = sal::static_int_cast<char>((c >> 8) & 0xff);
3700 mybuf[l++] = sal::static_int_cast<char>(c & 0xff);
3704 if (l >= sizeof(mybuf)-7)
3705 break;
3706 mybuf[l++] = '\n';
3707 pPar = pPar->Next();
3709 mybuf[l] = '\0';
3711 std::unique_ptr<Formula> form( new Formula(mybuf) );
3712 form->setDocumentHandler(m_rxDocumentHandler);
3713 form->setAttributeListImpl(mxList.get());
3714 form->parse();
3718 * Read the platform information. if the platform is Linux or Solaris, it needs to change
3719 * C: \ => Home, D: \ => changed to root (/). Because HWP uses DOS emulator.
3722 void HwpReader::makeHyperText(TxtBox * hbox)
3724 HyperText *hypert = hwpfile.GetHyperText();
3725 if( !hypert ) return;
3727 if (hypert->filename[0] != '\0') {
3728 ::std::string const tmp = hstr2ksstr(hypert->bookmark);
3729 ::std::string const tmp2 = hstr2ksstr(kstr2hstr(
3730 #ifdef _WIN32
3731 reinterpret_cast<uchar const *>(urltowin(reinterpret_cast<char *>(hypert->filename)).c_str())).c_str());
3732 #else
3733 reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hypert->filename)).c_str())).c_str());
3734 #endif
3735 padd("xlink:type", sXML_CDATA, "simple");
3736 if (!tmp.empty() && strcmp(tmp.c_str(), "[HTML]")) {
3737 ::std::string tmp3(tmp2);
3738 tmp3.push_back('#');
3739 tmp3.append(tmp);
3740 padd("xlink:href", sXML_CDATA,
3741 OUString(tmp3.c_str(), tmp3.size()+1, RTL_TEXTENCODING_EUC_KR));
3743 else{
3744 padd("xlink:href", sXML_CDATA,
3745 OUString(tmp2.c_str(), tmp2.size()+1, RTL_TEXTENCODING_EUC_KR));
3749 else
3751 padd("xlink:type", sXML_CDATA, "simple");
3752 ::std::string tmp;
3753 tmp.push_back('#');
3754 tmp.append(hstr2ksstr(hypert->bookmark));
3755 padd("xlink:href", sXML_CDATA,
3756 OUString(tmp.c_str(), tmp.size()+1, RTL_TEXTENCODING_EUC_KR));
3758 rstartEl("draw:a", mxList.get());
3759 mxList->clear();
3760 makeTextBox(hbox);
3761 rendEl("draw:a");
3766 * Read the platform information. if the platform is Linux or Solaris, it needs to change
3767 * C: \ => Home, D: \ => changed to root (/). Because HWP uses DOS emulator.
3770 void HwpReader::makePicture(Picture * hbox)
3772 switch (hbox->pictype)
3774 case PICTYPE_OLE:
3775 case PICTYPE_EMBED:
3776 case PICTYPE_FILE:
3778 if( hbox->style.cap_len > 0 )
3780 padd("draw:style-name", sXML_CDATA,
3781 ascii(Int2Str(hbox->style.boxnum, "CapBox%d", buf)));
3782 padd("draw:name", sXML_CDATA,
3783 ascii(Int2Str(hbox->style.boxnum, "CaptionBox%d", buf)));
3784 padd("draw:z-index", sXML_CDATA,
3785 ascii(Int2Str(hbox->zorder, "%d", buf)));
3786 switch (hbox->style.anchor_type)
3788 case CHAR_ANCHOR:
3789 padd("text:anchor-type", sXML_CDATA, "as-char");
3790 break;
3791 case PARA_ANCHOR:
3792 padd("text:anchor-type", sXML_CDATA, "paragraph");
3793 break;
3794 case PAGE_ANCHOR:
3795 case PAPER_ANCHOR:
3797 padd("text:anchor-type", sXML_CDATA, "page");
3798 padd("text:anchor-page-number", sXML_CDATA,
3799 ascii(Int2Str(hbox->pgno +1, "%d", buf)));
3800 break;
3803 if (hbox->style.anchor_type != CHAR_ANCHOR)
3805 padd("svg:x", sXML_CDATA,
3806 Double2Str(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
3807 padd("svg:y", sXML_CDATA,
3808 Double2Str(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
3810 padd("svg:width", sXML_CDATA,
3811 Double2Str(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1] )) + "mm");
3812 padd("fo:min-height", sXML_CDATA,
3813 Double2Str(WTMM( hbox->box_ys + hbox->style.margin[1][2] + hbox->style.margin[1][3] + hbox->cap_ys )) + "mm");
3814 rstartEl("draw:text-box", mxList.get());
3815 mxList->clear();
3816 if( hbox->cap_pos % 2 ) /* Caption is on the top */
3818 parsePara(hbox->caption.front().get());
3820 padd( "text:style-name", sXML_CDATA, "Standard");
3821 rstartEl("text:p", mxList.get());
3822 mxList->clear();
3824 if( hbox->ishyper )
3826 padd("xlink:type", sXML_CDATA, "simple");
3827 #ifdef _WIN32
3828 if( hbox->follow[4] != 0 )
3829 padd("xlink:href", sXML_CDATA, fromHcharStringToOUString(hstr2ucsstr(kstr2hstr(hbox->follow.data() + 4).c_str())));
3830 else
3831 padd("xlink:href", sXML_CDATA, fromHcharStringToOUString(hstr2ucsstr(kstr2hstr(hbox->follow.data() + 5).c_str())));
3832 #else
3833 if( hbox->follow[4] != 0 )
3834 padd("xlink:href", sXML_CDATA,
3835 fromHcharStringToOUString(hstr2ucsstr(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hbox->follow.data() + 4)).c_str())).c_str())));
3836 else
3837 padd("xlink:href", sXML_CDATA,
3838 fromHcharStringToOUString(hstr2ucsstr(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hbox->follow.data() + 5)).c_str())).c_str())));
3839 #endif
3840 rstartEl("draw:a", mxList.get());
3841 mxList->clear();
3843 padd("draw:style-name", sXML_CDATA,
3844 ascii(Int2Str(hbox->style.boxnum, "G%d", buf)));
3845 padd("draw:name", sXML_CDATA,
3846 ascii(Int2Str(hbox->style.boxnum, "Image%d", buf)));
3848 if( hbox->style.cap_len <= 0 )
3850 padd("draw:z-index", sXML_CDATA,
3851 ascii(Int2Str(hbox->zorder, "%d", buf)));
3852 switch (hbox->style.anchor_type)
3854 case CHAR_ANCHOR:
3855 padd("text:anchor-type", sXML_CDATA, "as-char");
3856 break;
3857 case PARA_ANCHOR:
3858 padd("text:anchor-type", sXML_CDATA, "paragraph");
3859 break;
3860 case PAGE_ANCHOR:
3861 case PAPER_ANCHOR:
3863 padd("text:anchor-type", sXML_CDATA, "page");
3864 padd("text:anchor-page-number", sXML_CDATA,
3865 ascii(Int2Str(hbox->pgno +1, "%d", buf)));
3866 break;
3869 if (hbox->style.anchor_type != CHAR_ANCHOR)
3871 padd("svg:x", sXML_CDATA,
3872 Double2Str(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
3873 padd("svg:y", sXML_CDATA,
3874 Double2Str(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
3877 else
3879 padd("text:anchor-type", sXML_CDATA, "as-char");
3880 padd("svg:y", sXML_CDATA, "0cm");
3882 padd("svg:width", sXML_CDATA,
3883 Double2Str(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1])) + "mm");
3884 padd("svg:height", sXML_CDATA,
3885 Double2Str(WTMM( hbox->box_ys + hbox->style.margin[1][2] + hbox->style.margin[1][3])) + "mm");
3887 if ( hbox->pictype == PICTYPE_FILE ){
3888 #ifdef _WIN32
3889 sprintf(buf, "file:///%s", hbox->picinfo.picun.path );
3890 padd("xlink:href", sXML_CDATA, fromHcharStringToOUString(hstr2ucsstr(kstr2hstr(reinterpret_cast<uchar *>(buf)).c_str())));
3891 #else
3892 padd("xlink:href", sXML_CDATA,
3893 fromHcharStringToOUString(hstr2ucsstr(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(hbox->picinfo.picun.path).c_str())).c_str())));
3894 #endif
3895 padd("xlink:type", sXML_CDATA, "simple");
3896 padd("xlink:show", sXML_CDATA, "embed");
3897 padd("xlink:actuate", sXML_CDATA, "onLoad");
3900 if( hbox->pictype == PICTYPE_OLE )
3901 rstartEl("draw:object-ole", mxList.get());
3902 else
3903 rstartEl("draw:image", mxList.get());
3904 mxList->clear();
3905 if (hbox->pictype == PICTYPE_EMBED || hbox->pictype == PICTYPE_OLE)
3907 rstartEl("office:binary-data", mxList.get());
3908 mxList->clear();
3909 if( hbox->pictype == PICTYPE_EMBED ){
3910 EmPicture *emp = hwpfile.GetEmPicture(hbox);
3911 if( emp )
3913 std::shared_ptr<char> pStr(base64_encode_string( emp->data.get(), emp->size ), Free<char>());
3914 rchars(ascii(pStr.get()));
3917 else{
3918 if( hwpfile.oledata ){
3919 #ifdef _WIN32
3920 LPSTORAGE srcsto;
3921 LPUNKNOWN pObj;
3922 wchar_t pathname[200];
3924 MultiByteToWideChar(CP_ACP, 0, hbox->picinfo.picole.embname, -1, pathname, 200);
3925 int rc = hwpfile.oledata->pis->OpenStorage(pathname, nullptr,
3926 STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, nullptr, 0, &srcsto);
3927 if (rc != S_OK) {
3928 rchars("");
3930 else{
3931 rc = OleLoad(srcsto, IID_IUnknown, nullptr, reinterpret_cast<LPVOID*>(&pObj));
3932 if( rc != S_OK ){
3933 srcsto->Release();
3934 rchars("");
3936 else{
3937 std::shared_ptr<char> pStr(base64_encode_string( reinterpret_cast<uchar *>(pObj), strlen(reinterpret_cast<char *>(pObj))), Free<char>());
3938 rchars(ascii(pStr.get()));
3939 pObj->Release();
3940 srcsto->Release();
3943 #else
3944 rchars("");
3945 #endif
3948 rendEl("office:binary-data");
3950 if( hbox->pictype == PICTYPE_OLE )
3951 rendEl("draw:object-ole");
3952 else
3953 rendEl("draw:image");
3954 if( hbox->ishyper )
3956 rendEl("draw:a");
3958 if( hbox->style.cap_len > 0 )
3960 rendEl( "text:p");
3961 if( !(hbox->cap_pos % 2)) /* Caption is at the bottom, */
3963 parsePara(hbox->caption.front().get());
3965 rendEl( "draw:text-box");
3967 break;
3969 case PICTYPE_DRAW:
3970 if( hbox->picinfo.picdraw.zorder > 0 )
3971 padd("draw:z-index", sXML_CDATA,
3972 ascii(Int2Str( hbox->picinfo.picdraw.zorder + 10000, "%d", buf)));
3973 makePictureDRAW(hbox->picinfo.picdraw.hdo, hbox);
3974 break;
3975 case PICTYPE_UNKNOWN:
3976 break;
3981 #define DBL(x) ((x) * (x))
3982 void HwpReader::makePictureDRAW(HWPDrawingObject *drawobj, Picture * hbox)
3984 int x = hbox->pgx;
3985 int y = hbox->pgy;
3986 bool bIsRotate = false;
3988 while (drawobj)
3990 padd("draw:style-name", sXML_CDATA,
3991 ascii(Int2Str(drawobj->index, "Draw%d", buf)));
3992 int a = 0;
3993 int b = 0;
3995 switch (hbox->style.anchor_type)
3997 case CHAR_ANCHOR:
3998 padd("text:anchor-type", sXML_CDATA, "as-char");
3999 break;
4000 case PARA_ANCHOR:
4001 padd("text:anchor-type", sXML_CDATA, "paragraph");
4002 break;
4003 case PAGE_ANCHOR:
4004 case PAPER_ANCHOR:
4006 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
4007 padd("text:anchor-type", sXML_CDATA, "page");
4008 padd("text:anchor-page-number", sXML_CDATA,
4009 ascii(Int2Str(hbox->pgno +1, "%d", buf)));
4010 a = hwpinfo.paper.left_margin;
4011 b = hwpinfo.paper.top_margin + hwpinfo.paper.header_length;
4012 break;
4016 if (drawobj->type == HWPDO_CONTAINER)
4018 rstartEl("draw:g", mxList.get());
4019 mxList->clear();
4020 makePictureDRAW(drawobj->child.get(), hbox);
4021 rendEl("draw:g");
4023 else
4025 bIsRotate = false;
4026 if( (drawobj->property.flag & HWPDO_FLAG_ROTATION) &&
4027 (drawobj->property.parall.pt[0].y != drawobj->property.parall.pt[1].y) &&
4028 //(drawobj->type == HWPDO_RECT || drawobj->type == HWPDO_ADVANCED_ELLIPSE || drawobj->type == HWPDO_ADVANCED_ARC )
4029 (drawobj->type == HWPDO_RECT || drawobj->type == HWPDO_ADVANCED_ELLIPSE )
4033 int i;
4034 ZZParall *pal = &drawobj->property.parall;
4036 ZZPoint pt[3], r_pt[3];
4037 for(i = 0 ; i < 3 ; i++ ){
4038 pt[i].x = pal->pt[i].x - drawobj->property.rot_originx;
4039 /* Convert to a physical coordinate */
4040 pt[i].y = -(pal->pt[i].y - drawobj->property.rot_originy);
4043 double rotate, skewX ;
4045 /* 2 - rotation angle calculation */
4046 if( pt[1].x == pt[0].x ){
4047 if( pt[1].y > pt[0].y )
4048 rotate = PI/2;
4049 else
4050 rotate = -(PI/2);
4052 else
4053 rotate = atan(static_cast<double>( pt[1].y - pt[0].y )/(pt[1].x - pt[0].x ));
4054 if( pt[1].x < pt[0].x )
4055 rotate += PI;
4057 for( i = 0 ; i < 3 ; i++){
4058 r_pt[i].x = static_cast<int>(pt[i].x * cos(-rotate) - pt[i].y * sin(-rotate));
4059 r_pt[i].y = static_cast<int>(pt[i].y * cos(-rotate) + pt[i].x * sin(-rotate));
4062 /* 4 - Calculation of reflex angle */
4063 if( r_pt[2].y == r_pt[1].y )
4064 skewX = 0;
4065 else
4066 skewX = atan(static_cast<double>(r_pt[2].x - r_pt[1].x )/( r_pt[2].y - r_pt[1].y ));
4067 if( skewX >= PI/2 )
4068 skewX -= PI;
4069 if( skewX <= -PI/2 )
4070 skewX += PI;
4072 OUString trans;
4073 if( skewX != 0.0 && rotate != 0.0 ){
4074 trans = "skewX (" + Double2Str(skewX)
4075 + ") rotate (" + Double2Str(rotate)
4076 + ") translate (" + Double2Str(WTMM(x + a + drawobj->offset2.x + pal->pt[0].x)) + "mm "
4077 + Double2Str(WTMM(y + b + drawobj->offset2.y + pal->pt[0].y)) + "mm)";
4078 bIsRotate = true;
4080 else if( skewX != 0.0 ){
4081 trans = "skewX (" + Double2Str(skewX)
4082 + ") translate (" + Double2Str(WTMM(x + a + drawobj->offset2.x + pal->pt[0].x)) + "mm "
4083 + Double2Str(WTMM(y + b + drawobj->offset2.y + pal->pt[0].y)) + "mm)";
4084 bIsRotate = true;
4086 else if( rotate != 0.0 ){
4087 trans = "rotate (" + Double2Str(rotate)
4088 + ") translate (" + Double2Str(WTMM(x + a + drawobj->offset2.x + pal->pt[0].x)) + "mm "
4089 + Double2Str(WTMM(y + b + drawobj->offset2.y + pal->pt[0].y)) + "mm)";
4090 bIsRotate = true;
4092 if( bIsRotate ){
4093 drawobj->extent.w = static_cast<int>(sqrt(double(DBL(pt[1].x-pt[0].x)+DBL(pt[1].y-pt[0].y))));
4094 drawobj->extent.h = static_cast<int>(sqrt(double(DBL(pt[2].x-pt[1].x)+DBL(pt[2].y-pt[1].y))));
4095 padd("draw:transform", sXML_CDATA, trans);
4098 switch (drawobj->type)
4100 case HWPDO_LINE: /* Line-starting coordinates, ending coordinates. */
4101 if( drawobj->u.line_arc.flip & 0x01 )
4103 padd("svg:x1", sXML_CDATA,
4104 Double2Str (WTMM(x + a + drawobj->offset2.x + drawobj->extent.w)) + "mm");
4105 padd("svg:x2", sXML_CDATA,
4106 Double2Str (WTMM( x + a + drawobj->offset2.x )) + "mm");
4108 else
4110 padd("svg:x1", sXML_CDATA,
4111 Double2Str (WTMM( x + a + drawobj->offset2.x )) + "mm");
4112 padd("svg:x2", sXML_CDATA,
4113 Double2Str (WTMM(x + a + drawobj->offset2.x + drawobj->extent.w)) + "mm");
4115 if( drawobj->u.line_arc.flip & 0x02 )
4117 padd("svg:y1", sXML_CDATA,
4118 Double2Str (WTMM( y + b + drawobj->offset2.y + drawobj->extent.h ) ) + "mm");
4119 padd("svg:y2", sXML_CDATA,
4120 Double2Str (WTMM( y + b + drawobj->offset2.y )) + "mm");
4122 else
4124 padd("svg:y1", sXML_CDATA,
4125 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4126 padd("svg:y2", sXML_CDATA,
4127 Double2Str (WTMM(y + b + drawobj->offset2.y + drawobj->extent.h)) + "mm");
4130 rstartEl("draw:line", mxList.get());
4131 mxList->clear();
4132 rendEl("draw:line");
4133 break;
4134 case HWPDO_RECT: /* rectangle - the starting position, vertical/horizontal */
4135 if( !bIsRotate )
4137 padd("svg:x", sXML_CDATA,
4138 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4139 padd("svg:y", sXML_CDATA,
4140 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4142 padd("svg:width", sXML_CDATA,
4143 Double2Str (WTMM( drawobj->extent.w )) + "mm");
4144 padd("svg:height", sXML_CDATA,
4145 Double2Str (WTMM( drawobj->extent.h )) + "mm");
4146 if( drawobj->property.flag & 0x01 )
4148 int value = drawobj->extent.w < drawobj->extent.h ?
4149 drawobj->extent.w : drawobj->extent.h ;
4150 padd("draw:corner-radius", sXML_CDATA,
4151 Double2Str (WTMM( value/10 )) + "mm");
4153 else if( drawobj->property.flag & 0x04 )
4155 int value = drawobj->extent.w < drawobj->extent.h ?
4156 drawobj->extent.w : drawobj->extent.h ;
4157 padd("draw:corner-radius", sXML_CDATA,
4158 Double2Str (WTMM( value / 2)) + "mm");
4161 rstartEl("draw:rect", mxList.get());
4162 mxList->clear();
4163 if( (drawobj->property.flag & HWPDO_FLAG_AS_TEXTBOX) &&
4164 drawobj->property.pPara ) // As Textbox
4166 HWPPara *pPara = drawobj->property.pPara;
4167 //parsePara(pPara);
4168 while(pPara)
4170 make_text_p1( pPara, false );
4171 pPara = pPara->Next();
4174 rendEl("draw:rect");
4175 break;
4176 case HWPDO_ELLIPSE: /* Ellipse - the starting position, vertical/horizontal */
4177 case HWPDO_ADVANCED_ELLIPSE: /* modified ellipse */
4179 if( !bIsRotate )
4181 padd("svg:x", sXML_CDATA,
4182 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4183 padd("svg:y", sXML_CDATA,
4184 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4187 padd("svg:width", sXML_CDATA,
4188 Double2Str (WTMM( drawobj->extent.w )) + "mm");
4189 padd("svg:height", sXML_CDATA,
4190 Double2Str (WTMM( drawobj->extent.h )) + "mm");
4191 if( drawobj->type == HWPDO_ADVANCED_ELLIPSE ){
4192 if( drawobj->u.arc.radial[0].x != drawobj->u.arc.radial[1].x
4193 || drawobj->u.arc.radial[0].y != drawobj->u.arc.radial[1].y ){
4194 int Cx,Cy;
4195 Cx = ( drawobj->offset2.x + drawobj->extent.w ) / 2;
4196 Cy = ( drawobj->offset2.y + drawobj->extent.h ) / 2;
4198 double start_angle, end_angle;
4199 start_angle = calcAngle( Cx, Cy, drawobj->u.arc.radial[0].x, drawobj->u.arc.radial[0].y );
4200 end_angle = calcAngle( Cx, Cy, drawobj->u.arc.radial[1].x, drawobj->u.arc.radial[1].y );
4201 if( drawobj->property.fill_color < 0xffffff )
4202 padd("draw:kind", sXML_CDATA, "section");
4203 else
4204 padd("draw:kind", sXML_CDATA, "arc");
4205 padd("draw:start-angle", sXML_CDATA, Double2Str(start_angle ));
4206 padd("draw:end-angle", sXML_CDATA, Double2Str(end_angle));
4209 rstartEl("draw:ellipse", mxList.get());
4210 mxList->clear();
4211 if( drawobj->property.flag >> 19 & 0x01 &&
4212 drawobj->property.pPara ) // As Textbox
4214 HWPPara *pPara = drawobj->property.pPara;
4215 //parsePara(pPara);
4216 while(pPara)
4218 make_text_p1( pPara, false );
4219 pPara = pPara->Next();
4222 rendEl("draw:ellipse");
4223 break;
4226 case HWPDO_ARC: /* Arc */
4227 case HWPDO_ADVANCED_ARC:
4229 /* If it is the arc, LibreOffice assumes the size as the entire ellipse size */
4230 uint flip = drawobj->u.line_arc.flip;
4231 if( !bIsRotate )
4233 if( ( flip == 0 || flip == 2 ) && drawobj->type == HWPDO_ARC)
4234 padd("svg:x", sXML_CDATA,
4235 Double2Str (WTMM( x + a + drawobj->offset2.x - drawobj->extent.w)) + "mm");
4236 else
4237 padd("svg:x", sXML_CDATA,
4238 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4239 if( ( flip == 0 || flip == 1 ) && drawobj->type == HWPDO_ARC)
4240 padd("svg:y", sXML_CDATA,
4241 Double2Str (WTMM( y + b + drawobj->offset2.y - drawobj->extent.h)) + "mm");
4242 else
4243 padd("svg:y", sXML_CDATA,
4244 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4247 padd("svg:width", sXML_CDATA,
4248 Double2Str (WTMM( drawobj->extent.w * 2)) + "mm");
4249 padd("svg:height", sXML_CDATA,
4250 Double2Str (WTMM( drawobj->extent.h * 2)) + "mm");
4251 if( drawobj->property.flag & HWPDO_FLAG_DRAW_PIE ||
4252 drawobj->property.fill_color < 0xffffff )
4253 padd("draw:kind", sXML_CDATA, "section");
4254 else
4255 padd("draw:kind", sXML_CDATA, "arc");
4257 if( drawobj->type == HWPDO_ADVANCED_ARC ){
4258 double start_angle, end_angle;
4259 ZZParall *pal = &drawobj->property.parall;
4261 if( pal->pt[1].x == pal->pt[0].x ){
4262 if( pal->pt[0].y < pal->pt[1].y )
4263 start_angle = 1.5 * PI;
4264 else
4265 start_angle = 0.5 * PI;
4267 else{
4268 start_angle = atan(static_cast<double>( pal->pt[0].y - pal->pt[1].y )/( pal->pt[1].x - pal->pt[0].x ));
4269 if( pal->pt[1].x < pal->pt[0].x )
4270 start_angle += PI;
4272 if( pal->pt[1].x == pal->pt[2].x ){
4273 if( pal->pt[2].y < pal->pt[1].y )
4274 end_angle = 1.5 * PI;
4275 else
4276 end_angle = 0.5 * PI;
4278 else{
4279 end_angle = atan(static_cast<double>( pal->pt[2].y - pal->pt[1].y )/( pal->pt[1].x - pal->pt[2].x ));
4280 if( pal->pt[1].x < pal->pt[2].x )
4281 end_angle += PI;
4284 if( start_angle >= 2 * PI )
4285 start_angle -= 2 * PI;
4286 if( end_angle >= 2 * PI )
4287 end_angle -= 2 * PI;
4288 if( ( start_angle > end_angle ) && (start_angle - end_angle < PI )){
4289 double tmp_angle = start_angle;
4290 start_angle = end_angle;
4291 end_angle = tmp_angle;
4293 padd("draw:start-angle", sXML_CDATA, Double2Str(start_angle * 180. / PI));
4294 padd("draw:end-angle", sXML_CDATA, Double2Str(end_angle * 180. / PI));
4297 else{
4298 if( drawobj->u.line_arc.flip == 0 )
4300 padd("draw:start-angle", sXML_CDATA, "270");
4301 padd("draw:end-angle", sXML_CDATA, "0");
4303 else if( drawobj->u.line_arc.flip == 1 )
4305 padd("draw:start-angle", sXML_CDATA, "180");
4306 padd("draw:end-angle", sXML_CDATA, "270");
4308 else if( drawobj->u.line_arc.flip == 2 )
4310 padd("draw:start-angle", sXML_CDATA, "0");
4311 padd("draw:end-angle", sXML_CDATA, "90");
4313 else
4315 padd("draw:start-angle", sXML_CDATA, "90");
4316 padd("draw:end-angle", sXML_CDATA, "180");
4319 rstartEl("draw:ellipse", mxList.get());
4320 mxList->clear();
4321 if( drawobj->property.flag >> 19 & 0x01 &&
4322 drawobj->property.pPara ) // As Textbox
4324 HWPPara *pPara = drawobj->property.pPara;
4325 //parsePara(pPara);
4326 while(pPara)
4328 make_text_p1( pPara, false );
4329 pPara = pPara->Next();
4332 rendEl("draw:ellipse");
4333 break;
4336 case HWPDO_CURVE: /* Curve: converts to polygons. */
4338 bool bIsNatural = true;
4339 if( drawobj->property.flag >> 5 & 0x01){
4340 bIsNatural = false;
4342 if( !bIsRotate )
4344 padd("svg:x", sXML_CDATA,
4345 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4346 padd("svg:y", sXML_CDATA,
4347 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4349 padd("svg:width", sXML_CDATA,
4350 Double2Str (WTMM( drawobj->extent.w )) + "mm");
4351 padd("svg:height", sXML_CDATA,
4352 Double2Str (WTMM( drawobj->extent.h )) + "mm");
4353 sprintf(buf, "0 0 %d %d", WTSM(drawobj->extent.w) , WTSM(drawobj->extent.h) );
4354 padd("svg:viewBox", sXML_CDATA, ascii(buf) );
4356 OUStringBuffer oustr;
4358 if ((drawobj->u.freeform.npt > 2) &&
4359 (o3tl::make_unsigned(drawobj->u.freeform.npt) <
4360 (::std::numeric_limits<int>::max() / sizeof(double))))
4362 int n, i;
4363 n = drawobj->u.freeform.npt;
4365 std::unique_ptr<double[]> xarr( new double[n+1] );
4366 std::unique_ptr<double[]> yarr( new double[n+1] );
4367 std::unique_ptr<double[]> tarr( new double[n+1] );
4369 std::unique_ptr<double[]> xb;
4370 std::unique_ptr<double[]> yb;
4372 std::unique_ptr<double[]> carr;
4373 std::unique_ptr<double[]> darr;
4376 for( i = 0 ; i < n ; i++ ){
4377 xarr[i] = drawobj->u.freeform.pt[i].x;
4378 yarr[i] = drawobj->u.freeform.pt[i].y;
4379 tarr[i] = i;
4381 xarr[n] = xarr[0];
4382 yarr[n] = yarr[0];
4383 tarr[n] = n;
4385 if( !bIsNatural ){
4386 PeriodicSpline(n, tarr.get(), xarr.get(), xb, carr, darr);
4387 // prevent memory leak
4388 carr.reset();
4389 darr.reset();
4390 PeriodicSpline(n, tarr.get(), yarr.get(), yb, carr, darr);
4392 else{
4393 NaturalSpline(n, tarr.get(), xarr.get(), xb, carr, darr);
4394 // prevent memory leak
4395 carr.reset();
4396 darr.reset();
4397 NaturalSpline(n, tarr.get(), yarr.get(), yb, carr, darr);
4400 sprintf(buf, "M%d %dC%d %d", WTSM(xarr[0]), WTSM(yarr[0]),
4401 WTSM(xarr[0] + xb[0]/3), WTSM(yarr[0] + yb[0]/3) );
4402 oustr.append(ascii(buf));
4404 for( i = 1 ; i < n ; i++ ){
4405 if( i == n -1 ){
4406 sprintf(buf, " %d %d %d %dz",
4407 WTSM(xarr[i] - xb[i]/3), WTSM(yarr[i] - yb[i]/3),
4408 WTSM(xarr[i]), WTSM(yarr[i]) );
4410 else{
4411 sprintf(buf, " %d %d %d %d %d %d",
4412 WTSM(xarr[i] - xb[i]/3), WTSM(yarr[i] - yb[i]/3),
4413 WTSM(xarr[i]), WTSM(yarr[i]),
4414 WTSM(xarr[i] + xb[i]/3), WTSM(yarr[i] + yb[i]/3) );
4417 oustr.append(ascii(buf));
4421 padd("svg:d", sXML_CDATA, oustr.makeStringAndClear());
4423 rstartEl("draw:path", mxList.get());
4424 mxList->clear();
4425 // As Textbox
4426 if( drawobj->property.flag >> 19 & 0x01 && drawobj->property.pPara )
4428 HWPPara *pPara = drawobj->property.pPara;
4429 while(pPara)
4431 make_text_p1( pPara, false );
4432 pPara = pPara->Next();
4435 rendEl("draw:path");
4436 break;
4438 case HWPDO_CLOSED_FREEFORM:
4439 case HWPDO_FREEFORM: /* polygon */
4441 bool bIsPolygon = false;
4443 padd("svg:x", sXML_CDATA,
4444 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4445 padd("svg:y", sXML_CDATA,
4446 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4448 padd("svg:width", sXML_CDATA,
4449 Double2Str (WTMM( drawobj->extent.w )) + "mm");
4450 padd("svg:height", sXML_CDATA,
4451 Double2Str (WTMM( drawobj->extent.h )) + "mm");
4453 sprintf(buf, "0 0 %d %d", WTSM(drawobj->extent.w), WTSM(drawobj->extent.h));
4454 padd("svg:viewBox", sXML_CDATA, ascii(buf) );
4456 OUStringBuffer oustr;
4458 if (drawobj->u.freeform.npt > 0)
4460 sprintf(buf, "%d,%d", WTSM(drawobj->u.freeform.pt[0].x), WTSM(drawobj->u.freeform.pt[0].y));
4461 oustr.append(ascii(buf));
4462 int i;
4463 for (i = 1; i < drawobj->u.freeform.npt ; i++)
4465 sprintf(buf, " %d,%d",
4466 WTSM(drawobj->u.freeform.pt[i].x),
4467 WTSM(drawobj->u.freeform.pt[i].y));
4468 oustr.append(ascii(buf));
4470 if( drawobj->u.freeform.pt[0].x == drawobj->u.freeform.pt[i-1].x &&
4471 drawobj->u.freeform.pt[0].y == drawobj->u.freeform.pt[i-1].y )
4473 bIsPolygon = true;
4476 padd("draw:points", sXML_CDATA, oustr.makeStringAndClear());
4478 if( drawobj->property.fill_color <= 0xffffff ||
4479 drawobj->property.pattern_type != 0)
4481 bIsPolygon = true;
4484 if(bIsPolygon)
4486 rstartEl("draw:polygon", mxList.get());
4487 mxList->clear();
4488 if( drawobj->property.flag >> 19 & 0x01 &&
4489 // As Textbox
4490 drawobj->property.pPara )
4492 HWPPara *pPara = drawobj->property.pPara;
4493 // parsePara(pPara);
4494 while(pPara)
4496 make_text_p1( pPara, false );
4497 pPara = pPara->Next();
4500 rendEl("draw:polygon");
4502 else
4504 rstartEl("draw:polyline", mxList.get());
4505 mxList->clear();
4506 if( drawobj->property.flag >> 19 & 0x01 &&
4507 // As Textbox
4508 drawobj->property.pPara )
4510 HWPPara *pPara = drawobj->property.pPara;
4511 //parsePara(pPara);
4512 while(pPara)
4514 make_text_p1( pPara, false );
4515 pPara = pPara->Next();
4518 rendEl("draw:polyline");
4520 break;
4522 case HWPDO_TEXTBOX:
4523 if( !bIsRotate )
4525 padd("svg:x", sXML_CDATA,
4526 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4527 padd("svg:y", sXML_CDATA,
4528 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4530 padd("svg:width", sXML_CDATA,
4531 Double2Str (WTMM( drawobj->extent.w )) + "mm");
4532 padd("svg:height", sXML_CDATA,
4533 Double2Str (WTMM( drawobj->extent.h )) + "mm");
4534 if( drawobj->property.flag & 0x01 )
4536 int value = drawobj->extent.w < drawobj->extent.h ?
4537 drawobj->extent.w : drawobj->extent.h ;
4538 padd("draw:corner-radius", sXML_CDATA,
4539 Double2Str (WTMM( value/10 )) + "mm");
4541 else if( drawobj->property.flag & 0x04 )
4543 int value = drawobj->extent.w < drawobj->extent.h ?
4544 drawobj->extent.w : drawobj->extent.h ;
4545 padd("draw:corner-radius", sXML_CDATA,
4546 Double2Str (WTMM( value / 2)) + "mm");
4549 rstartEl("draw:text-box", mxList.get());
4550 mxList->clear();
4552 HWPPara *pPara = drawobj->u.textbox.h;
4553 //parsePara(pPara);
4554 while(pPara)
4556 make_text_p1( pPara, false );
4557 pPara = pPara->Next();
4560 rendEl("draw:text-box");
4561 break;
4564 mxList->clear();
4565 drawobj = drawobj->next.get();
4570 void HwpReader::makeLine()
4572 padd("text:style-name", sXML_CDATA, "Horizontal Line");
4573 rstartEl( "text:p", mxList.get());
4574 mxList->clear();
4579 * Input-comment-hidden description: shows a hidden explanation to the users.
4580 * Parse out only strings, but it may contain paragraphs.
4582 void HwpReader::makeHidden(Hidden * hbox)
4584 hchar_string str;
4585 int res;
4586 hchar dest[3];
4588 padd("text:condition", sXML_CDATA, "");
4589 padd("text:string-value", sXML_CDATA, "");
4590 rstartEl("text:hidden-text", mxList.get());
4591 mxList->clear();
4592 HWPPara *para = hbox->plist.front().get();
4594 while (para)
4596 for (int n = 0; n < para->nch && para->hhstr[n]->hh;
4597 n += para->hhstr[n]->WSize())
4599 res = hcharconv(para->hhstr[n]->hh, dest, UNICODE);
4600 for( int j = 0 ; j < res ; j++ )
4602 str.push_back(dest[j]);
4605 para = para->Next();
4607 makeChars(str);
4608 rendEl("text:hidden-text");
4613 * Converts footnote to text:footnote, endnote to text:endnote
4615 void HwpReader::makeFootnote(Footnote * hbox)
4617 if (hbox->type)
4619 padd("text:id", sXML_CDATA,
4620 ascii(Int2Str(hbox->number, "edn%d", buf)));
4621 rstartEl("text:endnote", mxList.get());
4622 mxList->clear();
4623 padd("text:label", sXML_CDATA,
4624 ascii(Int2Str(hbox->number, "%d", buf)));
4625 rstartEl("text:endnote-citation", mxList.get());
4626 mxList->clear();
4627 rchars(ascii(Int2Str(hbox->number, "%d", buf)));
4628 rendEl("text:endnote-citation");
4629 rstartEl("text:endnote-body", mxList.get());
4630 parsePara(hbox->plist.front().get());
4631 rendEl("text:endnote-body");
4632 rendEl("text:endnote");
4634 else
4636 padd("text:id", sXML_CDATA,
4637 ascii(Int2Str(hbox->number, "ftn%d", buf)));
4638 rstartEl("text:footnote", mxList.get());
4639 mxList->clear();
4640 padd("text:label", sXML_CDATA,
4641 ascii(Int2Str(hbox->number, "%d", buf)));
4642 rstartEl("text:footnote-citation", mxList.get());
4643 mxList->clear();
4644 rchars(ascii(Int2Str(hbox->number, "%d", buf)));
4645 rendEl("text:footnote-citation");
4646 rstartEl("text:footnote-body", mxList.get());
4647 parsePara(hbox->plist.front().get());
4648 rendEl("text:footnote-body");
4649 rendEl("text:footnote");
4655 * page/footnote/endnote/picture/table/formula number
4657 void HwpReader::makeAutoNum(AutoNum const * hbox)
4659 switch (hbox->type)
4661 case PGNUM_AUTO:
4662 rstartEl("text:page-number", mxList.get());
4663 rchars(ascii(Int2Str(hbox->number, "%d", buf)));
4664 rendEl("text:page-number");
4665 break;
4666 case FNNUM_AUTO:
4667 break;
4668 case ENNUM_AUTO:
4669 break;
4670 case EQUNUM_AUTO:
4671 case PICNUM_AUTO:
4672 padd("text:ref-name",sXML_CDATA,
4673 ascii(Int2Str(hbox->number, "refIllustration%d", buf)));
4674 padd("text:name",sXML_CDATA, "Illustration");
4675 padd("style:num-format",sXML_CDATA, "1");
4676 rstartEl("text:sequence", mxList.get());
4677 rchars(ascii(Int2Str(hbox->number, "%d", buf)));
4678 rendEl("text:sequence");
4679 break;
4680 case TBLNUM_AUTO:
4681 padd("text:ref-name",sXML_CDATA,
4682 ascii(Int2Str(hbox->number, "refTable%d", buf)));
4683 padd("text:name",sXML_CDATA, "Table");
4684 padd("style:num-format",sXML_CDATA, "1");
4685 rstartEl("text:sequence", mxList.get());
4686 rchars(ascii(Int2Str(hbox->number, "%d", buf)));
4687 rendEl("text:sequence");
4688 break;
4693 void HwpReader::makeShowPageNum()
4695 ShowPageNum *hbox = d->pPn;
4696 int nPos = 0;
4697 if( hbox->where == 1 || hbox->where == 4 )
4698 nPos = 1;
4699 else if( hbox->where == 2 || hbox->where == 5 )
4700 nPos = 2;
4701 else if( hbox->where == 3 || hbox->where == 6 )
4702 nPos = 3;
4703 else /* should not exist in this case. */
4705 if( d->nPnPos == 1 )
4706 nPos = 1;
4707 else if( d->nPnPos == 3 )
4708 nPos = 3;
4711 padd("draw:style-name", sXML_CDATA,
4712 ascii(Int2Str(nPos, "PNBox%d", buf)));
4713 padd("draw:name", sXML_CDATA,
4714 ascii(Int2Str(nPos, "PageNumber%d", buf)));
4715 padd("text:anchor-type", sXML_CDATA, "paragraph");
4716 padd("svg:y", sXML_CDATA, "0cm");
4717 padd("svg:width", sXML_CDATA, "2.0cm");
4718 padd("fo:min-height", sXML_CDATA, "0.5cm");
4719 rstartEl("draw:text-box", mxList.get());
4720 mxList->clear();
4722 padd("text:style-name", sXML_CDATA,
4723 ascii(Int2Str(nPos, "PNPara%d", buf)));
4724 rstartEl("text:p", mxList.get());
4725 mxList->clear();
4726 if( hbox->shape > 2 )
4727 rchars("- ");
4728 if( hbox->shape % 3 == 0 )
4729 padd("style:num-format", sXML_CDATA, "1");
4730 else if( hbox->shape % 3 == 1 )
4731 padd("style:num-format", sXML_CDATA, "I");
4732 else
4733 padd("style:num-format", sXML_CDATA, "i");
4734 padd("text:select-page", sXML_CDATA, "current");
4735 rstartEl("text:page-number", mxList.get());
4736 mxList->clear();
4737 rchars("2");
4738 rendEl("text:page-number");
4739 if( hbox->shape > 2 )
4740 rchars(" -");
4741 rendEl("text:p");
4742 rendEl("draw:text-box");
4747 * mail merge operation using hwp addressbook and hwp data form.
4748 * not support operation in OO writer.
4750 void HwpReader::makeMailMerge(MailMerge *)
4752 hchar_string const boxstr = MailMerge::GetString();
4753 rchars(fromHcharStringToOUString(hstr2ucsstr(boxstr.c_str())));
4757 void HwpReader::makeOutline(Outline const * hbox)
4759 if( hbox->kind == 1 )
4760 rchars( fromHcharStringToOUString(hbox->GetUnicode()) );
4764 void HwpReader::parsePara(HWPPara * para)
4766 bool bParaStart = false;
4767 while (para)
4769 if( para->nch == 1)
4771 if( !bParaStart )
4773 padd("text:style-name", sXML_CDATA,
4774 ascii(getPStyleName(para->GetParaShape().index, buf)));
4775 rstartEl( "text:p",mxList.get());
4776 mxList->clear();
4778 if( d->bFirstPara && d->bInBody )
4780 /* for HWP's Bookmark */
4781 strcpy(
4782 buf,
4783 "[\xEB\xAC\xB8\xEC\x84\x9C\xEC\x9D\x98"
4784 " \xEC\xB2\x98\xEC\x9D\x8C]");
4785 // U+BB38 HANGUL SYLLABLE MUN, U+C11C HANGUL SYLLABLE SEO,
4786 // U+C758 HANGUL SYLLABLE YI, U+CC98 HANGUL SYLLABLE CEO,
4787 // U+C74C HANGUL SYLLABLE EUM: "Begin of Document"
4788 padd("text:name", sXML_CDATA, OUString(buf, strlen(buf), RTL_TEXTENCODING_UTF8));
4789 rstartEl("text:bookmark", mxList.get());
4790 mxList->clear();
4791 rendEl("text:bookmark");
4792 d->bFirstPara = false;
4794 if( d->bInHeader )
4796 makeShowPageNum();
4797 d->bInHeader = false;
4800 rendEl( "text:p" );
4802 else
4804 if (!para->ctrlflag)
4806 if (para->contain_cshape)
4807 make_text_p1(para, bParaStart);
4808 else
4809 make_text_p0(para, bParaStart);
4811 else
4812 make_text_p3(para, bParaStart);
4814 bParaStart = false;
4815 para = para->Next();
4820 namespace
4823 constexpr OUStringLiteral IMPLEMENTATION_NAME = u"com.sun.comp.hwpimport.HwpImportFilter";
4824 constexpr OUStringLiteral SERVICE_NAME1 = u"com.sun.star.document.ImportFilter";
4825 constexpr OUStringLiteral SERVICE_NAME2 = u"com.sun.star.document.ExtendedTypeDetection";
4827 class HwpImportFilter : public WeakImplHelper< XFilter, XImporter, XServiceInfo, XExtendedFilterDetection >
4829 public:
4830 explicit HwpImportFilter(const Reference< XComponentContext >& );
4832 public:
4833 // XFilter
4834 virtual sal_Bool SAL_CALL filter( const Sequence< PropertyValue >& aDescriptor ) override;
4835 virtual void SAL_CALL cancel() override;
4837 // XImporter
4838 virtual void SAL_CALL setTargetDocument( const Reference< XComponent >& xDoc) override;
4840 // XServiceInfo
4841 OUString SAL_CALL getImplementationName() override;
4842 Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
4843 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
4845 //XExtendedFilterDetection
4846 virtual OUString SAL_CALL detect( css::uno::Sequence< css::beans::PropertyValue >& rDescriptor ) override;
4848 private:
4849 Reference< XFilter > rFilter;
4850 Reference< XImporter > rImporter;
4854 HwpImportFilter::HwpImportFilter(const Reference< XComponentContext >& rxContext)
4856 try {
4857 Reference< XDocumentHandler > xHandler( rxContext->getServiceManager()->createInstanceWithContext( WRITER_IMPORTER_NAME, rxContext ), UNO_QUERY );
4859 HwpReader *p = new HwpReader;
4860 p->setDocumentHandler( xHandler );
4862 Reference< XImporter > xImporter( xHandler, UNO_QUERY );
4863 rImporter = xImporter;
4864 Reference< XFilter > xFilter( p );
4865 rFilter = xFilter;
4867 catch( Exception & )
4869 printf(" fail to instantiate %s\n", WRITER_IMPORTER_NAME );
4870 exit( 1 );
4874 sal_Bool HwpImportFilter::filter( const Sequence< PropertyValue >& aDescriptor )
4876 // delegate to IchitaroImporter
4877 return rFilter->filter( aDescriptor );
4880 void HwpImportFilter::cancel()
4882 rFilter->cancel();
4885 void HwpImportFilter::setTargetDocument( const Reference< XComponent >& xDoc )
4887 // delegate
4888 rImporter->setTargetDocument( xDoc );
4891 OUString HwpImportFilter::getImplementationName()
4893 return IMPLEMENTATION_NAME;
4896 sal_Bool HwpImportFilter::supportsService( const OUString& ServiceName )
4898 return cppu::supportsService(this, ServiceName);
4901 //XExtendedFilterDetection
4902 OUString HwpImportFilter::detect( css::uno::Sequence< css::beans::PropertyValue >& rDescriptor )
4904 OUString sTypeName;
4906 utl::MediaDescriptor aDescriptor(rDescriptor);
4907 aDescriptor.addInputStream();
4909 Reference< XInputStream > xInputStream(
4910 aDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM()], UNO_QUERY);
4912 if (xInputStream.is())
4914 Sequence< sal_Int8 > aData;
4915 sal_Int32 nLen = HWPIDLen;
4916 if (
4917 nLen == xInputStream->readBytes(aData, nLen) &&
4918 detect_hwp_version(reinterpret_cast<const char*>(aData.getConstArray()))
4921 sTypeName = "writer_MIZI_Hwp_97";
4925 return sTypeName;
4928 Sequence< OUString> HwpImportFilter::getSupportedServiceNames()
4930 return { SERVICE_NAME1, SERVICE_NAME2 };
4935 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
4936 hwpfilter_HwpImportFilter_get_implementation(
4937 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const&)
4939 return cppu::acquire(new HwpImportFilter(context));
4943 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */