summaryrefslogtreecommitdiff
path: root/editeng/source/items/borderline.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'editeng/source/items/borderline.cxx')
-rw-r--r--editeng/source/items/borderline.cxx495
1 files changed, 495 insertions, 0 deletions
diff --git a/editeng/source/items/borderline.cxx b/editeng/source/items/borderline.cxx
new file mode 100644
index 0000000000..de24284b92
--- /dev/null
+++ b/editeng/source/items/borderline.cxx
@@ -0,0 +1,495 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_editeng.hxx"
+
+
+// include ---------------------------------------------------------------
+#include <basegfx/color/bcolor.hxx>
+#include <basegfx/color/bcolortools.hxx>
+
+#include <editeng/borderline.hxx>
+#include <editeng/itemtype.hxx>
+
+// class SvxBorderLine --------------------------------------------------
+
+namespace {
+
+ Color lcl_compute3DColor( Color aMain, int nLight, int nMedium, int nDark )
+ {
+ basegfx::BColor color = aMain.getBColor( );
+ basegfx::BColor hsl = basegfx::tools::rgb2hsl( color );
+
+ int nCoef = 0;
+ if ( hsl.getZ( ) >= 0.5 )
+ nCoef = nLight;
+ else if ( 0.5 > hsl.getZ() && hsl.getZ() >= 0.25 )
+ nCoef = nMedium;
+ else
+ nCoef = nDark;
+
+ double L = hsl.getZ() * 255.0 + nCoef;
+ hsl.setZ( L / 255.0 );
+ color = basegfx::tools::hsl2rgb( hsl );
+
+ return Color( color );
+ }
+} // Anonymous namespace
+
+namespace editeng {
+
+Color SvxBorderLine::darkColor( Color aMain )
+{
+ return aMain;
+}
+
+Color SvxBorderLine::lightColor( Color aMain )
+{
+
+ // Divide Luminance by 2
+ basegfx::BColor color = aMain.getBColor( );
+ basegfx::BColor hsl = basegfx::tools::rgb2hsl( color );
+ hsl.setZ( hsl.getZ() * 0.5 );
+ color = basegfx::tools::hsl2rgb( hsl );
+
+ return Color( color );
+}
+
+
+Color SvxBorderLine::threeDLightColor( Color aMain )
+{
+ // These values have been defined in an empirical way
+ return lcl_compute3DColor( aMain, 3, 40, 83 );
+}
+
+Color SvxBorderLine::threeDDarkColor( Color aMain )
+{
+ // These values have been defined in an empirical way
+ return lcl_compute3DColor( aMain, -85, -43, -1 );
+}
+
+Color SvxBorderLine::threeDMediumColor( Color aMain )
+{
+ // These values have been defined in an empirical way
+ return lcl_compute3DColor( aMain, -42, -0, 42 );
+}
+
+SvxBorderLine::SvxBorderLine( const Color *pCol, long nWidth,
+ SvxBorderStyle nStyle, bool bUseLeftTop,
+ Color (*pColorOutFn)( Color ), Color (*pColorInFn)( Color ),
+ Color (*pColorGapFn)( Color ) )
+: m_nWidth( nWidth )
+, m_bMirrorWidths( false )
+, m_aWidthImpl( SvxBorderLine::getWidthImpl( nStyle ) )
+, m_nMult( 1 )
+, m_nDiv( 1 )
+, m_nStyle( nStyle )
+, m_bUseLeftTop( bUseLeftTop )
+, m_pColorOutFn( pColorOutFn )
+, m_pColorInFn( pColorInFn )
+, m_pColorGapFn( pColorGapFn )
+{
+ if ( pCol )
+ aColor = *pCol;
+}
+
+/** Get the BorderWithImpl object corresponding to the given #nStyle, all the
+ units handled by the resulting object are Twips and the
+ BorderWidthImpl::GetLine1() corresponds to the Outer Line.
+ */
+BorderWidthImpl SvxBorderLine::getWidthImpl( SvxBorderStyle nStyle )
+{
+ BorderWidthImpl aImpl;
+
+ switch ( nStyle )
+ {
+ // No line: no width
+ case NO_STYLE:
+ aImpl = BorderWidthImpl( 0, 0.0 );
+ break;
+
+ // Single lines
+ case SOLID:
+ case DOTTED:
+ case DASHED:
+ aImpl = BorderWidthImpl( CHANGE_LINE1, 1.0 );
+ break;
+
+ // Double lines
+
+ case DOUBLE:
+ aImpl = BorderWidthImpl(
+ CHANGE_LINE1 | CHANGE_LINE2 | CHANGE_DIST,
+ 1.0, 1.0, 1.0 );
+ break;
+
+ case THINTHICK_SMALLGAP:
+ aImpl = BorderWidthImpl( CHANGE_LINE1, 1.0, 15.0, 15.0 );
+ break;
+
+ case THINTHICK_MEDIUMGAP:
+ aImpl = BorderWidthImpl(
+ CHANGE_LINE1 | CHANGE_LINE2 | CHANGE_DIST,
+ 1.0, 0.5, 0.5 );
+ break;
+
+ case THINTHICK_LARGEGAP:
+ aImpl = BorderWidthImpl( CHANGE_DIST, 30.0, 15.0, 1.0 );
+ break;
+
+ case THICKTHIN_SMALLGAP:
+ aImpl = BorderWidthImpl( CHANGE_LINE2, 15.0, 1.0, 15.0 );
+ break;
+
+ case THICKTHIN_MEDIUMGAP:
+ aImpl = BorderWidthImpl(
+ CHANGE_LINE1 | CHANGE_LINE2 | CHANGE_DIST,
+ 0.5, 1.0, 0.5 );
+ break;
+
+ case THICKTHIN_LARGEGAP:
+ aImpl = BorderWidthImpl( CHANGE_DIST, 15.0, 30.0, 1.0 );
+ break;
+
+ // Engraved / Embossed
+ /*
+ * Word compat: the lines widths are exactly following this rule, shouldbe:
+ * 0.75pt up to 3pt and then 3pt
+ */
+
+ case EMBOSSED:
+ case ENGRAVED:
+ aImpl = BorderWidthImpl(
+ CHANGE_LINE1 | CHANGE_LINE2 | CHANGE_DIST,
+ 0.5, 0.5, 1.0 );
+ break;
+
+ // Inset / Outset
+ /*
+ * Word compat: the gap width should be measured relatively to the biggest width for the
+ * row or column.
+ */
+ case OUTSET:
+ aImpl = BorderWidthImpl(
+ CHANGE_LINE2 | CHANGE_DIST,
+ 15.0, 1.0, 1.0 );
+ break;
+
+ case INSET:
+ aImpl = BorderWidthImpl(
+ CHANGE_LINE1 | CHANGE_DIST,
+ 1.0, 15.0, 1.0 );
+ break;
+ }
+
+ return aImpl;
+}
+
+// -----------------------------------------------------------------------
+
+SvxBorderLine::SvxBorderLine( const SvxBorderLine& r )
+{
+ *this = r;
+}
+
+// -----------------------------------------------------------------------
+
+SvxBorderLine& SvxBorderLine::operator=( const SvxBorderLine& r )
+{
+ aColor = r.aColor;
+ m_nWidth = r.m_nWidth;
+ m_aWidthImpl = r.m_aWidthImpl;
+ m_bMirrorWidths = r.m_bMirrorWidths;
+ m_nMult = r.m_nMult;
+ m_nDiv = r.m_nDiv;
+ m_nStyle = r.m_nStyle;
+ m_bUseLeftTop = r.m_bUseLeftTop;
+ m_pColorOutFn = r.m_pColorOutFn;
+ m_pColorInFn = r.m_pColorInFn;
+ m_pColorGapFn = r.m_pColorGapFn;
+ return *this;
+}
+
+// -----------------------------------------------------------------------
+
+void SvxBorderLine::ScaleMetrics( long nMult, long nDiv )
+{
+ m_nMult = nMult;
+ m_nDiv = nDiv;
+}
+
+void SvxBorderLine::GuessLinesWidths( SvxBorderStyle nStyle, sal_uInt16 nOut, sal_uInt16 nIn, sal_uInt16 nDist )
+{
+ if ( nStyle == NO_STYLE ) {
+ nStyle = SOLID;
+ if ( nOut > 0 && nIn > 0 )
+ nStyle = DOUBLE;
+ }
+
+ if ( nStyle == DOUBLE )
+ {
+ static SvxBorderStyle aDoubleStyles[] =
+ {
+ DOUBLE,
+ THINTHICK_SMALLGAP,
+ THINTHICK_MEDIUMGAP,
+ THINTHICK_LARGEGAP,
+ THICKTHIN_SMALLGAP,
+ THICKTHIN_MEDIUMGAP,
+ THICKTHIN_LARGEGAP
+ };
+
+
+ int i = 0, len = sizeof( aDoubleStyles ) / sizeof( SvxBorderStyle );
+ long nWidth = 0;
+ SvxBorderStyle nTestStyle(NO_STYLE);
+ while ( i < len && nWidth == 0 )
+ {
+ nTestStyle = aDoubleStyles[i];
+ BorderWidthImpl aWidthImpl = getWidthImpl( nTestStyle );
+ nWidth = aWidthImpl.GuessWidth( nOut, nIn, nDist );
+ i++;
+ }
+
+ // If anything matched, then set it
+ if ( nWidth > 0 )
+ nStyle = nTestStyle;
+
+ SetStyle( nStyle );
+ m_nWidth = nWidth;
+ }
+ else
+ {
+ SetStyle( nStyle );
+ m_nWidth = m_aWidthImpl.GuessWidth( nOut, nIn, nDist );
+ }
+}
+
+sal_uInt16 SvxBorderLine::GetOutWidth() const
+{
+ sal_uInt16 nOut = (sal_uInt16)Scale( m_aWidthImpl.GetLine1( m_nWidth ), m_nMult, m_nDiv );
+ if ( m_bMirrorWidths )
+ nOut = (sal_uInt16)Scale( m_aWidthImpl.GetLine2( m_nWidth ), m_nMult, m_nDiv );
+ return nOut;
+}
+
+sal_uInt16 SvxBorderLine::GetInWidth() const
+{
+ sal_uInt16 nIn = (sal_uInt16)Scale( m_aWidthImpl.GetLine2( m_nWidth ), m_nMult, m_nDiv );
+ if ( m_bMirrorWidths )
+ nIn = (sal_uInt16)Scale( m_aWidthImpl.GetLine1( m_nWidth ), m_nMult, m_nDiv );
+ return nIn;
+}
+
+sal_uInt16 SvxBorderLine::GetDistance() const
+{
+ return (sal_uInt16)Scale( m_aWidthImpl.GetGap( m_nWidth ), m_nMult, m_nDiv );
+}
+
+// -----------------------------------------------------------------------
+
+sal_Bool SvxBorderLine::operator==( const SvxBorderLine& rCmp ) const
+{
+ return ( ( aColor == rCmp.aColor ) &&
+ ( m_nWidth == rCmp.m_nWidth ) &&
+ ( m_bMirrorWidths == rCmp.m_bMirrorWidths ) &&
+ ( m_aWidthImpl == rCmp.m_aWidthImpl ) &&
+ ( m_nStyle == rCmp.GetStyle() ) &&
+ ( m_bUseLeftTop == rCmp.m_bUseLeftTop ) &&
+ ( m_pColorOutFn == rCmp.m_pColorOutFn ) &&
+ ( m_pColorInFn == rCmp.m_pColorInFn ) &&
+ ( m_pColorGapFn == rCmp.m_pColorGapFn ) );
+}
+
+void SvxBorderLine::SetStyle( SvxBorderStyle nNew )
+{
+ m_nStyle = nNew;
+ m_aWidthImpl = getWidthImpl( m_nStyle );
+
+ switch ( nNew )
+ {
+ case EMBOSSED:
+ m_pColorOutFn = threeDLightColor;
+ m_pColorInFn = threeDDarkColor;
+ m_pColorGapFn = threeDMediumColor;
+ m_bUseLeftTop = true;
+ break;
+ case ENGRAVED:
+ m_pColorOutFn = threeDDarkColor;
+ m_pColorInFn = threeDLightColor;
+ m_pColorGapFn = threeDMediumColor;
+ m_bUseLeftTop = true;
+ break;
+ case OUTSET:
+ m_pColorOutFn = lightColor;
+ m_pColorInFn = darkColor;
+ m_bUseLeftTop = true;
+ m_pColorGapFn = NULL;
+ break;
+ case INSET:
+ m_pColorOutFn = darkColor;
+ m_pColorInFn = lightColor;
+ m_bUseLeftTop = true;
+ m_pColorGapFn = NULL;
+ break;
+ default:
+ m_pColorOutFn = darkColor;
+ m_pColorInFn = darkColor;
+ m_bUseLeftTop = false;
+ m_pColorGapFn = NULL;
+ break;
+ }
+}
+
+Color SvxBorderLine::GetColorOut( bool bLeftOrTop ) const
+{
+ Color aResult = aColor;
+
+ if ( m_aWidthImpl.IsDouble() && m_pColorOutFn != NULL )
+ {
+ if ( !bLeftOrTop && m_bUseLeftTop )
+ aResult = (*m_pColorInFn)( aColor );
+ else
+ aResult = (*m_pColorOutFn)( aColor );
+ }
+
+ return aResult;
+}
+
+Color SvxBorderLine::GetColorIn( bool bLeftOrTop ) const
+{
+ Color aResult = aColor;
+
+ if ( m_aWidthImpl.IsDouble() && m_pColorInFn != NULL )
+ {
+ if ( !bLeftOrTop && m_bUseLeftTop )
+ aResult = (*m_pColorOutFn)( aColor );
+ else
+ aResult = (*m_pColorInFn)( aColor );
+ }
+
+ return aResult;
+}
+
+Color SvxBorderLine::GetColorGap( ) const
+{
+ Color aResult = aColor;
+
+ if ( m_aWidthImpl.IsDouble() && m_pColorGapFn != NULL )
+ {
+ aResult = (*m_pColorGapFn)( aColor );
+ }
+
+ return aResult;
+}
+
+// -----------------------------------------------------------------------
+
+XubString SvxBorderLine::GetValueString( SfxMapUnit eSrcUnit,
+ SfxMapUnit eDestUnit,
+ const IntlWrapper* pIntl,
+ sal_Bool bMetricStr) const
+{
+ static const sal_uInt16 aStyleIds[] =
+ {
+ RID_SOLID,
+ RID_DOTTED,
+ RID_DASHED,
+ RID_DOUBLE,
+ RID_THINTHICK_SMALLGAP,
+ RID_THINTHICK_MEDIUMGAP,
+ RID_THINTHICK_LARGEGAP,
+ RID_THICKTHIN_SMALLGAP,
+ RID_THICKTHIN_MEDIUMGAP,
+ RID_THICKTHIN_LARGEGAP,
+ RID_EMBOSSED,
+ RID_ENGRAVED,
+ RID_OUTSET,
+ RID_INSET
+ };
+ sal_uInt16 nResId = aStyleIds[m_nStyle];
+ String aStr;
+ aStr += sal_Unicode('(');
+ aStr += ::GetColorString( aColor );
+ aStr += cpDelim;
+
+ if ( nResId )
+ aStr += EE_RESSTR(nResId);
+ else
+ {
+ String sMetric = EE_RESSTR(GetMetricId( eDestUnit ));
+ aStr += GetMetricText( (long)GetInWidth(), eSrcUnit, eDestUnit, pIntl );
+ if ( bMetricStr )
+ aStr += sMetric;
+ aStr += cpDelim;
+ aStr += GetMetricText( (long)GetOutWidth(), eSrcUnit, eDestUnit, pIntl );
+ if ( bMetricStr )
+ aStr += sMetric;
+ aStr += cpDelim;
+ aStr += GetMetricText( (long)GetDistance(), eSrcUnit, eDestUnit, pIntl );
+ if ( bMetricStr )
+ aStr += sMetric;
+ }
+ aStr += sal_Unicode(')');
+ return aStr;
+}
+
+bool SvxBorderLine::HasPriority( const SvxBorderLine& rOtherLine ) const
+{
+ const sal_uInt16 nThisSize = GetOutWidth() + GetDistance() + GetInWidth();
+ const sal_uInt16 nOtherSize = rOtherLine.GetOutWidth() + rOtherLine.GetDistance() + rOtherLine.GetInWidth();
+
+ if (nThisSize > nOtherSize)
+ {
+ return true;
+ }
+ else if (nThisSize < nOtherSize)
+ {
+ return false;
+ }
+ else
+ {
+ if ( rOtherLine.GetInWidth() && !GetInWidth() )
+ {
+ return true;
+ }
+ else if ( GetInWidth() && !rOtherLine.GetInWidth() )
+ {
+ return false;
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
+
+} // namespace editeng
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */