1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sfx2/dialoghelper.hxx>
21 #include <sfx2/viewsh.hxx>
22 #include <sfx2/printer.hxx>
23 #include <vcl/metric.hxx>
24 #include <vcl/svapp.hxx>
25 #include <vcl/settings.hxx>
27 #include <com/sun/star/i18n/ScriptType.hpp>
31 #include <svtools/colorcfg.hxx>
32 #include <svtools/sampletext.hxx>
34 #include <svx/fntctrl.hxx>
35 #include <svx/svxids.hrc>
38 #include <svl/itemset.hxx>
39 #include <svl/itempool.hxx>
40 #include <svl/stritem.hxx>
41 #include <svl/cjkoptions.hxx>
42 #include <svl/ctloptions.hxx>
44 #include <editeng/editeng.hxx>
45 #include <editeng/colritem.hxx>
46 #include <editeng/fontitem.hxx>
47 #include <editeng/editids.hrc>
48 #include <editeng/postitem.hxx>
49 #include <editeng/udlnitem.hxx>
50 #include <editeng/crossedoutitem.hxx>
51 #include <editeng/contouritem.hxx>
52 #include <editeng/wghtitem.hxx>
53 #include <editeng/fhgtitem.hxx>
54 #include <editeng/shdditem.hxx>
55 #include <editeng/escapementitem.hxx>
56 #include <editeng/wrlmitem.hxx>
57 #include <editeng/cmapitem.hxx>
58 #include <editeng/kernitem.hxx>
59 #include <editeng/brushitem.hxx>
60 #include <editeng/emphasismarkitem.hxx>
61 #include <editeng/charreliefitem.hxx>
62 #include <editeng/charscaleitem.hxx>
63 #include <editeng/langitem.hxx>
65 //TODO: remove this and calculate off the actual size of text, not
66 //an arbitrary number of characters
70 // small helper functions to set fonts
74 void scaleFontWidth(vcl::Font
& rFont
, vcl::RenderContext
const & rRenderContext
,tools::Long
& n100PercentFont
)
76 rFont
.SetAverageFontWidth(0);
77 n100PercentFont
= rRenderContext
.GetFontMetric(rFont
).GetAverageFontWidth();
80 void initFont(vcl::Font
& rFont
)
82 rFont
.SetTransparent(true);
83 rFont
.SetAlignment(ALIGN_BASELINE
);
86 void setFontSize(vcl::Font
& rFont
)
88 Size
aSize(rFont
.GetFontSize());
89 aSize
.setHeight( (aSize
.Height() * 3) / 5 );
90 aSize
.setWidth( (aSize
.Width() * 3) / 5 );
91 rFont
.SetFontSize(aSize
);
94 void calcFontHeightAnyAscent(vcl::RenderContext
& rRenderContext
, const vcl::Font
& rFont
, tools::Long
& nHeight
, tools::Long
& nAscent
)
98 rRenderContext
.SetFont(rFont
);
99 FontMetric
aMetric(rRenderContext
.GetFontMetric());
100 nHeight
= aMetric
.GetLineHeight();
101 nAscent
= aMetric
.GetAscent();
105 void setFont(const SvxFont
& rNewFont
, SvxFont
& rImplFont
)
107 rImplFont
= rNewFont
;
108 rImplFont
.SetTransparent(true);
109 rImplFont
.SetAlignment(ALIGN_BASELINE
);
113 * removes line feeds and carriage returns from string
114 * returns if param is empty
116 OUString
removeCRLF(const OUString
& rText
)
118 return rText
.replace(0xa, ' ').replace(0xd, ' ').trim();
123 tools::Long textWidth
;
124 SvtScriptType scriptType
;
126 ScriptInfo(SvtScriptType scrptType
, sal_Int32 position
)
128 , scriptType(scrptType
)
129 , changePos(position
)
134 } // end anonymous namespace
136 class FontPrevWin_Impl
138 friend class SvxFontPrevWindow
;
141 VclPtr
<Printer
> mpPrinter
;
144 std::vector
<ScriptInfo
> maScriptChanges
;
148 OUString maScriptText
;
149 std::optional
<Color
> mxColor
;
150 std::optional
<Color
> mxBackColor
;
151 std::optional
<Color
> mxTextLineColor
;
152 std::optional
<Color
> mxOverlineColor
;
153 tools::Long mnAscent
;
154 sal_Unicode mcStartBracket
;
155 sal_Unicode mcEndBracket
;
157 tools::Long mn100PercentFontWidth
; // initial -1 -> not set yet
158 tools::Long mn100PercentFontWidthCJK
;
159 tools::Long mn100PercentFontWidthCTL
;
160 sal_uInt16 mnFontWidthScale
;
162 bool mbSelection
: 1;
163 bool mbGetSelection
: 1;
165 bool mbUseFontNameAsText
: 1;
166 bool mbTextInited
: 1;
179 mnFontWidthScale(100),
181 mbGetSelection(false),
183 mbUseFontNameAsText(false),
186 m_bCJKEnabled
= SvtCJKOptions::IsAnyEnabled();
187 m_bCTLEnabled
= SvtCTLOptions::IsCTLFontEnabled();
188 mxBackColor
= svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
189 Invalidate100PercentFontWidth();
195 mpPrinter
.disposeAndClear();
199 Size
CalcTextSize(vcl::RenderContext
& rRenderContext
, OutputDevice
const * pPrinter
, const SvxFont
& rFont
);
200 void DrawPrev(vcl::RenderContext
& rRenderContext
, Printer
* pPrinter
, Point
& rPt
, const SvxFont
& rFont
);
202 bool SetFontWidthScale(sal_uInt16 nScaleInPercent
);
203 inline void Invalidate100PercentFontWidth();
204 inline bool Is100PercentFontWidthValid() const;
205 void ScaleFontWidth(vcl::RenderContext
const & rRenderContext
);
206 // scales rNonCJKFont and aCJKFont depending on nFontWidthScale and
207 // sets the 100%-Font-Widths
210 inline void FontPrevWin_Impl::Invalidate100PercentFontWidth()
212 mn100PercentFontWidth
= mn100PercentFontWidthCJK
= mn100PercentFontWidthCTL
= -1;
215 inline bool FontPrevWin_Impl::Is100PercentFontWidthValid() const
217 DBG_ASSERT( ( mn100PercentFontWidth
== -1 && mn100PercentFontWidthCJK
== -1 ) ||
218 ( mn100PercentFontWidth
!= -1 && mn100PercentFontWidthCJK
!= -1 ) ||
219 ( mn100PercentFontWidth
== -1 && mn100PercentFontWidthCTL
== -1 ) ||
220 ( mn100PercentFontWidth
!= -1 && mn100PercentFontWidthCTL
!= -1 ),
221 "*FontPrevWin_Impl::Is100PercentFontWidthValid(): 100PercentFontWidth's not synchronous" );
222 return mn100PercentFontWidth
!= -1;
226 * evaluates the scripttypes of the actual string.
227 * Afterwards the positions of script change are notified in aScriptChg,
228 * the scripttypes in aScriptType.
229 * The aTextWidth array will be filled with zero.
231 void FontPrevWin_Impl::CheckScript()
233 assert(!maText
.isEmpty()); // must have a preview text here!
234 if (maText
== maScriptText
)
236 return; // already initialized
239 maScriptText
= maText
;
240 maScriptChanges
.clear();
242 auto aEditEngine
= EditEngine(nullptr);
243 aEditEngine
.SetText(maScriptText
);
245 auto aScript
= aEditEngine
.GetScriptType({ 0, 0, 0, 0 });
246 for (sal_Int32 i
= 1; i
<= maScriptText
.getLength(); i
++)
248 auto aNextScript
= aEditEngine
.GetScriptType({ 0, i
, 0, i
});
249 if (aNextScript
!= aScript
)
250 maScriptChanges
.emplace_back(aScript
, i
- 1);
251 if (i
== maScriptText
.getLength())
252 maScriptChanges
.emplace_back(aScript
, i
);
253 aScript
= aNextScript
;
258 * Size FontPrevWin_Impl::CalcTextSize(..)
259 * fills the aTextWidth array with the text width of every part
260 * of the actual string without a script change inside.
261 * For Latin parts the given rFont will be used,
262 * for Asian parts the aCJKFont.
263 * The returned size contains the whole string.
264 * The member nAscent is calculated to the maximal ascent of all used fonts.
267 Size
FontPrevWin_Impl::CalcTextSize(vcl::RenderContext
& rRenderContext
, OutputDevice
const * _pPrinter
, const SvxFont
& rInFont
)
269 SvtScriptType aScript
;
271 sal_Int32 nStart
= 0;
273 size_t nCnt
= maScriptChanges
.size();
277 nEnd
= maScriptChanges
[nIdx
].changePos
;
278 aScript
= maScriptChanges
[nIdx
].scriptType
;
282 nEnd
= maText
.getLength();
283 aScript
= SvtScriptType::LATIN
;
285 tools::Long nTxtWidth
= 0;
286 tools::Long nCJKHeight
= 0;
287 tools::Long nCTLHeight
= 0;
288 tools::Long nHeight
= 0;
290 tools::Long nCJKAscent
= 0;
291 tools::Long nCTLAscent
= 0;
295 const SvxFont
& rFont
= (aScript
== SvtScriptType::ASIAN
) ?
297 ((aScript
== SvtScriptType::COMPLEX
) ?
300 tools::Long nWidth
= rFont
.GetTextSize(*_pPrinter
, maText
, nStart
, nEnd
- nStart
).Width();
301 if (nIdx
>= maScriptChanges
.size())
304 maScriptChanges
[nIdx
++].textWidth
= nWidth
;
309 case SvtScriptType::ASIAN
:
310 calcFontHeightAnyAscent(rRenderContext
, maCJKFont
, nCJKHeight
, nCJKAscent
);
312 case SvtScriptType::COMPLEX
:
313 calcFontHeightAnyAscent(rRenderContext
, maCTLFont
, nCTLHeight
, nCTLAscent
);
316 calcFontHeightAnyAscent(rRenderContext
, rFont
, nHeight
, mnAscent
);
319 if (nEnd
< maText
.getLength() && nIdx
< nCnt
)
322 nEnd
= maScriptChanges
[nIdx
].changePos
;
323 aScript
= maScriptChanges
[nIdx
].scriptType
;
331 nCJKHeight
-= nCJKAscent
;
332 nCTLHeight
-= nCTLAscent
;
334 if (nHeight
< nCJKHeight
)
335 nHeight
= nCJKHeight
;
337 if (mnAscent
< nCJKAscent
)
338 mnAscent
= nCJKAscent
;
340 if (nHeight
< nCTLHeight
)
341 nHeight
= nCTLHeight
;
343 if (mnAscent
< nCTLAscent
)
344 mnAscent
= nCTLAscent
;
348 Size
aTxtSize(nTxtWidth
, nHeight
);
353 * void FontPrevWin_Impl::DrawPrev(..)
354 * calls SvxFont::DrawPrev(..) for every part of the string without a script
355 * change inside, for Asian parts the aCJKFont will be used, otherwise the
359 void FontPrevWin_Impl::DrawPrev(vcl::RenderContext
& rRenderContext
, Printer
* _pPrinter
, Point
&rPt
, const SvxFont
& rInFont
)
361 vcl::Font aOldFont
= _pPrinter
->GetFont();
362 SvtScriptType aScript
;
364 sal_Int32 nStart
= 0;
366 size_t nCnt
= maScriptChanges
.size();
370 nEnd
= maScriptChanges
[nIdx
].changePos
;
371 aScript
= maScriptChanges
[nIdx
].scriptType
;
375 nEnd
= maText
.getLength();
376 aScript
= SvtScriptType::LATIN
;
380 const SvxFont
& rFont
= (aScript
== SvtScriptType::ASIAN
)
382 : ((aScript
== SvtScriptType::COMPLEX
)
385 _pPrinter
->SetFont(rFont
);
387 rFont
.DrawPrev(&rRenderContext
, _pPrinter
, rPt
, maText
, nStart
, nEnd
- nStart
);
389 rPt
.AdjustX(maScriptChanges
[nIdx
++].textWidth
);
390 if (nEnd
< maText
.getLength() && nIdx
< nCnt
)
393 nEnd
= maScriptChanges
[nIdx
].changePos
;
394 aScript
= maScriptChanges
[nIdx
].scriptType
;
400 _pPrinter
->SetFont(aOldFont
);
404 bool FontPrevWin_Impl::SetFontWidthScale(sal_uInt16 nScale
)
406 if (mnFontWidthScale
!= nScale
)
408 mnFontWidthScale
= nScale
;
415 void FontPrevWin_Impl::ScaleFontWidth(vcl::RenderContext
const & rOutDev
)
417 if (!Is100PercentFontWidthValid())
419 scaleFontWidth(maFont
, rOutDev
, mn100PercentFontWidth
);
420 scaleFontWidth(maCJKFont
, rOutDev
, mn100PercentFontWidthCJK
);
421 scaleFontWidth(maCTLFont
, rOutDev
, mn100PercentFontWidthCTL
);
424 maFont
.SetAverageFontWidth(mn100PercentFontWidth
* mnFontWidthScale
/ 100);
425 maCJKFont
.SetAverageFontWidth(mn100PercentFontWidthCJK
* mnFontWidthScale
/ 100);
426 maCTLFont
.SetAverageFontWidth(mn100PercentFontWidthCTL
* mnFontWidthScale
/ 100);
429 static bool GetWhich (const SfxItemSet
& rSet
, sal_uInt16 nSlot
, sal_uInt16
& rWhich
)
431 rWhich
= rSet
.GetPool()->GetWhichIDFromSlotID(nSlot
);
432 return rSet
.GetItemState(rWhich
) >= SfxItemState::DEFAULT
;
435 static void SetPrevFont(const SfxItemSet
& rSet
, sal_uInt16 nSlot
, SvxFont
& rFont
)
438 if (GetWhich(rSet
, nSlot
, nWhich
))
440 const SvxFontItem
& rFontItem
= static_cast<const SvxFontItem
&>(rSet
.Get(nWhich
));
441 rFont
.SetFamily(rFontItem
.GetFamily());
442 rFont
.SetFamilyName(rFontItem
.GetFamilyName());
443 rFont
.SetPitch(rFontItem
.GetPitch());
444 rFont
.SetCharSet(rFontItem
.GetCharSet());
445 rFont
.SetStyleName(rFontItem
.GetStyleName());
449 static void SetPrevFontStyle( const SfxItemSet
& rSet
, sal_uInt16 nPosture
, sal_uInt16 nWeight
, SvxFont
& rFont
)
452 if( GetWhich( rSet
, nPosture
, nWhich
) )
454 const SvxPostureItem
& rItem
= static_cast<const SvxPostureItem
&>( rSet
.Get( nWhich
) );
455 rFont
.SetItalic( rItem
.GetValue() != ITALIC_NONE
? ITALIC_NORMAL
: ITALIC_NONE
);
458 if( GetWhich( rSet
, nWeight
, nWhich
) )
460 const SvxWeightItem
& rItem
= static_cast<const SvxWeightItem
&>( rSet
.Get( nWhich
) );
461 rFont
.SetWeight( rItem
.GetValue() != WEIGHT_NORMAL
? WEIGHT_BOLD
: WEIGHT_NORMAL
);
465 static void SetPrevFontEscapement(SvxFont
& rFont
, sal_uInt8 nProp
, sal_uInt8 nEscProp
, short nEsc
)
467 rFont
.SetPropr(nProp
);
468 rFont
.SetProprRel(nEscProp
);
469 rFont
.SetEscapement(nEsc
);
472 void SvxFontPrevWindow::ApplySettings(vcl::RenderContext
& rRenderContext
)
474 Color aBgColor
= svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
475 Color aFgColor
= svtools::ColorConfig().GetColorValue(svtools::FONTCOLOR
, false).nColor
;
476 if (aFgColor
== COL_AUTO
)
477 aFgColor
= aBgColor
.IsDark() ? COL_WHITE
: COL_BLACK
;
478 rRenderContext
.SetBackground(aBgColor
);
479 rRenderContext
.SetTextColor(aFgColor
);
482 void SvxFontPrevWindow::SetDrawingArea(weld::DrawingArea
* pDrawingArea
)
484 CustomWidgetController::SetDrawingArea(pDrawingArea
);
485 Size
aPrefSize(getPreviewStripSize(pDrawingArea
->get_ref_device()));
486 pDrawingArea
->set_size_request(aPrefSize
.Width(), aPrefSize
.Height());
488 pImpl
.reset(new FontPrevWin_Impl
);
489 SfxViewShell
* pSh
= SfxViewShell::Current();
492 pImpl
->mpPrinter
= pSh
->GetPrinter();
494 if (!pImpl
->mpPrinter
)
496 pImpl
->mpPrinter
= VclPtr
<Printer
>::Create();
497 pImpl
->mbDelPrinter
= true;
499 initFont(pImpl
->maFont
);
500 initFont(pImpl
->maCJKFont
);
501 initFont(pImpl
->maCTLFont
);
506 SvxFontPrevWindow::SvxFontPrevWindow()
510 SvxFontPrevWindow::~SvxFontPrevWindow()
514 SvxFont
& SvxFontPrevWindow::GetCTLFont()
516 return pImpl
->maCTLFont
;
519 SvxFont
& SvxFontPrevWindow::GetCJKFont()
521 return pImpl
->maCJKFont
;
524 SvxFont
& SvxFontPrevWindow::GetFont()
526 pImpl
->Invalidate100PercentFontWidth(); // because the user might change the size
527 return pImpl
->maFont
;
530 const SvxFont
& SvxFontPrevWindow::GetFont() const
532 return pImpl
->maFont
;
535 void SvxFontPrevWindow::SetPreviewText( const OUString
& rString
)
537 pImpl
->maText
= rString
;
538 pImpl
->mbTextInited
= true;
541 void SvxFontPrevWindow::SetFontNameAsPreviewText()
543 pImpl
->mbUseFontNameAsText
= true;
546 void SvxFontPrevWindow::SetFont( const SvxFont
& rNormalOutFont
, const SvxFont
& rCJKOutFont
, const SvxFont
& rCTLFont
)
548 setFont(rNormalOutFont
, pImpl
->maFont
);
549 setFont(rCJKOutFont
, pImpl
->maCJKFont
);
550 setFont(rCTLFont
, pImpl
->maCTLFont
);
552 pImpl
->Invalidate100PercentFontWidth();
556 void SvxFontPrevWindow::SetColor(const Color
&rColor
)
558 pImpl
->mxColor
= rColor
;
562 void SvxFontPrevWindow::ResetColor()
564 pImpl
->mxColor
.reset();
568 void SvxFontPrevWindow::SetTextLineColor(const Color
&rColor
)
570 pImpl
->mxTextLineColor
= rColor
;
574 void SvxFontPrevWindow::SetOverlineColor(const Color
&rColor
)
576 pImpl
->mxOverlineColor
= rColor
;
580 void SvxFontPrevWindow::Paint(vcl::RenderContext
& rRenderContext
, const tools::Rectangle
&)
582 rRenderContext
.Push(vcl::PushFlags::ALL
);
583 rRenderContext
.SetMapMode(MapMode(MapUnit::MapTwip
));
585 ApplySettings(rRenderContext
);
586 rRenderContext
.Erase();
588 Printer
* pPrinter
= pImpl
->mpPrinter
;
589 const SvxFont
& rFont
= pImpl
->maFont
;
590 const SvxFont
& rCJKFont
= pImpl
->maCJKFont
;
591 const SvxFont
& rCTLFont
= pImpl
->maCTLFont
;
595 const StyleSettings
& rStyleSettings
= Application::GetSettings().GetStyleSettings();
596 const Size
aLogSize(rRenderContext
.GetOutputSize());
598 tools::Rectangle
aRect(Point(0, 0), aLogSize
);
599 rRenderContext
.SetLineColor();
600 rRenderContext
.SetFillColor(rStyleSettings
.GetWindowColor());
601 rRenderContext
.DrawRect(aRect
);
605 if (!pImpl
->mbSelection
&& !pImpl
->mbTextInited
)
607 using namespace css::i18n::ScriptType
;
609 SfxViewShell
* pSh
= SfxViewShell::Current();
611 if (pSh
&& !pImpl
->mbGetSelection
&& !pImpl
->mbUseFontNameAsText
)
613 pImpl
->maText
= removeCRLF(pSh
->GetSelectionText(/*bCompleteWords*/false, /*bOnlyASample*/true));
614 pImpl
->mbGetSelection
= true;
615 pImpl
->mbSelection
= !(pImpl
->maText
.isEmpty());
618 if (!pImpl
->mbSelection
|| pImpl
->mbUseFontNameAsText
)
620 //If we're showing multiple sample texts, then they're all
621 //sample texts. If only showing Latin, continue to use
622 //the fontname as the preview
623 if ((pImpl
->m_bCJKEnabled
) || (pImpl
->m_bCTLEnabled
))
624 pImpl
->maText
= makeRepresentativeTextForFont(LATIN
, rFont
);
626 pImpl
->maText
= rFont
.GetFamilyName();
628 if (pImpl
->m_bCJKEnabled
)
630 if (!pImpl
->maText
.isEmpty())
631 pImpl
->maText
+= " ";
632 pImpl
->maText
+= makeRepresentativeTextForFont(ASIAN
, rCJKFont
);
635 if (pImpl
->m_bCTLEnabled
)
637 if (!pImpl
->maText
.isEmpty())
638 pImpl
->maText
+= " ";
639 pImpl
->maText
+= makeRepresentativeTextForFont(COMPLEX
, rCTLFont
);
643 if (pImpl
->maText
.isEmpty())
644 { // fdo#58427: still no text? let's try that one...
645 pImpl
->maText
= makeRepresentativeTextForFont(LATIN
, rFont
);
648 pImpl
->maText
= removeCRLF(pImpl
->maText
);
650 if (pImpl
->maText
.getLength() > (TEXT_WIDTH
- 1))
652 const sal_Int32 nSpaceIdx
= pImpl
->maText
.indexOf(" ", TEXT_WIDTH
);
654 pImpl
->maText
= pImpl
->maText
.copy(0, nSpaceIdx
);
656 pImpl
->maText
= pImpl
->maText
.copy(0, (TEXT_WIDTH
- 1));
660 // calculate text width scaling
661 pImpl
->ScaleFontWidth(rRenderContext
);
663 pImpl
->CheckScript();
664 Size aTxtSize
= pImpl
->CalcTextSize(rRenderContext
, pPrinter
, rFont
);
666 const Size
aLogSize(rRenderContext
.GetOutputSize());
668 tools::Long nX
= aLogSize
.Width() / 2 - aTxtSize
.Width() / 2;
669 tools::Long nY
= aLogSize
.Height() / 2 - aTxtSize
.Height() / 2;
671 if (nY
+ pImpl
->mnAscent
> aLogSize
.Height())
672 nY
= aLogSize
.Height() - pImpl
->mnAscent
;
674 if (pImpl
->mxBackColor
)
676 tools::Rectangle
aRect(Point(0, 0), aLogSize
);
677 Color aLineCol
= rRenderContext
.GetLineColor();
678 Color aFillCol
= rRenderContext
.GetFillColor();
679 rRenderContext
.SetLineColor();
680 rRenderContext
.SetFillColor(*pImpl
->mxBackColor
);
681 rRenderContext
.DrawRect(aRect
);
682 rRenderContext
.SetLineColor(aLineCol
);
683 rRenderContext
.SetFillColor(aFillCol
);
687 tools::Rectangle
aRect(Point(nX
, nY
), aTxtSize
);
688 Color aLineCol
= rRenderContext
.GetLineColor();
689 Color aFillCol
= rRenderContext
.GetFillColor();
690 rRenderContext
.SetLineColor();
691 rRenderContext
.SetFillColor(*pImpl
->mxColor
);
692 rRenderContext
.DrawRect(aRect
);
693 rRenderContext
.SetLineColor(aLineCol
);
694 rRenderContext
.SetFillColor(aFillCol
);
697 if (pImpl
->mxTextLineColor
)
699 rRenderContext
.SetTextLineColor(*pImpl
->mxTextLineColor
);
702 if (pImpl
->mxOverlineColor
)
704 rRenderContext
.SetOverlineColor(*pImpl
->mxOverlineColor
);
707 tools::Long nStdAscent
= pImpl
->mnAscent
;
712 SvxFont
aSmallFont(rFont
);
713 Size aOldSize
= pImpl
->maCJKFont
.GetFontSize();
714 setFontSize(aSmallFont
);
715 setFontSize(pImpl
->maCJKFont
);
717 tools::Long nStartBracketWidth
= 0;
718 tools::Long nEndBracketWidth
= 0;
719 tools::Long nTextWidth
= 0;
720 if (pImpl
->mcStartBracket
)
722 OUString
sBracket(pImpl
->mcStartBracket
);
723 nStartBracketWidth
= rFont
.GetTextSize(*pPrinter
, sBracket
).Width();
725 if (pImpl
->mcEndBracket
)
727 OUString
sBracket(pImpl
->mcEndBracket
);
728 nEndBracketWidth
= rFont
.GetTextSize(*pPrinter
, sBracket
).Width();
730 nTextWidth
= pImpl
->CalcTextSize(rRenderContext
, pPrinter
, aSmallFont
).Width();
731 tools::Long nResultWidth
= nStartBracketWidth
;
732 nResultWidth
+= nEndBracketWidth
;
733 nResultWidth
+= nTextWidth
;
735 tools::Long _nX
= (aLogSize
.Width() - nResultWidth
) / 2;
736 rRenderContext
.DrawLine(Point(0, nY
), Point(_nX
, nY
));
737 rRenderContext
.DrawLine(Point(_nX
+ nResultWidth
, nY
), Point(aLogSize
.Width(), nY
));
739 tools::Long nSmallAscent
= pImpl
->mnAscent
;
740 tools::Long nOffset
= (nStdAscent
- nSmallAscent
) / 2;
742 if (pImpl
->mcStartBracket
)
744 OUString
sBracket(pImpl
->mcStartBracket
);
745 rFont
.DrawPrev(&rRenderContext
, pPrinter
, Point(_nX
, nY
- nOffset
- 4), sBracket
);
746 _nX
+= nStartBracketWidth
;
749 Point
aTmpPoint1(_nX
, nY
- nSmallAscent
- 2);
750 Point
aTmpPoint2(_nX
, nY
);
751 pImpl
->DrawPrev(rRenderContext
, pPrinter
, aTmpPoint1
, aSmallFont
);
752 pImpl
->DrawPrev(rRenderContext
, pPrinter
, aTmpPoint2
, aSmallFont
);
755 if (pImpl
->mcEndBracket
)
757 Point
aTmpPoint( _nX
+ 1, nY
- nOffset
- 4);
758 OUString
sBracket(pImpl
->mcEndBracket
);
759 rFont
.DrawPrev(&rRenderContext
, pPrinter
, aTmpPoint
, sBracket
);
761 pImpl
->maCJKFont
.SetFontSize(aOldSize
);
766 Color aLineCol
= rRenderContext
.GetLineColor();
768 rRenderContext
.SetLineColor(rFont
.GetColor());
769 rRenderContext
.DrawLine(Point(0, nY
), Point(nX
, nY
));
770 rRenderContext
.DrawLine(Point(nX
+ aTxtSize
.Width(), nY
), Point(aLogSize
.Width(), nY
));
771 rRenderContext
.SetLineColor(aLineCol
);
773 Point
aTmpPoint(nX
, nY
);
774 pImpl
->DrawPrev(rRenderContext
, pPrinter
, aTmpPoint
, rFont
);
777 rRenderContext
.Pop();
780 bool SvxFontPrevWindow::IsTwoLines() const
782 return pImpl
->mbTwoLines
;
785 void SvxFontPrevWindow::SetTwoLines(bool bSet
)
787 pImpl
->mbTwoLines
= bSet
;
790 void SvxFontPrevWindow::SetBrackets(sal_Unicode cStart
, sal_Unicode cEnd
)
792 pImpl
->mcStartBracket
= cStart
;
793 pImpl
->mcEndBracket
= cEnd
;
796 void SvxFontPrevWindow::SetFontWidthScale( sal_uInt16 n
)
798 if (pImpl
->SetFontWidthScale(n
))
802 void SvxFontPrevWindow::AutoCorrectFontColor()
804 Color
aColor(COL_AUTO
);
805 if ( pImpl
->mxBackColor
) aColor
= *pImpl
->mxBackColor
;
806 const bool bIsDark(aColor
.IsDark());
808 aColor
= pImpl
->maFont
.GetColor();
809 if (aColor
== COL_AUTO
)
810 pImpl
->maFont
.SetColor( bIsDark
? COL_WHITE
: COL_BLACK
);
811 aColor
= pImpl
->maCJKFont
.GetColor();
812 if (aColor
== COL_AUTO
)
813 pImpl
->maCJKFont
.SetColor( bIsDark
? COL_WHITE
: COL_BLACK
);
814 aColor
= pImpl
->maCTLFont
.GetColor();
815 if (aColor
== COL_AUTO
)
816 pImpl
->maCTLFont
.SetColor( bIsDark
? COL_WHITE
: COL_BLACK
);
819 void SvxFontPrevWindow::SetFontSize( const SfxItemSet
& rSet
, sal_uInt16 nSlot
, SvxFont
& rFont
)
823 if (GetWhich(rSet
, nSlot
, nWhich
))
825 nH
= OutputDevice::LogicToLogic(static_cast<const SvxFontHeightItem
&>(rSet
.Get(nWhich
)).GetHeight(),
826 rSet
.GetPool()->GetMetric(nWhich
),
830 nH
= 240;// as default 12pt
832 rFont
.SetFontSize(Size(0, nH
));
835 void SvxFontPrevWindow::SetFontLang(const SfxItemSet
& rSet
, sal_uInt16 nSlot
, SvxFont
& rFont
)
839 if( GetWhich( rSet
, nSlot
, nWhich
) )
840 nLang
= static_cast<const SvxLanguageItem
&>(rSet
.Get(nWhich
)).GetLanguage();
842 nLang
= LANGUAGE_NONE
;
843 rFont
.SetLanguage(nLang
);
846 void SvxFontPrevWindow::SetFromItemSet(const SfxItemSet
&rSet
, bool bPreviewBackgroundToCharacter
)
849 SvxFont
& rFont
= GetFont();
850 SvxFont
& rCJKFont
= GetCJKFont();
851 SvxFont
& rCTLFont
= GetCTLFont();
854 if( GetWhich( rSet
, SID_CHAR_DLG_PREVIEW_STRING
, nWhich
) )
856 const SfxStringItem
& rItem
= static_cast<const SfxStringItem
&>( rSet
.Get( nWhich
) );
857 const OUString
& aString
= rItem
.GetValue();
858 if( !aString
.isEmpty() )
859 SetPreviewText( aString
);
861 SetFontNameAsPreviewText();
865 FontLineStyle eUnderline
;
866 if( GetWhich( rSet
, SID_ATTR_CHAR_UNDERLINE
, nWhich
) )
868 const SvxUnderlineItem
& rItem
= static_cast<const SvxUnderlineItem
&>( rSet
.Get( nWhich
) );
869 eUnderline
= rItem
.GetValue();
872 eUnderline
= LINESTYLE_NONE
;
874 rFont
.SetUnderline( eUnderline
);
875 rCJKFont
.SetUnderline( eUnderline
);
876 rCTLFont
.SetUnderline( eUnderline
);
879 FontLineStyle eOverline
;
880 if( GetWhich( rSet
, SID_ATTR_CHAR_OVERLINE
, nWhich
) )
882 const SvxOverlineItem
& rItem
= static_cast<const SvxOverlineItem
&>( rSet
.Get( nWhich
) );
883 eOverline
= rItem
.GetValue();
886 eOverline
= LINESTYLE_NONE
;
888 rFont
.SetOverline( eOverline
);
889 rCJKFont
.SetOverline( eOverline
);
890 rCTLFont
.SetOverline( eOverline
);
893 FontStrikeout eStrikeout
;
894 if( GetWhich( rSet
, SID_ATTR_CHAR_STRIKEOUT
, nWhich
) )
896 const SvxCrossedOutItem
& rItem
= static_cast<const SvxCrossedOutItem
&>( rSet
.Get( nWhich
) );
897 eStrikeout
= rItem
.GetValue();
900 eStrikeout
= STRIKEOUT_NONE
;
902 rFont
.SetStrikeout( eStrikeout
);
903 rCJKFont
.SetStrikeout( eStrikeout
);
904 rCTLFont
.SetStrikeout( eStrikeout
);
907 if( GetWhich( rSet
, SID_ATTR_CHAR_WORDLINEMODE
, nWhich
) )
909 const SvxWordLineModeItem
& rItem
= static_cast<const SvxWordLineModeItem
&>( rSet
.Get( nWhich
) );
910 rFont
.SetWordLineMode( rItem
.GetValue() );
911 rCJKFont
.SetWordLineMode( rItem
.GetValue() );
912 rCTLFont
.SetWordLineMode( rItem
.GetValue() );
916 if( GetWhich( rSet
, SID_ATTR_CHAR_EMPHASISMARK
, nWhich
) )
918 const SvxEmphasisMarkItem
& rItem
= static_cast<const SvxEmphasisMarkItem
&>( rSet
.Get( nWhich
) );
919 FontEmphasisMark eMark
= rItem
.GetEmphasisMark();
920 rFont
.SetEmphasisMark( eMark
);
921 rCJKFont
.SetEmphasisMark( eMark
);
922 rCTLFont
.SetEmphasisMark( eMark
);
926 if( GetWhich( rSet
, SID_ATTR_CHAR_RELIEF
, nWhich
) )
928 const SvxCharReliefItem
& rItem
= static_cast<const SvxCharReliefItem
&>( rSet
.Get( nWhich
) );
929 FontRelief eFontRelief
= rItem
.GetValue();
930 rFont
.SetRelief( eFontRelief
);
931 rCJKFont
.SetRelief( eFontRelief
);
932 rCTLFont
.SetRelief( eFontRelief
);
936 if( GetWhich( rSet
, SID_ATTR_CHAR_CASEMAP
, nWhich
) )
938 const SvxCaseMapItem
& rItem
= static_cast<const SvxCaseMapItem
&>( rSet
.Get( nWhich
) );
939 SvxCaseMap eCaseMap
= rItem
.GetValue();
940 rFont
.SetCaseMap( eCaseMap
);
941 rCJKFont
.SetCaseMap( eCaseMap
);
942 // #i78474# small caps do not exist in CTL fonts
943 rCTLFont
.SetCaseMap( eCaseMap
== SvxCaseMap::SmallCaps
? SvxCaseMap::NotMapped
: eCaseMap
);
947 if( GetWhich( rSet
, SID_ATTR_CHAR_CONTOUR
, nWhich
) )
949 const SvxContourItem
& rItem
= static_cast<const SvxContourItem
&>( rSet
.Get( nWhich
) );
950 bool bOutline
= rItem
.GetValue();
951 rFont
.SetOutline( bOutline
);
952 rCJKFont
.SetOutline( bOutline
);
953 rCTLFont
.SetOutline( bOutline
);
957 if( GetWhich( rSet
, SID_ATTR_CHAR_SHADOWED
, nWhich
) )
959 const SvxShadowedItem
& rItem
= static_cast<const SvxShadowedItem
&>( rSet
.Get( nWhich
) );
960 bool bShadow
= rItem
.GetValue();
961 rFont
.SetShadow( bShadow
);
962 rCJKFont
.SetShadow( bShadow
);
963 rCTLFont
.SetShadow( bShadow
);
968 if( GetWhich( rSet
, bPreviewBackgroundToCharacter
? SID_ATTR_BRUSH
: SID_ATTR_BRUSH_CHAR
, nWhich
) )
970 const SvxBrushItem
& rBrush
= static_cast<const SvxBrushItem
&>( rSet
.Get( nWhich
) );
971 const Color
& rColor
= rBrush
.GetColor();
972 bTransparent
= rColor
.IsTransparent();
973 rFont
.SetFillColor( rColor
);
974 rCJKFont
.SetFillColor( rColor
);
975 rCTLFont
.SetFillColor( rColor
);
980 rFont
.SetTransparent( bTransparent
);
981 rCJKFont
.SetTransparent( bTransparent
);
982 rCTLFont
.SetTransparent( bTransparent
);
984 if( !bPreviewBackgroundToCharacter
)
986 bool bBackColorFound
= false;
987 if( GetWhich( rSet
, SID_ATTR_BRUSH
, nWhich
) )
989 const SvxBrushItem
& rBrush
= static_cast<const SvxBrushItem
&>( rSet
.Get( nWhich
) );
990 if (GPOS_NONE
== rBrush
.GetGraphicPos())
992 const Color
& rBrushColor
= rBrush
.GetColor();
993 if (rBrushColor
!= COL_TRANSPARENT
)
995 pImpl
->mxBackColor
= rBrush
.GetColor();
996 bBackColorFound
= true;
1000 if (!bBackColorFound
)
1001 pImpl
->mxBackColor
= svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR
).nColor
;
1005 SetPrevFont( rSet
, SID_ATTR_CHAR_FONT
, rFont
);
1006 SetPrevFont( rSet
, SID_ATTR_CHAR_CJK_FONT
, rCJKFont
);
1007 SetPrevFont( rSet
, SID_ATTR_CHAR_CTL_FONT
, rCTLFont
);
1010 SetPrevFontStyle( rSet
, SID_ATTR_CHAR_POSTURE
, SID_ATTR_CHAR_WEIGHT
, rFont
);
1011 SetPrevFontStyle( rSet
, SID_ATTR_CHAR_CJK_POSTURE
, SID_ATTR_CHAR_CJK_WEIGHT
, rCJKFont
);
1012 SetPrevFontStyle( rSet
, SID_ATTR_CHAR_CTL_POSTURE
, SID_ATTR_CHAR_CTL_WEIGHT
, rCTLFont
);
1015 SetFontSize( rSet
, SID_ATTR_CHAR_FONTHEIGHT
, rFont
);
1016 SetFontSize( rSet
, SID_ATTR_CHAR_CJK_FONTHEIGHT
, rCJKFont
);
1017 SetFontSize( rSet
, SID_ATTR_CHAR_CTL_FONTHEIGHT
, rCTLFont
);
1020 SetFontLang( rSet
, SID_ATTR_CHAR_LANGUAGE
, rFont
);
1021 SetFontLang( rSet
, SID_ATTR_CHAR_CJK_LANGUAGE
, rCJKFont
);
1022 SetFontLang( rSet
, SID_ATTR_CHAR_CTL_LANGUAGE
, rCTLFont
);
1025 if( GetWhich( rSet
, SID_ATTR_CHAR_COLOR
, nWhich
) )
1027 const SvxColorItem
& rItem
= static_cast<const SvxColorItem
&>( rSet
.Get( nWhich
) );
1028 Color
aCol( rItem
.GetValue() );
1029 rFont
.SetColor( aCol
);
1031 rCJKFont
.SetColor( aCol
);
1032 rCTLFont
.SetColor( aCol
);
1034 AutoCorrectFontColor(); // handle color COL_AUTO
1038 if( GetWhich( rSet
, SID_ATTR_CHAR_KERNING
, nWhich
) )
1040 const SvxKerningItem
& rItem
= static_cast<const SvxKerningItem
&>( rSet
.Get( nWhich
) );
1041 short nKern
= static_cast<short>(OutputDevice::LogicToLogic(rItem
.GetValue(), rSet
.GetPool()->GetMetric(nWhich
), MapUnit::MapTwip
));
1042 rFont
.SetFixKerning( nKern
);
1043 rCJKFont
.SetFixKerning( nKern
);
1044 rCTLFont
.SetFixKerning( nKern
);
1048 const sal_uInt8 nProp
= 100;
1051 if( GetWhich( rSet
, SID_ATTR_CHAR_ESCAPEMENT
, nWhich
) )
1053 const SvxEscapementItem
& rItem
= static_cast<const SvxEscapementItem
&>( rSet
.Get( nWhich
) );
1054 nEsc
= rItem
.GetEsc();
1055 nEscProp
= rItem
.GetProportionalHeight();
1057 if( nEsc
== DFLT_ESC_AUTO_SUPER
)
1058 nEsc
= DFLT_ESC_SUPER
;
1059 else if( nEsc
== DFLT_ESC_AUTO_SUB
)
1060 nEsc
= DFLT_ESC_SUB
;
1067 SetPrevFontEscapement( rFont
, nProp
, nEscProp
, nEsc
);
1068 SetPrevFontEscapement( rCJKFont
, nProp
, nEscProp
, nEsc
);
1069 SetPrevFontEscapement( rCTLFont
, nProp
, nEscProp
, nEsc
);
1072 if( GetWhich( rSet
, SID_ATTR_CHAR_SCALEWIDTH
, nWhich
) )
1074 const SvxCharScaleWidthItem
&rItem
= static_cast<const SvxCharScaleWidthItem
&>( rSet
.Get( nWhich
) );
1075 SetFontWidthScale( rItem
.GetValue() );
1081 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */