refactor handling of double border widths:

Word uses a completely different definition of "width" of a double border
than OOo and ODF: for Word the width is apparently the largest of the 3
component widths, while OOo and ODF define the width as the total with of
all 3 components.  The new border implementation in LO 3.4 was apparently
inspired by Word's double border definition, which resulted in
various import filter regressions, see the previous fixes:

36e43b52992735c622833e923faa63774b9e2f76
e2ffb71305c5f085eec6d396651c76d6daee3406
70a6a4d425558340bb49507975343a3e0a1bdde8

These fixes set the ScaleMetrics, which actually seems sub-optimal as
there is a ScaleItemSet function somewhere that apparently re-scales
all items in an itemset, which could undo the fixes.

Also, one of the fixes actually managed to break RTF/DOCX import
of double borders, as that ended up in the same code via the API.

This commit now reverses the change, so that the width of a border is
now always the total with of all components, which is (imho) much more
intutitive, and also leads to a consistent UI where selecting say 3pt
width has predictable results, no matter what the border style.

The border widths are now converted in the Word format import/export
filters (writerfilter and sw/source/filter/ww8), and various tests
were adapted to the new handling.

Change-Id: I50456c49b1a298569607e6c88f19f18441348ac3
diff --git a/editeng/inc/editeng/borderline.hxx b/editeng/inc/editeng/borderline.hxx
index e026fc2..7d18587 100644
--- a/editeng/inc/editeng/borderline.hxx
+++ b/editeng/inc/editeng/borderline.hxx
@@ -52,6 +52,10 @@ namespace editeng {
    // values from ::com::sun::star::table::BorderLineStyle
    typedef sal_Int16 SvxBorderStyle;

    /// convert border width in twips between Word formats and LO
    double EDITENG_DLLPUBLIC ConvertBorderWidthToWord(SvxBorderStyle, double);
    double EDITENG_DLLPUBLIC ConvertBorderWidthFromWord(SvxBorderStyle, double);

    class EDITENG_DLLPUBLIC SvxBorderLine
    {
    protected:
diff --git a/editeng/qa/items/borderline_test.cxx b/editeng/qa/items/borderline_test.cxx
index f839103..ea0fcf7 100644
--- a/editeng/qa/items/borderline_test.cxx
+++ b/editeng/qa/items/borderline_test.cxx
@@ -97,7 +97,10 @@ void BorderLineTest::testGuessWidthDouble()
    SvxBorderLine line;
    line.GuessLinesWidths( DOUBLE, TEST_WIDTH, TEST_WIDTH, TEST_WIDTH );
    CPPUNIT_ASSERT_EQUAL( DOUBLE, line.GetBorderLineStyle() );
    CPPUNIT_ASSERT_EQUAL( TEST_WIDTH, line.GetWidth() );
    CPPUNIT_ASSERT_EQUAL( TEST_WIDTH, static_cast<long>(line.GetOutWidth()) );
    CPPUNIT_ASSERT_EQUAL( TEST_WIDTH, static_cast<long>(line.GetInWidth()) );
    CPPUNIT_ASSERT_EQUAL( TEST_WIDTH, static_cast<long>(line.GetDistance()) );
    CPPUNIT_ASSERT_EQUAL( 3*TEST_WIDTH, line.GetWidth() );
}

void BorderLineTest::testGuessWidthNoMatch()
@@ -106,6 +109,9 @@ void BorderLineTest::testGuessWidthNoMatch()
    line.GuessLinesWidths( DOUBLE,
            TEST_WIDTH + 1, TEST_WIDTH + 2, TEST_WIDTH + 3 );
    CPPUNIT_ASSERT_EQUAL( DOUBLE, line.GetBorderLineStyle() );
    CPPUNIT_ASSERT_EQUAL( TEST_WIDTH+1, static_cast<long>(line.GetOutWidth()) );
    CPPUNIT_ASSERT_EQUAL( TEST_WIDTH+2, static_cast<long>(line.GetInWidth()) );
    CPPUNIT_ASSERT_EQUAL( TEST_WIDTH+3, static_cast<long>(line.GetDistance()));
    CPPUNIT_ASSERT_EQUAL( long( (3 * TEST_WIDTH) + 6 ), line.GetWidth() );
}

@@ -117,7 +123,14 @@ void BorderLineTest::testGuessWidthThinthickSmallgap()
            THINTHICKSG_IN_WIDTH,
            THINTHICKSG_DIST_WIDTH );
    CPPUNIT_ASSERT_EQUAL( THINTHICK_SMALLGAP, line.GetBorderLineStyle() );
    CPPUNIT_ASSERT_EQUAL( TEST_WIDTH, line.GetWidth() );
    CPPUNIT_ASSERT_EQUAL( THINTHICKSG_OUT_WIDTH,
            static_cast<long>(line.GetOutWidth()) );
    CPPUNIT_ASSERT_EQUAL( THINTHICKSG_IN_WIDTH,
            static_cast<long>(line.GetInWidth()) );
    CPPUNIT_ASSERT_EQUAL( THINTHICKSG_DIST_WIDTH,
            static_cast<long>(line.GetDistance()) );
    CPPUNIT_ASSERT_EQUAL( THINTHICKSG_OUT_WIDTH + THINTHICKSG_IN_WIDTH
            + THINTHICKSG_DIST_WIDTH, line.GetWidth() );
}

void BorderLineTest::testGuessWidthThinthickLargegap()
@@ -128,7 +141,14 @@ void BorderLineTest::testGuessWidthThinthickLargegap()
            THINTHICKLG_IN_WIDTH,
            THINTHICKLG_DIST_WIDTH );
    CPPUNIT_ASSERT_EQUAL( THINTHICK_LARGEGAP, line.GetBorderLineStyle() );
    CPPUNIT_ASSERT_EQUAL( TEST_WIDTH, line.GetWidth() );
    CPPUNIT_ASSERT_EQUAL( THINTHICKLG_OUT_WIDTH,
            static_cast<long>(line.GetOutWidth()) );
    CPPUNIT_ASSERT_EQUAL( THINTHICKLG_IN_WIDTH,
            static_cast<long>(line.GetInWidth()) );
    CPPUNIT_ASSERT_EQUAL( THINTHICKLG_DIST_WIDTH,
            static_cast<long>(line.GetDistance()) );
    CPPUNIT_ASSERT_EQUAL( THINTHICKLG_OUT_WIDTH + THINTHICKLG_IN_WIDTH
            + THINTHICKLG_DIST_WIDTH, line.GetWidth() );
}

void BorderLineTest::testGuessWidthNostyleDouble()
@@ -139,7 +159,14 @@ void BorderLineTest::testGuessWidthNostyleDouble()
            THINTHICKLG_IN_WIDTH,
            THINTHICKLG_DIST_WIDTH );
    CPPUNIT_ASSERT_EQUAL( THINTHICK_LARGEGAP, line.GetBorderLineStyle() );
    CPPUNIT_ASSERT_EQUAL( TEST_WIDTH, line.GetWidth() );
    CPPUNIT_ASSERT_EQUAL( THINTHICKLG_OUT_WIDTH,
            static_cast<long>(line.GetOutWidth()) );
    CPPUNIT_ASSERT_EQUAL( THINTHICKLG_IN_WIDTH,
            static_cast<long>(line.GetInWidth()) );
    CPPUNIT_ASSERT_EQUAL( THINTHICKLG_DIST_WIDTH,
            static_cast<long>(line.GetDistance()) );
    CPPUNIT_ASSERT_EQUAL( THINTHICKLG_OUT_WIDTH + THINTHICKLG_IN_WIDTH
            + THINTHICKLG_DIST_WIDTH, line.GetWidth() );
}

void BorderLineTest::testGuessWidthNostyleSingle()
diff --git a/editeng/source/items/borderline.cxx b/editeng/source/items/borderline.cxx
index de53ccb..225d914 100644
--- a/editeng/source/items/borderline.cxx
+++ b/editeng/source/items/borderline.cxx
@@ -117,6 +117,127 @@ SvxBorderLine::SvxBorderLine( const Color *pCol, long nWidth,
        aColor = *pCol;
}

static const double THINTHICK_SMALLGAP_line2 = 15.0;
static const double THINTHICK_SMALLGAP_gap   = 15.0;
static const double THINTHICK_LARGEGAP_line1 = 30.0;
static const double THINTHICK_LARGEGAP_line2 = 15.0;
static const double THICKTHIN_SMALLGAP_line1 = 15.0;
static const double THICKTHIN_SMALLGAP_gap   = 15.0;
static const double THICKTHIN_LARGEGAP_line1 = 15.0;
static const double THICKTHIN_LARGEGAP_line2 = 30.0;
static const double OUTSET_line1 = 15.0;
static const double INSET_line2  = 15.0;

double
ConvertBorderWidthFromWord(SvxBorderStyle const eStyle, double const fWidth)
{
    switch (eStyle)
    {
        // Single lines
        case SOLID:
        case DOTTED:
        case DASHED:
            return fWidth;
            break;

        // Double lines
        case DOUBLE:
            return fWidth * 3.0;
            break;

        case THINTHICK_MEDIUMGAP:
        case THICKTHIN_MEDIUMGAP:
        case EMBOSSED:
        case ENGRAVED:
            return fWidth * 2.0;
            break;

        case THINTHICK_SMALLGAP:
            return fWidth + THINTHICK_SMALLGAP_line2 + THINTHICK_SMALLGAP_gap;
            break;

        case THINTHICK_LARGEGAP:
            return fWidth + THINTHICK_LARGEGAP_line1 + THINTHICK_LARGEGAP_line2;
            break;

        case THICKTHIN_SMALLGAP:
            return fWidth + THICKTHIN_SMALLGAP_line1 + THICKTHIN_SMALLGAP_gap;
            break;

        case THICKTHIN_LARGEGAP:
            return fWidth + THICKTHIN_LARGEGAP_line1 + THICKTHIN_LARGEGAP_line2;
            break;

        case OUTSET:
            return (fWidth * 2.0) + OUTSET_line1;
            break;

        case INSET:
            return (fWidth * 2.0) + INSET_line2;
            break;

        default:
            assert(false); // should only be called for known border style
            return 0;
            break;
    }
}

double
ConvertBorderWidthToWord(SvxBorderStyle const eStyle, double const fWidth)
{
    switch (eStyle)
    {
        // Single lines
        case SOLID:
        case DOTTED:
        case DASHED:
            return fWidth;
            break;

        // Double lines
        case DOUBLE:
            return fWidth / 3.0;
            break;

        case THINTHICK_MEDIUMGAP:
        case THICKTHIN_MEDIUMGAP:
        case EMBOSSED:
        case ENGRAVED:
            return fWidth / 2.0;
            break;

        case THINTHICK_SMALLGAP:
            return fWidth - THINTHICK_SMALLGAP_line2 - THINTHICK_SMALLGAP_gap;
            break;

        case THINTHICK_LARGEGAP:
            return fWidth - THINTHICK_LARGEGAP_line1 - THINTHICK_LARGEGAP_line2;
            break;

        case THICKTHIN_SMALLGAP:
            return fWidth - THICKTHIN_SMALLGAP_line1 - THICKTHIN_SMALLGAP_gap;
            break;

        case THICKTHIN_LARGEGAP:
            return fWidth - THICKTHIN_LARGEGAP_line1 - THICKTHIN_LARGEGAP_line2;
            break;

        case OUTSET:
            return (fWidth / 2.0) - OUTSET_line1;
            break;

        case INSET:
            return (fWidth / 2.0) - INSET_line2;
            break;

        default:
            assert(false); // should only be called for known border style
            return 0;
            break;
    }
}

/** 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.
@@ -144,35 +265,41 @@ BorderWidthImpl SvxBorderLine::getWidthImpl( SvxBorderStyle nStyle )
        case DOUBLE:
            aImpl = BorderWidthImpl(
                    CHANGE_LINE1 | CHANGE_LINE2 | CHANGE_DIST,
                    1.0, 1.0, 1.0 );
                    // fdo#46112 fdo#38542 fdo#43249:
                    // non-constant witdths must sum to 1
                    1.0/3.0, 1.0/3.0, 1.0/3.0 );
            break;

        case THINTHICK_SMALLGAP:
            aImpl = BorderWidthImpl( CHANGE_LINE1, 1.0, 15.0, 15.0 );
            aImpl = BorderWidthImpl( CHANGE_LINE1, 1.0,
                    THINTHICK_SMALLGAP_line2, THINTHICK_SMALLGAP_gap );
            break;

        case THINTHICK_MEDIUMGAP:
            aImpl = BorderWidthImpl(
                    CHANGE_LINE1 | CHANGE_LINE2 | CHANGE_DIST,
                    1.0, 0.5, 0.5 );
                    0.5, 0.25, 0.25 );
            break;

        case THINTHICK_LARGEGAP:
            aImpl = BorderWidthImpl( CHANGE_DIST, 30.0, 15.0, 1.0 );
            aImpl = BorderWidthImpl( CHANGE_DIST,
                    THINTHICK_LARGEGAP_line1, THINTHICK_LARGEGAP_line2, 1.0 );
            break;

        case THICKTHIN_SMALLGAP:
            aImpl = BorderWidthImpl( CHANGE_LINE2, 15.0, 1.0, 15.0 );
            aImpl = BorderWidthImpl( CHANGE_LINE2, THICKTHIN_SMALLGAP_line1,
                    1.0, THICKTHIN_SMALLGAP_gap );
            break;

        case THICKTHIN_MEDIUMGAP:
            aImpl = BorderWidthImpl(
                    CHANGE_LINE1 | CHANGE_LINE2 | CHANGE_DIST,
                    0.5, 1.0, 0.5 );
                    0.25, 0.5, 0.25 );
            break;

        case THICKTHIN_LARGEGAP:
            aImpl = BorderWidthImpl( CHANGE_DIST, 15.0, 30.0, 1.0 );
            aImpl = BorderWidthImpl( CHANGE_DIST, THICKTHIN_LARGEGAP_line1,
                    THICKTHIN_LARGEGAP_line2, 1.0 );
            break;

        // Engraved / Embossed
@@ -185,7 +312,7 @@ BorderWidthImpl SvxBorderLine::getWidthImpl( SvxBorderStyle nStyle )
        case ENGRAVED:
            aImpl = BorderWidthImpl(
                    CHANGE_LINE1 | CHANGE_LINE2 | CHANGE_DIST,
                    0.5, 0.5, 1.0 );
                    0.25, 0.25, 0.5 );
            break;

        // Inset / Outset
@@ -196,13 +323,13 @@ BorderWidthImpl SvxBorderLine::getWidthImpl( SvxBorderStyle nStyle )
        case OUTSET:
            aImpl = BorderWidthImpl(
                    CHANGE_LINE2 | CHANGE_DIST,
                    15.0, 1.0, 1.0 );
                    OUTSET_line1, 0.5, 0.5 );
            break;

        case INSET:
            aImpl = BorderWidthImpl(
                    CHANGE_LINE1 | CHANGE_DIST,
                    1.0, 15.0, 1.0 );
                    0.5, INSET_line2, 0.5 );
            break;
    }

diff --git a/editeng/source/items/frmitems.cxx b/editeng/source/items/frmitems.cxx
index 733ba58..dbf3943 100644
--- a/editeng/source/items/frmitems.cxx
+++ b/editeng/source/items/frmitems.cxx
@@ -1786,13 +1786,6 @@ lcl_lineToSvxLine(const table::BorderLine& rLine, SvxBorderLine& rSvxLine, sal_B
                sal_uInt16( bConvert ? MM100_TO_TWIP(rLine.InnerLineWidth) : rLine.InnerLineWidth  ),
                sal_uInt16( bConvert ? MM100_TO_TWIP(rLine.LineDistance )  : rLine.LineDistance  ));
    }
    else
    {
        if (DOUBLE == rSvxLine.GetBorderLineStyle())
        {   // fdo#46112: divide width by 3 for outer line, gap, inner line
           rSvxLine.ScaleMetrics(1, 3);
        }
    }

    sal_Bool bRet = !rSvxLine.isEmpty();
    return bRet;
diff --git a/svtools/source/control/ctrlbox.cxx b/svtools/source/control/ctrlbox.cxx
index be53f12..7dff33d 100644
--- a/svtools/source/control/ctrlbox.cxx
+++ b/svtools/source/control/ctrlbox.cxx
@@ -322,7 +322,12 @@ long BorderWidthImpl::GetLine1( long nWidth ) const
{
    long result = static_cast<long>(m_nRate1);
    if ( ( m_nFlags & CHANGE_LINE1 ) > 0 )
        result = static_cast<long>(m_nRate1 * nWidth);
    {
        long const nConstant2 = (m_nFlags & CHANGE_LINE2) ? 0 : m_nRate2;
        long const nConstantD = (m_nFlags & CHANGE_DIST ) ? 0 : m_nRateGap;
        result = std::max<long>(0,
            static_cast<long>(m_nRate1 * nWidth) - (nConstant2 + nConstantD));
    }
    return result;
}

@@ -330,7 +335,12 @@ long BorderWidthImpl::GetLine2( long nWidth ) const
{
    long result = static_cast<long>(m_nRate2);
    if ( ( m_nFlags & CHANGE_LINE2 ) > 0 )
        result = static_cast<long>(m_nRate2 * nWidth);
    {
        long const nConstant1 = (m_nFlags & CHANGE_LINE1) ? 0 : m_nRate1;
        long const nConstantD = (m_nFlags & CHANGE_DIST ) ? 0 : m_nRateGap;
        result = std::max<long>(0,
            static_cast<long>(m_nRate2 * nWidth) - (nConstant1 + nConstantD));
    }
    return result;
}

@@ -338,7 +348,12 @@ long BorderWidthImpl::GetGap( long nWidth ) const
{
    long result = static_cast<long>(m_nRateGap);
    if ( ( m_nFlags & CHANGE_DIST ) > 0 )
        result = static_cast<long>(m_nRateGap * nWidth);
    {
        long const nConstant1 = (m_nFlags & CHANGE_LINE1) ? 0 : m_nRate1;
        long const nConstant2 = (m_nFlags & CHANGE_LINE2) ? 0 : m_nRate2;
        result = std::max<long>(0,
            static_cast<long>(m_nRateGap * nWidth) - (nConstant1 + nConstant2));
    }

    // Avoid having too small distances (less than 0.1pt)
    if ( result < MINGAPWIDTH && m_nRate1 > 0 && m_nRate2 > 0 )
@@ -387,6 +402,11 @@ long BorderWidthImpl::GuessWidth( long nLine1, long nLine2, long nGap )
    else if ( !bGapChange && nWidthGap < 0 )
        bInvalid = true;

    // non-constant line width factors must sum to 1
    assert((((bLine1Change) ? m_nRate1 : 0) +
            ((bLine2Change) ? m_nRate2 : 0) +
            ((bGapChange) ? m_nRateGap : 0)) - 1.0 < 0.00001 );

    double nWidth = 0.0;
    if ( (!bInvalid) && (!aToCompare.empty()) )
    {
@@ -397,11 +417,10 @@ long BorderWidthImpl::GuessWidth( long nLine1, long nLine2, long nGap )
            bInvalid = ( nWidth != *pIt );
            ++pIt;
        }
        if ( bInvalid )
            nWidth = 0.0;
        nWidth = (bInvalid) ?  0.0 : nLine1 + nLine2 + nGap;
    }

    return long( nWidth );
    return nWidth;
}

/** Utility class storing the border line width, style and colors. The widths
diff --git a/sw/qa/extras/ooxmltok/ooxmltok.cxx b/sw/qa/extras/ooxmltok/ooxmltok.cxx
index 790194d..a3fd38a 100644
--- a/sw/qa/extras/ooxmltok/ooxmltok.cxx
+++ b/sw/qa/extras/ooxmltok/ooxmltok.cxx
@@ -581,7 +581,7 @@ void Test::testN758883()
    uno::Reference<beans::XPropertySet> xPropertySet(getStyles("PageStyles")->getByName("Default"), uno::UNO_QUERY);
    sal_Int32 nValue = 0;
    xPropertySet->getPropertyValue("LeftMargin") >>= nValue;
    CPPUNIT_ASSERT_EQUAL(sal_Int32(820), nValue);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(794), nValue);

    // No assert for the 3rd problem: see the comment in the test doc.

diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index eea8da3..e5b35c5 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -1410,8 +1410,10 @@ static void impl_borderLine( FSHelperPtr pSerializer, sal_Int32 elementToken, co
    {
        // Compute the sz attribute

        double const fConverted( ::editeng::ConvertBorderWidthToWord(
                pBorderLine->GetBorderLineStyle(), pBorderLine->GetWidth()));
        // The unit is the 8th of point
        sal_Int32 nWidth = sal_Int32( pBorderLine->GetWidth() / 2.5 );
        sal_Int32 nWidth = sal_Int32( fConverted / 2.5 );
        sal_uInt16 nMinWidth = 2;
        sal_uInt16 nMaxWidth = 96;

diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx
index e22f7cf..5957606 100644
--- a/sw/source/filter/ww8/rtfattributeoutput.cxx
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -179,12 +179,18 @@ static OString OutTBLBorderLine(RtfExport &rExport, const SvxBorderLine* pLine, 
                break;
        }

        double const fConverted( ::editeng::ConvertBorderWidthToWord(
                    pLine->GetBorderLineStyle(), pLine->GetWidth()) );
        if ( 255 >= pLine->GetWidth() ) // That value comes from RTF specs
        {
            aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRW).append((sal_Int32)pLine->GetWidth());
            aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRW).append(
                    static_cast<sal_Int32>(fConverted));
        }
        else
            aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRTH OOO_STRING_SVTOOLS_RTF_BRDRW).append((sal_Int32)pLine->GetWidth() / 2);
        {   // use \brdrth to double the value range...
            aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRTH OOO_STRING_SVTOOLS_RTF_BRDRW);
            aRet.append(static_cast<sal_Int32>(fConverted) / 2);
        }

        aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRCF);
        aRet.append((sal_Int32)rExport.GetColor(pLine->GetColor()));
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index acf2dbf..78ff6be 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -4061,7 +4061,8 @@ WW8_BRC WW8Export::TranslateBorderLine(const SvxBorderLine& rLine,
    // what SwRTFWriter::OutRTFBorder does in the RTF filter Eventually it
    // would be nice if all this functionality was in the one place
    WW8_BRC aBrc;
    sal_uInt16 nWidth = rLine.GetWidth();
    sal_uInt16 nWidth = ::editeng::ConvertBorderWidthToWord(
            rLine.GetBorderLineStyle(), rLine.GetWidth());
    sal_uInt8 brcType = 0, nColCode = 0;

    if( nWidth )                                // Linie ?
diff --git a/sw/source/filter/ww8/ww8graf.cxx b/sw/source/filter/ww8/ww8graf.cxx
index c5c6631..1c350b2 100644
--- a/sw/source/filter/ww8/ww8graf.cxx
+++ b/sw/source/filter/ww8/ww8graf.cxx
@@ -1570,10 +1570,6 @@ sal_Int32 SwWW8ImplReader::MatchSdrBoxIntoFlyBoxItem(const Color& rLineColor,

        aLine.SetWidth( nLineThick ); // No conversion here, nLineThick is already in twips
        aLine.SetBorderLineStyle(nIdx);
        if (table::BorderLineStyle::DOUBLE == nIdx)
        {  // fdo#43249: divide width by 3 for outer line, gap, inner line
           aLine.ScaleMetrics(1, 3);
        }

        for(sal_uInt16 nLine = 0; nLine < 4; ++nLine)
            rBox.SetLine(new SvxBorderLine( aLine ), nLine);
diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx
index 7582a2b..c86300a 100644
--- a/sw/source/filter/ww8/ww8par6.cxx
+++ b/sw/source/filter/ww8/ww8par6.cxx
@@ -1355,7 +1355,9 @@ void GetLineIndex(SvxBoxItem &rBox, short nLineThickness, short nSpace, sal_uInt

    ::editeng::SvxBorderLine aLine;
    aLine.SetBorderLineStyle( eStyle );
    aLine.SetWidth( nLineThickness );
    double const fConverted( (table::BorderLineStyle::NONE == eStyle) ? 0.0 :
            ::editeng::ConvertBorderWidthFromWord(eStyle, nLineThickness));
    aLine.SetWidth(fConverted);

    //No AUTO for borders as yet, so if AUTO, use BLACK
    if (nCol == 0)
@@ -1364,7 +1366,7 @@ void GetLineIndex(SvxBoxItem &rBox, short nLineThickness, short nSpace, sal_uInt
    aLine.SetColor(SwWW8ImplReader::GetCol(nCol));

    if (pSize)
        pSize[nWWIndex] = nLineThickness+nSpace;
        pSize[nWWIndex] = fConverted + nSpace;

    rBox.SetLine(&aLine, nOOIndex);
    rBox.SetDistance(nSpace, nOOIndex);
diff --git a/sw/source/filter/xml/xmlithlp.cxx b/sw/source/filter/xml/xmlithlp.cxx
index 0902899..d29853e 100644
--- a/sw/source/filter/xml/xmlithlp.cxx
+++ b/sw/source/filter/xml/xmlithlp.cxx
@@ -218,10 +218,6 @@ sal_Bool lcl_frmitems_setXMLBorder( SvxBorderLine*& rpLine,
                       rpLine->GetOutWidth();

               rpLine->SetWidth( nWidth );
               if (bDouble)
               { // fdo#38542: divide width by 3 for outer line, gap, inner line
                   rpLine->ScaleMetrics(1, 3);
               }
           }
       }
       lcl_frmitems_setXMLBorderStyle( *rpLine, nStyle );
diff --git a/writerfilter/Library_writerfilter.mk b/writerfilter/Library_writerfilter.mk
index a405090..f768dce 100644
--- a/writerfilter/Library_writerfilter.mk
+++ b/writerfilter/Library_writerfilter.mk
@@ -68,6 +68,7 @@ $(eval $(call gb_Library_use_libraries,writerfilter,\
    comphelper \
    cppu \
    cppuhelper \
    editeng \
    i18nisolang1 \
    i18nutil \
    msfilter \
diff --git a/writerfilter/source/dmapper/BorderHandler.cxx b/writerfilter/source/dmapper/BorderHandler.cxx
index 2d08017..068c210 100644
--- a/writerfilter/source/dmapper/BorderHandler.cxx
+++ b/writerfilter/source/dmapper/BorderHandler.cxx
@@ -35,7 +35,7 @@ using namespace ::com::sun::star;
BorderHandler::BorderHandler( bool bOOXML ) :
LoggedProperties(dmapper_logger, "BorderHandler"),
m_nCurrentBorderPosition( BORDER_TOP ),
m_nLineWidth(26), // Word default
m_nLineWidth(15), // Word default, in twips
m_nLineType(0),
m_nLineColor(0),
m_nLineDistance(0),
@@ -70,7 +70,7 @@ void BorderHandler::lcl_attribute(Id rName, Value & rVal)
        break;
        case NS_rtf::LN_DPTLINEWIDTH: // 0x2871
            //  width of a single line in 1/8 pt, max of 32 pt -> twip * 5 / 2.
            m_nLineWidth = ConversionHelper::convertTwipToMM100( nIntValue * 5 / 2 );
            m_nLineWidth = nIntValue * 5 / 2;
        break;
        case NS_rtf::LN_BRCTYPE:    // 0x2872
            m_nLineType = nIntValue;
diff --git a/writerfilter/source/dmapper/ConversionHelper.cxx b/writerfilter/source/dmapper/ConversionHelper.cxx
index 8796829..3b89630 100644
--- a/writerfilter/source/dmapper/ConversionHelper.cxx
+++ b/writerfilter/source/dmapper/ConversionHelper.cxx
@@ -22,6 +22,7 @@
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/text/HoriOrientation.hpp>
#include <com/sun/star/style/NumberingType.hpp>
#include <editeng/borderline.hxx>
#include <ooxml/resourceids.hxx>
#include <rtl/ustrbuf.hxx>
#include <tools/color.hxx>
@@ -110,8 +111,7 @@ sal_Int32 MakeBorderLine( sal_Int32 nSprmValue, table::BorderLine2& rToFill )
    sal_Int32 nLineType       = ((nSprmValue & 0xff00) >> 8);
    sal_Int32 nLineColor    = (nSprmValue & 0xff0000)>>16;
    sal_Int32 nLineDistance = (((nSprmValue & 0x3f000000)>>24) * 2540 + 36)/72L;
    sal_Int32 nLineThickness = TWIP_TO_MM100(nLineThicknessTwip);
    MakeBorderLine( nLineThickness, nLineType, nLineColor, rToFill, false);
    MakeBorderLine( nLineThicknessTwip, nLineType, nLineColor, rToFill, false);
    return nLineDistance;
}
void MakeBorderLine( sal_Int32 nLineThickness,   sal_Int32 nLineType,
@@ -202,7 +202,9 @@ void MakeBorderLine( sal_Int32 nLineThickness,   sal_Int32 nLineType,
    }

    rToFill.LineStyle = nLineStyle;
    rToFill.LineWidth = sal_uInt32( nLineThickness );
    double const fConverted( (NONE == nLineStyle) ? 0.0 :
        ::editeng::ConvertBorderWidthFromWord(nLineStyle, nLineThickness));
    rToFill.LineWidth = convertTwipToMM100(fConverted);
    rToFill.Color = nLineColor;
}

diff --git a/writerfilter/source/dmapper/MeasureHandler.cxx b/writerfilter/source/dmapper/MeasureHandler.cxx
index 4171143..9eefa23 100644
--- a/writerfilter/source/dmapper/MeasureHandler.cxx
+++ b/writerfilter/source/dmapper/MeasureHandler.cxx
@@ -95,7 +95,9 @@ sal_Int32 MeasureHandler::getMeasureValue() const
    {
        // TODO m_nUnit 3 - twip, other values unknown :-(
        if( m_nUnit == 3 || sal::static_int_cast<Id>(m_nUnit) == NS_ooxml::LN_Value_ST_TblWidth_dxa)
        {
            nRet = ConversionHelper::convertTwipToMM100( m_nMeasureValue );
        }
        //todo: handle additional width types:
        //NS_ooxml::LN_Value_ST_TblWidth_nil, NS_ooxml::LN_Value_ST_TblWidth_pct,
        //NS_ooxml::LN_Value_ST_TblWidth_dxa, NS_ooxml::LN_Value_ST_TblWidth_auto;
diff --git a/writerfilter/source/dmapper/TDefTableHandler.cxx b/writerfilter/source/dmapper/TDefTableHandler.cxx
index 8225779..dcd000d 100644
--- a/writerfilter/source/dmapper/TDefTableHandler.cxx
+++ b/writerfilter/source/dmapper/TDefTableHandler.cxx
@@ -101,7 +101,7 @@ void TDefTableHandler::lcl_attribute(Id rName, Value & rVal)
        //from LN_BRCXXXX - handled within the BorderHandler
        case NS_rtf::LN_DPTLINEWIDTH: // 0x2871
            //  width of a single line in 1/8 pt, max of 32 pt -> twip * 5 / 2.
            m_nLineWidth = ConversionHelper::convertTwipToMM100( nIntValue * 5 / 2 );
            m_nLineWidth = nIntValue * 5 / 2;
        break;
        case NS_rtf::LN_BRCTYPE:    // 0x2872
            m_nLineType = nIntValue;