[Libreoffice-commits] core.git: vcl/Library_vcl.mk vcl/source

Chris Sherlock chris.sherlock79 at gmail.com
Sat Apr 19 20:12:04 PDT 2014


 vcl/Library_vcl.mk             |    1 
 vcl/source/outdev/text.cxx     |  967 -------------------------------------
 vcl/source/outdev/textline.cxx | 1068 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1069 insertions(+), 967 deletions(-)

New commits:
commit ffce13a5e48e193463be65b569af2e4f22d17926
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date:   Sun Apr 20 13:10:09 2014 +1000

    Move VCL text line functions from text.cxx to textline.cxx
    
    Change-Id: I3adea9cd08c86f676e6af525e5a7caf430c96d8d

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 72285c5..989bf8e 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -243,6 +243,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/outdev/bitmap \
     vcl/source/outdev/font \
     vcl/source/outdev/text \
+    vcl/source/outdev/textline \
     vcl/source/outdev/pixel \
     vcl/source/outdev/rect \
     vcl/source/outdev/line \
diff --git a/vcl/source/outdev/text.cxx b/vcl/source/outdev/text.cxx
index 7063c32..4850339 100644
--- a/vcl/source/outdev/text.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -135,19 +135,6 @@ void ImplMultiTextLineInfo::Clear()
     mnLines = 0;
 }
 
-bool OutputDevice::ImplIsUnderlineAbove( const Font& rFont )
-{
-    if ( !rFont.IsVertical() )
-        return false;
-
-    if( (LANGUAGE_JAPANESE == rFont.GetLanguage())
-    ||  (LANGUAGE_JAPANESE == rFont.GetCJKContextLanguage()) )
-        // the underline is right for Japanese only
-        return true;
-
-    return false;
-}
-
 void OutputDevice::ImplInitTextColor()
 {
     DBG_TESTSOLARMUTEX();
@@ -273,745 +260,6 @@ Rectangle OutputDevice::ImplGetTextBoundRect( const SalLayout& rSalLayout )
     return Rectangle( Point( nX, nY ), Size( nWidth, nHeight ) );
 }
 
-void OutputDevice::ImplInitTextLineSize()
-{
-    mpFontEntry->maMetric.ImplInitTextLineSize( this );
-}
-
-void OutputDevice::ImplInitAboveTextLineSize()
-{
-    mpFontEntry->maMetric.ImplInitAboveTextLineSize();
-}
-
-static void ImplDrawWavePixel( long nOriginX, long nOriginY,
-                               long nCurX, long nCurY,
-                               short nOrientation,
-                               SalGraphics* pGraphics,
-                               OutputDevice* pOutDev,
-                               bool bDrawPixAsRect,
-
-                               long nPixWidth, long nPixHeight )
-{
-    if ( nOrientation )
-        ImplRotatePos( nOriginX, nOriginY, nCurX, nCurY, nOrientation );
-
-    if ( bDrawPixAsRect )
-    {
-
-        pGraphics->DrawRect( nCurX, nCurY, nPixWidth, nPixHeight, pOutDev );
-    }
-    else
-    {
-        pGraphics->DrawPixel( nCurX, nCurY, pOutDev );
-    }
-}
-
-void OutputDevice::ImplDrawWaveLine( long nBaseX, long nBaseY,
-                                     long nDistX, long nDistY,
-                                     long nWidth, long nHeight,
-                                     long nLineWidth, short nOrientation,
-                                     const Color& rColor )
-{
-    if ( !nHeight )
-        return;
-
-    long nStartX = nBaseX + nDistX;
-    long nStartY = nBaseY + nDistY;
-
-    // If the height is 1 pixel, it's enough ouput a line
-    if ( (nLineWidth == 1) && (nHeight == 1) )
-    {
-        mpGraphics->SetLineColor( ImplColorToSal( rColor ) );
-        mbInitLineColor = true;
-
-        long nEndX = nStartX+nWidth;
-        long nEndY = nStartY;
-        if ( nOrientation )
-        {
-            ImplRotatePos( nBaseX, nBaseY, nStartX, nStartY, nOrientation );
-            ImplRotatePos( nBaseX, nBaseY, nEndX, nEndY, nOrientation );
-        }
-        mpGraphics->DrawLine( nStartX, nStartY, nEndX, nEndY, this );
-    }
-    else
-    {
-        long    nCurX = nStartX;
-        long    nCurY = nStartY;
-        long    nDiffX = 2;
-        long    nDiffY = nHeight-1;
-        long    nCount = nWidth;
-        long    nOffY = -1;
-        long    nFreq;
-        long    i;
-        long    nPixWidth;
-        long    nPixHeight;
-        bool    bDrawPixAsRect;
-        // On printers that ouput pixel via DrawRect()
-        if ( (GetOutDevType() == OUTDEV_PRINTER) || (nLineWidth > 1) )
-        {
-            if ( mbLineColor || mbInitLineColor )
-            {
-                mpGraphics->SetLineColor();
-                mbInitLineColor = true;
-            }
-            mpGraphics->SetFillColor( ImplColorToSal( rColor ) );
-            mbInitFillColor = true;
-            bDrawPixAsRect  = true;
-            nPixWidth       = nLineWidth;
-            nPixHeight      = ((nLineWidth*mnDPIX)+(mnDPIY/2))/mnDPIY;
-        }
-        else
-        {
-            mpGraphics->SetLineColor( ImplColorToSal( rColor ) );
-            mbInitLineColor = true;
-            nPixWidth       = 1;
-            nPixHeight      = 1;
-            bDrawPixAsRect  = false;
-        }
-
-        if ( !nDiffY )
-        {
-            while ( nWidth )
-            {
-                ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
-                                   mpGraphics, this,
-                                   bDrawPixAsRect, nPixWidth, nPixHeight );
-                nCurX++;
-                nWidth--;
-            }
-        }
-        else
-        {
-            nCurY += nDiffY;
-            nFreq = nCount / (nDiffX+nDiffY);
-            while ( nFreq-- )
-            {
-                for( i = nDiffY; i; --i )
-                {
-                    ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
-                                       mpGraphics, this,
-                                       bDrawPixAsRect, nPixWidth, nPixHeight );
-                    nCurX++;
-                    nCurY += nOffY;
-                }
-                for( i = nDiffX; i; --i )
-                {
-                    ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
-                                       mpGraphics, this,
-                                       bDrawPixAsRect, nPixWidth, nPixHeight );
-                    nCurX++;
-                }
-                nOffY = -nOffY;
-            }
-            nFreq = nCount % (nDiffX+nDiffY);
-            if ( nFreq )
-            {
-                for( i = nDiffY; i && nFreq; --i, --nFreq )
-                {
-                    ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
-                                       mpGraphics, this,
-                                       bDrawPixAsRect, nPixWidth, nPixHeight );
-                    nCurX++;
-                    nCurY += nOffY;
-
-                }
-                for( i = nDiffX; i && nFreq; --i, --nFreq )
-                {
-                    ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
-                                       mpGraphics, this,
-                                       bDrawPixAsRect, nPixWidth, nPixHeight );
-                    nCurX++;
-                }
-            }
-        }
-
-    }
-}
-
-void OutputDevice::ImplDrawWaveTextLine( long nBaseX, long nBaseY,
-                                         long nDistX, long nDistY, long nWidth,
-                                         FontUnderline eTextLine,
-                                         Color aColor,
-                                         bool bIsAbove )
-{
-    ImplFontEntry*  pFontEntry = mpFontEntry;
-    long            nLineHeight;
-    long            nLinePos;
-
-    if ( bIsAbove )
-    {
-        nLineHeight = pFontEntry->maMetric.mnAboveWUnderlineSize;
-        nLinePos = pFontEntry->maMetric.mnAboveWUnderlineOffset;
-    }
-    else
-    {
-        nLineHeight = pFontEntry->maMetric.mnWUnderlineSize;
-        nLinePos = pFontEntry->maMetric.mnWUnderlineOffset;
-    }
-    if ( (eTextLine == UNDERLINE_SMALLWAVE) && (nLineHeight > 3) )
-        nLineHeight = 3;
-    long nLineWidth = (mnDPIX/300);
-    if ( !nLineWidth )
-        nLineWidth = 1;
-    if ( eTextLine == UNDERLINE_BOLDWAVE )
-        nLineWidth *= 2;
-    nLinePos += nDistY - (nLineHeight / 2);
-    long nLineWidthHeight = ((nLineWidth*mnDPIX)+(mnDPIY/2))/mnDPIY;
-    if ( eTextLine == UNDERLINE_DOUBLEWAVE )
-    {
-        long nOrgLineHeight = nLineHeight;
-        nLineHeight /= 3;
-        if ( nLineHeight < 2 )
-        {
-            if ( nOrgLineHeight > 1 )
-                nLineHeight = 2;
-            else
-                nLineHeight = 1;
-        }
-        long nLineDY = nOrgLineHeight-(nLineHeight*2);
-        if ( nLineDY < nLineWidthHeight )
-            nLineDY = nLineWidthHeight;
-        long nLineDY2 = nLineDY/2;
-        if ( !nLineDY2 )
-            nLineDY2 = 1;
-
-        nLinePos -= nLineWidthHeight-nLineDY2;
-        ImplDrawWaveLine( nBaseX, nBaseY, nDistX, nLinePos, nWidth, nLineHeight,
-                          nLineWidth, mpFontEntry->mnOrientation, aColor );
-        nLinePos += nLineWidthHeight+nLineDY;
-        ImplDrawWaveLine( nBaseX, nBaseY, nDistX, nLinePos, nWidth, nLineHeight,
-                          nLineWidth, mpFontEntry->mnOrientation, aColor );
-    }
-    else
-    {
-        nLinePos -= nLineWidthHeight/2;
-        ImplDrawWaveLine( nBaseX, nBaseY, nDistX, nLinePos, nWidth, nLineHeight,
-                          nLineWidth, mpFontEntry->mnOrientation, aColor );
-    }
-}
-
-void OutputDevice::ImplDrawStraightTextLine( long nBaseX, long nBaseY,
-                                             long nDistX, long nDistY, long nWidth,
-                                             FontUnderline eTextLine,
-                                             Color aColor,
-                                             bool bIsAbove )
-{
-    ImplFontEntry*  pFontEntry = mpFontEntry;
-    long            nLineHeight = 0;
-    long            nLinePos  = 0;
-    long            nLinePos2 = 0;
-
-    const long nY = nDistY;
-
-    if ( eTextLine > UNDERLINE_LAST )
-        eTextLine = UNDERLINE_SINGLE;
-
-    switch ( eTextLine )
-    {
-        case UNDERLINE_SINGLE:
-        case UNDERLINE_DOTTED:
-        case UNDERLINE_DASH:
-        case UNDERLINE_LONGDASH:
-        case UNDERLINE_DASHDOT:
-        case UNDERLINE_DASHDOTDOT:
-            if ( bIsAbove )
-            {
-                nLineHeight = pFontEntry->maMetric.mnAboveUnderlineSize;
-                nLinePos    = nY + pFontEntry->maMetric.mnAboveUnderlineOffset;
-            }
-            else
-            {
-                nLineHeight = pFontEntry->maMetric.mnUnderlineSize;
-                nLinePos    = nY + pFontEntry->maMetric.mnUnderlineOffset;
-            }
-            break;
-        case UNDERLINE_BOLD:
-        case UNDERLINE_BOLDDOTTED:
-        case UNDERLINE_BOLDDASH:
-        case UNDERLINE_BOLDLONGDASH:
-        case UNDERLINE_BOLDDASHDOT:
-        case UNDERLINE_BOLDDASHDOTDOT:
-            if ( bIsAbove )
-            {
-                nLineHeight = pFontEntry->maMetric.mnAboveBUnderlineSize;
-                nLinePos    = nY + pFontEntry->maMetric.mnAboveBUnderlineOffset;
-            }
-            else
-            {
-                nLineHeight = pFontEntry->maMetric.mnBUnderlineSize;
-                nLinePos    = nY + pFontEntry->maMetric.mnBUnderlineOffset;
-            }
-            break;
-        case UNDERLINE_DOUBLE:
-            if ( bIsAbove )
-            {
-                nLineHeight = pFontEntry->maMetric.mnAboveDUnderlineSize;
-                nLinePos    = nY + pFontEntry->maMetric.mnAboveDUnderlineOffset1;
-                nLinePos2   = nY + pFontEntry->maMetric.mnAboveDUnderlineOffset2;
-            }
-            else
-            {
-                nLineHeight = pFontEntry->maMetric.mnDUnderlineSize;
-                nLinePos    = nY + pFontEntry->maMetric.mnDUnderlineOffset1;
-                nLinePos2   = nY + pFontEntry->maMetric.mnDUnderlineOffset2;
-            }
-            break;
-        default:
-            break;
-    }
-
-    if ( nLineHeight )
-    {
-        if ( mbLineColor || mbInitLineColor )
-        {
-            mpGraphics->SetLineColor();
-            mbInitLineColor = true;
-        }
-        mpGraphics->SetFillColor( ImplColorToSal( aColor ) );
-        mbInitFillColor = true;
-
-        long nLeft = nDistX;
-
-        switch ( eTextLine )
-        {
-            case UNDERLINE_SINGLE:
-            case UNDERLINE_BOLD:
-                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
-                break;
-            case UNDERLINE_DOUBLE:
-                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos,  nWidth, nLineHeight );
-                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos2, nWidth, nLineHeight );
-                break;
-            case UNDERLINE_DOTTED:
-            case UNDERLINE_BOLDDOTTED:
-                {
-                    long nDotWidth = nLineHeight*mnDPIY;
-                    nDotWidth += mnDPIY/2;
-                    nDotWidth /= mnDPIY;
-                    long nTempWidth = nDotWidth;
-                    long nEnd = nLeft+nWidth;
-                    while ( nLeft < nEnd )
-                    {
-                        if ( nLeft+nTempWidth > nEnd )
-                            nTempWidth = nEnd-nLeft;
-                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
-                        nLeft += nDotWidth*2;
-                    }
-                }
-                break;
-            case UNDERLINE_DASH:
-            case UNDERLINE_LONGDASH:
-            case UNDERLINE_BOLDDASH:
-            case UNDERLINE_BOLDLONGDASH:
-                {
-                    long nDotWidth = nLineHeight*mnDPIY;
-                    nDotWidth += mnDPIY/2;
-                    nDotWidth /= mnDPIY;
-                    long nMinDashWidth;
-                    long nMinSpaceWidth;
-                    long nSpaceWidth;
-                    long nDashWidth;
-                    if ( (eTextLine == UNDERLINE_LONGDASH) ||
-                         (eTextLine == UNDERLINE_BOLDLONGDASH) )
-                    {
-                        nMinDashWidth = nDotWidth*6;
-                        nMinSpaceWidth = nDotWidth*2;
-                        nDashWidth = 200;
-                        nSpaceWidth = 100;
-                    }
-                    else
-                    {
-                        nMinDashWidth = nDotWidth*4;
-                        nMinSpaceWidth = (nDotWidth*150)/100;
-                        nDashWidth = 100;
-                        nSpaceWidth = 50;
-                    }
-                    nDashWidth = ((nDashWidth*mnDPIX)+1270)/2540;
-                    nSpaceWidth = ((nSpaceWidth*mnDPIX)+1270)/2540;
-                    // DashWidth will be increased if the line is getting too thick
-                    // in proportion to the line's length
-                    if ( nDashWidth < nMinDashWidth )
-                        nDashWidth = nMinDashWidth;
-                    if ( nSpaceWidth < nMinSpaceWidth )
-                        nSpaceWidth = nMinSpaceWidth;
-                    long nTempWidth = nDashWidth;
-                    long nEnd = nLeft+nWidth;
-                    while ( nLeft < nEnd )
-                    {
-                        if ( nLeft+nTempWidth > nEnd )
-                            nTempWidth = nEnd-nLeft;
-                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
-                        nLeft += nDashWidth+nSpaceWidth;
-                    }
-                }
-                break;
-            case UNDERLINE_DASHDOT:
-            case UNDERLINE_BOLDDASHDOT:
-                {
-                    long nDotWidth = nLineHeight*mnDPIY;
-                    nDotWidth += mnDPIY/2;
-                    nDotWidth /= mnDPIY;
-                    long nDashWidth = ((100*mnDPIX)+1270)/2540;
-                    long nMinDashWidth = nDotWidth*4;
-                    // DashWidth will be increased if the line is getting too thick
-                    // in proportion to the line's length
-                    if ( nDashWidth < nMinDashWidth )
-                        nDashWidth = nMinDashWidth;
-                    long nTempDotWidth = nDotWidth;
-                    long nTempDashWidth = nDashWidth;
-                    long nEnd = nLeft+nWidth;
-                    while ( nLeft < nEnd )
-                    {
-                        if ( nLeft+nTempDotWidth > nEnd )
-                            nTempDotWidth = nEnd-nLeft;
-                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
-                        nLeft += nDotWidth*2;
-                        if ( nLeft > nEnd )
-                            break;
-                        if ( nLeft+nTempDashWidth > nEnd )
-                            nTempDashWidth = nEnd-nLeft;
-                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
-                        nLeft += nDashWidth+nDotWidth;
-                    }
-                }
-                break;
-            case UNDERLINE_DASHDOTDOT:
-            case UNDERLINE_BOLDDASHDOTDOT:
-                {
-                    long nDotWidth = nLineHeight*mnDPIY;
-                    nDotWidth += mnDPIY/2;
-                    nDotWidth /= mnDPIY;
-                    long nDashWidth = ((100*mnDPIX)+1270)/2540;
-                    long nMinDashWidth = nDotWidth*4;
-                    // DashWidth will be increased if the line is getting too thick
-                    // in proportion to the line's length
-                    if ( nDashWidth < nMinDashWidth )
-                        nDashWidth = nMinDashWidth;
-                    long nTempDotWidth = nDotWidth;
-                    long nTempDashWidth = nDashWidth;
-                    long nEnd = nLeft+nWidth;
-                    while ( nLeft < nEnd )
-                    {
-                        if ( nLeft+nTempDotWidth > nEnd )
-                            nTempDotWidth = nEnd-nLeft;
-                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
-                        nLeft += nDotWidth*2;
-                        if ( nLeft > nEnd )
-                            break;
-                        if ( nLeft+nTempDotWidth > nEnd )
-                            nTempDotWidth = nEnd-nLeft;
-                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
-                        nLeft += nDotWidth*2;
-                        if ( nLeft > nEnd )
-                            break;
-                        if ( nLeft+nTempDashWidth > nEnd )
-                            nTempDashWidth = nEnd-nLeft;
-                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
-                        nLeft += nDashWidth+nDotWidth;
-                    }
-                }
-                break;
-            default:
-                break;
-        }
-    }
-}
-
-void OutputDevice::ImplDrawStrikeoutLine( long nBaseX, long nBaseY,
-                                          long nDistX, long nDistY, long nWidth,
-                                          FontStrikeout eStrikeout,
-                                          Color aColor )
-{
-    ImplFontEntry*  pFontEntry = mpFontEntry;
-    long            nLineHeight = 0;
-    long            nLinePos  = 0;
-    long            nLinePos2 = 0;
-
-    long nY = nDistY;
-
-    if ( eStrikeout > STRIKEOUT_LAST )
-        eStrikeout = STRIKEOUT_SINGLE;
-
-    switch ( eStrikeout )
-    {
-        case STRIKEOUT_SINGLE:
-            nLineHeight = pFontEntry->maMetric.mnStrikeoutSize;
-            nLinePos    = nY + pFontEntry->maMetric.mnStrikeoutOffset;
-            break;
-        case STRIKEOUT_BOLD:
-            nLineHeight = pFontEntry->maMetric.mnBStrikeoutSize;
-            nLinePos    = nY + pFontEntry->maMetric.mnBStrikeoutOffset;
-            break;
-        case STRIKEOUT_DOUBLE:
-            nLineHeight = pFontEntry->maMetric.mnDStrikeoutSize;
-            nLinePos    = nY + pFontEntry->maMetric.mnDStrikeoutOffset1;
-            nLinePos2   = nY + pFontEntry->maMetric.mnDStrikeoutOffset2;
-            break;
-        default:
-            break;
-    }
-
-    if ( nLineHeight )
-    {
-        if ( mbLineColor || mbInitLineColor )
-        {
-            mpGraphics->SetLineColor();
-            mbInitLineColor = true;
-        }
-        mpGraphics->SetFillColor( ImplColorToSal( aColor ) );
-        mbInitFillColor = true;
-
-        const long& nLeft = nDistX;
-
-        switch ( eStrikeout )
-        {
-            case STRIKEOUT_SINGLE:
-            case STRIKEOUT_BOLD:
-                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
-                break;
-            case STRIKEOUT_DOUBLE:
-                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
-                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos2, nWidth, nLineHeight );
-                break;
-            default:
-                break;
-        }
-    }
-}
-
-void OutputDevice::ImplDrawStrikeoutChar( long nBaseX, long nBaseY,
-                                          long nDistX, long nDistY, long nWidth,
-                                          FontStrikeout eStrikeout,
-                                          Color aColor )
-{
-    // See qadevOOo/testdocs/StrikeThrough.odt for examples if you need
-    // to tweak this
-    if (!nWidth)
-        return;
-
-    // prepare string for strikeout measurement
-    static char cStrikeoutChar;
-    if ( eStrikeout == STRIKEOUT_SLASH )
-        cStrikeoutChar = '/';
-    else // ( eStrikeout == STRIKEOUT_X )
-        cStrikeoutChar = 'X';
-    static const int nTestStrLen = 4;
-    static const int nMaxStrikeStrLen = 2048;
-    sal_Unicode aChars[nMaxStrikeStrLen+1]; // +1 for valgrind...
-    for( int i = 0; i < nTestStrLen; ++i)
-        aChars[i] = cStrikeoutChar;
-    const OUString aStrikeoutTest(aChars, nTestStrLen);
-
-    // calculate approximation of strikeout atom size
-    long nStrikeoutWidth = 0;
-    SalLayout* pLayout = ImplLayout( aStrikeoutTest, 0, nTestStrLen );
-    if( pLayout )
-    {
-        nStrikeoutWidth = pLayout->GetTextWidth() / (nTestStrLen * pLayout->GetUnitsPerPixel());
-        pLayout->Release();
-    }
-    if( nStrikeoutWidth <= 0 ) // sanity check
-        return;
-
-    int nStrikeStrLen = (nWidth+(nStrikeoutWidth-1)) / nStrikeoutWidth;
-    if( nStrikeStrLen > nMaxStrikeStrLen )
-        nStrikeStrLen = nMaxStrikeStrLen;
-
-    // build the strikeout string
-    for( int i = nTestStrLen; i < nStrikeStrLen; ++i)
-        aChars[i] = cStrikeoutChar;
-    const OUString aStrikeoutText(aChars, nStrikeStrLen);
-
-    if( mpFontEntry->mnOrientation )
-        ImplRotatePos( 0, 0, nDistX, nDistY, mpFontEntry->mnOrientation );
-    nBaseX += nDistX;
-    nBaseY += nDistY;
-
-    // strikeout text has to be left aligned
-    sal_uLong nOrigTLM = mnTextLayoutMode;
-    mnTextLayoutMode = TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_COMPLEX_DISABLED;
-    pLayout = ImplLayout( aStrikeoutText, 0, aStrikeoutText.getLength() );
-    mnTextLayoutMode = nOrigTLM;
-
-    if( !pLayout )
-        return;
-
-    // draw the strikeout text
-    const Color aOldColor = GetTextColor();
-    SetTextColor( aColor );
-    ImplInitTextColor();
-
-    pLayout->DrawBase() = Point( nBaseX+mnTextOffX, nBaseY+mnTextOffY );
-
-    Rectangle aPixelRect;
-    aPixelRect.Left() = nBaseX+mnTextOffX;
-    aPixelRect.Right() = aPixelRect.Left()+nWidth;
-    aPixelRect.Bottom() = nBaseY+mpFontEntry->maMetric.mnDescent;
-    aPixelRect.Top() = nBaseY-mpFontEntry->maMetric.mnAscent;
-
-    if (mpFontEntry->mnOrientation)
-    {
-        Polygon aPoly( aPixelRect );
-        aPoly.Rotate( Point(nBaseX+mnTextOffX, nBaseY+mnTextOffY), mpFontEntry->mnOrientation);
-        aPixelRect = aPoly.GetBoundRect();
-    }
-
-    Push( PUSH_CLIPREGION );
-    IntersectClipRegion( PixelToLogic(aPixelRect) );
-    if( mbInitClipRegion )
-        ImplInitClipRegion();
-
-    pLayout->DrawText( *mpGraphics );
-
-    pLayout->Release();
-    Pop();
-
-    SetTextColor( aOldColor );
-    ImplInitTextColor();
-}
-
-void OutputDevice::ImplDrawTextLine( long nX, long nY,
-                                     long nDistX, long nWidth,
-                                     FontStrikeout eStrikeout,
-                                     FontUnderline eUnderline,
-                                     FontUnderline eOverline,
-                                     bool bUnderlineAbove )
-{
-    if ( !nWidth )
-        return;
-
-    Color           aStrikeoutColor = GetTextColor();
-    Color           aUnderlineColor = GetTextLineColor();
-    Color           aOverlineColor  = GetOverlineColor();
-    bool            bStrikeoutDone = false;
-    bool            bUnderlineDone = false;
-    bool            bOverlineDone  = false;
-
-    if ( IsRTLEnabled() )
-    {
-        // --- RTL --- mirror at basex
-        long nXAdd = nWidth - nDistX;
-        if( mpFontEntry->mnOrientation )
-            nXAdd = FRound( nXAdd * cos( mpFontEntry->mnOrientation * F_PI1800 ) );
-        nX += nXAdd - 1;
-    }
-
-    if ( !IsTextLineColor() )
-        aUnderlineColor = GetTextColor();
-
-    if ( !IsOverlineColor() )
-        aOverlineColor = GetTextColor();
-
-    if ( (eUnderline == UNDERLINE_SMALLWAVE) ||
-         (eUnderline == UNDERLINE_WAVE) ||
-         (eUnderline == UNDERLINE_DOUBLEWAVE) ||
-         (eUnderline == UNDERLINE_BOLDWAVE) )
-    {
-        ImplDrawWaveTextLine( nX, nY, nDistX, 0, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
-        bUnderlineDone = true;
-    }
-    if ( (eOverline == UNDERLINE_SMALLWAVE) ||
-         (eOverline == UNDERLINE_WAVE) ||
-         (eOverline == UNDERLINE_DOUBLEWAVE) ||
-         (eOverline == UNDERLINE_BOLDWAVE) )
-    {
-        ImplDrawWaveTextLine( nX, nY, nDistX, 0, nWidth, eOverline, aOverlineColor, true );
-        bOverlineDone = true;
-    }
-
-    if ( (eStrikeout == STRIKEOUT_SLASH) ||
-         (eStrikeout == STRIKEOUT_X) )
-    {
-        ImplDrawStrikeoutChar( nX, nY, nDistX, 0, nWidth, eStrikeout, aStrikeoutColor );
-        bStrikeoutDone = true;
-    }
-
-    if ( !bUnderlineDone )
-        ImplDrawStraightTextLine( nX, nY, nDistX, 0, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
-
-    if ( !bOverlineDone )
-        ImplDrawStraightTextLine( nX, nY, nDistX, 0, nWidth, eOverline, aOverlineColor, true );
-
-    if ( !bStrikeoutDone )
-        ImplDrawStrikeoutLine( nX, nY, nDistX, 0, nWidth, eStrikeout, aStrikeoutColor );
-}
-
-void OutputDevice::ImplDrawTextLines( SalLayout& rSalLayout,
-    FontStrikeout eStrikeout, FontUnderline eUnderline, FontUnderline eOverline, bool bWordLine, bool bUnderlineAbove )
-{
-    if( bWordLine )
-    {
-        // draw everything relative to the layout base point
-        const Point aStartPt = rSalLayout.DrawBase();
-
-        // calculate distance of each word from the base point
-        Point aPos;
-        sal_Int32 nDist = 0, nWidth = 0, nAdvance=0;
-        for( int nStart = 0;;)
-        {
-            // iterate through the layouted glyphs
-            sal_GlyphId aGlyphId;
-            if( !rSalLayout.GetNextGlyphs( 1, &aGlyphId, aPos, nStart, &nAdvance ) )
-                break;
-
-            // calculate the boundaries of each word
-            if( !rSalLayout.IsSpacingGlyph( aGlyphId ) )
-            {
-                if( !nWidth )
-                {
-                    // get the distance to the base point (as projected to baseline)
-                    nDist = aPos.X() - aStartPt.X();
-                    if( mpFontEntry->mnOrientation )
-                    {
-                        const long nDY = aPos.Y() - aStartPt.Y();
-                        const double fRad = mpFontEntry->mnOrientation * F_PI1800;
-                        nDist = FRound( nDist*cos(fRad) - nDY*sin(fRad) );
-                    }
-                }
-
-                // update the length of the textline
-                nWidth += nAdvance;
-            }
-            else if( nWidth > 0 )
-            {
-                // draw the textline for each word
-                ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), nDist, nWidth,
-                    eStrikeout, eUnderline, eOverline, bUnderlineAbove );
-                nWidth = 0;
-            }
-        }
-
-        // draw textline for the last word
-        if( nWidth > 0 )
-        {
-            ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), nDist, nWidth,
-                eStrikeout, eUnderline, eOverline, bUnderlineAbove );
-        }
-    }
-    else
-    {
-        Point aStartPt = rSalLayout.GetDrawPosition();
-        int nWidth = rSalLayout.GetTextWidth() / rSalLayout.GetUnitsPerPixel();
-        ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), 0, nWidth,
-            eStrikeout, eUnderline, eOverline, bUnderlineAbove );
-    }
-}
-
-void OutputDevice::ImplDrawMnemonicLine( long nX, long nY, long nWidth )
-{
-    long nBaseX = nX;
-    if( /*HasMirroredGraphics() &&*/ IsRTLEnabled() )
-    {
-        // --- RTL ---
-        // add some strange offset
-        nX += 2;
-        // revert the hack that will be done later in ImplDrawTextLine
-        nX = nBaseX - nWidth - (nX - nBaseX - 1);
-    }
-
-    ImplDrawTextLine( nX, nY, 0, nWidth, STRIKEOUT_NONE, UNDERLINE_SINGLE, UNDERLINE_NONE, false );
-}
-
 bool OutputDevice::ImplDrawRotateText( SalLayout& rSalLayout )
 {
     int nX = rSalLayout.DrawBase().X();
@@ -1641,108 +889,6 @@ Color OutputDevice::GetTextFillColor() const
         return maFont.GetFillColor();
 }
 
-void OutputDevice::SetTextLineColor()
-{
-
-    if ( mpMetaFile )
-        mpMetaFile->AddAction( new MetaTextLineColorAction( Color(), false ) );
-
-    maTextLineColor = Color( COL_TRANSPARENT );
-
-    if( mpAlphaVDev )
-        mpAlphaVDev->SetTextLineColor();
-}
-
-void OutputDevice::SetTextLineColor( const Color& rColor )
-{
-
-    Color aColor( rColor );
-
-    if ( mnDrawMode & ( DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT |
-                        DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT |
-                        DRAWMODE_SETTINGSTEXT ) )
-    {
-        if ( mnDrawMode & DRAWMODE_BLACKTEXT )
-            aColor = Color( COL_BLACK );
-        else if ( mnDrawMode & DRAWMODE_WHITETEXT )
-            aColor = Color( COL_WHITE );
-        else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
-        {
-            const sal_uInt8 cLum = aColor.GetLuminance();
-            aColor = Color( cLum, cLum, cLum );
-        }
-        else if ( mnDrawMode & DRAWMODE_SETTINGSTEXT )
-            aColor = GetSettings().GetStyleSettings().GetFontColor();
-
-        if( (mnDrawMode & DRAWMODE_GHOSTEDTEXT)
-        &&  (aColor.GetColor() != COL_TRANSPARENT) )
-        {
-            aColor = Color( (aColor.GetRed() >> 1) | 0x80,
-                            (aColor.GetGreen() >> 1) | 0x80,
-                            (aColor.GetBlue() >> 1) | 0x80 );
-        }
-    }
-
-    if ( mpMetaFile )
-        mpMetaFile->AddAction( new MetaTextLineColorAction( aColor, true ) );
-
-    maTextLineColor = aColor;
-
-    if( mpAlphaVDev )
-        mpAlphaVDev->SetTextLineColor( COL_BLACK );
-}
-
-void OutputDevice::SetOverlineColor()
-{
-
-    if ( mpMetaFile )
-        mpMetaFile->AddAction( new MetaOverlineColorAction( Color(), false ) );
-
-    maOverlineColor = Color( COL_TRANSPARENT );
-
-    if( mpAlphaVDev )
-        mpAlphaVDev->SetOverlineColor();
-}
-
-void OutputDevice::SetOverlineColor( const Color& rColor )
-{
-
-    Color aColor( rColor );
-
-    if ( mnDrawMode & ( DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT |
-                        DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT |
-                        DRAWMODE_SETTINGSTEXT ) )
-    {
-        if ( mnDrawMode & DRAWMODE_BLACKTEXT )
-            aColor = Color( COL_BLACK );
-        else if ( mnDrawMode & DRAWMODE_WHITETEXT )
-            aColor = Color( COL_WHITE );
-        else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
-        {
-            const sal_uInt8 cLum = aColor.GetLuminance();
-            aColor = Color( cLum, cLum, cLum );
-        }
-        else if ( mnDrawMode & DRAWMODE_SETTINGSTEXT )
-            aColor = GetSettings().GetStyleSettings().GetFontColor();
-
-        if( (mnDrawMode & DRAWMODE_GHOSTEDTEXT)
-        &&  (aColor.GetColor() != COL_TRANSPARENT) )
-        {
-            aColor = Color( (aColor.GetRed() >> 1) | 0x80,
-                            (aColor.GetGreen() >> 1) | 0x80,
-                            (aColor.GetBlue() >> 1) | 0x80 );
-        }
-    }
-
-    if ( mpMetaFile )
-        mpMetaFile->AddAction( new MetaOverlineColorAction( aColor, true ) );
-
-    maOverlineColor = aColor;
-
-    if( mpAlphaVDev )
-        mpAlphaVDev->SetOverlineColor( COL_BLACK );
-}
-
 void OutputDevice::SetTextAlign( TextAlign eAlign )
 {
 
@@ -1759,119 +905,6 @@ void OutputDevice::SetTextAlign( TextAlign eAlign )
         mpAlphaVDev->SetTextAlign( eAlign );
 }
 
-void OutputDevice::DrawTextLine( const Point& rPos, long nWidth,
-                                 FontStrikeout eStrikeout,
-                                 FontUnderline eUnderline,
-                                 FontUnderline eOverline,
-                                 bool bUnderlineAbove )
-{
-
-    if ( mpMetaFile )
-        mpMetaFile->AddAction( new MetaTextLineAction( rPos, nWidth, eStrikeout, eUnderline, eOverline ) );
-
-    if ( ((eUnderline == UNDERLINE_NONE) || (eUnderline == UNDERLINE_DONTKNOW)) &&
-         ((eOverline  == UNDERLINE_NONE) || (eOverline  == UNDERLINE_DONTKNOW)) &&
-         ((eStrikeout == STRIKEOUT_NONE) || (eStrikeout == STRIKEOUT_DONTKNOW)) )
-        return;
-
-    if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
-        return;
-
-    // we need a graphics
-    if( !mpGraphics && !ImplGetGraphics() )
-        return;
-    if( mbInitClipRegion )
-        ImplInitClipRegion();
-    if( mbOutputClipped )
-        return;
-
-    // initialize font if needed to get text offsets
-    // TODO: only needed for mnTextOff!=(0,0)
-    if( mbNewFont )
-        if( !ImplNewFont() )
-            return;
-    if( mbInitFont )
-        InitFont();
-
-    Point aPos = ImplLogicToDevicePixel( rPos );
-    nWidth = ImplLogicWidthToDevicePixel( nWidth );
-    aPos += Point( mnTextOffX, mnTextOffY );
-    ImplDrawTextLine( aPos.X(), aPos.X(), 0, nWidth, eStrikeout, eUnderline, eOverline, bUnderlineAbove );
-
-    if( mpAlphaVDev )
-        mpAlphaVDev->DrawTextLine( rPos, nWidth, eStrikeout, eUnderline, eOverline, bUnderlineAbove );
-}
-
-void OutputDevice::DrawWaveLine( const Point& rStartPos, const Point& rEndPos )
-{
-
-    if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
-        return;
-
-    // we need a graphics
-    if( !mpGraphics )
-        if( !ImplGetGraphics() )
-            return;
-
-    if ( mbInitClipRegion )
-        ImplInitClipRegion();
-    if ( mbOutputClipped )
-        return;
-
-    if( mbNewFont )
-        if( !ImplNewFont() )
-            return;
-
-    Point   aStartPt = ImplLogicToDevicePixel( rStartPos );
-    Point   aEndPt = ImplLogicToDevicePixel( rEndPos );
-    long    nStartX = aStartPt.X();
-    long    nStartY = aStartPt.Y();
-    long    nEndX = aEndPt.X();
-    long    nEndY = aEndPt.Y();
-    short   nOrientation = 0;
-
-    // when rotated
-    if ( (nStartY != nEndY) || (nStartX > nEndX) )
-    {
-        long nDX = nEndX - nStartX;
-        double nO = atan2( -nEndY + nStartY, ((nDX == 0L) ? 0.000000001 : nDX) );
-        nO /= F_PI1800;
-        nOrientation = (short)nO;
-        ImplRotatePos( nStartX, nStartY, nEndX, nEndY, -nOrientation );
-    }
-
-    long nWaveHeight;
-
-    nWaveHeight = 3;
-    nStartY++;
-    nEndY++;
-
-    if (mnDPIScaleFactor > 1)
-    {
-        nWaveHeight *= mnDPIScaleFactor;
-
-        nStartY += mnDPIScaleFactor - 1; // Shift down additional pixel(s) to create more visual separation.
-
-        // odd heights look better than even
-        if (mnDPIScaleFactor % 2 == 0)
-        {
-            nWaveHeight--;
-        }
-    }
-
-    // #109280# make sure the waveline does not exceed the descent to avoid paint problems
-    ImplFontEntry* pFontEntry = mpFontEntry;
-    if( nWaveHeight > pFontEntry->maMetric.mnWUnderlineSize )
-        nWaveHeight = pFontEntry->maMetric.mnWUnderlineSize;
-
-    ImplDrawWaveLine(nStartX, nStartY, 0, 0,
-            nEndX-nStartX, nWaveHeight,
-            mnDPIScaleFactor, nOrientation, GetLineColor());
-
-    if( mpAlphaVDev )
-        mpAlphaVDev->DrawWaveLine( rStartPos, rEndPos );
-}
-
 void OutputDevice::DrawText( const Point& rStartPt, const OUString& rStr,
                              sal_Int32 nIndex, sal_Int32 nLen,
                              MetricVector* pVector, OUString* pDisplayText
diff --git a/vcl/source/outdev/textline.cxx b/vcl/source/outdev/textline.cxx
new file mode 100644
index 0000000..7257eb0
--- /dev/null
+++ b/vcl/source/outdev/textline.cxx
@@ -0,0 +1,1068 @@
+/* -*- 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 "i18nlangtag/mslangid.hxx"
+#include "i18nlangtag/languagetag.hxx"
+
+#include "rtl/tencinfo.h"
+#include "rtl/logfile.hxx"
+
+#include "tools/debug.hxx"
+#include "tools/poly.hxx"
+
+#include "basegfx/polygon/b2dpolygon.hxx"
+#include "basegfx/polygon/b2dpolypolygon.hxx"
+#include "basegfx/matrix/b2dhommatrix.hxx"
+
+#include "vcl/metric.hxx"
+#include "vcl/metaact.hxx"
+#include "vcl/gdimtf.hxx"
+#include "vcl/virdev.hxx"
+#include "vcl/print.hxx"
+#include "vcl/event.hxx"
+#include "vcl/window.hxx"
+#include "vcl/svapp.hxx"
+#include "vcl/bmpacc.hxx"
+#include "vcl/outdev.hxx"
+#include "vcl/edit.hxx"
+#include <vcl/settings.hxx>
+// declare system types in sysdata.hxx
+#include <svsys.h>
+#include "vcl/sysdata.hxx"
+#include "vcl/unohelp.hxx"
+#include "vcl/controllayout.hxx"
+
+#include "salgdi.hxx"
+#include "sallayout.hxx"
+#include "svdata.hxx"
+#include "impfont.hxx"
+#include "outdata.hxx"
+#include "outfont.hxx"
+#include "outdev.h"
+#include "PhysicalFontCollection.hxx"
+#include "PhysicalFontFace.hxx"
+#include "PhysicalFontFamily.hxx"
+
+#include "textlayout.hxx"
+#include "svids.hrc"
+#include "window.h"
+
+#include "unotools/fontcvt.hxx"
+#include "unotools/fontcfg.hxx"
+
+#include "osl/file.h"
+
+#include <config_graphite.h>
+#if ENABLE_GRAPHITE
+#include "graphite_features.hxx"
+#endif
+
+#include "../gdi/pdfwriter_impl.hxx"
+
+#include "com/sun/star/beans/PropertyValues.hpp"
+#include "com/sun/star/i18n/XBreakIterator.hpp"
+#include "com/sun/star/i18n/WordType.hpp"
+#include "com/sun/star/linguistic2/LinguServiceManager.hpp"
+#include <comphelper/processfactory.hxx>
+
+#include "sal/alloca.h"
+
+#include <cmath>
+#include <cstring>
+
+#include <memory>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::rtl;
+using namespace ::vcl;
+using namespace ::utl;
+
+#define UNDERLINE_LAST      UNDERLINE_BOLDWAVE
+#define STRIKEOUT_LAST      STRIKEOUT_X
+
+bool OutputDevice::ImplIsUnderlineAbove( const Font& rFont )
+{
+    if ( !rFont.IsVertical() )
+        return false;
+
+    if( (LANGUAGE_JAPANESE == rFont.GetLanguage())
+    ||  (LANGUAGE_JAPANESE == rFont.GetCJKContextLanguage()) )
+        // the underline is right for Japanese only
+        return true;
+
+    return false;
+}
+
+void OutputDevice::ImplInitTextLineSize()
+{
+    mpFontEntry->maMetric.ImplInitTextLineSize( this );
+}
+
+void OutputDevice::ImplInitAboveTextLineSize()
+{
+    mpFontEntry->maMetric.ImplInitAboveTextLineSize();
+}
+
+static void ImplDrawWavePixel( long nOriginX, long nOriginY,
+                               long nCurX, long nCurY,
+                               short nOrientation,
+                               SalGraphics* pGraphics,
+                               OutputDevice* pOutDev,
+                               bool bDrawPixAsRect,
+
+                               long nPixWidth, long nPixHeight )
+{
+    if ( nOrientation )
+        ImplRotatePos( nOriginX, nOriginY, nCurX, nCurY, nOrientation );
+
+    if ( bDrawPixAsRect )
+    {
+
+        pGraphics->DrawRect( nCurX, nCurY, nPixWidth, nPixHeight, pOutDev );
+    }
+    else
+    {
+        pGraphics->DrawPixel( nCurX, nCurY, pOutDev );
+    }
+}
+
+void OutputDevice::ImplDrawWaveLine( long nBaseX, long nBaseY,
+                                     long nDistX, long nDistY,
+                                     long nWidth, long nHeight,
+                                     long nLineWidth, short nOrientation,
+                                     const Color& rColor )
+{
+    if ( !nHeight )
+        return;
+
+    long nStartX = nBaseX + nDistX;
+    long nStartY = nBaseY + nDistY;
+
+    // If the height is 1 pixel, it's enough ouput a line
+    if ( (nLineWidth == 1) && (nHeight == 1) )
+    {
+        mpGraphics->SetLineColor( ImplColorToSal( rColor ) );
+        mbInitLineColor = true;
+
+        long nEndX = nStartX+nWidth;
+        long nEndY = nStartY;
+        if ( nOrientation )
+        {
+            ImplRotatePos( nBaseX, nBaseY, nStartX, nStartY, nOrientation );
+            ImplRotatePos( nBaseX, nBaseY, nEndX, nEndY, nOrientation );
+        }
+        mpGraphics->DrawLine( nStartX, nStartY, nEndX, nEndY, this );
+    }
+    else
+    {
+        long    nCurX = nStartX;
+        long    nCurY = nStartY;
+        long    nDiffX = 2;
+        long    nDiffY = nHeight-1;
+        long    nCount = nWidth;
+        long    nOffY = -1;
+        long    nFreq;
+        long    i;
+        long    nPixWidth;
+        long    nPixHeight;
+        bool    bDrawPixAsRect;
+        // On printers that ouput pixel via DrawRect()
+        if ( (GetOutDevType() == OUTDEV_PRINTER) || (nLineWidth > 1) )
+        {
+            if ( mbLineColor || mbInitLineColor )
+            {
+                mpGraphics->SetLineColor();
+                mbInitLineColor = true;
+            }
+            mpGraphics->SetFillColor( ImplColorToSal( rColor ) );
+            mbInitFillColor = true;
+            bDrawPixAsRect  = true;
+            nPixWidth       = nLineWidth;
+            nPixHeight      = ((nLineWidth*mnDPIX)+(mnDPIY/2))/mnDPIY;
+        }
+        else
+        {
+            mpGraphics->SetLineColor( ImplColorToSal( rColor ) );
+            mbInitLineColor = true;
+            nPixWidth       = 1;
+            nPixHeight      = 1;
+            bDrawPixAsRect  = false;
+        }
+
+        if ( !nDiffY )
+        {
+            while ( nWidth )
+            {
+                ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+                                   mpGraphics, this,
+                                   bDrawPixAsRect, nPixWidth, nPixHeight );
+                nCurX++;
+                nWidth--;
+            }
+        }
+        else
+        {
+            nCurY += nDiffY;
+            nFreq = nCount / (nDiffX+nDiffY);
+            while ( nFreq-- )
+            {
+                for( i = nDiffY; i; --i )
+                {
+                    ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+                                       mpGraphics, this,
+                                       bDrawPixAsRect, nPixWidth, nPixHeight );
+                    nCurX++;
+                    nCurY += nOffY;
+                }
+                for( i = nDiffX; i; --i )
+                {
+                    ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+                                       mpGraphics, this,
+                                       bDrawPixAsRect, nPixWidth, nPixHeight );
+                    nCurX++;
+                }
+                nOffY = -nOffY;
+            }
+            nFreq = nCount % (nDiffX+nDiffY);
+            if ( nFreq )
+            {
+                for( i = nDiffY; i && nFreq; --i, --nFreq )
+                {
+                    ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+                                       mpGraphics, this,
+                                       bDrawPixAsRect, nPixWidth, nPixHeight );
+                    nCurX++;
+                    nCurY += nOffY;
+
+                }
+                for( i = nDiffX; i && nFreq; --i, --nFreq )
+                {
+                    ImplDrawWavePixel( nBaseX, nBaseY, nCurX, nCurY, nOrientation,
+                                       mpGraphics, this,
+                                       bDrawPixAsRect, nPixWidth, nPixHeight );
+                    nCurX++;
+                }
+            }
+        }
+
+    }
+}
+
+void OutputDevice::ImplDrawWaveTextLine( long nBaseX, long nBaseY,
+                                         long nDistX, long nDistY, long nWidth,
+                                         FontUnderline eTextLine,
+                                         Color aColor,
+                                         bool bIsAbove )
+{
+    ImplFontEntry*  pFontEntry = mpFontEntry;
+    long            nLineHeight;
+    long            nLinePos;
+
+    if ( bIsAbove )
+    {
+        nLineHeight = pFontEntry->maMetric.mnAboveWUnderlineSize;
+        nLinePos = pFontEntry->maMetric.mnAboveWUnderlineOffset;
+    }
+    else
+    {
+        nLineHeight = pFontEntry->maMetric.mnWUnderlineSize;
+        nLinePos = pFontEntry->maMetric.mnWUnderlineOffset;
+    }
+    if ( (eTextLine == UNDERLINE_SMALLWAVE) && (nLineHeight > 3) )
+        nLineHeight = 3;
+    long nLineWidth = (mnDPIX/300);
+    if ( !nLineWidth )
+        nLineWidth = 1;
+    if ( eTextLine == UNDERLINE_BOLDWAVE )
+        nLineWidth *= 2;
+    nLinePos += nDistY - (nLineHeight / 2);
+    long nLineWidthHeight = ((nLineWidth*mnDPIX)+(mnDPIY/2))/mnDPIY;
+    if ( eTextLine == UNDERLINE_DOUBLEWAVE )
+    {
+        long nOrgLineHeight = nLineHeight;
+        nLineHeight /= 3;
+        if ( nLineHeight < 2 )
+        {
+            if ( nOrgLineHeight > 1 )
+                nLineHeight = 2;
+            else
+                nLineHeight = 1;
+        }
+        long nLineDY = nOrgLineHeight-(nLineHeight*2);
+        if ( nLineDY < nLineWidthHeight )
+            nLineDY = nLineWidthHeight;
+        long nLineDY2 = nLineDY/2;
+        if ( !nLineDY2 )
+            nLineDY2 = 1;
+
+        nLinePos -= nLineWidthHeight-nLineDY2;
+        ImplDrawWaveLine( nBaseX, nBaseY, nDistX, nLinePos, nWidth, nLineHeight,
+                          nLineWidth, mpFontEntry->mnOrientation, aColor );
+        nLinePos += nLineWidthHeight+nLineDY;
+        ImplDrawWaveLine( nBaseX, nBaseY, nDistX, nLinePos, nWidth, nLineHeight,
+                          nLineWidth, mpFontEntry->mnOrientation, aColor );
+    }
+    else
+    {
+        nLinePos -= nLineWidthHeight/2;
+        ImplDrawWaveLine( nBaseX, nBaseY, nDistX, nLinePos, nWidth, nLineHeight,
+                          nLineWidth, mpFontEntry->mnOrientation, aColor );
+    }
+}
+
+void OutputDevice::ImplDrawStraightTextLine( long nBaseX, long nBaseY,
+                                             long nDistX, long nDistY, long nWidth,
+                                             FontUnderline eTextLine,
+                                             Color aColor,
+                                             bool bIsAbove )
+{
+    ImplFontEntry*  pFontEntry = mpFontEntry;
+    long            nLineHeight = 0;
+    long            nLinePos  = 0;
+    long            nLinePos2 = 0;
+
+    const long nY = nDistY;
+
+    if ( eTextLine > UNDERLINE_LAST )
+        eTextLine = UNDERLINE_SINGLE;
+
+    switch ( eTextLine )
+    {
+        case UNDERLINE_SINGLE:
+        case UNDERLINE_DOTTED:
+        case UNDERLINE_DASH:
+        case UNDERLINE_LONGDASH:
+        case UNDERLINE_DASHDOT:
+        case UNDERLINE_DASHDOTDOT:
+            if ( bIsAbove )
+            {
+                nLineHeight = pFontEntry->maMetric.mnAboveUnderlineSize;
+                nLinePos    = nY + pFontEntry->maMetric.mnAboveUnderlineOffset;
+            }
+            else
+            {
+                nLineHeight = pFontEntry->maMetric.mnUnderlineSize;
+                nLinePos    = nY + pFontEntry->maMetric.mnUnderlineOffset;
+            }
+            break;
+        case UNDERLINE_BOLD:
+        case UNDERLINE_BOLDDOTTED:
+        case UNDERLINE_BOLDDASH:
+        case UNDERLINE_BOLDLONGDASH:
+        case UNDERLINE_BOLDDASHDOT:
+        case UNDERLINE_BOLDDASHDOTDOT:
+            if ( bIsAbove )
+            {
+                nLineHeight = pFontEntry->maMetric.mnAboveBUnderlineSize;
+                nLinePos    = nY + pFontEntry->maMetric.mnAboveBUnderlineOffset;
+            }
+            else
+            {
+                nLineHeight = pFontEntry->maMetric.mnBUnderlineSize;
+                nLinePos    = nY + pFontEntry->maMetric.mnBUnderlineOffset;
+            }
+            break;
+        case UNDERLINE_DOUBLE:
+            if ( bIsAbove )
+            {
+                nLineHeight = pFontEntry->maMetric.mnAboveDUnderlineSize;
+                nLinePos    = nY + pFontEntry->maMetric.mnAboveDUnderlineOffset1;
+                nLinePos2   = nY + pFontEntry->maMetric.mnAboveDUnderlineOffset2;
+            }
+            else
+            {
+                nLineHeight = pFontEntry->maMetric.mnDUnderlineSize;
+                nLinePos    = nY + pFontEntry->maMetric.mnDUnderlineOffset1;
+                nLinePos2   = nY + pFontEntry->maMetric.mnDUnderlineOffset2;
+            }
+            break;
+        default:
+            break;
+    }
+
+    if ( nLineHeight )
+    {
+        if ( mbLineColor || mbInitLineColor )
+        {
+            mpGraphics->SetLineColor();
+            mbInitLineColor = true;
+        }
+        mpGraphics->SetFillColor( ImplColorToSal( aColor ) );
+        mbInitFillColor = true;
+
+        long nLeft = nDistX;
+
+        switch ( eTextLine )
+        {
+            case UNDERLINE_SINGLE:
+            case UNDERLINE_BOLD:
+                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
+                break;
+            case UNDERLINE_DOUBLE:
+                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos,  nWidth, nLineHeight );
+                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos2, nWidth, nLineHeight );
+                break;
+            case UNDERLINE_DOTTED:
+            case UNDERLINE_BOLDDOTTED:
+                {
+                    long nDotWidth = nLineHeight*mnDPIY;
+                    nDotWidth += mnDPIY/2;
+                    nDotWidth /= mnDPIY;
+                    long nTempWidth = nDotWidth;
+                    long nEnd = nLeft+nWidth;
+                    while ( nLeft < nEnd )
+                    {
+                        if ( nLeft+nTempWidth > nEnd )
+                            nTempWidth = nEnd-nLeft;
+                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
+                        nLeft += nDotWidth*2;
+                    }
+                }
+                break;
+            case UNDERLINE_DASH:
+            case UNDERLINE_LONGDASH:
+            case UNDERLINE_BOLDDASH:
+            case UNDERLINE_BOLDLONGDASH:
+                {
+                    long nDotWidth = nLineHeight*mnDPIY;
+                    nDotWidth += mnDPIY/2;
+                    nDotWidth /= mnDPIY;
+                    long nMinDashWidth;
+                    long nMinSpaceWidth;
+                    long nSpaceWidth;
+                    long nDashWidth;
+                    if ( (eTextLine == UNDERLINE_LONGDASH) ||
+                         (eTextLine == UNDERLINE_BOLDLONGDASH) )
+                    {
+                        nMinDashWidth = nDotWidth*6;
+                        nMinSpaceWidth = nDotWidth*2;
+                        nDashWidth = 200;
+                        nSpaceWidth = 100;
+                    }
+                    else
+                    {
+                        nMinDashWidth = nDotWidth*4;
+                        nMinSpaceWidth = (nDotWidth*150)/100;
+                        nDashWidth = 100;
+                        nSpaceWidth = 50;
+                    }
+                    nDashWidth = ((nDashWidth*mnDPIX)+1270)/2540;
+                    nSpaceWidth = ((nSpaceWidth*mnDPIX)+1270)/2540;
+                    // DashWidth will be increased if the line is getting too thick
+                    // in proportion to the line's length
+                    if ( nDashWidth < nMinDashWidth )
+                        nDashWidth = nMinDashWidth;
+                    if ( nSpaceWidth < nMinSpaceWidth )
+                        nSpaceWidth = nMinSpaceWidth;
+                    long nTempWidth = nDashWidth;
+                    long nEnd = nLeft+nWidth;
+                    while ( nLeft < nEnd )
+                    {
+                        if ( nLeft+nTempWidth > nEnd )
+                            nTempWidth = nEnd-nLeft;
+                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempWidth, nLineHeight );
+                        nLeft += nDashWidth+nSpaceWidth;
+                    }
+                }
+                break;
+            case UNDERLINE_DASHDOT:
+            case UNDERLINE_BOLDDASHDOT:
+                {
+                    long nDotWidth = nLineHeight*mnDPIY;
+                    nDotWidth += mnDPIY/2;
+                    nDotWidth /= mnDPIY;
+                    long nDashWidth = ((100*mnDPIX)+1270)/2540;
+                    long nMinDashWidth = nDotWidth*4;
+                    // DashWidth will be increased if the line is getting too thick
+                    // in proportion to the line's length
+                    if ( nDashWidth < nMinDashWidth )
+                        nDashWidth = nMinDashWidth;
+                    long nTempDotWidth = nDotWidth;
+                    long nTempDashWidth = nDashWidth;
+                    long nEnd = nLeft+nWidth;
+                    while ( nLeft < nEnd )
+                    {
+                        if ( nLeft+nTempDotWidth > nEnd )
+                            nTempDotWidth = nEnd-nLeft;
+                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
+                        nLeft += nDotWidth*2;
+                        if ( nLeft > nEnd )
+                            break;
+                        if ( nLeft+nTempDashWidth > nEnd )
+                            nTempDashWidth = nEnd-nLeft;
+                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
+                        nLeft += nDashWidth+nDotWidth;
+                    }
+                }
+                break;
+            case UNDERLINE_DASHDOTDOT:
+            case UNDERLINE_BOLDDASHDOTDOT:
+                {
+                    long nDotWidth = nLineHeight*mnDPIY;
+                    nDotWidth += mnDPIY/2;
+                    nDotWidth /= mnDPIY;
+                    long nDashWidth = ((100*mnDPIX)+1270)/2540;
+                    long nMinDashWidth = nDotWidth*4;
+                    // DashWidth will be increased if the line is getting too thick
+                    // in proportion to the line's length
+                    if ( nDashWidth < nMinDashWidth )
+                        nDashWidth = nMinDashWidth;
+                    long nTempDotWidth = nDotWidth;
+                    long nTempDashWidth = nDashWidth;
+                    long nEnd = nLeft+nWidth;
+                    while ( nLeft < nEnd )
+                    {
+                        if ( nLeft+nTempDotWidth > nEnd )
+                            nTempDotWidth = nEnd-nLeft;
+                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
+                        nLeft += nDotWidth*2;
+                        if ( nLeft > nEnd )
+                            break;
+                        if ( nLeft+nTempDotWidth > nEnd )
+                            nTempDotWidth = nEnd-nLeft;
+                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDotWidth, nLineHeight );
+                        nLeft += nDotWidth*2;
+                        if ( nLeft > nEnd )
+                            break;
+                        if ( nLeft+nTempDashWidth > nEnd )
+                            nTempDashWidth = nEnd-nLeft;
+                        ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nTempDashWidth, nLineHeight );
+                        nLeft += nDashWidth+nDotWidth;
+                    }
+                }
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+void OutputDevice::ImplDrawStrikeoutLine( long nBaseX, long nBaseY,
+                                          long nDistX, long nDistY, long nWidth,
+                                          FontStrikeout eStrikeout,
+                                          Color aColor )
+{
+    ImplFontEntry*  pFontEntry = mpFontEntry;
+    long            nLineHeight = 0;
+    long            nLinePos  = 0;
+    long            nLinePos2 = 0;
+
+    long nY = nDistY;
+
+    if ( eStrikeout > STRIKEOUT_LAST )
+        eStrikeout = STRIKEOUT_SINGLE;
+
+    switch ( eStrikeout )
+    {
+        case STRIKEOUT_SINGLE:
+            nLineHeight = pFontEntry->maMetric.mnStrikeoutSize;
+            nLinePos    = nY + pFontEntry->maMetric.mnStrikeoutOffset;
+            break;
+        case STRIKEOUT_BOLD:
+            nLineHeight = pFontEntry->maMetric.mnBStrikeoutSize;
+            nLinePos    = nY + pFontEntry->maMetric.mnBStrikeoutOffset;
+            break;
+        case STRIKEOUT_DOUBLE:
+            nLineHeight = pFontEntry->maMetric.mnDStrikeoutSize;
+            nLinePos    = nY + pFontEntry->maMetric.mnDStrikeoutOffset1;
+            nLinePos2   = nY + pFontEntry->maMetric.mnDStrikeoutOffset2;
+            break;
+        default:
+            break;
+    }
+
+    if ( nLineHeight )
+    {
+        if ( mbLineColor || mbInitLineColor )
+        {
+            mpGraphics->SetLineColor();
+            mbInitLineColor = true;
+        }
+        mpGraphics->SetFillColor( ImplColorToSal( aColor ) );
+        mbInitFillColor = true;
+
+        const long& nLeft = nDistX;
+
+        switch ( eStrikeout )
+        {
+            case STRIKEOUT_SINGLE:
+            case STRIKEOUT_BOLD:
+                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
+                break;
+            case STRIKEOUT_DOUBLE:
+                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos, nWidth, nLineHeight );
+                ImplDrawTextRect( nBaseX, nBaseY, nLeft, nLinePos2, nWidth, nLineHeight );
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+void OutputDevice::ImplDrawStrikeoutChar( long nBaseX, long nBaseY,
+                                          long nDistX, long nDistY, long nWidth,
+                                          FontStrikeout eStrikeout,
+                                          Color aColor )
+{
+    // See qadevOOo/testdocs/StrikeThrough.odt for examples if you need
+    // to tweak this
+    if (!nWidth)
+        return;
+
+    // prepare string for strikeout measurement
+    static char cStrikeoutChar;
+    if ( eStrikeout == STRIKEOUT_SLASH )
+        cStrikeoutChar = '/';
+    else // ( eStrikeout == STRIKEOUT_X )
+        cStrikeoutChar = 'X';
+    static const int nTestStrLen = 4;
+    static const int nMaxStrikeStrLen = 2048;
+    sal_Unicode aChars[nMaxStrikeStrLen+1]; // +1 for valgrind...
+    for( int i = 0; i < nTestStrLen; ++i)
+        aChars[i] = cStrikeoutChar;
+    const OUString aStrikeoutTest(aChars, nTestStrLen);
+
+    // calculate approximation of strikeout atom size
+    long nStrikeoutWidth = 0;
+    SalLayout* pLayout = ImplLayout( aStrikeoutTest, 0, nTestStrLen );
+    if( pLayout )
+    {
+        nStrikeoutWidth = pLayout->GetTextWidth() / (nTestStrLen * pLayout->GetUnitsPerPixel());
+        pLayout->Release();
+    }
+    if( nStrikeoutWidth <= 0 ) // sanity check
+        return;
+
+    int nStrikeStrLen = (nWidth+(nStrikeoutWidth-1)) / nStrikeoutWidth;
+    if( nStrikeStrLen > nMaxStrikeStrLen )
+        nStrikeStrLen = nMaxStrikeStrLen;
+
+    // build the strikeout string
+    for( int i = nTestStrLen; i < nStrikeStrLen; ++i)
+        aChars[i] = cStrikeoutChar;
+    const OUString aStrikeoutText(aChars, nStrikeStrLen);
+
+    if( mpFontEntry->mnOrientation )
+        ImplRotatePos( 0, 0, nDistX, nDistY, mpFontEntry->mnOrientation );
+    nBaseX += nDistX;
+    nBaseY += nDistY;
+
+    // strikeout text has to be left aligned
+    sal_uLong nOrigTLM = mnTextLayoutMode;
+    mnTextLayoutMode = TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_COMPLEX_DISABLED;
+    pLayout = ImplLayout( aStrikeoutText, 0, aStrikeoutText.getLength() );
+    mnTextLayoutMode = nOrigTLM;
+
+    if( !pLayout )
+        return;
+
+    // draw the strikeout text
+    const Color aOldColor = GetTextColor();
+    SetTextColor( aColor );
+    ImplInitTextColor();
+
+    pLayout->DrawBase() = Point( nBaseX+mnTextOffX, nBaseY+mnTextOffY );
+
+    Rectangle aPixelRect;
+    aPixelRect.Left() = nBaseX+mnTextOffX;
+    aPixelRect.Right() = aPixelRect.Left()+nWidth;
+    aPixelRect.Bottom() = nBaseY+mpFontEntry->maMetric.mnDescent;
+    aPixelRect.Top() = nBaseY-mpFontEntry->maMetric.mnAscent;
+
+    if (mpFontEntry->mnOrientation)
+    {
+        Polygon aPoly( aPixelRect );
+        aPoly.Rotate( Point(nBaseX+mnTextOffX, nBaseY+mnTextOffY), mpFontEntry->mnOrientation);
+        aPixelRect = aPoly.GetBoundRect();
+    }
+
+    Push( PUSH_CLIPREGION );
+    IntersectClipRegion( PixelToLogic(aPixelRect) );
+    if( mbInitClipRegion )
+        ImplInitClipRegion();
+
+    pLayout->DrawText( *mpGraphics );
+
+    pLayout->Release();
+    Pop();
+
+    SetTextColor( aOldColor );
+    ImplInitTextColor();
+}
+
+void OutputDevice::ImplDrawTextLine( long nX, long nY,
+                                     long nDistX, long nWidth,
+                                     FontStrikeout eStrikeout,
+                                     FontUnderline eUnderline,
+                                     FontUnderline eOverline,
+                                     bool bUnderlineAbove )
+{
+    if ( !nWidth )
+        return;
+
+    Color           aStrikeoutColor = GetTextColor();
+    Color           aUnderlineColor = GetTextLineColor();
+    Color           aOverlineColor  = GetOverlineColor();
+    bool            bStrikeoutDone = false;
+    bool            bUnderlineDone = false;
+    bool            bOverlineDone  = false;
+
+    if ( IsRTLEnabled() )
+    {
+        // --- RTL --- mirror at basex
+        long nXAdd = nWidth - nDistX;
+        if( mpFontEntry->mnOrientation )
+            nXAdd = FRound( nXAdd * cos( mpFontEntry->mnOrientation * F_PI1800 ) );
+        nX += nXAdd - 1;
+    }
+
+    if ( !IsTextLineColor() )
+        aUnderlineColor = GetTextColor();
+
+    if ( !IsOverlineColor() )
+        aOverlineColor = GetTextColor();
+
+    if ( (eUnderline == UNDERLINE_SMALLWAVE) ||
+         (eUnderline == UNDERLINE_WAVE) ||
+         (eUnderline == UNDERLINE_DOUBLEWAVE) ||
+         (eUnderline == UNDERLINE_BOLDWAVE) )
+    {
+        ImplDrawWaveTextLine( nX, nY, nDistX, 0, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
+        bUnderlineDone = true;
+    }
+    if ( (eOverline == UNDERLINE_SMALLWAVE) ||
+         (eOverline == UNDERLINE_WAVE) ||
+         (eOverline == UNDERLINE_DOUBLEWAVE) ||
+         (eOverline == UNDERLINE_BOLDWAVE) )
+    {
+        ImplDrawWaveTextLine( nX, nY, nDistX, 0, nWidth, eOverline, aOverlineColor, true );
+        bOverlineDone = true;
+    }
+
+    if ( (eStrikeout == STRIKEOUT_SLASH) ||
+         (eStrikeout == STRIKEOUT_X) )
+    {
+        ImplDrawStrikeoutChar( nX, nY, nDistX, 0, nWidth, eStrikeout, aStrikeoutColor );
+        bStrikeoutDone = true;
+    }
+
+    if ( !bUnderlineDone )
+        ImplDrawStraightTextLine( nX, nY, nDistX, 0, nWidth, eUnderline, aUnderlineColor, bUnderlineAbove );
+
+    if ( !bOverlineDone )
+        ImplDrawStraightTextLine( nX, nY, nDistX, 0, nWidth, eOverline, aOverlineColor, true );
+
+    if ( !bStrikeoutDone )
+        ImplDrawStrikeoutLine( nX, nY, nDistX, 0, nWidth, eStrikeout, aStrikeoutColor );
+}
+
+void OutputDevice::ImplDrawTextLines( SalLayout& rSalLayout,
+    FontStrikeout eStrikeout, FontUnderline eUnderline, FontUnderline eOverline, bool bWordLine, bool bUnderlineAbove )
+{
+    if( bWordLine )
+    {
+        // draw everything relative to the layout base point
+        const Point aStartPt = rSalLayout.DrawBase();
+
+        // calculate distance of each word from the base point
+        Point aPos;
+        sal_Int32 nDist = 0, nWidth = 0, nAdvance=0;
+        for( int nStart = 0;;)
+        {
+            // iterate through the layouted glyphs
+            sal_GlyphId aGlyphId;
+            if( !rSalLayout.GetNextGlyphs( 1, &aGlyphId, aPos, nStart, &nAdvance ) )
+                break;
+
+            // calculate the boundaries of each word
+            if( !rSalLayout.IsSpacingGlyph( aGlyphId ) )
+            {
+                if( !nWidth )
+                {
+                    // get the distance to the base point (as projected to baseline)
+                    nDist = aPos.X() - aStartPt.X();
+                    if( mpFontEntry->mnOrientation )
+                    {
+                        const long nDY = aPos.Y() - aStartPt.Y();
+                        const double fRad = mpFontEntry->mnOrientation * F_PI1800;
+                        nDist = FRound( nDist*cos(fRad) - nDY*sin(fRad) );
+                    }
+                }
+
+                // update the length of the textline
+                nWidth += nAdvance;
+            }
+            else if( nWidth > 0 )
+            {
+                // draw the textline for each word
+                ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), nDist, nWidth,
+                    eStrikeout, eUnderline, eOverline, bUnderlineAbove );
+                nWidth = 0;
+            }
+        }
+
+        // draw textline for the last word
+        if( nWidth > 0 )
+        {
+            ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), nDist, nWidth,
+                eStrikeout, eUnderline, eOverline, bUnderlineAbove );
+        }
+    }
+    else
+    {
+        Point aStartPt = rSalLayout.GetDrawPosition();
+        int nWidth = rSalLayout.GetTextWidth() / rSalLayout.GetUnitsPerPixel();
+        ImplDrawTextLine( aStartPt.X(), aStartPt.Y(), 0, nWidth,
+            eStrikeout, eUnderline, eOverline, bUnderlineAbove );
+    }
+}
+
+void OutputDevice::ImplDrawMnemonicLine( long nX, long nY, long nWidth )
+{
+    long nBaseX = nX;
+    if( /*HasMirroredGraphics() &&*/ IsRTLEnabled() )
+    {
+        // --- RTL ---
+        // add some strange offset
+        nX += 2;
+        // revert the hack that will be done later in ImplDrawTextLine
+        nX = nBaseX - nWidth - (nX - nBaseX - 1);
+    }
+
+    ImplDrawTextLine( nX, nY, 0, nWidth, STRIKEOUT_NONE, UNDERLINE_SINGLE, UNDERLINE_NONE, false );
+}
+
+void OutputDevice::SetTextLineColor()
+{
+
+    if ( mpMetaFile )
+        mpMetaFile->AddAction( new MetaTextLineColorAction( Color(), false ) );
+
+    maTextLineColor = Color( COL_TRANSPARENT );
+
+    if( mpAlphaVDev )
+        mpAlphaVDev->SetTextLineColor();
+}
+
+void OutputDevice::SetTextLineColor( const Color& rColor )
+{
+
+    Color aColor( rColor );
+
+    if ( mnDrawMode & ( DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT |
+                        DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT |
+                        DRAWMODE_SETTINGSTEXT ) )
+    {
+        if ( mnDrawMode & DRAWMODE_BLACKTEXT )
+            aColor = Color( COL_BLACK );
+        else if ( mnDrawMode & DRAWMODE_WHITETEXT )
+            aColor = Color( COL_WHITE );
+        else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
+        {
+            const sal_uInt8 cLum = aColor.GetLuminance();
+            aColor = Color( cLum, cLum, cLum );
+        }
+        else if ( mnDrawMode & DRAWMODE_SETTINGSTEXT )
+            aColor = GetSettings().GetStyleSettings().GetFontColor();
+
+        if( (mnDrawMode & DRAWMODE_GHOSTEDTEXT)
+        &&  (aColor.GetColor() != COL_TRANSPARENT) )
+        {
+            aColor = Color( (aColor.GetRed() >> 1) | 0x80,
+                            (aColor.GetGreen() >> 1) | 0x80,
+                            (aColor.GetBlue() >> 1) | 0x80 );
+        }
+    }
+
+    if ( mpMetaFile )
+        mpMetaFile->AddAction( new MetaTextLineColorAction( aColor, true ) );
+
+    maTextLineColor = aColor;
+
+    if( mpAlphaVDev )
+        mpAlphaVDev->SetTextLineColor( COL_BLACK );
+}
+
+void OutputDevice::SetOverlineColor()
+{
+
+    if ( mpMetaFile )
+        mpMetaFile->AddAction( new MetaOverlineColorAction( Color(), false ) );
+
+    maOverlineColor = Color( COL_TRANSPARENT );
+
+    if( mpAlphaVDev )
+        mpAlphaVDev->SetOverlineColor();
+}
+
+void OutputDevice::SetOverlineColor( const Color& rColor )
+{
+
+    Color aColor( rColor );
+
+    if ( mnDrawMode & ( DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT |
+                        DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT |
+                        DRAWMODE_SETTINGSTEXT ) )
+    {
+        if ( mnDrawMode & DRAWMODE_BLACKTEXT )
+            aColor = Color( COL_BLACK );
+        else if ( mnDrawMode & DRAWMODE_WHITETEXT )
+            aColor = Color( COL_WHITE );
+        else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
+        {
+            const sal_uInt8 cLum = aColor.GetLuminance();
+            aColor = Color( cLum, cLum, cLum );
+        }
+        else if ( mnDrawMode & DRAWMODE_SETTINGSTEXT )
+            aColor = GetSettings().GetStyleSettings().GetFontColor();
+
+        if( (mnDrawMode & DRAWMODE_GHOSTEDTEXT)
+        &&  (aColor.GetColor() != COL_TRANSPARENT) )
+        {
+            aColor = Color( (aColor.GetRed() >> 1) | 0x80,
+                            (aColor.GetGreen() >> 1) | 0x80,
+                            (aColor.GetBlue() >> 1) | 0x80 );
+        }
+    }
+
+    if ( mpMetaFile )
+        mpMetaFile->AddAction( new MetaOverlineColorAction( aColor, true ) );
+
+    maOverlineColor = aColor;
+
+    if( mpAlphaVDev )
+        mpAlphaVDev->SetOverlineColor( COL_BLACK );
+}
+
+void OutputDevice::DrawTextLine( const Point& rPos, long nWidth,
+                                 FontStrikeout eStrikeout,
+                                 FontUnderline eUnderline,
+                                 FontUnderline eOverline,
+                                 bool bUnderlineAbove )
+{
+
+    if ( mpMetaFile )
+        mpMetaFile->AddAction( new MetaTextLineAction( rPos, nWidth, eStrikeout, eUnderline, eOverline ) );
+
+    if ( ((eUnderline == UNDERLINE_NONE) || (eUnderline == UNDERLINE_DONTKNOW)) &&
+         ((eOverline  == UNDERLINE_NONE) || (eOverline  == UNDERLINE_DONTKNOW)) &&
+         ((eStrikeout == STRIKEOUT_NONE) || (eStrikeout == STRIKEOUT_DONTKNOW)) )
+        return;
+
+    if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
+        return;
+
+    // we need a graphics
+    if( !mpGraphics && !ImplGetGraphics() )
+        return;
+    if( mbInitClipRegion )
+        ImplInitClipRegion();
+    if( mbOutputClipped )
+        return;
+
+    // initialize font if needed to get text offsets
+    // TODO: only needed for mnTextOff!=(0,0)
+    if( mbNewFont )
+        if( !ImplNewFont() )
+            return;
+    if( mbInitFont )
+        InitFont();
+
+    Point aPos = ImplLogicToDevicePixel( rPos );
+    nWidth = ImplLogicWidthToDevicePixel( nWidth );
+    aPos += Point( mnTextOffX, mnTextOffY );
+    ImplDrawTextLine( aPos.X(), aPos.X(), 0, nWidth, eStrikeout, eUnderline, eOverline, bUnderlineAbove );
+
+    if( mpAlphaVDev )
+        mpAlphaVDev->DrawTextLine( rPos, nWidth, eStrikeout, eUnderline, eOverline, bUnderlineAbove );
+}
+
+void OutputDevice::DrawWaveLine( const Point& rStartPos, const Point& rEndPos )
+{
+
+    if ( !IsDeviceOutputNecessary() || ImplIsRecordLayout() )
+        return;
+
+    // we need a graphics
+    if( !mpGraphics )
+        if( !ImplGetGraphics() )
+            return;
+
+    if ( mbInitClipRegion )
+        ImplInitClipRegion();
+    if ( mbOutputClipped )
+        return;
+
+    if( mbNewFont )
+        if( !ImplNewFont() )
+            return;
+
+    Point   aStartPt = ImplLogicToDevicePixel( rStartPos );
+    Point   aEndPt = ImplLogicToDevicePixel( rEndPos );
+    long    nStartX = aStartPt.X();
+    long    nStartY = aStartPt.Y();
+    long    nEndX = aEndPt.X();
+    long    nEndY = aEndPt.Y();
+    short   nOrientation = 0;
+
+    // when rotated
+    if ( (nStartY != nEndY) || (nStartX > nEndX) )
+    {
+        long nDX = nEndX - nStartX;
+        double nO = atan2( -nEndY + nStartY, ((nDX == 0L) ? 0.000000001 : nDX) );
+        nO /= F_PI1800;
+        nOrientation = (short)nO;
+        ImplRotatePos( nStartX, nStartY, nEndX, nEndY, -nOrientation );
+    }
+
+    long nWaveHeight;
+
+    nWaveHeight = 3;
+    nStartY++;
+    nEndY++;
+
+    if (mnDPIScaleFactor > 1)
+    {
+        nWaveHeight *= mnDPIScaleFactor;
+
+        nStartY += mnDPIScaleFactor - 1; // Shift down additional pixel(s) to create more visual separation.
+
+        // odd heights look better than even
+        if (mnDPIScaleFactor % 2 == 0)
+        {
+            nWaveHeight--;
+        }
+    }
+
+    // #109280# make sure the waveline does not exceed the descent to avoid paint problems
+    ImplFontEntry* pFontEntry = mpFontEntry;
+    if( nWaveHeight > pFontEntry->maMetric.mnWUnderlineSize )
+        nWaveHeight = pFontEntry->maMetric.mnWUnderlineSize;
+
+    ImplDrawWaveLine(nStartX, nStartY, 0, 0,
+            nEndX-nStartX, nWaveHeight,
+            mnDPIScaleFactor, nOrientation, GetLineColor());
+
+    if( mpAlphaVDev )
+        mpAlphaVDev->DrawWaveLine( rStartPos, rEndPos );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */


More information about the Libreoffice-commits mailing list