summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Sherlock <chris.sherlock79@gmail.com>2014-04-20 13:10:09 +1000
committerChris Sherlock <chris.sherlock79@gmail.com>2014-04-20 13:10:09 +1000
commitffce13a5e48e193463be65b569af2e4f22d17926 (patch)
treedd65b29f0d61b6f37d54c9ef62c42beccd61eb4d
parent588bb542bebdee5a67bd4695253c70646fb8a303 (diff)
Move VCL text line functions from text.cxx to textline.cxx
Change-Id: I3adea9cd08c86f676e6af525e5a7caf430c96d8d
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/source/outdev/text.cxx967
-rw-r--r--vcl/source/outdev/textline.cxx1068
3 files changed, 1069 insertions, 967 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 72285c5811c3..989bf8e1069e 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 7063c32075b1..485033999ef3 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 000000000000..7257eb087de0
--- /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: */