Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / hwpfilter / source / hwpreader.cxx
blob4144d20e0bdee07856a3bf563324782329479950
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 <osl/diagnose.h>
27 #include <tools/stream.hxx>
29 #include "fontmap.hxx"
30 #include "formula.h"
31 #include "cspline.h"
32 #include "datecode.h"
34 #include <iostream>
35 #include <locale.h>
36 #include <sal/types.h>
37 #include <rtl/ustrbuf.hxx>
39 // To be shorten source code by realking
40 #define hconv(x) hstr2ucsstr(x).c_str()
41 #define ascii(x) OUString::createFromAscii(x)
42 #define rstartEl(x,y) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->startElement(x,y); } while(false)
43 #define rendEl(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->endElement(x); } while(false)
44 #define rchars(x) do { if (m_rxDocumentHandler.is()) m_rxDocumentHandler->characters(x); } while(false)
45 #define padd(x,y,z) mxList->addAttribute(x,y,z)
46 #define Double2Str(x) OUString::number(x)
47 #define WTI(x) (static_cast<double>(x) / 1800.) // unit => inch
48 #define WTMM(x) (static_cast<double>(x) / 1800. * 25.4) // unit => mm
49 #define WTSM(x) (static_cast<int>((x) / 1800. * 2540)) // unit ==> 1/100 mm
51 #define PI 3.14159265358979323846
53 // xmloff/xmlkyd.hxx
54 #define sXML_CDATA "CDATA"
56 #define STARTP padd( "text:style-name", "CDATA", ascii(getPStyleName((para->GetParaShape()).index,buf))); \
57 rstartEl( "text:p",mxList.get() ); \
58 mxList->clear(); \
59 pstart = true
60 #define STARTT \
61 curr = para->GetCharShape(n > 0 ? n-1 : 0)->index; \
62 padd( "text:style-name", "CDATA" , ascii( getTStyleName(curr, buf) ) ); \
63 rstartEl( "text:span",mxList.get() ); \
64 mxList->clear(); \
65 tstart = true
66 #define ENDP \
67 rendEl("text:p"); \
68 pstart = false
69 #define ENDT \
70 rendEl("text:span"); \
71 tstart = false
73 static hchar *field = nullptr;
74 static char buf[1024];
76 namespace
79 template<typename T>
80 struct Free
82 void operator()(T* const ptr)
84 free(ptr);
90 struct HwpReaderPrivate
92 HwpReaderPrivate()
94 bFirstPara = true;
95 bInBody = false;
96 bInHeader = false;
97 nPnPos = 0;
98 pPn = nullptr;
101 bool bFirstPara;
102 bool bInBody;
103 bool bInHeader;
104 ShowPageNum *pPn;
105 int nPnPos;
108 HwpReader::HwpReader()
110 mxList = new AttributeListImpl;
111 d.reset( new HwpReaderPrivate );
115 HwpReader::~HwpReader()
119 extern "C" SAL_DLLPUBLIC_EXPORT bool TestImportHWP(SvStream &rStream)
123 std::unique_ptr<HStream> stream(new HStream);
124 byte aData[32768];
126 while (true)
128 std::size_t nRead = rStream.ReadBytes(aData, 32768);
129 if (nRead == 0)
130 break;
131 stream->addData(aData, static_cast<int>(nRead));
134 HWPFile hwpfile;
135 if (hwpfile.ReadHwpFile(std::move(stream)))
136 return false;
138 catch (...)
140 return false;
142 return true;
145 sal_Bool HwpReader::filter(const Sequence< PropertyValue >& rDescriptor)
147 utl::MediaDescriptor aDescriptor(rDescriptor);
148 aDescriptor.addInputStream();
150 Reference< XInputStream > xInputStream(
151 aDescriptor[utl::MediaDescriptor::PROP_INPUTSTREAM()], UNO_QUERY_THROW);
153 std::unique_ptr<HStream> stream(new HStream);
154 Sequence < sal_Int8 > aBuffer;
155 sal_Int32 nRead, nTotal = 0;
156 while( true )
158 nRead = xInputStream->readBytes(aBuffer, 32768);
159 if( nRead == 0 )
160 break;
161 stream->addData( reinterpret_cast<const byte *>(aBuffer.getConstArray()), nRead );
162 nTotal += nRead;
165 if( nTotal == 0 ) return false;
167 if (hwpfile.ReadHwpFile(std::move(stream)))
168 return false;
170 if (m_rxDocumentHandler.is())
171 m_rxDocumentHandler->startDocument();
173 padd("office:class", sXML_CDATA, "text");
174 padd("office:version", sXML_CDATA, "0.9");
176 padd("xmlns:office", "CDATA", "http://openoffice.org/2000/office");
177 padd("xmlns:style", "CDATA", "http://openoffice.org/2000/style");
178 padd("xmlns:text", "CDATA", "http://openoffice.org/2000/text");
179 padd("xmlns:table", "CDATA", "http://openoffice.org/2000/table");
180 padd("xmlns:draw", "CDATA", "http://openoffice.org/2000/drawing");
181 padd("xmlns:fo", "CDATA", "http://www.w3.org/1999/XSL/Format");
182 padd("xmlns:xlink", "CDATA", "http://www.w3.org/1999/xlink");
183 padd("xmlns:dc", "CDATA", "http://purl.org/dc/elements/1.1/");
184 padd("xmlns:meta", "CDATA", "http://openoffice.org/2000/meta");
185 padd("xmlns:number", "CDATA", "http://openoffice.org/2000/datastyle");
186 padd("xmlns:svg", "CDATA", "http://www.w3.org/2000/svg");
187 padd("xmlns:chart", "CDATA", "http://openoffice.org/2000/chart");
188 padd("xmlns:dr3d", "CDATA", "http://openoffice.org/2000/dr3d");
189 padd("xmlns:math", "CDATA", "http://www.w3.org/1998/Math/MathML");
190 padd("xmlns:form", "CDATA", "http://openoffice.org/2000/form");
191 padd("xmlns:script", "CDATA", "http://openoffice.org/2000/script");
193 rstartEl("office:document", mxList.get());
194 mxList->clear();
196 makeMeta();
197 makeStyles();
198 makeAutoStyles();
199 makeMasterStyles();
200 makeBody();
202 rendEl("office:document");
204 if (m_rxDocumentHandler.is())
205 m_rxDocumentHandler->endDocument();
206 return true;
211 * make office:body
213 void HwpReader::makeBody()
215 rstartEl("office:body", mxList.get());
216 makeTextDecls();
217 HWPPara *hwppara = hwpfile.GetFirstPara();
218 d->bInBody = true;
219 parsePara(hwppara);
220 rendEl("office:body");
221 d->bInBody = false;
226 * make text decls
228 void HwpReader::makeTextDecls()
230 rstartEl("text:sequence-decls", mxList.get());
231 padd("text:display-outline-level", sXML_CDATA, "0");
232 padd("text:name", sXML_CDATA, "Illustration");
233 rstartEl("text:sequence-decl", mxList.get());
234 mxList->clear();
235 rendEl("text:sequence-decl");
236 padd("text:display-outline-level", sXML_CDATA, "0");
237 padd("text:name", sXML_CDATA, "Table");
238 rstartEl("text:sequence-decl", mxList.get());
239 mxList->clear();
240 rendEl("text:sequence-decl");
241 padd("text:display-outline-level", sXML_CDATA, "0");
242 padd("text:name", sXML_CDATA, "Text");
243 rstartEl("text:sequence-decl", mxList.get());
244 mxList->clear();
245 rendEl("text:sequence-decl");
246 padd("text:display-outline-level", sXML_CDATA, "0");
247 padd("text:name", sXML_CDATA, "Drawing");
248 rstartEl("text:sequence-decl", mxList.get());
249 mxList->clear();
250 rendEl("text:sequence-decl");
251 rendEl("text:sequence-decls");
255 #define ISNUMBER(x) ( (x) <= 0x39 && (x) >= 0x30 )
257 * make office:meta
258 * Completed
260 void HwpReader::makeMeta()
262 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
264 rstartEl("office:meta", mxList.get());
266 if (hwpinfo.summary.title[0])
268 rstartEl("dc:title", mxList.get());
269 rchars(reinterpret_cast<sal_Unicode const *>(hconv(hwpinfo.summary.title)));
270 rendEl("dc:title");
273 if (hwpinfo.summary.subject[0])
275 rstartEl("dc:subject", mxList.get());
276 rchars(reinterpret_cast<sal_Unicode const *>(hconv(hwpinfo.summary.subject)));
277 rendEl("dc:subject");
280 if (hwpinfo.summary.author[0])
282 rstartEl("meta:initial-creator", mxList.get());
283 rchars(reinterpret_cast<sal_Unicode const *>(hconv(hwpinfo.summary.author)));
284 rendEl("meta:initial-creator");
287 if (hwpinfo.summary.date[0])
289 unsigned short *pDate = hwpinfo.summary.date;
290 int year,month,day,hour,minute;
291 int gab = 0;
292 if( ISNUMBER( pDate[0] ) && ISNUMBER( pDate[1] ) &&
293 ISNUMBER( pDate[2] ) && ISNUMBER( pDate[3] ))
295 year = (pDate[0]-0x30) * 1000 + (pDate[1]-0x30) * 100 +
296 (pDate[2]-0x30) * 10 + (pDate[3]-0x30);
298 else {
299 year = 0;
301 if( ISNUMBER( pDate[6] ))
303 if( ISNUMBER( pDate[7] ) )
304 month = (pDate[6] - 0x30) * 10 + (pDate[6+ ++gab]-0x30);
305 else
306 month = (pDate[6] - 0x30);
308 else {
309 month = 0;
311 if( ISNUMBER( pDate[9 + gab] ) )
313 if( ISNUMBER( pDate[10 + gab])) {
314 day = ( pDate[9 + gab] - 0x30 ) * 10 + (pDate[9+ gab + 1]-0x30);
315 ++gab;
316 } else
317 day = (pDate[9+gab]-0x30);
319 else {
320 day = 0;
322 if( ISNUMBER( pDate[17 + gab] ) )
324 if( ISNUMBER( pDate[18 + gab])) {
325 hour = ( pDate[17 + gab] - 0x30 ) * 10 + (pDate[17+ gab + 1]-0x30);
326 ++gab;
327 } else
328 hour = (pDate[17+gab]-0x30);
330 else {
331 hour = 0;
333 if( ISNUMBER( pDate[20 + gab] ) )
335 if( ISNUMBER( pDate[21 + gab])) {
336 minute = ( pDate[20 + gab] - 0x30 ) * 10 + (pDate[20+ gab + 1]-0x30);
337 ++gab;
338 } else
339 minute = (pDate[20+gab]-0x30);
341 else {
342 minute = 0;
344 sprintf(buf,"%d-%02d-%02dT%02d:%02d:00",year,month,day,hour,minute);
346 rstartEl( "meta:creation-date", mxList.get() );
347 rchars( ascii(buf));
348 rendEl( "meta:creation-date" );
351 if (hwpinfo.summary.keyword[0][0] || hwpinfo.summary.etc[0][0])
353 rstartEl("meta:keywords", mxList.get());
354 if (hwpinfo.summary.keyword[0][0])
356 rstartEl("meta:keyword", mxList.get());
357 rchars(reinterpret_cast<sal_Unicode const *>(hconv(hwpinfo.summary.keyword[0])));
358 rendEl("meta:keyword");
360 if (hwpinfo.summary.keyword[1][0])
362 rstartEl("meta:keyword", mxList.get());
363 rchars(reinterpret_cast<sal_Unicode const *>(hconv(hwpinfo.summary.keyword[1])));
364 rendEl("meta:keyword");
366 if (hwpinfo.summary.etc[0][0])
368 rstartEl("meta:keyword", mxList.get());
369 rchars(reinterpret_cast<sal_Unicode const *>(hconv(hwpinfo.summary.etc[0])));
370 rendEl("meta:keyword");
372 if (hwpinfo.summary.etc[1][0])
374 rstartEl("meta:keyword", mxList.get());
375 rchars(reinterpret_cast<sal_Unicode const *>(hconv(hwpinfo.summary.etc[1])));
376 rendEl("meta:keyword");
378 if (hwpinfo.summary.etc[2][0])
380 rstartEl("meta:keyword", mxList.get());
381 rchars(reinterpret_cast<sal_Unicode const *>(hconv(hwpinfo.summary.etc[2])));
382 rendEl("meta:keyword");
384 rendEl("meta:keywords");
386 rendEl("office:meta");
390 static struct
392 const char *name;
393 bool bMade;
395 ArrowShape[] =
397 { "", false },
398 { "Arrow", false },
399 { "Line Arrow", false },
400 { "Square", false }
403 static struct
405 double dots1;
406 double dots2;
407 double distance;
411 const LineStyle[] =
413 { 0.0, 0.0, 0.0 },
415 0.34, 0., 0.272
417 { 0.17, 0., 0.136},
419 0.612, 0.17, 0.136
421 { 0.85, 0.17, 0.136}
424 void HwpReader::makeDrawMiscStyle( HWPDrawingObject *hdo )
426 while( hdo )
428 if( hdo->child )
429 makeDrawMiscStyle( hdo->child.get() );
431 HWPDOProperty *prop = &hdo->property;
432 if( hdo->type == HWPDO_CONTAINER )
434 hdo = hdo->next.get();
435 continue;
438 if( prop->line_pstyle > 0 && prop->line_pstyle < 5 && prop->line_color <= 0xffffff)
440 padd( "draw:name", sXML_CDATA, ascii(Int2Str(hdo->index, "LineType%d", buf)));
441 padd( "draw:style", sXML_CDATA, "round");
442 padd( "draw:dots1", sXML_CDATA, "1");
443 padd( "draw:dots1-length", sXML_CDATA, Double2Str( LineStyle[prop->line_pstyle].dots1 * WTMM(prop->line_width) ) + "cm");
444 if( prop->line_pstyle == 3 )
446 padd( "draw:dots2", sXML_CDATA, "1");
447 padd( "draw:dots2-length", sXML_CDATA, Double2Str( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width) ) + "cm");
449 else if( prop->line_pstyle == 4 )
451 padd( "draw:dots2", sXML_CDATA, "2");
452 padd( "draw:dots2-length", sXML_CDATA, Double2Str( LineStyle[prop->line_pstyle].dots2 * WTMM(prop->line_width)) + "cm");
454 padd( "draw:distance", sXML_CDATA, Double2Str( LineStyle[prop->line_pstyle].distance * WTMM(prop->line_width)) + "cm");
455 rstartEl( "draw:stroke-dash", mxList.get());
456 mxList->clear();
457 rendEl( "draw:stroke-dash" );
460 if( hdo->type == HWPDO_LINE || hdo->type == HWPDO_ARC || hdo->type == HWPDO_FREEFORM ||
461 hdo->type == HWPDO_ADVANCED_ARC )
463 if( prop->line_tstyle && !ArrowShape[prop->line_tstyle].bMade )
465 ArrowShape[prop->line_tstyle].bMade = true;
466 padd("draw:name", sXML_CDATA,
467 ascii(ArrowShape[prop->line_tstyle].name));
468 if( prop->line_tstyle == 1 )
470 padd("svg:viewBox", sXML_CDATA, "0 0 20 30");
471 padd("svg:d", sXML_CDATA, "m10 0-10 30h20z");
473 else if( prop->line_tstyle == 2 )
475 padd("svg:viewBox", sXML_CDATA, "0 0 1122 2243");
476 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");
478 else if( prop->line_tstyle == 3 )
480 padd("svg:viewBox", sXML_CDATA, "0 0 30 30");
481 padd("svg:d", sXML_CDATA, "m0 0h30v30h-30z");
483 rstartEl("draw:marker", mxList.get());
484 mxList->clear();
485 rendEl("draw:marker");
487 if( prop->line_hstyle && !ArrowShape[prop->line_hstyle].bMade)
489 ArrowShape[prop->line_hstyle].bMade = true;
490 padd("draw:name", sXML_CDATA,
491 ascii(ArrowShape[prop->line_hstyle].name));
492 if( prop->line_hstyle == 1 )
494 padd("svg:viewBox", sXML_CDATA, "0 0 20 30");
495 padd("svg:d", sXML_CDATA, "m10 0-10 30h20z");
497 else if( prop->line_hstyle == 2 )
499 padd("svg:viewBox", sXML_CDATA, "0 0 1122 2243");
500 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");
502 else if( prop->line_hstyle == 3 )
504 padd("svg:viewBox", sXML_CDATA, "0 0 20 20");
505 padd("svg:d", sXML_CDATA, "m0 0h20v20h-20z");
507 rstartEl("draw:marker", mxList.get());
508 mxList->clear();
509 rendEl("draw:marker");
513 if( hdo->type != HWPDO_LINE )
515 if( prop->flag >> 18 & 0x01 )
517 padd( "draw:name", sXML_CDATA, ascii(Int2Str(hdo->index, "fillimage%d", buf)));
518 if( !prop->pictype )
520 padd( "xlink:href", sXML_CDATA,
521 reinterpret_cast<sal_Unicode const *>(hconv(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(prop->szPatternFile).c_str())).c_str())));
523 else
525 EmPicture *emp = nullptr;
526 if ( strlen( prop->szPatternFile ) > 3)
527 emp = hwpfile.GetEmPictureByName(prop->szPatternFile);
528 if( emp )
530 char filename[128+17+9];
531 char dirname[128];
532 int fd;
533 #ifdef _WIN32
534 GetTempPathA(sizeof(dirname), dirname);
535 sprintf(filename, "%s%s",dirname, emp->name);
536 if( (fd = open( filename , _O_CREAT | _O_WRONLY | _O_BINARY , 0666)) >= 0 )
537 #else
538 strcpy(dirname, "/tmp/");
539 sprintf(filename, "%s%s", dirname, emp->name);
540 if( (fd = open( filename , O_CREAT | O_WRONLY , 0666)) >= 0 )
541 #endif
543 size_t nWritten = write(fd, emp->data.get(), emp->size);
544 OSL_VERIFY(nWritten == emp->size);
545 close(fd);
547 #ifdef _WIN32
548 int j;
549 for(j = 0 ; j < static_cast<int>(strlen( dirname )) ; j++)
551 if( dirname[j] == '\\' ) buf[j] = '/';
552 else buf[j] = dirname[j];
554 buf[j] = '\0';
555 sprintf(filename, "file:///%s%s",buf, emp->name );
556 #else
557 sprintf(filename, "file://%s%s",dirname, emp->name );
558 #endif
559 padd( "xlink:href", sXML_CDATA, ascii(filename));
561 else
563 padd( "xlink:href", sXML_CDATA,
564 reinterpret_cast<sal_Unicode const *>(hconv(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(prop->szPatternFile).c_str())).c_str())));
568 padd( "xlink:type", sXML_CDATA, "simple");
569 padd( "xlink:show", sXML_CDATA, "embed");
570 padd( "xlink:actuate", sXML_CDATA, "onLoad");
572 rstartEl( "draw:fill-image", mxList.get());
573 mxList->clear();
574 rendEl( "draw:fill-image");
576 /* If there is a gradient, when a bitmap file is present, this is the first. */
577 else if( prop->flag >> 16 & 0x01 ) /* existence gradient */
579 padd( "draw:name", sXML_CDATA, ascii(Int2Str(hdo->index, "Grad%d", buf)));
580 switch( prop->gstyle )
582 case 1 :
583 if( prop->center_y == 50 )
584 padd( "draw:style", sXML_CDATA, "axial");
585 else
586 padd( "draw:style", sXML_CDATA, "linear");
587 break;
588 case 2:
589 case 3:
590 padd( "draw:style", sXML_CDATA, "radial");
591 break;
592 case 4:
593 padd( "draw:style", sXML_CDATA, "square");
594 break;
595 default:
596 padd( "draw:style", sXML_CDATA, "linear");
597 break;
599 padd( "draw:cx", sXML_CDATA,ascii(Int2Str(prop->center_x, "%d%%", buf)));
600 padd( "draw:cy", sXML_CDATA,ascii(Int2Str(prop->center_y, "%d%%", buf)));
602 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
603 int default_color = 0xffffff;
604 if( hwpinfo.back_info.isset )
606 if( hwpinfo.back_info.color[0] > 0 || hwpinfo.back_info.color[1] > 0
607 || hwpinfo.back_info.color[2] > 0 )
608 default_color = hwpinfo.back_info.color[0] << 16 |
609 hwpinfo.back_info.color[1] << 8 | hwpinfo.back_info.color[2];
612 if( prop->fromcolor > 0xffffff )
613 prop->fromcolor = default_color;
614 if( prop->tocolor > 0xffffff )
615 prop->tocolor = default_color;
617 if( prop->gstyle == 1)
619 if( prop->center_y == 100 )
621 sprintf( buf, "#%02x%02x%02x", prop->tocolor & 0xff,
622 (prop->tocolor >> 8) & 0xff, (prop->tocolor >>16) & 0xff );
623 padd( "draw:start-color", sXML_CDATA, ascii( buf ));
624 sprintf( buf, "#%02x%02x%02x", prop->fromcolor & 0xff,
625 (prop->fromcolor >> 8) & 0xff, (prop->fromcolor >>16) & 0xff );
626 padd( "draw:end-color", sXML_CDATA, ascii( buf ));
628 else
630 sprintf( buf, "#%02x%02x%02x", prop->fromcolor & 0xff,
631 (prop->fromcolor >> 8) & 0xff, (prop->fromcolor >>16) & 0xff );
632 padd( "draw:start-color", sXML_CDATA, ascii( buf ));
633 sprintf( buf, "#%02x%02x%02x", prop->tocolor & 0xff,
634 (prop->tocolor >> 8) & 0xff, (prop->tocolor >>16) & 0xff );
635 padd( "draw:end-color", sXML_CDATA, ascii( buf ));
638 else
640 sprintf( buf, "#%02x%02x%02x", prop->tocolor & 0xff,
641 (prop->tocolor >> 8) & 0xff, (prop->tocolor >>16) & 0xff );
642 padd( "draw:start-color", sXML_CDATA,ascii( buf ));
644 sprintf( buf, "#%02x%02x%02x", prop->fromcolor & 0xff,
645 (prop->fromcolor >> 8) & 0xff, (prop->fromcolor >>16) & 0xff );
646 padd( "draw:end-color", sXML_CDATA,ascii( buf ));
648 if( prop->angle > 0 && ( prop->gstyle == 1 || prop->gstyle == 4))
650 int angle = 1800 - prop->angle * 10;
651 padd( "draw:angle", sXML_CDATA,
652 ascii(Int2Str( angle, "%d", buf)));
654 rstartEl( "draw:gradient", mxList.get() );
655 mxList->clear();
656 rendEl( "draw:gradient");
658 /* hatch */
659 else if( prop->pattern_type >> 24 & 0x01 )
661 int type = prop->pattern_type & 0xffffff;
662 padd( "draw:name", sXML_CDATA,
663 ascii(Int2Str(hdo->index, "Hatch%d", buf)));
664 if( type < 4 )
665 padd( "draw:style", sXML_CDATA, "single" );
666 else
667 padd( "draw:style", sXML_CDATA, "double" );
668 sprintf( buf, "#%02x%02x%02x",
669 sal_uInt16(prop->pattern_color & 0xff),
670 sal_uInt16((prop->pattern_color >> 8) & 0xff),
671 sal_uInt16((prop->pattern_color >>16) & 0xff) );
672 padd( "draw:color", sXML_CDATA, ascii( buf ));
673 padd( "draw:distance", sXML_CDATA, "0.12cm");
674 switch( type )
676 case 0 :
677 case 4 :
678 padd( "draw:rotation", sXML_CDATA, "0");
679 break;
680 case 1 :
681 padd( "draw:rotation", sXML_CDATA, "900");
682 break;
683 case 2 :
684 padd( "draw:rotation", sXML_CDATA, "1350");
685 break;
686 case 3 :
687 case 5 :
688 padd( "draw:rotation", sXML_CDATA, "450");
689 break;
691 rstartEl( "draw:hatch", mxList.get());
692 mxList->clear();
693 rendEl( "draw:hatch");
696 hdo = hdo->next.get();
701 void HwpReader::makeStyles()
703 HWPStyle& hwpstyle = hwpfile.GetHWPStyle();
705 rstartEl("office:styles", mxList.get());
707 int i;
708 for (i = 0; i < hwpfile.getFBoxStyleCount(); i++)
710 if( hwpfile.getFBoxStyle(i)->boxtype == 'D' )
712 makeDrawMiscStyle(static_cast<HWPDrawingObject *>(hwpfile.getFBoxStyle(i)->cell) );
716 padd("style:name", sXML_CDATA, "Standard");
717 padd("style:family", sXML_CDATA, "paragraph");
718 padd("style:class", sXML_CDATA, "text");
719 rstartEl("style:style", mxList.get());
720 mxList->clear();
722 padd("fo:line-height", sXML_CDATA, "160%");
723 padd("fo:text-align", sXML_CDATA, "justify");
724 rstartEl("style:properties", mxList.get());
725 mxList->clear();
726 rstartEl("style:tab-stops", mxList.get());
728 for( i = 1 ; i < 40 ; i++)
730 padd("style:position", sXML_CDATA,
731 Double2Str( WTI(1000 * i)) + "inch");
732 rstartEl("style:tab-stop", mxList.get());
733 mxList->clear();
734 rendEl("style:tab-stop");
736 rendEl("style:tab-stops");
737 rendEl("style:properties");
739 rendEl("style:style");
741 for (int ii = 0; ii < hwpstyle.Num(); ii++)
743 unsigned char *stylename = reinterpret_cast<unsigned char *>(hwpstyle.GetName(ii));
744 padd("style:name", sXML_CDATA, reinterpret_cast<sal_Unicode const *>(hconv(kstr2hstr(stylename).c_str())));
745 padd("style:family", sXML_CDATA, "paragraph");
746 padd("style:parent-style-name", sXML_CDATA, "Standard");
748 rstartEl("style:style", mxList.get());
750 mxList->clear();
752 parseCharShape(hwpstyle.GetCharShape(ii));
753 parseParaShape(hwpstyle.GetParaShape(ii));
755 rstartEl("style:properties", mxList.get());
756 mxList->clear();
757 rendEl("style:properties");
759 rendEl("style:style");
763 padd( "style:name", sXML_CDATA, "Header");
764 padd( "style:family", sXML_CDATA, "paragraph");
765 padd( "style:parent-style-name", sXML_CDATA, "Standard");
766 padd( "style:class", sXML_CDATA, "extra");
767 rstartEl("style:style", mxList.get());
768 mxList->clear();
769 rendEl("style:style");
773 padd( "style:name", sXML_CDATA, "Footer");
774 padd( "style:family", sXML_CDATA, "paragraph");
775 padd( "style:parent-style-name", sXML_CDATA, "Standard");
776 padd( "style:class", sXML_CDATA, "extra");
777 rstartEl("style:style", mxList.get());
778 mxList->clear();
780 rendEl("style:style");
783 if( hwpfile.linenumber > 0)
785 padd( "style:name", sXML_CDATA, "Horizontal Line");
786 padd( "style:family", sXML_CDATA, "paragraph");
787 padd( "style:parent-style-name", sXML_CDATA, "Standard");
788 padd( "style:class", sXML_CDATA, "html");
789 rstartEl( "style:style", mxList.get());
790 mxList->clear();
791 padd( "fo:font-size", sXML_CDATA, "6pt");
792 padd( "fo:margin-top", sXML_CDATA, "0cm");
793 padd( "fo:margin-bottom", sXML_CDATA, "0cm");
794 padd( "style:border-line-width-bottom", sXML_CDATA, "0.02cm 0.035cm 0.002cm");
795 padd( "fo:padding", sXML_CDATA, "0cm");
796 padd( "fo:border-bottom", sXML_CDATA, "0.039cm double #808080");
797 padd( "text:number-lines", sXML_CDATA, "false");
798 padd( "text:line-number", sXML_CDATA, "0");
799 padd("fo:line-height", sXML_CDATA, "100%");
800 rstartEl( "style:properties", mxList.get());
801 mxList->clear();
802 rendEl( "style:properties");
803 rendEl( "style:style");
806 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
808 padd("text:num-suffix", sXML_CDATA, ")");
809 padd("text:num-format", sXML_CDATA, "1");
810 if( hwpinfo.beginfnnum != 1)
811 padd("text:offset", sXML_CDATA, ascii(Int2Str(hwpinfo.beginfnnum -1, "%d", buf)));
812 rstartEl("text:footnotes-configuration", mxList.get());
813 mxList->clear();
814 rendEl("text:footnotes-configuration");
816 rendEl("office:styles");
821 * parse automatic styles from hwpfile
822 * 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.
823 * 1. supports for the styles of paragraph, text, fbox, and page.
825 void HwpReader::makeAutoStyles()
827 int i;
829 rstartEl("office:automatic-styles", mxList.get());
831 for (i = 0; i < hwpfile.getParaShapeCount(); i++)
832 makePStyle(hwpfile.getParaShape(i));
834 for (i = 0; i < hwpfile.getCharShapeCount(); i++)
835 makeTStyle(hwpfile.getCharShape(i));
837 for( i = 0 ; i < hwpfile.getTableCount(); i++)
838 makeTableStyle(hwpfile.getTable(i));
840 for (i = 0; i < hwpfile.getFBoxStyleCount(); i++)
842 if( hwpfile.getFBoxStyle(i)->boxtype == 'D' )
843 makeDrawStyle(static_cast<HWPDrawingObject *>(hwpfile.getFBoxStyle(i)->cell), hwpfile.getFBoxStyle(i));
844 else
845 makeFStyle(hwpfile.getFBoxStyle(i));
848 bool bIsLeft = false, bIsMiddle = false, bIsRight = false;
849 for( i = 0 ; i < hwpfile.getPageNumberCount() ; i++ )
851 ShowPageNum *pn = hwpfile.getPageNumber(i);
852 if( pn->where == 7 || pn->where == 8 )
854 bIsLeft = true;
855 bIsRight = true;
857 else if( pn->where == 1 || pn->where == 4 )
859 bIsLeft = true;
861 else if( pn->where == 2 || pn->where == 5 )
863 bIsMiddle = true;
865 else if( pn->where == 3 || pn->where == 6 )
867 bIsRight = true;
871 for( i = 1; i <= 3 ; i++ )
873 if( i == 1 && !bIsLeft )
874 continue;
875 if( i == 2 && !bIsMiddle )
876 continue;
877 if( i == 3 && !bIsRight )
878 continue;
879 padd("style:name", sXML_CDATA,
880 ascii(Int2Str(i,"PNPara%d", buf)));
881 padd("style:family", sXML_CDATA, "paragraph");
882 padd("style:parent-style-name", sXML_CDATA, "Standard");
883 rstartEl("style:style", mxList.get());
884 mxList->clear();
885 if( i == 1 )
886 padd("fo:text-align", sXML_CDATA, "start");
887 else if ( i == 2 )
888 padd("fo:text-align", sXML_CDATA, "center");
889 else if ( i == 3 )
890 padd("fo:text-align", sXML_CDATA, "end");
891 rstartEl("style:properties", mxList.get());
892 mxList->clear();
893 rendEl( "style:properties");
894 rendEl( "style:style");
896 padd("style:name", sXML_CDATA, ascii(Int2Str(i,"PNBox%d",buf)));
897 padd("style:family", sXML_CDATA, "graphics");
898 rstartEl("style:style", mxList.get());
899 mxList->clear();
901 padd("fo:margin-top", sXML_CDATA, "0cm");
902 padd("fo:margin-bottom", sXML_CDATA, "0cm");
903 padd("style:wrap", sXML_CDATA, "run-through");
904 padd("style:vertical-pos", sXML_CDATA, "from-top");
905 padd("style:vertical-rel", sXML_CDATA, "paragraph");
907 if( i == 1 )
908 padd("style:horizontal-pos", sXML_CDATA, "left");
909 else if ( i == 2 )
910 padd("style:horizontal-pos", sXML_CDATA, "center");
911 else if ( i == 3 )
912 padd("style:horizontal-pos", sXML_CDATA, "right");
913 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
914 padd("fo:padding", sXML_CDATA, "0cm");
915 padd("stylefamily", sXML_CDATA, "graphics");
916 rstartEl("style:properties", mxList.get());
917 mxList->clear();
918 rendEl("style:properties");
919 rendEl("style:style");
922 for (i = 0; i < hwpfile.getDateFormatCount(); i++)
923 makeDateFormat(hwpfile.getDateCode(i));
925 makePageStyle();
927 rendEl("office:automatic-styles");
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;
954 void HwpReader::makeMasterStyles()
956 rstartEl("office:master-styles", mxList.get());
958 int i;
959 int nMax = hwpfile.getMaxSettedPage();
960 std::deque<PageSetting> aSet(nMax + 1);
962 for( i = 0 ; i < hwpfile.getPageNumberCount() ; i++ )
964 ShowPageNum *pn = hwpfile.getPageNumber(i);
965 aSet[pn->m_nPageNumber].pagenumber = pn;
966 aSet[pn->m_nPageNumber].bIsSet = true;
968 for( i = 0 ; i < hwpfile.getHeaderFooterCount() ; i++ )
970 HeaderFooter* hf = hwpfile.getHeaderFooter(i);
971 aSet[hf->m_nPageNumber].bIsSet = true;
972 if( hf->type == 0 ) // header
974 switch( hf->where )
976 case 0 :
977 aSet[hf->m_nPageNumber].header = hf;
978 aSet[hf->m_nPageNumber].header_even = nullptr;
979 aSet[hf->m_nPageNumber].header_odd = nullptr;
980 break;
981 case 1:
982 aSet[hf->m_nPageNumber].header_even = hf;
983 if( aSet[hf->m_nPageNumber].header )
985 aSet[hf->m_nPageNumber].header_odd =
986 aSet[hf->m_nPageNumber].header;
987 aSet[hf->m_nPageNumber].header = nullptr;
989 break;
990 case 2:
991 aSet[hf->m_nPageNumber].header_odd = hf;
992 if( aSet[hf->m_nPageNumber].header )
994 aSet[hf->m_nPageNumber].header_even =
995 aSet[hf->m_nPageNumber].header;
996 aSet[hf->m_nPageNumber].header = nullptr;
998 break;
1001 else // footer
1003 switch( hf->where )
1005 case 0 :
1006 aSet[hf->m_nPageNumber].footer = hf;
1007 aSet[hf->m_nPageNumber].footer_even = nullptr;
1008 aSet[hf->m_nPageNumber].footer_odd = nullptr;
1009 break;
1010 case 1:
1011 aSet[hf->m_nPageNumber].footer_even = hf;
1012 if( aSet[hf->m_nPageNumber].footer )
1014 aSet[hf->m_nPageNumber].footer_odd =
1015 aSet[hf->m_nPageNumber].footer;
1016 aSet[hf->m_nPageNumber].footer = nullptr;
1018 break;
1019 case 2:
1020 aSet[hf->m_nPageNumber].footer_odd = hf;
1021 if( aSet[hf->m_nPageNumber].footer )
1023 aSet[hf->m_nPageNumber].footer_even =
1024 aSet[hf->m_nPageNumber].footer;
1025 aSet[hf->m_nPageNumber].footer = nullptr;
1027 break;
1032 PageSetting *pPrevSet = nullptr;
1033 PageSetting *pPage = nullptr;
1035 for( i = 1; i <= nMax ; i++ )
1037 if( i == 1 )
1038 padd("style:name", sXML_CDATA, "Standard");
1039 else
1040 padd("style:name", sXML_CDATA,
1041 ascii(Int2Str(i, "p%d", buf)));
1042 padd("style:page-master-name", sXML_CDATA,
1043 ascii(Int2Str(hwpfile.GetPageMasterNum(i), "pm%d", buf)));
1044 if( i < nMax )
1045 padd("style:next-style-name", sXML_CDATA,
1046 ascii(Int2Str(i+1, "p%d", buf)));
1047 padd("draw:style-name", sXML_CDATA,
1048 ascii(Int2Str(i, "master%d", buf)));
1049 rstartEl("style:master-page", mxList.get());
1050 mxList->clear();
1052 if( aSet[i].bIsSet ) /* If you've changed the current setting */
1054 if( !aSet[i].pagenumber ){
1055 if( pPrevSet && pPrevSet->pagenumber )
1056 aSet[i].pagenumber = pPrevSet->pagenumber;
1058 if( aSet[i].pagenumber )
1060 if( aSet[i].pagenumber->where == 7 && aSet[i].header )
1062 aSet[i].header_even = aSet[i].header;
1063 aSet[i].header_odd = aSet[i].header;
1064 aSet[i].header = nullptr;
1066 if( aSet[i].pagenumber->where == 8 && aSet[i].footer )
1068 aSet[i].footer_even = aSet[i].footer;
1069 aSet[i].footer_odd = aSet[i].footer;
1070 aSet[i].footer = nullptr;
1074 if( !aSet[i].header_even && pPrevSet && pPrevSet->header_even )
1076 aSet[i].header_even = pPrevSet->header_even;
1078 if( !aSet[i].header_odd && pPrevSet && pPrevSet->header_odd )
1080 aSet[i].header_odd = pPrevSet->header_odd;
1082 if( !aSet[i].footer_even && pPrevSet && pPrevSet->footer_even )
1084 aSet[i].footer_even = pPrevSet->footer_even;
1086 if( !aSet[i].footer_odd && pPrevSet && pPrevSet->footer_odd )
1088 aSet[i].footer_odd = pPrevSet->footer_odd;
1091 pPage = &aSet[i];
1092 pPrevSet = &aSet[i];
1094 else if( pPrevSet ) /* If the previous setting exists */
1096 pPage = pPrevSet;
1098 else /* If the previous settings doesn't exist, set to the default settings */
1100 rstartEl("style:header", mxList.get());
1101 padd("text:style-name", sXML_CDATA, "Standard");
1102 rstartEl("text:p", mxList.get());
1103 mxList->clear();
1104 rendEl("text:p");
1105 rendEl("style:header");
1107 rstartEl("style:footer", mxList.get());
1108 padd("text:style-name", sXML_CDATA, "Standard");
1109 rstartEl("text:p", mxList.get());
1110 mxList->clear();
1111 rendEl("text:p");
1112 rendEl("style:footer");
1114 rendEl("style:master-page");
1116 continue;
1118 // header
1119 if( pPage->header )
1121 rstartEl("style:header", mxList.get());
1122 if( pPage->pagenumber && pPage->pagenumber->where < 4 )
1124 d->bInHeader = true;
1125 d->pPn = pPage->pagenumber;
1127 parsePara(pPage->header->plist.front().get());
1128 d->bInHeader = false;
1129 d->pPn = nullptr;
1130 rendEl("style:header");
1132 if( pPage->header_even )
1134 rstartEl("style:header", mxList.get());
1135 if( pPage->pagenumber && ( pPage->pagenumber->where < 4
1136 || pPage->pagenumber->where == 7 ) )
1138 d->bInHeader = true;
1139 d->pPn = pPage->pagenumber;
1140 d->nPnPos = 3;
1142 parsePara(pPage->header_even->plist.front().get());
1143 d->bInHeader = false;
1144 d->pPn = nullptr;
1145 d->nPnPos = 0;
1146 rendEl("style:header");
1148 /* Will be the default. */
1149 else if (pPage->header_odd)
1151 rstartEl("style:header", mxList.get());
1152 padd("text:style-name", sXML_CDATA, "Standard");
1153 rstartEl("text:p", mxList.get());
1154 mxList->clear();
1155 if( pPage->pagenumber && ( pPage->pagenumber->where < 4 ||
1156 pPage->pagenumber->where == 7 ) )
1158 d->pPn = pPage->pagenumber;
1159 d->nPnPos = 3;
1160 makeShowPageNum();
1161 d->pPn = nullptr;
1162 d->nPnPos = 0;
1164 rendEl("text:p");
1165 rendEl("style:header");
1167 if( pPage->header_odd )
1169 rstartEl("style:header-left", mxList.get());
1170 if( pPage->pagenumber && ( pPage->pagenumber->where < 4
1171 || pPage->pagenumber->where == 7 ) )
1173 d->bInHeader = true;
1174 d->nPnPos = 1;
1175 d->pPn = pPage->pagenumber;
1177 parsePara(pPage->header_odd->plist.front().get());
1178 d->bInHeader = false;
1179 d->pPn = nullptr;
1180 d->nPnPos = 0;
1181 rendEl("style:header-left");
1183 /* Will be the default. */
1184 else if (pPage->header_even)
1186 rstartEl("style:header-left", mxList.get());
1187 padd("text:style-name", sXML_CDATA, "Standard");
1188 rstartEl("text:p", mxList.get());
1189 mxList->clear();
1190 if( pPage->pagenumber && ( pPage->pagenumber->where < 4 ||
1191 pPage->pagenumber->where == 7 ) )
1193 d->pPn = pPage->pagenumber;
1194 d->nPnPos = 1;
1195 makeShowPageNum();
1196 d->pPn = nullptr;
1197 d->nPnPos = 0;
1199 rendEl("text:p");
1200 rendEl("style:header-left");
1202 if( !pPage->header && !pPage->header_even && !pPage->header_odd )
1204 rstartEl("style:header", mxList.get());
1205 padd("text:style-name", sXML_CDATA, "Standard");
1206 rstartEl("text:p", mxList.get());
1207 mxList->clear();
1208 if( pPage->pagenumber && (pPage->pagenumber->where < 4 ||
1209 pPage->pagenumber->where == 7 ) )
1211 d->pPn = pPage->pagenumber;
1212 makeShowPageNum();
1213 d->pPn = nullptr;
1215 rendEl("text:p");
1216 rendEl("style:header");
1218 // footer
1219 if( pPage->footer )
1221 rstartEl("style:footer", mxList.get());
1222 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1223 && pPage->pagenumber->where != 7 )
1225 d->bInHeader = true;
1226 d->pPn = pPage->pagenumber;
1228 parsePara(pPage->footer->plist.front().get());
1229 d->bInHeader = false;
1230 d->pPn = nullptr;
1231 rendEl("style:footer");
1233 if( pPage->footer_even )
1235 rstartEl("style:footer", mxList.get());
1236 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1237 && pPage->pagenumber->where != 7 )
1239 d->bInHeader = true;
1240 d->pPn = pPage->pagenumber;
1241 d->nPnPos = 3;
1243 parsePara(pPage->footer_even->plist.front().get());
1244 d->bInHeader = false;
1245 d->pPn = nullptr;
1246 d->nPnPos = 0;
1247 rendEl("style:footer");
1249 /* Will be the default. */
1250 else if (pPage->footer_odd)
1252 rstartEl("style:footer", mxList.get());
1253 padd("text:style-name", sXML_CDATA, "Standard");
1254 rstartEl("text:p", mxList.get());
1255 mxList->clear();
1256 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1257 && pPage->pagenumber->where != 7 )
1259 d->pPn = pPage->pagenumber;
1260 d->nPnPos = 3;
1261 makeShowPageNum();
1262 d->pPn = nullptr;
1263 d->nPnPos = 0;
1265 rendEl("text:p");
1266 rendEl("style:footer");
1268 if( pPage->footer_odd )
1270 rstartEl("style:footer-left", mxList.get());
1271 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1272 && pPage->pagenumber->where != 7 )
1274 d->bInHeader = true;
1275 d->pPn = pPage->pagenumber;
1276 d->nPnPos = 1;
1278 parsePara(pPage->footer_odd->plist.front().get());
1279 d->bInHeader = false;
1280 d->pPn = nullptr;
1281 d->nPnPos = 0;
1282 rendEl("style:footer-left");
1284 /* Will be the default. */
1285 else if (pPage->footer_even)
1287 rstartEl("style:footer-left", mxList.get());
1288 padd("text:style-name", sXML_CDATA, "Standard");
1289 rstartEl("text:p", mxList.get());
1290 mxList->clear();
1291 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1292 && pPage->pagenumber->where != 7 )
1294 d->pPn = pPage->pagenumber;
1295 d->nPnPos = 1;
1296 makeShowPageNum();
1297 d->pPn = nullptr;
1298 d->nPnPos = 0;
1300 rendEl("text:p");
1301 rendEl("style:footer-left");
1303 if( !pPage->footer && !pPage->footer_even && !pPage->footer_odd )
1305 rstartEl("style:footer", mxList.get());
1306 padd("text:style-name", sXML_CDATA, "Standard");
1307 rstartEl("text:p", mxList.get());
1308 mxList->clear();
1309 if( pPage->pagenumber && pPage->pagenumber->where >= 4
1310 && pPage->pagenumber->where != 7 )
1312 d->pPn = pPage->pagenumber;
1313 makeShowPageNum();
1314 d->pPn = nullptr;
1316 rendEl("text:p");
1317 rendEl("style:footer");
1320 rendEl("style:master-page");
1322 rendEl("office:master-styles");
1327 * Create the properties for text styles.
1328 * 1. fo:font-size, fo:font-family, fo:letter-spacing, fo:color,
1329 * style:text-background-color, fo:font-style, fo:font-weight,
1330 * style:text-underline,style:text-outline,fo:text-shadow,style:text-position
1331 * Support them.
1333 void HwpReader::parseCharShape(CharShape const * cshape)
1335 HWPFont& hwpfont = hwpfile.GetHWPFont();
1337 padd("fo:font-size", sXML_CDATA,
1338 ascii(Int2Str(cshape->size / 25, "%dpt", buf)));
1339 padd("style:font-size-asian", sXML_CDATA,
1340 ascii(Int2Str(cshape->size / 25, "%dpt", buf)));
1342 ::std::string const tmp = hstr2ksstr(kstr2hstr(
1343 reinterpret_cast<unsigned char const *>(hwpfont.GetFontName(0, cshape->font[0]))).c_str());
1344 double fRatio = 1.0;
1345 int size = getRepFamilyName(tmp.c_str(), buf, fRatio);
1347 padd("fo:font-family", sXML_CDATA,
1348 OUString(buf, size, RTL_TEXTENCODING_EUC_KR));
1349 padd("style:font-family-asian", sXML_CDATA,
1350 OUString(buf, size, RTL_TEXTENCODING_EUC_KR));
1352 padd("style:text-scale", sXML_CDATA,
1353 ascii(Int2Str(static_cast<int>(cshape->ratio[0] * fRatio), "%d%%", buf)));
1355 double sspace = (cshape->size / 25) * cshape->space[0] / 100.;
1357 if (sspace != 0.)
1359 padd("fo:letter-spacing", sXML_CDATA,
1360 Double2Str(sspace) + "pt");
1362 if (cshape->color[1] != 0)
1363 padd("fo:color", sXML_CDATA,
1364 ascii(hcolor2str(cshape->color[1], 100, buf, true)));
1365 if (cshape->shade != 0)
1366 padd("style:text-background-color", sXML_CDATA,
1367 ascii(hcolor2str(cshape->color[0], cshape->shade, buf)));
1368 if (cshape->attr & 0x01)
1370 padd("fo:font-style", sXML_CDATA, "italic");
1371 padd("style:font-style-asian", sXML_CDATA, "italic");
1373 else{
1374 padd("fo:font-style", sXML_CDATA, "normal");
1375 padd("style:font-style-asian", sXML_CDATA, "normal");
1377 if (cshape->attr >> 1 & 0x01)
1379 padd("fo:font-weight", sXML_CDATA, "bold");
1380 padd("style:font-weight-asian", sXML_CDATA, "bold");
1382 else{
1383 padd("fo:font-weight", sXML_CDATA, "normal");
1384 padd("style:font-weight-asian", sXML_CDATA, "normal");
1386 if (cshape->attr >> 2 & 0x01)
1387 padd("style:text-underline", sXML_CDATA, "single");
1388 if (cshape->attr >> 3 & 0x01)
1389 padd("style:text-outline", sXML_CDATA, "true");
1390 if (cshape->attr >> 4 & 0x01)
1391 padd("fo:text-shadow", sXML_CDATA, "1pt 1pt");
1392 if (cshape->attr >> 5 & 0x01)
1393 padd("style:text-position", sXML_CDATA, "super 58%");
1394 if (cshape->attr >> 6 & 0x01)
1395 padd("style:text-position", sXML_CDATA, "sub 58%");
1401 * Create the properties that correspond to the real Paragraph.
1402 * 1. fo:margin-left,fo:margin-right,fo:margin-top, fo:margin-bottom,
1403 * fo:text-indent, fo:line-height, fo:text-align, fo:border
1404 * are implemented.
1405 * TODO: Tab Settings => set values of properties only which doesn't have the default value
1407 void HwpReader::parseParaShape(ParaShape const * pshape)
1410 if (pshape->left_margin != 0)
1411 padd("fo:margin-left", sXML_CDATA, Double2Str
1412 (WTI(pshape->left_margin )) + "inch");
1413 if (pshape->right_margin != 0)
1414 padd("fo:margin-right", sXML_CDATA, Double2Str
1415 (WTI(pshape->right_margin)) + "inch");
1416 if (pshape->pspacing_prev != 0)
1417 padd("fo:margin-top", sXML_CDATA, Double2Str
1418 (WTI(pshape->pspacing_prev)) + "inch");
1419 if (pshape->pspacing_next != 0)
1420 padd("fo:margin-bottom", sXML_CDATA, Double2Str
1421 (WTI(pshape->pspacing_next)) + "inch");
1422 if (pshape->indent != 0)
1423 padd("fo:text-indent", sXML_CDATA, Double2Str
1424 (WTI(pshape->indent)) + "inch");
1425 if (pshape->lspacing != 0)
1426 padd("fo:line-height", sXML_CDATA,
1427 ascii(Int2Str (pshape->lspacing, "%d%%", buf)));
1429 unsigned char set_align = 0;
1431 switch (static_cast<int>(pshape->arrange_type))
1433 case 1:
1434 strcpy(buf, "start");
1435 set_align = 1;
1436 break;
1437 case 2:
1438 strcpy(buf, "end");
1439 set_align = 1;
1440 break;
1441 case 3:
1442 strcpy(buf, "center");
1443 set_align = 1;
1444 break;
1445 case 4:
1446 case 5:
1447 case 6:
1448 strcpy(buf, "justify");
1449 set_align = 1;
1450 break;
1453 if (set_align)
1454 padd("fo:text-align", sXML_CDATA, ascii(buf));
1456 if (pshape->outline)
1457 padd("fo:border", sXML_CDATA, "0.002cm solid #000000");
1458 if( pshape->shade > 0 )
1460 padd("fo:background-color", sXML_CDATA,
1461 ascii(hcolor2str(0, pshape->shade, buf)));
1464 if( pshape->pagebreak & 0x02 || pshape->pagebreak & 0x04)
1465 padd("fo:break-before", sXML_CDATA, "page");
1466 else if( pshape->pagebreak & 0x01 )
1467 padd("fo:break-before", sXML_CDATA, "column");
1473 * Make the style of the Paragraph.
1475 void HwpReader::makePStyle(ParaShape const * pshape)
1477 int nscount = pshape->tabs[MAXTABS -1].type;
1478 padd("style:name", sXML_CDATA,
1479 ascii(Int2Str(pshape->index, "P%d", buf)));
1480 padd("style:family", sXML_CDATA, "paragraph");
1481 rstartEl("style:style", mxList.get());
1482 mxList->clear();
1483 parseParaShape(pshape);
1484 parseCharShape(pshape->cshape.get());
1485 rstartEl("style:properties", mxList.get());
1486 mxList->clear();
1488 if( nscount )
1490 unsigned char tf = 0;
1491 rstartEl("style:tab-stops",mxList.get());
1493 int tab_margin = pshape->left_margin + pshape->indent;
1494 if( tab_margin < 0 )
1495 tab_margin = 0;
1496 for( int i = 0 ; i < MAXTABS -1 ; i++)
1498 if( i > 0 && pshape->tabs[i].position == 0. )
1499 break;
1500 if( pshape->tabs[i].position <= tab_margin )
1501 continue;
1502 padd("style:position", sXML_CDATA,
1503 Double2Str(WTMM(pshape->tabs[i].position - tab_margin )) + "mm");
1504 if( pshape->tabs[i].type )
1506 tf = 1;
1507 switch(pshape->tabs[i].type)
1509 case 1 :
1510 padd("style:type", sXML_CDATA, "right");
1511 break;
1512 case 2:
1513 padd("style:type", sXML_CDATA, "center");
1514 break;
1515 case 3:
1516 padd("style:type", sXML_CDATA, "char");
1517 padd("style:char", sXML_CDATA, ".");
1518 break;
1521 if( pshape->tabs[i].dot_continue )
1523 tf = 1;
1524 padd("style:leader-char", sXML_CDATA, ".");
1526 rstartEl( "style:tab-stop", mxList.get());
1527 mxList->clear();
1528 rendEl( "style:tab-stop" );
1530 if( (pshape->tabs[i].position != 1000 * i ) || tf )
1532 if( !--nscount ) break;
1535 rendEl( "style:tab-stops");
1537 rendEl("style:properties");
1538 rendEl("style:style");
1543 * Create a style for the page. This includes the header/footer, footnote and more.
1544 * TODO: fo: background-color (no information)
1546 void HwpReader::makePageStyle()
1548 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
1549 int pmCount = hwpfile.getColumnCount();
1551 for( int i = 0 ; i < pmCount ; i++ ){
1552 padd("style:name", sXML_CDATA, ascii(Int2Str(i + 1, "pm%d", buf)));
1553 rstartEl("style:page-master",mxList.get());
1554 mxList->clear();
1557 switch( hwpinfo.paper.paper_kind )
1559 case 3: // A4
1560 if( hwpinfo.paper.paper_direction )
1562 padd("fo:page-height",sXML_CDATA, "210mm");
1563 padd("fo:page-width",sXML_CDATA, "297mm");
1565 else
1567 padd("fo:page-width",sXML_CDATA, "210mm");
1568 padd("fo:page-height",sXML_CDATA, "297mm");
1570 break;
1571 case 4: // 80 column
1572 if( hwpinfo.paper.paper_direction )
1574 padd("fo:page-height",sXML_CDATA, "8.5inch");
1575 padd("fo:page-width",sXML_CDATA, "11inch");
1577 else
1579 padd("fo:page-width",sXML_CDATA, "8.5inch");
1580 padd("fo:page-height",sXML_CDATA, "11inch");
1582 break;
1583 case 5: // B5
1584 if( hwpinfo.paper.paper_direction )
1586 padd("fo:page-height",sXML_CDATA, "176mm");
1587 padd("fo:page-width",sXML_CDATA, "250mm");
1589 else
1591 padd("fo:page-width",sXML_CDATA, "176mm");
1592 padd("fo:page-height",sXML_CDATA, "250mm");
1594 break;
1595 case 6: // B4
1596 if( hwpinfo.paper.paper_direction )
1598 padd("fo:page-height",sXML_CDATA, "250mm");
1599 padd("fo:page-width",sXML_CDATA, "353mm");
1601 else
1603 padd("fo:page-width",sXML_CDATA, "250mm");
1604 padd("fo:page-height",sXML_CDATA, "353mm");
1606 break;
1607 case 7:
1608 if( hwpinfo.paper.paper_direction )
1610 padd("fo:page-height",sXML_CDATA, "8.5inch");
1611 padd("fo:page-width",sXML_CDATA, "14inch");
1613 else
1615 padd("fo:page-width",sXML_CDATA, "8.5inch");
1616 padd("fo:page-height",sXML_CDATA, "14inch");
1618 break;
1619 case 8:
1620 if( hwpinfo.paper.paper_direction )
1622 padd("fo:page-height",sXML_CDATA, "297mm");
1623 padd("fo:page-width",sXML_CDATA, "420mm");
1625 else
1627 padd("fo:page-width",sXML_CDATA, "297mm");
1628 padd("fo:page-height",sXML_CDATA, "420mm");
1630 break;
1631 case 0:
1632 case 1:
1633 case 2:
1634 default:
1635 if( hwpinfo.paper.paper_direction )
1637 padd("fo:page-width",sXML_CDATA,
1638 Double2Str(WTI(hwpinfo.paper.paper_height)) + "inch");
1639 padd("fo:page-height",sXML_CDATA,
1640 Double2Str(WTI(hwpinfo.paper.paper_width)) + "inch");
1642 else
1644 padd("fo:page-width",sXML_CDATA,
1645 Double2Str(WTI(hwpinfo.paper.paper_width)) + "inch");
1646 padd("fo:page-height",sXML_CDATA,
1647 Double2Str(WTI(hwpinfo.paper.paper_height)) + "inch");
1649 break;
1653 padd("style:print-orientation",sXML_CDATA,
1654 ascii(hwpinfo.paper.paper_direction ? "landscape" : "portrait"));
1655 if( hwpinfo.beginpagenum != 1)
1656 padd("style:first-page-number",sXML_CDATA,
1657 ascii(Int2Str(hwpinfo.beginpagenum, "%d", buf)));
1659 if( hwpinfo.borderline ){
1660 padd("fo:margin-left",sXML_CDATA,
1661 Double2Str(WTI(hwpinfo.paper.left_margin - hwpinfo.bordermargin[0] + hwpinfo.paper.gutter_length)) + "inch");
1662 padd("fo:margin-right",sXML_CDATA,
1663 Double2Str(WTI(hwpinfo.paper.right_margin - hwpinfo.bordermargin[1])) + "inch");
1664 padd("fo:margin-top",sXML_CDATA,
1665 Double2Str(WTI(hwpinfo.paper.top_margin - hwpinfo.bordermargin[2])) + "inch");
1666 padd("fo:margin-bottom",sXML_CDATA,
1667 Double2Str(WTI(hwpinfo.paper.bottom_margin - hwpinfo.bordermargin[3])) + "inch");
1669 else{
1670 padd("fo:margin-left",sXML_CDATA,
1671 Double2Str(WTI(hwpinfo.paper.left_margin + hwpinfo.paper.gutter_length)) + "inch");
1672 padd("fo:margin-right",sXML_CDATA,
1673 Double2Str(WTI(hwpinfo.paper.right_margin)) + "inch");
1674 padd("fo:margin-top",sXML_CDATA,
1675 Double2Str(WTI(hwpinfo.paper.top_margin)) + "inch");
1676 padd("fo:margin-bottom",sXML_CDATA,
1677 Double2Str(WTI(hwpinfo.paper.bottom_margin)) + "inch");
1680 switch( hwpinfo.borderline )
1682 case 1:
1683 padd("fo:border", sXML_CDATA,"0.002cm solid #000000");
1684 break;
1685 case 3:
1686 padd("fo:border", sXML_CDATA,"0.002cm dotted #000000");
1687 break;
1688 case 2:
1689 padd("fo:border", sXML_CDATA,"0.035cm solid #000000");
1690 break;
1691 case 4:
1692 padd("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1693 padd("fo:border", sXML_CDATA,"0.039cm double #000000");
1694 break;
1697 padd("fo:padding-left", sXML_CDATA,
1698 Double2Str(WTI(hwpinfo.bordermargin[0])) + "inch");
1699 padd("fo:padding-right", sXML_CDATA,
1700 Double2Str(WTI(hwpinfo.bordermargin[1])) + "inch");
1701 padd("fo:padding-top", sXML_CDATA,
1702 Double2Str(WTI(hwpinfo.bordermargin[2])) + "inch");
1703 padd("fo:padding-bottom", sXML_CDATA,
1704 Double2Str(WTI(hwpinfo.bordermargin[3])) + "inch");
1706 /* background color */
1707 if( hwpinfo.back_info.isset )
1709 if( hwpinfo.back_info.color[0] > 0 || hwpinfo.back_info.color[1] > 0
1710 || hwpinfo.back_info.color[2] > 0 ){
1711 sprintf(buf,"#%02x%02x%02x",hwpinfo.back_info.color[0],
1712 hwpinfo.back_info.color[1],hwpinfo.back_info.color[2] );
1713 padd("fo:background-color", sXML_CDATA, ascii(buf));
1717 rstartEl("style:properties",mxList.get());
1718 mxList->clear();
1720 /* background image */
1721 if( hwpinfo.back_info.isset && hwpinfo.back_info.type > 0 )
1723 if( hwpinfo.back_info.type == 1 ){
1724 #ifdef _WIN32
1725 padd("xlink:href", sXML_CDATA,
1726 reinterpret_cast<sal_Unicode const *>(hconv(kstr2hstr(reinterpret_cast<uchar const *>(urltowin(hwpinfo.back_info.filename).c_str())).c_str())));
1727 #else
1728 padd("xlink:href", sXML_CDATA,
1729 reinterpret_cast<sal_Unicode const *>(hconv(kstr2hstr( reinterpret_cast<uchar const *>(urltounix(hwpinfo.back_info.filename).c_str())).c_str())));
1730 #endif
1731 padd("xlink:type", sXML_CDATA, "simple");
1732 padd("xlink:actuate", sXML_CDATA, "onLoad");
1734 if( hwpinfo.back_info.flag >= 2)
1735 padd("style:repeat", sXML_CDATA, "stretch");
1736 else if( hwpinfo.back_info.flag == 1 ){
1737 padd("style:repeat", sXML_CDATA, "no-repeat");
1738 padd("style:position", sXML_CDATA, "center");
1740 rstartEl("style:background-image",mxList.get());
1742 if( hwpinfo.back_info.type == 2 ){
1743 rstartEl("office:binary-data", mxList.get());
1744 mxList->clear();
1745 std::shared_ptr<char> pStr(base64_encode_string(reinterpret_cast<unsigned char *>(hwpinfo.back_info.data.data()), hwpinfo.back_info.size ), Free<char>());
1746 rchars(ascii(pStr.get()));
1747 rendEl("office:binary-data");
1749 rendEl("style:background-image");
1752 makeColumns( hwpfile.GetColumnDef(i) );
1754 rendEl("style:properties");
1756 /* header style */
1757 rstartEl("style:header-style", mxList.get());
1758 padd("svg:height", sXML_CDATA,
1759 Double2Str(WTI(hwpinfo.paper.header_length)) + "inch");
1760 padd("fo:margin-bottom", sXML_CDATA, "0mm");
1762 rstartEl("style:properties",mxList.get());
1763 mxList->clear();
1764 rendEl("style:properties");
1765 rendEl("style:header-style");
1767 /* footer style */
1768 rstartEl("style:footer-style", mxList.get());
1769 padd("svg:height", sXML_CDATA,
1770 Double2Str(WTI(hwpinfo.paper.footer_length)) + "inch");
1771 padd("fo:margin-top", sXML_CDATA, "0mm");
1772 rstartEl("style:properties",mxList.get());
1773 mxList->clear();
1774 rendEl("style:properties");
1775 rendEl("style:footer-style");
1777 /* Footnote style, but it fell in the dtd, the specification has been defined. REALKING */
1778 rstartEl("style:footnote-layout", mxList.get());
1780 padd("style:distance-before-sep", sXML_CDATA,
1781 Double2Str(WTI(hwpinfo.splinetext)) + "inch");
1782 padd("style:distance-after-sep", sXML_CDATA,
1783 Double2Str(WTI(hwpinfo.splinefn)) + "inch");
1784 rstartEl("style:properties",mxList.get());
1785 mxList->clear();
1786 rendEl("style:properties");
1787 if ( hwpinfo.fnlinetype == 2 )
1788 padd("style:width", sXML_CDATA, "15cm");
1789 else if ( hwpinfo.fnlinetype == 1)
1790 padd("style:width", sXML_CDATA, "2cm");
1791 else if ( hwpinfo.fnlinetype == 3)
1792 padd("style:width", sXML_CDATA, "0cm");
1793 else
1794 padd("style:width", sXML_CDATA, "5cm");
1796 rstartEl("style:footnote-sep",mxList.get());
1797 mxList->clear();
1798 rendEl("style:footnote-sep");
1800 rendEl("style:footnote-layout");
1802 rendEl("style:page-master");
1806 void HwpReader::makeColumns(ColumnDef const *coldef)
1808 if( !coldef ) return;
1809 padd("fo:column-count", sXML_CDATA, ascii(Int2Str(coldef->ncols, "%d", buf)));
1810 rstartEl("style:columns",mxList.get());
1811 mxList->clear();
1812 if( coldef->separator != 0 )
1814 switch( coldef->separator )
1816 case 1: /* thin line */
1817 padd("style:width", sXML_CDATA, "0.02mm");
1818 [[fallthrough]];
1819 case 3: /* dotted line */
1820 padd("style:style", sXML_CDATA, "dotted");
1821 padd("style:width", sXML_CDATA, "0.02mm");
1822 break;
1823 case 2: /* thick line */
1824 case 4: /* double line */
1825 padd("style:width", sXML_CDATA, "0.35mm");
1826 break;
1827 case 0: /* None */
1828 default:
1829 padd("style:style", sXML_CDATA, "none");
1830 break;
1832 rstartEl("style:column-sep",mxList.get());
1833 mxList->clear();
1834 rendEl("style:column-sep");
1836 double spacing = WTI(coldef->spacing)/ 2. ;
1837 for(int ii = 0 ; ii < coldef->ncols ; ii++)
1839 if( ii == 0 )
1840 padd("fo:margin-left", sXML_CDATA, "0mm");
1841 else
1842 padd("fo:margin-left", sXML_CDATA,
1843 Double2Str( spacing) + "inch");
1844 if( ii == ( coldef->ncols -1) )
1845 padd("fo:margin-right", sXML_CDATA,"0mm");
1846 else
1847 padd("fo:margin-right", sXML_CDATA,
1848 Double2Str( spacing) + "inch");
1849 rstartEl("style:column",mxList.get());
1850 mxList->clear();
1851 rendEl("style:column");
1853 rendEl("style:columns");
1856 void HwpReader::makeTStyle(CharShape const * cshape)
1858 padd("style:name", sXML_CDATA,
1859 ascii(Int2Str(cshape->index, "T%d", buf)));
1860 padd("style:family", sXML_CDATA, "text");
1861 rstartEl("style:style", mxList.get());
1862 mxList->clear();
1863 parseCharShape(cshape);
1864 rstartEl("style:properties", mxList.get());
1865 mxList->clear();
1866 rendEl("style:properties");
1867 rendEl("style:style");
1871 void HwpReader::makeTableStyle(Table *tbl)
1873 // table
1874 TxtBox *hbox = tbl->box;
1876 padd("style:name", sXML_CDATA,
1877 ascii(Int2Str(hbox->style.boxnum, "Table%d", buf)));
1878 padd("style:family", sXML_CDATA,"table");
1879 rstartEl("style:style", mxList.get());
1880 mxList->clear();
1881 padd("style:width", sXML_CDATA,
1882 Double2Str(WTMM(hbox->box_xs)) + "mm");
1883 padd("table:align", sXML_CDATA,"left");
1884 padd("fo:keep-with-next", sXML_CDATA,"false");
1885 rstartEl("style:properties", mxList.get());
1886 mxList->clear();
1887 rendEl("style:properties");
1888 rendEl("style:style");
1890 // column
1891 for (size_t i = 0 ; i < tbl->columns.nCount -1 ; i++)
1893 sprintf(buf,"Table%d.%c",hbox->style.boxnum, static_cast<char>('A'+i));
1894 padd("style:name", sXML_CDATA, ascii( buf ));
1895 padd("style:family", sXML_CDATA,"table-column");
1896 rstartEl("style:style", mxList.get());
1897 mxList->clear();
1898 padd("style:column-width", sXML_CDATA,
1899 Double2Str(WTMM(tbl->columns.data[i+1] - tbl->columns.data[i])) + "mm");
1900 rstartEl("style:properties", mxList.get());
1901 mxList->clear();
1902 rendEl("style:properties");
1903 rendEl("style:style");
1906 // row
1907 for (size_t i = 0 ; i < tbl->rows.nCount -1 ; i++)
1909 sprintf(buf,"Table%d.row%" SAL_PRI_SIZET "u",hbox->style.boxnum, i + 1);
1910 padd("style:name", sXML_CDATA, ascii( buf ));
1911 padd("style:family", sXML_CDATA,"table-row");
1912 rstartEl("style:style", mxList.get());
1913 mxList->clear();
1914 padd("style:row-height", sXML_CDATA,
1915 Double2Str(WTMM(tbl->rows.data[i+1] - tbl->rows.data[i])) + "mm");
1916 rstartEl("style:properties", mxList.get());
1917 mxList->clear();
1918 rendEl("style:properties");
1919 rendEl("style:style");
1922 // cell
1923 for (auto const& tcell : tbl->cells)
1925 sprintf(buf,"Table%d.%c%d",hbox->style.boxnum, 'A'+ tcell->nColumnIndex, tcell->nRowIndex +1);
1926 padd("style:name", sXML_CDATA, ascii( buf ));
1927 padd("style:family", sXML_CDATA,"table-cell");
1928 rstartEl("style:style", mxList.get());
1929 mxList->clear();
1930 Cell *cl = tcell->pCell;
1931 if( cl->ver_align == 1 )
1932 padd("fo:vertical-align", sXML_CDATA,"middle");
1934 if(cl->linetype[2] == cl->linetype[3] && cl->linetype[2] == cl->linetype[0]
1935 && cl->linetype[2] == cl->linetype[1])
1937 switch( cl->linetype[2] )
1939 case 1: /* A thin solid line */
1940 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1941 padd("fo:border", sXML_CDATA,"0.002cm solid #000000");
1942 break;
1943 case 2: /* Bold lines */
1944 padd("fo:border", sXML_CDATA,"0.035cm solid #000000");
1945 break;
1946 case 4: /* Double line */
1947 padd("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1948 padd("fo:border", sXML_CDATA,"0.039cm double #000000");
1949 break;
1952 else
1954 switch( cl->linetype[0] )
1956 case 1: /* A thin solid line */
1957 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1958 padd("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
1959 break;
1960 case 2: /* Bold lines */
1961 padd("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
1962 break;
1963 case 4: /* Double line */
1964 padd("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1965 padd("fo:border-left", sXML_CDATA,"0.039cm double #000000");
1966 break;
1968 switch( cl->linetype[1] )
1970 case 1: /* A thin solid line */
1971 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1972 padd("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
1973 break;
1974 case 2: /* Bold lines */
1975 padd("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
1976 break;
1977 case 4: /* Double line */
1978 padd("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1979 padd("fo:border-right", sXML_CDATA,"0.039cm double #000000");
1980 break;
1982 switch( cl->linetype[2] )
1984 case 1: /* A thin solid line */
1985 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
1986 padd("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
1987 break;
1988 case 2: /* Bold lines */
1989 padd("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
1990 break;
1991 case 4: /* Double line */
1992 padd("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
1993 padd("fo:border-top", sXML_CDATA,"0.039cm double #000000");
1994 break;
1996 switch( cl->linetype[3] )
1998 case 1: /* A thin solid line */
1999 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2000 padd("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
2001 break;
2002 case 2: /* Bold lines */
2003 padd("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
2004 break;
2005 case 4: /* Double line */
2006 padd("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2007 padd("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
2008 break;
2011 if(cl->shade != 0)
2012 padd("fo:background-color", sXML_CDATA,
2013 ascii(hcolor2str(sal::static_int_cast<uchar>(cl->color),
2014 sal::static_int_cast<uchar>(cl->shade), buf)));
2016 rstartEl("style:properties", mxList.get());
2017 mxList->clear();
2018 rendEl("style:properties");
2020 rendEl("style:style");
2025 void HwpReader::makeDrawStyle( HWPDrawingObject * hdo, FBoxStyle * fstyle)
2027 while( hdo )
2029 padd("style:name", sXML_CDATA,
2030 ascii(Int2Str(hdo->index, "Draw%d", buf)));
2031 padd("style:family", sXML_CDATA, "graphics");
2033 rstartEl("style:style", mxList.get());
2034 mxList->clear();
2036 switch (fstyle->txtflow)
2038 case 0:
2039 break;
2040 case 1:
2041 padd("style:wrap", sXML_CDATA, "run-through");
2042 break;
2043 case 2:
2044 padd("style:wrap", sXML_CDATA, "dynamic");
2045 break;
2047 long color;
2048 // invisible line
2049 if( hdo->property.line_color > 0xffffff )
2051 padd("draw:stroke", sXML_CDATA, "none" );
2053 else
2056 if( hdo->property.line_pstyle == 0 )
2057 padd("draw:stroke", sXML_CDATA, "solid" );
2058 else if( hdo->property.line_pstyle < 5 )
2060 padd("draw:stroke", sXML_CDATA, "dash" );
2061 padd("draw:stroke-dash", sXML_CDATA,
2062 ascii(Int2Str(hdo->index, "LineType%d", buf)));
2064 padd("svg:stroke-width", sXML_CDATA,
2065 Double2Str( WTMM(hdo->property.line_width)) + "mm");
2066 color = hdo->property.line_color;
2067 sprintf( buf, "#%02x%02x%02x",
2068 sal_uInt16(color & 0xff),
2069 sal_uInt16((color >> 8) & 0xff),
2070 sal_uInt16((color >>16) & 0xff) );
2071 padd("svg:stroke-color", sXML_CDATA, ascii( buf) );
2074 if( hdo->type == HWPDO_LINE || hdo->type == HWPDO_ARC ||
2075 hdo->type == HWPDO_FREEFORM || hdo->type == HWPDO_ADVANCED_ARC )
2078 if( hdo->property.line_tstyle > 0 )
2080 padd("draw:marker-start", sXML_CDATA,
2081 ascii(ArrowShape[hdo->property.line_tstyle].name) );
2082 if( hdo->property.line_width > 100 )
2083 padd("draw:marker-start-width", sXML_CDATA,
2084 Double2Str( WTMM(hdo->property.line_width * 3)) + "mm");
2085 else if( hdo->property.line_width > 80 )
2086 padd("draw:marker-start-width", sXML_CDATA,
2087 Double2Str( WTMM(hdo->property.line_width * 4)) + "mm");
2088 else if( hdo->property.line_width > 60 )
2089 padd("draw:marker-start-width", sXML_CDATA,
2090 Double2Str( WTMM(hdo->property.line_width * 5)) + "mm");
2091 else if( hdo->property.line_width > 40 )
2092 padd("draw:marker-start-width", sXML_CDATA,
2093 Double2Str( WTMM(hdo->property.line_width * 6)) + "mm");
2094 else
2095 padd("draw:marker-start-width", sXML_CDATA,
2096 Double2Str( WTMM(hdo->property.line_width * 7)) + "mm");
2099 if( hdo->property.line_hstyle > 0 )
2101 padd("draw:marker-end", sXML_CDATA,
2102 ascii(ArrowShape[hdo->property.line_hstyle].name) );
2103 if( hdo->property.line_width > 100 )
2104 padd("draw:marker-end-width", sXML_CDATA,
2105 Double2Str( WTMM(hdo->property.line_width * 3)) + "mm");
2106 else if( hdo->property.line_width > 80 )
2107 padd("draw:marker-end-width", sXML_CDATA,
2108 Double2Str( WTMM(hdo->property.line_width * 4)) + "mm");
2109 else if( hdo->property.line_width > 60 )
2110 padd("draw:marker-end-width", sXML_CDATA,
2111 Double2Str( WTMM(hdo->property.line_width * 5)) + "mm");
2112 else if( hdo->property.line_width > 40 )
2113 padd("draw:marker-end-width", sXML_CDATA,
2114 Double2Str( WTMM(hdo->property.line_width * 6)) + "mm");
2115 else
2116 padd("draw:marker-end-width", sXML_CDATA,
2117 Double2Str( WTMM(hdo->property.line_width * 7)) + "mm");
2121 if(hdo->type != HWPDO_LINE )
2123 if( hdo->property.flag >> 19 & 0x01 )
2125 padd( "draw:textarea-horizontal-align", sXML_CDATA, "center");
2128 color = hdo->property.fill_color;
2130 if( hdo->property.flag >> 18 & 0x01 ) // bitmap pattern
2132 padd("draw:fill", sXML_CDATA, "bitmap");
2133 padd("draw:fill-image-name", sXML_CDATA,
2134 ascii(Int2Str(hdo->index, "fillimage%d", buf)));
2135 // bitmap resizing
2136 if( hdo->property.flag >> 3 & 0x01 )
2138 padd("style:repeat", sXML_CDATA, "stretch");
2140 else
2142 padd("style:repeat", sXML_CDATA, "repeat");
2143 padd("draw:fill-image-ref-point", sXML_CDATA, "top-left");
2145 if( hdo->property.flag >> 20 & 0x01 )
2147 if( hdo->property.luminance > 0 )
2149 padd("draw:transparency", sXML_CDATA,
2150 ascii(Int2Str(hdo->property.luminance, "%d%%", buf)));
2155 // Gradation
2156 else if( hdo->property.flag >> 16 & 0x01 )
2158 padd("draw:fill", sXML_CDATA, "gradient");
2159 padd("draw:fill-gradient-name", sXML_CDATA,
2160 ascii(Int2Str(hdo->index, "Grad%d", buf)));
2161 padd("draw:gradient-step-count", sXML_CDATA,
2162 ascii(Int2Str(hdo->property.nstep, "%d", buf)));
2165 // Hatching
2166 else if( hdo->property.pattern_type >> 24 & 0x01 )
2168 padd("draw:fill", sXML_CDATA, "hatch");
2169 padd("draw:fill-hatch-name", sXML_CDATA,
2170 ascii(Int2Str(hdo->index, "Hatch%d", buf)));
2171 if( color < 0xffffff )
2173 sprintf( buf, "#%02x%02x%02x",
2174 sal_uInt16(color & 0xff),
2175 sal_uInt16((color >> 8) & 0xff),
2176 sal_uInt16((color >>16) & 0xff) );
2177 padd("draw:fill-color", sXML_CDATA, ascii( buf) );
2178 padd("draw:fill-hatch-solid", sXML_CDATA, "true");
2181 else if( color <= 0xffffff )
2183 padd("draw:fill", sXML_CDATA, "solid");
2184 sprintf( buf, "#%02x%02x%02x",
2185 sal_uInt16(color & 0xff),
2186 sal_uInt16((color >> 8) & 0xff),
2187 sal_uInt16((color >>16) & 0xff) );
2188 padd("draw:fill-color", sXML_CDATA, ascii( buf) );
2190 else
2191 padd("draw:fill", sXML_CDATA, "none");
2194 if( fstyle->anchor_type == CHAR_ANCHOR )
2196 padd("style:vertical-pos", sXML_CDATA, "top");
2197 padd("style:vertical-rel", sXML_CDATA, "baseline");
2200 rstartEl("style:properties", mxList.get());
2201 mxList->clear();
2202 rendEl("style:properties");
2203 rendEl("style:style");
2205 if( hdo->type == 0 )
2207 makeDrawStyle( hdo->child.get(), fstyle );
2209 hdo = hdo->next.get();
2214 void HwpReader::makeCaptionStyle(FBoxStyle * fstyle)
2216 padd("style:name", sXML_CDATA,
2217 ascii(Int2Str(fstyle->boxnum, "CapBox%d", buf)));
2218 padd("style:family", sXML_CDATA, "graphics");
2219 rstartEl("style:style", mxList.get());
2220 mxList->clear();
2221 padd("fo:margin-left", sXML_CDATA, "0cm");
2222 padd("fo:margin-right", sXML_CDATA, "0cm");
2223 padd("fo:margin-top", sXML_CDATA, "0cm");
2224 padd("fo:margin-bottom", sXML_CDATA, "0cm");
2225 padd("fo:padding", sXML_CDATA, "0cm");
2226 switch (fstyle->txtflow)
2228 case 0:
2229 padd("style:wrap", sXML_CDATA, "none");
2230 break;
2231 case 1:
2232 if( fstyle->boxtype == 'G' )
2233 padd("style:run-through", sXML_CDATA, "background");
2234 padd("style:wrap", sXML_CDATA, "run-through");
2235 break;
2236 case 2:
2237 padd("style:wrap", sXML_CDATA, "dynamic");
2238 break;
2240 if (fstyle->anchor_type == CHAR_ANCHOR)
2242 padd("style:vertical-pos", sXML_CDATA, "top");
2243 padd("style:vertical-rel", sXML_CDATA, "baseline");
2244 padd("style:horizontal-pos", sXML_CDATA, "center");
2245 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
2247 else
2250 switch (-(fstyle->xpos))
2252 case 2:
2253 padd("style:horizontal-pos", sXML_CDATA, "right");
2254 break;
2255 case 3:
2256 padd("style:horizontal-pos", sXML_CDATA, "center");
2257 break;
2258 case 1:
2259 default:
2260 padd("style:horizontal-pos", sXML_CDATA, "from-left");
2261 break;
2263 switch (-(fstyle->ypos))
2265 case 2:
2266 padd("style:vertical-pos", sXML_CDATA, "bottom");
2267 break;
2268 case 3:
2269 padd("style:vertical-pos", sXML_CDATA, "middle");
2270 break;
2271 case 1:
2272 default:
2273 padd("style:vertical-pos", sXML_CDATA, "from-top");
2274 break;
2276 if ( fstyle->anchor_type == PARA_ANCHOR )
2278 padd("style:vertical-rel", sXML_CDATA, "paragraph");
2279 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
2281 else
2283 padd("style:vertical-rel", sXML_CDATA, "page-content");
2284 padd("style:horizontal-rel", sXML_CDATA, "page-content");
2287 rstartEl("style:properties", mxList.get());
2288 mxList->clear();
2289 rendEl("style:properties");
2290 rendEl("style:style");
2291 if( fstyle->boxtype == 'G' )
2293 padd("style:name", sXML_CDATA,
2294 ascii(Int2Str(fstyle->boxnum, "G%d", buf)));
2296 else
2298 padd("style:name", sXML_CDATA,
2299 ascii(Int2Str(fstyle->boxnum, "Txtbox%d", buf)));
2302 padd("style:family", sXML_CDATA, "graphics");
2303 rstartEl("style:style", mxList.get());
2304 mxList->clear();
2306 padd("fo:margin-left", sXML_CDATA, "0cm");
2307 padd("fo:margin-right", sXML_CDATA, "0cm");
2308 padd("fo:margin-top", sXML_CDATA, "0cm");
2309 padd("fo:margin-bottom", sXML_CDATA, "0cm");
2310 padd("fo:padding", sXML_CDATA, "0cm");
2311 padd("style:wrap", sXML_CDATA, "none");
2312 padd("style:vertical-pos", sXML_CDATA, "from-top");
2313 padd("style:vertical-rel", sXML_CDATA, "paragraph");
2314 padd("style:horizontal-pos", sXML_CDATA, "from-left");
2315 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
2316 if( fstyle->boxtype == 'G' )
2318 char *cell = static_cast<char *>(fstyle->cell);
2319 padd("draw:luminance", sXML_CDATA,
2320 ascii(Int2Str(cell[0], "%d%%", buf)));
2321 padd("draw:contrast", sXML_CDATA,
2322 ascii(Int2Str(cell[1], "%d%%", buf)));
2323 if( cell[2] == 0 )
2324 padd("draw:color-mode", sXML_CDATA, "standard");
2325 else if( cell[2] == 1 )
2326 padd("draw:color-mode", sXML_CDATA, "greyscale");
2327 else if( cell[2] == 2 )
2328 padd("draw:color-mode", sXML_CDATA, "mono");
2330 else
2332 Cell *cell = static_cast<Cell *>(fstyle->cell);
2333 if(cell->linetype[0] == cell->linetype[1] &&
2334 cell->linetype[0] == cell->linetype[2] &&
2335 cell->linetype[0] == cell->linetype[3])
2337 switch( cell->linetype[0] )
2339 case 0:
2340 padd("fo:padding", sXML_CDATA,"0mm");
2341 break;
2342 case 1: /* A thin solid line */
2343 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2344 padd("fo:border", sXML_CDATA,"0.002cm solid #000000");
2345 break;
2346 case 2: /* Bold lines */
2347 padd("fo:border", sXML_CDATA,"0.035cm solid #000000");
2348 break;
2349 case 4: /* Double line */
2350 padd("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2351 padd("fo:border", sXML_CDATA,"0.039cm double #000000");
2352 break;
2355 else
2357 switch( cell->linetype[0] )
2359 case 1: /* A thin solid line */
2360 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2361 padd("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
2362 break;
2363 case 2: /* Bold lines */
2364 padd("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
2365 break;
2366 case 4: /* Double line */
2367 padd("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2368 padd("fo:border-left", sXML_CDATA,"0.039cm double #000000");
2369 break;
2371 switch( cell->linetype[1] )
2373 case 1: /* A thin solid line */
2374 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2375 padd("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
2376 break;
2377 case 2: /* Bold lines */
2378 padd("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
2379 break;
2380 case 4: /* Double line */
2381 padd("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2382 padd("fo:border-right", sXML_CDATA,"0.039cm double #000000");
2383 break;
2385 switch( cell->linetype[2] )
2387 case 1: /* A thin solid line */
2388 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2389 padd("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
2390 break;
2391 case 2: /* Bold lines */
2392 padd("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
2393 break;
2394 case 4: /* Double line */
2395 padd("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2396 padd("fo:border-top", sXML_CDATA,"0.039cm double #000000");
2397 break;
2399 switch( cell->linetype[3] )
2401 case 1: /* A thin solid line */
2402 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2403 padd("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
2404 break;
2405 case 2: /* Bold lines */
2406 padd("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
2407 break;
2408 case 4: /* Double line */
2409 padd("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2410 padd("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
2411 break;
2414 if(cell->shade != 0)
2415 padd("fo:background-color", sXML_CDATA, ascii(hcolor2str(
2416 sal::static_int_cast<uchar>(cell->color),
2417 sal::static_int_cast<uchar>(cell->shade), buf)));
2419 rstartEl("style:properties", mxList.get());
2420 mxList->clear();
2421 rendEl("style:properties");
2422 rendEl("style:style");
2427 * Create a style for the Floating objects.
2429 void HwpReader::makeFStyle(FBoxStyle * fstyle)
2431 /* caption exist */
2432 if( ( fstyle->boxtype == 'G' || fstyle->boxtype == 'X' ) && fstyle->cap_len > 0 )
2434 makeCaptionStyle(fstyle);
2435 return;
2437 switch( fstyle->boxtype )
2439 case 'X' : // txtbox
2440 case 'E' : // equation
2441 case 'B' : // button
2442 case 'O' : // other
2443 case 'T' : // table
2444 padd("style:name", sXML_CDATA,
2445 ascii(Int2Str(fstyle->boxnum, "Txtbox%d", buf)));
2446 padd("style:family", sXML_CDATA, "graphics");
2447 break;
2448 case 'G' : // graphics
2449 padd("style:name", sXML_CDATA,
2450 ascii(Int2Str(fstyle->boxnum, "G%d", buf)));
2451 padd("style:family", sXML_CDATA, "graphics");
2452 break;
2453 case 'L' : // line TODO : all
2454 padd("style:name", sXML_CDATA,
2455 ascii(Int2Str(fstyle->boxnum, "L%d", buf)));
2456 padd( "style:family" , sXML_CDATA , "paragraph" );
2457 break;
2460 rstartEl("style:style", mxList.get());
2461 mxList->clear();
2463 if ( fstyle->boxtype == 'T')
2465 padd("fo:padding", sXML_CDATA, "0cm");
2468 if( !(fstyle->boxtype == 'G' && fstyle->cap_len > 0 ))
2470 padd("fo:margin-left", sXML_CDATA,
2471 Double2Str(WTMM(fstyle->margin[0][0]) ) + "mm");
2472 padd("fo:margin-right", sXML_CDATA,
2473 Double2Str(WTMM(fstyle->margin[0][1])) + "mm");
2474 padd("fo:margin-top", sXML_CDATA,
2475 Double2Str(WTMM(fstyle->margin[0][2])) + "mm");
2476 padd("fo:margin-bottom", sXML_CDATA,
2477 Double2Str(WTMM(fstyle->margin[0][3])) + "mm");
2480 switch (fstyle->txtflow)
2482 case 0:
2483 padd("style:wrap", sXML_CDATA, "none");
2484 break;
2485 case 1:
2486 if( fstyle->boxtype == 'G' || fstyle->boxtype == 'B' || fstyle->boxtype == 'O')
2487 padd("style:run-through", sXML_CDATA, "background");
2488 padd("style:wrap", sXML_CDATA, "run-through");
2489 break;
2490 case 2:
2491 padd("style:wrap", sXML_CDATA, "dynamic");
2492 break;
2494 if (fstyle->anchor_type == CHAR_ANCHOR)
2496 padd("style:vertical-pos", sXML_CDATA, "top");
2497 padd("style:vertical-rel", sXML_CDATA, "baseline");
2498 padd("style:horizontal-pos", sXML_CDATA, "center");
2499 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
2501 else
2504 switch (-(fstyle->xpos))
2506 case 2:
2507 padd("style:horizontal-pos", sXML_CDATA, "right");
2508 break;
2509 case 3:
2510 padd("style:horizontal-pos", sXML_CDATA, "center");
2511 break;
2512 case 1:
2513 default:
2514 padd("style:horizontal-pos", sXML_CDATA, "from-left");
2515 break;
2517 switch (-(fstyle->ypos))
2519 case 2:
2520 padd("style:vertical-pos", sXML_CDATA, "bottom");
2521 break;
2522 case 3:
2523 padd("style:vertical-pos", sXML_CDATA, "middle");
2524 break;
2525 case 1:
2526 default:
2527 padd("style:vertical-pos", sXML_CDATA, "from-top");
2528 break;
2530 if ( fstyle->anchor_type == PARA_ANCHOR )
2532 padd("style:vertical-rel", sXML_CDATA, "paragraph");
2533 padd("style:horizontal-rel", sXML_CDATA, "paragraph");
2535 else
2537 padd("style:vertical-rel", sXML_CDATA, "page-content");
2538 padd("style:horizontal-rel", sXML_CDATA, "page-content");
2541 if( fstyle->boxtype == 'X' || fstyle->boxtype == 'B' )
2543 Cell *cell = static_cast<Cell *>(fstyle->cell);
2544 if(cell->linetype[0] == cell->linetype[1] &&
2545 cell->linetype[0] == cell->linetype[2] &&
2546 cell->linetype[0] == cell->linetype[3])
2548 switch( cell->linetype[0] )
2550 case 0:
2551 padd("fo:border", sXML_CDATA, "none");
2552 break;
2553 case 1: /* A thin solid line */
2554 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2555 padd("fo:border", sXML_CDATA,"0.002cm solid #000000");
2556 break;
2557 case 2: /* Bold lines */
2558 padd("fo:border", sXML_CDATA,"0.035cm solid #000000");
2559 break;
2560 case 4: /* Double line */
2561 padd("style:border-line-width", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2562 padd("fo:border", sXML_CDATA,"0.039cm double #000000");
2563 break;
2566 else
2568 switch( cell->linetype[0] )
2570 case 1: /* A thin solid line */
2571 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2572 padd("fo:border-left", sXML_CDATA,"0.002cm solid #000000");
2573 break;
2574 case 2: /* Bold lines */
2575 padd("fo:border-left", sXML_CDATA,"0.035cm solid #000000");
2576 break;
2577 case 4: /* Double line */
2578 padd("style:border-line-width-left", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2579 padd("fo:border-left", sXML_CDATA,"0.039cm double #000000");
2580 break;
2582 switch( cell->linetype[1] )
2584 case 1: /* A thin solid line */
2585 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2586 padd("fo:border-right", sXML_CDATA,"0.002cm solid #000000");
2587 break;
2588 case 2: /* Bold lines */
2589 padd("fo:border-right", sXML_CDATA,"0.035cm solid #000000");
2590 break;
2591 case 4: /* Double line */
2592 padd("style:border-line-width-right", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2593 padd("fo:border-right", sXML_CDATA,"0.039cm double #000000");
2594 break;
2596 switch( cell->linetype[2] )
2598 case 1: /* A thin solid line */
2599 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2600 padd("fo:border-top", sXML_CDATA,"0.002cm solid #000000");
2601 break;
2602 case 2: /* Bold lines */
2603 padd("fo:border-top", sXML_CDATA,"0.035cm solid #000000");
2604 break;
2605 case 4: /* Double line */
2606 padd("style:border-line-width-top", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2607 padd("fo:border-top", sXML_CDATA,"0.039cm double #000000");
2608 break;
2610 switch( cell->linetype[3] )
2612 case 1: /* A thin solid line */
2613 case 3: /* Dotted line -> LibreOffice, there is no dotted line */
2614 padd("fo:border-bottom", sXML_CDATA,"0.002cm solid #000000");
2615 break;
2616 case 2: /* Bold lines */
2617 padd("fo:border-bottom", sXML_CDATA,"0.035cm solid #000000");
2618 break;
2619 case 4: /* Double line */
2620 padd("style:border-line-width-bottom", sXML_CDATA,"0.002cm 0.035cm 0.002cm");
2621 padd("fo:border-bottom", sXML_CDATA,"0.039cm double #000000");
2622 break;
2626 if( cell->linetype[0] == 0 && cell->linetype[1] == 0 &&
2627 cell->linetype[2] == 0 && cell->linetype[3] == 0 ){
2628 padd("fo:padding", sXML_CDATA,"0mm");
2630 else{
2631 padd("fo:padding-left", sXML_CDATA,
2632 Double2Str(WTMM(fstyle->margin[1][0])) + "mm");
2633 padd("fo:padding-right", sXML_CDATA,
2634 Double2Str(WTMM(fstyle->margin[1][1])) + "mm");
2635 padd("fo:padding-top", sXML_CDATA,
2636 Double2Str(WTMM(fstyle->margin[1][2])) + "mm");
2637 padd("fo:padding-bottom", sXML_CDATA,
2638 Double2Str(WTMM(fstyle->margin[1][3])) + "mm");
2640 if(cell->shade != 0)
2641 padd("fo:background-color", sXML_CDATA,
2642 ascii(hcolor2str(
2643 sal::static_int_cast<uchar>(cell->color),
2644 sal::static_int_cast<uchar>(cell->shade),
2645 buf)));
2647 else if( fstyle->boxtype == 'E' )
2649 padd("fo:padding", sXML_CDATA,"0mm");
2651 else if( fstyle->boxtype == 'L' )
2653 padd( "style:border-line-width-bottom", sXML_CDATA, "0.02mm 0.35mm 0.02mm");
2654 padd("fo:border-bottom", sXML_CDATA,"0.039cm double #808080");
2656 else if( fstyle->boxtype == 'G' )
2658 if( fstyle->margin[1][0] || fstyle->margin[1][1] || fstyle->margin[1][2] || fstyle->margin[1][3] ){
2659 OUString clip = "rect(" +
2660 Double2Str(WTMM(-fstyle->margin[1][0]) ) + "mm " +
2661 Double2Str(WTMM(-fstyle->margin[1][1]) ) + "mm " +
2662 Double2Str(WTMM(-fstyle->margin[1][2]) ) + "mm " +
2663 Double2Str(WTMM(-fstyle->margin[1][3]) ) + "mm)";
2664 padd("style:mirror", sXML_CDATA, "none");
2665 padd("fo:clip", sXML_CDATA, clip);
2667 char *cell = static_cast<char *>(fstyle->cell);
2668 padd("draw:luminance", sXML_CDATA,
2669 ascii(Int2Str(cell[0], "%d%%", buf)));
2670 padd("draw:contrast", sXML_CDATA,
2671 ascii(Int2Str(cell[1], "%d%%", buf)));
2672 if( cell[2] == 0 )
2673 padd("draw:color-mode", sXML_CDATA, "standard");
2674 else if( cell[2] == 1 )
2675 padd("draw:color-mode", sXML_CDATA, "greyscale");
2676 else if( cell[2] == 2 )
2677 padd("draw:color-mode", sXML_CDATA, "mono");
2680 rstartEl("style:properties", mxList.get());
2681 mxList->clear();
2682 rendEl("style:properties");
2683 rendEl("style:style");
2687 char *HwpReader::getTStyleName(int index, char *_buf)
2689 return Int2Str(index, "T%d", _buf);
2693 char *HwpReader::getPStyleName(int index, char *_buf)
2695 return Int2Str(index, "P%d", _buf);
2699 void HwpReader::makeChars(hchar_string & rStr)
2701 rchars(reinterpret_cast<sal_Unicode const *>(rStr.c_str()));
2702 rStr.clear();
2707 * If no special characters in the paragraph and all characters use the same CharShape
2709 void HwpReader::make_text_p0(HWPPara * para, bool bParaStart)
2711 hchar_string str;
2712 int n;
2713 int res;
2714 hchar dest[3];
2715 unsigned char firstspace = 0;
2716 if( !bParaStart)
2718 padd("text:style-name", sXML_CDATA,
2719 ascii(getPStyleName(para->GetParaShape().index, buf)));
2720 rstartEl("text:p", mxList.get());
2721 mxList->clear();
2723 if( d->bFirstPara && d->bInBody )
2725 strcpy(
2726 buf,
2727 "[\xEB\xAC\xB8\xEC\x84\x9C\xEC\x9D\x98 \xEC\xB2\x98\xEC\x9D\x8C]");
2728 // U+BB38 HANGUL SYLLABLE MUN, U+C11C HANGUL SYLLABLE SEO,
2729 // U+C758 HANGUL SYLLABLE YI, U+CC98 HANGUL SYLLABLE CEO,
2730 // U+C74C HANGUL SYLLABLE EUM: "Begin of Document"
2731 padd("text:name", sXML_CDATA, OUString(buf, strlen(buf), RTL_TEXTENCODING_UTF8));
2732 rstartEl("text:bookmark", mxList.get());
2733 mxList->clear();
2734 rendEl("text:bookmark");
2735 d->bFirstPara = false;
2737 if( d->bInHeader )
2739 makeShowPageNum();
2740 d->bInHeader = false;
2742 padd("text:style-name", sXML_CDATA,
2743 ascii(getTStyleName(para->cshape->index, buf)));
2744 rstartEl("text:span", mxList.get());
2745 mxList->clear();
2747 for (n = 0; n < para->nch && para->hhstr[n]->hh;
2748 n += para->hhstr[n]->WSize())
2750 if (para->hhstr[n]->hh == CH_SPACE && !firstspace)
2752 makeChars(str);
2753 rstartEl("text:s", mxList.get());
2754 rendEl("text:s");
2756 else if (para->hhstr[n]->hh == CH_END_PARA)
2758 makeChars(str);
2759 rendEl("text:span");
2760 rendEl("text:p");
2761 break;
2763 else
2765 if (para->hhstr[n]->hh == CH_SPACE)
2766 firstspace = 0;
2767 else
2768 firstspace = 1;
2769 res = hcharconv(para->hhstr[n]->hh, dest, UNICODE);
2770 for( int j = 0 ; j < res; j++ )
2772 str.push_back(dest[j]);
2780 * There is no special characters in the paragraph, but characters use different CharShapes
2782 void HwpReader::make_text_p1(HWPPara * para,bool bParaStart)
2784 hchar_string str;
2785 int n;
2786 int res;
2787 hchar dest[3];
2788 int curr = para->cshape->index;
2789 unsigned char firstspace = 0;
2791 if( !bParaStart )
2793 padd("text:style-name", sXML_CDATA,
2794 ascii(getPStyleName(para->GetParaShape().index, buf)));
2795 rstartEl("text:p", mxList.get());
2796 mxList->clear();
2798 if( d->bFirstPara && d->bInBody )
2800 /* for HWP's Bookmark */
2801 strcpy(
2802 buf,
2803 "[\xEB\xAC\xB8\xEC\x84\x9C\xEC\x9D\x98 \xEC\xB2\x98\xEC\x9D\x8C]");
2804 // U+BB38 HANGUL SYLLABLE MUN, U+C11C HANGUL SYLLABLE SEO,
2805 // U+C758 HANGUL SYLLABLE YI, U+CC98 HANGUL SYLLABLE CEO,
2806 // U+C74C HANGUL SYLLABLE EUM: "Begin of Document"
2807 padd("text:name", sXML_CDATA, OUString(buf, strlen(buf), RTL_TEXTENCODING_UTF8));
2808 rstartEl("text:bookmark", mxList.get());
2809 mxList->clear();
2810 rendEl("text:bookmark");
2811 d->bFirstPara = false;
2813 if( d->bInHeader )
2815 makeShowPageNum();
2816 d->bInHeader = false;
2818 padd("text:style-name", sXML_CDATA,
2819 ascii(getTStyleName(curr, buf)));
2820 rstartEl("text:span", mxList.get());
2821 mxList->clear();
2823 for (n = 0; n < para->nch && para->hhstr[n]->hh;
2824 n += para->hhstr[n]->WSize())
2826 if (para->GetCharShape(n)->index != curr)
2828 makeChars(str);
2829 rendEl("text:span");
2830 curr = para->GetCharShape(n)->index;
2831 padd("text:style-name", sXML_CDATA,
2832 ascii(getTStyleName(curr, buf)));
2833 rstartEl("text:span", mxList.get());
2834 mxList->clear();
2836 if (para->hhstr[n]->hh == CH_SPACE && !firstspace)
2838 makeChars(str);
2839 rstartEl("text:s", mxList.get());
2840 rendEl("text:s");
2842 else if (para->hhstr[n]->hh == CH_END_PARA)
2844 makeChars(str);
2845 rendEl("text:span");
2846 rendEl("text:p");
2847 break;
2849 else
2851 if( para->hhstr[n]->hh < CH_SPACE )
2852 continue;
2853 if (para->hhstr[n]->hh == CH_SPACE)
2854 firstspace = 0;
2855 else
2856 firstspace = 1;
2857 res = hcharconv(para->hhstr[n]->hh, dest, UNICODE);
2858 for( int j = 0 ; j < res; j++ )
2860 str.push_back(dest[j]);
2868 * Special characters are in the paragraph and characters use different CharShapes
2870 void HwpReader::make_text_p3(HWPPara * para,bool bParaStart)
2872 hchar_string str;
2873 int n, res;
2874 hchar dest[3];
2875 unsigned char firstspace = 0;
2876 bool pstart = bParaStart;
2877 bool tstart = false;
2878 bool infield = false;
2879 int curr;
2880 if( d->bFirstPara && d->bInBody )
2882 if ( !pstart ) {
2883 STARTP;
2885 strcpy(
2886 buf,
2887 "[\xEB\xAC\xB8\xEC\x84\x9C\xEC\x9D\x98 \xEC\xB2\x98\xEC\x9D\x8C]");
2888 // U+BB38 HANGUL SYLLABLE MUN, U+C11C HANGUL SYLLABLE SEO,
2889 // U+C758 HANGUL SYLLABLE YI, U+CC98 HANGUL SYLLABLE CEO,
2890 // U+C74C HANGUL SYLLABLE EUM: "Begin of Document"
2891 padd("text:name", sXML_CDATA, OUString(buf, strlen(buf), RTL_TEXTENCODING_UTF8));
2892 rstartEl("text:bookmark", mxList.get());
2893 mxList->clear();
2894 rendEl("text:bookmark");
2895 d->bFirstPara = false;
2897 if( d->bInHeader )
2899 if ( !pstart ) {
2900 STARTP;
2902 makeShowPageNum();
2903 d->bInHeader = false;
2906 for (n = 0; n < para->nch && para->hhstr[n]->hh;
2907 n += para->hhstr[n]->WSize())
2909 if( para->hhstr[n]->hh == CH_END_PARA )
2911 if (!str.empty())
2913 if( !pstart ){ STARTP;}
2914 if( !tstart ){ STARTT;}
2915 makeChars(str);
2917 if( tstart ){ ENDT;}
2918 if( !pstart ){ STARTP;}
2919 if( pstart ){ ENDP;}
2920 break;
2922 else if( para->hhstr[n]->hh == CH_SPACE && !firstspace)
2924 if( !pstart ) {STARTP;}
2925 if( !tstart ) {STARTT;}
2926 makeChars(str);
2927 rstartEl("text:s", mxList.get());
2928 mxList->clear();
2929 rendEl("text:s");
2931 else if ( para->hhstr[n]->hh >= CH_SPACE )
2933 if( n > 0 )
2934 if( para->GetCharShape(n)->index != para->GetCharShape(n-1)->index && !infield )
2936 if( !pstart ) {STARTP;}
2937 if( !tstart ) {STARTT;}
2938 makeChars(str);
2939 ENDT;
2941 if( para->hhstr[n]->hh == CH_SPACE )
2942 firstspace = 0;
2943 else
2944 firstspace = 1;
2945 res = hcharconv(para->hhstr[n]->hh, dest, UNICODE);
2946 for( int j = 0 ; j < res; j++ )
2948 str.push_back(dest[j]);
2951 else if (para->hhstr[n]->hh == CH_FIELD)
2953 FieldCode *hbox = static_cast<FieldCode*>(para->hhstr[n].get());
2954 if( hbox->location_info == 1)
2956 if( !pstart ) {STARTP;}
2957 if( !tstart ) {STARTT;}
2958 makeChars(str);
2959 firstspace = 1;
2960 if( hbox->type[0] == 4 && hbox->type[1] == 0 )
2962 field = hbox->str3.get();
2964 else{
2965 makeFieldCode(str, hbox);
2967 infield = true;
2969 else
2971 firstspace = 1;
2972 if( hbox->type[0] == 4 && hbox->type[1] == 0 )
2974 makeFieldCode(str, hbox);
2975 field = nullptr;
2977 infield = false;
2978 str.clear();
2981 else
2983 switch (para->hhstr[n]->hh)
2985 case CH_BOOKMARK:
2986 if( !pstart ) {STARTP;}
2987 if( !tstart ) {STARTT;}
2988 makeChars(str);
2989 makeBookmark(static_cast<Bookmark*>(para->hhstr[n].get()));
2990 break;
2991 case CH_DATE_FORM: // 7
2992 break;
2993 case CH_DATE_CODE: // 8
2994 if( !pstart ) {STARTP;}
2995 if( !tstart ) {STARTT;}
2996 makeChars(str);
2997 makeDateCode(static_cast<DateCode*>(para->hhstr[n].get()));
2998 break;
2999 case CH_TAB: // 9
3000 if( !pstart ) {STARTP;}
3001 if (!str.empty())
3003 if( !tstart ) {STARTT;}
3004 makeChars(str);
3006 makeTab();
3007 break;
3008 case CH_TEXT_BOX: /* 10 - ordered by Table/text box/formula/button/hypertext */
3010 /* produce tables first, and treat formula as being in text:p. */
3011 TxtBox *hbox = static_cast<TxtBox*>(para->hhstr[n].get());
3013 if( hbox->style.anchor_type == 0 )
3015 if( !pstart ) {STARTP;}
3016 if( !tstart ) {STARTT;}
3017 makeChars(str);
3019 else
3021 if( !pstart ) {STARTP;}
3022 if (!str.empty())
3024 if( !tstart ) {STARTT;}
3025 makeChars(str);
3027 if( tstart ) {ENDT;}
3029 switch (hbox->type)
3031 case TBL_TYPE: // table
3032 case TXT_TYPE: // text box
3033 case EQU_TYPE: // formula
3034 makeTextBox(hbox);
3035 break;
3036 case BUTTON_TYPE: // text button
3037 case HYPERTEXT_TYPE: // hypertext
3038 makeHyperText(hbox);
3039 break;
3041 break;
3043 case CH_PICTURE: // 11
3045 Picture *hbox = static_cast<Picture*>(para->hhstr[n].get());
3046 if( hbox->style.anchor_type == 0 )
3048 if( !pstart ) {STARTP;}
3049 if( !tstart ) {STARTT;}
3050 makeChars(str);
3052 else
3054 if( !pstart ) {STARTP;}
3055 if (!str.empty())
3057 if( !tstart ) {STARTT;}
3058 makeChars(str);
3060 if( tstart ) {ENDT;}
3062 makePicture(hbox);
3063 break;
3065 case CH_LINE: // 14
3067 if (!str.empty())
3069 if( !pstart ) {STARTP;}
3070 if( !tstart ) {STARTT;}
3071 makeChars(str);
3073 if( tstart ) {ENDT;}
3074 if( pstart ) {ENDP;}
3075 makeLine();
3076 pstart = true;
3077 break;
3079 case CH_HIDDEN: // 15
3080 if( !pstart ) {STARTP;}
3081 if( !tstart ) {STARTT;}
3082 makeChars(str);
3083 makeHidden(static_cast<Hidden*>(para->hhstr[n].get()));
3084 break;
3085 case CH_FOOTNOTE: // 17
3086 if( !pstart ) {STARTP;}
3087 if( !tstart ) {STARTT;}
3088 makeChars(str);
3089 makeFootnote(static_cast<Footnote*>(para->hhstr[n].get()));
3090 break;
3091 case CH_AUTO_NUM: // 18
3092 if( !pstart ) {STARTP;}
3093 if( !tstart ) {STARTT;}
3094 makeChars(str);
3095 makeAutoNum(static_cast<AutoNum*>(para->hhstr[n].get()));
3096 break;
3097 case CH_NEW_NUM: // 19 -skip
3098 break;
3099 case CH_PAGE_NUM_CTRL: // 21
3100 break;
3101 case CH_MAIL_MERGE: // 22
3102 if( !pstart ) {STARTP;}
3103 if( !tstart ) {STARTT;}
3104 makeChars(str);
3105 makeMailMerge(static_cast<MailMerge*>(para->hhstr[n].get()));
3106 break;
3107 case CH_COMPOSE: /* 23 - overlapping letters */
3108 break;
3109 case CH_HYPHEN: // 24
3110 break;
3111 case CH_TOC_MARK: /* 25 Need to fix below 3 */
3112 if( !pstart ) {STARTP;}
3113 if( !tstart ) {STARTT;}
3114 makeChars(str);
3115 break;
3116 case CH_INDEX_MARK: // 26
3117 if( !pstart ) {STARTP;}
3118 if( !tstart ) {STARTT;}
3119 makeChars(str);
3120 break;
3121 case CH_OUTLINE: // 28
3122 if( !pstart ) {STARTP;}
3123 if( !tstart ) {STARTT;}
3124 makeChars(str);
3125 makeOutline(static_cast<Outline *>(para->hhstr[n].get()));
3126 break;
3127 case CH_FIXED_SPACE:
3128 case CH_KEEP_SPACE:
3129 str.push_back(0x0020);
3130 break;
3137 void HwpReader::makeFieldCode(hchar_string const & rStr, FieldCode const *hbox)
3139 /* Push frame */
3140 if( hbox->type[0] == 4 && hbox->type[1] == 0 )
3142 padd("text:placeholder-type", sXML_CDATA, "text");
3143 if( field )
3144 padd("text:description", sXML_CDATA, reinterpret_cast<sal_Unicode const *>(hconv(field)));
3145 rstartEl( "text:placeholder", mxList.get());
3146 mxList->clear();
3147 rchars( reinterpret_cast<sal_Unicode const *>(rStr.c_str()) );
3148 rendEl( "text:placeholder" );
3150 /* Document Summary */
3151 else if( hbox->type[0] == 3 && hbox->type[1] == 0 )
3153 if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "title")
3155 rstartEl( "text:title", mxList.get() );
3156 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3157 rendEl( "text:title" );
3159 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "subject")
3161 rstartEl( "text:subject", mxList.get() );
3162 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3163 rendEl( "text:subject" );
3165 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "author")
3167 rstartEl( "text:author-name", mxList.get() );
3168 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3169 rendEl( "text:author-name" );
3171 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "keywords")
3173 rstartEl( "text:keywords", mxList.get() );
3174 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3175 rendEl( "text:keywords" );
3178 /* Personal Information */
3179 else if( hbox->type[0] == 3 && hbox->type[1] == 1 )
3181 if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "User")
3183 rstartEl( "text:sender-lastname", mxList.get() );
3184 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3185 rendEl( "text:sender-lastname" );
3187 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Company")
3189 rstartEl( "text:sender-company", mxList.get() );
3190 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3191 rendEl( "text:sender-company" );
3193 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Position")
3195 rstartEl( "text:sender-title", mxList.get() );
3196 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3197 rendEl( "text:sender-title" );
3199 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Division")
3201 rstartEl( "text:sender-position", mxList.get() );
3202 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3203 rendEl( "text:sender-position" );
3205 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Fax")
3207 rstartEl( "text:sender-fax", mxList.get() );
3208 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3209 rendEl( "text:sender-fax" );
3211 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Pager")
3213 rstartEl( "text:phone-private", mxList.get() );
3214 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3215 rendEl( "text:phone-private" );
3217 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "E-mail")
3219 rstartEl( "text:sender-email", mxList.get() );
3220 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3221 rendEl( "text:sender-email" );
3223 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Zipcode(office)")
3225 rstartEl( "text:sender-postal-code", mxList.get() );
3226 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3227 rendEl( "text:sender-postal-code" );
3229 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Phone(office)")
3231 rstartEl( "text:sender-phone-work", mxList.get() );
3232 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3233 rendEl( "text:sender-phone-work" );
3235 else if (OUString(reinterpret_cast<sal_Unicode const *>(hconv(hbox->str3.get()))) == "Address(office)")
3237 rstartEl( "text:sender-street", mxList.get() );
3238 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3239 rendEl( "text:sender-street" );
3243 else if( hbox->type[0] == 3 && hbox->type[1] == 2 ) /* creation date */
3245 if( hbox->m_pDate )
3246 padd("style:data-style-name", sXML_CDATA,
3247 ascii(Int2Str(hbox->m_pDate->key, "N%d", buf)));
3248 rstartEl( "text:creation-date", mxList.get() );
3249 mxList->clear();
3250 rchars( reinterpret_cast<sal_Unicode const *>(hconv(hbox->str2.get())) );
3251 rendEl( "text:creation-date" );
3257 * Completed
3258 * In LibreOffice, refer bookmarks as reference, but hwp doesn't have the sort of feature.
3260 void HwpReader::makeBookmark(Bookmark const * hbox)
3262 if (hbox->type == 0)
3264 padd("text:name", sXML_CDATA, reinterpret_cast<sal_Unicode const *>(hconv(hbox->id)));
3265 rstartEl("text:bookmark", mxList.get());
3266 mxList->clear();
3267 rendEl("text:bookmark");
3269 else if (hbox->type == 1) /* Block bookmarks days begin and end there if */
3271 padd("text:name", sXML_CDATA, reinterpret_cast<sal_Unicode const *>(hconv(hbox->id)));
3272 rstartEl("text:bookmark-start", mxList.get());
3273 mxList->clear();
3274 rendEl("text:bookmark-start");
3276 else if (hbox->type == 2)
3278 padd("text:name", sXML_CDATA, reinterpret_cast<sal_Unicode const *>(hconv(hbox->id)));
3279 rstartEl("text:bookmark-end", mxList.get());
3280 mxList->clear();
3281 rendEl("text:bookmark-end");
3286 void HwpReader::makeDateFormat(DateCode * hbox)
3288 padd("style:name", sXML_CDATA,
3289 ascii(Int2Str(hbox->key, "N%d", buf)));
3290 padd("style:family", sXML_CDATA,"data-style");
3291 padd("number:language", sXML_CDATA,"ko");
3292 padd("number:country", sXML_CDATA,"KR");
3294 rstartEl("number:date-style", mxList.get());
3295 mxList->clear();
3297 bool add_zero = false;
3298 int zero_check = 0;
3299 hbox->format[DATE_SIZE -1] = 0;
3301 const hchar *fmt = hbox->format[0] ? hbox->format : defaultform;
3303 for( ; *fmt ; fmt++ )
3305 if( zero_check == 1 )
3307 zero_check = 0;
3309 else
3310 add_zero = false;
3312 switch( *fmt )
3314 case '0':
3315 zero_check = 1;
3316 add_zero = true;
3317 break;
3318 case '1':
3319 padd("number:style", sXML_CDATA, "long");
3320 rstartEl("number:year", mxList.get());
3321 mxList->clear();
3322 rendEl("number:year");
3323 break;
3324 case '!':
3325 rstartEl("number:year", mxList.get());
3326 mxList->clear();
3327 rendEl("number:year");
3328 break;
3329 case '2':
3330 if( add_zero )
3331 padd("number:style", sXML_CDATA, "long");
3332 rstartEl("number:month", mxList.get());
3333 mxList->clear();
3334 rendEl("number:month");
3335 break;
3336 case '@':
3337 padd("number:textual", sXML_CDATA, "true");
3338 rstartEl("number:month", mxList.get());
3339 mxList->clear();
3340 rendEl("number:month");
3341 break;
3342 case '*':
3343 padd("number:textual", sXML_CDATA, "true");
3344 padd("number:style", sXML_CDATA, "long");
3345 rstartEl("number:month", mxList.get());
3346 mxList->clear();
3347 rendEl("number:month");
3348 break;
3349 case '3':
3350 if( add_zero )
3351 padd("number:style", sXML_CDATA, "long");
3352 rstartEl("number:day", mxList.get());
3353 mxList->clear();
3354 rendEl("number:day");
3355 break;
3356 case '#':
3357 if( add_zero )
3358 padd("number:style", sXML_CDATA, "long");
3359 rstartEl("number:day", mxList.get());
3360 mxList->clear();
3361 rendEl("number:day");
3362 switch( hbox->date[DateCode::DAY] % 10)
3364 case 1:
3365 rstartEl("number:text", mxList.get());
3366 rchars("st");
3367 rendEl("number:text");
3368 break;
3369 case 2:
3370 rstartEl("number:text", mxList.get());
3371 rchars("nd");
3372 rendEl("number:text");
3373 break;
3374 case 3:
3375 rstartEl("number:text", mxList.get());
3376 rchars("rd");
3377 rendEl("number:text");
3378 break;
3379 default:
3380 rstartEl("number:text", mxList.get());
3381 rchars("th");
3382 rendEl("number:text");
3383 break;
3385 break;
3386 case '4':
3387 case '$':
3388 if( add_zero )
3389 padd("number:style", sXML_CDATA, "long");
3390 rstartEl("number:hours", mxList.get());
3391 mxList->clear();
3392 rendEl("number:hours");
3393 break;
3394 case '5':
3395 case '%':
3396 if( add_zero )
3397 padd("number:style", sXML_CDATA, "long");
3398 rstartEl("number:minutes", mxList.get());
3399 mxList->clear();
3400 rendEl("number:minutes");
3401 break;
3402 case '_':
3403 padd("number:style", sXML_CDATA, "long");
3404 [[fallthrough]];
3405 case '6':
3406 case '^':
3407 rstartEl("number:day-of-week", mxList.get());
3408 mxList->clear();
3409 rendEl("number:day-of-week");
3410 break;
3411 case '7':
3412 case '&':
3413 case '+':
3414 rstartEl("number:am-pm", mxList.get());
3415 mxList->clear();
3416 rendEl("number:am-pm");
3417 break;
3418 case '~': // Chinese Locale
3419 break;
3420 default:
3421 hchar sbuf[2];
3422 sbuf[0] = *fmt;
3423 sbuf[1] = 0;
3424 rstartEl("number:text", mxList.get());
3425 rchars(reinterpret_cast<sal_Unicode const *>(hconv(sbuf)));
3426 rendEl("number:text");
3427 break;
3430 mxList->clear();
3431 rendEl("number:date-style");
3435 void HwpReader::makeDateCode(DateCode * hbox)
3437 padd("style:data-style-name", sXML_CDATA,
3438 ascii(Int2Str(hbox->key, "N%d", buf)));
3439 rstartEl( "text:date", mxList.get() );
3440 mxList->clear();
3441 hchar_string const boxstr = hbox->GetString();
3442 rchars(reinterpret_cast<sal_Unicode const *>(hconv(boxstr.c_str())));
3443 rendEl( "text:date" );
3447 void HwpReader::makeTab()
3449 rstartEl("text:tab-stop", mxList.get());
3450 rendEl("text:tab-stop");
3454 void HwpReader::makeTable(TxtBox * hbox)
3456 padd("table:name", sXML_CDATA,
3457 ascii(Int2Str(hbox->style.boxnum, "Table%d", buf)));
3458 padd("table:style-name", sXML_CDATA,
3459 ascii(Int2Str(hbox->style.boxnum, "Table%d", buf)));
3460 rstartEl("table:table", mxList.get());
3461 mxList->clear();
3463 Table *tbl = hbox->m_pTable;
3464 // column
3465 for (size_t i = 0 ; i < tbl->columns.nCount -1 ; i++)
3467 sprintf(buf,"Table%d.%c",hbox->style.boxnum, static_cast<char>('A'+i));
3468 padd("table:style-name", sXML_CDATA, ascii( buf ));
3469 rstartEl("table:table-column", mxList.get());
3470 mxList->clear();
3471 rendEl("table:table-column");
3474 // cell
3475 int j = -1, k = -1;
3476 for (auto const& tcell : tbl->cells)
3478 if( tcell->nRowIndex > j )
3480 if( j > k )
3482 rendEl("table:table-row");
3483 k = j;
3485 // row
3486 sprintf(buf,"Table%d.row%d",hbox->style.boxnum, tcell->nRowIndex + 1);
3487 padd("table:style-name", sXML_CDATA, ascii( buf ));
3488 rstartEl("table:table-row", mxList.get());
3489 mxList->clear();
3490 j = tcell->nRowIndex;
3493 sprintf(buf,"Table%d.%c%d",hbox->style.boxnum, 'A'+ tcell->nColumnIndex, tcell->nRowIndex +1);
3494 padd("table:style-name", sXML_CDATA, ascii( buf ));
3495 if( tcell->nColumnSpan > 1 )
3496 padd("table:number-columns-spanned", sXML_CDATA,
3497 ascii(Int2Str(tcell->nColumnSpan, "%d", buf)));
3498 if( tcell->nRowSpan > 1 )
3499 padd("table:number-rows-spanned", sXML_CDATA,
3500 ascii(Int2Str(tcell->nRowSpan, "%d", buf)));
3501 padd("table:value-type", sXML_CDATA,"string");
3502 if( tcell->pCell->protect )
3503 padd("table:protected", sXML_CDATA,"true");
3504 rstartEl("table:table-cell", mxList.get());
3505 mxList->clear();
3506 parsePara(hbox->plists[tcell->pCell->key].front().get());
3507 rendEl("table:table-cell");
3509 rendEl("table:table-row");
3510 rendEl("table:table");
3515 * Parses the text boxes and tables.
3516 * 1. draw: style-name, draw: name, text: anchor-type, svg: width,
3517 * Fo: min-height, svg: x, svg: y
3518 * TODO: fo:background-color <= no idea whether the value of color setting->style is in it or not
3520 void HwpReader::makeTextBox(TxtBox * hbox)
3522 if( hbox->style.cap_len > 0 && hbox->type == TXT_TYPE)
3524 padd("draw:style-name", sXML_CDATA,
3525 ascii(Int2Str(hbox->style.boxnum, "CapBox%d", buf)));
3526 padd("draw:name", sXML_CDATA,
3527 ascii(Int2Str(hbox->style.boxnum, "CaptionBox%d", buf)));
3528 padd("draw:z-index", sXML_CDATA,
3529 ascii(Int2Str(hbox->zorder, "%d", buf)));
3530 switch (hbox->style.anchor_type)
3532 case CHAR_ANCHOR:
3533 padd("text:anchor-type", sXML_CDATA, "as-char");
3534 break;
3535 case PARA_ANCHOR:
3536 padd("text:anchor-type", sXML_CDATA, "paragraph");
3537 break;
3538 case PAGE_ANCHOR:
3539 case PAPER_ANCHOR:
3541 padd("text:anchor-type", sXML_CDATA, "page");
3542 padd("text:anchor-page-number", sXML_CDATA,
3543 ascii(Int2Str(hbox->pgno +1, "%d", buf)));
3544 break;
3547 if (hbox->style.anchor_type != CHAR_ANCHOR)
3549 padd("svg:x", sXML_CDATA,
3550 Double2Str(WTMM( ( hbox->pgx + hbox->style.margin[0][0] ) )) + "mm");
3551 padd("svg:y", sXML_CDATA,
3552 Double2Str(WTMM( ( hbox->pgy + hbox->style.margin[0][2] ) )) + "mm");
3554 padd("svg:width", sXML_CDATA,
3555 Double2Str(WTMM(( hbox->box_xs + hbox->cap_xs) )) + "mm");
3556 padd("fo:min-height", sXML_CDATA,
3557 Double2Str(WTMM(( hbox->box_ys + hbox->cap_ys) )) + "mm");
3558 rstartEl("draw:text-box", mxList.get());
3559 mxList->clear();
3560 if( hbox->cap_pos % 2 ) /* The caption is on the top */
3562 parsePara(hbox->caption.front().get());
3564 padd( "text:style-name", sXML_CDATA, "Standard");
3565 rstartEl("text:p", mxList.get());
3566 mxList->clear();
3568 else{
3569 padd("draw:z-index", sXML_CDATA,
3570 ascii(Int2Str(hbox->zorder, "%d", buf)));
3573 padd("draw:style-name", sXML_CDATA,
3574 ascii(Int2Str(hbox->style.boxnum, "Txtbox%d", buf)));
3575 padd("draw:name", sXML_CDATA,
3576 ascii(Int2Str(hbox->style.boxnum, "Frame%d", buf)));
3578 if( hbox->style.cap_len <= 0 || hbox->type != TXT_TYPE )
3580 int x = 0;
3581 int y = 0;
3582 switch (hbox->style.anchor_type)
3584 case CHAR_ANCHOR:
3585 padd("text:anchor-type", sXML_CDATA, "as-char");
3586 break;
3587 case PARA_ANCHOR:
3588 padd("text:anchor-type", sXML_CDATA, "paragraph");
3589 break;
3590 case PAGE_ANCHOR:
3591 case PAPER_ANCHOR:
3593 padd("text:anchor-type", sXML_CDATA, "page");
3594 padd("text:anchor-page-number", sXML_CDATA,
3595 ascii(Int2Str(hbox->pgno +1, "%d", buf)));
3596 break;
3599 if( hbox->style.anchor_type != CHAR_ANCHOR )
3601 x += hbox->style.margin[0][0];
3602 y += hbox->style.margin[0][2];
3604 padd("svg:x", sXML_CDATA,
3605 Double2Str(WTMM( hbox->pgx + x )) + "mm");
3606 padd("svg:y", sXML_CDATA,
3607 Double2Str(WTMM( hbox->pgy + y )) + "mm");
3609 else
3611 padd("text:anchor-type", sXML_CDATA, "as-char");
3612 padd("svg:y", sXML_CDATA, "0cm");
3614 padd("svg:width", sXML_CDATA,
3615 Double2Str(WTMM( hbox->box_xs )) + "mm");
3616 if( hbox->style.cap_len > 0 && hbox->type != TXT_TYPE)
3617 padd("fo:min-height", sXML_CDATA,
3618 Double2Str(WTMM( hbox->box_ys + hbox->cap_ys)) + "mm");
3619 else
3620 padd("svg:height", sXML_CDATA,
3621 Double2Str(WTMM(hbox->box_ys )) + "mm");
3623 if( hbox->type != EQU_TYPE )
3625 rstartEl("draw:text-box", mxList.get());
3626 mxList->clear();
3627 /* If captions are present and it is on the top */
3628 if( hbox->style.cap_len > 0 && (hbox->cap_pos % 2) && hbox->type == TBL_TYPE )
3630 parsePara(hbox->caption.front().get());
3632 if( hbox->type == TBL_TYPE) // Is Table
3634 makeTable(hbox);
3636 else // Is TextBox
3638 parsePara(hbox->plists[0].front().get());
3640 /* If captions are present and it is on the bottom */
3641 if( hbox->style.cap_len > 0 && !(hbox->cap_pos % 2) && hbox->type == TBL_TYPE)
3643 parsePara(hbox->caption.front().get());
3645 rendEl("draw:text-box");
3646 // Caption exist and it is text-box
3647 if( hbox->style.cap_len > 0 && hbox->type == TXT_TYPE)
3649 rendEl( "text:p");
3650 if( !(hbox->cap_pos % 2))
3652 parsePara(hbox->caption.front().get());
3654 rendEl( "draw:text-box");
3657 else // is Formula
3659 rstartEl("draw:object", mxList.get());
3660 mxList->clear();
3661 makeFormula(hbox);
3662 rendEl("draw:object");
3668 * It must be converted into MathML.
3671 void HwpReader::makeFormula(TxtBox * hbox)
3673 char mybuf[3000];
3674 HWPPara* pPar;
3676 int n, c, res;
3677 hchar dest[3];
3678 size_t l = 0;
3680 pPar = hbox->plists[0].front().get();
3681 while( pPar )
3683 for( n = 0; n < pPar->nch && pPar->hhstr[n]->hh;
3684 n += pPar->hhstr[n]->WSize() )
3686 if (l >= sizeof(mybuf)-7)
3687 break;
3688 res = hcharconv(pPar->hhstr[n]->hh, dest, UNICODE);
3689 for( int j = 0 ; j < res; j++ ){
3690 c = dest[j];
3691 if( c < 32 )
3692 c = ' ';
3693 if( c < 256 )
3694 mybuf[l++] = sal::static_int_cast<char>(c);
3695 else
3697 mybuf[l++] = sal::static_int_cast<char>((c >> 8) & 0xff);
3698 mybuf[l++] = sal::static_int_cast<char>(c & 0xff);
3702 if (l >= sizeof(mybuf)-7)
3703 break;
3704 mybuf[l++] = '\n';
3705 pPar = pPar->Next();
3707 mybuf[l] = '\0';
3709 std::unique_ptr<Formula> form( new Formula(mybuf) );
3710 form->setDocumentHandler(m_rxDocumentHandler);
3711 form->setAttributeListImpl(mxList.get());
3712 form->parse();
3716 * Read the platform information. if the platform is Linux or Solaris, it needs to change
3717 * C: \ => Home, D: \ => changed to root (/). Because HWP uses DOS emulator.
3720 void HwpReader::makeHyperText(TxtBox * hbox)
3722 HyperText *hypert = hwpfile.GetHyperText();
3723 if( !hypert ) return;
3725 if (hypert->filename[0] != '\0') {
3726 ::std::string const tmp = hstr2ksstr(hypert->bookmark);
3727 ::std::string const tmp2 = hstr2ksstr(kstr2hstr(
3728 #ifdef _WIN32
3729 reinterpret_cast<uchar const *>(urltowin(reinterpret_cast<char *>(hypert->filename)).c_str())).c_str());
3730 #else
3731 reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hypert->filename)).c_str())).c_str());
3732 #endif
3733 padd("xlink:type", sXML_CDATA, "simple");
3734 if (!tmp.empty() && strcmp(tmp.c_str(), "[HTML]")) {
3735 ::std::string tmp3(tmp2);
3736 tmp3.push_back('#');
3737 tmp3.append(tmp);
3738 padd("xlink:href", sXML_CDATA,
3739 OUString(tmp3.c_str(), tmp3.size()+1, RTL_TEXTENCODING_EUC_KR));
3741 else{
3742 padd("xlink:href", sXML_CDATA,
3743 OUString(tmp2.c_str(), tmp2.size()+1, RTL_TEXTENCODING_EUC_KR));
3747 else
3749 padd("xlink:type", sXML_CDATA, "simple");
3750 ::std::string tmp;
3751 tmp.push_back('#');
3752 tmp.append(hstr2ksstr(hypert->bookmark));
3753 padd("xlink:href", sXML_CDATA,
3754 OUString(tmp.c_str(), tmp.size()+1, RTL_TEXTENCODING_EUC_KR));
3756 rstartEl("draw:a", mxList.get());
3757 mxList->clear();
3758 makeTextBox(hbox);
3759 rendEl("draw:a");
3764 * Read the platform information. if the platform is Linux or Solaris, it needs to change
3765 * C: \ => Home, D: \ => changed to root (/). Because HWP uses DOS emulator.
3768 void HwpReader::makePicture(Picture * hbox)
3770 switch (hbox->pictype)
3772 case PICTYPE_OLE:
3773 case PICTYPE_EMBED:
3774 case PICTYPE_FILE:
3776 if( hbox->style.cap_len > 0 )
3778 padd("draw:style-name", sXML_CDATA,
3779 ascii(Int2Str(hbox->style.boxnum, "CapBox%d", buf)));
3780 padd("draw:name", sXML_CDATA,
3781 ascii(Int2Str(hbox->style.boxnum, "CaptionBox%d", buf)));
3782 padd("draw:z-index", sXML_CDATA,
3783 ascii(Int2Str(hbox->zorder, "%d", buf)));
3784 switch (hbox->style.anchor_type)
3786 case CHAR_ANCHOR:
3787 padd("text:anchor-type", sXML_CDATA, "as-char");
3788 break;
3789 case PARA_ANCHOR:
3790 padd("text:anchor-type", sXML_CDATA, "paragraph");
3791 break;
3792 case PAGE_ANCHOR:
3793 case PAPER_ANCHOR:
3795 padd("text:anchor-type", sXML_CDATA, "page");
3796 padd("text:anchor-page-number", sXML_CDATA,
3797 ascii(Int2Str(hbox->pgno +1, "%d", buf)));
3798 break;
3801 if (hbox->style.anchor_type != CHAR_ANCHOR)
3803 padd("svg:x", sXML_CDATA,
3804 Double2Str(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
3805 padd("svg:y", sXML_CDATA,
3806 Double2Str(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
3808 padd("svg:width", sXML_CDATA,
3809 Double2Str(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1] )) + "mm");
3810 padd("fo:min-height", sXML_CDATA,
3811 Double2Str(WTMM( hbox->box_ys + hbox->style.margin[1][2] + hbox->style.margin[1][3] + hbox->cap_ys )) + "mm");
3812 rstartEl("draw:text-box", mxList.get());
3813 mxList->clear();
3814 if( hbox->cap_pos % 2 ) /* Caption is on the top */
3816 parsePara(hbox->caption.front().get());
3818 padd( "text:style-name", sXML_CDATA, "Standard");
3819 rstartEl("text:p", mxList.get());
3820 mxList->clear();
3822 if( hbox->ishyper )
3824 padd("xlink:type", sXML_CDATA, "simple");
3825 #ifdef _WIN32
3826 if( hbox->follow[4] != 0 )
3827 padd("xlink:href", sXML_CDATA, reinterpret_cast<sal_Unicode const *>(hconv(kstr2hstr(hbox->follow.data() + 4).c_str())));
3828 else
3829 padd("xlink:href", sXML_CDATA, reinterpret_cast<sal_Unicode const *>(hconv(kstr2hstr(hbox->follow.data() + 5).c_str())));
3830 #else
3831 if( hbox->follow[4] != 0 )
3832 padd("xlink:href", sXML_CDATA,
3833 reinterpret_cast<sal_Unicode const *>(hconv(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hbox->follow.data() + 4)).c_str())).c_str())));
3834 else
3835 padd("xlink:href", sXML_CDATA,
3836 reinterpret_cast<sal_Unicode const *>(hconv(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(reinterpret_cast<char *>(hbox->follow.data() + 5)).c_str())).c_str())));
3837 #endif
3838 rstartEl("draw:a", mxList.get());
3839 mxList->clear();
3841 padd("draw:style-name", sXML_CDATA,
3842 ascii(Int2Str(hbox->style.boxnum, "G%d", buf)));
3843 padd("draw:name", sXML_CDATA,
3844 ascii(Int2Str(hbox->style.boxnum, "Image%d", buf)));
3846 if( hbox->style.cap_len <= 0 )
3848 padd("draw:z-index", sXML_CDATA,
3849 ascii(Int2Str(hbox->zorder, "%d", buf)));
3850 switch (hbox->style.anchor_type)
3852 case CHAR_ANCHOR:
3853 padd("text:anchor-type", sXML_CDATA, "as-char");
3854 break;
3855 case PARA_ANCHOR:
3856 padd("text:anchor-type", sXML_CDATA, "paragraph");
3857 break;
3858 case PAGE_ANCHOR:
3859 case PAPER_ANCHOR:
3861 padd("text:anchor-type", sXML_CDATA, "page");
3862 padd("text:anchor-page-number", sXML_CDATA,
3863 ascii(Int2Str(hbox->pgno +1, "%d", buf)));
3864 break;
3867 if (hbox->style.anchor_type != CHAR_ANCHOR)
3869 padd("svg:x", sXML_CDATA,
3870 Double2Str(WTMM( hbox->pgx + hbox->style.margin[0][0] )) + "mm");
3871 padd("svg:y", sXML_CDATA,
3872 Double2Str(WTMM( hbox->pgy + hbox->style.margin[0][2] )) + "mm");
3875 else
3877 padd("text:anchor-type", sXML_CDATA, "as-char");
3878 padd("svg:y", sXML_CDATA, "0cm");
3880 padd("svg:width", sXML_CDATA,
3881 Double2Str(WTMM( hbox->box_xs + hbox->style.margin[1][0] + hbox->style.margin[1][1])) + "mm");
3882 padd("svg:height", sXML_CDATA,
3883 Double2Str(WTMM( hbox->box_ys + hbox->style.margin[1][2] + hbox->style.margin[1][3])) + "mm");
3885 if ( hbox->pictype == PICTYPE_FILE ){
3886 #ifdef _WIN32
3887 sprintf(buf, "file:///%s", hbox->picinfo.picun.path );
3888 padd("xlink:href", sXML_CDATA, reinterpret_cast<sal_Unicode const *>(hconv(kstr2hstr(reinterpret_cast<uchar *>(buf)).c_str())));
3889 #else
3890 padd("xlink:href", sXML_CDATA,
3891 reinterpret_cast<sal_Unicode const *>(hconv(kstr2hstr(reinterpret_cast<uchar const *>(urltounix(hbox->picinfo.picun.path).c_str())).c_str())));
3892 #endif
3893 padd("xlink:type", sXML_CDATA, "simple");
3894 padd("xlink:show", sXML_CDATA, "embed");
3895 padd("xlink:actuate", sXML_CDATA, "onLoad");
3898 if( hbox->pictype == PICTYPE_OLE )
3899 rstartEl("draw:object-ole", mxList.get());
3900 else
3901 rstartEl("draw:image", mxList.get());
3902 mxList->clear();
3903 if (hbox->pictype == PICTYPE_EMBED || hbox->pictype == PICTYPE_OLE)
3905 rstartEl("office:binary-data", mxList.get());
3906 mxList->clear();
3907 if( hbox->pictype == PICTYPE_EMBED ){
3908 EmPicture *emp = hwpfile.GetEmPicture(hbox);
3909 if( emp )
3911 std::shared_ptr<char> pStr(base64_encode_string( emp->data.get(), emp->size ), Free<char>());
3912 rchars(ascii(pStr.get()));
3915 else{
3916 if( hwpfile.oledata ){
3917 #ifdef _WIN32
3918 LPSTORAGE srcsto;
3919 LPUNKNOWN pObj;
3920 wchar_t pathname[200];
3922 MultiByteToWideChar(CP_ACP, 0, hbox->picinfo.picole.embname, -1, pathname, 200);
3923 int rc = hwpfile.oledata->pis->OpenStorage(pathname, nullptr,
3924 STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_TRANSACTED, nullptr, 0, &srcsto);
3925 if (rc != S_OK) {
3926 rchars("");
3928 else{
3929 rc = OleLoad(srcsto, IID_IUnknown, nullptr, reinterpret_cast<LPVOID*>(&pObj));
3930 if( rc != S_OK ){
3931 srcsto->Release();
3932 rchars("");
3934 else{
3935 std::shared_ptr<char> pStr(base64_encode_string( reinterpret_cast<uchar *>(pObj), strlen(reinterpret_cast<char *>(pObj))), Free<char>());
3936 rchars(ascii(pStr.get()));
3937 pObj->Release();
3938 srcsto->Release();
3941 #else
3942 rchars("");
3943 #endif
3946 rendEl("office:binary-data");
3948 if( hbox->pictype == PICTYPE_OLE )
3949 rendEl("draw:object-ole");
3950 else
3951 rendEl("draw:image");
3952 if( hbox->ishyper )
3954 rendEl("draw:a");
3956 if( hbox->style.cap_len > 0 )
3958 rendEl( "text:p");
3959 if( !(hbox->cap_pos % 2)) /* Caption is at the bottom, */
3961 parsePara(hbox->caption.front().get());
3963 rendEl( "draw:text-box");
3965 break;
3967 case PICTYPE_DRAW:
3968 if( hbox->picinfo.picdraw.zorder > 0 )
3969 padd("draw:z-index", sXML_CDATA,
3970 ascii(Int2Str( hbox->picinfo.picdraw.zorder + 10000, "%d", buf)));
3971 makePictureDRAW(hbox->picinfo.picdraw.hdo, hbox);
3972 break;
3973 case PICTYPE_UNKNOWN:
3974 break;
3979 #define DBL(x) ((x) * (x))
3980 void HwpReader::makePictureDRAW(HWPDrawingObject *drawobj, Picture * hbox)
3982 int x = hbox->pgx;
3983 int y = hbox->pgy;
3984 bool bIsRotate = false;
3986 while (drawobj)
3988 padd("draw:style-name", sXML_CDATA,
3989 ascii(Int2Str(drawobj->index, "Draw%d", buf)));
3990 int a = 0;
3991 int b = 0;
3993 switch (hbox->style.anchor_type)
3995 case CHAR_ANCHOR:
3996 padd("text:anchor-type", sXML_CDATA, "as-char");
3997 break;
3998 case PARA_ANCHOR:
3999 padd("text:anchor-type", sXML_CDATA, "paragraph");
4000 break;
4001 case PAGE_ANCHOR:
4002 case PAPER_ANCHOR:
4004 HWPInfo& hwpinfo = hwpfile.GetHWPInfo();
4005 padd("text:anchor-type", sXML_CDATA, "page");
4006 padd("text:anchor-page-number", sXML_CDATA,
4007 ascii(Int2Str(hbox->pgno +1, "%d", buf)));
4008 a = hwpinfo.paper.left_margin;
4009 b = hwpinfo.paper.top_margin + hwpinfo.paper.header_length;
4010 break;
4014 if (drawobj->type == HWPDO_CONTAINER)
4016 rstartEl("draw:g", mxList.get());
4017 mxList->clear();
4018 makePictureDRAW(drawobj->child.get(), hbox);
4019 rendEl("draw:g");
4021 else
4023 bIsRotate = false;
4024 if( (drawobj->property.flag & HWPDO_FLAG_ROTATION) &&
4025 (drawobj->property.parall.pt[0].y != drawobj->property.parall.pt[1].y) &&
4026 //(drawobj->type == HWPDO_RECT || drawobj->type == HWPDO_ADVANCED_ELLIPSE || drawobj->type == HWPDO_ADVANCED_ARC )
4027 (drawobj->type == HWPDO_RECT || drawobj->type == HWPDO_ADVANCED_ELLIPSE )
4031 int i;
4032 ZZParall *pal = &drawobj->property.parall;
4034 ZZPoint pt[3], r_pt[3];
4035 for(i = 0 ; i < 3 ; i++ ){
4036 pt[i].x = pal->pt[i].x - drawobj->property.rot_originx;
4037 /* Convert to a physical coordinate */
4038 pt[i].y = -(pal->pt[i].y - drawobj->property.rot_originy);
4041 double rotate, skewX ;
4043 /* 2 - rotation angle calculation */
4044 if( pt[1].x == pt[0].x ){
4045 if( pt[1].y > pt[0].y )
4046 rotate = PI/2;
4047 else
4048 rotate = -(PI/2);
4050 else
4051 rotate = atan(static_cast<double>( pt[1].y - pt[0].y )/(pt[1].x - pt[0].x ));
4052 if( pt[1].x < pt[0].x )
4053 rotate += PI;
4055 for( i = 0 ; i < 3 ; i++){
4056 r_pt[i].x = static_cast<int>(pt[i].x * cos(-rotate) - pt[i].y * sin(-rotate));
4057 r_pt[i].y = static_cast<int>(pt[i].y * cos(-rotate) + pt[i].x * sin(-rotate));
4060 /* 4 - Calculation of reflex angle */
4061 if( r_pt[2].y == r_pt[1].y )
4062 skewX = 0;
4063 else
4064 skewX = atan(static_cast<double>(r_pt[2].x - r_pt[1].x )/( r_pt[2].y - r_pt[1].y ));
4065 if( skewX >= PI/2 )
4066 skewX -= PI;
4067 if( skewX <= -PI/2 )
4068 skewX += PI;
4070 OUString trans;
4071 if( skewX != 0.0 && rotate != 0.0 ){
4072 trans = "skewX (" + Double2Str(skewX)
4073 + ") rotate (" + Double2Str(rotate)
4074 + ") translate (" + Double2Str(WTMM(x + a + drawobj->offset2.x + pal->pt[0].x)) + "mm "
4075 + Double2Str(WTMM(y + b + drawobj->offset2.y + pal->pt[0].y)) + "mm)";
4076 bIsRotate = true;
4078 else if( skewX != 0.0 ){
4079 trans = "skewX (" + Double2Str(skewX)
4080 + ") translate (" + Double2Str(WTMM(x + a + drawobj->offset2.x + pal->pt[0].x)) + "mm "
4081 + Double2Str(WTMM(y + b + drawobj->offset2.y + pal->pt[0].y)) + "mm)";
4082 bIsRotate = true;
4084 else if( rotate != 0.0 ){
4085 trans = "rotate (" + Double2Str(rotate)
4086 + ") translate (" + Double2Str(WTMM(x + a + drawobj->offset2.x + pal->pt[0].x)) + "mm "
4087 + Double2Str(WTMM(y + b + drawobj->offset2.y + pal->pt[0].y)) + "mm)";
4088 bIsRotate = true;
4090 if( bIsRotate ){
4091 drawobj->extent.w = static_cast<int>(sqrt(double(DBL(pt[1].x-pt[0].x)+DBL(pt[1].y-pt[0].y))));
4092 drawobj->extent.h = static_cast<int>(sqrt(double(DBL(pt[2].x-pt[1].x)+DBL(pt[2].y-pt[1].y))));
4093 padd("draw:transform", sXML_CDATA, trans);
4096 switch (drawobj->type)
4098 case HWPDO_LINE: /* Line-starting coordinates, ending coordinates. */
4099 if( drawobj->u.line_arc.flip & 0x01 )
4101 padd("svg:x1", sXML_CDATA,
4102 Double2Str (WTMM(x + a + drawobj->offset2.x + drawobj->extent.w)) + "mm");
4103 padd("svg:x2", sXML_CDATA,
4104 Double2Str (WTMM( x + a + drawobj->offset2.x )) + "mm");
4106 else
4108 padd("svg:x1", sXML_CDATA,
4109 Double2Str (WTMM( x + a + drawobj->offset2.x )) + "mm");
4110 padd("svg:x2", sXML_CDATA,
4111 Double2Str (WTMM(x + a + drawobj->offset2.x + drawobj->extent.w)) + "mm");
4113 if( drawobj->u.line_arc.flip & 0x02 )
4115 padd("svg:y1", sXML_CDATA,
4116 Double2Str (WTMM( y + b + drawobj->offset2.y + drawobj->extent.h ) ) + "mm");
4117 padd("svg:y2", sXML_CDATA,
4118 Double2Str (WTMM( y + b + drawobj->offset2.y )) + "mm");
4120 else
4122 padd("svg:y1", sXML_CDATA,
4123 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4124 padd("svg:y2", sXML_CDATA,
4125 Double2Str (WTMM(y + b + drawobj->offset2.y + drawobj->extent.h)) + "mm");
4128 rstartEl("draw:line", mxList.get());
4129 mxList->clear();
4130 rendEl("draw:line");
4131 break;
4132 case HWPDO_RECT: /* rectangle - the starting position, vertical/horizontal */
4133 if( !bIsRotate )
4135 padd("svg:x", sXML_CDATA,
4136 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4137 padd("svg:y", sXML_CDATA,
4138 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4140 padd("svg:width", sXML_CDATA,
4141 Double2Str (WTMM( drawobj->extent.w )) + "mm");
4142 padd("svg:height", sXML_CDATA,
4143 Double2Str (WTMM( drawobj->extent.h )) + "mm");
4144 if( drawobj->property.flag & 0x01 )
4146 int value = drawobj->extent.w < drawobj->extent.h ?
4147 drawobj->extent.w : drawobj->extent.h ;
4148 padd("draw:corner-radius", sXML_CDATA,
4149 Double2Str (WTMM( value/10 )) + "mm");
4151 else if( drawobj->property.flag & 0x04 )
4153 int value = drawobj->extent.w < drawobj->extent.h ?
4154 drawobj->extent.w : drawobj->extent.h ;
4155 padd("draw:corner-radius", sXML_CDATA,
4156 Double2Str (WTMM( value / 2)) + "mm");
4159 rstartEl("draw:rect", mxList.get());
4160 mxList->clear();
4161 if( (drawobj->property.flag & HWPDO_FLAG_AS_TEXTBOX) &&
4162 drawobj->property.pPara ) // As Textbox
4164 HWPPara *pPara = drawobj->property.pPara;
4165 //parsePara(pPara);
4166 while(pPara)
4168 make_text_p1( pPara, false );
4169 pPara = pPara->Next();
4172 rendEl("draw:rect");
4173 break;
4174 case HWPDO_ELLIPSE: /* Ellipse - the starting position, vertical/horizontal */
4175 case HWPDO_ADVANCED_ELLIPSE: /* modified ellipse */
4177 if( !bIsRotate )
4179 padd("svg:x", sXML_CDATA,
4180 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4181 padd("svg:y", sXML_CDATA,
4182 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4185 padd("svg:width", sXML_CDATA,
4186 Double2Str (WTMM( drawobj->extent.w )) + "mm");
4187 padd("svg:height", sXML_CDATA,
4188 Double2Str (WTMM( drawobj->extent.h )) + "mm");
4189 if( drawobj->type == HWPDO_ADVANCED_ELLIPSE ){
4190 if( drawobj->u.arc.radial[0].x != drawobj->u.arc.radial[1].x
4191 || drawobj->u.arc.radial[0].y != drawobj->u.arc.radial[1].y ){
4192 int Cx,Cy;
4193 Cx = ( drawobj->offset2.x + drawobj->extent.w ) / 2;
4194 Cy = ( drawobj->offset2.y + drawobj->extent.h ) / 2;
4196 double start_angle, end_angle;
4197 start_angle = calcAngle( Cx, Cy, drawobj->u.arc.radial[0].x, drawobj->u.arc.radial[0].y );
4198 end_angle = calcAngle( Cx, Cy, drawobj->u.arc.radial[1].x, drawobj->u.arc.radial[1].y );
4199 if( drawobj->property.fill_color < 0xffffff )
4200 padd("draw:kind", sXML_CDATA, "section");
4201 else
4202 padd("draw:kind", sXML_CDATA, "arc");
4203 padd("draw:start-angle", sXML_CDATA, Double2Str(start_angle ));
4204 padd("draw:end-angle", sXML_CDATA, Double2Str(end_angle));
4207 rstartEl("draw:ellipse", mxList.get());
4208 mxList->clear();
4209 if( drawobj->property.flag >> 19 & 0x01 &&
4210 drawobj->property.pPara ) // As Textbox
4212 HWPPara *pPara = drawobj->property.pPara;
4213 //parsePara(pPara);
4214 while(pPara)
4216 make_text_p1( pPara, false );
4217 pPara = pPara->Next();
4220 rendEl("draw:ellipse");
4221 break;
4224 case HWPDO_ARC: /* Arc */
4225 case HWPDO_ADVANCED_ARC:
4227 /* If it is the arc, LibreOffice assumes the size as the entire ellipse size */
4228 uint flip = drawobj->u.line_arc.flip;
4229 if( !bIsRotate )
4231 if( ( flip == 0 || flip == 2 ) && drawobj->type == HWPDO_ARC)
4232 padd("svg:x", sXML_CDATA,
4233 Double2Str (WTMM( x + a + drawobj->offset2.x - drawobj->extent.w)) + "mm");
4234 else
4235 padd("svg:x", sXML_CDATA,
4236 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4237 if( ( flip == 0 || flip == 1 ) && drawobj->type == HWPDO_ARC)
4238 padd("svg:y", sXML_CDATA,
4239 Double2Str (WTMM( y + b + drawobj->offset2.y - drawobj->extent.h)) + "mm");
4240 else
4241 padd("svg:y", sXML_CDATA,
4242 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4245 padd("svg:width", sXML_CDATA,
4246 Double2Str (WTMM( drawobj->extent.w * 2)) + "mm");
4247 padd("svg:height", sXML_CDATA,
4248 Double2Str (WTMM( drawobj->extent.h * 2)) + "mm");
4249 if( drawobj->property.flag & HWPDO_FLAG_DRAW_PIE ||
4250 drawobj->property.fill_color < 0xffffff )
4251 padd("draw:kind", sXML_CDATA, "section");
4252 else
4253 padd("draw:kind", sXML_CDATA, "arc");
4255 if( drawobj->type == HWPDO_ADVANCED_ARC ){
4256 double start_angle, end_angle;
4257 ZZParall *pal = &drawobj->property.parall;
4259 if( pal->pt[1].x == pal->pt[0].x ){
4260 if( pal->pt[0].y < pal->pt[1].y )
4261 start_angle = 1.5 * PI;
4262 else
4263 start_angle = 0.5 * PI;
4265 else{
4266 start_angle = atan(static_cast<double>( pal->pt[0].y - pal->pt[1].y )/( pal->pt[1].x - pal->pt[0].x ));
4267 if( pal->pt[1].x < pal->pt[0].x )
4268 start_angle += PI;
4270 if( pal->pt[1].x == pal->pt[2].x ){
4271 if( pal->pt[2].y < pal->pt[1].y )
4272 end_angle = 1.5 * PI;
4273 else
4274 end_angle = 0.5 * PI;
4276 else{
4277 end_angle = atan(static_cast<double>( pal->pt[2].y - pal->pt[1].y )/( pal->pt[1].x - pal->pt[2].x ));
4278 if( pal->pt[1].x < pal->pt[2].x )
4279 end_angle += PI;
4282 if( start_angle >= 2 * PI )
4283 start_angle -= 2 * PI;
4284 if( end_angle >= 2 * PI )
4285 end_angle -= 2 * PI;
4286 if( ( start_angle > end_angle ) && (start_angle - end_angle < PI )){
4287 double tmp_angle = start_angle;
4288 start_angle = end_angle;
4289 end_angle = tmp_angle;
4291 padd("draw:start-angle", sXML_CDATA, Double2Str(start_angle * 180. / PI));
4292 padd("draw:end-angle", sXML_CDATA, Double2Str(end_angle * 180. / PI));
4295 else{
4296 if( drawobj->u.line_arc.flip == 0 )
4298 padd("draw:start-angle", sXML_CDATA, "270");
4299 padd("draw:end-angle", sXML_CDATA, "0");
4301 else if( drawobj->u.line_arc.flip == 1 )
4303 padd("draw:start-angle", sXML_CDATA, "180");
4304 padd("draw:end-angle", sXML_CDATA, "270");
4306 else if( drawobj->u.line_arc.flip == 2 )
4308 padd("draw:start-angle", sXML_CDATA, "0");
4309 padd("draw:end-angle", sXML_CDATA, "90");
4311 else
4313 padd("draw:start-angle", sXML_CDATA, "90");
4314 padd("draw:end-angle", sXML_CDATA, "180");
4317 rstartEl("draw:ellipse", mxList.get());
4318 mxList->clear();
4319 if( drawobj->property.flag >> 19 & 0x01 &&
4320 drawobj->property.pPara ) // As Textbox
4322 HWPPara *pPara = drawobj->property.pPara;
4323 //parsePara(pPara);
4324 while(pPara)
4326 make_text_p1( pPara, false );
4327 pPara = pPara->Next();
4330 rendEl("draw:ellipse");
4331 break;
4334 case HWPDO_CURVE: /* Curve: converts to polygons. */
4336 bool bIsNatural = true;
4337 if( drawobj->property.flag >> 5 & 0x01){
4338 bIsNatural = false;
4340 if( !bIsRotate )
4342 padd("svg:x", sXML_CDATA,
4343 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4344 padd("svg:y", sXML_CDATA,
4345 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4347 padd("svg:width", sXML_CDATA,
4348 Double2Str (WTMM( drawobj->extent.w )) + "mm");
4349 padd("svg:height", sXML_CDATA,
4350 Double2Str (WTMM( drawobj->extent.h )) + "mm");
4351 sprintf(buf, "0 0 %d %d", WTSM(drawobj->extent.w) , WTSM(drawobj->extent.h) );
4352 padd("svg:viewBox", sXML_CDATA, ascii(buf) );
4354 OUStringBuffer oustr;
4356 if ((drawobj->u.freeform.npt > 2) &&
4357 (static_cast<size_t>(drawobj->u.freeform.npt) <
4358 (::std::numeric_limits<int>::max() / sizeof(double))))
4360 int n, i;
4361 n = drawobj->u.freeform.npt;
4363 std::unique_ptr<double[]> xarr( new double[n+1] );
4364 std::unique_ptr<double[]> yarr( new double[n+1] );
4365 std::unique_ptr<double[]> tarr( new double[n+1] );
4367 std::unique_ptr<double[]> xb;
4368 std::unique_ptr<double[]> yb;
4370 std::unique_ptr<double[]> carr;
4371 std::unique_ptr<double[]> darr;
4374 for( i = 0 ; i < n ; i++ ){
4375 xarr[i] = drawobj->u.freeform.pt[i].x;
4376 yarr[i] = drawobj->u.freeform.pt[i].y;
4377 tarr[i] = i;
4379 xarr[n] = xarr[0];
4380 yarr[n] = yarr[0];
4381 tarr[n] = n;
4383 if( !bIsNatural ){
4384 PeriodicSpline(n, tarr.get(), xarr.get(), xb, carr, darr);
4385 // prevent memory leak
4386 carr.reset();
4387 darr.reset();
4388 PeriodicSpline(n, tarr.get(), yarr.get(), yb, carr, darr);
4390 else{
4391 NaturalSpline(n, tarr.get(), xarr.get(), xb, carr, darr);
4392 // prevent memory leak
4393 carr.reset();
4394 darr.reset();
4395 NaturalSpline(n, tarr.get(), yarr.get(), yb, carr, darr);
4398 sprintf(buf, "M%d %dC%d %d", WTSM(xarr[0]), WTSM(yarr[0]),
4399 WTSM(xarr[0] + xb[0]/3), WTSM(yarr[0] + yb[0]/3) );
4400 oustr.append(ascii(buf));
4402 for( i = 1 ; i < n ; i++ ){
4403 if( i == n -1 ){
4404 sprintf(buf, " %d %d %d %dz",
4405 WTSM(xarr[i] - xb[i]/3), WTSM(yarr[i] - yb[i]/3),
4406 WTSM(xarr[i]), WTSM(yarr[i]) );
4408 else{
4409 sprintf(buf, " %d %d %d %d %d %d",
4410 WTSM(xarr[i] - xb[i]/3), WTSM(yarr[i] - yb[i]/3),
4411 WTSM(xarr[i]), WTSM(yarr[i]),
4412 WTSM(xarr[i] + xb[i]/3), WTSM(yarr[i] + yb[i]/3) );
4415 oustr.append(ascii(buf));
4419 padd("svg:d", sXML_CDATA, oustr.makeStringAndClear());
4421 rstartEl("draw:path", mxList.get());
4422 mxList->clear();
4423 // As Textbox
4424 if( drawobj->property.flag >> 19 & 0x01 && drawobj->property.pPara )
4426 HWPPara *pPara = drawobj->property.pPara;
4427 while(pPara)
4429 make_text_p1( pPara, false );
4430 pPara = pPara->Next();
4433 rendEl("draw:path");
4434 break;
4436 case HWPDO_CLOSED_FREEFORM:
4437 case HWPDO_FREEFORM: /* polygon */
4439 bool bIsPolygon = false;
4441 padd("svg:x", sXML_CDATA,
4442 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4443 padd("svg:y", sXML_CDATA,
4444 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4446 padd("svg:width", sXML_CDATA,
4447 Double2Str (WTMM( drawobj->extent.w )) + "mm");
4448 padd("svg:height", sXML_CDATA,
4449 Double2Str (WTMM( drawobj->extent.h )) + "mm");
4451 sprintf(buf, "0 0 %d %d", WTSM(drawobj->extent.w), WTSM(drawobj->extent.h));
4452 padd("svg:viewBox", sXML_CDATA, ascii(buf) );
4454 OUStringBuffer oustr;
4456 if (drawobj->u.freeform.npt > 0)
4458 sprintf(buf, "%d,%d", WTSM(drawobj->u.freeform.pt[0].x), WTSM(drawobj->u.freeform.pt[0].y));
4459 oustr.append(ascii(buf));
4460 int i;
4461 for (i = 1; i < drawobj->u.freeform.npt ; i++)
4463 sprintf(buf, " %d,%d",
4464 WTSM(drawobj->u.freeform.pt[i].x),
4465 WTSM(drawobj->u.freeform.pt[i].y));
4466 oustr.append(ascii(buf));
4468 if( drawobj->u.freeform.pt[0].x == drawobj->u.freeform.pt[i-1].x &&
4469 drawobj->u.freeform.pt[0].y == drawobj->u.freeform.pt[i-1].y )
4471 bIsPolygon = true;
4474 padd("draw:points", sXML_CDATA, oustr.makeStringAndClear());
4476 if( drawobj->property.fill_color <= 0xffffff ||
4477 drawobj->property.pattern_type != 0)
4479 bIsPolygon = true;
4482 if(bIsPolygon)
4484 rstartEl("draw:polygon", mxList.get());
4485 mxList->clear();
4486 if( drawobj->property.flag >> 19 & 0x01 &&
4487 // As Textbox
4488 drawobj->property.pPara )
4490 HWPPara *pPara = drawobj->property.pPara;
4491 // parsePara(pPara);
4492 while(pPara)
4494 make_text_p1( pPara, false );
4495 pPara = pPara->Next();
4498 rendEl("draw:polygon");
4500 else
4502 rstartEl("draw:polyline", mxList.get());
4503 mxList->clear();
4504 if( drawobj->property.flag >> 19 & 0x01 &&
4505 // As Textbox
4506 drawobj->property.pPara )
4508 HWPPara *pPara = drawobj->property.pPara;
4509 //parsePara(pPara);
4510 while(pPara)
4512 make_text_p1( pPara, false );
4513 pPara = pPara->Next();
4516 rendEl("draw:polyline");
4518 break;
4520 case HWPDO_TEXTBOX:
4521 if( !bIsRotate )
4523 padd("svg:x", sXML_CDATA,
4524 Double2Str (WTMM( x + a + drawobj->offset2.x)) + "mm");
4525 padd("svg:y", sXML_CDATA,
4526 Double2Str (WTMM( y + b + drawobj->offset2.y)) + "mm");
4528 padd("svg:width", sXML_CDATA,
4529 Double2Str (WTMM( drawobj->extent.w )) + "mm");
4530 padd("svg:height", sXML_CDATA,
4531 Double2Str (WTMM( drawobj->extent.h )) + "mm");
4532 if( drawobj->property.flag & 0x01 )
4534 int value = drawobj->extent.w < drawobj->extent.h ?
4535 drawobj->extent.w : drawobj->extent.h ;
4536 padd("draw:corner-radius", sXML_CDATA,
4537 Double2Str (WTMM( value/10 )) + "mm");
4539 else if( drawobj->property.flag & 0x04 )
4541 int value = drawobj->extent.w < drawobj->extent.h ?
4542 drawobj->extent.w : drawobj->extent.h ;
4543 padd("draw:corner-radius", sXML_CDATA,
4544 Double2Str (WTMM( value / 2)) + "mm");
4547 rstartEl("draw:text-box", mxList.get());
4548 mxList->clear();
4550 HWPPara *pPara = drawobj->u.textbox.h;
4551 //parsePara(pPara);
4552 while(pPara)
4554 make_text_p1( pPara, false );
4555 pPara = pPara->Next();
4558 rendEl("draw:text-box");
4559 break;
4562 mxList->clear();
4563 drawobj = drawobj->next.get();
4568 void HwpReader::makeLine()
4570 padd("text:style-name", sXML_CDATA, "Horizontal Line");
4571 rstartEl( "text:p", mxList.get());
4572 mxList->clear();
4577 * Input-comment-hidden description: shows a hidden explanation to the users.
4578 * Parse out only strings, but it may contain paragraphs.
4580 void HwpReader::makeHidden(Hidden * hbox)
4582 hchar_string str;
4583 int res;
4584 hchar dest[3];
4586 padd("text:condition", sXML_CDATA, "");
4587 padd("text:string-value", sXML_CDATA, "");
4588 rstartEl("text:hidden-text", mxList.get());
4589 mxList->clear();
4590 HWPPara *para = hbox->plist.front().get();
4592 while (para)
4594 for (int n = 0; n < para->nch && para->hhstr[n]->hh;
4595 n += para->hhstr[n]->WSize())
4597 res = hcharconv(para->hhstr[n]->hh, dest, UNICODE);
4598 for( int j = 0 ; j < res ; j++ )
4600 str.push_back(dest[j]);
4603 para = para->Next();
4605 makeChars(str);
4606 rendEl("text:hidden-text");
4611 * Converts footnote to text:footnote, endnote to text:endnote
4613 void HwpReader::makeFootnote(Footnote * hbox)
4615 if (hbox->type)
4617 padd("text:id", sXML_CDATA,
4618 ascii(Int2Str(hbox->number, "edn%d", buf)));
4619 rstartEl("text:endnote", mxList.get());
4620 mxList->clear();
4621 padd("text:label", sXML_CDATA,
4622 ascii(Int2Str(hbox->number, "%d", buf)));
4623 rstartEl("text:endnote-citation", mxList.get());
4624 mxList->clear();
4625 rchars(ascii(Int2Str(hbox->number, "%d", buf)));
4626 rendEl("text:endnote-citation");
4627 rstartEl("text:endnote-body", mxList.get());
4628 parsePara(hbox->plist.front().get());
4629 rendEl("text:endnote-body");
4630 rendEl("text:endnote");
4632 else
4634 padd("text:id", sXML_CDATA,
4635 ascii(Int2Str(hbox->number, "ftn%d", buf)));
4636 rstartEl("text:footnote", mxList.get());
4637 mxList->clear();
4638 padd("text:label", sXML_CDATA,
4639 ascii(Int2Str(hbox->number, "%d", buf)));
4640 rstartEl("text:footnote-citation", mxList.get());
4641 mxList->clear();
4642 rchars(ascii(Int2Str(hbox->number, "%d", buf)));
4643 rendEl("text:footnote-citation");
4644 rstartEl("text:footnote-body", mxList.get());
4645 parsePara(hbox->plist.front().get());
4646 rendEl("text:footnote-body");
4647 rendEl("text:footnote");
4653 * page/footnote/endnote/picture/table/formula number
4655 void HwpReader::makeAutoNum(AutoNum const * hbox)
4657 switch (hbox->type)
4659 case PGNUM_AUTO:
4660 rstartEl("text:page-number", mxList.get());
4661 rchars(ascii(Int2Str(hbox->number, "%d", buf)));
4662 rendEl("text:page-number");
4663 break;
4664 case FNNUM_AUTO:
4665 break;
4666 case ENNUM_AUTO:
4667 break;
4668 case EQUNUM_AUTO:
4669 case PICNUM_AUTO:
4670 padd("text:ref-name",sXML_CDATA,
4671 ascii(Int2Str(hbox->number, "refIllustration%d", buf)));
4672 padd("text:name",sXML_CDATA, "Illustration");
4673 padd("style:num-format",sXML_CDATA, "1");
4674 rstartEl("text:sequence", mxList.get());
4675 rchars(ascii(Int2Str(hbox->number, "%d", buf)));
4676 rendEl("text:sequence");
4677 break;
4678 case TBLNUM_AUTO:
4679 padd("text:ref-name",sXML_CDATA,
4680 ascii(Int2Str(hbox->number, "refTable%d", buf)));
4681 padd("text:name",sXML_CDATA, "Table");
4682 padd("style:num-format",sXML_CDATA, "1");
4683 rstartEl("text:sequence", mxList.get());
4684 rchars(ascii(Int2Str(hbox->number, "%d", buf)));
4685 rendEl("text:sequence");
4686 break;
4691 void HwpReader::makeShowPageNum()
4693 ShowPageNum *hbox = d->pPn;
4694 int nPos = 0;
4695 if( hbox->where == 1 || hbox->where == 4 )
4696 nPos = 1;
4697 else if( hbox->where == 2 || hbox->where == 5 )
4698 nPos = 2;
4699 else if( hbox->where == 3 || hbox->where == 6 )
4700 nPos = 3;
4701 else /* should not exist in this case. */
4703 if( d->nPnPos == 1 )
4704 nPos = 1;
4705 else if( d->nPnPos == 3 )
4706 nPos = 3;
4709 padd("draw:style-name", sXML_CDATA,
4710 ascii(Int2Str(nPos, "PNBox%d", buf)));
4711 padd("draw:name", sXML_CDATA,
4712 ascii(Int2Str(nPos, "PageNumber%d", buf)));
4713 padd("text:anchor-type", sXML_CDATA, "paragraph");
4714 padd("svg:y", sXML_CDATA, "0cm");
4715 padd("svg:width", sXML_CDATA, "2.0cm");
4716 padd("fo:min-height", sXML_CDATA, "0.5cm");
4717 rstartEl("draw:text-box", mxList.get());
4718 mxList->clear();
4720 padd("text:style-name", sXML_CDATA,
4721 ascii(Int2Str(nPos, "PNPara%d", buf)));
4722 rstartEl("text:p", mxList.get());
4723 mxList->clear();
4724 if( hbox->shape > 2 )
4725 rchars("- ");
4726 if( hbox->shape % 3 == 0 )
4727 padd("style:num-format", sXML_CDATA, "1");
4728 else if( hbox->shape % 3 == 1 )
4729 padd("style:num-format", sXML_CDATA, "I");
4730 else
4731 padd("style:num-format", sXML_CDATA, "i");
4732 padd("text:select-page", sXML_CDATA, "current");
4733 rstartEl("text:page-number", mxList.get());
4734 mxList->clear();
4735 rchars("2");
4736 rendEl("text:page-number");
4737 if( hbox->shape > 2 )
4738 rchars(" -");
4739 rendEl("text:p");
4740 rendEl("draw:text-box");
4745 * mail merge operation using hwp addressbook and hwp data form.
4746 * not support operation in OO writer.
4748 void HwpReader::makeMailMerge(MailMerge *)
4750 hchar_string const boxstr = MailMerge::GetString();
4751 rchars(reinterpret_cast<sal_Unicode const *>(hconv(boxstr.c_str())));
4755 void HwpReader::makeOutline(Outline const * hbox)
4757 if( hbox->kind == 1 )
4758 rchars( reinterpret_cast<sal_Unicode const *>(hbox->GetUnicode().c_str()) );
4762 void HwpReader::parsePara(HWPPara * para)
4764 bool bParaStart = false;
4765 while (para)
4767 if( para->nch == 1)
4769 if( !bParaStart )
4771 padd("text:style-name", sXML_CDATA,
4772 ascii(getPStyleName(para->GetParaShape().index, buf)));
4773 rstartEl( "text:p",mxList.get());
4774 mxList->clear();
4776 if( d->bFirstPara && d->bInBody )
4778 /* for HWP's Bookmark */
4779 strcpy(
4780 buf,
4781 "[\xEB\xAC\xB8\xEC\x84\x9C\xEC\x9D\x98"
4782 " \xEC\xB2\x98\xEC\x9D\x8C]");
4783 // U+BB38 HANGUL SYLLABLE MUN, U+C11C HANGUL SYLLABLE SEO,
4784 // U+C758 HANGUL SYLLABLE YI, U+CC98 HANGUL SYLLABLE CEO,
4785 // U+C74C HANGUL SYLLABLE EUM: "Begin of Document"
4786 padd("text:name", sXML_CDATA, OUString(buf, strlen(buf), RTL_TEXTENCODING_UTF8));
4787 rstartEl("text:bookmark", mxList.get());
4788 mxList->clear();
4789 rendEl("text:bookmark");
4790 d->bFirstPara = false;
4792 if( d->bInHeader )
4794 makeShowPageNum();
4795 d->bInHeader = false;
4798 rendEl( "text:p" );
4800 else
4802 if (!para->ctrlflag)
4804 if (para->contain_cshape)
4805 make_text_p1(para, bParaStart);
4806 else
4807 make_text_p0(para, bParaStart);
4809 else
4810 make_text_p3(para, bParaStart);
4812 bParaStart = false;
4813 para = para->Next();
4817 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */