summaryrefslogtreecommitdiffstats
path: root/sw/source/filter/html/svxcss1.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/source/filter/html/svxcss1.cxx
parentInitial commit. (diff)
downloadlibreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz
libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/filter/html/svxcss1.cxx')
-rw-r--r--sw/source/filter/html/svxcss1.cxx3153
1 files changed, 3153 insertions, 0 deletions
diff --git a/sw/source/filter/html/svxcss1.cxx b/sw/source/filter/html/svxcss1.cxx
new file mode 100644
index 0000000000..d75cc487da
--- /dev/null
+++ b/sw/source/filter/html/svxcss1.cxx
@@ -0,0 +1,3153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <algorithm>
+#include <cmath>
+#include <limits>
+#include <memory>
+#include <stdlib.h>
+
+#include <svx/svxids.hrc>
+#include <i18nlangtag/languagetag.hxx>
+#include <svtools/ctrltool.hxx>
+#include <svl/urihelper.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/adjustitem.hxx>
+#include <editeng/blinkitem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/borderline.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/langitem.hxx>
+#include <svl/itempool.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/orphitem.hxx>
+#include <utility>
+#include <vcl/svapp.hxx>
+#include <sal/log.hxx>
+#include <osl/diagnose.h>
+#include <o3tl/string_view.hxx>
+
+#include <hintids.hxx>
+
+#include "css1kywd.hxx"
+#include "svxcss1.hxx"
+#include "htmlnum.hxx"
+
+using namespace ::com::sun::star;
+
+/// type of functions to parse CSS1 properties
+typedef void (*FnParseCSS1Prop)( const CSS1Expression *pExpr,
+ SfxItemSet& rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser );
+
+CSS1PropertyEnum const aFontSizeTable[] =
+{
+ { "xx-small", 0 },
+ { "x-small", 1 },
+ { "small", 2 },
+ { "medium", 3 },
+ { "large", 4 },
+ { "x-large", 5 },
+ { "xx-large", 6 },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aFontWeightTable[] =
+{
+ { "extra-light", WEIGHT_NORMAL }, // WEIGHT_ULTRALIGHT (OBS)
+ { "light", WEIGHT_NORMAL }, // WEIGHT_LIGHT (OBSOLETE)
+ { "demi-light", WEIGHT_NORMAL }, // WEIGHT_SEMILIGHT (OBS)
+ { "medium", WEIGHT_NORMAL }, // WEIGHT_MEDIUM (OBS)
+ { "normal", WEIGHT_NORMAL }, // WEIGHT_MEDIUM
+ { "demi-bold", WEIGHT_NORMAL }, // WEIGHT_SEMIBOLD (OBS)
+ { "bold", WEIGHT_BOLD }, // WEIGHT_BOLD (OBSOLETE)
+ { "extra-bold", WEIGHT_BOLD }, // WEIGHT_ULTRABOLD (OBS)
+ { "bolder", WEIGHT_BOLD },
+ { "lighter", WEIGHT_NORMAL },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aFontStyleTable[] =
+{
+ { "normal", ITALIC_NONE },
+ { "italic", ITALIC_NORMAL },
+ { "oblique", ITALIC_NORMAL },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aFontVariantTable[] =
+{
+ { "normal", sal_uInt16(SvxCaseMap::NotMapped) },
+ { "small-caps", sal_uInt16(SvxCaseMap::SmallCaps) },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aTextTransformTable[] =
+{
+ { "uppercase", sal_uInt16(SvxCaseMap::Uppercase) },
+ { "lowercase", sal_uInt16(SvxCaseMap::Lowercase) },
+ { "capitalize", sal_uInt16(SvxCaseMap::Capitalize) },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aDirectionTable[] =
+{
+ { "ltr", sal_uInt16(SvxFrameDirection::Horizontal_LR_TB) },
+ { "rtl", sal_uInt16(SvxFrameDirection::Horizontal_RL_TB) },
+ { "inherit", sal_uInt16(SvxFrameDirection::Environment) },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aBGRepeatTable[] =
+{
+ { "repeat", GPOS_TILED },
+ { "repeat-x", GPOS_TILED },
+ { "repeat-y", GPOS_TILED },
+ { "no-repeat", GPOS_NONE },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aBGHoriPosTable[] =
+{
+ { "left", GPOS_LT },
+ { "center", GPOS_MT },
+ { "right", GPOS_RT },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aBGVertPosTable[] =
+{
+ { "top", GPOS_LT },
+ { "middle", GPOS_LM },
+ { "bottom", GPOS_LB },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aTextAlignTable[] =
+{
+ { "left", sal_uInt16(SvxAdjust::Left) },
+ { "center", sal_uInt16(SvxAdjust::Center) },
+ { "right", sal_uInt16(SvxAdjust::Right) },
+ { "justify", sal_uInt16(SvxAdjust::Block) },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aBorderWidthTable[] =
+{
+ { "thin", 0 }, // DEF_LINE_WIDTH_0 / DEF_DOUBLE_LINE0
+ { "medium", 1 }, // DEF_LINE_WIDTH_1 / DEF_DOUBLE_LINE1
+ { "thick", 2 }, // DEF_LINE_WIDTH_2 / DEF_DOUBLE_LINE2
+ { nullptr, 0 }
+};
+
+namespace {
+
+enum CSS1BorderStyle { CSS1_BS_NONE, CSS1_BS_SINGLE, CSS1_BS_DOUBLE, CSS1_BS_DOTTED, CSS1_BS_DASHED, CSS1_BS_GROOVE, CSS1_BS_RIDGE, CSS1_BS_INSET, CSS1_BS_OUTSET };
+
+}
+
+CSS1PropertyEnum const aBorderStyleTable[] =
+{
+ { "none", CSS1_BS_NONE },
+ { "dotted", CSS1_BS_DOTTED },
+ { "dashed", CSS1_BS_DASHED },
+ { "solid", CSS1_BS_SINGLE },
+ { "double", CSS1_BS_DOUBLE },
+ { "groove", CSS1_BS_GROOVE },
+ { "ridge", CSS1_BS_RIDGE },
+ { "inset", CSS1_BS_INSET },
+ { "outset", CSS1_BS_OUTSET },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aFloatTable[] =
+{
+ { "left", sal_uInt16(SvxAdjust::Left) },
+ { "right", sal_uInt16(SvxAdjust::Right) },
+ { "none", sal_uInt16(SvxAdjust::End) },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aPositionTable[] =
+{
+ { "absolute", SVX_CSS1_POS_ABSOLUTE },
+ { "relative", SVX_CSS1_POS_RELATIVE },
+ { "static", SVX_CSS1_POS_STATIC },
+ { nullptr, 0 }
+};
+
+// Feature: PrintExt
+CSS1PropertyEnum const aSizeTable[] =
+{
+ { "auto", SVX_CSS1_STYPE_AUTO },
+ { "landscape", SVX_CSS1_STYPE_LANDSCAPE },
+ { "portrait", SVX_CSS1_STYPE_PORTRAIT },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aPageBreakTable[] =
+{
+ { "auto", SVX_CSS1_PBREAK_AUTO },
+ { "always", SVX_CSS1_PBREAK_ALWAYS },
+ { "avoid", SVX_CSS1_PBREAK_AVOID },
+ { "left", SVX_CSS1_PBREAK_LEFT },
+ { "right", SVX_CSS1_PBREAK_RIGHT },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aNumberStyleTable[] =
+{
+ { "decimal", SVX_NUM_ARABIC },
+ { "lower-alpha", SVX_NUM_CHARS_LOWER_LETTER },
+ { "lower-latin", SVX_NUM_CHARS_LOWER_LETTER },
+ { "lower-roman", SVX_NUM_ROMAN_LOWER },
+ { "upper-alpha", SVX_NUM_CHARS_UPPER_LETTER },
+ { "upper-latin", SVX_NUM_CHARS_UPPER_LETTER },
+ { "upper-roman", SVX_NUM_ROMAN_UPPER },
+ { nullptr, 0 }
+};
+
+CSS1PropertyEnum const aBulletStyleTable[] =
+{
+ { "circle", HTML_BULLETCHAR_CIRCLE },
+ { "disc", HTML_BULLETCHAR_DISC },
+ { "square", HTML_BULLETCHAR_SQUARE },
+ { nullptr, 0 }
+};
+
+sal_uInt16 const aBorderWidths[] =
+{
+ SvxBorderLineWidth::Hairline,
+ SvxBorderLineWidth::VeryThin,
+ SvxBorderLineWidth::Thin
+};
+
+#undef SBORDER_ENTRY
+#undef DBORDER_ENTRY
+
+namespace {
+
+struct SvxCSS1ItemIds
+{
+ sal_uInt16 nFont;
+ sal_uInt16 nFontCJK;
+ sal_uInt16 nFontCTL;
+ sal_uInt16 nPosture;
+ sal_uInt16 nPostureCJK;
+ sal_uInt16 nPostureCTL;
+ sal_uInt16 nWeight;
+ sal_uInt16 nWeightCJK;
+ sal_uInt16 nWeightCTL;
+ sal_uInt16 nFontHeight;
+ sal_uInt16 nFontHeightCJK;
+ sal_uInt16 nFontHeightCTL;
+ sal_uInt16 nUnderline;
+ sal_uInt16 nOverline;
+ sal_uInt16 nCrossedOut;
+ sal_uInt16 nColor;
+ sal_uInt16 nKerning;
+ sal_uInt16 nCaseMap;
+ sal_uInt16 nBlink;
+
+ sal_uInt16 nLineSpacing;
+ sal_uInt16 nAdjust;
+ sal_uInt16 nWidows;
+ sal_uInt16 nOrphans;
+ sal_uInt16 nFormatSplit;
+
+ // this looks a bit superfluous? TypedWhichId<SvxLRSpaceItem> nLRSpace{0};
+ TypedWhichId<SvxULSpaceItem> nULSpace{0};
+ sal_uInt16 nBox;
+ sal_uInt16 nBrush;
+
+ sal_uInt16 nLanguage;
+ sal_uInt16 nLanguageCJK;
+ sal_uInt16 nLanguageCTL;
+ sal_uInt16 nDirection;
+};
+
+}
+
+static SvxCSS1ItemIds aItemIds;
+
+struct SvxCSS1BorderInfo
+{
+ Color aColor;
+ sal_uInt16 nAbsWidth;
+ sal_uInt16 nNamedWidth;
+ CSS1BorderStyle eStyle;
+
+ SvxCSS1BorderInfo() :
+ aColor( COL_BLACK ), nAbsWidth( USHRT_MAX ),
+ nNamedWidth( USHRT_MAX ), eStyle( CSS1_BS_NONE )
+ {}
+
+ void SetBorderLine( SvxBoxItemLine nLine, SvxBoxItem &rBoxItem ) const;
+};
+
+void SvxCSS1BorderInfo::SetBorderLine( SvxBoxItemLine nLine, SvxBoxItem &rBoxItem ) const
+{
+ if( CSS1_BS_NONE==eStyle || nAbsWidth==0 ||
+ (nAbsWidth==USHRT_MAX && nNamedWidth==USHRT_MAX) )
+ {
+ rBoxItem.SetLine( nullptr, nLine );
+ return;
+ }
+
+ ::editeng::SvxBorderLine aBorderLine( &aColor );
+
+ // Line style double or single?
+ switch ( eStyle )
+ {
+ case CSS1_BS_SINGLE:
+ aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::SOLID);
+ break;
+ case CSS1_BS_DOUBLE:
+ aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::DOUBLE);
+ break;
+ case CSS1_BS_DOTTED:
+ aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::DOTTED);
+ break;
+ case CSS1_BS_DASHED:
+ aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::DASHED);
+ break;
+ case CSS1_BS_GROOVE:
+ aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::ENGRAVED);
+ break;
+ case CSS1_BS_RIDGE:
+ aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::EMBOSSED);
+ break;
+ case CSS1_BS_INSET:
+ aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::INSET);
+ break;
+ case CSS1_BS_OUTSET:
+ aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::OUTSET);
+ break;
+ default:
+ aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::NONE);
+ break;
+ }
+
+ // convert named width, if no absolute is given
+ if( nAbsWidth==USHRT_MAX )
+ aBorderLine.SetWidth( aBorderWidths[ nNamedWidth ] );
+ else
+ aBorderLine.SetWidth( nAbsWidth );
+
+ rBoxItem.SetLine( &aBorderLine, nLine );
+}
+
+SvxCSS1PropertyInfo::SvxCSS1PropertyInfo()
+{
+ Clear();
+}
+
+SvxCSS1PropertyInfo::SvxCSS1PropertyInfo( const SvxCSS1PropertyInfo& rProp ) :
+ m_aId( rProp.m_aId ),
+ m_bTopMargin( rProp.m_bTopMargin ),
+ m_bBottomMargin( rProp.m_bBottomMargin ),
+ m_bLeftMargin( rProp.m_bLeftMargin ),
+ m_bRightMargin( rProp.m_bRightMargin ),
+ m_bTextIndent( rProp.m_bTextIndent ),
+ m_bNumbering ( rProp.m_bNumbering ),
+ m_bBullet ( rProp.m_bBullet ),
+ m_eFloat( rProp.m_eFloat ),
+ m_ePosition( rProp.m_ePosition ),
+ m_nTopBorderDistance( rProp.m_nTopBorderDistance ),
+ m_nBottomBorderDistance( rProp.m_nBottomBorderDistance ),
+ m_nLeftBorderDistance( rProp.m_nLeftBorderDistance ),
+ m_nRightBorderDistance( rProp.m_nRightBorderDistance ),
+ m_nNumberingType ( rProp.m_nNumberingType ),
+ m_cBulletChar( rProp.m_cBulletChar ),
+ m_nColumnCount( rProp.m_nColumnCount ),
+ m_nLeft( rProp.m_nLeft ),
+ m_nTop( rProp.m_nTop ),
+ m_nWidth( rProp.m_nWidth ),
+ m_nHeight( rProp.m_nHeight ),
+ m_nLeftMargin( rProp.m_nLeftMargin ),
+ m_nRightMargin( rProp.m_nRightMargin ),
+ m_eLeftType( rProp.m_eLeftType ),
+ m_eTopType( rProp.m_eTopType ),
+ m_eWidthType( rProp.m_eWidthType ),
+ m_eHeightType( rProp.m_eHeightType ),
+ m_eLeftMarginType( rProp.m_eLeftMarginType ),
+ m_eRightMarginType( rProp.m_eRightMarginType ),
+ m_eSizeType( rProp.m_eSizeType ),
+ m_ePageBreakBefore( rProp.m_ePageBreakBefore ),
+ m_ePageBreakAfter( rProp.m_ePageBreakAfter )
+{
+ for( size_t i=0; i<m_aBorderInfos.size(); ++i )
+ if (rProp.m_aBorderInfos[i])
+ m_aBorderInfos[i].reset( new SvxCSS1BorderInfo( *rProp.m_aBorderInfos[i] ) );
+}
+
+SvxCSS1PropertyInfo::~SvxCSS1PropertyInfo()
+{
+}
+
+void SvxCSS1PropertyInfo::DestroyBorderInfos()
+{
+ for(auto & rp : m_aBorderInfos)
+ rp.reset();
+}
+
+void SvxCSS1PropertyInfo::Clear()
+{
+ m_aId.clear();
+ m_bTopMargin = m_bBottomMargin = false;
+ m_bLeftMargin = m_bRightMargin = m_bTextIndent = false;
+ m_bNumbering = m_bBullet = false;
+ m_nLeftMargin = m_nRightMargin = 0;
+ m_eFloat = SvxAdjust::End;
+
+ m_ePosition = SVX_CSS1_POS_NONE;
+ m_nTopBorderDistance = m_nBottomBorderDistance =
+ m_nLeftBorderDistance = m_nRightBorderDistance = UNSET_BORDER_DISTANCE;
+
+ m_nNumberingType = SVX_NUM_CHARS_UPPER_LETTER;
+ m_cBulletChar = ' ';
+
+ m_nColumnCount = 0;
+
+ m_nLeft = m_nTop = m_nWidth = m_nHeight = 0;
+ m_eLeftType = m_eTopType = m_eWidthType = m_eHeightType = SVX_CSS1_LTYPE_NONE;
+ m_eLeftMarginType = SVX_CSS1_LTYPE_NONE;
+ m_eRightMarginType = SVX_CSS1_LTYPE_NONE;
+
+// Feature: PrintExt
+ m_eSizeType = SVX_CSS1_STYPE_NONE;
+ m_ePageBreakBefore = SVX_CSS1_PBREAK_NONE;
+ m_ePageBreakAfter = SVX_CSS1_PBREAK_NONE;
+
+ DestroyBorderInfos();
+}
+
+void SvxCSS1PropertyInfo::Merge( const SvxCSS1PropertyInfo& rProp )
+{
+ if( rProp.m_bTopMargin )
+ m_bTopMargin = true;
+ if( rProp.m_bBottomMargin )
+ m_bBottomMargin = true;
+
+ if( rProp.m_bLeftMargin )
+ {
+ m_bLeftMargin = true;
+ m_nLeftMargin = rProp.m_nLeftMargin;
+ }
+ if( rProp.m_bRightMargin )
+ {
+ m_bRightMargin = true;
+ m_nRightMargin = rProp.m_nRightMargin;
+ }
+ if( rProp.m_bTextIndent )
+ m_bTextIndent = true;
+
+ for( size_t i=0; i<m_aBorderInfos.size(); ++i )
+ {
+ if( rProp.m_aBorderInfos[i] )
+ m_aBorderInfos[i].reset( new SvxCSS1BorderInfo( *rProp.m_aBorderInfos[i] ) );
+ }
+
+ if( UNSET_BORDER_DISTANCE != rProp.m_nTopBorderDistance )
+ m_nTopBorderDistance = rProp.m_nTopBorderDistance;
+ if( UNSET_BORDER_DISTANCE != rProp.m_nBottomBorderDistance )
+ m_nBottomBorderDistance = rProp.m_nBottomBorderDistance;
+ if( UNSET_BORDER_DISTANCE != rProp.m_nLeftBorderDistance )
+ m_nLeftBorderDistance = rProp.m_nLeftBorderDistance;
+ if( UNSET_BORDER_DISTANCE != rProp.m_nRightBorderDistance )
+ m_nRightBorderDistance = rProp.m_nRightBorderDistance;
+
+ m_nColumnCount = rProp.m_nColumnCount;
+
+ if( rProp.m_eFloat != SvxAdjust::End )
+ m_eFloat = rProp.m_eFloat;
+
+ if( rProp.m_ePosition != SVX_CSS1_POS_NONE )
+ m_ePosition = rProp.m_ePosition;
+
+// Feature: PrintExt
+ if( rProp.m_eSizeType != SVX_CSS1_STYPE_NONE )
+ {
+ m_eSizeType = rProp.m_eSizeType;
+ m_nWidth = rProp.m_nWidth;
+ m_nHeight = rProp.m_nHeight;
+ }
+
+ if( rProp.m_ePageBreakBefore != SVX_CSS1_PBREAK_NONE )
+ m_ePageBreakBefore = rProp.m_ePageBreakBefore;
+
+ if( rProp.m_ePageBreakAfter != SVX_CSS1_PBREAK_NONE )
+ m_ePageBreakAfter = rProp.m_ePageBreakAfter;
+
+ if( rProp.m_eLeftType != SVX_CSS1_LTYPE_NONE )
+ {
+ m_eLeftType = rProp.m_eLeftType;
+ m_nLeft = rProp.m_nLeft;
+ }
+
+ if( rProp.m_eTopType != SVX_CSS1_LTYPE_NONE )
+ {
+ m_eTopType = rProp.m_eTopType;
+ m_nTop = rProp.m_nTop;
+ }
+
+ if( rProp.m_eWidthType != SVX_CSS1_LTYPE_NONE )
+ {
+ m_eWidthType = rProp.m_eWidthType;
+ m_nWidth = rProp.m_nWidth;
+ }
+
+ if( rProp.m_eHeightType != SVX_CSS1_LTYPE_NONE )
+ {
+ m_eHeightType = rProp.m_eHeightType;
+ m_nHeight = rProp.m_nHeight;
+ }
+}
+
+SvxCSS1BorderInfo *SvxCSS1PropertyInfo::GetBorderInfo( SvxBoxItemLine nLine, bool bCreate )
+{
+ sal_uInt16 nPos = 0;
+ switch( nLine )
+ {
+ case SvxBoxItemLine::TOP: nPos = 0; break;
+ case SvxBoxItemLine::BOTTOM: nPos = 1; break;
+ case SvxBoxItemLine::LEFT: nPos = 2; break;
+ case SvxBoxItemLine::RIGHT: nPos = 3; break;
+ }
+
+ if( !m_aBorderInfos[nPos] && bCreate )
+ m_aBorderInfos[nPos].reset( new SvxCSS1BorderInfo );
+
+ return m_aBorderInfos[nPos].get();
+}
+
+void SvxCSS1PropertyInfo::CopyBorderInfo( SvxBoxItemLine nSrcLine, SvxBoxItemLine nDstLine,
+ sal_uInt16 nWhat )
+{
+ SvxCSS1BorderInfo *pSrcInfo = GetBorderInfo( nSrcLine, false );
+ if( !pSrcInfo )
+ return;
+
+ SvxCSS1BorderInfo *pDstInfo = GetBorderInfo( nDstLine );
+ if( (nWhat & SVX_CSS1_BORDERINFO_WIDTH) != 0 )
+ {
+ pDstInfo->nAbsWidth = pSrcInfo->nAbsWidth;
+ pDstInfo->nNamedWidth = pSrcInfo->nNamedWidth;
+ }
+
+ if( (nWhat & SVX_CSS1_BORDERINFO_COLOR) != 0 )
+ pDstInfo->aColor = pSrcInfo->aColor;
+
+ if( (nWhat & SVX_CSS1_BORDERINFO_STYLE) != 0 )
+ pDstInfo->eStyle = pSrcInfo->eStyle;
+}
+
+void SvxCSS1PropertyInfo::CopyBorderInfo( sal_uInt16 nCount, sal_uInt16 nWhat )
+{
+ if( nCount==0 )
+ {
+ CopyBorderInfo( SvxBoxItemLine::BOTTOM, SvxBoxItemLine::TOP, nWhat );
+ CopyBorderInfo( SvxBoxItemLine::TOP, SvxBoxItemLine::LEFT, nWhat );
+ }
+ if( nCount<=1 )
+ {
+ CopyBorderInfo( SvxBoxItemLine::LEFT, SvxBoxItemLine::RIGHT, nWhat );
+ }
+}
+
+void SvxCSS1PropertyInfo::SetBoxItem( SfxItemSet& rItemSet,
+ sal_uInt16 nMinBorderDist,
+ const SvxBoxItem *pDfltItem )
+{
+ bool bChg = m_nTopBorderDistance != UNSET_BORDER_DISTANCE ||
+ m_nBottomBorderDistance != UNSET_BORDER_DISTANCE ||
+ m_nLeftBorderDistance != UNSET_BORDER_DISTANCE ||
+ m_nRightBorderDistance != UNSET_BORDER_DISTANCE;
+
+ for( size_t i=0; !bChg && i<m_aBorderInfos.size(); ++i )
+ bChg = m_aBorderInfos[i]!=nullptr;
+
+ if( !bChg )
+ return;
+
+ std::shared_ptr<SvxBoxItem> aBoxItem(std::make_shared<SvxBoxItem>(aItemIds.nBox));
+ if( pDfltItem )
+ aBoxItem.reset(pDfltItem->Clone());
+
+ SvxCSS1BorderInfo *pInfo = GetBorderInfo( SvxBoxItemLine::TOP, false );
+ if( pInfo )
+ pInfo->SetBorderLine( SvxBoxItemLine::TOP, *aBoxItem );
+
+ pInfo = GetBorderInfo( SvxBoxItemLine::BOTTOM, false );
+ if( pInfo )
+ pInfo->SetBorderLine( SvxBoxItemLine::BOTTOM, *aBoxItem );
+
+ pInfo = GetBorderInfo( SvxBoxItemLine::LEFT, false );
+ if( pInfo )
+ pInfo->SetBorderLine( SvxBoxItemLine::LEFT, *aBoxItem );
+
+ pInfo = GetBorderInfo( SvxBoxItemLine::RIGHT, false );
+ if( pInfo )
+ pInfo->SetBorderLine( SvxBoxItemLine::RIGHT, *aBoxItem );
+
+ for( size_t i=0; i<m_aBorderInfos.size(); ++i )
+ {
+ SvxBoxItemLine nLine = SvxBoxItemLine::TOP;
+ sal_uInt16 nDist = 0;
+ switch( i )
+ {
+ case 0: nLine = SvxBoxItemLine::TOP;
+ nDist = m_nTopBorderDistance;
+ m_nTopBorderDistance = UNSET_BORDER_DISTANCE;
+ break;
+ case 1: nLine = SvxBoxItemLine::BOTTOM;
+ nDist = m_nBottomBorderDistance;
+ m_nBottomBorderDistance = UNSET_BORDER_DISTANCE;
+ break;
+ case 2: nLine = SvxBoxItemLine::LEFT;
+ nDist = m_nLeftBorderDistance;
+ m_nLeftBorderDistance = UNSET_BORDER_DISTANCE;
+ break;
+ case 3: nLine = SvxBoxItemLine::RIGHT;
+ nDist = m_nRightBorderDistance;
+ m_nRightBorderDistance = UNSET_BORDER_DISTANCE;
+ break;
+ }
+
+ if( aBoxItem->GetLine( nLine ) )
+ {
+ if( UNSET_BORDER_DISTANCE == nDist )
+ nDist = aBoxItem->GetDistance( nLine );
+
+ if( nDist < nMinBorderDist )
+ nDist = nMinBorderDist;
+ }
+ else
+ {
+ nDist = 0U;
+ }
+
+ aBoxItem->SetDistance( nDist, nLine );
+ }
+
+ rItemSet.Put( *aBoxItem );
+
+ DestroyBorderInfos();
+}
+
+SvxCSS1MapEntry::SvxCSS1MapEntry( SfxItemSet aItemSet,
+ const SvxCSS1PropertyInfo& rProp ) :
+ m_aItemSet(std::move( aItemSet )),
+ m_aPropInfo( rProp )
+{}
+
+void SvxCSS1Parser::StyleParsed( const CSS1Selector * /*pSelector*/,
+ SfxItemSet& /*rItemSet*/,
+ SvxCSS1PropertyInfo& /*rPropInfo*/ )
+{
+ // you see nothing is happening here
+}
+
+void SvxCSS1Parser::SelectorParsed( std::unique_ptr<CSS1Selector> pSelector, bool bFirst )
+{
+ if( bFirst )
+ {
+ OSL_ENSURE( m_pSheetItemSet, "Where is the Item-Set for Style-Sheets?" );
+
+ for (const std::unique_ptr<CSS1Selector> & rpSelection : m_Selectors)
+ {
+ StyleParsed(rpSelection.get(), *m_pSheetItemSet, *m_pSheetPropInfo);
+ }
+ m_pSheetItemSet->ClearItem();
+ m_pSheetPropInfo->Clear();
+
+ // prepare the next rule
+ m_Selectors.clear();
+ }
+
+ m_Selectors.push_back(std::move(pSelector));
+}
+
+SvxCSS1Parser::SvxCSS1Parser( SfxItemPool& rPool, OUString aBaseURL,
+ sal_uInt16 const *pWhichIds, sal_uInt16 nWhichIds ) :
+ m_sBaseURL(std::move( aBaseURL )),
+ m_pItemSet(nullptr),
+ m_pPropInfo( nullptr ),
+ m_eDefaultEnc( RTL_TEXTENCODING_DONTKNOW ),
+ m_bIgnoreFontFamily( false )
+{
+ // also initialize item IDs
+ auto initTrueWhich = [&rPool, this](sal_uInt16 rWid)
+ {
+ rWid = rPool.GetTrueWhich(rWid, false);
+ m_aWhichMap = m_aWhichMap.MergeRange(rWid, rWid);
+ return rWid;
+ };
+
+ aItemIds.nFont = initTrueWhich( SID_ATTR_CHAR_FONT );
+ aItemIds.nFontCJK = initTrueWhich( SID_ATTR_CHAR_CJK_FONT );
+ aItemIds.nFontCTL = initTrueWhich( SID_ATTR_CHAR_CTL_FONT );
+ aItemIds.nPosture = initTrueWhich( SID_ATTR_CHAR_POSTURE );
+ aItemIds.nPostureCJK = initTrueWhich( SID_ATTR_CHAR_CJK_POSTURE );
+ aItemIds.nPostureCTL = initTrueWhich( SID_ATTR_CHAR_CTL_POSTURE );
+ aItemIds.nWeight = initTrueWhich( SID_ATTR_CHAR_WEIGHT );
+ aItemIds.nWeightCJK = initTrueWhich( SID_ATTR_CHAR_CJK_WEIGHT );
+ aItemIds.nWeightCTL = initTrueWhich( SID_ATTR_CHAR_CTL_WEIGHT );
+ aItemIds.nFontHeight = initTrueWhich( SID_ATTR_CHAR_FONTHEIGHT );
+ aItemIds.nFontHeightCJK = initTrueWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT );
+ aItemIds.nFontHeightCTL = initTrueWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT );
+ aItemIds.nUnderline = initTrueWhich( SID_ATTR_CHAR_UNDERLINE );
+ aItemIds.nOverline = initTrueWhich( SID_ATTR_CHAR_OVERLINE );
+ aItemIds.nCrossedOut = initTrueWhich( SID_ATTR_CHAR_STRIKEOUT );
+ aItemIds.nColor = initTrueWhich( SID_ATTR_CHAR_COLOR );
+ aItemIds.nKerning = initTrueWhich( SID_ATTR_CHAR_KERNING );
+ aItemIds.nCaseMap = initTrueWhich( SID_ATTR_CHAR_CASEMAP );
+ aItemIds.nBlink = initTrueWhich( SID_ATTR_FLASH );
+
+ aItemIds.nLineSpacing = initTrueWhich( SID_ATTR_PARA_LINESPACE );
+ aItemIds.nAdjust = initTrueWhich( SID_ATTR_PARA_ADJUST );
+ aItemIds.nWidows = initTrueWhich( SID_ATTR_PARA_WIDOWS );
+ aItemIds.nOrphans = initTrueWhich( SID_ATTR_PARA_ORPHANS );
+ aItemIds.nFormatSplit = initTrueWhich( SID_ATTR_PARA_SPLIT );
+
+ // every id that is used must be added
+ m_aWhichMap = m_aWhichMap.MergeRange(RES_MARGIN_FIRSTLINE, RES_MARGIN_FIRSTLINE);
+ m_aWhichMap = m_aWhichMap.MergeRange(RES_MARGIN_TEXTLEFT, RES_MARGIN_TEXTLEFT);
+ m_aWhichMap = m_aWhichMap.MergeRange(RES_MARGIN_RIGHT, RES_MARGIN_RIGHT);
+ aItemIds.nULSpace = TypedWhichId<SvxULSpaceItem>(initTrueWhich( SID_ATTR_ULSPACE ));
+ aItemIds.nBox = initTrueWhich( SID_ATTR_BORDER_OUTER );
+ aItemIds.nBrush = initTrueWhich( SID_ATTR_BRUSH );
+
+ aItemIds.nLanguage = initTrueWhich( SID_ATTR_CHAR_LANGUAGE );
+ aItemIds.nLanguageCJK = initTrueWhich( SID_ATTR_CHAR_CJK_LANGUAGE );
+ aItemIds.nLanguageCTL = initTrueWhich( SID_ATTR_CHAR_CTL_LANGUAGE );
+ aItemIds.nDirection = initTrueWhich( SID_ATTR_FRAMEDIRECTION );
+
+ if( pWhichIds && nWhichIds )
+ for (sal_uInt16 i = 0; i < nWhichIds; ++i)
+ m_aWhichMap = m_aWhichMap.MergeRange(pWhichIds[i], pWhichIds[i]);
+
+ m_pSheetItemSet.reset( new SfxItemSet( rPool, m_aWhichMap ) );
+ m_pSheetPropInfo.reset( new SvxCSS1PropertyInfo );
+}
+
+SvxCSS1Parser::~SvxCSS1Parser()
+{
+ m_pSheetItemSet.reset();
+ m_pSheetPropInfo.reset();
+}
+
+void SvxCSS1Parser::InsertId( const OUString& rId,
+ const SfxItemSet& rItemSet,
+ const SvxCSS1PropertyInfo& rProp )
+{
+ InsertMapEntry( rId, rItemSet, rProp, m_Ids );
+}
+
+const SvxCSS1MapEntry* SvxCSS1Parser::GetId( const OUString& rId ) const
+{
+ CSS1Map::const_iterator itr = m_Ids.find(rId);
+ return itr == m_Ids.end() ? nullptr : itr->second.get();
+}
+
+void SvxCSS1Parser::InsertClass( const OUString& rClass,
+ const SfxItemSet& rItemSet,
+ const SvxCSS1PropertyInfo& rProp )
+{
+ InsertMapEntry( rClass, rItemSet, rProp, m_Classes );
+}
+
+const SvxCSS1MapEntry* SvxCSS1Parser::GetClass( const OUString& rClass ) const
+{
+ CSS1Map::const_iterator itr = m_Classes.find(rClass);
+ return itr == m_Classes.end() ? nullptr : itr->second.get();
+}
+
+void SvxCSS1Parser::InsertPage( const OUString& rPage,
+ bool bPseudo,
+ const SfxItemSet& rItemSet,
+ const SvxCSS1PropertyInfo& rProp )
+{
+ OUString aKey( rPage );
+ if( bPseudo )
+ aKey = ":" + aKey;
+ InsertMapEntry( aKey, rItemSet, rProp, m_Pages );
+}
+
+SvxCSS1MapEntry* SvxCSS1Parser::GetPage( const OUString& rPage, bool bPseudo )
+{
+ OUString aKey( rPage );
+ if( bPseudo )
+ aKey = ":" + aKey;
+
+ CSS1Map::iterator itr = m_Pages.find(aKey);
+ return itr == m_Pages.end() ? nullptr : itr->second.get();
+}
+
+void SvxCSS1Parser::InsertTag( const OUString& rTag,
+ const SfxItemSet& rItemSet,
+ const SvxCSS1PropertyInfo& rProp )
+{
+ InsertMapEntry( rTag, rItemSet, rProp, m_Tags );
+}
+
+SvxCSS1MapEntry* SvxCSS1Parser::GetTag( const OUString& rTag )
+{
+ CSS1Map::iterator itr = m_Tags.find(rTag);
+ return itr == m_Tags.end() ? nullptr : itr->second.get();
+}
+
+bool SvxCSS1Parser::ParseStyleSheet( const OUString& rIn )
+{
+ m_pItemSet = m_pSheetItemSet.get();
+ m_pPropInfo = m_pSheetPropInfo.get();
+
+ CSS1Parser::ParseStyleSheet( rIn );
+
+ for (const std::unique_ptr<CSS1Selector> & rpSelector : m_Selectors)
+ {
+ StyleParsed(rpSelector.get(), *m_pSheetItemSet, *m_pSheetPropInfo);
+ }
+
+ // and clean up a little bit
+ m_Selectors.clear();
+ m_pSheetItemSet->ClearItem();
+ m_pSheetPropInfo->Clear();
+
+ m_pItemSet = nullptr;
+ m_pPropInfo = nullptr;
+
+ return true;
+}
+
+void SvxCSS1Parser::ParseStyleOption( const OUString& rIn,
+ SfxItemSet& rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo )
+{
+ m_pItemSet = &rItemSet;
+ m_pPropInfo = &rPropInfo;
+
+ CSS1Parser::ParseStyleOption( rIn );
+ rItemSet.ClearItem( aItemIds.nDirection );
+
+ m_pItemSet = nullptr;
+ m_pPropInfo = nullptr;
+}
+
+bool SvxCSS1Parser::GetEnum( const CSS1PropertyEnum *pPropTable,
+ std::u16string_view rValue, sal_uInt16& rEnum )
+{
+ while( pPropTable->pName )
+ {
+ if( !o3tl::equalsIgnoreAsciiCase( rValue, pPropTable->pName ) )
+ pPropTable++;
+ else
+ break;
+ }
+
+ if( pPropTable->pName )
+ rEnum = pPropTable->nEnum;
+
+ return (pPropTable->pName != nullptr);
+}
+
+void SvxCSS1Parser::PixelToTwip( tools::Long &rWidth, tools::Long &rHeight )
+{
+ rWidth = o3tl::convert(rWidth, o3tl::Length::px, o3tl::Length::twip);
+ rHeight = o3tl::convert(rHeight, o3tl::Length::px, o3tl::Length::twip);
+}
+
+sal_uInt32 SvxCSS1Parser::GetFontHeight( sal_uInt16 nSize ) const
+{
+ sal_uInt16 nHeight;
+
+ switch( nSize )
+ {
+ case 0: nHeight = 8*20; break;
+ case 1: nHeight = 10*20; break;
+ case 2: nHeight = 11*20; break;
+ case 3: nHeight = 12*20; break;
+ case 4: nHeight = 17*20; break;
+ case 5: nHeight = 20*20; break;
+ case 6:
+ default: nHeight = 32*20; break;
+ }
+
+ return nHeight;
+}
+
+const FontList *SvxCSS1Parser::GetFontList() const
+{
+ return nullptr;
+}
+
+void SvxCSS1Parser::InsertMapEntry( const OUString& rKey,
+ const SfxItemSet& rItemSet,
+ const SvxCSS1PropertyInfo& rProp,
+ CSS1Map& rMap )
+{
+ auto [itr,inserted] = rMap.insert(std::make_pair(rKey, nullptr));
+ if (inserted)
+ itr->second = std::make_unique<SvxCSS1MapEntry>(rItemSet, rProp);
+ else
+ {
+ SvxCSS1MapEntry *const p = itr->second.get();
+ MergeStyles( rItemSet, rProp,
+ p->GetItemSet(), p->GetPropertyInfo(), true );
+ }
+}
+
+void SvxCSS1Parser::MergeStyles( const SfxItemSet& rSrcSet,
+ const SvxCSS1PropertyInfo& rSrcInfo,
+ SfxItemSet& rTargetSet,
+ SvxCSS1PropertyInfo& rTargetInfo,
+ bool bSmart )
+{
+ if( !bSmart )
+ {
+ rTargetSet.Put( rSrcSet );
+ }
+ else
+ {
+ // not sure if this is really necessary?
+ SfxItemSet copy(rSrcSet);
+ if (!rSrcInfo.m_bTextIndent)
+ {
+ copy.ClearItem(RES_MARGIN_FIRSTLINE);
+ }
+ if (!rSrcInfo.m_bLeftMargin)
+ {
+ copy.ClearItem(RES_MARGIN_TEXTLEFT);
+ }
+ if (!rSrcInfo.m_bRightMargin)
+ {
+ copy.ClearItem(RES_MARGIN_RIGHT);
+ }
+
+ SvxULSpaceItem aULSpace( rTargetSet.Get(aItemIds.nULSpace) );
+
+ rTargetSet.Put(copy);
+
+ if( rSrcInfo.m_bTopMargin || rSrcInfo.m_bBottomMargin )
+ {
+ const SvxULSpaceItem& rNewULSpace = rSrcSet.Get( aItemIds.nULSpace );
+
+ if( rSrcInfo.m_bTopMargin )
+ aULSpace.SetUpper( rNewULSpace.GetUpper() );
+ if( rSrcInfo.m_bBottomMargin )
+ aULSpace.SetLower( rNewULSpace.GetLower() );
+
+ rTargetSet.Put( aULSpace );
+ }
+ }
+
+ rTargetInfo.Merge( rSrcInfo );
+}
+
+void SvxCSS1Parser::SetDfltEncoding( rtl_TextEncoding eEnc )
+{
+ m_eDefaultEnc = eEnc;
+}
+
+static void ParseCSS1_font_size( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& rParser )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ sal_uLong nHeight = 0;
+ sal_uInt16 nPropHeight = 100;
+
+ switch( pExpr->GetType() )
+ {
+ case CSS1_LENGTH:
+ nHeight = pExpr->GetULength();
+ break;
+ case CSS1_PIXLENGTH:
+ {
+ double fHeight = pExpr->GetNumber();
+ if (fHeight < SAL_MAX_INT32/2.0 && fHeight > SAL_MIN_INT32/2.0)
+ {
+ tools::Long nPHeight = static_cast<tools::Long>(fHeight);
+ tools::Long nPWidth = 0;
+ SvxCSS1Parser::PixelToTwip(nPWidth, nPHeight);
+ nHeight = static_cast<sal_uLong>(nPHeight);
+ }
+ else
+ {
+ SAL_WARN("sw.html", "out-of-size pxlength: " << fHeight);
+ }
+ }
+ break;
+ case CSS1_PERCENTAGE:
+ // only for drop caps!
+ nPropHeight = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber());
+ break;
+ case CSS1_IDENT:
+ {
+ sal_uInt16 nSize;
+
+ if( SvxCSS1Parser::GetEnum( aFontSizeTable, pExpr->GetString(),
+ nSize ) )
+ {
+ nHeight = rParser.GetFontHeight( nSize );
+ }
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ if( nHeight || nPropHeight!=100 )
+ {
+ SvxFontHeightItem aFontHeight( nHeight, nPropHeight,
+ aItemIds.nFontHeight );
+ rItemSet.Put( aFontHeight );
+ aFontHeight.SetWhich( aItemIds.nFontHeightCJK );
+ rItemSet.Put( aFontHeight );
+ aFontHeight.SetWhich( aItemIds.nFontHeightCTL );
+ rItemSet.Put( aFontHeight );
+ }
+}
+
+static void ParseCSS1_font_family( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& rParser )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ OUStringBuffer aName;
+ rtl_TextEncoding eEnc = rParser.GetDfltEncoding();
+ const FontList *pFList = rParser.GetFontList();
+ bool bFirst = true;
+ bool bFound = false;
+ while( pExpr && (bFirst || ','==pExpr->GetOp() || !pExpr->GetOp()) )
+ {
+ CSS1Token eType = pExpr->GetType();
+ if( CSS1_IDENT==eType || CSS1_STRING==eType )
+ {
+ OUString aIdent( pExpr->GetString() );
+
+ if( CSS1_IDENT==eType )
+ {
+ // Collect all following IDs and append them with a space
+ const CSS1Expression *pNext = pExpr->GetNext();
+ while( pNext && !pNext->GetOp() &&
+ CSS1_IDENT==pNext->GetType() )
+ {
+ aIdent += " " + pNext->GetString();
+ pExpr = pNext;
+ pNext = pExpr->GetNext();
+ }
+ }
+ if( !aIdent.isEmpty() )
+ {
+ if( !bFound && pFList )
+ {
+ sal_Handle hFont = pFList->GetFirstFontMetric( aIdent );
+ if( nullptr != hFont )
+ {
+ const FontMetric& rFMetric = FontList::GetFontMetric( hFont );
+ if( RTL_TEXTENCODING_DONTKNOW != rFMetric.GetCharSet() )
+ {
+ bFound = true;
+ if( RTL_TEXTENCODING_SYMBOL == rFMetric.GetCharSet() )
+ eEnc = RTL_TEXTENCODING_SYMBOL;
+ }
+ }
+ }
+ if( !bFirst )
+ aName.append(";");
+ aName.append(aIdent);
+ }
+ }
+
+ pExpr = pExpr->GetNext();
+ bFirst = false;
+ }
+
+ if( !aName.isEmpty() && !rParser.IsIgnoreFontFamily() )
+ {
+ SvxFontItem aFont( FAMILY_DONTKNOW, aName.makeStringAndClear(), OUString(), PITCH_DONTKNOW,
+ eEnc, aItemIds.nFont );
+ rItemSet.Put( aFont );
+ aFont.SetWhich( aItemIds.nFontCJK );
+ rItemSet.Put( aFont );
+ aFont.SetWhich( aItemIds.nFontCTL );
+ rItemSet.Put( aFont );
+ }
+}
+
+static void ParseCSS1_font_weight( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ switch( pExpr->GetType() )
+ {
+ case CSS1_IDENT:
+ case CSS1_STRING: // MS-IE, what else
+ {
+ sal_uInt16 nWeight;
+ if( SvxCSS1Parser::GetEnum( aFontWeightTable, pExpr->GetString(),
+ nWeight ) )
+ {
+ SvxWeightItem aWeight( static_cast<FontWeight>(nWeight), aItemIds.nWeight );
+ rItemSet.Put( aWeight );
+ aWeight.SetWhich( aItemIds.nWeightCJK );
+ rItemSet.Put( aWeight );
+ aWeight.SetWhich( aItemIds.nWeightCTL );
+ rItemSet.Put( aWeight );
+ }
+ }
+ break;
+ case CSS1_NUMBER:
+ {
+ sal_uInt16 nWeight = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber());
+ SvxWeightItem aWeight( nWeight>400 ? WEIGHT_BOLD : WEIGHT_NORMAL,
+ aItemIds.nWeight );
+ rItemSet.Put( aWeight );
+ aWeight.SetWhich( aItemIds.nWeightCJK );
+ rItemSet.Put( aWeight );
+ aWeight.SetWhich( aItemIds.nWeightCTL );
+ rItemSet.Put( aWeight );
+ }
+ break;
+
+ default:
+ ;
+ }
+}
+
+static void ParseCSS1_font_style( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ bool bPosture = false;
+ bool bCaseMap = false;
+ FontItalic eItalic = ITALIC_NONE;
+ SvxCaseMap eCaseMap = SvxCaseMap::NotMapped;
+
+ // normal | italic || small-caps | oblique || small-caps | small-caps
+ // (only normal, italic and oblique are valid)
+
+ // the value can have two values!
+ for( int i=0; pExpr && i<2; ++i )
+ {
+ // also here MS-IE parser leaves traces
+ if( (CSS1_IDENT==pExpr->GetType() || CSS1_STRING==pExpr->GetType()) &&
+ !pExpr->GetOp() )
+ {
+ const OUString& rValue = pExpr->GetString();
+ // first check if the value is italic or 'normal'
+ sal_uInt16 nItalic;
+ if( SvxCSS1Parser::GetEnum( aFontStyleTable, rValue, nItalic ) )
+ {
+ eItalic = static_cast<FontItalic>(nItalic);
+ if( !bCaseMap && ITALIC_NONE==eItalic )
+ {
+ // for 'normal' we must also exclude case-map
+ eCaseMap = SvxCaseMap::NotMapped;
+ bCaseMap = true;
+ }
+ bPosture = true;
+ }
+ else if( !bCaseMap &&
+ rValue.equalsIgnoreAsciiCase( "small-caps" ) )
+ {
+ eCaseMap = SvxCaseMap::SmallCaps;
+ bCaseMap = true;
+ }
+ }
+
+ // fetch next expression
+ pExpr = pExpr->GetNext();
+ }
+
+ if( bPosture )
+ {
+ SvxPostureItem aPosture( eItalic, aItemIds.nPosture );
+ rItemSet.Put( aPosture );
+ aPosture.SetWhich( aItemIds.nPostureCJK );
+ rItemSet.Put( aPosture );
+ aPosture.SetWhich( aItemIds.nPostureCTL );
+ rItemSet.Put( aPosture );
+ }
+
+ if( bCaseMap )
+ rItemSet.Put( SvxCaseMapItem( eCaseMap, aItemIds.nCaseMap ) );
+}
+
+static void ParseCSS1_font_variant( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ assert(pExpr && "no expression");
+
+ // normal | small-caps
+ switch( pExpr->GetType() )
+ {
+ case CSS1_IDENT:
+ {
+ sal_uInt16 nCaseMap;
+ if( SvxCSS1Parser::GetEnum( aFontVariantTable, pExpr->GetString(),
+ nCaseMap ) )
+ {
+ rItemSet.Put( SvxCaseMapItem( static_cast<SvxCaseMap>(nCaseMap),
+ aItemIds.nCaseMap ) );
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void ParseCSS1_text_transform( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ // none | capitalize | uppercase | lowercase
+
+ switch( pExpr->GetType() )
+ {
+ case CSS1_IDENT:
+ {
+ sal_uInt16 nCaseMap;
+ if( SvxCSS1Parser::GetEnum( aTextTransformTable, pExpr->GetString(),
+ nCaseMap ) )
+ {
+ rItemSet.Put( SvxCaseMapItem( static_cast<SvxCaseMap>(nCaseMap),
+ aItemIds.nCaseMap ) );
+ }
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static void ParseCSS1_color( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ switch( pExpr->GetType() )
+ {
+ case CSS1_IDENT:
+ case CSS1_RGB:
+ case CSS1_HEXCOLOR:
+ case CSS1_STRING: // because MS-IE
+ {
+ Color aColor;
+ if( pExpr->GetColor( aColor ) )
+ rItemSet.Put( SvxColorItem( aColor, aItemIds.nColor ) );
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+static void ParseCSS1_column_count( const CSS1Expression *pExpr,
+ SfxItemSet& /*rItemSet*/,
+ SvxCSS1PropertyInfo &rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ assert(pExpr && "no expression");
+
+ if ( pExpr->GetType() == CSS1_NUMBER )
+ {
+ double columnCount = pExpr->GetNumber();
+ if ( columnCount >= 2 )
+ {
+ rPropInfo.m_nColumnCount = columnCount;
+ }
+ }
+}
+
+static void ParseCSS1_direction( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ assert(pExpr && "no expression");
+
+ sal_uInt16 nDir;
+ switch( pExpr->GetType() )
+ {
+ case CSS1_IDENT:
+ case CSS1_STRING:
+ if( SvxCSS1Parser::GetEnum( aDirectionTable, pExpr->GetString(),
+ nDir ) )
+ {
+ rItemSet.Put( SvxFrameDirectionItem(
+ static_cast < SvxFrameDirection >( nDir ),
+ aItemIds.nDirection ) );
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+static void MergeHori( SvxGraphicPosition& ePos, SvxGraphicPosition eHori )
+{
+ OSL_ENSURE( GPOS_LT==eHori || GPOS_MT==eHori || GPOS_RT==eHori,
+ "vertical position not at the top" );
+
+ switch( ePos )
+ {
+ case GPOS_LT:
+ case GPOS_MT:
+ case GPOS_RT:
+ ePos = eHori;
+ break;
+
+ case GPOS_LM:
+ case GPOS_MM:
+ case GPOS_RM:
+ ePos = GPOS_LT==eHori ? GPOS_LM : (GPOS_MT==eHori ? GPOS_MM : GPOS_RM);
+ break;
+
+ case GPOS_LB:
+ case GPOS_MB:
+ case GPOS_RB:
+ ePos = GPOS_LT==eHori ? GPOS_LB : (GPOS_MT==eHori ? GPOS_MB : GPOS_RB);
+ break;
+
+ default:
+ ;
+ }
+}
+
+static void MergeVert( SvxGraphicPosition& ePos, SvxGraphicPosition eVert )
+{
+ OSL_ENSURE( GPOS_LT==eVert || GPOS_LM==eVert || GPOS_LB==eVert,
+ "horizontal position not on the left side" );
+
+ switch( ePos )
+ {
+ case GPOS_LT:
+ case GPOS_LM:
+ case GPOS_LB:
+ ePos = eVert;
+ break;
+
+ case GPOS_MT:
+ case GPOS_MM:
+ case GPOS_MB:
+ ePos = GPOS_LT==eVert ? GPOS_MT : (GPOS_LM==eVert ? GPOS_MM : GPOS_MB);
+ break;
+
+ case GPOS_RT:
+ case GPOS_RM:
+ case GPOS_RB:
+ ePos = GPOS_LT==eVert ? GPOS_RT : (GPOS_LM==eVert ? GPOS_RM : GPOS_RB);
+ break;
+
+ default:
+ ;
+ }
+}
+
+static void ParseCSS1_background( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& rParser )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ Color aColor;
+ OUString aURL;
+
+ bool bColor = false, bTransparent = false;
+ SvxGraphicPosition eRepeat = GPOS_TILED;
+ SvxGraphicPosition ePos = GPOS_LT;
+ bool bHori = false, bVert = false;
+
+ while( pExpr && !pExpr->GetOp() )
+ {
+ switch( pExpr->GetType() )
+ {
+ case CSS1_URL:
+ pExpr->GetURL( aURL );
+ break;
+
+ case CSS1_RGB:
+ bColor = pExpr->GetColor( aColor );
+ break;
+
+ case CSS1_LENGTH:
+ case CSS1_PIXLENGTH:
+ {
+ // since we don't know any absolute position, we
+ // only distinguish between 0 and !0. Therefore pixel
+ // can be handled like all other units.
+
+ bool nonZero = std::trunc(pExpr->GetNumber()) != 0.0;
+ if( !bHori )
+ {
+ ePos = nonZero ? GPOS_MM : GPOS_LT;
+ bHori = true;
+ }
+ else if( !bVert )
+ {
+ MergeVert( ePos, (nonZero ? GPOS_LM : GPOS_LT) );
+ bVert = true;
+ }
+ }
+ break;
+
+ case CSS1_PERCENTAGE:
+ {
+ // the percentage is converted to an enum
+
+ sal_uInt16 nPerc = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber());
+ if( !bHori )
+ {
+ ePos = nPerc < 25 ? GPOS_LT
+ : (nPerc < 75 ? GPOS_MM
+ : GPOS_RB);
+ }
+ else if( !bVert )
+ {
+ SvxGraphicPosition eVert =
+ nPerc < 25 ? GPOS_LT: (nPerc < 75 ? GPOS_LM
+ : GPOS_LB);
+ MergeVert( ePos, eVert );
+ }
+ }
+ break;
+
+ case CSS1_IDENT:
+ case CSS1_HEXCOLOR:
+ case CSS1_STRING: // because of MS-IE
+ {
+ sal_uInt16 nEnum;
+ const OUString &rValue = pExpr->GetString();
+ if( rValue.equalsIgnoreAsciiCase( "transparent" ) )
+ {
+ bTransparent = true;
+ }
+ if( SvxCSS1Parser::GetEnum( aBGRepeatTable, rValue, nEnum ) )
+ {
+ eRepeat = static_cast<SvxGraphicPosition>(nEnum);
+ }
+ else if( SvxCSS1Parser::GetEnum( aBGHoriPosTable, rValue, nEnum ) )
+ {
+ // <position>, horizontal
+ MergeHori( ePos, static_cast<SvxGraphicPosition>(nEnum) );
+ }
+ else if( SvxCSS1Parser::GetEnum( aBGVertPosTable, rValue, nEnum ) )
+ {
+ // <position>, vertical
+ MergeVert( ePos, static_cast<SvxGraphicPosition>(nEnum) );
+ }
+ else if( !bColor )
+ {
+ // <color>
+ bColor = pExpr->GetColor( aColor );
+ }
+ // <scroll> we don't know
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ pExpr = pExpr->GetNext();
+ }
+
+ // transparent beats everything
+ if( bTransparent )
+ {
+ bColor = false;
+ aURL.clear();
+ }
+
+ // repeat has priority over a position
+ if( GPOS_NONE == eRepeat )
+ eRepeat = ePos;
+
+ if( !bTransparent && !bColor && aURL.isEmpty() )
+ return;
+
+ SvxBrushItem aBrushItem( aItemIds.nBrush );
+
+ if( bTransparent )
+ aBrushItem.SetColor( COL_TRANSPARENT);
+ else if( bColor )
+ aBrushItem.SetColor( aColor );
+
+ if( !aURL.isEmpty() )
+ {
+ aBrushItem.SetGraphicLink( URIHelper::SmartRel2Abs( INetURLObject( rParser.GetBaseURL()), aURL, Link<OUString *, bool>(), false ) );
+ aBrushItem.SetGraphicPos( eRepeat );
+ }
+
+ rItemSet.Put( aBrushItem );
+}
+
+static void ParseCSS1_background_color( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ Color aColor;
+
+ bool bColor = false, bTransparent = false;
+
+ switch( pExpr->GetType() )
+ {
+ case CSS1_RGB:
+ bColor = pExpr->GetColor( aColor );
+ break;
+ case CSS1_IDENT:
+ case CSS1_HEXCOLOR:
+ case CSS1_STRING: // because of MS-IE
+ if( pExpr->GetString().equalsIgnoreAsciiCase( "transparent" ) )
+ {
+ bTransparent = true;
+ }
+ else
+ {
+ // <color>
+ bColor = pExpr->GetColor( aColor );
+ }
+ break;
+ default:
+ ;
+ }
+
+ if( bTransparent || bColor )
+ {
+ SvxBrushItem aBrushItem( aItemIds.nBrush );
+
+ if( bTransparent )
+ aBrushItem.SetColor( COL_TRANSPARENT );
+ else if( bColor )
+ aBrushItem.SetColor( aColor);
+
+ rItemSet.Put( aBrushItem );
+ }
+}
+
+static void ParseCSS1_line_height( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ sal_uInt16 nHeight = 0;
+ sal_uInt16 nPropHeight = 0;
+
+ switch( pExpr->GetType() )
+ {
+ case CSS1_LENGTH:
+ nHeight = o3tl::narrowing<sal_uInt16>(pExpr->GetULength());
+ break;
+ case CSS1_PIXLENGTH:
+ {
+ double fHeight = pExpr->GetNumber();
+ if (fHeight < SAL_MAX_INT32/2.0 && fHeight > SAL_MIN_INT32/2.0)
+ {
+ tools::Long nPHeight = static_cast<tools::Long>(fHeight);
+ tools::Long nPWidth = 0;
+ SvxCSS1Parser::PixelToTwip(nPWidth, nPHeight);
+ nHeight = o3tl::narrowing<sal_uInt16>(nPHeight);
+ }
+ }
+ break;
+ case CSS1_PERCENTAGE:
+ {
+ nPropHeight = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber());
+ }
+ break;
+ case CSS1_NUMBER:
+ {
+ nPropHeight = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber() * 100);
+ }
+ break;
+ default:
+ ;
+ }
+
+ if( nHeight )
+ {
+ if( nHeight < SvxCSS1Parser::GetMinFixLineSpace() )
+ nHeight = SvxCSS1Parser::GetMinFixLineSpace();
+ SvxLineSpacingItem aLSItem( nHeight, aItemIds.nLineSpacing );
+ aLSItem.SetLineHeight( nHeight );
+ // interpret <line-height> attribute as minimum line height
+ aLSItem.SetLineSpaceRule( SvxLineSpaceRule::Min );
+ aLSItem.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off );
+ rItemSet.Put( aLSItem );
+ }
+ else if( nPropHeight )
+ {
+ SvxLineSpacingItem aLSItem( nPropHeight, aItemIds.nLineSpacing );
+ aLSItem.SetLineSpaceRule( SvxLineSpaceRule::Auto );
+ if( 100 == nPropHeight )
+ aLSItem.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off );
+ else
+ aLSItem.SetPropLineSpace( nPropHeight );
+ rItemSet.Put( aLSItem );
+ }
+
+}
+
+static void ParseCSS1_list_style_type( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ if( pExpr->GetType() != CSS1_IDENT )
+ return;
+
+ const OUString& rValue = pExpr->GetString();
+
+ // values are context-dependent, so fill both
+ sal_uInt16 nEnum;
+ if( SvxCSS1Parser::GetEnum( aNumberStyleTable, rValue, nEnum ) )
+ {
+ rPropInfo.m_bNumbering = true;
+ rPropInfo.m_nNumberingType = static_cast<SvxNumType>(nEnum);
+ }
+ if( SvxCSS1Parser::GetEnum( aBulletStyleTable, rValue, nEnum ) )
+ {
+ rPropInfo.m_bBullet = true;
+ rPropInfo.m_cBulletChar = nEnum;
+ }
+}
+
+static void ParseCSS1_font( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ FontItalic eItalic = ITALIC_NONE;
+ SvxCaseMap eCaseMap = SvxCaseMap::NotMapped;
+ FontWeight eWeight = WEIGHT_NORMAL;
+
+ // [ <font-style> || <font-variant> || <font-weight> ] ?
+ while( pExpr && !pExpr->GetOp() &&
+ (CSS1_IDENT==pExpr->GetType() ||
+ CSS1_STRING==pExpr->GetType() ||
+ CSS1_NUMBER==pExpr->GetType()) )
+ {
+ if( CSS1_IDENT==pExpr->GetType() ||
+ CSS1_STRING==pExpr->GetType() )
+ {
+ const OUString& rValue = pExpr->GetString();
+
+ sal_uInt16 nEnum;
+
+ if( SvxCSS1Parser::GetEnum( aFontStyleTable, rValue, nEnum ) )
+ {
+ eItalic = static_cast<FontItalic>(nEnum);
+ }
+ else if( SvxCSS1Parser::GetEnum( aFontVariantTable, rValue, nEnum ) )
+ {
+ eCaseMap = static_cast<SvxCaseMap>(nEnum);
+ }
+ else if( SvxCSS1Parser::GetEnum( aFontWeightTable, rValue, nEnum ) )
+ {
+ eWeight = static_cast<FontWeight>(nEnum);
+ }
+ }
+ else
+ {
+ eWeight = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber()) > 400 ? WEIGHT_BOLD
+ : WEIGHT_NORMAL;
+ }
+
+ pExpr = pExpr->GetNext();
+ }
+
+ if( !pExpr || pExpr->GetOp() )
+ return;
+
+ // Since "font" resets all values for which nothing is specified,
+ // we do it here.
+ SvxPostureItem aPosture( eItalic, aItemIds.nPosture );
+ rItemSet.Put( aPosture );
+ aPosture.SetWhich( aItemIds.nPostureCJK );
+ rItemSet.Put( aPosture );
+ aPosture.SetWhich( aItemIds.nPostureCTL );
+ rItemSet.Put( aPosture );
+
+ rItemSet.Put( SvxCaseMapItem( eCaseMap, aItemIds.nCaseMap ) );
+
+ SvxWeightItem aWeight( eWeight, aItemIds.nWeight );
+ rItemSet.Put( aWeight );
+ aWeight.SetWhich( aItemIds.nWeightCJK );
+ rItemSet.Put( aWeight );
+ aWeight.SetWhich( aItemIds.nWeightCTL );
+ rItemSet.Put( aWeight );
+
+ // font-size
+ CSS1Expression aExpr( pExpr->GetType(), pExpr->GetString(),
+ pExpr->GetNumber() );
+ ParseCSS1_font_size( &aExpr, rItemSet, rPropInfo, rParser );
+ pExpr = pExpr->GetNext();
+
+ if( !pExpr )
+ return;
+
+ // [ '/' line-height ]?
+ if( '/' == pExpr->GetOp() )
+ {
+ // '/' line-height
+ aExpr.Set( pExpr->GetType(), pExpr->GetString(), pExpr->GetNumber() );
+ ParseCSS1_line_height( &aExpr, rItemSet, rPropInfo, rParser );
+
+ pExpr = pExpr->GetNext();
+ }
+
+ if( !pExpr || pExpr->GetOp() )
+ return;
+
+ // font-family
+ ParseCSS1_font_family( pExpr, rItemSet, rPropInfo, rParser );
+}
+
+static void ParseCSS1_letter_spacing( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ switch( pExpr->GetType() )
+ {
+ case CSS1_LENGTH:
+ rItemSet.Put( SvxKerningItem( static_cast<short>(pExpr->GetSLength()),
+ aItemIds.nKerning ) );
+ break;
+
+ case CSS1_PIXLENGTH:
+ {
+ double fHeight = pExpr->GetNumber();
+ if (fHeight < SAL_MAX_INT32/2.0 && fHeight > SAL_MIN_INT32/2.0)
+ {
+ tools::Long nPWidth = static_cast<tools::Long>(fHeight);
+ tools::Long nPHeight = 0;
+ SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
+ rItemSet.Put( SvxKerningItem( static_cast<short>(nPWidth), aItemIds.nKerning ) );
+ }
+ }
+ break;
+
+ case CSS1_NUMBER:
+ if( pExpr->GetNumber() == 0 )
+ {
+ // normally unnecessary, but we are tolerant
+ rItemSet.Put( SvxKerningItem( short(0), aItemIds.nKerning ) );
+ }
+ break;
+
+ case CSS1_IDENT:
+ case CSS1_STRING: // As a precaution also MS-IE
+ if( pExpr->GetString().equalsIgnoreAsciiCase( "normal" ) )
+ {
+ rItemSet.Put( SvxKerningItem( short(0), aItemIds.nKerning ) );
+ }
+ break;
+ default:
+ ;
+ }
+}
+
+static void ParseCSS1_text_decoration( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ bool bUnderline = false;
+ bool bOverline = false;
+ bool bCrossedOut = false;
+ bool bBlink = false;
+ bool bBlinkOn = false;
+ FontLineStyle eUnderline = LINESTYLE_NONE;
+ FontLineStyle eOverline = LINESTYLE_NONE;
+ FontStrikeout eCrossedOut = STRIKEOUT_NONE;
+
+ // the value can contain two values! And MS-IE also strings
+ while( pExpr && (pExpr->GetType() == CSS1_IDENT ||
+ pExpr->GetType() == CSS1_STRING) && !pExpr->GetOp() )
+ {
+ OUString aValue = pExpr->GetString().toAsciiLowerCase();
+ bool bKnown = false;
+
+ switch( aValue[0] )
+ {
+ case 'n':
+ if( aValue == "none" )
+ {
+ bUnderline = true;
+ eUnderline = LINESTYLE_NONE;
+
+ bOverline = true;
+ eOverline = LINESTYLE_NONE;
+
+ bCrossedOut = true;
+ eCrossedOut = STRIKEOUT_NONE;
+
+ bBlink = true;
+ bBlinkOn = false;
+
+ bKnown = true;
+ }
+ break;
+
+ case 'u':
+ if( aValue == "underline" )
+ {
+ bUnderline = true;
+ eUnderline = LINESTYLE_SINGLE;
+
+ bKnown = true;
+ }
+ break;
+
+ case 'o':
+ if( aValue == "overline" )
+ {
+ bOverline = true;
+ eOverline = LINESTYLE_SINGLE;
+
+ bKnown = true;
+ }
+ break;
+
+ case 'l':
+ if( aValue == "line-through" )
+ {
+ bCrossedOut = true;
+ eCrossedOut = STRIKEOUT_SINGLE;
+
+ bKnown = true;
+ }
+ break;
+
+ case 'b':
+ if( aValue == "blink" )
+ {
+ bBlink = true;
+ bBlinkOn = true;
+
+ bKnown = true;
+ }
+ break;
+ }
+
+ if( !bKnown )
+ {
+ bUnderline = true;
+ eUnderline = LINESTYLE_SINGLE;
+ }
+
+ pExpr = pExpr->GetNext();
+ }
+
+ if( bUnderline )
+ rItemSet.Put( SvxUnderlineItem( eUnderline, aItemIds.nUnderline ) );
+
+ if( bOverline )
+ rItemSet.Put( SvxOverlineItem( eOverline, aItemIds.nOverline ) );
+
+ if( bCrossedOut )
+ rItemSet.Put( SvxCrossedOutItem( eCrossedOut, aItemIds.nCrossedOut ) );
+
+ if( bBlink )
+ rItemSet.Put( SvxBlinkItem( bBlinkOn, aItemIds.nBlink ) );
+}
+
+static void ParseCSS1_text_align( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ if( CSS1_IDENT==pExpr->GetType() ||
+ CSS1_STRING==pExpr->GetType() ) // MS-IE, again
+ {
+ sal_uInt16 nAdjust;
+ if( SvxCSS1Parser::GetEnum( aTextAlignTable, pExpr->GetString(),
+ nAdjust ) )
+ {
+ rItemSet.Put( SvxAdjustItem( static_cast<SvxAdjust>(nAdjust),
+ aItemIds.nAdjust ) );
+ }
+ }
+}
+
+static void ParseCSS1_text_indent( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ short nIndent = 0;
+ bool bSet = false;
+ switch( pExpr->GetType() )
+ {
+ case CSS1_LENGTH:
+ {
+ double n = std::round(pExpr->GetNumber());
+ SAL_WARN_IF(
+ n < std::numeric_limits<short>::min() || n > std::numeric_limits<short>::max(),
+ "sw.html", "clamping length " << n << " to short range");
+ nIndent = static_cast<short>(
+ std::clamp(
+ n, double(std::numeric_limits<short>::min()),
+ double(std::numeric_limits<short>::max())));
+ bSet = true;
+ }
+ break;
+ case CSS1_PIXLENGTH:
+ {
+ double fWidth = pExpr->GetNumber();
+ if (fWidth < SAL_MAX_INT32/2.0 && fWidth > SAL_MIN_INT32/2.0)
+ {
+ tools::Long nPWidth = static_cast<tools::Long>(fWidth);
+ tools::Long nPHeight = 0;
+ SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
+ nIndent = static_cast<short>(nPWidth);
+ bSet = true;
+ }
+ }
+ break;
+ case CSS1_PERCENTAGE:
+ // we aren't able
+ break;
+ default:
+ ;
+ }
+
+ if( !bSet )
+ return;
+
+ SvxFirstLineIndentItem const firstLine(nIndent, RES_MARGIN_FIRSTLINE);
+ rItemSet.Put(firstLine);
+ rPropInfo.m_bTextIndent = true;
+}
+
+static void ParseCSS1_margin_left( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ tools::Long nLeft = 0;
+ bool bSet = false;
+ switch( pExpr->GetType() )
+ {
+ case CSS1_LENGTH:
+ {
+ nLeft = pExpr->GetSLength();
+ bSet = true;
+ }
+ break;
+ case CSS1_PIXLENGTH:
+ {
+ double fLeft = pExpr->GetNumber();
+ if (fLeft < SAL_MAX_INT32/2.0 && fLeft > SAL_MIN_INT32/2.0)
+ {
+ nLeft = static_cast<tools::Long>(fLeft);
+ tools::Long nPHeight = 0;
+ SvxCSS1Parser::PixelToTwip( nLeft, nPHeight );
+ bSet = true;
+ }
+ else
+ {
+ SAL_WARN("sw.html", "out-of-size pxlength: " << fLeft);
+ }
+ }
+ break;
+ case CSS1_PERCENTAGE:
+ // we aren't able
+ break;
+ default:
+ ;
+ }
+
+ if (pExpr->GetString() == "auto")
+ {
+ rPropInfo.m_bLeftMargin = true;
+ rPropInfo.m_eLeftMarginType = SVX_CSS1_LTYPE_AUTO;
+ }
+
+ if( !bSet )
+ return;
+
+ rPropInfo.m_nLeftMargin = nLeft;
+ if( nLeft < 0 )
+ nLeft = 0;
+
+ // TODO: other things may need a SvxLeftMarginItem ? but they currently convert it anyway so they can convert that too.
+ SvxTextLeftMarginItem const leftMargin(o3tl::narrowing<sal_uInt16>(nLeft), RES_MARGIN_TEXTLEFT);
+ rItemSet.Put(leftMargin);
+ rPropInfo.m_bLeftMargin = true;
+}
+
+static void ParseCSS1_margin_right( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ tools::Long nRight = 0;
+ bool bSet = false;
+ switch( pExpr->GetType() )
+ {
+ case CSS1_LENGTH:
+ {
+ nRight = pExpr->GetSLength();
+ bSet = true;
+ }
+ break;
+ case CSS1_PIXLENGTH:
+ {
+ double fRight = pExpr->GetNumber();
+ if (fRight < SAL_MAX_INT32/2.0 && fRight > SAL_MIN_INT32/2.0)
+ {
+ nRight = static_cast<tools::Long>(fRight);
+ tools::Long nPHeight = 0;
+ SvxCSS1Parser::PixelToTwip( nRight, nPHeight );
+ bSet = true;
+ }
+ }
+ break;
+ case CSS1_PERCENTAGE:
+ // we aren't able
+ break;
+ default:
+ ;
+ }
+
+ if (pExpr->GetString() == "auto")
+ {
+ rPropInfo.m_bRightMargin = true;
+ rPropInfo.m_eRightMarginType = SVX_CSS1_LTYPE_AUTO;
+ }
+
+ if( !bSet )
+ return;
+
+ rPropInfo.m_nRightMargin = nRight;
+ if( nRight < 0 )
+ nRight = 0;
+
+ SvxRightMarginItem rightMargin(o3tl::narrowing<sal_uInt16>(nRight), RES_MARGIN_RIGHT);
+ rItemSet.Put(rightMargin);
+ rPropInfo.m_bRightMargin = true;
+}
+
+static void ParseCSS1_margin_top( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ assert(pExpr && "no expression");
+
+ sal_uInt16 nUpper = 0;
+ bool bSet = false;
+ switch( pExpr->GetType() )
+ {
+ case CSS1_LENGTH:
+ {
+ tools::Long nTmp = pExpr->GetSLength();
+ if( nTmp < 0 )
+ nTmp = 0;
+ nUpper = o3tl::narrowing<sal_uInt16>(nTmp);
+ bSet = true;
+ }
+ break;
+ case CSS1_PIXLENGTH:
+ {
+ double fHeight = pExpr->GetNumber();
+ if (fHeight < SAL_MAX_INT32/2.0 && fHeight > SAL_MIN_INT32/2.0)
+ {
+ tools::Long nPWidth = 0;
+ tools::Long nPHeight = static_cast<tools::Long>(fHeight);
+ if( nPHeight < 0 )
+ nPHeight = 0;
+ SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
+ nUpper = o3tl::narrowing<sal_uInt16>(nPHeight);
+ bSet = true;
+ }
+ }
+ break;
+ case CSS1_PERCENTAGE:
+ // we aren't able
+ break;
+ default:
+ ;
+ }
+
+ if( !bSet )
+ return;
+
+ if( const SvxULSpaceItem* pItem = rItemSet.GetItemIfSet( aItemIds.nULSpace, false ) )
+ {
+ SvxULSpaceItem aULItem( *pItem );
+ aULItem.SetUpper( nUpper );
+ rItemSet.Put( aULItem );
+ }
+ else
+ {
+ SvxULSpaceItem aULItem( aItemIds.nULSpace );
+ aULItem.SetUpper( nUpper );
+ rItemSet.Put( aULItem );
+ }
+ rPropInfo.m_bTopMargin = true;
+}
+
+static void ParseCSS1_margin_bottom( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ sal_uInt16 nLower = 0;
+ bool bSet = false;
+ switch( pExpr->GetType() )
+ {
+ case CSS1_LENGTH:
+ {
+ tools::Long nTmp = pExpr->GetSLength();
+ if( nTmp < 0 )
+ nTmp = 0;
+ nLower = o3tl::narrowing<sal_uInt16>(nTmp);
+ bSet = true;
+ }
+ break;
+ case CSS1_PIXLENGTH:
+ {
+ double fHeight = pExpr->GetNumber();
+ if (fHeight < SAL_MAX_INT32/2.0 && fHeight > SAL_MIN_INT32/2.0)
+ {
+ tools::Long nPWidth = 0;
+ tools::Long nPHeight = static_cast<tools::Long>(fHeight);
+ if( nPHeight < 0 )
+ nPHeight = 0;
+ SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
+ nLower = o3tl::narrowing<sal_uInt16>(nPHeight);
+ bSet = true;
+ }
+ }
+ break;
+ case CSS1_PERCENTAGE:
+ // we aren't able
+ break;
+ default:
+ ;
+ }
+
+ if( !bSet )
+ return;
+
+ if( const SvxULSpaceItem* pItem = rItemSet.GetItemIfSet( aItemIds.nULSpace, false ) )
+ {
+ SvxULSpaceItem aULItem( *pItem );
+ aULItem.SetLower( nLower );
+ rItemSet.Put( aULItem );
+ }
+ else
+ {
+ SvxULSpaceItem aULItem( aItemIds.nULSpace );
+ aULItem.SetLower( nLower );
+ rItemSet.Put( aULItem );
+ }
+ rPropInfo.m_bBottomMargin = true;
+}
+
+static void ParseCSS1_margin( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ tools::Long nMargins[4] = { 0, 0, 0, 0 };
+ bool bSetMargins[4] = { false, false, false, false };
+
+ for( int i=0; pExpr && i<4 && !pExpr->GetOp(); ++i )
+ {
+ bool bSetThis = false;
+ tools::Long nMargin = 0;
+
+ switch( pExpr->GetType() )
+ {
+ case CSS1_LENGTH:
+ {
+ nMargin = pExpr->GetSLength();
+ bSetThis = true;
+ }
+ break;
+ case CSS1_PIXLENGTH:
+ {
+ double fMargin = pExpr->GetNumber();
+ if (fMargin < SAL_MAX_INT32/2.0 && fMargin > SAL_MIN_INT32/2.0)
+ {
+ nMargin = static_cast<tools::Long>(fMargin);
+ tools::Long nPWidth = 0;
+ SvxCSS1Parser::PixelToTwip( nPWidth, nMargin );
+ bSetThis = true;
+ }
+ else
+ {
+ SAL_WARN("sw.html", "out-of-size pxlength: " << fMargin);
+ }
+ }
+ break;
+ case CSS1_PERCENTAGE:
+ // we aren't able
+ break;
+ default:
+ ;
+ }
+
+ if( bSetThis )
+ {
+ // 0 = top
+ // 1 = right
+ // 2 = bottom
+ // 3 = left
+ switch( i )
+ {
+ case 0:
+ nMargins[0] = nMargins[1] =nMargins[2] = nMargins[3] = nMargin;
+ bSetMargins[0] = bSetMargins[1] =
+ bSetMargins[2] = bSetMargins[3] = true;
+ break;
+ case 1:
+ nMargins[1] = nMargins[3] = nMargin; // right + left
+ bSetMargins[1] = bSetMargins[3] = true;
+ break;
+ case 2:
+ nMargins[2] = nMargin; // bottom
+ bSetMargins[2] = true;
+ break;
+ case 3:
+ nMargins[3] = nMargin; // left
+ bSetMargins[3] = true;
+ break;
+ }
+ }
+ pExpr = pExpr->GetNext();
+ }
+
+ if( bSetMargins[3] || bSetMargins[1] )
+ {
+ if( bSetMargins[3] )
+ {
+ rPropInfo.m_bLeftMargin = true;
+ rPropInfo.m_nLeftMargin = nMargins[3];
+ if( nMargins[3] < 0 )
+ nMargins[3] = 0;
+ }
+ if( bSetMargins[1] )
+ {
+ rPropInfo.m_bRightMargin = true;
+ rPropInfo.m_nRightMargin = nMargins[1];
+ if( nMargins[1] < 0 )
+ nMargins[1] = 0;
+ }
+
+ if (bSetMargins[3])
+ {
+ SvxTextLeftMarginItem const leftMargin(o3tl::narrowing<sal_uInt16>(nMargins[3]), RES_MARGIN_TEXTLEFT);
+ rItemSet.Put(leftMargin);
+ }
+ if (bSetMargins[1])
+ {
+ SvxRightMarginItem const rightMargin(o3tl::narrowing<sal_uInt16>(nMargins[1]), RES_MARGIN_RIGHT);
+ rItemSet.Put(rightMargin);
+ }
+ }
+
+ if( !(bSetMargins[0] || bSetMargins[2]) )
+ return;
+
+ if( nMargins[0] < 0 )
+ nMargins[0] = 0;
+ if( nMargins[2] < 0 )
+ nMargins[2] = 0;
+
+ if( const SvxULSpaceItem* pItem = rItemSet.GetItemIfSet( aItemIds.nULSpace, false ) )
+ {
+ SvxULSpaceItem aULItem( *pItem );
+ if( bSetMargins[0] )
+ aULItem.SetUpper( o3tl::narrowing<sal_uInt16>(nMargins[0]) );
+ if( bSetMargins[2] )
+ aULItem.SetLower( o3tl::narrowing<sal_uInt16>(nMargins[2]) );
+ rItemSet.Put( aULItem );
+ }
+ else
+ {
+ SvxULSpaceItem aULItem( aItemIds.nULSpace );
+ if( bSetMargins[0] )
+ aULItem.SetUpper( o3tl::narrowing<sal_uInt16>(nMargins[0]) );
+ if( bSetMargins[2] )
+ aULItem.SetLower( o3tl::narrowing<sal_uInt16>(nMargins[2]) );
+ rItemSet.Put( aULItem );
+ }
+
+ rPropInfo.m_bTopMargin |= bSetMargins[0];
+ rPropInfo.m_bBottomMargin |= bSetMargins[2];
+}
+
+static bool ParseCSS1_padding_xxx( const CSS1Expression *pExpr,
+ SvxCSS1PropertyInfo& rPropInfo,
+ SvxBoxItemLine nWhichLine )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ bool bSet = false;
+ sal_uInt16 nDist = 0;
+
+ switch( pExpr->GetType() )
+ {
+ case CSS1_LENGTH:
+ {
+ tools::Long nTmp = pExpr->GetSLength();
+ if( nTmp < 0 )
+ nTmp = 0;
+ else if( nTmp > SvxCSS1PropertyInfo::UNSET_BORDER_DISTANCE-1 )
+ nTmp = SvxCSS1PropertyInfo::UNSET_BORDER_DISTANCE-1;
+ nDist = o3tl::narrowing<sal_uInt16>(nTmp);
+ bSet = true;
+ }
+ break;
+ case CSS1_PIXLENGTH:
+ {
+ double fWidth = pExpr->GetNumber();
+ if (fWidth < SAL_MAX_INT32/2.0 && fWidth > SAL_MIN_INT32/2.0)
+ {
+ tools::Long nPWidth = static_cast<tools::Long>(fWidth);
+ tools::Long nPHeight = 0;
+ if( nPWidth < 0 )
+ nPWidth = 0;
+ SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
+ if( nPWidth > SvxCSS1PropertyInfo::UNSET_BORDER_DISTANCE-1 )
+ nPWidth = SvxCSS1PropertyInfo::UNSET_BORDER_DISTANCE-1;
+ nDist = o3tl::narrowing<sal_uInt16>(nPWidth);
+ bSet = true;
+ }
+ }
+ break;
+ case CSS1_PERCENTAGE:
+ // we aren't able
+ break;
+ default:
+ ;
+ }
+
+ if( bSet )
+ {
+ switch( nWhichLine )
+ {
+ case SvxBoxItemLine::TOP: rPropInfo.m_nTopBorderDistance = nDist; break;
+ case SvxBoxItemLine::BOTTOM: rPropInfo.m_nBottomBorderDistance = nDist;break;
+ case SvxBoxItemLine::LEFT: rPropInfo.m_nLeftBorderDistance = nDist; break;
+ case SvxBoxItemLine::RIGHT: rPropInfo.m_nRightBorderDistance = nDist; break;
+ }
+ }
+
+ return bSet;
+}
+
+static void ParseCSS1_padding_top( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ ParseCSS1_padding_xxx( pExpr, rPropInfo, SvxBoxItemLine::TOP );
+}
+
+static void ParseCSS1_padding_bottom( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ ParseCSS1_padding_xxx( pExpr, rPropInfo, SvxBoxItemLine::BOTTOM );
+}
+
+static void ParseCSS1_padding_left( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ ParseCSS1_padding_xxx( pExpr, rPropInfo, SvxBoxItemLine::LEFT );
+}
+
+static void ParseCSS1_padding_right( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ ParseCSS1_padding_xxx( pExpr, rPropInfo, SvxBoxItemLine::RIGHT );
+}
+
+static void ParseCSS1_padding( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ int n=0;
+ while( n<4 && pExpr && !pExpr->GetOp() )
+ {
+ SvxBoxItemLine nLine = n==0 || n==2 ? SvxBoxItemLine::BOTTOM : SvxBoxItemLine::LEFT;
+ if( ParseCSS1_padding_xxx( pExpr, rPropInfo, nLine ) )
+ {
+ if( n==0 )
+ {
+ rPropInfo.m_nTopBorderDistance = rPropInfo.m_nBottomBorderDistance;
+ rPropInfo.m_nLeftBorderDistance = rPropInfo.m_nTopBorderDistance;
+ }
+ if( n <= 1 )
+ rPropInfo.m_nRightBorderDistance = rPropInfo.m_nLeftBorderDistance;
+ }
+
+ pExpr = pExpr->GetNext();
+ n++;
+ }
+}
+
+static void ParseCSS1_border_xxx( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/,
+ SvxBoxItemLine nWhichLine, bool bAll )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ sal_uInt16 nWidth = USHRT_MAX; // line thickness
+ sal_uInt16 nNWidth = 1; // named line thickness (and default)
+ CSS1BorderStyle eStyle = CSS1_BS_NONE; // line style
+ Color aColor;
+ bool bColor = false;
+
+ while( pExpr && !pExpr->GetOp() )
+ {
+ switch( pExpr->GetType() )
+ {
+ case CSS1_RGB:
+ case CSS1_HEXCOLOR:
+ if( pExpr->GetColor( aColor ) )
+ bColor = true;
+ break;
+
+ case CSS1_IDENT:
+ {
+ const OUString& rValue = pExpr->GetString();
+ sal_uInt16 nValue;
+ if( SvxCSS1Parser::GetEnum( aBorderWidthTable, rValue, nValue ) )
+ {
+ nNWidth = nValue;
+ }
+ else if( SvxCSS1Parser::GetEnum( aBorderStyleTable, rValue, nValue ) )
+ {
+ eStyle = static_cast<CSS1BorderStyle>(nValue);
+ }
+ else if( pExpr->GetColor( aColor ) )
+ {
+ bColor = true;
+ }
+ }
+ break;
+
+ case CSS1_LENGTH:
+ nWidth = o3tl::narrowing<sal_uInt16>(pExpr->GetULength());
+ break;
+
+ case CSS1_PIXLENGTH:
+ {
+ // One Pixel becomes a hairline (is prettier)
+ double fWidth = pExpr->GetNumber();
+ if (fWidth > 1.0 && fWidth < SAL_MAX_INT32/2.0)
+ {
+ bool bHori = nWhichLine == SvxBoxItemLine::TOP ||
+ nWhichLine == SvxBoxItemLine::BOTTOM;
+
+ tools::Long nPWidth = bHori ? 0 : fWidth;
+ tools::Long nPHeight = bHori ? fWidth : 0;
+ SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
+ nWidth = o3tl::narrowing<sal_uInt16>(bHori ? nPHeight : nPWidth);
+ }
+ else
+ nWidth = 1;
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ pExpr = pExpr->GetNext();
+ }
+
+ for( int i=0; i<4; ++i )
+ {
+ SvxBoxItemLine nLine = SvxBoxItemLine::TOP;
+ switch( i )
+ {
+ case 0: nLine = SvxBoxItemLine::TOP; break;
+ case 1: nLine = SvxBoxItemLine::BOTTOM; break;
+ case 2: nLine = SvxBoxItemLine::LEFT; break;
+ case 3: nLine = SvxBoxItemLine::RIGHT; break;
+ }
+
+ if( bAll || nLine == nWhichLine )
+ {
+ SvxCSS1BorderInfo *pInfo = rPropInfo.GetBorderInfo( nLine );
+ pInfo->eStyle = eStyle;
+ pInfo->nAbsWidth = nWidth;
+ pInfo->nNamedWidth = nNWidth;
+ if( bColor )
+ pInfo->aColor = aColor;
+ }
+ }
+}
+
+static void ParseCSS1_border_xxx_width( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/,
+ SvxBoxItemLine nWhichLine )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ sal_uInt16 nWidth = USHRT_MAX; // line thickness
+ sal_uInt16 nNWidth = 1; // named line thickness (and default)
+
+ switch( pExpr->GetType() )
+ {
+ case CSS1_IDENT:
+ {
+ sal_uInt16 nValue;
+ if( SvxCSS1Parser::GetEnum( aBorderWidthTable, pExpr->GetString(), nValue ) )
+ {
+ nNWidth = nValue;
+ }
+ }
+ break;
+
+ case CSS1_LENGTH:
+ nWidth = o3tl::narrowing<sal_uInt16>(pExpr->GetULength());
+ break;
+
+ case CSS1_PIXLENGTH:
+ {
+ double fLength = pExpr->GetNumber();
+ if (fLength < SAL_MAX_INT32/2.0 && fLength > SAL_MIN_INT32/2.0)
+ {
+ tools::Long nWidthL = static_cast<tools::Long>(fLength);
+
+ bool bHori = nWhichLine == SvxBoxItemLine::TOP ||
+ nWhichLine == SvxBoxItemLine::BOTTOM;
+
+ tools::Long nPWidth = bHori ? 0 : nWidthL;
+ tools::Long nPHeight = bHori ? nWidthL : 0;
+ SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
+ nWidth = o3tl::narrowing<sal_uInt16>(bHori ? nPHeight : nPWidth);
+ }
+ }
+ break;
+
+ default:
+ ;
+ }
+
+ SvxCSS1BorderInfo *pInfo = rPropInfo.GetBorderInfo( nWhichLine );
+ pInfo->nAbsWidth = nWidth;
+ pInfo->nNamedWidth = nNWidth;
+}
+
+static void ParseCSS1_border_top_width( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser )
+{
+ ParseCSS1_border_xxx_width( pExpr, rItemSet, rPropInfo, rParser, SvxBoxItemLine::TOP );
+}
+
+static void ParseCSS1_border_right_width( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser )
+{
+ ParseCSS1_border_xxx_width( pExpr, rItemSet, rPropInfo, rParser, SvxBoxItemLine::RIGHT );
+}
+
+static void ParseCSS1_border_bottom_width( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser )
+{
+ ParseCSS1_border_xxx_width( pExpr, rItemSet, rPropInfo, rParser, SvxBoxItemLine::BOTTOM );
+}
+
+static void ParseCSS1_border_left_width( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser )
+{
+ ParseCSS1_border_xxx_width( pExpr, rItemSet, rPropInfo, rParser, SvxBoxItemLine::LEFT );
+}
+
+static void ParseCSS1_border_width( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser )
+{
+ sal_uInt16 n=0;
+ while( n<4 && pExpr && !pExpr->GetOp() )
+ {
+ SvxBoxItemLine nLine = n==0 || n==2 ? SvxBoxItemLine::BOTTOM : SvxBoxItemLine::LEFT;
+ ParseCSS1_border_xxx_width( pExpr, rItemSet, rPropInfo, rParser, nLine );
+ rPropInfo.CopyBorderInfo( n, SVX_CSS1_BORDERINFO_WIDTH );
+
+ pExpr = pExpr->GetNext();
+ n++;
+ }
+}
+
+static void ParseCSS1_border_color( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ sal_uInt16 n=0;
+ while( n<4 && pExpr && !pExpr->GetOp() )
+ {
+ SvxBoxItemLine nLine = n==0 || n==2 ? SvxBoxItemLine::BOTTOM : SvxBoxItemLine::LEFT;
+ Color aColor;
+ switch( pExpr->GetType() )
+ {
+ case CSS1_RGB:
+ case CSS1_HEXCOLOR:
+ case CSS1_IDENT:
+ if( pExpr->GetColor( aColor ) )
+ rPropInfo.GetBorderInfo( nLine )->aColor = aColor;
+ break;
+ default:
+ ;
+ }
+ rPropInfo.CopyBorderInfo( n, SVX_CSS1_BORDERINFO_COLOR );
+
+ pExpr = pExpr->GetNext();
+ n++;
+ }
+}
+
+static void ParseCSS1_border_style( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ sal_uInt16 n=0;
+ while( n<4 && pExpr && !pExpr->GetOp() )
+ {
+ SvxBoxItemLine nLine = n==0 || n==2 ? SvxBoxItemLine::BOTTOM : SvxBoxItemLine::LEFT;
+ sal_uInt16 nValue = 0;
+ if( CSS1_IDENT==pExpr->GetType() &&
+ SvxCSS1Parser::GetEnum( aBorderStyleTable, pExpr->GetString(),
+ nValue ) )
+ {
+ rPropInfo.GetBorderInfo( nLine )->eStyle = static_cast<CSS1BorderStyle>(nValue);
+ }
+ rPropInfo.CopyBorderInfo( n, SVX_CSS1_BORDERINFO_STYLE );
+
+ pExpr = pExpr->GetNext();
+ n++;
+ }
+}
+
+static void ParseCSS1_border_top( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser )
+{
+ ParseCSS1_border_xxx( pExpr, rItemSet, rPropInfo, rParser, SvxBoxItemLine::TOP, false );
+}
+
+static void ParseCSS1_border_right( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser )
+{
+ ParseCSS1_border_xxx( pExpr, rItemSet, rPropInfo, rParser, SvxBoxItemLine::RIGHT, false );
+}
+
+static void ParseCSS1_border_bottom( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser )
+{
+ ParseCSS1_border_xxx( pExpr, rItemSet, rPropInfo, rParser, SvxBoxItemLine::BOTTOM, false );
+}
+
+static void ParseCSS1_border_left( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser )
+{
+ ParseCSS1_border_xxx( pExpr, rItemSet, rPropInfo, rParser, SvxBoxItemLine::LEFT, false );
+}
+
+static void ParseCSS1_border( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& rParser )
+{
+ ParseCSS1_border_xxx( pExpr, rItemSet, rPropInfo, rParser, SvxBoxItemLine::TOP, true );
+}
+
+static void ParseCSS1_float( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ if( CSS1_IDENT==pExpr->GetType() )
+ {
+ sal_uInt16 nFloat;
+ if( SvxCSS1Parser::GetEnum( aFloatTable, pExpr->GetString(), nFloat ) )
+ rPropInfo.m_eFloat = static_cast<SvxAdjust>(nFloat);
+ }
+}
+
+static void ParseCSS1_position( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ OSL_ENSURE( pExpr, "no expression" );
+
+ if( CSS1_IDENT==pExpr->GetType() )
+ {
+ sal_uInt16 nPos;
+ if( SvxCSS1Parser::GetEnum( aPositionTable, pExpr->GetString(), nPos ) )
+ rPropInfo.m_ePosition = static_cast<SvxCSS1Position>(nPos);
+ }
+}
+
+static void ParseCSS1_length( const CSS1Expression *pExpr,
+ tools::Long& rLength,
+ SvxCSS1LengthType& rLengthType,
+ bool bHori )
+{
+ switch( pExpr->GetType() )
+ {
+ case CSS1_IDENT:
+ if( pExpr->GetString().equalsIgnoreAsciiCase( "auto" ) )
+ {
+ rLength = 0;
+ rLengthType = SVX_CSS1_LTYPE_AUTO;
+ }
+ break;
+
+ case CSS1_LENGTH:
+ rLength = pExpr->GetSLength();
+ rLengthType = SVX_CSS1_LTYPE_TWIP;
+ break;
+
+ case CSS1_PIXLENGTH:
+ case CSS1_NUMBER: // because of Netscape and IE
+ {
+ double fLength = pExpr->GetNumber();
+ if (fLength < SAL_MAX_INT32/2.0 && fLength > SAL_MIN_INT32/2.0)
+ {
+ tools::Long nWidthL = static_cast<tools::Long>(fLength);
+ tools::Long nPWidth = bHori ? 0 : nWidthL;
+ tools::Long nPHeight = bHori ? nWidthL : 0;
+ SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
+ rLength = (bHori ? nPHeight : nPWidth);
+ rLengthType = SVX_CSS1_LTYPE_TWIP;
+ }
+ }
+ break;
+
+ case CSS1_PERCENTAGE:
+ rLength = static_cast<tools::Long>(std::min(pExpr->GetNumber(), 100.0));
+ rLengthType = SVX_CSS1_LTYPE_PERCENTAGE;
+ break;
+
+ default:
+ ;
+ }
+}
+
+static void ParseCSS1_width( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ ParseCSS1_length( pExpr, rPropInfo.m_nWidth, rPropInfo.m_eWidthType, true );
+}
+
+static void ParseCSS1_height( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ ParseCSS1_length( pExpr, rPropInfo.m_nHeight, rPropInfo.m_eHeightType, false );
+}
+
+static void ParseCSS1_left( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ ParseCSS1_length( pExpr, rPropInfo.m_nLeft, rPropInfo.m_eLeftType, true );
+}
+
+static void ParseCSS1_top( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ ParseCSS1_length( pExpr, rPropInfo.m_nTop, rPropInfo.m_eTopType, false );
+}
+
+// Feature: PrintExt
+static void ParseCSS1_size( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ int n=0;
+ while( n<2 && pExpr && !pExpr->GetOp() )
+ {
+ switch( pExpr->GetType() )
+ {
+ case CSS1_IDENT:
+ {
+ sal_uInt16 nValue;
+ if( SvxCSS1Parser::GetEnum( aSizeTable, pExpr->GetString(),
+ nValue ) )
+ {
+ rPropInfo.m_eSizeType = static_cast<SvxCSS1SizeType>(nValue);
+ }
+ }
+ break;
+
+ case CSS1_LENGTH:
+ rPropInfo.m_nHeight = pExpr->GetSLength();
+ if( n==0 )
+ rPropInfo.m_nWidth = rPropInfo.m_nHeight;
+ rPropInfo.m_eSizeType = SVX_CSS1_STYPE_TWIP;
+ break;
+
+ case CSS1_PIXLENGTH:
+ {
+ double fHeight = pExpr->GetNumber();
+ if (fHeight < SAL_MAX_INT32/2.0 && fHeight > SAL_MIN_INT32/2.0)
+ {
+ tools::Long nPHeight = static_cast<tools::Long>(fHeight);
+ tools::Long nPWidth = n==0 ? nPHeight : 0;
+ SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight );
+ rPropInfo.m_nHeight = nPHeight;
+ if( n==0 )
+ rPropInfo.m_nWidth = nPWidth;
+ rPropInfo.m_eSizeType = SVX_CSS1_STYPE_TWIP;
+ }
+ break;
+ }
+ default:
+ ;
+ }
+
+ pExpr = pExpr->GetNext();
+ n++;
+ }
+}
+
+static void ParseCSS1_page_break_xxx( const CSS1Expression *pExpr,
+ SvxCSS1PageBreak& rPBreak )
+{
+ if( CSS1_IDENT == pExpr->GetType() )
+ {
+ sal_uInt16 nValue;
+ if( SvxCSS1Parser::GetEnum( aPageBreakTable, pExpr->GetString(),
+ nValue ) )
+ {
+ rPBreak = static_cast<SvxCSS1PageBreak>(nValue);
+ }
+ }
+}
+
+static void ParseCSS1_page_break_before( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ ParseCSS1_page_break_xxx( pExpr, rPropInfo.m_ePageBreakBefore );
+}
+
+static void ParseCSS1_page_break_after( const CSS1Expression *pExpr,
+ SfxItemSet & /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ ParseCSS1_page_break_xxx( pExpr, rPropInfo.m_ePageBreakAfter );
+}
+
+static void ParseCSS1_page_break_inside( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ SvxCSS1PageBreak eBreak(SVX_CSS1_PBREAK_NONE);
+ ParseCSS1_page_break_xxx( pExpr, eBreak );
+
+ bool bSetSplit = false, bSplit = true;
+ switch( eBreak )
+ {
+ case SVX_CSS1_PBREAK_AUTO:
+ bSetSplit = true;
+ break;
+ case SVX_CSS1_PBREAK_AVOID:
+ bSplit = false;
+ bSetSplit = true;
+ break;
+ default:
+ ;
+ }
+
+ if( bSetSplit )
+ rItemSet.Put( SvxFormatSplitItem( bSplit, aItemIds.nFormatSplit ) );
+}
+
+static void ParseCSS1_widows( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ if( CSS1_NUMBER == pExpr->GetType() )
+ {
+ sal_uInt8 nVal = pExpr->GetNumber() <= 255
+ ? static_cast<sal_uInt8>(pExpr->GetNumber())
+ : 255;
+ SvxWidowsItem aWidowsItem( nVal, aItemIds.nWidows );
+ rItemSet.Put( aWidowsItem );
+ }
+}
+
+static void ParseCSS1_orphans( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ if( CSS1_NUMBER == pExpr->GetType() )
+ {
+ sal_uInt8 nVal = pExpr->GetNumber() <= 255
+ ? static_cast<sal_uInt8>(pExpr->GetNumber())
+ : 255;
+ SvxOrphansItem aOrphansItem( nVal, aItemIds.nOrphans );
+ rItemSet.Put( aOrphansItem );
+ }
+}
+
+static void ParseCSS1_so_language( const CSS1Expression *pExpr,
+ SfxItemSet &rItemSet,
+ SvxCSS1PropertyInfo& /*rPropInfo*/,
+ const SvxCSS1Parser& /*rParser*/ )
+{
+ if( CSS1_IDENT != pExpr->GetType() && CSS1_STRING != pExpr->GetType() )
+ return;
+
+ LanguageType eLang = LanguageTag::convertToLanguageTypeWithFallback( pExpr->GetString() );
+ if( LANGUAGE_DONTKNOW != eLang )
+ {
+ SvxLanguageItem aLang( eLang, aItemIds.nLanguage );
+ rItemSet.Put( aLang );
+ aLang.SetWhich( aItemIds.nLanguageCJK );
+ rItemSet.Put( aLang );
+ aLang.SetWhich( aItemIds.nLanguageCTL );
+ rItemSet.Put( aLang );
+ }
+}
+
+static void ParseCSS1_visibility(const CSS1Expression* pExpr, SfxItemSet& /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo, const SvxCSS1Parser& /*rParser*/)
+{
+ if (pExpr->GetType() != CSS1_IDENT)
+ return;
+
+ rPropInfo.m_bVisible = pExpr->GetString() != "hidden";
+}
+
+static void ParseCSS1_white_space(const CSS1Expression* pExpr, SfxItemSet& /*rItemSet*/,
+ SvxCSS1PropertyInfo& rPropInfo, const SvxCSS1Parser& /*rParser*/)
+{
+ if (pExpr->GetType() == CSS1_IDENT)
+ {
+ if (pExpr->GetString().equalsIgnoreAsciiCase("pre")
+ || pExpr->GetString().equalsIgnoreAsciiCase("pre-wrap"))
+ {
+ rPropInfo.m_bPreserveSpace = true;
+ }
+ }
+}
+
+namespace {
+
+// the assignment of property to parsing function
+struct CSS1PropEntry
+{
+ std::string_view pName;
+ FnParseCSS1Prop pFunc;
+};
+
+}
+
+// the table with assignments
+CSS1PropEntry constexpr aCSS1PropFnTab[] =
+{
+ { sCSS1_P_background, ParseCSS1_background },
+ { sCSS1_P_background_color, ParseCSS1_background_color },
+ { sCSS1_P_border, ParseCSS1_border },
+ { sCSS1_P_border_bottom, ParseCSS1_border_bottom },
+ { sCSS1_P_border_bottom_width, ParseCSS1_border_bottom_width },
+ { sCSS1_P_border_color, ParseCSS1_border_color },
+ { sCSS1_P_border_left, ParseCSS1_border_left },
+ { sCSS1_P_border_left_width, ParseCSS1_border_left_width },
+ { sCSS1_P_border_right, ParseCSS1_border_right },
+ { sCSS1_P_border_right_width, ParseCSS1_border_right_width },
+ { sCSS1_P_border_style, ParseCSS1_border_style },
+ { sCSS1_P_border_top, ParseCSS1_border_top },
+ { sCSS1_P_border_top_width, ParseCSS1_border_top_width },
+ { sCSS1_P_border_width, ParseCSS1_border_width },
+ { sCSS1_P_color, ParseCSS1_color },
+ { sCSS1_P_column_count, ParseCSS1_column_count },
+ { sCSS1_P_direction, ParseCSS1_direction },
+ { sCSS1_P_float, ParseCSS1_float },
+ { sCSS1_P_font, ParseCSS1_font },
+ { sCSS1_P_font_family, ParseCSS1_font_family },
+ { sCSS1_P_font_size, ParseCSS1_font_size },
+ { sCSS1_P_font_style, ParseCSS1_font_style },
+ { sCSS1_P_font_variant, ParseCSS1_font_variant },
+ { sCSS1_P_font_weight, ParseCSS1_font_weight },
+ { sCSS1_P_height, ParseCSS1_height },
+ { sCSS1_P_left, ParseCSS1_left },
+ { sCSS1_P_letter_spacing, ParseCSS1_letter_spacing },
+ { sCSS1_P_line_height, ParseCSS1_line_height },
+ { sCSS1_P_list_style_type, ParseCSS1_list_style_type },
+ { sCSS1_P_margin, ParseCSS1_margin },
+ { sCSS1_P_margin_bottom, ParseCSS1_margin_bottom },
+ { sCSS1_P_margin_left, ParseCSS1_margin_left },
+ { sCSS1_P_margin_right, ParseCSS1_margin_right },
+ { sCSS1_P_margin_top, ParseCSS1_margin_top },
+ { sCSS1_P_orphans, ParseCSS1_orphans },
+ { sCSS1_P_padding, ParseCSS1_padding },
+ { sCSS1_P_padding_bottom, ParseCSS1_padding_bottom },
+ { sCSS1_P_padding_left, ParseCSS1_padding_left },
+ { sCSS1_P_padding_right, ParseCSS1_padding_right },
+ { sCSS1_P_padding_top, ParseCSS1_padding_top },
+ { sCSS1_P_page_break_after, ParseCSS1_page_break_after },
+ { sCSS1_P_page_break_before, ParseCSS1_page_break_before },
+ { sCSS1_P_page_break_inside, ParseCSS1_page_break_inside },
+ { sCSS1_P_position, ParseCSS1_position },
+ { sCSS1_P_size, ParseCSS1_size },
+ { sCSS1_P_so_language, ParseCSS1_so_language },
+ { sCSS1_P_text_align, ParseCSS1_text_align },
+ { sCSS1_P_text_decoration, ParseCSS1_text_decoration },
+ { sCSS1_P_text_indent, ParseCSS1_text_indent },
+ { sCSS1_P_text_transform, ParseCSS1_text_transform },
+ { sCSS1_P_top, ParseCSS1_top },
+ { sCSS1_P_visibility, ParseCSS1_visibility },
+ { sCSS1_white_space, ParseCSS1_white_space },
+ { sCSS1_P_widows, ParseCSS1_widows },
+ { sCSS1_P_width, ParseCSS1_width },
+};
+
+static_assert(std::is_sorted(std::begin(aCSS1PropFnTab), std::end(aCSS1PropFnTab),
+ [](const auto& lhs, const auto& rhs) constexpr
+ { return lhs.pName < rhs.pName; }));
+
+static bool CSS1PropEntryFindCompare(CSS1PropEntry const & lhs, OUString const & s)
+{
+ return s.compareToIgnoreAsciiCaseAscii(lhs.pName) > 0;
+}
+
+void SvxCSS1Parser::DeclarationParsed( const OUString& rProperty,
+ std::unique_ptr<CSS1Expression> pExpr )
+{
+ OSL_ENSURE( m_pItemSet, "DeclarationParsed() without ItemSet" );
+
+ auto it = std::lower_bound( std::begin(aCSS1PropFnTab), std::end(aCSS1PropFnTab), rProperty,
+ CSS1PropEntryFindCompare );
+ if( it != std::end(aCSS1PropFnTab) && !CSS1PropEntryFindCompare(*it,rProperty) )
+ {
+ it->pFunc( pExpr.get(), *m_pItemSet, *m_pPropInfo, *this );
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */