Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
core
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
LibreOffice
core
Commits
ffce13a5
Kaydet (Commit)
ffce13a5
authored
Nis 20, 2014
tarafından
Chris Sherlock
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Move VCL text line functions from text.cxx to textline.cxx
Change-Id: I3adea9cd08c86f676e6af525e5a7caf430c96d8d
üst
588bb542
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1069 additions
and
967 deletions
+1069
-967
Library_vcl.mk
vcl/Library_vcl.mk
+1
-0
text.cxx
vcl/source/outdev/text.cxx
+0
-967
textline.cxx
vcl/source/outdev/textline.cxx
+1068
-0
No files found.
vcl/Library_vcl.mk
Dosyayı görüntüle @
ffce13a5
...
@@ -243,6 +243,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
...
@@ -243,6 +243,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/outdev/bitmap \
vcl/source/outdev/bitmap \
vcl/source/outdev/font \
vcl/source/outdev/font \
vcl/source/outdev/text \
vcl/source/outdev/text \
vcl/source/outdev/textline \
vcl/source/outdev/pixel \
vcl/source/outdev/pixel \
vcl/source/outdev/rect \
vcl/source/outdev/rect \
vcl/source/outdev/line \
vcl/source/outdev/line \
...
...
vcl/source/outdev/text.cxx
Dosyayı görüntüle @
ffce13a5
...
@@ -135,19 +135,6 @@ void ImplMultiTextLineInfo::Clear()
...
@@ -135,19 +135,6 @@ void ImplMultiTextLineInfo::Clear()
mnLines
=
0
;
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
()
void
OutputDevice
::
ImplInitTextColor
()
{
{
DBG_TESTSOLARMUTEX
();
DBG_TESTSOLARMUTEX
();
...
@@ -273,745 +260,6 @@ Rectangle OutputDevice::ImplGetTextBoundRect( const SalLayout& rSalLayout )
...
@@ -273,745 +260,6 @@ Rectangle OutputDevice::ImplGetTextBoundRect( const SalLayout& rSalLayout )
return
Rectangle
(
Point
(
nX
,
nY
),
Size
(
nWidth
,
nHeight
)
);
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
)
bool
OutputDevice
::
ImplDrawRotateText
(
SalLayout
&
rSalLayout
)
{
{
int
nX
=
rSalLayout
.
DrawBase
().
X
();
int
nX
=
rSalLayout
.
DrawBase
().
X
();
...
@@ -1641,108 +889,6 @@ Color OutputDevice::GetTextFillColor() const
...
@@ -1641,108 +889,6 @@ Color OutputDevice::GetTextFillColor() const
return
maFont
.
GetFillColor
();
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
)
void
OutputDevice
::
SetTextAlign
(
TextAlign
eAlign
)
{
{
...
@@ -1759,119 +905,6 @@ void OutputDevice::SetTextAlign( TextAlign eAlign )
...
@@ -1759,119 +905,6 @@ void OutputDevice::SetTextAlign( TextAlign eAlign )
mpAlphaVDev
->
SetTextAlign
(
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
,
void
OutputDevice
::
DrawText
(
const
Point
&
rStartPt
,
const
OUString
&
rStr
,
sal_Int32
nIndex
,
sal_Int32
nLen
,
sal_Int32
nIndex
,
sal_Int32
nLen
,
MetricVector
*
pVector
,
OUString
*
pDisplayText
MetricVector
*
pVector
,
OUString
*
pDisplayText
...
...
vcl/source/outdev/textline.cxx
0 → 100644
Dosyayı görüntüle @
ffce13a5
/* -*- 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: */
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment