1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <sal/config.h>
21
22 #include <string_view>
23
24 #include <hintids.hxx>
25 #include <comphelper/string.hxx>
26 #include <vcl/svapp.hxx>
27 #include <svl/whiter.hxx>
28 #include <editeng/boxitem.hxx>
29 #include <editeng/ulspitem.hxx>
30 #include <editeng/udlnitem.hxx>
31 #include <editeng/crossedoutitem.hxx>
32 #include <editeng/blinkitem.hxx>
33 #include <editeng/cmapitem.hxx>
34 #include <editeng/colritem.hxx>
35 #include <editeng/fontitem.hxx>
36 #include <editeng/fhgtitem.hxx>
37 #include <editeng/postitem.hxx>
38 #include <editeng/kernitem.hxx>
39 #include <editeng/wghtitem.hxx>
40 #include <editeng/lspcitem.hxx>
41 #include <editeng/adjustitem.hxx>
42 #include <editeng/lrspitem.hxx>
43 #include <editeng/brushitem.hxx>
44 #include <editeng/formatbreakitem.hxx>
45 #include <editeng/keepitem.hxx>
46 #include <editeng/widwitem.hxx>
47 #include <editeng/spltitem.hxx>
48 #include <editeng/orphitem.hxx>
49 #include <editeng/charhiddenitem.hxx>
50 #include <svx/xoutbmp.hxx>
51 #include <svx/svdobj.hxx>
52 #include <editeng/langitem.hxx>
53 #include <editeng/frmdiritem.hxx>
54 #include <svtools/htmlout.hxx>
55 #include <svtools/htmlkywd.hxx>
56 #include <svl/urihelper.hxx>
57 #include <unotools/charclass.hxx>
58 #include <i18nlangtag/languagetag.hxx>
59 #include <charfmt.hxx>
60 #include <fmtclds.hxx>
61 #include <fmtcol.hxx>
62 #include <fmtfsize.hxx>
63 #include <fmtornt.hxx>
64 #include <fmtpdsc.hxx>
65 #include <fmtlsplt.hxx>
66 #include <pagedesc.hxx>
67 #include <fmtanchr.hxx>
68 #include <docary.hxx>
69 #include <pam.hxx>
70 #include <viewsh.hxx>
71 #include <viewopt.hxx>
72 #include <swtable.hxx>
73 // NOTES
74 #include <ftninfo.hxx>
75 #include <ftnidx.hxx>
76 #include <txtftn.hxx>
77 #include <fmtftn.hxx>
78 // FOOTNOTES
79 #include <doc.hxx>
80 #include <IDocumentSettingAccess.hxx>
81 #include <IDocumentLayoutAccess.hxx>
82 #include <swerror.h>
83 #include <paratr.hxx>
84 #include <frmatr.hxx>
85 #include <poolfmt.hxx>
86 #include "css1kywd.hxx"
87 #include "wrthtml.hxx"
88 #include "htmlnum.hxx"
89 #include "css1atr.hxx"
90
91 #include <IDocumentStylePoolAccess.hxx>
92 #include <numrule.hxx>
93 #include <o3tl/typed_flags_set.hxx>
94 #include <o3tl/unit_conversion.hxx>
95
96 #include <rtl/strbuf.hxx>
97 #include <osl/diagnose.h>
98
99 using namespace css;
100 using editeng::SvxBorderLine;
101
102 #define HTML_HEADSPACE (12*20)
103
104 namespace {
105
106 enum class Css1Background {
107 Attr = 1,
108 Page = 2,
109 Table = 3,
110 Fly = 4,
111 Section = 5
112 };
113
114 enum class Css1FrameSize {
115 NONE = 0x00,
116 Width = 0x01,
117 MinHeight = 0x02,
118 FixHeight = 0x04,
119 Pixel = 0x10,
120 };
121
122 }
123
124 namespace o3tl {
125 template<> struct typed_flags<Css1FrameSize> : is_typed_flags<Css1FrameSize, 0x17> {};
126 }
127
128 #define DOT_LEADERS_MAX_WIDTH 18
129
130 static Writer& OutCSS1_SwFormat( Writer& rWrt, const SwFormat& rFormat,
131 IDocumentStylePoolAccess /*SwDoc*/ *pDoc, SwDoc *pTemplate );
132 static Writer& OutCSS1_SwPageDesc( Writer& rWrt, const SwPageDesc& rFormat,
133 IDocumentStylePoolAccess /*SwDoc*/ *pDoc, SwDoc *pTemplate,
134 sal_uInt16 nRefPoolId, bool bExtRef,
135 bool bPseudo=true );
136 static Writer& OutCSS1_SwFootnoteInfo( Writer& rWrt, const SwEndNoteInfo& rInfo,
137 SwDoc *pDoc, bool bHasNotes, bool bEndNote );
138 static void OutCSS1_SwFormatDropAttrs( SwHTMLWriter& rHWrt,
139 const SwFormatDrop& rDrop,
140 const SfxItemSet *pCharFormatItemSet=nullptr );
141 static Writer& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( Writer& rWrt,
142 const SvxUnderlineItem *pUItem,
143 const SvxOverlineItem *pOItem,
144 const SvxCrossedOutItem *pCOItem,
145 const SvxBlinkItem *pBItem );
146 static Writer& OutCSS1_SvxFontWeight( Writer& rWrt, const SfxPoolItem& rHt );
147 static Writer& OutCSS1_SvxPosture( Writer& rWrt, const SfxPoolItem& rHt );
148 static Writer& OutCSS1_SvxULSpace( Writer& rWrt, const SfxPoolItem& rHt );
149 static Writer& OutCSS1_SvxLRSpace( Writer& rWrt, const SfxPoolItem& rHt );
150 static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt,
151 const SvxULSpaceItem *pULSpace,
152 const SvxLRSpaceItem *pLRSpace );
153 static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt,
154 const SfxItemSet& rItemSet );
155 static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt,
156 Css1Background nMode,
157 const OUString *pGraphicName );
158 static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt );
159 static Writer& OutCSS1_SwFormatFrameSize( Writer& rWrt, const SfxPoolItem& rHt,
160 Css1FrameSize nMode );
161 static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt,
162 const SfxItemSet& rItemSet,
163 bool bDeep );
164 static Writer& OutCSS1_SwFormatLayoutSplit( Writer& rWrt, const SfxPoolItem& rHt );
165
166 namespace
167 {
168
169 const char sCSS1_rule_end[] = " }";
170 const char sCSS1_span_tag_end[] = "\">";
171 const char cCSS1_style_opt_end = '\"';
172
173 const char* const sHTML_FTN_fontheight = "57%";
174
lclConvToHex(sal_uInt16 nHex)175 OString lclConvToHex(sal_uInt16 nHex)
176 {
177 char aNToABuf[] = "00";
178
179 // set pointer to end of buffer
180 char *pStr = aNToABuf + (sizeof(aNToABuf)-1);
181 for( sal_uInt8 n = 0; n < 2; ++n )
182 {
183 *(--pStr) = static_cast<char>(nHex & 0xf ) + 48;
184 if( *pStr > '9' )
185 *pStr += 39;
186 nHex >>= 4;
187 }
188
189 return OString(aNToABuf, 2);
190 }
191 }
192
IgnorePropertyForReqIF(bool bReqIF,std::string_view rProperty,std::string_view rValue)193 bool IgnorePropertyForReqIF(bool bReqIF, std::string_view rProperty, std::string_view rValue)
194 {
195 if (!bReqIF)
196 return false;
197
198 // Only allow these two keys, nothing else in ReqIF mode.
199 if (rProperty == sCSS1_P_text_decoration)
200 {
201 // Deny other text-decoration values (e.g. "none").
202 if (rValue == "underline" || rValue == "line-through")
203 {
204 return false;
205 }
206
207 return true;
208 }
209
210 if (rProperty == sCSS1_P_color)
211 return false;
212
213 return true;
214 }
215
GetCSS1_Color(const Color & rColor)216 OString GetCSS1_Color(const Color& rColor)
217 {
218 return "#" + lclConvToHex(rColor.GetRed()) + lclConvToHex(rColor.GetGreen()) + lclConvToHex(rColor.GetBlue());
219 }
220
221 namespace {
222
223 class SwCSS1OutMode
224 {
225 SwHTMLWriter& rWrt;
226 sal_uInt16 nOldMode;
227
228 public:
229
SwCSS1OutMode(SwHTMLWriter & rHWrt,sal_uInt16 nMode,const OUString * pSelector)230 SwCSS1OutMode( SwHTMLWriter& rHWrt, sal_uInt16 nMode,
231 const OUString *pSelector ) :
232 rWrt( rHWrt ),
233 nOldMode( rHWrt.m_nCSS1OutMode )
234 {
235 rWrt.m_nCSS1OutMode = nMode;
236 rWrt.m_bFirstCSS1Property = true;
237 if( pSelector )
238 rWrt.m_aCSS1Selector = *pSelector;
239 }
240
~SwCSS1OutMode()241 ~SwCSS1OutMode()
242 {
243 rWrt.m_nCSS1OutMode = nOldMode;
244 }
245 };
246
247 }
248
OutCSS1_Property(const char * pProp,std::string_view sVal,const OUString * pSVal)249 void SwHTMLWriter::OutCSS1_Property( const char *pProp,
250 std::string_view sVal,
251 const OUString *pSVal )
252 {
253 if (IgnorePropertyForReqIF(mbReqIF, pProp, sVal))
254 return;
255
256 OStringBuffer sOut;
257
258 if( m_bFirstCSS1Rule && (m_nCSS1OutMode & CSS1_OUTMODE_RULE_ON)!=0 )
259 {
260 m_bFirstCSS1Rule = false;
261 OutNewLine();
262 sOut.append("<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_style " "
263 OOO_STRING_SVTOOLS_HTML_O_type "=\"text/css\">");
264 // Optional CSS2 code for dot leaders (dotted line between the Table of Contents titles and page numbers):
265 // (More information: http://www.w3.org/Style/Examples/007/leaders.en.html)
266 //
267 // p.leaders {
268 // /* FIXME:
269 // (1) dots line up vertically only in the paragraphs with the same alignment/level
270 // (2) max-width = 18 cm instead of 80em; possible improvement with the new CSS3 calc() */
271 // max-width: 18cm; /* note: need to overwrite max-width with max-width - border-left_of_the_actual_paragraph */
272 // padding: 0;
273 // overflow-x: hidden;
274 // line-height: 120%; /* note: avoid HTML scrollbars and missing descenders of the letters */
275 // }
276 // p.leaders:after {
277 // float: left;
278 // width: 0;
279 // white-space: nowrap;
280 // content: ". . . . . . . . . . . . . . . . . . ...";
281 // }
282 // p.leaders span:first-child {
283 // padding-right: 0.33em;
284 // background: white;
285 // }
286 // p.leaders span + span {
287 // float: right;
288 // padding-left: 0.33em;
289 // background: white;
290 // position: relative;
291 // z-index: 1
292 // }
293
294 if (m_bCfgPrintLayout) {
295 sOut.append(
296 "p." sCSS2_P_CLASS_leaders "{max-width:" + OString::number(DOT_LEADERS_MAX_WIDTH) +
297 "cm;padding:0;overflow-x:hidden;line-height:120%}"
298 "p." sCSS2_P_CLASS_leaders ":after{float:left;width:0;white-space:nowrap;content:\"");
299 for (int i = 0; i < 100; i++ )
300 sOut.append(". ");
301 sOut.append(
302 "\"}p." sCSS2_P_CLASS_leaders " span:first-child{padding-right:0.33em;background:white}"
303 "p." sCSS2_P_CLASS_leaders " span+span{float:right;padding-left:0.33em;"
304 "background:white;position:relative;z-index:1}");
305 }
306 Strm().WriteOString( sOut.makeStringAndClear() );
307
308 IncIndentLevel();
309 }
310
311 if( m_bFirstCSS1Property )
312 {
313 switch( m_nCSS1OutMode & CSS1_OUTMODE_ANY_ON )
314 {
315 case CSS1_OUTMODE_SPAN_TAG_ON:
316 case CSS1_OUTMODE_SPAN_TAG1_ON:
317 if( m_bTagOn )
318 {
319 sOut.append("<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_span
320 " " OOO_STRING_SVTOOLS_HTML_O_style "=\"");
321 }
322 else
323 {
324 HTMLOutFuncs::Out_AsciiTag( Strm(), OString(GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false );
325 return;
326 }
327 break;
328
329 case CSS1_OUTMODE_RULE_ON:
330 {
331 OutNewLine();
332 sOut.append(OUStringToOString(m_aCSS1Selector, m_eDestEnc) + " { ");
333 }
334 break;
335
336 case CSS1_OUTMODE_STYLE_OPT_ON:
337 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_style "=\"");
338 break;
339 }
340 m_bFirstCSS1Property = false;
341 }
342 else
343 {
344 sOut.append("; ");
345 }
346
347 sOut.append(pProp + OString::Concat(": "));
348 if( m_nCSS1OutMode & CSS1_OUTMODE_ENCODE )
349 {
350 // for STYLE-Option encode string
351 Strm().WriteOString( sOut.makeStringAndClear() );
352 if( !sVal.empty() )
353 HTMLOutFuncs::Out_String( Strm(), OUString::createFromAscii(sVal),
354 m_eDestEnc, &m_aNonConvertableCharacters );
355 else if( pSVal )
356 HTMLOutFuncs::Out_String( Strm(), *pSVal, m_eDestEnc, &m_aNonConvertableCharacters );
357 }
358 else
359 {
360 // for STYLE-Tag print string directly
361 if( !sVal.empty() )
362 sOut.append(sVal);
363 else if( pSVal )
364 sOut.append(OUStringToOString(*pSVal, m_eDestEnc));
365 }
366
367 if (!sOut.isEmpty())
368 Strm().WriteOString( sOut.makeStringAndClear() );
369 }
370
AddUnitPropertyValue(OStringBuffer & rOut,tools::Long nVal,FieldUnit eUnit)371 static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal,
372 FieldUnit eUnit)
373 {
374 if( nVal < 0 )
375 {
376 // special-case sign symbol
377 nVal = -nVal;
378 rOut.append('-');
379 }
380
381 o3tl::Length eTo;
382 int nFac; // used to get specific number of decimals
383 const char *pUnit;
384 switch( eUnit )
385 {
386 case FieldUnit::MM_100TH:
387 OSL_ENSURE( FieldUnit::MM == eUnit, "Measuring unit not supported" );
388 [[fallthrough]];
389 case FieldUnit::MM:
390 eTo = o3tl::Length::mm;
391 nFac = 100;
392 pUnit = sCSS1_UNIT_mm;
393 break;
394
395 case FieldUnit::M:
396 case FieldUnit::KM:
397 OSL_ENSURE( FieldUnit::CM == eUnit, "Measuring unit not supported" );
398 [[fallthrough]];
399 case FieldUnit::CM:
400 eTo = o3tl::Length::cm;
401 nFac = 100;
402 pUnit = sCSS1_UNIT_cm;
403 break;
404
405 case FieldUnit::TWIP:
406 OSL_ENSURE( FieldUnit::POINT == eUnit, "Measuring unit not supported" );
407 [[fallthrough]];
408 case FieldUnit::POINT:
409 eTo = o3tl::Length::pt;
410 nFac = 10;
411 pUnit = sCSS1_UNIT_pt;
412 break;
413
414 case FieldUnit::PICA:
415 eTo = o3tl::Length::pc;
416 nFac = 100;
417 pUnit = sCSS1_UNIT_pc;
418 break;
419
420 case FieldUnit::NONE:
421 case FieldUnit::FOOT:
422 case FieldUnit::MILE:
423 case FieldUnit::CUSTOM:
424 case FieldUnit::PERCENT:
425 case FieldUnit::INCH:
426 default:
427 OSL_ENSURE( FieldUnit::INCH == eUnit, "Measuring unit not supported" );
428 eTo = o3tl::Length::in;
429 nFac = 100;
430 pUnit = sCSS1_UNIT_inch;
431 break;
432 }
433
434 sal_Int64 nResult = o3tl::convert(nVal * nFac, o3tl::Length::twip, eTo);
435 rOut.append(nResult/nFac);
436 if ((nResult % nFac) != 0)
437 {
438 rOut.append('.');
439 while (nFac > 1 && (nResult % nFac) != 0)
440 {
441 nFac /= 10;
442 rOut.append((nResult / nFac) % 10);
443 }
444 }
445
446 rOut.append(pUnit);
447 }
448
OutCSS1_UnitProperty(const char * pProp,tools::Long nVal)449 void SwHTMLWriter::OutCSS1_UnitProperty( const char *pProp, tools::Long nVal )
450 {
451 OStringBuffer sOut;
452 AddUnitPropertyValue(sOut, nVal, m_eCSS1Unit);
453 OutCSS1_PropertyAscii(pProp, sOut.makeStringAndClear());
454 }
455
OutCSS1_PixelProperty(const char * pProp,tools::Long nVal,bool bVert)456 void SwHTMLWriter::OutCSS1_PixelProperty( const char *pProp, tools::Long nVal,
457 bool bVert )
458 {
459 OString sOut(OString::number(ToPixel(nVal,bVert)) + sCSS1_UNIT_px);
460 OutCSS1_PropertyAscii(pProp, sOut);
461 }
462
OutStyleSheet(const SwPageDesc & rPageDesc)463 void SwHTMLWriter::OutStyleSheet( const SwPageDesc& rPageDesc )
464 {
465 m_bFirstCSS1Rule = true;
466
467 // Feature: PrintExt
468 if( IsHTMLMode(HTMLMODE_PRINT_EXT) )
469 {
470 const SwPageDesc *pFirstPageDesc = nullptr;
471 sal_uInt16 nFirstRefPoolId = RES_POOLPAGE_HTML;
472 m_bCSS1IgnoreFirstPageDesc = true;
473
474 // First we try to guess how the document is constructed.
475 // Allowed are only the templates: HTML, 1st page, left page, and right page.
476 // A first page is only exported, if it matches the template "1st page".
477 // Left and right pages are only exported, if their templates are linked.
478 // If other templates are used, only very simple cases are exported.
479 const SwPageDesc *pPageDesc = &rPageDesc;
480 const SwPageDesc *pFollow = rPageDesc.GetFollow();
481 if( RES_POOLPAGE_FIRST == pPageDesc->GetPoolFormatId() &&
482 pFollow != pPageDesc &&
483 !IsPoolUserFormat( pFollow->GetPoolFormatId() ) )
484 {
485 // the document has a first page
486 pFirstPageDesc = pPageDesc;
487 pPageDesc = pFollow;
488 pFollow = pPageDesc->GetFollow();
489 }
490
491 IDocumentStylePoolAccess* pStylePoolAccess = &getIDocumentStylePoolAccess();
492 if( pPageDesc == pFollow )
493 {
494 // The document is one-sided; no matter what page, we do not create a 2-sided doc.
495 // The attribute is exported relative to the HTML page template.
496 OutCSS1_SwPageDesc( *this, *pPageDesc, pStylePoolAccess, m_xTemplate.get(),
497 RES_POOLPAGE_HTML, true, false );
498 nFirstRefPoolId = pFollow->GetPoolFormatId();
499 }
500 else if( (RES_POOLPAGE_LEFT == pPageDesc->GetPoolFormatId() &&
501 RES_POOLPAGE_RIGHT == pFollow->GetPoolFormatId()) ||
502 (RES_POOLPAGE_RIGHT == pPageDesc->GetPoolFormatId() &&
503 RES_POOLPAGE_LEFT == pFollow->GetPoolFormatId()) )
504 {
505 // the document is double-sided
506 OutCSS1_SwPageDesc( *this, *pPageDesc, pStylePoolAccess, m_xTemplate.get(),
507 RES_POOLPAGE_HTML, true );
508 OutCSS1_SwPageDesc( *this, *pFollow, pStylePoolAccess, m_xTemplate.get(),
509 RES_POOLPAGE_HTML, true );
510 nFirstRefPoolId = RES_POOLPAGE_RIGHT;
511 m_bCSS1IgnoreFirstPageDesc = false;
512 }
513 // other cases we miss
514
515 if( pFirstPageDesc )
516 OutCSS1_SwPageDesc( *this, *pFirstPageDesc, pStylePoolAccess, m_xTemplate.get(),
517 nFirstRefPoolId, false );
518 }
519
520 // The text body style has to be exported always (if it is changed compared
521 // to the template), because it is used as reference for any style
522 // that maps to <P>, and that's especially the standard style
523 getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT, false );
524
525 // the Default-TextStyle is not also exported !!
526 // 0-Style is the Default; is never exported !!
527 const size_t nTextFormats = m_pDoc->GetTextFormatColls()->size();
528 for( size_t i = 1; i < nTextFormats; ++i )
529 {
530 const SwTextFormatColl* pColl = (*m_pDoc->GetTextFormatColls())[i];
531 sal_uInt16 nPoolId = pColl->GetPoolFormatId();
532 if( nPoolId == RES_POOLCOLL_TEXT || m_pDoc->IsUsed( *pColl ) )
533 OutCSS1_SwFormat( *this, *pColl, &m_pDoc->getIDocumentStylePoolAccess(), m_xTemplate.get() );
534 }
535
536 // the Default-TextStyle is not also exported !!
537 const size_t nCharFormats = m_pDoc->GetCharFormats()->size();
538 for( size_t i = 1; i < nCharFormats; ++i )
539 {
540 const SwCharFormat *pCFormat = (*m_pDoc->GetCharFormats())[i];
541 sal_uInt16 nPoolId = pCFormat->GetPoolFormatId();
542 if( nPoolId == RES_POOLCHR_INET_NORMAL ||
543 nPoolId == RES_POOLCHR_INET_VISIT ||
544 m_pDoc->IsUsed( *pCFormat ) )
545 OutCSS1_SwFormat( *this, *pCFormat, &m_pDoc->getIDocumentStylePoolAccess(), m_xTemplate.get() );
546 }
547
548 bool bHasEndNotes {false};
549 bool bHasFootNotes {false};
550 const SwFootnoteIdxs& rIdxs = m_pDoc->GetFootnoteIdxs();
551 for( auto pIdx : rIdxs )
552 {
553 if( pIdx->GetFootnote().IsEndNote() )
554 {
555 bHasEndNotes = true;
556 if (bHasFootNotes)
557 break;
558 }
559 else
560 {
561 bHasFootNotes = true;
562 if (bHasEndNotes)
563 break;
564 }
565 }
566 OutCSS1_SwFootnoteInfo( *this, m_pDoc->GetFootnoteInfo(), m_pDoc, bHasFootNotes, false );
567 OutCSS1_SwFootnoteInfo( *this, m_pDoc->GetEndNoteInfo(), m_pDoc, bHasEndNotes, true );
568
569 if( !m_bFirstCSS1Rule )
570 {
571 DecIndentLevel();
572
573 OutNewLine();
574 HTMLOutFuncs::Out_AsciiTag( Strm(), OString(GetNamespace() + OOO_STRING_SVTOOLS_HTML_style), false );
575 }
576 else
577 {
578 m_bFirstCSS1Rule = false;
579 }
580
581 m_nDfltTopMargin = 0;
582 m_nDfltBottomMargin = 0;
583 }
584
585 // if pPseudo is set, Styles-Sheets will be exported;
586 // otherwise we only search for Token and Class for a Format
GetCSS1Selector(const SwFormat * pFormat,OString & rToken,OUString & rClass,sal_uInt16 & rRefPoolId,OUString * pPseudo)587 sal_uInt16 SwHTMLWriter::GetCSS1Selector( const SwFormat *pFormat, OString& rToken,
588 OUString& rClass, sal_uInt16& rRefPoolId,
589 OUString *pPseudo )
590 {
591 sal_uInt16 nDeep = 0;
592 rToken.clear();
593 rClass.clear();
594 rRefPoolId = 0;
595 if( pPseudo )
596 pPseudo->clear();
597
598 bool bChrFormat = RES_CHRFMT==pFormat->Which();
599
600 // search formats above for the nearest standard or HTML-Tag template
601 const SwFormat *pPFormat = pFormat;
602 while( pPFormat && !pPFormat->IsDefault() )
603 {
604 bool bStop = false;
605 sal_uInt16 nPoolId = pPFormat->GetPoolFormatId();
606 if( USER_FMT & nPoolId )
607 {
608 // user templates
609 const OUString& aNm(pPFormat->GetName());
610
611 if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_blockquote)
612 {
613 rRefPoolId = RES_POOLCOLL_HTML_BLOCKQUOTE;
614 rToken = OString(OOO_STRING_SVTOOLS_HTML_blockquote);
615 }
616 else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_citation)
617 {
618 rRefPoolId = RES_POOLCHR_HTML_CITATION;
619 rToken = OString(OOO_STRING_SVTOOLS_HTML_citation);
620 }
621 else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_code)
622 {
623 rRefPoolId = RES_POOLCHR_HTML_CODE;
624 rToken = OString(OOO_STRING_SVTOOLS_HTML_code);
625 }
626 else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_definstance)
627 {
628 rRefPoolId = RES_POOLCHR_HTML_DEFINSTANCE;
629 rToken = OString(OOO_STRING_SVTOOLS_HTML_definstance);
630 }
631 else if (!bChrFormat && (aNm == OOO_STRING_SVTOOLS_HTML_dd ||
632 aNm == OOO_STRING_SVTOOLS_HTML_dt))
633 {
634 sal_uInt16 nDefListLvl = GetDefListLvl(aNm, nPoolId);
635 // Export the templates DD 1/DT 1,
636 // but none of their derived templates,
637 // also not DD 2/DT 2 etc.
638 if (nDefListLvl)
639 {
640 if (pPseudo && (nDeep || (nDefListLvl & 0x0fff) > 1))
641 {
642 bStop = true;
643 }
644 else if (nDefListLvl & HTML_DLCOLL_DD)
645 {
646 rRefPoolId = RES_POOLCOLL_HTML_DD;
647 rToken = OString(OOO_STRING_SVTOOLS_HTML_dd);
648 }
649 else
650 {
651 rRefPoolId = RES_POOLCOLL_HTML_DT;
652 rToken = OString(OOO_STRING_SVTOOLS_HTML_dt);
653 }
654 }
655 }
656 else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_emphasis)
657 {
658 rRefPoolId = RES_POOLCHR_HTML_EMPHASIS;
659 rToken = OString(OOO_STRING_SVTOOLS_HTML_emphasis);
660 }
661 else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_horzrule)
662 {
663 // do not export HR !
664 bStop = (nDeep==0);
665 }
666 else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_keyboard)
667 {
668 rRefPoolId = RES_POOLCHR_HTML_KEYBOARD;
669 rToken = OString(OOO_STRING_SVTOOLS_HTML_keyboard);
670 }
671 else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_listing)
672 {
673 // Export Listings as PRE or PRE-derived template
674 rToken = OString(OOO_STRING_SVTOOLS_HTML_preformtxt);
675 rRefPoolId = RES_POOLCOLL_HTML_PRE;
676 nDeep = CSS1_FMT_CMPREF;
677 }
678 else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_preformtxt)
679 {
680 rRefPoolId = RES_POOLCOLL_HTML_PRE;
681 rToken = OString(OOO_STRING_SVTOOLS_HTML_preformtxt);
682 }
683 else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_sample)
684 {
685 rRefPoolId = RES_POOLCHR_HTML_SAMPLE;
686 rToken = OString(OOO_STRING_SVTOOLS_HTML_sample);
687 }
688 else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_strong)
689 {
690 rRefPoolId = RES_POOLCHR_HTML_STRONG;
691 rToken = OString(OOO_STRING_SVTOOLS_HTML_strong);
692 }
693 else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_teletype)
694 {
695 rRefPoolId = RES_POOLCHR_HTML_TELETYPE;
696 rToken = OString(OOO_STRING_SVTOOLS_HTML_teletype);
697 }
698 else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_variable)
699 {
700 rRefPoolId = RES_POOLCHR_HTML_VARIABLE;
701 rToken = OString(OOO_STRING_SVTOOLS_HTML_variable);
702 }
703 else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_xmp)
704 {
705 // export XMP as PRE (but not the template as Style)
706 rToken = OString(OOO_STRING_SVTOOLS_HTML_preformtxt);
707 rRefPoolId = RES_POOLCOLL_HTML_PRE;
708 nDeep = CSS1_FMT_CMPREF;
709 }
710
711 // if a PoolId is set, the Name of the template is that of the related Token
712 OSL_ENSURE( (rRefPoolId != 0) == (!rToken.isEmpty()),
713 "Token missing" );
714 }
715 else
716 {
717 // Pool templates
718 switch( nPoolId )
719 {
720 // paragraph templates
721 case RES_POOLCOLL_HEADLINE_BASE:
722 case RES_POOLCOLL_STANDARD:
723 // do not export this template
724 bStop = (nDeep==0);
725 break;
726 case RES_POOLCOLL_TEXT:
727 rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak);
728 break;
729 case RES_POOLCOLL_HEADLINE1:
730 rToken = OString(OOO_STRING_SVTOOLS_HTML_head1);
731 break;
732 case RES_POOLCOLL_HEADLINE2:
733 rToken = OString(OOO_STRING_SVTOOLS_HTML_head2);
734 break;
735 case RES_POOLCOLL_HEADLINE3:
736 rToken = OString(OOO_STRING_SVTOOLS_HTML_head3);
737 break;
738 case RES_POOLCOLL_HEADLINE4:
739 rToken = OString(OOO_STRING_SVTOOLS_HTML_head4);
740 break;
741 case RES_POOLCOLL_HEADLINE5:
742 rToken = OString(OOO_STRING_SVTOOLS_HTML_head5);
743 break;
744 case RES_POOLCOLL_HEADLINE6:
745 rToken = OString(OOO_STRING_SVTOOLS_HTML_head6);
746 break;
747 case RES_POOLCOLL_SEND_ADDRESS:
748 rToken = OString(OOO_STRING_SVTOOLS_HTML_address);
749 break;
750 case RES_POOLCOLL_HTML_BLOCKQUOTE:
751 rToken = OString(OOO_STRING_SVTOOLS_HTML_blockquote);
752 break;
753 case RES_POOLCOLL_HTML_PRE:
754 rToken = OString(OOO_STRING_SVTOOLS_HTML_preformtxt);
755 break;
756
757 case RES_POOLCOLL_HTML_DD:
758 rToken = OString(OOO_STRING_SVTOOLS_HTML_dd);
759 break;
760 case RES_POOLCOLL_HTML_DT:
761 rToken = OString(OOO_STRING_SVTOOLS_HTML_dt);
762 break;
763
764 case RES_POOLCOLL_TABLE:
765 if( pPseudo )
766 {
767 rToken = OOO_STRING_SVTOOLS_HTML_tabledata " "
768 OOO_STRING_SVTOOLS_HTML_parabreak;
769 }
770 else
771 rToken = OOO_STRING_SVTOOLS_HTML_parabreak;
772 break;
773 case RES_POOLCOLL_TABLE_HDLN:
774 if( pPseudo )
775 {
776 rToken = OOO_STRING_SVTOOLS_HTML_tableheader " "
777 OOO_STRING_SVTOOLS_HTML_parabreak;
778 }
779 else
780 rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak);
781 break;
782 case RES_POOLCOLL_HTML_HR:
783 // do not export HR !
784 bStop = (nDeep==0);
785 break;
786 case RES_POOLCOLL_FOOTNOTE:
787 if( !nDeep )
788 {
789 rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak);
790 rClass = OOO_STRING_SVTOOLS_HTML_sdfootnote;
791 rRefPoolId = RES_POOLCOLL_TEXT;
792 nDeep = CSS1_FMT_CMPREF;
793 }
794 break;
795 case RES_POOLCOLL_ENDNOTE:
796 if( !nDeep )
797 {
798 rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak);
799 rClass = OOO_STRING_SVTOOLS_HTML_sdendnote;
800 rRefPoolId = RES_POOLCOLL_TEXT;
801 nDeep = CSS1_FMT_CMPREF;
802 }
803 break;
804
805 // character templates
806 case RES_POOLCHR_HTML_EMPHASIS:
807 rToken = OString(OOO_STRING_SVTOOLS_HTML_emphasis);
808 break;
809 case RES_POOLCHR_HTML_CITATION:
810 rToken = OString(OOO_STRING_SVTOOLS_HTML_citation);
811 break;
812 case RES_POOLCHR_HTML_STRONG:
813 rToken = OString(OOO_STRING_SVTOOLS_HTML_strong);
814 break;
815 case RES_POOLCHR_HTML_CODE:
816 rToken = OString(OOO_STRING_SVTOOLS_HTML_code);
817 break;
818 case RES_POOLCHR_HTML_SAMPLE:
819 rToken = OString(OOO_STRING_SVTOOLS_HTML_sample);
820 break;
821 case RES_POOLCHR_HTML_KEYBOARD:
822 rToken = OString(OOO_STRING_SVTOOLS_HTML_keyboard);
823 break;
824 case RES_POOLCHR_HTML_VARIABLE:
825 rToken = OString(OOO_STRING_SVTOOLS_HTML_variable);
826 break;
827 case RES_POOLCHR_HTML_DEFINSTANCE:
828 rToken = OString(OOO_STRING_SVTOOLS_HTML_definstance);
829 break;
830 case RES_POOLCHR_HTML_TELETYPE:
831 rToken = OString(OOO_STRING_SVTOOLS_HTML_teletype);
832 break;
833
834 case RES_POOLCHR_INET_NORMAL:
835 if( pPseudo )
836 {
837 rToken = OString(OOO_STRING_SVTOOLS_HTML_anchor);
838 *pPseudo = OStringToOUString( sCSS1_link, RTL_TEXTENCODING_ASCII_US );
839 }
840 break;
841 case RES_POOLCHR_INET_VISIT:
842 if( pPseudo )
843 {
844 rToken = OString(OOO_STRING_SVTOOLS_HTML_anchor);
845 *pPseudo = OStringToOUString( sCSS1_visited, RTL_TEXTENCODING_ASCII_US );
846 }
847 break;
848 }
849
850 // if a token is set, PoolId contains the related template
851 if( !rToken.isEmpty() && !rRefPoolId )
852 rRefPoolId = nPoolId;
853 }
854
855 if( !rToken.isEmpty() || bStop )
856 {
857 // stop if a HTML-Tag template was found
858 break;
859 }
860 else
861 {
862 // continue otherwise
863 nDeep++;
864 pPFormat = pPFormat->DerivedFrom();
865 }
866 }
867
868 if( !rToken.isEmpty() )
869 {
870 // this is a HTML-Tag template
871 if( !nDeep )
872 nDeep = CSS1_FMT_ISTAG;
873 }
874 else
875 {
876 // this is not a HTML-Tag template nor derived from one
877 nDeep = 0;
878 }
879 if( nDeep > 0 && nDeep < CSS1_FMT_SPECIAL )
880 {
881 // If the template is derived from a HTML template,
882 // we export it as <TOKEN>.<CLASS>, otherwise as .<CLASS>.
883 // <CLASS> is the name of the template after removing all characters
884 // before and including the first '.'
885 rClass = pFormat->GetName();
886 sal_Int32 nPos = rClass.indexOf( '.' );
887 if( nPos >= 0 && rClass.getLength() > nPos+1 )
888 {
889 rClass = rClass.replaceAt( 0, nPos+1, "" );
890 }
891
892 rClass = GetAppCharClass().lowercase( rClass );
893 rClass = rClass.replaceAll( ".", "-" );
894 rClass = rClass.replaceAll( " ", "-" );
895 rClass = rClass.replaceAll( "_", "-" );
896 }
897
898 return nDeep;
899 }
900
GetCSS1Selector(const SwFormat * pFormat,OUString & rSelector,sal_uInt16 & rRefPoolId)901 static sal_uInt16 GetCSS1Selector( const SwFormat *pFormat, OUString& rSelector,
902 sal_uInt16& rRefPoolId )
903 {
904 OString aToken;
905 OUString aClass;
906 OUString aPseudo;
907
908 sal_uInt16 nDeep = SwHTMLWriter::GetCSS1Selector( pFormat, aToken, aClass,
909 rRefPoolId, &aPseudo );
910 if( nDeep )
911 {
912 if( !aToken.isEmpty() )
913 rSelector = OStringToOUString(aToken, RTL_TEXTENCODING_ASCII_US);
914 else
915 rSelector.clear();
916
917 if( !aClass.isEmpty() )
918 rSelector += "." + aClass;
919 if( !aPseudo.isEmpty() )
920 rSelector += ":" + aPseudo;
921 }
922
923 return nDeep;
924 }
925
GetTemplateFormat(sal_uInt16 nPoolFormatId,IDocumentStylePoolAccess * pTemplate)926 const SwFormat *SwHTMLWriter::GetTemplateFormat( sal_uInt16 nPoolFormatId,
927 IDocumentStylePoolAccess* pTemplate /*SwDoc *pTemplate*/)
928 {
929 const SwFormat *pRefFormat = nullptr;
930
931 if( pTemplate )
932 {
933 OSL_ENSURE( !(USER_FMT & nPoolFormatId),
934 "No user templates found" );
935 if( POOLGRP_NOCOLLID & nPoolFormatId )
936 pRefFormat = pTemplate->GetCharFormatFromPool( nPoolFormatId );
937 else
938 pRefFormat = pTemplate->GetTextCollFromPool( nPoolFormatId, false );
939 }
940
941 return pRefFormat;
942 }
943
GetParentFormat(const SwFormat & rFormat,sal_uInt16 nDeep)944 const SwFormat *SwHTMLWriter::GetParentFormat( const SwFormat& rFormat, sal_uInt16 nDeep )
945 {
946 OSL_ENSURE( nDeep != USHRT_MAX, "Called GetParent for HTML-template!" );
947 const SwFormat *pRefFormat = nullptr;
948
949 if( nDeep > 0 )
950 {
951 // get the pointer for the HTML-Tag template, from which the template is derived
952 pRefFormat = &rFormat;
953 for( sal_uInt16 i=nDeep; i>0; i-- )
954 pRefFormat = pRefFormat->DerivedFrom();
955
956 if( pRefFormat && pRefFormat->IsDefault() )
957 pRefFormat = nullptr;
958 }
959
960 return pRefFormat;
961 }
962
swhtml_css1atr_equalFontItems(const SfxPoolItem & r1,const SfxPoolItem & r2)963 bool swhtml_css1atr_equalFontItems( const SfxPoolItem& r1, const SfxPoolItem& r2 )
964 {
965 return static_cast<const SvxFontItem &>(r1).GetFamilyName() ==
966 static_cast<const SvxFontItem &>(r2).GetFamilyName() &&
967 static_cast<const SvxFontItem &>(r1).GetFamily() ==
968 static_cast<const SvxFontItem &>(r2).GetFamily();
969 }
970
SubtractItemSet(SfxItemSet & rItemSet,const SfxItemSet & rRefItemSet,bool bSetDefaults,bool bClearSame,const SfxItemSet * pRefScriptItemSet)971 void SwHTMLWriter::SubtractItemSet( SfxItemSet& rItemSet,
972 const SfxItemSet& rRefItemSet,
973 bool bSetDefaults,
974 bool bClearSame,
975 const SfxItemSet *pRefScriptItemSet )
976 {
977 OSL_ENSURE( bSetDefaults || bClearSame,
978 "SwHTMLWriter::SubtractItemSet: No action for this Flag" );
979 SfxItemSet aRefItemSet( *rRefItemSet.GetPool(), rRefItemSet.GetRanges() );
980 aRefItemSet.Set( rRefItemSet );
981
982 // compare with the Attr-Set of the template
983 SfxWhichIter aIter( rItemSet );
984 sal_uInt16 nWhich = aIter.FirstWhich();
985 while( nWhich )
986 {
987 const SfxPoolItem *pRefItem, *pItem;
988 bool bItemSet = ( SfxItemState::SET ==
989 rItemSet.GetItemState( nWhich, false, &pItem) );
990 bool bRefItemSet;
991
992 if( pRefScriptItemSet )
993 {
994 switch( nWhich )
995 {
996 case RES_CHRATR_FONT:
997 case RES_CHRATR_FONTSIZE:
998 case RES_CHRATR_LANGUAGE:
999 case RES_CHRATR_POSTURE:
1000 case RES_CHRATR_WEIGHT:
1001 case RES_CHRATR_CJK_FONT:
1002 case RES_CHRATR_CJK_FONTSIZE:
1003 case RES_CHRATR_CJK_LANGUAGE:
1004 case RES_CHRATR_CJK_POSTURE:
1005 case RES_CHRATR_CJK_WEIGHT:
1006 case RES_CHRATR_CTL_FONT:
1007 case RES_CHRATR_CTL_FONTSIZE:
1008 case RES_CHRATR_CTL_LANGUAGE:
1009 case RES_CHRATR_CTL_POSTURE:
1010 case RES_CHRATR_CTL_WEIGHT:
1011 bRefItemSet = ( SfxItemState::SET ==
1012 pRefScriptItemSet->GetItemState( nWhich, true, &pRefItem) );
1013 break;
1014 default:
1015 bRefItemSet = ( SfxItemState::SET ==
1016 aRefItemSet.GetItemState( nWhich, false, &pRefItem) );
1017 break;
1018 }
1019 }
1020 else
1021 {
1022 bRefItemSet = ( SfxItemState::SET ==
1023 aRefItemSet.GetItemState( nWhich, false, &pRefItem) );
1024 }
1025
1026 if( bItemSet )
1027 {
1028 if( (bClearSame || pRefScriptItemSet) && bRefItemSet &&
1029 ( *pItem == *pRefItem ||
1030 ((RES_CHRATR_FONT == nWhich ||
1031 RES_CHRATR_CJK_FONT == nWhich ||
1032 RES_CHRATR_CTL_FONT == nWhich) &&
1033 swhtml_css1atr_equalFontItems( *pItem, *pRefItem )) ) )
1034 {
1035 // the Attribute is in both templates with the same value
1036 // and does not need to be exported
1037 rItemSet.ClearItem( nWhich );
1038 }
1039 }
1040 else
1041 {
1042 if( (bSetDefaults || pRefScriptItemSet) && bRefItemSet )
1043 {
1044 // the Attribute exists only in the reference; the default
1045 // might have to be exported
1046 rItemSet.Put( rItemSet.GetPool()->GetDefaultItem(nWhich) );
1047 }
1048 }
1049
1050 nWhich = aIter.NextWhich();
1051 }
1052 }
1053
PrepareFontList(const SvxFontItem & rFontItem,OUString & rNames,sal_Unicode cQuote,bool bGeneric)1054 void SwHTMLWriter::PrepareFontList( const SvxFontItem& rFontItem,
1055 OUString& rNames,
1056 sal_Unicode cQuote, bool bGeneric )
1057 {
1058 rNames.clear();
1059 const OUString& rName = rFontItem.GetFamilyName();
1060 bool bContainsKeyword = false;
1061 if( !rName.isEmpty() )
1062 {
1063 sal_Int32 nStrPos = 0;
1064 while( nStrPos != -1 )
1065 {
1066 OUString aName = rName.getToken( 0, ';', nStrPos );
1067 aName = comphelper::string::strip(aName, ' ');
1068 if( aName.isEmpty() )
1069 continue;
1070
1071 bool bIsKeyword = false;
1072 switch( aName[0] )
1073 {
1074 case 'c':
1075 case 'C':
1076 bIsKeyword = aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_cursive );
1077 break;
1078
1079 case 'f':
1080 case 'F':
1081 bIsKeyword = aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_fantasy );
1082 break;
1083
1084 case 'm':
1085 case 'M':
1086 bIsKeyword = aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_monospace );
1087 break;
1088
1089 case 's':
1090 case 'S':
1091 bIsKeyword =
1092 aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_serif ) ||
1093 aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_sans_serif );
1094 break;
1095 }
1096
1097 bContainsKeyword |= bIsKeyword;
1098
1099 if( !rNames.isEmpty() )
1100 rNames += ", ";
1101 if( cQuote && !bIsKeyword )
1102 rNames += OUStringChar( cQuote );
1103 rNames += aName;
1104 if( cQuote && !bIsKeyword )
1105 rNames += OUStringChar( cQuote );
1106 }
1107 }
1108
1109 if( bContainsKeyword || !bGeneric )
1110 return;
1111
1112 const char *pStr = nullptr;
1113 switch( rFontItem.GetFamily() )
1114 {
1115 case FAMILY_ROMAN: pStr = sCSS1_PV_serif; break;
1116 case FAMILY_SWISS: pStr = sCSS1_PV_sans_serif; break;
1117 case FAMILY_SCRIPT: pStr = sCSS1_PV_cursive; break;
1118 case FAMILY_DECORATIVE: pStr = sCSS1_PV_fantasy; break;
1119 case FAMILY_MODERN: pStr = sCSS1_PV_monospace; break;
1120 default:
1121 ;
1122 }
1123
1124 if( pStr )
1125 {
1126 if( !rNames.isEmpty() )
1127 rNames += ", ";
1128 rNames += OStringToOUString( pStr, RTL_TEXTENCODING_ASCII_US );
1129 }
1130 }
1131
HasScriptDependentItems(const SfxItemSet & rItemSet,bool bCheckDropCap)1132 bool SwHTMLWriter::HasScriptDependentItems( const SfxItemSet& rItemSet,
1133 bool bCheckDropCap )
1134 {
1135 static const sal_uInt16 aWhichIds[] =
1136 {
1137 RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_FONT,
1138 RES_CHRATR_FONTSIZE, RES_CHRATR_CJK_FONTSIZE, RES_CHRATR_CTL_FONTSIZE,
1139 RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
1140 RES_CHRATR_POSTURE, RES_CHRATR_CJK_POSTURE, RES_CHRATR_CTL_POSTURE,
1141 RES_CHRATR_WEIGHT, RES_CHRATR_CJK_WEIGHT, RES_CHRATR_CTL_WEIGHT,
1142 0, 0, 0
1143 };
1144
1145 for( int i=0; aWhichIds[i]; i += 3 )
1146 {
1147 const SfxPoolItem *pItem = nullptr, *pItemCJK = nullptr, *pItemCTL = nullptr, *pTmp;
1148 int nItemCount = 0;
1149 if( SfxItemState::SET == rItemSet.GetItemState( aWhichIds[i], false,
1150 &pTmp ) )
1151 {
1152 pItem = pTmp;
1153 nItemCount++;
1154 }
1155 if( SfxItemState::SET == rItemSet.GetItemState( aWhichIds[i+1], false,
1156 &pTmp ) )
1157 {
1158 pItemCJK = pTmp;
1159 nItemCount++;
1160 }
1161 if( SfxItemState::SET == rItemSet.GetItemState( aWhichIds[i+2], false,
1162 &pTmp ) )
1163 {
1164 pItemCTL = pTmp;
1165 nItemCount++;
1166 }
1167
1168 // If some of the items are set, but not all, we need script dependent
1169 // styles
1170 if( nItemCount > 0 && nItemCount < 3 )
1171 return true;
1172
1173 if( 3 == nItemCount )
1174 {
1175 // If all items are set, but some of them have different values,
1176 // we need script dependent styles, too. For font items, we have
1177 // to take care about their special HTML/CSS1 representation.
1178 if( RES_CHRATR_FONT == aWhichIds[i] )
1179 {
1180 if( !swhtml_css1atr_equalFontItems( *pItem, *pItemCJK ) ||
1181 !swhtml_css1atr_equalFontItems( *pItem, *pItemCTL ) ||
1182 !swhtml_css1atr_equalFontItems( *pItemCJK, *pItemCTL ) )
1183 return true;
1184 }
1185 else
1186 {
1187 if( *pItem != *pItemCJK ||
1188 *pItem != *pItemCTL ||
1189 *pItemCJK != *pItemCTL )
1190 return true;
1191 }
1192 }
1193 }
1194
1195 const SfxPoolItem *pItem;
1196 if( bCheckDropCap &&
1197 SfxItemState::SET == rItemSet.GetItemState( RES_PARATR_DROP, true,
1198 &pItem ) )
1199 {
1200 const SwFormatDrop *pDrop = static_cast<const SwFormatDrop *>(pItem);
1201 const SwCharFormat *pDCCharFormat = pDrop->GetCharFormat();
1202 if( pDCCharFormat )
1203 {
1204 //sequence of (start, end) property ranges we want to
1205 //query
1206 SfxItemSet aTstItemSet(
1207 *pDCCharFormat->GetAttrSet().GetPool(),
1208 svl::Items<
1209 RES_CHRATR_FONT, RES_CHRATR_FONT,
1210 RES_CHRATR_POSTURE, RES_CHRATR_POSTURE,
1211 RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT,
1212 RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT,
1213 RES_CHRATR_CJK_POSTURE, RES_CHRATR_CTL_FONT,
1214 RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT>{});
1215 aTstItemSet.Set( pDCCharFormat->GetAttrSet() );
1216 return HasScriptDependentItems( aTstItemSet, false );
1217 }
1218 }
1219
1220 return false;
1221 }
1222
OutCSS1Rule(SwHTMLWriter & rHTMLWrt,const OUString & rSelector,const SfxItemSet & rItemSet,bool bHasClass,bool bCheckForPseudo)1223 static bool OutCSS1Rule( SwHTMLWriter& rHTMLWrt, const OUString& rSelector,
1224 const SfxItemSet& rItemSet, bool bHasClass,
1225 bool bCheckForPseudo )
1226 {
1227 bool bScriptDependent = false;
1228 if( SwHTMLWriter::HasScriptDependentItems( rItemSet, bHasClass ) )
1229 {
1230 bScriptDependent = true;
1231 OUString aSelector( rSelector );
1232
1233 OUString aPseudo;
1234 if( bCheckForPseudo )
1235 {
1236 sal_Int32 nPos = aSelector.lastIndexOf( ':' );
1237 if( nPos >= 0 )
1238 {
1239 aPseudo = aSelector.copy( nPos );
1240 aSelector =aSelector.copy( 0, nPos );
1241 }
1242 }
1243
1244 if( !bHasClass )
1245 {
1246 // If we are exporting styles for a tag we have to export a tag
1247 // rule for all properties that aren't style dependent and
1248 // some class rule for the additional style dependen properties
1249 {
1250 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_NO_SCRIPT|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1251 &rSelector );
1252 rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1253 }
1254
1255 //sequence of (start, end) property ranges we want to
1256 //query
1257 SfxItemSet aScriptItemSet( *rItemSet.GetPool(),
1258 svl::Items<RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
1259 RES_CHRATR_LANGUAGE, RES_CHRATR_POSTURE,
1260 RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT,
1261 RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_WEIGHT>{} );
1262 aScriptItemSet.Put( rItemSet );
1263
1264 OUString aNewSelector = aSelector + ".western" + aPseudo;
1265 {
1266 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1267 &aNewSelector );
1268 rHTMLWrt.OutCSS1_SfxItemSet( aScriptItemSet, false );
1269 }
1270
1271 aNewSelector = aSelector + ".cjk" + aPseudo;
1272 {
1273 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1274 &aNewSelector );
1275 rHTMLWrt.OutCSS1_SfxItemSet( aScriptItemSet, false );
1276 }
1277
1278 aNewSelector = aSelector + ".ctl" + aPseudo;
1279 {
1280 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1281 &aNewSelector );
1282 rHTMLWrt.OutCSS1_SfxItemSet( aScriptItemSet, false );
1283 }
1284 }
1285 else
1286 {
1287 // If there are script dependencies and we are derived from a tag,
1288 // when we have to export a style dependent class for all
1289 // scripts
1290 OUString aNewSelector = aSelector + "-western" + aPseudo;
1291 {
1292 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1293 &aNewSelector );
1294 rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1295 }
1296
1297 aNewSelector = aSelector + "-cjk" + aPseudo;
1298 {
1299 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1300 &aNewSelector );
1301 rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1302 }
1303
1304 aNewSelector = aSelector + "-ctl" + aPseudo;
1305 {
1306 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1307 &aNewSelector );
1308 rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1309 }
1310 }
1311 }
1312 else
1313 {
1314 // If there are no script dependencies, when all items are
1315 // exported in one step. For hyperlinks only, a script information
1316 // must be there, because these two chr formats don't support
1317 // script dependencies by now.
1318 SwCSS1OutMode aMode( rHTMLWrt,
1319 rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1320 &rSelector );
1321 rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1322 }
1323
1324 return bScriptDependent;
1325 }
1326
OutCSS1DropCapRule(SwHTMLWriter & rHTMLWrt,const OUString & rSelector,const SwFormatDrop & rDrop,bool bHasClass,bool bHasScriptDependencies)1327 static void OutCSS1DropCapRule(
1328 SwHTMLWriter& rHTMLWrt, const OUString& rSelector,
1329 const SwFormatDrop& rDrop, bool bHasClass,
1330 bool bHasScriptDependencies )
1331 {
1332 const SwCharFormat *pDCCharFormat = rDrop.GetCharFormat();
1333 if( (bHasScriptDependencies && bHasClass) ||
1334 (pDCCharFormat && SwHTMLWriter::HasScriptDependentItems( pDCCharFormat->GetAttrSet(), false ) ) )
1335 {
1336 OUString aSelector( rSelector );
1337
1338 OUString aPseudo;
1339 sal_Int32 nPos = aSelector.lastIndexOf( ':' );
1340 if( nPos >= 0 )
1341 {
1342 aPseudo = aSelector.copy( nPos );
1343 aSelector = aSelector.copy( 0, nPos );
1344 }
1345
1346 if( !bHasClass )
1347 {
1348 // If we are exporting styles for a tag we have to export a tag
1349 // rule for all properties that aren't style dependent and
1350 // some class rule for the additional style dependen properties
1351 {
1352 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_NO_SCRIPT|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1353 &rSelector );
1354 OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop );
1355 }
1356
1357 SfxItemSet aScriptItemSet( rHTMLWrt.m_pDoc->GetAttrPool(),
1358 svl::Items<RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
1359 RES_CHRATR_LANGUAGE, RES_CHRATR_POSTURE,
1360 RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT,
1361 RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_WEIGHT>{} );
1362 if( pDCCharFormat )
1363 aScriptItemSet.Set( pDCCharFormat->GetAttrSet() );
1364
1365 OUString aNewSelector = aSelector + ".western" + aPseudo;
1366 {
1367 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1368 &aNewSelector );
1369 OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop, &aScriptItemSet );
1370 }
1371
1372 aNewSelector = aSelector + ".cjk" + aPseudo;
1373 {
1374 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1375 &aNewSelector );
1376 OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop, &aScriptItemSet );
1377 }
1378
1379 aNewSelector = aSelector + ".ctl" + aPseudo;
1380 {
1381 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1382 &aNewSelector );
1383 OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop, &aScriptItemSet );
1384 }
1385 }
1386 else
1387 {
1388 // If there are script dependencies and we are derived from a tag,
1389 // when we have to export a style dependent class for all
1390 // scripts
1391 OUString aNewSelector = aSelector + "-western" + aPseudo;
1392 {
1393 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1394 &aNewSelector );
1395 OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop );
1396 }
1397
1398 aNewSelector = aSelector + "-cjk" + aPseudo;
1399 {
1400 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1401 &aNewSelector );
1402 OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop );
1403 }
1404
1405 aNewSelector = aSelector + "-ctl" + aPseudo;
1406 {
1407 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1408 &aNewSelector );
1409 OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop );
1410 }
1411 }
1412 }
1413 else
1414 {
1415 // If there are no script dependencies, when all items are
1416 // exported in one step. For hyperlinks only, a script information
1417 // must be there, because these two chr formats don't support
1418 // script dependencies by now.
1419 SwCSS1OutMode aMode( rHTMLWrt,
1420 rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1421 &rSelector );
1422 OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop );
1423 }
1424 }
1425
OutCSS1_SwFormat(Writer & rWrt,const SwFormat & rFormat,IDocumentStylePoolAccess * pDoc,SwDoc * pTemplate)1426 static Writer& OutCSS1_SwFormat( Writer& rWrt, const SwFormat& rFormat,
1427 IDocumentStylePoolAccess/*SwDoc*/ *pDoc, SwDoc *pTemplate )
1428 {
1429 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1430
1431 bool bCharFormat = false;
1432 switch( rFormat.Which() )
1433 {
1434 case RES_CHRFMT:
1435 bCharFormat = true;
1436 break;
1437
1438 case RES_TXTFMTCOLL:
1439 case RES_CONDTXTFMTCOLL:
1440 // these template-types can be exported
1441 break;
1442
1443 default:
1444 // but not these
1445 return rWrt;
1446 }
1447
1448 // determine Selector and the to-be-exported Attr-Set-depth
1449 OUString aSelector;
1450 sal_uInt16 nRefPoolId = 0;
1451 sal_uInt16 nDeep = GetCSS1Selector( &rFormat, aSelector, nRefPoolId );
1452 if( !nDeep )
1453 return rWrt; // not derived from a HTML-template
1454
1455 sal_uInt16 nPoolFormatId = rFormat.GetPoolFormatId();
1456
1457 // Determine the to-be-exported Attr-Set. We have to distinguish 3 cases:
1458 // - HTML-Tag templates (nDeep==USHRT_MAX):
1459 // Export Attrs...
1460 // - that are set in the template, but not in the original of the HTML template
1461 // - the Default-Attrs for the Attrs, that are set in the Original of the
1462 // HTML template, but not in the current template.
1463 // - templates directly derived from HTML templates (nDeep==1):
1464 // Export only Attributes of the template Item-Set w/o its parents.
1465 // - templates in-directly derived from HTML templates (nDeep>1):
1466 // Export Attributes of the template Item-Set incl. its Parents,
1467 // but w/o Attributes that are set in the HTML-Tag template.
1468
1469 // create Item-Set with all Attributes from the template
1470 // (all but for nDeep==1)
1471 const SfxItemSet& rFormatItemSet = rFormat.GetAttrSet();
1472 SfxItemSet aItemSet( *rFormatItemSet.GetPool(), rFormatItemSet.GetRanges() );
1473 aItemSet.Set( rFormatItemSet ); // Was nDeep!=1 that is not working
1474 // for script dependent items but should
1475 // not make a difference for any other
1476
1477 bool bSetDefaults = true, bClearSame = true;
1478 const SwFormat *pRefFormat = nullptr;
1479 const SwFormat *pRefFormatScript = nullptr;
1480 switch( nDeep )
1481 {
1482 case CSS1_FMT_ISTAG:
1483 pRefFormat = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pTemplate == nullptr ? nullptr : &pTemplate->getIDocumentStylePoolAccess() );
1484 break;
1485 case CSS1_FMT_CMPREF:
1486 pRefFormat = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pDoc );
1487 pRefFormatScript = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pTemplate == nullptr ? nullptr : &pTemplate->getIDocumentStylePoolAccess() );
1488 bClearSame = false;
1489 break;
1490 default:
1491 pRefFormat = SwHTMLWriter::GetParentFormat( rFormat, nDeep );
1492 pRefFormatScript = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pTemplate == nullptr ? nullptr : &pTemplate->getIDocumentStylePoolAccess() );
1493 bSetDefaults = false;
1494 break;
1495 }
1496
1497 if( pRefFormat )
1498 {
1499 // subtract Item-Set of the Reference template (incl. its Parents)
1500 SwHTMLWriter::SubtractItemSet( aItemSet, pRefFormat->GetAttrSet(),
1501 bSetDefaults, bClearSame,
1502 pRefFormatScript
1503 ? &pRefFormatScript->GetAttrSet()
1504 : nullptr );
1505
1506 if( !bCharFormat )
1507 {
1508 const SvxULSpaceItem& rULItem = pRefFormat->GetULSpace();
1509 rHTMLWrt.m_nDfltTopMargin = rULItem.GetUpper();
1510 rHTMLWrt.m_nDfltBottomMargin = rULItem.GetLower();
1511 }
1512 }
1513 else if( CSS1_FMT_ISTAG==nDeep && !bCharFormat )
1514 {
1515 // set Default-distance above and below (for the
1516 // case that there is no reference template)
1517 rHTMLWrt.m_nDfltTopMargin = 0;
1518 rHTMLWrt.m_nDfltBottomMargin = HTML_PARSPACE;
1519 if( USER_FMT & nPoolFormatId )
1520 {
1521 // user templates
1522 const OUString& aNm(rFormat.GetName());
1523
1524 if (aNm == "DD 1" || aNm == "DT 1")
1525 rHTMLWrt.m_nDfltBottomMargin = 0;
1526 else if (aNm == OOO_STRING_SVTOOLS_HTML_listing)
1527 rHTMLWrt.m_nDfltBottomMargin = 0;
1528 else if (aNm == OOO_STRING_SVTOOLS_HTML_preformtxt)
1529 rHTMLWrt.m_nDfltBottomMargin = 0;
1530 else if (aNm == OOO_STRING_SVTOOLS_HTML_xmp)
1531 rHTMLWrt.m_nDfltBottomMargin = 0;
1532 }
1533 else
1534 {
1535 // Pool templates
1536 switch( nPoolFormatId )
1537 {
1538 case RES_POOLCOLL_HEADLINE1:
1539 case RES_POOLCOLL_HEADLINE2:
1540 case RES_POOLCOLL_HEADLINE3:
1541 case RES_POOLCOLL_HEADLINE4:
1542 case RES_POOLCOLL_HEADLINE5:
1543 case RES_POOLCOLL_HEADLINE6:
1544 rHTMLWrt.m_nDfltTopMargin = HTML_HEADSPACE;
1545 break;
1546 case RES_POOLCOLL_SEND_ADDRESS:
1547 case RES_POOLCOLL_HTML_DT:
1548 case RES_POOLCOLL_HTML_DD:
1549 case RES_POOLCOLL_HTML_PRE:
1550 rHTMLWrt.m_nDfltBottomMargin = 0;
1551 break;
1552 }
1553 }
1554 }
1555
1556 // if nothing is to be exported ...
1557 if( !aItemSet.Count() )
1558 return rWrt;
1559
1560 // There is no support for script dependent hyperlinks by now.
1561 bool bCheckForPseudo = false;
1562 if( bCharFormat &&
1563 (RES_POOLCHR_INET_NORMAL==nRefPoolId ||
1564 RES_POOLCHR_INET_VISIT==nRefPoolId) )
1565 bCheckForPseudo = true;
1566
1567 // export now the Attributes (incl. selector)
1568 bool bHasScriptDependencies = false;
1569 if( OutCSS1Rule( rHTMLWrt, aSelector, aItemSet, CSS1_FMT_ISTAG != nDeep,
1570 bCheckForPseudo ) )
1571 {
1572 if( bCharFormat )
1573 rHTMLWrt.m_aScriptTextStyles.insert( rFormat.GetName() );
1574 else
1575 {
1576 if( nPoolFormatId==RES_POOLCOLL_TEXT )
1577 rHTMLWrt.m_aScriptParaStyles.insert( pDoc->GetTextCollFromPool( RES_POOLCOLL_STANDARD, false )->GetName() );
1578 rHTMLWrt.m_aScriptParaStyles.insert( rFormat.GetName() );
1579 }
1580 bHasScriptDependencies = true;
1581 }
1582
1583 // export Drop-Caps
1584 const SfxPoolItem *pItem;
1585 if( SfxItemState::SET==aItemSet.GetItemState( RES_PARATR_DROP, false, &pItem ))
1586 {
1587 OUString sOut = aSelector +
1588 ":" + OStringToOUString( sCSS1_first_letter, RTL_TEXTENCODING_ASCII_US );
1589 const SwFormatDrop *pDrop = static_cast<const SwFormatDrop *>(pItem);
1590 OutCSS1DropCapRule( rHTMLWrt, sOut, *pDrop, CSS1_FMT_ISTAG != nDeep, bHasScriptDependencies );
1591 }
1592
1593 return rWrt;
1594 }
1595
OutCSS1_SwPageDesc(Writer & rWrt,const SwPageDesc & rPageDesc,IDocumentStylePoolAccess * pDoc,SwDoc * pTemplate,sal_uInt16 nRefPoolId,bool bExtRef,bool bPseudo)1596 static Writer& OutCSS1_SwPageDesc( Writer& rWrt, const SwPageDesc& rPageDesc,
1597 IDocumentStylePoolAccess/*SwDoc*/ *pDoc, SwDoc *pTemplate,
1598 sal_uInt16 nRefPoolId, bool bExtRef,
1599 bool bPseudo )
1600 {
1601 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1602
1603 const SwPageDesc* pRefPageDesc = nullptr;
1604 if( !bExtRef )
1605 pRefPageDesc = pDoc->GetPageDescFromPool( nRefPoolId, false );
1606 else if( pTemplate )
1607 pRefPageDesc = pTemplate->getIDocumentStylePoolAccess().GetPageDescFromPool( nRefPoolId, false );
1608
1609 OUString aSelector = "@" + OStringToOUString( sCSS1_page, RTL_TEXTENCODING_ASCII_US );
1610
1611 if( bPseudo )
1612 {
1613 const char *pPseudo = nullptr;
1614 switch( rPageDesc.GetPoolFormatId() )
1615 {
1616 case RES_POOLPAGE_FIRST: pPseudo = sCSS1_first; break;
1617 case RES_POOLPAGE_LEFT: pPseudo = sCSS1_left; break;
1618 case RES_POOLPAGE_RIGHT: pPseudo = sCSS1_right; break;
1619 }
1620 if( pPseudo )
1621 aSelector += ":" + OStringToOUString( pPseudo, RTL_TEXTENCODING_ASCII_US );
1622 }
1623
1624 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_RULE_ON|CSS1_OUTMODE_TEMPLATE,
1625 &aSelector );
1626
1627 // Size: If the only difference is the Landscape-Flag,
1628 // only export Portrait or Landscape. Otherwise export size.
1629 bool bRefLandscape = pRefPageDesc && pRefPageDesc->GetLandscape();
1630 Size aRefSz;
1631 const Size& rSz = rPageDesc.GetMaster().GetFrameSize().GetSize();
1632 if( pRefPageDesc )
1633 {
1634 aRefSz = pRefPageDesc->GetMaster().GetFrameSize().GetSize();
1635 if( bRefLandscape != rPageDesc.GetLandscape() )
1636 {
1637 tools::Long nTmp = aRefSz.Height();
1638 aRefSz.setHeight( aRefSz.Width() );
1639 aRefSz.setWidth( nTmp );
1640 }
1641 }
1642
1643 // TODO: Bad Hack: On the Page-Tabpage there are small rounding errors
1644 // for the page size. Partially because of bug 25535, we stupidly still
1645 // use the Size-Item from Dialog, even if nothing changed.
1646 // Thus: once one visited the Page-Dialog and left it with OK, we get a
1647 // new page size that then gets exported here. To avoid that, we allow
1648 // here small deviations.
1649 if( std::abs( rSz.Width() - aRefSz.Width() ) <= 2 &&
1650 std::abs( rSz.Height() - aRefSz.Height() ) <= 2 )
1651 {
1652 if( bRefLandscape != rPageDesc.GetLandscape() )
1653 {
1654 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_size,
1655 rPageDesc.GetLandscape() ? sCSS1_PV_landscape
1656 : sCSS1_PV_portrait );
1657 }
1658 }
1659 else
1660 {
1661 OStringBuffer sVal;
1662 AddUnitPropertyValue(sVal, rSz.Width(), rHTMLWrt.GetCSS1Unit());
1663 sVal.append(' ');
1664 AddUnitPropertyValue(sVal, rSz.Height(), rHTMLWrt.GetCSS1Unit());
1665 rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_size, sVal.makeStringAndClear());
1666 }
1667
1668 // Export the distance-Attributes as normally
1669 const SwFrameFormat &rMaster = rPageDesc.GetMaster();
1670 SfxItemSet aItemSet( *rMaster.GetAttrSet().GetPool(),
1671 svl::Items<RES_LR_SPACE, RES_UL_SPACE>{} );
1672 aItemSet.Set( rMaster.GetAttrSet() );
1673
1674 if( pRefPageDesc )
1675 {
1676 SwHTMLWriter::SubtractItemSet( aItemSet,
1677 pRefPageDesc->GetMaster().GetAttrSet(),
1678 true );
1679 }
1680
1681 OutCSS1_SvxULSpace_SvxLRSpace( rWrt, aItemSet );
1682
1683 // If for a Pseudo-Selector no Property had been set, we still
1684 // have to export something, so that the corresponding template is
1685 // created on the next import.
1686 if( rHTMLWrt.m_bFirstCSS1Property && bPseudo )
1687 {
1688 rHTMLWrt.OutNewLine();
1689 OString sTmp(OUStringToOString(aSelector, rHTMLWrt.m_eDestEnc));
1690 rWrt.Strm().WriteOString( sTmp ).WriteCharPtr( " {" );
1691 rHTMLWrt.m_bFirstCSS1Property = false;
1692 }
1693
1694 if( !rHTMLWrt.m_bFirstCSS1Property )
1695 rWrt.Strm().WriteCharPtr( sCSS1_rule_end );
1696
1697 return rWrt;
1698 }
1699
OutCSS1_SwFootnoteInfo(Writer & rWrt,const SwEndNoteInfo & rInfo,SwDoc * pDoc,bool bHasNotes,bool bEndNote)1700 static Writer& OutCSS1_SwFootnoteInfo( Writer& rWrt, const SwEndNoteInfo& rInfo,
1701 SwDoc *pDoc, bool bHasNotes, bool bEndNote )
1702 {
1703 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1704
1705 OUString aSelector;
1706
1707 if( bHasNotes )
1708 {
1709 aSelector = OUString::Concat(OOO_STRING_SVTOOLS_HTML_anchor ".") +
1710 ( bEndNote ? std::u16string_view(u"" OOO_STRING_SVTOOLS_HTML_sdendnote_anc)
1711 : std::u16string_view(u"" OOO_STRING_SVTOOLS_HTML_sdfootnote_anc) );
1712 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1713 &aSelector );
1714 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_size,
1715 sHTML_FTN_fontheight );
1716 rHTMLWrt.Strm().WriteCharPtr( sCSS1_rule_end );
1717 }
1718
1719 const SwCharFormat *pSymCharFormat = rInfo.GetCharFormat( *pDoc );
1720 if( pSymCharFormat )
1721 {
1722 const SfxItemSet& rFormatItemSet = pSymCharFormat->GetAttrSet();
1723 SfxItemSet aItemSet( *rFormatItemSet.GetPool(), rFormatItemSet.GetRanges() );
1724 aItemSet.Set( rFormatItemSet );
1725
1726 // If there are footnotes or endnotes, then all Attributes have to be
1727 // exported, so that Netscape displays the document correctly.
1728 // Otherwise it is sufficient, to export the differences to the
1729 // footnote and endnote template.
1730 if( !bHasNotes && rHTMLWrt.m_xTemplate.is() )
1731 {
1732 SwFormat *pRefFormat = rHTMLWrt.m_xTemplate->getIDocumentStylePoolAccess().GetCharFormatFromPool(
1733 static_cast< sal_uInt16 >(bEndNote ? RES_POOLCHR_ENDNOTE : RES_POOLCHR_FOOTNOTE) );
1734 if( pRefFormat )
1735 SwHTMLWriter::SubtractItemSet( aItemSet, pRefFormat->GetAttrSet(),
1736 true );
1737 }
1738 if( aItemSet.Count() )
1739 {
1740 aSelector = OUString::Concat(OOO_STRING_SVTOOLS_HTML_anchor ".") +
1741 ( bEndNote ? std::u16string_view(u"" OOO_STRING_SVTOOLS_HTML_sdendnote_sym)
1742 : std::u16string_view(
1743 u"" OOO_STRING_SVTOOLS_HTML_sdfootnote_sym));
1744 if( OutCSS1Rule( rHTMLWrt, aSelector, aItemSet, true, false ))
1745 rHTMLWrt.m_aScriptTextStyles.insert( pSymCharFormat->GetName() );
1746 }
1747 }
1748
1749 return rWrt;
1750 }
1751
OutCSS1_BodyTagStyleOpt(Writer & rWrt,const SfxItemSet & rItemSet)1752 Writer& OutCSS1_BodyTagStyleOpt( Writer& rWrt, const SfxItemSet& rItemSet )
1753 {
1754 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1755
1756 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT_ON |
1757 CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_BODY, nullptr );
1758
1759 // Only export the attributes of the page template.
1760 // The attributes of the default paragraph template were
1761 // considered already when exporting the paragraph template.
1762
1763 const SfxPoolItem *pItem;
1764 if( SfxItemState::SET == rItemSet.GetItemState( RES_BACKGROUND, false,
1765 &pItem ) )
1766 {
1767 OUString rEmbeddedGraphicName;
1768 OutCSS1_SvxBrush( rWrt, *pItem, Css1Background::Page, &rEmbeddedGraphicName );
1769 }
1770
1771 if( SfxItemState::SET == rItemSet.GetItemState( RES_BOX, false,
1772 &pItem ))
1773 {
1774 OutCSS1_SvxBox( rWrt, *pItem );
1775 }
1776
1777 if( !rHTMLWrt.m_bFirstCSS1Property )
1778 {
1779 // if a Property was exported as part of a Style-Option,
1780 // the Option still needs to be finished
1781 rWrt.Strm().WriteChar( '\"' );
1782 }
1783
1784 return rWrt;
1785 }
1786
OutCSS1_ParaTagStyleOpt(Writer & rWrt,const SfxItemSet & rItemSet)1787 Writer& OutCSS1_ParaTagStyleOpt( Writer& rWrt, const SfxItemSet& rItemSet )
1788 {
1789 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1790
1791 SwCSS1OutMode aMode( rHTMLWrt, rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_STYLE_OPT |
1792 CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_PARA, nullptr );
1793 rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1794
1795 return rWrt;
1796 }
1797
1798 // Wrapper for Table background
OutCSS1_TableBGStyleOpt(Writer & rWrt,const SfxPoolItem & rHt)1799 Writer& OutCSS1_TableBGStyleOpt( Writer& rWrt, const SfxPoolItem& rHt )
1800 {
1801 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1802
1803 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT_ON |
1804 CSS1_OUTMODE_ENCODE|
1805 CSS1_OUTMODE_TABLEBOX, nullptr );
1806 OutCSS1_SvxBrush( rWrt, rHt, Css1Background::Table, nullptr );
1807
1808 if( !rHTMLWrt.m_bFirstCSS1Property )
1809 rWrt.Strm().WriteChar( '\"' );
1810
1811 return rWrt;
1812 }
1813
OutCSS1_NumberBulletListStyleOpt(Writer & rWrt,const SwNumRule & rNumRule,sal_uInt8 nLevel)1814 Writer& OutCSS1_NumberBulletListStyleOpt( Writer& rWrt, const SwNumRule& rNumRule,
1815 sal_uInt8 nLevel )
1816 {
1817 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1818
1819 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT |
1820 CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_PARA, nullptr );
1821
1822 const SwNumFormat& rNumFormat = rNumRule.Get( nLevel );
1823
1824 tools::Long nLSpace = rNumFormat.GetAbsLSpace();
1825 tools::Long nFirstLineOffset = rNumFormat.GetFirstLineOffset();
1826 tools::Long nDfltFirstLineOffset = HTML_NUMBER_BULLET_INDENT;
1827 if( nLevel > 0 )
1828 {
1829 const SwNumFormat& rPrevNumFormat = rNumRule.Get( nLevel-1 );
1830 nLSpace -= rPrevNumFormat.GetAbsLSpace();
1831 nDfltFirstLineOffset = rPrevNumFormat.GetFirstLineOffset();
1832 }
1833
1834 if( rHTMLWrt.IsHTMLMode(HTMLMODE_LSPACE_IN_NUMBER_BULLET) &&
1835 nLSpace != HTML_NUMBER_BULLET_MARGINLEFT )
1836 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_left, nLSpace );
1837
1838 if( rHTMLWrt.IsHTMLMode(HTMLMODE_FRSTLINE_IN_NUMBER_BULLET) &&
1839 nFirstLineOffset != nDfltFirstLineOffset )
1840 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_text_indent, nFirstLineOffset );
1841
1842 if( !rHTMLWrt.m_bFirstCSS1Property )
1843 rWrt.Strm().WriteChar( '\"' );
1844
1845 return rWrt;
1846 }
1847
OutCSS1_FrameFormatOptions(const SwFrameFormat & rFrameFormat,HtmlFrmOpts nFrameOpts,const SdrObject * pSdrObj,const SfxItemSet * pItemSet)1848 void SwHTMLWriter::OutCSS1_FrameFormatOptions( const SwFrameFormat& rFrameFormat,
1849 HtmlFrmOpts nFrameOpts,
1850 const SdrObject *pSdrObj,
1851 const SfxItemSet *pItemSet )
1852 {
1853 SwCSS1OutMode aMode( *this, CSS1_OUTMODE_STYLE_OPT_ON |
1854 CSS1_OUTMODE_ENCODE|
1855 CSS1_OUTMODE_FRAME, nullptr );
1856
1857 const SwFormatHoriOrient& rHoriOri = rFrameFormat.GetHoriOrient();
1858 SvxLRSpaceItem aLRItem( rFrameFormat.GetLRSpace() );
1859 SvxULSpaceItem aULItem( rFrameFormat.GetULSpace() );
1860 if( nFrameOpts & HtmlFrmOpts::SAlign )
1861 {
1862 const SwFormatAnchor& rAnchor = rFrameFormat.GetAnchor();
1863 switch( rAnchor.GetAnchorId() )
1864 {
1865 case RndStdIds::FLY_AT_PARA:
1866 case RndStdIds::FLY_AT_CHAR:
1867 if( text::RelOrientation::FRAME == rHoriOri.GetRelationOrient() ||
1868 text::RelOrientation::PRINT_AREA == rHoriOri.GetRelationOrient() )
1869 {
1870 if( !(nFrameOpts & HtmlFrmOpts::Align) )
1871 {
1872 // float
1873 const char *pStr = text::HoriOrientation::RIGHT==rHoriOri.GetHoriOrient()
1874 ? sCSS1_PV_right
1875 : sCSS1_PV_left;
1876 OutCSS1_PropertyAscii( sCSS1_P_float, pStr );
1877 }
1878 break;
1879 }
1880 [[fallthrough]];
1881
1882 case RndStdIds::FLY_AT_PAGE:
1883 case RndStdIds::FLY_AT_FLY:
1884 {
1885 // position
1886 OutCSS1_PropertyAscii( sCSS1_P_position, sCSS1_PV_absolute );
1887
1888 // For top/left we need to subtract the distance to the frame
1889 // from the position, as in CSS1 it is added to the position.
1890 // This works also for automatically aligned frames, even that
1891 // in this case Writer also adds the distance; because in this
1892 // case the Orient-Attribute contains the correct position.
1893
1894 // top
1895 tools::Long nXPos=0, nYPos=0;
1896 bool bOutXPos = false, bOutYPos = false;
1897 if( RES_DRAWFRMFMT == rFrameFormat.Which() )
1898 {
1899 OSL_ENSURE( pSdrObj, "Do not pass a SdrObject. Inefficient" );
1900 if( !pSdrObj )
1901 pSdrObj = rFrameFormat.FindSdrObject();
1902 OSL_ENSURE( pSdrObj, "Where is the SdrObject" );
1903 if( pSdrObj )
1904 {
1905 Point aPos( pSdrObj->GetRelativePos() );
1906 nXPos = aPos.X();
1907 nYPos = aPos.Y();
1908 }
1909 bOutXPos = bOutYPos = true;
1910 }
1911 else
1912 {
1913 bOutXPos = text::RelOrientation::CHAR != rHoriOri.GetRelationOrient();
1914 nXPos = text::HoriOrientation::NONE == rHoriOri.GetHoriOrient()
1915 ? rHoriOri.GetPos() : 0;
1916
1917 const SwFormatVertOrient& rVertOri = rFrameFormat.GetVertOrient();
1918 bOutYPos = text::RelOrientation::CHAR != rVertOri.GetRelationOrient();
1919 nYPos = text::VertOrientation::NONE == rVertOri.GetVertOrient()
1920 ? rVertOri.GetPos() : 0;
1921 }
1922
1923 if( bOutYPos )
1924 {
1925 if( IsHTMLMode( HTMLMODE_FLY_MARGINS) )
1926 {
1927 nYPos -= aULItem.GetUpper();
1928 if( nYPos < 0 )
1929 {
1930 aULItem.SetUpper( o3tl::narrowing<sal_uInt16>(aULItem.GetUpper() + nYPos) );
1931 nYPos = 0;
1932 }
1933 }
1934
1935 OutCSS1_UnitProperty( sCSS1_P_top, nYPos );
1936 }
1937
1938 if( bOutXPos )
1939 {
1940 // left
1941 if( IsHTMLMode( HTMLMODE_FLY_MARGINS) )
1942 {
1943 nXPos -= aLRItem.GetLeft();
1944 if( nXPos < 0 )
1945 {
1946 aLRItem.SetLeft( o3tl::narrowing<sal_uInt16>(aLRItem.GetLeft() + nXPos) );
1947 nXPos = 0;
1948 }
1949 }
1950
1951 OutCSS1_UnitProperty( sCSS1_P_left, nXPos );
1952 }
1953 }
1954 break;
1955
1956 default:
1957 ;
1958 }
1959 }
1960
1961 // width/height
1962 if( nFrameOpts & HtmlFrmOpts::SSize )
1963 {
1964 if( RES_DRAWFRMFMT == rFrameFormat.Which() )
1965 {
1966 OSL_ENSURE( pSdrObj, "Do not pass a SdrObject. Inefficient" );
1967 if( !pSdrObj )
1968 pSdrObj = rFrameFormat.FindSdrObject();
1969 OSL_ENSURE( pSdrObj, "Where is the SdrObject" );
1970 if( pSdrObj )
1971 {
1972 Size aTwipSz( pSdrObj->GetLogicRect().GetSize() );
1973 if( nFrameOpts & HtmlFrmOpts::SWidth )
1974 {
1975 if( nFrameOpts & HtmlFrmOpts::SPixSize )
1976 OutCSS1_PixelProperty( sCSS1_P_width, aTwipSz.Width(),
1977 false );
1978 else
1979 OutCSS1_UnitProperty( sCSS1_P_width, aTwipSz.Width() );
1980 }
1981 if( nFrameOpts & HtmlFrmOpts::SHeight )
1982 {
1983 if( nFrameOpts & HtmlFrmOpts::SPixSize )
1984 OutCSS1_PixelProperty( sCSS1_P_height, aTwipSz.Height(),
1985 true );
1986 else
1987 OutCSS1_UnitProperty( sCSS1_P_height, aTwipSz.Height() );
1988 }
1989 }
1990 }
1991 else
1992 {
1993 OSL_ENSURE( HtmlFrmOpts::AbsSize & nFrameOpts,
1994 "Export absolute size" );
1995 OSL_ENSURE( HtmlFrmOpts::AnySize & nFrameOpts,
1996 "Export every size" );
1997 Css1FrameSize nMode = Css1FrameSize::NONE;
1998 if( nFrameOpts & HtmlFrmOpts::SWidth )
1999 nMode |= Css1FrameSize::Width;
2000 if( nFrameOpts & HtmlFrmOpts::SHeight )
2001 nMode |= Css1FrameSize::MinHeight|Css1FrameSize::FixHeight;
2002 if( nFrameOpts & HtmlFrmOpts::SPixSize )
2003 nMode |= Css1FrameSize::Pixel;
2004
2005 OutCSS1_SwFormatFrameSize( *this, rFrameFormat.GetFrameSize(), nMode );
2006 }
2007 }
2008
2009 const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet();
2010 // margin-*
2011 if( (nFrameOpts & HtmlFrmOpts::SSpace) &&
2012 IsHTMLMode( HTMLMODE_FLY_MARGINS) )
2013 {
2014 const SvxLRSpaceItem *pLRItem = nullptr;
2015 const SvxULSpaceItem *pULItem = nullptr;
2016 if( SfxItemState::SET == rItemSet.GetItemState( RES_LR_SPACE ) )
2017 pLRItem = &aLRItem;
2018 if( SfxItemState::SET == rItemSet.GetItemState( RES_UL_SPACE ) )
2019 pULItem = &aULItem;
2020 if( pLRItem || pULItem )
2021 OutCSS1_SvxULSpace_SvxLRSpace( *this, pULItem, pLRItem );
2022 }
2023
2024 // border
2025 if( nFrameOpts & HtmlFrmOpts::SBorder )
2026 {
2027 const SfxPoolItem* pItem;
2028 if( nFrameOpts & HtmlFrmOpts::SNoBorder )
2029 OutCSS1_SvxBox( *this, rFrameFormat.GetBox() );
2030 else if( SfxItemState::SET==rItemSet.GetItemState( RES_BOX, true, &pItem ) )
2031 OutCSS1_SvxBox( *this, *pItem );
2032 }
2033
2034 // background (if, then the color must be set also)
2035 if( nFrameOpts & HtmlFrmOpts::SBackground )
2036 OutCSS1_FrameFormatBackground( rFrameFormat );
2037
2038 if( pItemSet )
2039 OutCSS1_SfxItemSet( *pItemSet, false );
2040
2041 if( !m_bFirstCSS1Property )
2042 Strm().WriteChar( '\"' );
2043 }
2044
OutCSS1_TableFrameFormatOptions(const SwFrameFormat & rFrameFormat)2045 void SwHTMLWriter::OutCSS1_TableFrameFormatOptions( const SwFrameFormat& rFrameFormat )
2046 {
2047 SwCSS1OutMode aMode( *this, CSS1_OUTMODE_STYLE_OPT_ON |
2048 CSS1_OUTMODE_ENCODE|
2049 CSS1_OUTMODE_TABLE, nullptr );
2050
2051 const SfxPoolItem *pItem;
2052 const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet();
2053 if( SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) )
2054 OutCSS1_SvxBrush( *this, *pItem, Css1Background::Table, nullptr );
2055
2056 if( IsHTMLMode( HTMLMODE_PRINT_EXT ) )
2057 OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( *this, rItemSet, false );
2058
2059 if( SfxItemState::SET==rItemSet.GetItemState( RES_LAYOUT_SPLIT, false, &pItem ) )
2060 OutCSS1_SwFormatLayoutSplit( *this, *pItem );
2061
2062 if( !m_bFirstCSS1Property )
2063 Strm().WriteChar( '\"' );
2064 }
2065
OutCSS1_TableCellBordersAndBG(SwFrameFormat const & rFrameFormat,const SvxBrushItem * pBrushItem)2066 void SwHTMLWriter::OutCSS1_TableCellBordersAndBG(SwFrameFormat const& rFrameFormat, const SvxBrushItem *pBrushItem)
2067 {
2068 SwCSS1OutMode const aMode( *this,
2069 CSS1_OUTMODE_STYLE_OPT_ON|CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_TABLEBOX, nullptr );
2070 if (pBrushItem)
2071 OutCSS1_SvxBrush(*this, *pBrushItem, Css1Background::Table, nullptr);
2072 OutCSS1_SvxBox(*this, rFrameFormat.GetBox());
2073 if (!m_bFirstCSS1Property)
2074 {
2075 Strm().WriteChar( cCSS1_style_opt_end );
2076 }
2077 }
2078
OutCSS1_SectionFormatOptions(const SwFrameFormat & rFrameFormat,const SwFormatCol * pCol)2079 void SwHTMLWriter::OutCSS1_SectionFormatOptions( const SwFrameFormat& rFrameFormat, const SwFormatCol *pCol )
2080 {
2081 SwCSS1OutMode aMode( *this, CSS1_OUTMODE_STYLE_OPT_ON |
2082 CSS1_OUTMODE_ENCODE|
2083 CSS1_OUTMODE_SECTION, nullptr );
2084
2085 const SfxPoolItem *pItem;
2086 const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet();
2087 if( SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) )
2088 OutCSS1_SvxBrush( *this, *pItem, Css1Background::Section, nullptr );
2089
2090 if (pCol)
2091 {
2092 OString sColumnCount(OString::number(static_cast<sal_Int32>(pCol->GetNumCols())));
2093 OutCSS1_PropertyAscii(sCSS1_P_column_count, sColumnCount);
2094 }
2095
2096 if( !m_bFirstCSS1Property )
2097 Strm().WriteChar( '\"' );
2098 }
2099
OutCSS1_FrameFormatBrush(SwHTMLWriter & rWrt,const SvxBrushItem & rBrushItem)2100 static bool OutCSS1_FrameFormatBrush( SwHTMLWriter& rWrt,
2101 const SvxBrushItem& rBrushItem )
2102 {
2103 bool bWritten = false;
2104 /// output brush of frame format, if its background color is not "no fill"/"auto fill"
2105 /// or it has a background graphic.
2106 if( rBrushItem.GetColor() != COL_TRANSPARENT ||
2107 !rBrushItem.GetGraphicLink().isEmpty() ||
2108 0 != rBrushItem.GetGraphicPos() )
2109 {
2110 OutCSS1_SvxBrush( rWrt, rBrushItem, Css1Background::Fly, nullptr );
2111 bWritten = true;
2112 }
2113 return bWritten;
2114 }
2115
OutCSS1_FrameFormatBackground(const SwFrameFormat & rFrameFormat)2116 void SwHTMLWriter::OutCSS1_FrameFormatBackground( const SwFrameFormat& rFrameFormat )
2117 {
2118 // If the frame itself has a background, then export.
2119 if( OutCSS1_FrameFormatBrush( *this, *rFrameFormat.makeBackgroundBrushItem() ) )
2120 return;
2121
2122 // If the frame is not linked to a page, we use the background of the anchor.
2123 const SwFormatAnchor& rAnchor = rFrameFormat.GetAnchor();
2124 RndStdIds eAnchorId = rAnchor.GetAnchorId();
2125 const SwPosition *pAnchorPos = rAnchor.GetContentAnchor();
2126 if (RndStdIds::FLY_AT_PAGE != eAnchorId && pAnchorPos)
2127 {
2128 const SwNode& rNode = pAnchorPos->nNode.GetNode();
2129 if( rNode.IsContentNode() )
2130 {
2131 // If the frame is linked to a content-node,
2132 // we take the background of the content-node, if it has one.
2133 if( OutCSS1_FrameFormatBrush( *this,
2134 rNode.GetContentNode()->GetSwAttrSet().GetBackground()) )
2135 return;
2136
2137 // Otherwise we also could be in a table
2138 const SwTableNode *pTableNd = rNode.FindTableNode();
2139 if( pTableNd )
2140 {
2141 const SwStartNode *pBoxSttNd = rNode.FindTableBoxStartNode();
2142 const SwTableBox *pBox =
2143 pTableNd->GetTable().GetTableBox( pBoxSttNd->GetIndex() );
2144
2145 // If the box has a background, we take it.
2146 if( OutCSS1_FrameFormatBrush( *this,
2147 *pBox->GetFrameFormat()->makeBackgroundBrushItem() ) )
2148 return;
2149
2150 // Otherwise we use that of the lines
2151 const SwTableLine *pLine = pBox->GetUpper();
2152 while( pLine )
2153 {
2154 if( OutCSS1_FrameFormatBrush( *this,
2155 *pLine->GetFrameFormat()->makeBackgroundBrushItem() ) )
2156 return;
2157 pBox = pLine->GetUpper();
2158 pLine = pBox ? pBox->GetUpper() : nullptr;
2159 }
2160
2161 // If there was none either, we use the background of the table.
2162 if( OutCSS1_FrameFormatBrush( *this,
2163 *pTableNd->GetTable().GetFrameFormat()->makeBackgroundBrushItem() ) )
2164 return;
2165 }
2166
2167 }
2168
2169 // If the anchor is again in a Fly-Frame, use the background of the Fly-Frame.
2170 const SwFrameFormat *pFrameFormat = rNode.GetFlyFormat();
2171 if( pFrameFormat )
2172 {
2173 OutCSS1_FrameFormatBackground( *pFrameFormat );
2174 return;
2175 }
2176 }
2177
2178 // At last there is the background of the page, and as the final rescue
2179 // the value of the Config.
2180 OSL_ENSURE( m_pCurrPageDesc, "no page template found" );
2181 if( OutCSS1_FrameFormatBrush( *this,
2182 *m_pCurrPageDesc->GetMaster().makeBackgroundBrushItem() ) )
2183 return;
2184
2185 Color aColor( COL_WHITE );
2186
2187 // The background color is normally only used in Browse-Mode.
2188 // We always use it for a HTML document, but for a text document
2189 // only if viewed in Browse-Mode.
2190 if( m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) ||
2191 m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE))
2192 {
2193 SwViewShell *pVSh = m_pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
2194 if ( pVSh &&
2195 COL_TRANSPARENT != pVSh->GetViewOptions()->GetRetoucheColor())
2196 aColor = pVSh->GetViewOptions()->GetRetoucheColor();
2197 }
2198
2199 OutCSS1_PropertyAscii(sCSS1_P_background, GetCSS1_Color(aColor));
2200 }
2201
OutCSS1_SvxTextLn_SvxCrOut_SvxBlink(Writer & rWrt,const SvxUnderlineItem * pUItem,const SvxOverlineItem * pOItem,const SvxCrossedOutItem * pCOItem,const SvxBlinkItem * pBItem)2202 static Writer& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( Writer& rWrt,
2203 const SvxUnderlineItem *pUItem,
2204 const SvxOverlineItem *pOItem,
2205 const SvxCrossedOutItem *pCOItem,
2206 const SvxBlinkItem *pBItem )
2207 {
2208 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2209 bool bNone = false;
2210
2211 const char *pUStr = nullptr;
2212 if( pUItem )
2213 {
2214 switch( pUItem->GetLineStyle() )
2215 {
2216 case LINESTYLE_NONE:
2217 bNone = true;
2218 break;
2219 case LINESTYLE_DONTKNOW:
2220 break;
2221 default:
2222 if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2223 {
2224 // this also works in HTML does not need to be written as
2225 // a STYLE-Options, and must not be written as Hint
2226 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT) || rHTMLWrt.mbReqIF,
2227 "write underline as Hint?" );
2228 pUStr = sCSS1_PV_underline;
2229 }
2230 break;
2231 }
2232 }
2233
2234 const char *pOStr = nullptr;
2235 if( pOItem )
2236 {
2237 switch( pOItem->GetLineStyle() )
2238 {
2239 case LINESTYLE_NONE:
2240 bNone = true;
2241 break;
2242 case LINESTYLE_DONTKNOW:
2243 break;
2244 default:
2245 if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2246 {
2247 // this also works in HTML does not need to be written as
2248 // a STYLE-Options, and must not be written as Hint
2249 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2250 "write overline as Hint?" );
2251 pOStr = sCSS1_PV_overline;
2252 }
2253 break;
2254 }
2255 }
2256
2257 const char *pCOStr = nullptr;
2258 if( pCOItem )
2259 {
2260 switch( pCOItem->GetStrikeout() )
2261 {
2262 case STRIKEOUT_NONE:
2263 bNone = true;
2264 break;
2265 case STRIKEOUT_DONTKNOW:
2266 break;
2267 default:
2268 if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2269 {
2270 // this also works in HTML does not need to be written as
2271 // a STYLE-Options, and must not be written as Hint
2272 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT) || rHTMLWrt.mbReqIF,
2273 "write crossedOut as Hint?" );
2274 pCOStr = sCSS1_PV_line_through;
2275 }
2276 break;
2277 }
2278 }
2279
2280 const char *pBStr = nullptr;
2281 if( pBItem )
2282 {
2283 if( !pBItem->GetValue() )
2284 {
2285 bNone = true;
2286 }
2287 else if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2288 {
2289 // this also works in HTML does not need to be written as
2290 // a STYLE-Options, and must not be written as Hint
2291 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2292 "write blink as Hint?" );
2293 pBStr = sCSS1_PV_blink;
2294 }
2295 }
2296
2297 OStringBuffer sOut;
2298 if( pUStr )
2299 sOut.append(pUStr);
2300
2301 if( pOStr )
2302 {
2303 if (!sOut.isEmpty())
2304 sOut.append(' ');
2305 sOut.append(pOStr);
2306 }
2307
2308 if( pCOStr )
2309 {
2310 if (!sOut.isEmpty())
2311 sOut.append(' ');
2312 sOut.append(pCOStr);
2313 }
2314
2315 if( pBStr )
2316 {
2317 if (!sOut.isEmpty())
2318 sOut.append(' ');
2319 sOut.append(pBStr);
2320 }
2321
2322 if (!sOut.isEmpty())
2323 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_decoration, sOut.makeStringAndClear() );
2324 else if( bNone )
2325 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_decoration, sCSS1_PV_none );
2326
2327 return rWrt;
2328 }
2329
OutCSS1_SvxCaseMap(Writer & rWrt,const SfxPoolItem & rHt)2330 static Writer& OutCSS1_SvxCaseMap( Writer& rWrt, const SfxPoolItem& rHt )
2331 {
2332 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2333
2334 switch( static_cast<const SvxCaseMapItem&>(rHt).GetCaseMap() )
2335 {
2336 case SvxCaseMap::NotMapped:
2337 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_variant, sCSS1_PV_normal );
2338 break;
2339 case SvxCaseMap::SmallCaps:
2340 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_variant, sCSS1_PV_small_caps );
2341 break;
2342 case SvxCaseMap::Uppercase:
2343 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_uppercase );
2344 break;
2345 case SvxCaseMap::Lowercase:
2346 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_lowercase );
2347 break;
2348 case SvxCaseMap::Capitalize:
2349 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_capitalize );
2350 break;
2351 default:
2352 ;
2353 }
2354
2355 return rWrt;
2356 }
2357
OutCSS1_SvxColor(Writer & rWrt,const SfxPoolItem & rHt)2358 static Writer& OutCSS1_SvxColor( Writer& rWrt, const SfxPoolItem& rHt )
2359 {
2360 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2361
2362 // Colors do not need to be exported for Style-Option.
2363 if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) &&
2364 !rHTMLWrt.m_bCfgPreferStyles )
2365 return rWrt;
2366 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2367 "write color as Hint?" );
2368
2369 Color aColor( static_cast<const SvxColorItem&>(rHt).GetValue() );
2370 if( COL_AUTO == aColor )
2371 aColor = COL_BLACK;
2372
2373 rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_color, GetCSS1_Color(aColor));
2374
2375 return rWrt;
2376 }
2377
OutCSS1_SvxCrossedOut(Writer & rWrt,const SfxPoolItem & rHt)2378 static Writer& OutCSS1_SvxCrossedOut( Writer& rWrt, const SfxPoolItem& rHt )
2379 {
2380 // This function only exports Hints!
2381 // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
2382
2383 if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) )
2384 OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
2385 nullptr, nullptr, static_cast<const SvxCrossedOutItem *>(&rHt), nullptr );
2386
2387 return rWrt;
2388 }
2389
OutCSS1_SvxFont(Writer & rWrt,const SfxPoolItem & rHt)2390 static Writer& OutCSS1_SvxFont( Writer& rWrt, const SfxPoolItem& rHt )
2391 {
2392 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2393
2394 // No need to export Fonts for the Style-Option.
2395 if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2396 return rWrt;
2397
2398 sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
2399 switch( rHt.Which() )
2400 {
2401 case RES_CHRATR_CJK_FONT: nScript = CSS1_OUTMODE_CJK; break;
2402 case RES_CHRATR_CTL_FONT: nScript = CSS1_OUTMODE_CTL; break;
2403 }
2404 if( !rHTMLWrt.IsCSS1Script( nScript ) )
2405 return rWrt;
2406
2407 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2408 "write Font as Hint?" );
2409
2410 OUString sOut;
2411 // MS IE3b1 has problems with single quotes
2412 sal_uInt16 nMode = rHTMLWrt.m_nCSS1OutMode & CSS1_OUTMODE_ANY_ON;
2413 sal_Unicode cQuote = nMode == CSS1_OUTMODE_RULE_ON ? '\"' : '\'';
2414 SwHTMLWriter::PrepareFontList( static_cast<const SvxFontItem&>(rHt), sOut, cQuote,
2415 true );
2416
2417 rHTMLWrt.OutCSS1_Property( sCSS1_P_font_family, sOut );
2418
2419 return rWrt;
2420 }
2421
OutCSS1_SvxFontHeight(Writer & rWrt,const SfxPoolItem & rHt)2422 static Writer& OutCSS1_SvxFontHeight( Writer& rWrt, const SfxPoolItem& rHt )
2423 {
2424 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2425
2426 // Font-Height need not be exported in the Style-Option.
2427 // For Drop-Caps another Font-Size is exported.
2428 if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ||
2429 rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_DROPCAP ) )
2430 return rWrt;
2431
2432 sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
2433 switch( rHt.Which() )
2434 {
2435 case RES_CHRATR_CJK_FONTSIZE: nScript = CSS1_OUTMODE_CJK; break;
2436 case RES_CHRATR_CTL_FONTSIZE: nScript = CSS1_OUTMODE_CTL; break;
2437 }
2438 if( !rHTMLWrt.IsCSS1Script( nScript ) )
2439 return rWrt;
2440
2441 sal_uInt32 nHeight = static_cast<const SvxFontHeightItem&>(rHt).GetHeight();
2442 OString sHeight(OString::number(nHeight/20) + sCSS1_UNIT_pt);
2443 rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_font_size, sHeight);
2444
2445 return rWrt;
2446 }
2447
OutCSS1_SvxPosture(Writer & rWrt,const SfxPoolItem & rHt)2448 static Writer& OutCSS1_SvxPosture( Writer& rWrt, const SfxPoolItem& rHt )
2449 {
2450 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2451
2452 sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
2453 switch( rHt.Which() )
2454 {
2455 case RES_CHRATR_CJK_POSTURE: nScript = CSS1_OUTMODE_CJK; break;
2456 case RES_CHRATR_CTL_POSTURE: nScript = CSS1_OUTMODE_CTL; break;
2457 }
2458 if( !rHTMLWrt.IsCSS1Script( nScript ) )
2459 return rWrt;
2460
2461 const char *pStr = nullptr;
2462 switch( static_cast<const SvxPostureItem&>(rHt).GetPosture() )
2463 {
2464 case ITALIC_NONE: pStr = sCSS1_PV_normal; break;
2465 case ITALIC_OBLIQUE: pStr = sCSS1_PV_oblique; break;
2466 case ITALIC_NORMAL:
2467 if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2468 {
2469 // this also works in HTML does not need to be written as
2470 // a STYLE-Options, and must not be written as Hint
2471 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2472 "write italic as Hint?" );
2473 pStr = sCSS1_PV_italic;
2474 }
2475 break;
2476 default:
2477 ;
2478 }
2479
2480 if( pStr )
2481 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_style, pStr );
2482
2483 return rWrt;
2484 }
2485
OutCSS1_SvxKerning(Writer & rWrt,const SfxPoolItem & rHt)2486 static Writer& OutCSS1_SvxKerning( Writer& rWrt, const SfxPoolItem& rHt )
2487 {
2488 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2489
2490 sal_Int16 nValue = static_cast<const SvxKerningItem&>(rHt).GetValue();
2491 if( nValue )
2492 {
2493 OStringBuffer sOut;
2494 if( nValue < 0 )
2495 {
2496 sOut.append('-');
2497 nValue = -nValue;
2498 }
2499
2500 // Width as n.n pt
2501 nValue = (nValue + 1) / 2; // 1/10pt
2502 sOut.append(OString::number(nValue / 10) + "." + OString::number(nValue % 10) +
2503 sCSS1_UNIT_pt);
2504
2505 rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_letter_spacing,
2506 sOut.makeStringAndClear());
2507 }
2508 else
2509 {
2510 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_letter_spacing,
2511 sCSS1_PV_normal );
2512 }
2513
2514 return rWrt;
2515 }
2516
OutCSS1_SvxLanguage(Writer & rWrt,const SfxPoolItem & rHt)2517 static Writer& OutCSS1_SvxLanguage( Writer& rWrt, const SfxPoolItem& rHt )
2518 {
2519 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2520
2521 // Only export Language rules
2522 if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2523 return rWrt;
2524
2525 sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
2526 switch( rHt.Which() )
2527 {
2528 case RES_CHRATR_CJK_LANGUAGE: nScript = CSS1_OUTMODE_CJK; break;
2529 case RES_CHRATR_CTL_LANGUAGE: nScript = CSS1_OUTMODE_CTL; break;
2530 }
2531 if( !rHTMLWrt.IsCSS1Script( nScript ) )
2532 return rWrt;
2533
2534 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2535 "write Language as Hint?" );
2536
2537 LanguageType eLang = static_cast<const SvxLanguageItem &>(rHt).GetLanguage();
2538 if( LANGUAGE_DONTKNOW == eLang )
2539 return rWrt;
2540
2541 OUString sOut = LanguageTag::convertToBcp47( eLang );
2542
2543 rHTMLWrt.OutCSS1_Property( sCSS1_P_so_language, sOut );
2544
2545 return rWrt;
2546 }
2547
OutCSS1_SvxUnderline(Writer & rWrt,const SfxPoolItem & rHt)2548 static Writer& OutCSS1_SvxUnderline( Writer& rWrt, const SfxPoolItem& rHt )
2549 {
2550 // This function only exports Hints!
2551 // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
2552
2553 if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) )
2554 OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
2555 static_cast<const SvxUnderlineItem *>(&rHt), nullptr, nullptr, nullptr );
2556
2557 return rWrt;
2558 }
2559
OutCSS1_SvxOverline(Writer & rWrt,const SfxPoolItem & rHt)2560 static Writer& OutCSS1_SvxOverline( Writer& rWrt, const SfxPoolItem& rHt )
2561 {
2562 // This function only exports Hints!
2563 // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
2564
2565 if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) )
2566 OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
2567 nullptr, static_cast<const SvxOverlineItem *>(&rHt), nullptr, nullptr );
2568
2569 return rWrt;
2570 }
2571
OutCSS1_SvxHidden(Writer & rWrt,const SfxPoolItem & rHt)2572 static Writer& OutCSS1_SvxHidden( Writer& rWrt, const SfxPoolItem& rHt )
2573 {
2574 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2575
2576 if ( static_cast<const SvxCharHiddenItem&>(rHt).GetValue() )
2577 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_display, sCSS1_PV_none );
2578
2579 return rWrt;
2580 }
2581
OutCSS1_SvxFontWeight(Writer & rWrt,const SfxPoolItem & rHt)2582 static Writer& OutCSS1_SvxFontWeight( Writer& rWrt, const SfxPoolItem& rHt )
2583 {
2584 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2585
2586 sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
2587 switch( rHt.Which() )
2588 {
2589 case RES_CHRATR_CJK_WEIGHT: nScript = CSS1_OUTMODE_CJK; break;
2590 case RES_CHRATR_CTL_WEIGHT: nScript = CSS1_OUTMODE_CTL; break;
2591 }
2592 if( !rHTMLWrt.IsCSS1Script( nScript ) )
2593 return rWrt;
2594
2595 const char *pStr = nullptr;
2596 switch( static_cast<const SvxWeightItem&>(rHt).GetWeight() )
2597 {
2598 case WEIGHT_ULTRALIGHT: pStr = sCSS1_PV_extra_light; break;
2599 case WEIGHT_LIGHT: pStr = sCSS1_PV_light; break;
2600 case WEIGHT_SEMILIGHT: pStr = sCSS1_PV_demi_light; break;
2601 case WEIGHT_NORMAL: pStr = sCSS1_PV_normal; break;
2602 case WEIGHT_SEMIBOLD: pStr = sCSS1_PV_demi_bold; break;
2603 case WEIGHT_BOLD:
2604 if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2605 {
2606 // this also works in HTML does not need to be written as
2607 // a STYLE-Options, and must not be written as Hint
2608 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2609 "write bold as Hint?" );
2610 pStr = sCSS1_PV_bold;
2611 }
2612 break;
2613 case WEIGHT_ULTRABOLD: pStr = sCSS1_PV_extra_bold; break;
2614 default:
2615 pStr = sCSS1_PV_normal;
2616 }
2617
2618 if( pStr )
2619 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_weight, pStr );
2620
2621 return rWrt;
2622 }
2623
OutCSS1_SvxBlink(Writer & rWrt,const SfxPoolItem & rHt)2624 static Writer& OutCSS1_SvxBlink( Writer& rWrt, const SfxPoolItem& rHt )
2625 {
2626 // This function only exports Hints!
2627 // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
2628
2629 if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) )
2630 OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
2631 nullptr, nullptr, nullptr, static_cast<const SvxBlinkItem *>(&rHt) );
2632
2633 return rWrt;
2634 }
2635
OutCSS1_SvxLineSpacing(Writer & rWrt,const SfxPoolItem & rHt)2636 static Writer& OutCSS1_SvxLineSpacing( Writer& rWrt, const SfxPoolItem& rHt )
2637 {
2638 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2639
2640 // Netscape4 has big problems with cell heights if the line spacing is
2641 // changed within a table and the width of the table is not calculated
2642 // automatically (== if there is a WIDTH-Option)
2643 if( rHTMLWrt.m_bOutTable && rHTMLWrt.m_bCfgNetscape4 )
2644 return rWrt;
2645
2646 const SvxLineSpacingItem& rLSItem = static_cast<const SvxLineSpacingItem&>(rHt);
2647
2648 sal_uInt16 nHeight = 0;
2649 sal_uInt16 nPercentHeight = 0;
2650 SvxLineSpaceRule eLineSpace = rLSItem.GetLineSpaceRule();
2651 switch( rLSItem.GetInterLineSpaceRule() )
2652 {
2653 case SvxInterLineSpaceRule::Off:
2654 case SvxInterLineSpaceRule::Fix:
2655 {
2656 switch( eLineSpace )
2657 {
2658 case SvxLineSpaceRule::Min:
2659 case SvxLineSpaceRule::Fix:
2660 nHeight = rLSItem.GetLineHeight();
2661 break;
2662 case SvxLineSpaceRule::Auto:
2663 nPercentHeight = 100;
2664 break;
2665 default:
2666 ;
2667 }
2668 }
2669 break;
2670 case SvxInterLineSpaceRule::Prop:
2671 nPercentHeight = rLSItem.GetPropLineSpace();
2672 break;
2673
2674 default:
2675 ;
2676 }
2677
2678 if( nHeight )
2679 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_line_height, static_cast<tools::Long>(nHeight) );
2680 else if( nPercentHeight &&
2681 !(nPercentHeight < 115 && rHTMLWrt.m_bParaDotLeaders )) // avoid HTML scrollbars and missing descenders
2682 {
2683 OString sHeight(OString::number(nPercentHeight) + "%");
2684 rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_line_height, sHeight);
2685 }
2686
2687 return rWrt;
2688 }
2689
OutCSS1_SvxAdjust(Writer & rWrt,const SfxPoolItem & rHt)2690 static Writer& OutCSS1_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt )
2691 {
2692 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2693
2694 // Export Alignment in Style-Option only if the Tag does not allow ALIGN=xxx
2695 if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) &&
2696 !rHTMLWrt.m_bNoAlign)
2697 return rWrt;
2698
2699 const char* pStr = nullptr;
2700 switch( static_cast<const SvxAdjustItem&>(rHt).GetAdjust() )
2701 {
2702 case SvxAdjust::Left: pStr = sCSS1_PV_left; break;
2703 case SvxAdjust::Right: pStr = sCSS1_PV_right; break;
2704 case SvxAdjust::Block: pStr = sCSS1_PV_justify; break;
2705 case SvxAdjust::Center: pStr = sCSS1_PV_center; break;
2706 default:
2707 ;
2708 }
2709
2710 if( pStr )
2711 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_align, pStr );
2712
2713 return rWrt;
2714 }
2715
OutCSS1_SvxFormatSplit(Writer & rWrt,const SfxPoolItem & rHt)2716 static Writer& OutCSS1_SvxFormatSplit( Writer& rWrt, const SfxPoolItem& rHt )
2717 {
2718 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2719
2720 const char *pStr = static_cast<const SvxFormatSplitItem&>(rHt).GetValue()
2721 ? sCSS1_PV_auto
2722 : sCSS1_PV_avoid;
2723 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_inside, pStr );
2724
2725 return rWrt;
2726 }
2727
OutCSS1_SwFormatLayoutSplit(Writer & rWrt,const SfxPoolItem & rHt)2728 static Writer& OutCSS1_SwFormatLayoutSplit( Writer& rWrt, const SfxPoolItem& rHt )
2729 {
2730 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2731
2732 const char *pStr = static_cast<const SwFormatLayoutSplit&>(rHt).GetValue()
2733 ? sCSS1_PV_auto
2734 : sCSS1_PV_avoid;
2735 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_inside, pStr );
2736
2737 return rWrt;
2738 }
2739
OutCSS1_SvxWidows(Writer & rWrt,const SfxPoolItem & rHt)2740 static Writer& OutCSS1_SvxWidows( Writer& rWrt, const SfxPoolItem& rHt )
2741 {
2742 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2743
2744 OString aStr(OString::number(static_cast<const SvxWidowsItem&>(rHt).GetValue()));
2745 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_widows, aStr );
2746
2747 return rWrt;
2748 }
2749
OutCSS1_SvxOrphans(Writer & rWrt,const SfxPoolItem & rHt)2750 static Writer& OutCSS1_SvxOrphans( Writer& rWrt, const SfxPoolItem& rHt )
2751 {
2752 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2753
2754 OString aStr(OString::number(static_cast<const SvxOrphansItem&>(rHt).GetValue()));
2755 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_orphans, aStr );
2756
2757 return rWrt;
2758 }
2759
OutCSS1_SwFormatDropAttrs(SwHTMLWriter & rHWrt,const SwFormatDrop & rDrop,const SfxItemSet * pCharFormatItemSet)2760 static void OutCSS1_SwFormatDropAttrs( SwHTMLWriter& rHWrt,
2761 const SwFormatDrop& rDrop,
2762 const SfxItemSet *pCharFormatItemSet )
2763 {
2764 // Text flows around on right side
2765 rHWrt.OutCSS1_PropertyAscii( sCSS1_P_float, sCSS1_PV_left );
2766
2767 // number of lines -> use % for Font-Height!
2768 OString sOut(OString::number(rDrop.GetLines()*100) + "%");
2769 rHWrt.OutCSS1_PropertyAscii(sCSS1_P_font_size, sOut);
2770
2771 // distance to Text = right margin
2772 sal_uInt16 nDistance = rDrop.GetDistance();
2773 if( nDistance > 0 )
2774 rHWrt.OutCSS1_UnitProperty( sCSS1_P_margin_right, nDistance );
2775
2776 const SwCharFormat *pDCCharFormat = rDrop.GetCharFormat();
2777 if( pCharFormatItemSet )
2778 rHWrt.OutCSS1_SfxItemSet( *pCharFormatItemSet );
2779 else if( pDCCharFormat )
2780 rHWrt.OutCSS1_SfxItemSet( pDCCharFormat->GetAttrSet() );
2781 else if( (rHWrt.m_nCSS1OutMode & CSS1_OUTMODE_ANY_OFF) == CSS1_OUTMODE_RULE_OFF )
2782 rHWrt.Strm().WriteCharPtr( sCSS1_rule_end );
2783
2784 }
2785
OutCSS1_SwFormatDrop(Writer & rWrt,const SfxPoolItem & rHt)2786 static Writer& OutCSS1_SwFormatDrop( Writer& rWrt, const SfxPoolItem& rHt )
2787 {
2788 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2789
2790 // never export as an Option of a paragraph, but only as Hints
2791 if( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT) )
2792 return rWrt;
2793
2794 if( rHTMLWrt.m_bTagOn )
2795 {
2796 SwCSS1OutMode aMode( rHTMLWrt,
2797 rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_SPAN_TAG1_ON|CSS1_OUTMODE_ENCODE|
2798 CSS1_OUTMODE_DROPCAP, nullptr );
2799
2800 OutCSS1_SwFormatDropAttrs( rHTMLWrt, static_cast<const SwFormatDrop&>(rHt) );
2801 // A "> is already printed by the calling OutCSS1_HintAsSpanTag.
2802 }
2803 else
2804 {
2805 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false );
2806 }
2807
2808 return rWrt;
2809 }
2810
OutCSS1_SwFormatFrameSize(Writer & rWrt,const SfxPoolItem & rHt,Css1FrameSize nMode)2811 static Writer& OutCSS1_SwFormatFrameSize( Writer& rWrt, const SfxPoolItem& rHt,
2812 Css1FrameSize nMode )
2813 {
2814 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2815
2816 const SwFormatFrameSize& rFSItem = static_cast<const SwFormatFrameSize&>(rHt);
2817
2818 if( nMode & Css1FrameSize::Width )
2819 {
2820 sal_uInt8 nPercentWidth = rFSItem.GetWidthPercent();
2821 if( nPercentWidth )
2822 {
2823 OString sOut(OString::number(nPercentWidth) + "%");
2824 rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_width, sOut);
2825 }
2826 else if( nMode & Css1FrameSize::Pixel )
2827 {
2828 rHTMLWrt.OutCSS1_PixelProperty( sCSS1_P_width,
2829 rFSItem.GetSize().Width(), false );
2830 }
2831 else
2832 {
2833 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_width,
2834 rFSItem.GetSize().Width() );
2835 }
2836 }
2837
2838 return rWrt;
2839 }
2840
OutCSS1_SvxLRSpace(Writer & rWrt,const SfxPoolItem & rHt)2841 static Writer& OutCSS1_SvxLRSpace( Writer& rWrt, const SfxPoolItem& rHt )
2842 {
2843 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2844
2845 const SvxLRSpaceItem& rLRItem = static_cast<const SvxLRSpaceItem&>(rHt);
2846
2847 // No Export of a firm attribute is needed if the new values
2848 // match that of the current template
2849
2850 // A left margin can exist because of a list nearby
2851 tools::Long nLeftMargin = rLRItem.GetTextLeft() - rHTMLWrt.m_nLeftMargin;
2852 if( rHTMLWrt.m_nDfltLeftMargin != nLeftMargin )
2853 {
2854 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_left, nLeftMargin );
2855
2856 // max-width = max-width - margin-left for TOC paragraphs with dot leaders
2857 if( rHTMLWrt.m_bParaDotLeaders )
2858 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_max_width, tools::Long(DOT_LEADERS_MAX_WIDTH/2.54*72*20) - nLeftMargin );
2859
2860 }
2861
2862 if( rHTMLWrt.m_nDfltRightMargin != rLRItem.GetRight() )
2863 {
2864 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_right, rLRItem.GetRight() );
2865 }
2866
2867 // The LineIndent of the first line might contain the room for numbering
2868 tools::Long nFirstLineIndent = static_cast<tools::Long>(rLRItem.GetTextFirstLineOffset()) -
2869 rHTMLWrt.m_nFirstLineIndent;
2870 if( rHTMLWrt.m_nDfltFirstLineIndent != nFirstLineIndent )
2871 {
2872 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_text_indent,
2873 nFirstLineIndent );
2874 }
2875
2876 return rWrt;
2877 }
2878
OutCSS1_SvxULSpace(Writer & rWrt,const SfxPoolItem & rHt)2879 static Writer& OutCSS1_SvxULSpace( Writer& rWrt, const SfxPoolItem& rHt )
2880 {
2881 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2882
2883 const SvxULSpaceItem& rULItem = static_cast<const SvxULSpaceItem&>(rHt);
2884
2885 if( rHTMLWrt.m_nDfltTopMargin != rULItem.GetUpper() )
2886 {
2887 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_top,
2888 static_cast<tools::Long>(rULItem.GetUpper()) );
2889 }
2890
2891 if( rHTMLWrt.m_nDfltBottomMargin != rULItem.GetLower() )
2892 {
2893 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_bottom,
2894 static_cast<tools::Long>(rULItem.GetLower()) );
2895 }
2896
2897 return rWrt;
2898 }
2899
OutCSS1_SvxULSpace_SvxLRSpace(Writer & rWrt,const SvxULSpaceItem * pULItem,const SvxLRSpaceItem * pLRItem)2900 static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt,
2901 const SvxULSpaceItem *pULItem,
2902 const SvxLRSpaceItem *pLRItem )
2903 {
2904 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2905
2906 if( pLRItem && pULItem &&
2907 pLRItem->GetLeft() == pLRItem->GetRight() &&
2908 pLRItem->GetLeft() == pULItem->GetUpper() &&
2909 pLRItem->GetLeft() == pULItem->GetLower() &&
2910 pLRItem->GetLeft() != rHTMLWrt.m_nDfltLeftMargin &&
2911 pLRItem->GetRight() != rHTMLWrt.m_nDfltRightMargin &&
2912 pULItem->GetUpper() != rHTMLWrt.m_nDfltTopMargin &&
2913 pULItem->GetLower() != rHTMLWrt.m_nDfltBottomMargin )
2914 {
2915 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin, pLRItem->GetLeft() );
2916 }
2917 else
2918 {
2919 if( pLRItem )
2920 OutCSS1_SvxLRSpace( rWrt, *pLRItem );
2921 if( pULItem )
2922 OutCSS1_SvxULSpace( rWrt, *pULItem );
2923 }
2924
2925 return rWrt;
2926 }
2927
OutCSS1_SvxULSpace_SvxLRSpace(Writer & rWrt,const SfxItemSet & rItemSet)2928 static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt,
2929 const SfxItemSet& rItemSet )
2930 {
2931 const SvxULSpaceItem *pULSpace = nullptr;
2932 const SvxLRSpaceItem *pLRSpace = nullptr;
2933 const SfxPoolItem *pItem;
2934 if( SfxItemState::SET == rItemSet.GetItemState( RES_LR_SPACE, false/*bDeep*/, &pItem ) )
2935 pLRSpace = static_cast<const SvxLRSpaceItem *>(pItem);
2936
2937 if( SfxItemState::SET == rItemSet.GetItemState( RES_UL_SPACE, false/*bDeep*/, &pItem ) )
2938 pULSpace = static_cast<const SvxULSpaceItem *>(pItem);
2939
2940 if( pLRSpace || pULSpace )
2941 OutCSS1_SvxULSpace_SvxLRSpace( rWrt, pULSpace, pLRSpace );
2942
2943 return rWrt;
2944 }
2945
OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep(Writer & rWrt,const SvxFormatBreakItem * pBreakItem,const SwFormatPageDesc * pPDescItem,const SvxFormatKeepItem * pKeepItem)2946 static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt,
2947 const SvxFormatBreakItem *pBreakItem,
2948 const SwFormatPageDesc *pPDescItem,
2949 const SvxFormatKeepItem *pKeepItem )
2950 {
2951 SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2952
2953 if( !rHTMLWrt.IsHTMLMode(HTMLMODE_PRINT_EXT) )
2954 return rWrt;
2955
2956 const char *pBreakBefore = nullptr;
2957 const char *pBreakAfter = nullptr;
2958
2959 if( pKeepItem )
2960 {
2961 pBreakAfter = pKeepItem->GetValue() ? sCSS1_PV_avoid : sCSS1_PV_auto;
2962 }
2963 if( pBreakItem )
2964 {
2965 switch( pBreakItem->GetBreak() )
2966 {
2967 case SvxBreak::NONE:
2968 pBreakBefore = sCSS1_PV_auto;
2969 if( !pBreakAfter )
2970 pBreakAfter = sCSS1_PV_auto;
2971 break;
2972
2973 case SvxBreak::PageBefore:
2974 pBreakBefore = sCSS1_PV_always;
2975 break;
2976
2977 case SvxBreak::PageAfter:
2978 pBreakAfter= sCSS1_PV_always;
2979 break;
2980
2981 default:
2982 ;
2983 }
2984 }
2985 if( pPDescItem )
2986 {
2987 const SwPageDesc *pPDesc = pPDescItem->GetPageDesc();
2988 if( pPDesc )
2989 {
2990 switch( pPDesc->GetPoolFormatId() )
2991 {
2992 case RES_POOLPAGE_LEFT: pBreakBefore = sCSS1_PV_left; break;
2993 case RES_POOLPAGE_RIGHT: pBreakBefore = sCSS1_PV_right; break;
2994 default: pBreakBefore = sCSS1_PV_always; break;
2995 }
2996 }
2997 else if( !pBreakBefore )
2998 {
2999 pBreakBefore = sCSS1_PV_auto;
3000 }
3001 }
3002
3003 if (rHTMLWrt.mbSkipHeaderFooter)
3004 // No page break when writing only a fragment.
3005 return rWrt;
3006
3007 if( pBreakBefore )
3008 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_before,
3009 pBreakBefore );
3010 if( pBreakAfter )
3011 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_after,
3012 pBreakAfter );
3013
3014 return rWrt;
3015 }
3016
OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep(Writer & rWrt,const SfxItemSet & rItemSet,bool bDeep)3017 static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt,
3018 const SfxItemSet& rItemSet,
3019 bool bDeep )
3020 {
3021 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
3022 const SfxPoolItem *pItem;
3023 const SvxFormatBreakItem *pBreakItem = nullptr;
3024 if( SfxItemState::SET==rItemSet.GetItemState( RES_BREAK, bDeep, &pItem ))
3025 pBreakItem = static_cast<const SvxFormatBreakItem *>(pItem);
3026
3027 const SwFormatPageDesc *pPDescItem = nullptr;
3028 if( ( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ||
3029 !rHTMLWrt.m_bCSS1IgnoreFirstPageDesc ||
3030 rHTMLWrt.m_pStartNdIdx->GetIndex() !=
3031 rHTMLWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex() ) &&
3032 SfxItemState::SET==rItemSet.GetItemState( RES_PAGEDESC, bDeep, &pItem ))
3033 pPDescItem = static_cast<const SwFormatPageDesc*>(pItem);
3034
3035 const SvxFormatKeepItem *pKeepItem = nullptr;
3036 if( SfxItemState::SET==rItemSet.GetItemState( RES_KEEP, bDeep, &pItem ))
3037 pKeepItem = static_cast<const SvxFormatKeepItem *>(pItem);
3038
3039 if( pBreakItem || pPDescItem || pKeepItem )
3040 OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( rWrt, pBreakItem,
3041 pPDescItem, pKeepItem );
3042
3043 return rWrt;
3044 }
3045
3046 // Wrapper for OutCSS1_SfxItemSet etc.
OutCSS1_SvxBrush(Writer & rWrt,const SfxPoolItem & rHt)3047 static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt )
3048 {
3049 OutCSS1_SvxBrush( rWrt, rHt, Css1Background::Attr, nullptr );
3050 return rWrt;
3051 }
3052
OutCSS1_SvxBrush(Writer & rWrt,const SfxPoolItem & rHt,Css1Background nMode,const OUString * pGraphicName)3053 static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt,
3054 Css1Background nMode,
3055 const OUString* pGraphicName)
3056 {
3057 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
3058
3059 // The Character-Attribute is skipped, if we are about to
3060 // exporting options
3061 if( rHt.Which() < RES_CHRATR_END &&
3062 rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
3063 return rWrt;
3064
3065 // start getting a few values
3066 // const Brush &rBrush = static_cast<const SvxBrushItem &>(rHt).GetBrush();
3067 const Color & rColor = static_cast<const SvxBrushItem &>(rHt).GetColor();
3068 OUString aLink = pGraphicName ? *pGraphicName
3069 : static_cast<const SvxBrushItem &>(rHt).GetGraphicLink();
3070 SvxGraphicPosition ePos = static_cast<const SvxBrushItem &>(rHt).GetGraphicPos();
3071 if( Css1Background::Page == nMode && !rHTMLWrt.mbEmbedImages )
3072 {
3073 // page style images are exported if not tiled
3074 if( aLink.isEmpty() || GPOS_TILED==ePos )
3075 return rWrt;
3076 }
3077
3078 // get the color
3079 bool bColor = false;
3080 /// set <bTransparent> to true, if color is "no fill"/"auto fill"
3081 bool bTransparent = (rColor == COL_TRANSPARENT);
3082 Color aColor;
3083 if( !bTransparent )
3084 {
3085 aColor = rColor;
3086 bColor = true;
3087 }
3088
3089 // and now the Graphic
3090 OUString aGraphicInBase64;
3091
3092 // Embedded Graphic -> export WriteEmbedded
3093 const Graphic* pGrf = nullptr;
3094 if( rHTMLWrt.mbEmbedImages || aLink.isEmpty())
3095 {
3096 pGrf = static_cast<const SvxBrushItem &>(rHt).GetGraphic();
3097 if( pGrf )
3098 {
3099 if( !XOutBitmap::GraphicToBase64(*pGrf, aGraphicInBase64) )
3100 {
3101 rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD;
3102 }
3103 }
3104 aLink.clear();
3105 }
3106 else if( !pGraphicName && rHTMLWrt.m_bCfgCpyLinkedGrfs )
3107 {
3108 OUString aGraphicAsLink = aLink;
3109 rWrt.CopyLocalFileToINet( aGraphicAsLink );
3110 aLink = aGraphicAsLink;
3111 }
3112 // In tables we only export something if there is a Graphic
3113 if( Css1Background::Table==nMode && !pGrf && !aLink.isEmpty())
3114 return rWrt;
3115
3116 // if necessary, add the orientation of the Graphic
3117 const char *pRepeat = nullptr, *pHori = nullptr, *pVert = nullptr;
3118 if( pGrf || !aLink.isEmpty() )
3119 {
3120 if( GPOS_TILED==ePos )
3121 {
3122 pRepeat = sCSS1_PV_repeat;
3123 }
3124 else
3125 {
3126 switch( ePos )
3127 {
3128 case GPOS_LT:
3129 case GPOS_MT:
3130 case GPOS_RT:
3131 pHori = sCSS1_PV_top;
3132 break;
3133
3134 case GPOS_LM:
3135 case GPOS_MM:
3136 case GPOS_RM:
3137 pHori = sCSS1_PV_middle;
3138 break;
3139
3140 case GPOS_LB:
3141 case GPOS_MB:
3142 case GPOS_RB:
3143 pHori = sCSS1_PV_bottom;
3144 break;
3145
3146 default:
3147 ;
3148 }
3149
3150 switch( ePos )
3151 {
3152 case GPOS_LT:
3153 case GPOS_LM:
3154 case GPOS_LB:
3155 pVert = sCSS1_PV_left;
3156 break;
3157
3158 case GPOS_MT:
3159 case GPOS_MM:
3160 case GPOS_MB:
3161 pVert = sCSS1_PV_center;
3162 break;
3163
3164 case GPOS_RT:
3165 case GPOS_RM:
3166 case GPOS_RB:
3167 pVert = sCSS1_PV_right;
3168 break;
3169
3170 default:
3171 ;
3172 }
3173
3174 if( pHori || pVert )
3175 pRepeat = sCSS1_PV_no_repeat;
3176 }
3177 }
3178
3179 // now build the string
3180 OUString sOut;
3181 if( !pGrf && aLink.isEmpty() && !bColor )
3182 {
3183 // no color and no Link, but a transparent Brush
3184 if( bTransparent && Css1Background::Fly != nMode )
3185 sOut += OStringToOUString(sCSS1_PV_transparent, RTL_TEXTENCODING_ASCII_US);
3186 }
3187 else
3188 {
3189 if( bColor )
3190 {
3191 OString sTmp(GetCSS1_Color(aColor));
3192 sOut += OStringToOUString(sTmp, RTL_TEXTENCODING_ASCII_US);
3193 }
3194
3195 if( pGrf || !aLink.isEmpty() )
3196 {
3197 if( bColor )
3198 sOut += " ";
3199
3200 if(pGrf)
3201 {
3202 sOut += OStringToOUString(sCSS1_url, RTL_TEXTENCODING_ASCII_US) +
3203 "(\'" OOO_STRING_SVTOOLS_HTML_O_data ":" + aGraphicInBase64 + "\')";
3204 }
3205 else
3206 {
3207 sOut += OStringToOUString(sCSS1_url, RTL_TEXTENCODING_ASCII_US)+
3208 "(" + URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(),
3209 aLink) + ")";
3210 }
3211
3212 if( pRepeat )
3213 {
3214 sOut += " " + OStringToOUString(pRepeat, RTL_TEXTENCODING_ASCII_US);
3215 }
3216
3217 if( pHori )
3218 {
3219 sOut += " " + OStringToOUString(pHori, RTL_TEXTENCODING_ASCII_US);
3220 }
3221 if( pVert )
3222 {
3223 sOut += " " + OStringToOUString(pVert, RTL_TEXTENCODING_ASCII_US);
3224 }
3225
3226 sOut += " " + OStringToOUString(sCSS1_PV_scroll, RTL_TEXTENCODING_ASCII_US) + " ";
3227 }
3228 }
3229
3230 if( !sOut.isEmpty() )
3231 rHTMLWrt.OutCSS1_Property( sCSS1_P_background, sOut );
3232
3233 return rWrt;
3234 }
3235
OutCSS1_SvxBorderLine(SwHTMLWriter & rHTMLWrt,const char * pProperty,const SvxBorderLine * pLine)3236 static void OutCSS1_SvxBorderLine( SwHTMLWriter& rHTMLWrt,
3237 const char *pProperty,
3238 const SvxBorderLine *pLine )
3239 {
3240 if( !pLine || pLine->isEmpty() )
3241 {
3242 rHTMLWrt.OutCSS1_PropertyAscii( pProperty, sCSS1_PV_none );
3243 return;
3244 }
3245
3246 sal_Int32 nWidth = pLine->GetWidth();
3247
3248 OStringBuffer sOut;
3249 if( Application::GetDefaultDevice() &&
3250 nWidth <= Application::GetDefaultDevice()->PixelToLogic(
3251 Size( 1, 1 ), MapMode( MapUnit::MapTwip) ).Width() )
3252 {
3253 // If the width is smaller than one pixel, then export as 1px
3254 // so that Netscape and IE show the line.
3255 sOut.append("1px");
3256 }
3257 else
3258 {
3259 nWidth *= 5; // 1/100pt
3260
3261 // width in n.nn pt
3262 sOut.append(OString::number(nWidth / 100) + "." + OString::number((nWidth/10) % 10) +
3263 OString::number(nWidth % 10) + sCSS1_UNIT_pt);
3264 }
3265
3266 // Line-Style: solid or double
3267 sOut.append(' ');
3268 switch (pLine->GetBorderLineStyle())
3269 {
3270 case SvxBorderLineStyle::SOLID:
3271 sOut.append(sCSS1_PV_solid);
3272 break;
3273 case SvxBorderLineStyle::DOTTED:
3274 sOut.append(sCSS1_PV_dotted);
3275 break;
3276 case SvxBorderLineStyle::DASHED:
3277 sOut.append(sCSS1_PV_dashed);
3278 break;
3279 case SvxBorderLineStyle::DOUBLE:
3280 case SvxBorderLineStyle::THINTHICK_SMALLGAP:
3281 case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
3282 case SvxBorderLineStyle::THINTHICK_LARGEGAP:
3283 case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
3284 case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
3285 case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
3286 sOut.append(sCSS1_PV_double);
3287 break;
3288 case SvxBorderLineStyle::EMBOSSED:
3289 sOut.append(sCSS1_PV_ridge);
3290 break;
3291 case SvxBorderLineStyle::ENGRAVED:
3292 sOut.append(sCSS1_PV_groove);
3293 break;
3294 case SvxBorderLineStyle::INSET:
3295 sOut.append(sCSS1_PV_inset);
3296 break;
3297 case SvxBorderLineStyle::OUTSET:
3298 sOut.append(sCSS1_PV_outset);
3299 break;
3300 default:
3301 sOut.append(sCSS1_PV_none);
3302 }
3303 sOut.append(' ');
3304
3305 // and also the color
3306 sOut.append(GetCSS1_Color(pLine->GetColor()));
3307
3308 rHTMLWrt.OutCSS1_PropertyAscii(pProperty, sOut.makeStringAndClear());
3309 }
3310
OutCSS1_SvxBox(Writer & rWrt,const SfxPoolItem & rHt)3311 Writer& OutCSS1_SvxBox( Writer& rWrt, const SfxPoolItem& rHt )
3312 {
3313 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
3314
3315 // Avoid interference between character and paragraph attributes
3316 if( rHt.Which() < RES_CHRATR_END &&
3317 rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
3318 return rWrt;
3319
3320 if( rHt.Which() == RES_CHRATR_BOX )
3321 {
3322 if( rHTMLWrt.m_bTagOn )
3323 {
3324 // Inline-block to make the line height changing correspond to the character border
3325 rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_display, "inline-block");
3326 }
3327 else
3328 {
3329 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false );
3330 return rWrt;
3331 }
3332 }
3333
3334 const SvxBoxItem& rBoxItem = static_cast<const SvxBoxItem&>(rHt);
3335 const SvxBorderLine *pTop = rBoxItem.GetTop();
3336 const SvxBorderLine *pBottom = rBoxItem.GetBottom();
3337 const SvxBorderLine *pLeft = rBoxItem.GetLeft();
3338 const SvxBorderLine *pRight = rBoxItem.GetRight();
3339
3340 if( (pTop && pBottom && pLeft && pRight &&
3341 *pTop == *pBottom && *pTop == *pLeft && *pTop == *pRight) ||
3342 (!pTop && !pBottom && !pLeft && !pRight) )
3343 {
3344 // all Lines are set and equal, or all Lines are not set
3345 // => border : ...
3346 OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border, pTop );
3347 }
3348 else
3349 {
3350 // otherwise export all Lines separately
3351 OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_top, pTop );
3352 OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_bottom, pBottom );
3353 OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_left, pLeft );
3354 OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_right, pRight );
3355 }
3356
3357 tools::Long nTopDist = pTop ? rBoxItem.GetDistance( SvxBoxItemLine::TOP ) : 0;
3358 tools::Long nBottomDist = pBottom ? rBoxItem.GetDistance( SvxBoxItemLine::BOTTOM ) : 0;
3359 tools::Long nLeftDist = pLeft ? rBoxItem.GetDistance( SvxBoxItemLine::LEFT ) : 0;
3360 tools::Long nRightDist = pRight ? rBoxItem.GetDistance( SvxBoxItemLine::RIGHT ) : 0;
3361
3362 if( nTopDist == nBottomDist && nLeftDist == nRightDist )
3363 {
3364 OStringBuffer sVal;
3365 AddUnitPropertyValue(sVal, nTopDist, rHTMLWrt.GetCSS1Unit());
3366 if( nTopDist != nLeftDist )
3367 {
3368 sVal.append(' ');
3369 AddUnitPropertyValue(sVal, nLeftDist, rHTMLWrt.GetCSS1Unit());
3370 }
3371 rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_padding, sVal.makeStringAndClear());
3372 }
3373 else
3374 {
3375 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_top, nTopDist );
3376 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_bottom, nBottomDist );
3377 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_left, nLeftDist );
3378 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_right, nRightDist );
3379 }
3380
3381 return rWrt;
3382 }
3383
OutCSS1_SvxFrameDirection(Writer & rWrt,const SfxPoolItem & rHt)3384 static Writer& OutCSS1_SvxFrameDirection( Writer& rWrt, const SfxPoolItem& rHt )
3385 {
3386 SwHTMLWriter& rHTMLWrt = static_cast< SwHTMLWriter& >( rWrt );
3387
3388 // Language will be exported rules only
3389 if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_TEMPLATE ) )
3390 return rWrt;
3391
3392 SvxFrameDirection nDir =
3393 static_cast< const SvxFrameDirectionItem& >( rHt ).GetValue();
3394 const char* pStr = nullptr;
3395 switch( nDir )
3396 {
3397 case SvxFrameDirection::Horizontal_LR_TB:
3398 case SvxFrameDirection::Vertical_LR_TB:
3399 pStr = sCSS1_PV_ltr;
3400 break;
3401 case SvxFrameDirection::Horizontal_RL_TB:
3402 case SvxFrameDirection::Vertical_RL_TB:
3403 pStr = sCSS1_PV_rtl;
3404 break;
3405 case SvxFrameDirection::Environment:
3406 pStr = sCSS1_PV_inherit;
3407 break;
3408 default: break;
3409 }
3410
3411 if( pStr )
3412 rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_direction, pStr );
3413
3414 return rWrt;
3415 }
3416
3417 /*
3418 * Place here the table for the HTML-Function-Pointer to the
3419 * Export-Functions.
3420 * They are local structures, only needed within the HTML-DLL.
3421 */
3422
3423 SwAttrFnTab const aCSS1AttrFnTab = {
3424 /* RES_CHRATR_CASEMAP */ OutCSS1_SvxCaseMap,
3425 /* RES_CHRATR_CHARSETCOLOR */ nullptr,
3426 /* RES_CHRATR_COLOR */ OutCSS1_SvxColor,
3427 /* RES_CHRATR_CONTOUR */ nullptr,
3428 /* RES_CHRATR_CROSSEDOUT */ OutCSS1_SvxCrossedOut,
3429 /* RES_CHRATR_ESCAPEMENT */ nullptr,
3430 /* RES_CHRATR_FONT */ OutCSS1_SvxFont,
3431 /* RES_CHRATR_FONTSIZE */ OutCSS1_SvxFontHeight,
3432 /* RES_CHRATR_KERNING */ OutCSS1_SvxKerning,
3433 /* RES_CHRATR_LANGUAGE */ OutCSS1_SvxLanguage,
3434 /* RES_CHRATR_POSTURE */ OutCSS1_SvxPosture,
3435 /* RES_CHRATR_UNUSED1*/ nullptr,
3436 /* RES_CHRATR_SHADOWED */ nullptr,
3437 /* RES_CHRATR_UNDERLINE */ OutCSS1_SvxUnderline,
3438 /* RES_CHRATR_WEIGHT */ OutCSS1_SvxFontWeight,
3439 /* RES_CHRATR_WORDLINEMODE */ nullptr,
3440 /* RES_CHRATR_AUTOKERN */ nullptr,
3441 /* RES_CHRATR_BLINK */ OutCSS1_SvxBlink,
3442 /* RES_CHRATR_NOHYPHEN */ nullptr, // new: don't separate
3443 /* RES_CHRATR_UNUSED2 */ nullptr,
3444 /* RES_CHRATR_BACKGROUND */ OutCSS1_SvxBrush, // new: character background
3445 /* RES_CHRATR_CJK_FONT */ OutCSS1_SvxFont,
3446 /* RES_CHRATR_CJK_FONTSIZE */ OutCSS1_SvxFontHeight,
3447 /* RES_CHRATR_CJK_LANGUAGE */ OutCSS1_SvxLanguage,
3448 /* RES_CHRATR_CJK_POSTURE */ OutCSS1_SvxPosture,
3449 /* RES_CHRATR_CJK_WEIGHT */ OutCSS1_SvxFontWeight,
3450 /* RES_CHRATR_CTL_FONT */ OutCSS1_SvxFont,
3451 /* RES_CHRATR_CTL_FONTSIZE */ OutCSS1_SvxFontHeight,
3452 /* RES_CHRATR_CTL_LANGUAGE */ OutCSS1_SvxLanguage,
3453 /* RES_CHRATR_CTL_POSTURE */ OutCSS1_SvxPosture,
3454 /* RES_CHRATR_CTL_WEIGHT */ OutCSS1_SvxFontWeight,
3455 /* RES_CHRATR_ROTATE */ nullptr,
3456 /* RES_CHRATR_EMPHASIS_MARK */ nullptr,
3457 /* RES_CHRATR_TWO_LINES */ nullptr,
3458 /* RES_CHRATR_SCALEW */ nullptr,
3459 /* RES_CHRATR_RELIEF */ nullptr,
3460 /* RES_CHRATR_HIDDEN */ OutCSS1_SvxHidden,
3461 /* RES_CHRATR_OVERLINE */ OutCSS1_SvxOverline,
3462 /* RES_CHRATR_RSID */ nullptr,
3463 /* RES_CHRATR_BOX */ OutCSS1_SvxBox,
3464 /* RES_CHRATR_SHADOW */ nullptr,
3465 /* RES_CHRATR_HIGHLIGHT */ nullptr,
3466 /* RES_CHRATR_GRABBAG */ nullptr,
3467 /* RES_CHRATR_BIDIRTL */ nullptr,
3468 /* RES_CHRATR_IDCTHINT */ nullptr,
3469
3470 /* RES_TXTATR_REFMARK */ nullptr,
3471 /* RES_TXTATR_TOXMARK */ nullptr,
3472 /* RES_TXTATR_META */ nullptr,
3473 /* RES_TXTATR_METAFIELD */ nullptr,
3474 /* RES_TXTATR_AUTOFMT */ nullptr,
3475 /* RES_TXTATR_INETFMT */ nullptr,
3476 /* RES_TXTATR_CHARFMT */ nullptr,
3477 /* RES_TXTATR_CJK_RUBY */ nullptr,
3478 /* RES_TXTATR_UNKNOWN_CONTAINER */ nullptr,
3479 /* RES_TXTATR_INPUTFIELD */ nullptr,
3480
3481 /* RES_TXTATR_FIELD */ nullptr,
3482 /* RES_TXTATR_FLYCNT */ nullptr,
3483 /* RES_TXTATR_FTN */ nullptr,
3484 /* RES_TXTATR_ANNOTATION */ nullptr,
3485 /* RES_TXTATR_DUMMY3 */ nullptr,
3486 /* RES_TXTATR_DUMMY1 */ nullptr, // Dummy:
3487 /* RES_TXTATR_DUMMY2 */ nullptr, // Dummy:
3488
3489 /* RES_PARATR_LINESPACING */ OutCSS1_SvxLineSpacing,
3490 /* RES_PARATR_ADJUST */ OutCSS1_SvxAdjust,
3491 /* RES_PARATR_SPLIT */ OutCSS1_SvxFormatSplit,
3492 /* RES_PARATR_ORPHANS */ OutCSS1_SvxOrphans,
3493 /* RES_PARATR_WIDOWS */ OutCSS1_SvxWidows,
3494 /* RES_PARATR_TABSTOP */ nullptr,
3495 /* RES_PARATR_HYPHENZONE*/ nullptr,
3496 /* RES_PARATR_DROP */ OutCSS1_SwFormatDrop,
3497 /* RES_PARATR_REGISTER */ nullptr, // new: register-true
3498 /* RES_PARATR_NUMRULE */ nullptr,
3499 /* RES_PARATR_SCRIPTSPACE */ nullptr,
3500 /* RES_PARATR_HANGINGPUNCTUATION */ nullptr,
3501 /* RES_PARATR_FORBIDDEN_RULES */ nullptr, // new
3502 /* RES_PARATR_VERTALIGN */ nullptr, // new
3503 /* RES_PARATR_SNAPTOGRID*/ nullptr, // new
3504 /* RES_PARATR_CONNECT_TO_BORDER */ nullptr, // new
3505 /* RES_PARATR_OUTLINELEVEL */ nullptr, // new since cws outlinelevel
3506 /* RES_PARATR_RSID */ nullptr, // new
3507 /* RES_PARATR_GRABBAG */ nullptr,
3508
3509 /* RES_PARATR_LIST_ID */ nullptr, // new
3510 /* RES_PARATR_LIST_LEVEL */ nullptr, // new
3511 /* RES_PARATR_LIST_ISRESTART */ nullptr, // new
3512 /* RES_PARATR_LIST_RESTARTVALUE */ nullptr, // new
3513 /* RES_PARATR_LIST_ISCOUNTED */ nullptr, // new
3514 /* RES_PARATR_LIST_AUTOFMT */ nullptr, // new
3515
3516 /* RES_FILL_ORDER */ nullptr,
3517 /* RES_FRM_SIZE */ nullptr,
3518 /* RES_PAPER_BIN */ nullptr,
3519 /* RES_LR_SPACE */ OutCSS1_SvxLRSpace,
3520 /* RES_UL_SPACE */ OutCSS1_SvxULSpace,
3521 /* RES_PAGEDESC */ nullptr,
3522 /* RES_BREAK */ nullptr,
3523 /* RES_CNTNT */ nullptr,
3524 /* RES_HEADER */ nullptr,
3525 /* RES_FOOTER */ nullptr,
3526 /* RES_PRINT */ nullptr,
3527 /* RES_OPAQUE */ nullptr,
3528 /* RES_PROTECT */ nullptr,
3529 /* RES_SURROUND */ nullptr,
3530 /* RES_VERT_ORIENT */ nullptr,
3531 /* RES_HORI_ORIENT */ nullptr,
3532 /* RES_ANCHOR */ nullptr,
3533 /* RES_BACKGROUND */ OutCSS1_SvxBrush,
3534 /* RES_BOX */ OutCSS1_SvxBox,
3535 /* RES_SHADOW */ nullptr,
3536 /* RES_FRMMACRO */ nullptr,
3537 /* RES_COL */ nullptr,
3538 /* RES_KEEP */ nullptr,
3539 /* RES_URL */ nullptr,
3540 /* RES_EDIT_IN_READONLY */ nullptr,
3541 /* RES_LAYOUT_SPLIT */ nullptr,
3542 /* RES_CHAIN */ nullptr,
3543 /* RES_TEXTGRID */ nullptr,
3544 /* RES_LINENUMBER */ nullptr,
3545 /* RES_FTN_AT_TXTEND */ nullptr,
3546 /* RES_END_AT_TXTEND */ nullptr,
3547 /* RES_COLUMNBALANCE */ nullptr,
3548 /* RES_FRAMEDIR */ OutCSS1_SvxFrameDirection,
3549 /* RES_HEADER_FOOTER_EAT_SPACING */ nullptr,
3550 /* RES_ROW_SPLIT */ nullptr,
3551 /* RES_FOLLOW_TEXT_FLOW */ nullptr,
3552 /* RES_COLLAPSING_BORDERS */ nullptr,
3553 /* RES_WRAP_INFLUENCE_ON_OBJPOS */ nullptr,
3554 /* RES_AUTO_STYLE */ nullptr,
3555 /* RES_FRMATR_STYLE_NAME */ nullptr,
3556 /* RES_FRMATR_CONDITIONAL_STYLE_NAME */ nullptr,
3557 /* RES_FRMATR_GRABBAG */ nullptr,
3558 /* RES_TEXT_VERT_ADJUST */ nullptr,
3559
3560 /* RES_GRFATR_MIRRORGRF */ nullptr,
3561 /* RES_GRFATR_CROPGRF */ nullptr,
3562 /* RES_GRFATR_ROTATION */ nullptr,
3563 /* RES_GRFATR_LUMINANCE */ nullptr,
3564 /* RES_GRFATR_CONTRAST */ nullptr,
3565 /* RES_GRFATR_CHANNELR */ nullptr,
3566 /* RES_GRFATR_CHANNELG */ nullptr,
3567 /* RES_GRFATR_CHANNELB */ nullptr,
3568 /* RES_GRFATR_GAMMA */ nullptr,
3569 /* RES_GRFATR_INVERT */ nullptr,
3570 /* RES_GRFATR_TRANSPARENCY */ nullptr,
3571 /* RES_GRFATR_DRWAMODE */ nullptr,
3572 /* RES_GRFATR_DUMMY1 */ nullptr,
3573 /* RES_GRFATR_DUMMY2 */ nullptr,
3574 /* RES_GRFATR_DUMMY3 */ nullptr,
3575 /* RES_GRFATR_DUMMY4 */ nullptr,
3576 /* RES_GRFATR_DUMMY5 */ nullptr,
3577
3578 /* RES_BOXATR_FORMAT */ nullptr,
3579 /* RES_BOXATR_FORMULA */ nullptr,
3580 /* RES_BOXATR_VALUE */ nullptr
3581 };
3582
3583 static_assert(SAL_N_ELEMENTS(aCSS1AttrFnTab) == RES_BOXATR_END);
3584
OutCSS1_SfxItemSet(const SfxItemSet & rItemSet,bool bDeep)3585 void SwHTMLWriter::OutCSS1_SfxItemSet( const SfxItemSet& rItemSet,
3586 bool bDeep )
3587 {
3588 // print ItemSet, including all attributes
3589 Out_SfxItemSet( aCSS1AttrFnTab, *this, rItemSet, bDeep );
3590
3591 // some Attributes require special treatment
3592 const SfxPoolItem *pItem = nullptr;
3593
3594 // Underline, Overline, CrossedOut and Blink form together a CSS1-Property
3595 // (doesn't work of course for Hints)
3596 if( !IsCSS1Source(CSS1_OUTMODE_HINT) )
3597 {
3598 const SvxUnderlineItem *pUnderlineItem = nullptr;
3599 if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_UNDERLINE, bDeep, &pItem ))
3600 pUnderlineItem = static_cast<const SvxUnderlineItem *>(pItem);
3601
3602 const SvxOverlineItem *pOverlineItem = nullptr;
3603 if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_OVERLINE, bDeep, &pItem ))
3604 pOverlineItem = static_cast<const SvxOverlineItem *>(pItem);
3605
3606 const SvxCrossedOutItem *pCrossedOutItem = nullptr;
3607 if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_CROSSEDOUT, bDeep, &pItem ))
3608 pCrossedOutItem = static_cast<const SvxCrossedOutItem *>(pItem);
3609
3610 const SvxBlinkItem *pBlinkItem = nullptr;
3611 if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_BLINK, bDeep, &pItem ))
3612 pBlinkItem = static_cast<const SvxBlinkItem *>(pItem);
3613
3614 if( pUnderlineItem || pOverlineItem || pCrossedOutItem || pBlinkItem )
3615 OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( *this, pUnderlineItem,
3616 pOverlineItem,
3617 pCrossedOutItem,
3618 pBlinkItem );
3619
3620 OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( *this, rItemSet, bDeep );
3621 }
3622
3623 if( m_bFirstCSS1Property )
3624 return;
3625
3626 // if a Property was exported as part of a Style-Option,
3627 // the Option still needs to be finished
3628 OStringBuffer sOut;
3629 switch( m_nCSS1OutMode & CSS1_OUTMODE_ANY_OFF )
3630 {
3631 case CSS1_OUTMODE_SPAN_TAG_OFF:
3632 sOut.append(sCSS1_span_tag_end);
3633 break;
3634
3635 case CSS1_OUTMODE_STYLE_OPT_OFF:
3636 sOut.append(cCSS1_style_opt_end);
3637 break;
3638
3639 case CSS1_OUTMODE_RULE_OFF:
3640 sOut.append(sCSS1_rule_end);
3641 break;
3642 }
3643 if (!sOut.isEmpty())
3644 Strm().WriteOString( sOut.makeStringAndClear() );
3645 }
3646
OutCSS1_HintSpanTag(Writer & rWrt,const SfxPoolItem & rHt)3647 Writer& OutCSS1_HintSpanTag( Writer& rWrt, const SfxPoolItem& rHt )
3648 {
3649 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
3650
3651 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_SPAN_TAG |
3652 CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_HINT, nullptr );
3653
3654 Out( aCSS1AttrFnTab, rHt, rWrt );
3655
3656 if( !rHTMLWrt.m_bFirstCSS1Property && rHTMLWrt.m_bTagOn )
3657 rWrt.Strm().WriteCharPtr( sCSS1_span_tag_end );
3658
3659 return rWrt;
3660 }
3661
OutCSS1_HintStyleOpt(Writer & rWrt,const SfxPoolItem & rHt)3662 Writer& OutCSS1_HintStyleOpt( Writer& rWrt, const SfxPoolItem& rHt )
3663 {
3664 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
3665
3666 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT_ON |
3667 CSS1_OUTMODE_ENCODE|
3668 CSS1_OUTMODE_HINT, nullptr );
3669
3670 Out( aCSS1AttrFnTab, rHt, rWrt );
3671
3672 if( !rHTMLWrt.m_bFirstCSS1Property )
3673 rWrt.Strm().WriteChar( '\"' );
3674
3675 return rWrt;
3676 }
3677
3678 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3679