xref: /core/svx/source/dialog/fntctrl.cxx (revision 704e71b9)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
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>
26 
27 #include <com/sun/star/i18n/ScriptType.hpp>
28 
29 #include <vector>
30 #include <optional>
31 #include <svtools/colorcfg.hxx>
32 #include <svtools/sampletext.hxx>
33 
34 #include <svx/fntctrl.hxx>
35 #include <svx/svxids.hrc>
36 
37 // Item set includes
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>
43 
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>
64 
65 //TODO: remove this and calculate off the actual size of text, not
66 //an arbitrary number of characters
67 #define TEXT_WIDTH 80
68 
69 
70 // small helper functions to set fonts
71 
72 namespace
73 {
scaleFontWidth(vcl::Font & rFont,vcl::RenderContext const & rRenderContext,tools::Long & n100PercentFont)74 void scaleFontWidth(vcl::Font& rFont, vcl::RenderContext const & rRenderContext,tools::Long& n100PercentFont)
75 {
76     rFont.SetAverageFontWidth(0);
77     n100PercentFont = rRenderContext.GetFontMetric(rFont).GetAverageFontWidth();
78 }
79 
initFont(vcl::Font & rFont)80 void initFont(vcl::Font& rFont)
81 {
82     rFont.SetTransparent(true);
83     rFont.SetAlignment(ALIGN_BASELINE);
84 }
85 
setFontSize(vcl::Font & rFont)86 void setFontSize(vcl::Font& rFont)
87 {
88     Size aSize(rFont.GetFontSize());
89     aSize.setHeight( (aSize.Height() * 3) / 5 );
90     aSize.setWidth( (aSize.Width() * 3) / 5 );
91     rFont.SetFontSize(aSize);
92 }
93 
calcFontHeightAnyAscent(vcl::RenderContext & rRenderContext,const vcl::Font & rFont,tools::Long & nHeight,tools::Long & nAscent)94 void calcFontHeightAnyAscent(vcl::RenderContext& rRenderContext, const vcl::Font& rFont, tools::Long& nHeight, tools::Long& nAscent)
95 {
96     if (!nHeight)
97     {
98         rRenderContext.SetFont(rFont);
99         FontMetric aMetric(rRenderContext.GetFontMetric());
100         nHeight = aMetric.GetLineHeight();
101         nAscent = aMetric.GetAscent();
102     }
103 }
104 
setFont(const SvxFont & rNewFont,SvxFont & rImplFont)105 void setFont(const SvxFont& rNewFont, SvxFont& rImplFont)
106 {
107     rImplFont = rNewFont;
108     rImplFont.SetTransparent(true);
109     rImplFont.SetAlignment(ALIGN_BASELINE);
110 }
111 
112 /*
113  * removes line feeds and carriage returns from string
114  * returns if param is empty
115  */
removeCRLF(const OUString & rText)116 OUString removeCRLF(const OUString& rText)
117 {
118     return rText.replace(0xa, ' ').replace(0xd, ' ').trim();
119 }
120 
121 struct ScriptInfo
122 {
123     tools::Long textWidth;
124     SvtScriptType scriptType;
125     sal_Int32 changePos;
ScriptInfo__anon940313420111::ScriptInfo126     ScriptInfo(SvtScriptType scrptType, sal_Int32 position)
127         : textWidth(0)
128         , scriptType(scrptType)
129         , changePos(position)
130     {
131     }
132 };
133 
134 } // end anonymous namespace
135 
136 class FontPrevWin_Impl
137 {
138     friend class SvxFontPrevWindow;
139 
140     SvxFont maFont;
141     VclPtr<Printer> mpPrinter;
142     bool mbDelPrinter;
143 
144     std::vector<ScriptInfo> maScriptChanges;
145     SvxFont maCJKFont;
146     SvxFont maCTLFont;
147     OUString maText;
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;
156 
157     tools::Long mn100PercentFontWidth; // initial -1 -> not set yet
158     tools::Long mn100PercentFontWidthCJK;
159     tools::Long mn100PercentFontWidthCTL;
160     sal_uInt16 mnFontWidthScale;
161 
162     bool mbSelection : 1;
163     bool mbGetSelection : 1;
164     bool mbTwoLines : 1;
165     bool mbUseFontNameAsText : 1;
166     bool mbTextInited : 1;
167 
168     bool m_bCJKEnabled;
169     bool m_bCTLEnabled;
170 
171 
172 public:
FontPrevWin_Impl()173     FontPrevWin_Impl() :
174         mpPrinter(nullptr),
175         mbDelPrinter(false),
176         mnAscent(0),
177         mcStartBracket(0),
178         mcEndBracket(0),
179         mnFontWidthScale(100),
180         mbSelection(false),
181         mbGetSelection(false),
182         mbTwoLines(false),
183         mbUseFontNameAsText(false),
184         mbTextInited(false)
185     {
186         m_bCJKEnabled = SvtCJKOptions::IsAnyEnabled();
187         m_bCTLEnabled = SvtCTLOptions::IsCTLFontEnabled();
188         mxBackColor = svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
189         Invalidate100PercentFontWidth();
190     }
191 
~FontPrevWin_Impl()192     ~FontPrevWin_Impl()
193     {
194         if (mbDelPrinter)
195             mpPrinter.disposeAndClear();
196     }
197 
198     void CheckScript();
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);
201 
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
208 };
209 
Invalidate100PercentFontWidth()210 inline void FontPrevWin_Impl::Invalidate100PercentFontWidth()
211 {
212     mn100PercentFontWidth = mn100PercentFontWidthCJK = mn100PercentFontWidthCTL = -1;
213 }
214 
Is100PercentFontWidthValid() const215 inline bool FontPrevWin_Impl::Is100PercentFontWidthValid() const
216 {
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;
223 }
224 
225 /*
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.
230  */
CheckScript()231 void FontPrevWin_Impl::CheckScript()
232 {
233     assert(!maText.isEmpty()); // must have a preview text here!
234     if (maText == maScriptText)
235     {
236         return; // already initialized
237     }
238 
239     maScriptText = maText;
240     maScriptChanges.clear();
241 
242     auto aEditEngine = EditEngine(nullptr);
243     aEditEngine.SetText(maScriptText);
244 
245     auto aScript = aEditEngine.GetScriptType({ 0, 0, 0, 0 });
246     for (sal_Int32 i = 1; i <= maScriptText.getLength(); i++)
247     {
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;
254     }
255 }
256 
257 /*
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.
265  */
266 
CalcTextSize(vcl::RenderContext & rRenderContext,OutputDevice const * _pPrinter,const SvxFont & rInFont)267 Size FontPrevWin_Impl::CalcTextSize(vcl::RenderContext& rRenderContext, OutputDevice const * _pPrinter, const SvxFont& rInFont)
268 {
269     SvtScriptType aScript;
270     sal_uInt16 nIdx = 0;
271     sal_Int32 nStart = 0;
272     sal_Int32 nEnd;
273     size_t nCnt = maScriptChanges.size();
274 
275     if (nCnt)
276     {
277         nEnd = maScriptChanges[nIdx].changePos;
278         aScript = maScriptChanges[nIdx].scriptType;
279     }
280     else
281     {
282         nEnd = maText.getLength();
283         aScript = SvtScriptType::LATIN;
284     }
285     tools::Long nTxtWidth = 0;
286     tools::Long nCJKHeight = 0;
287     tools::Long nCTLHeight = 0;
288     tools::Long nHeight = 0;
289     mnAscent = 0;
290     tools::Long nCJKAscent = 0;
291     tools::Long nCTLAscent = 0;
292 
293     do
294     {
295         const SvxFont& rFont = (aScript == SvtScriptType::ASIAN) ?
296                                     maCJKFont :
297                                     ((aScript == SvtScriptType::COMPLEX) ?
298                                         maCTLFont :
299                                         rInFont);
300         tools::Long nWidth = rFont.GetTextSize(*_pPrinter, maText, nStart, nEnd - nStart).Width();
301         if (nIdx >= maScriptChanges.size())
302             break;
303 
304         maScriptChanges[nIdx++].textWidth = nWidth;
305         nTxtWidth += nWidth;
306 
307         switch (aScript)
308         {
309             case SvtScriptType::ASIAN:
310                 calcFontHeightAnyAscent(rRenderContext, maCJKFont, nCJKHeight, nCJKAscent);
311                 break;
312             case SvtScriptType::COMPLEX:
313                 calcFontHeightAnyAscent(rRenderContext, maCTLFont, nCTLHeight, nCTLAscent);
314                 break;
315             default:
316                 calcFontHeightAnyAscent(rRenderContext, rFont, nHeight, mnAscent);
317         }
318 
319         if (nEnd < maText.getLength() && nIdx < nCnt)
320         {
321             nStart = nEnd;
322             nEnd = maScriptChanges[nIdx].changePos;
323             aScript = maScriptChanges[nIdx].scriptType;
324         }
325         else
326             break;
327     }
328     while(true);
329 
330     nHeight -= mnAscent;
331     nCJKHeight -= nCJKAscent;
332     nCTLHeight -= nCTLAscent;
333 
334     if (nHeight < nCJKHeight)
335         nHeight = nCJKHeight;
336 
337     if (mnAscent < nCJKAscent)
338         mnAscent = nCJKAscent;
339 
340     if (nHeight < nCTLHeight)
341         nHeight = nCTLHeight;
342 
343     if (mnAscent < nCTLAscent)
344         mnAscent = nCTLAscent;
345 
346     nHeight += mnAscent;
347 
348     Size aTxtSize(nTxtWidth, nHeight);
349     return aTxtSize;
350 }
351 
352 /*
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
356  * given rFont.
357  */
358 
DrawPrev(vcl::RenderContext & rRenderContext,Printer * _pPrinter,Point & rPt,const SvxFont & rInFont)359 void FontPrevWin_Impl::DrawPrev(vcl::RenderContext& rRenderContext, Printer* _pPrinter, Point &rPt, const SvxFont& rInFont)
360 {
361     vcl::Font aOldFont = _pPrinter->GetFont();
362     SvtScriptType aScript;
363     sal_uInt16 nIdx = 0;
364     sal_Int32 nStart = 0;
365     sal_Int32 nEnd;
366     size_t nCnt = maScriptChanges.size();
367 
368     if (nCnt)
369     {
370         nEnd = maScriptChanges[nIdx].changePos;
371         aScript = maScriptChanges[nIdx].scriptType;
372     }
373     else
374     {
375         nEnd = maText.getLength();
376         aScript = SvtScriptType::LATIN;
377     }
378     do
379     {
380         const SvxFont& rFont = (aScript == SvtScriptType::ASIAN)
381                                     ? maCJKFont
382                                     : ((aScript == SvtScriptType::COMPLEX)
383                                         ? maCTLFont
384                                         : rInFont);
385         _pPrinter->SetFont(rFont);
386 
387         rFont.DrawPrev(&rRenderContext, _pPrinter, rPt, maText, nStart, nEnd - nStart);
388 
389         rPt.AdjustX(maScriptChanges[nIdx++].textWidth);
390         if (nEnd < maText.getLength() && nIdx < nCnt)
391         {
392             nStart = nEnd;
393             nEnd = maScriptChanges[nIdx].changePos;
394             aScript = maScriptChanges[nIdx].scriptType;
395         }
396         else
397             break;
398     }
399     while(true);
400     _pPrinter->SetFont(aOldFont);
401 }
402 
403 
SetFontWidthScale(sal_uInt16 nScale)404 bool FontPrevWin_Impl::SetFontWidthScale(sal_uInt16 nScale)
405 {
406     if (mnFontWidthScale != nScale)
407     {
408         mnFontWidthScale = nScale;
409         return true;
410     }
411 
412     return false;
413 }
414 
ScaleFontWidth(vcl::RenderContext const & rOutDev)415 void FontPrevWin_Impl::ScaleFontWidth(vcl::RenderContext const & rOutDev)
416 {
417     if (!Is100PercentFontWidthValid())
418     {
419         scaleFontWidth(maFont, rOutDev, mn100PercentFontWidth);
420         scaleFontWidth(maCJKFont, rOutDev, mn100PercentFontWidthCJK);
421         scaleFontWidth(maCTLFont, rOutDev, mn100PercentFontWidthCTL);
422     }
423 
424     maFont.SetAverageFontWidth(mn100PercentFontWidth * mnFontWidthScale / 100);
425     maCJKFont.SetAverageFontWidth(mn100PercentFontWidthCJK * mnFontWidthScale / 100);
426     maCTLFont.SetAverageFontWidth(mn100PercentFontWidthCTL * mnFontWidthScale / 100);
427 }
428 
GetWhich(const SfxItemSet & rSet,sal_uInt16 nSlot,sal_uInt16 & rWhich)429 static bool GetWhich (const SfxItemSet& rSet, sal_uInt16 nSlot, sal_uInt16& rWhich)
430 {
431     rWhich = rSet.GetPool()->GetWhichIDFromSlotID(nSlot);
432     return rSet.GetItemState(rWhich) >= SfxItemState::DEFAULT;
433 }
434 
SetPrevFont(const SfxItemSet & rSet,sal_uInt16 nSlot,SvxFont & rFont)435 static void SetPrevFont(const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont)
436 {
437     sal_uInt16 nWhich;
438     if (GetWhich(rSet, nSlot, nWhich))
439     {
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());
446     }
447 }
448 
SetPrevFontStyle(const SfxItemSet & rSet,sal_uInt16 nPosture,sal_uInt16 nWeight,SvxFont & rFont)449 static void SetPrevFontStyle( const SfxItemSet& rSet, sal_uInt16 nPosture, sal_uInt16 nWeight, SvxFont& rFont )
450 {
451     sal_uInt16 nWhich;
452     if( GetWhich( rSet, nPosture, nWhich ) )
453     {
454         const SvxPostureItem& rItem = static_cast<const SvxPostureItem&>( rSet.Get( nWhich ) );
455         rFont.SetItalic( rItem.GetValue() != ITALIC_NONE ? ITALIC_NORMAL : ITALIC_NONE );
456     }
457 
458     if( GetWhich( rSet, nWeight, nWhich ) )
459     {
460         const SvxWeightItem& rItem = static_cast<const SvxWeightItem&>( rSet.Get( nWhich ) );
461         rFont.SetWeight( rItem.GetValue() != WEIGHT_NORMAL ? WEIGHT_BOLD : WEIGHT_NORMAL );
462     }
463 }
464 
SetPrevFontEscapement(SvxFont & rFont,sal_uInt8 nProp,sal_uInt8 nEscProp,short nEsc)465 static void SetPrevFontEscapement(SvxFont& rFont, sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc)
466 {
467     rFont.SetPropr(nProp);
468     rFont.SetProprRel(nEscProp);
469     rFont.SetEscapement(nEsc);
470 }
471 
ApplySettings(vcl::RenderContext & rRenderContext)472 void SvxFontPrevWindow::ApplySettings(vcl::RenderContext& rRenderContext)
473 {
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);
480 }
481 
SetDrawingArea(weld::DrawingArea * pDrawingArea)482 void SvxFontPrevWindow::SetDrawingArea(weld::DrawingArea* pDrawingArea)
483 {
484     CustomWidgetController::SetDrawingArea(pDrawingArea);
485     Size aPrefSize(getPreviewStripSize(pDrawingArea->get_ref_device()));
486     pDrawingArea->set_size_request(aPrefSize.Width(), aPrefSize.Height());
487 
488     pImpl.reset(new FontPrevWin_Impl);
489     SfxViewShell* pSh = SfxViewShell::Current();
490 
491     if (pSh)
492         pImpl->mpPrinter = pSh->GetPrinter();
493 
494     if (!pImpl->mpPrinter)
495     {
496         pImpl->mpPrinter = VclPtr<Printer>::Create();
497         pImpl->mbDelPrinter = true;
498     }
499     initFont(pImpl->maFont);
500     initFont(pImpl->maCJKFont);
501     initFont(pImpl->maCTLFont);
502 
503     Invalidate();
504 }
505 
SvxFontPrevWindow()506 SvxFontPrevWindow::SvxFontPrevWindow()
507 {
508 }
509 
~SvxFontPrevWindow()510 SvxFontPrevWindow::~SvxFontPrevWindow()
511 {
512 }
513 
GetCTLFont()514 SvxFont& SvxFontPrevWindow::GetCTLFont()
515 {
516     return pImpl->maCTLFont;
517 }
518 
GetCJKFont()519 SvxFont& SvxFontPrevWindow::GetCJKFont()
520 {
521     return pImpl->maCJKFont;
522 }
523 
GetFont()524 SvxFont& SvxFontPrevWindow::GetFont()
525 {
526     pImpl->Invalidate100PercentFontWidth();     // because the user might change the size
527     return pImpl->maFont;
528 }
529 
GetFont() const530 const SvxFont& SvxFontPrevWindow::GetFont() const
531 {
532     return pImpl->maFont;
533 }
534 
SetPreviewText(const OUString & rString)535 void SvxFontPrevWindow::SetPreviewText( const OUString& rString )
536 {
537     pImpl->maText = rString;
538     pImpl->mbTextInited = true;
539 }
540 
SetFontNameAsPreviewText()541 void SvxFontPrevWindow::SetFontNameAsPreviewText()
542 {
543     pImpl->mbUseFontNameAsText = true;
544 }
545 
SetFont(const SvxFont & rNormalOutFont,const SvxFont & rCJKOutFont,const SvxFont & rCTLFont)546 void SvxFontPrevWindow::SetFont( const SvxFont& rNormalOutFont, const SvxFont& rCJKOutFont, const SvxFont& rCTLFont )
547 {
548     setFont(rNormalOutFont, pImpl->maFont);
549     setFont(rCJKOutFont, pImpl->maCJKFont);
550     setFont(rCTLFont, pImpl->maCTLFont);
551 
552     pImpl->Invalidate100PercentFontWidth();
553     Invalidate();
554 }
555 
SetColor(const Color & rColor)556 void SvxFontPrevWindow::SetColor(const Color &rColor)
557 {
558     pImpl->mxColor = rColor;
559     Invalidate();
560 }
561 
ResetColor()562 void SvxFontPrevWindow::ResetColor()
563 {
564     pImpl->mxColor.reset();
565     Invalidate();
566 }
567 
SetTextLineColor(const Color & rColor)568 void SvxFontPrevWindow::SetTextLineColor(const Color &rColor)
569 {
570     pImpl->mxTextLineColor = rColor;
571     Invalidate();
572 }
573 
SetOverlineColor(const Color & rColor)574 void SvxFontPrevWindow::SetOverlineColor(const Color &rColor)
575 {
576     pImpl->mxOverlineColor = rColor;
577     Invalidate();
578 }
579 
Paint(vcl::RenderContext & rRenderContext,const tools::Rectangle &)580 void SvxFontPrevWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
581 {
582     rRenderContext.Push(vcl::PushFlags::ALL);
583     rRenderContext.SetMapMode(MapMode(MapUnit::MapTwip));
584 
585     ApplySettings(rRenderContext);
586     rRenderContext.Erase();
587 
588     Printer* pPrinter = pImpl->mpPrinter;
589     const SvxFont& rFont = pImpl->maFont;
590     const SvxFont& rCJKFont = pImpl->maCJKFont;
591     const SvxFont& rCTLFont = pImpl->maCTLFont;
592 
593     if (!IsEnabled())
594     {
595         const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
596         const Size aLogSize(rRenderContext.GetOutputSize());
597 
598         tools::Rectangle aRect(Point(0, 0), aLogSize);
599         rRenderContext.SetLineColor();
600         rRenderContext.SetFillColor(rStyleSettings.GetWindowColor());
601         rRenderContext.DrawRect(aRect);
602     }
603     else
604     {
605         if (!pImpl->mbSelection && !pImpl->mbTextInited)
606         {
607             using namespace css::i18n::ScriptType;
608 
609             SfxViewShell* pSh = SfxViewShell::Current();
610 
611             if (pSh && !pImpl->mbGetSelection && !pImpl->mbUseFontNameAsText)
612             {
613                 pImpl->maText = removeCRLF(pSh->GetSelectionText(/*bCompleteWords*/false, /*bOnlyASample*/true));
614                 pImpl->mbGetSelection = true;
615                 pImpl->mbSelection = !(pImpl->maText.isEmpty());
616             }
617 
618             if (!pImpl->mbSelection || pImpl->mbUseFontNameAsText)
619             {
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);
625                 else
626                     pImpl->maText = rFont.GetFamilyName();
627 
628                 if (pImpl->m_bCJKEnabled)
629                 {
630                     if (!pImpl->maText.isEmpty())
631                         pImpl->maText += "   ";
632                     pImpl->maText += makeRepresentativeTextForFont(ASIAN, rCJKFont);
633 
634                 }
635                 if (pImpl->m_bCTLEnabled)
636                 {
637                     if (!pImpl->maText.isEmpty())
638                         pImpl->maText += "   ";
639                     pImpl->maText += makeRepresentativeTextForFont(COMPLEX, rCTLFont);
640                 }
641             }
642 
643             if (pImpl->maText.isEmpty())
644             {   // fdo#58427: still no text? let's try that one...
645                 pImpl->maText = makeRepresentativeTextForFont(LATIN, rFont);
646             }
647 
648             pImpl->maText = removeCRLF(pImpl->maText);
649 
650             if (pImpl->maText.getLength() > (TEXT_WIDTH - 1))
651             {
652                 const sal_Int32 nSpaceIdx = pImpl->maText.indexOf(" ", TEXT_WIDTH);
653                 if (nSpaceIdx != -1)
654                     pImpl->maText = pImpl->maText.copy(0, nSpaceIdx);
655                 else
656                     pImpl->maText = pImpl->maText.copy(0, (TEXT_WIDTH - 1));
657             }
658         }
659 
660         // calculate text width scaling
661         pImpl->ScaleFontWidth(rRenderContext);
662 
663         pImpl->CheckScript();
664         Size aTxtSize = pImpl->CalcTextSize(rRenderContext, pPrinter, rFont);
665 
666         const Size aLogSize(rRenderContext.GetOutputSize());
667 
668         tools::Long nX = aLogSize.Width()  / 2 - aTxtSize.Width() / 2;
669         tools::Long nY = aLogSize.Height() / 2 - aTxtSize.Height() / 2;
670 
671         if (nY + pImpl->mnAscent > aLogSize.Height())
672             nY = aLogSize.Height() - pImpl->mnAscent;
673 
674         if (pImpl->mxBackColor)
675         {
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);
684         }
685         if (pImpl->mxColor)
686         {
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);
695         }
696 
697         if (pImpl->mxTextLineColor)
698         {
699             rRenderContext.SetTextLineColor(*pImpl->mxTextLineColor);
700         }
701 
702         if (pImpl->mxOverlineColor)
703         {
704             rRenderContext.SetOverlineColor(*pImpl->mxOverlineColor);
705         }
706 
707         tools::Long nStdAscent = pImpl->mnAscent;
708         nY += nStdAscent;
709 
710         if (IsTwoLines())
711         {
712             SvxFont aSmallFont(rFont);
713             Size aOldSize = pImpl->maCJKFont.GetFontSize();
714             setFontSize(aSmallFont);
715             setFontSize(pImpl->maCJKFont);
716 
717             tools::Long nStartBracketWidth = 0;
718             tools::Long nEndBracketWidth = 0;
719             tools::Long nTextWidth = 0;
720             if (pImpl->mcStartBracket)
721             {
722                 OUString sBracket(pImpl->mcStartBracket);
723                 nStartBracketWidth = rFont.GetTextSize(*pPrinter, sBracket).Width();
724             }
725             if (pImpl->mcEndBracket)
726             {
727                 OUString sBracket(pImpl->mcEndBracket);
728                 nEndBracketWidth = rFont.GetTextSize(*pPrinter, sBracket).Width();
729             }
730             nTextWidth = pImpl->CalcTextSize(rRenderContext, pPrinter, aSmallFont).Width();
731             tools::Long nResultWidth = nStartBracketWidth;
732             nResultWidth += nEndBracketWidth;
733             nResultWidth += nTextWidth;
734 
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));
738 
739             tools::Long nSmallAscent = pImpl->mnAscent;
740             tools::Long nOffset = (nStdAscent - nSmallAscent) / 2;
741 
742             if (pImpl->mcStartBracket)
743             {
744                 OUString sBracket(pImpl->mcStartBracket);
745                 rFont.DrawPrev(&rRenderContext, pPrinter, Point(_nX, nY - nOffset - 4), sBracket);
746                 _nX += nStartBracketWidth;
747             }
748 
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);
753 
754             _nX += nTextWidth;
755             if (pImpl->mcEndBracket)
756             {
757                 Point aTmpPoint( _nX + 1, nY - nOffset - 4);
758                 OUString sBracket(pImpl->mcEndBracket);
759                 rFont.DrawPrev(&rRenderContext, pPrinter, aTmpPoint, sBracket);
760             }
761             pImpl->maCJKFont.SetFontSize(aOldSize);
762         }
763         else
764         {
765 
766             Color aLineCol = rRenderContext.GetLineColor();
767 
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);
772 
773             Point aTmpPoint(nX, nY);
774             pImpl->DrawPrev(rRenderContext, pPrinter, aTmpPoint, rFont);
775         }
776     }
777     rRenderContext.Pop();
778 }
779 
IsTwoLines() const780 bool SvxFontPrevWindow::IsTwoLines() const
781 {
782     return pImpl->mbTwoLines;
783 }
784 
SetTwoLines(bool bSet)785 void SvxFontPrevWindow::SetTwoLines(bool bSet)
786 {
787     pImpl->mbTwoLines = bSet;
788 }
789 
SetBrackets(sal_Unicode cStart,sal_Unicode cEnd)790 void SvxFontPrevWindow::SetBrackets(sal_Unicode cStart, sal_Unicode cEnd)
791 {
792     pImpl->mcStartBracket = cStart;
793     pImpl->mcEndBracket = cEnd;
794 }
795 
SetFontWidthScale(sal_uInt16 n)796 void SvxFontPrevWindow::SetFontWidthScale( sal_uInt16 n )
797 {
798     if (pImpl->SetFontWidthScale(n))
799         Invalidate();
800 }
801 
AutoCorrectFontColor()802 void SvxFontPrevWindow::AutoCorrectFontColor()
803 {
804     Color aColor(COL_AUTO);
805     if ( pImpl->mxBackColor ) aColor = *pImpl->mxBackColor;
806     const bool bIsDark(aColor.IsDark());
807 
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 );
817 }
818 
SetFontSize(const SfxItemSet & rSet,sal_uInt16 nSlot,SvxFont & rFont)819 void SvxFontPrevWindow::SetFontSize( const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont )
820 {
821     sal_uInt16 nWhich;
822     tools::Long nH;
823     if (GetWhich(rSet, nSlot, nWhich))
824     {
825         nH = OutputDevice::LogicToLogic(static_cast<const SvxFontHeightItem&>(rSet.Get(nWhich)).GetHeight(),
826                           rSet.GetPool()->GetMetric(nWhich),
827                           MapUnit::MapTwip);
828     }
829     else
830         nH = 240;// as default 12pt
831 
832     rFont.SetFontSize(Size(0, nH));
833 }
834 
SetFontLang(const SfxItemSet & rSet,sal_uInt16 nSlot,SvxFont & rFont)835 void SvxFontPrevWindow::SetFontLang(const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont)
836 {
837     sal_uInt16 nWhich;
838     LanguageType nLang;
839     if( GetWhich( rSet, nSlot, nWhich ) )
840         nLang = static_cast<const SvxLanguageItem&>(rSet.Get(nWhich)).GetLanguage();
841     else
842         nLang = LANGUAGE_NONE;
843     rFont.SetLanguage(nLang);
844 }
845 
SetFromItemSet(const SfxItemSet & rSet,bool bPreviewBackgroundToCharacter)846 void SvxFontPrevWindow::SetFromItemSet(const SfxItemSet &rSet, bool bPreviewBackgroundToCharacter)
847 {
848     sal_uInt16 nWhich;
849     SvxFont& rFont = GetFont();
850     SvxFont& rCJKFont = GetCJKFont();
851     SvxFont& rCTLFont = GetCTLFont();
852 
853     // Preview string
854     if( GetWhich( rSet, SID_CHAR_DLG_PREVIEW_STRING, nWhich ) )
855     {
856         const SfxStringItem& rItem = static_cast<const SfxStringItem&>( rSet.Get( nWhich ) );
857         const OUString& aString = rItem.GetValue();
858         if( !aString.isEmpty() )
859             SetPreviewText( aString );
860         else
861             SetFontNameAsPreviewText();
862     }
863 
864     // Underline
865     FontLineStyle eUnderline;
866     if( GetWhich( rSet, SID_ATTR_CHAR_UNDERLINE, nWhich ) )
867     {
868         const SvxUnderlineItem& rItem = static_cast<const SvxUnderlineItem&>( rSet.Get( nWhich ) );
869         eUnderline = rItem.GetValue();
870     }
871     else
872         eUnderline = LINESTYLE_NONE;
873 
874     rFont.SetUnderline( eUnderline );
875     rCJKFont.SetUnderline( eUnderline );
876     rCTLFont.SetUnderline( eUnderline );
877 
878     // Overline
879     FontLineStyle eOverline;
880     if( GetWhich( rSet, SID_ATTR_CHAR_OVERLINE, nWhich ) )
881     {
882         const SvxOverlineItem& rItem = static_cast<const SvxOverlineItem&>( rSet.Get( nWhich ) );
883         eOverline = rItem.GetValue();
884     }
885     else
886         eOverline = LINESTYLE_NONE;
887 
888     rFont.SetOverline( eOverline );
889     rCJKFont.SetOverline( eOverline );
890     rCTLFont.SetOverline( eOverline );
891 
892     //  Strikeout
893     FontStrikeout eStrikeout;
894     if( GetWhich( rSet, SID_ATTR_CHAR_STRIKEOUT, nWhich ) )
895     {
896         const SvxCrossedOutItem& rItem = static_cast<const SvxCrossedOutItem&>( rSet.Get( nWhich ) );
897         eStrikeout = rItem.GetValue();
898     }
899     else
900         eStrikeout = STRIKEOUT_NONE;
901 
902     rFont.SetStrikeout( eStrikeout );
903     rCJKFont.SetStrikeout( eStrikeout );
904     rCTLFont.SetStrikeout( eStrikeout );
905 
906     // WordLineMode
907     if( GetWhich( rSet, SID_ATTR_CHAR_WORDLINEMODE, nWhich ) )
908     {
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() );
913     }
914 
915     // Emphasis
916     if( GetWhich( rSet, SID_ATTR_CHAR_EMPHASISMARK, nWhich ) )
917     {
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 );
923     }
924 
925     // Relief
926     if( GetWhich( rSet, SID_ATTR_CHAR_RELIEF, nWhich ) )
927     {
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 );
933     }
934 
935     // Effects
936     if( GetWhich( rSet, SID_ATTR_CHAR_CASEMAP, nWhich ) )
937     {
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 );
944     }
945 
946     // Outline
947     if( GetWhich( rSet, SID_ATTR_CHAR_CONTOUR, nWhich ) )
948     {
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 );
954     }
955 
956     // Shadow
957     if( GetWhich( rSet, SID_ATTR_CHAR_SHADOWED, nWhich ) )
958     {
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 );
964     }
965 
966     // Background
967     bool bTransparent;
968     if( GetWhich( rSet, bPreviewBackgroundToCharacter ? SID_ATTR_BRUSH : SID_ATTR_BRUSH_CHAR, nWhich ) )
969     {
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 );
976     }
977     else
978         bTransparent = true;
979 
980     rFont.SetTransparent( bTransparent );
981     rCJKFont.SetTransparent( bTransparent );
982     rCTLFont.SetTransparent( bTransparent );
983 
984     if( !bPreviewBackgroundToCharacter )
985     {
986         bool bBackColorFound = false;
987         if( GetWhich( rSet, SID_ATTR_BRUSH, nWhich ) )
988         {
989             const SvxBrushItem& rBrush = static_cast<const  SvxBrushItem&>( rSet.Get( nWhich ) );
990             if (GPOS_NONE == rBrush.GetGraphicPos())
991             {
992                 const Color& rBrushColor = rBrush.GetColor();
993                 if (rBrushColor != COL_TRANSPARENT)
994                 {
995                     pImpl->mxBackColor = rBrush.GetColor();
996                     bBackColorFound = true;
997                 }
998             }
999         }
1000         if (!bBackColorFound)
1001             pImpl->mxBackColor = svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
1002     }
1003 
1004     // Font
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 );
1008 
1009     // Style
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 );
1013 
1014     // Size
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 );
1018 
1019     // Language
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 );
1023 
1024     // Color
1025     if( GetWhich( rSet, SID_ATTR_CHAR_COLOR, nWhich ) )
1026     {
1027         const SvxColorItem& rItem = static_cast<const SvxColorItem&>( rSet.Get( nWhich ) );
1028         Color aCol( rItem.GetValue() );
1029         rFont.SetColor( aCol );
1030 
1031         rCJKFont.SetColor( aCol );
1032         rCTLFont.SetColor( aCol );
1033 
1034         AutoCorrectFontColor(); // handle color COL_AUTO
1035     }
1036 
1037     // Kerning
1038     if( GetWhich( rSet, SID_ATTR_CHAR_KERNING, nWhich ) )
1039     {
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 );
1045     }
1046 
1047     // Escapement
1048     const sal_uInt8 nProp = 100;
1049     short nEsc;
1050     sal_uInt8 nEscProp;
1051     if( GetWhich( rSet, SID_ATTR_CHAR_ESCAPEMENT, nWhich ) )
1052     {
1053         const SvxEscapementItem& rItem = static_cast<const SvxEscapementItem&>( rSet.Get( nWhich ) );
1054         nEsc = rItem.GetEsc();
1055         nEscProp = rItem.GetProportionalHeight();
1056 
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;
1061     }
1062     else
1063     {
1064         nEsc  = 0;
1065         nEscProp = 100;
1066     }
1067     SetPrevFontEscapement( rFont, nProp, nEscProp, nEsc );
1068     SetPrevFontEscapement( rCJKFont, nProp, nEscProp, nEsc );
1069     SetPrevFontEscapement( rCTLFont, nProp, nEscProp, nEsc );
1070 
1071     // Font width scale
1072     if( GetWhich( rSet, SID_ATTR_CHAR_SCALEWIDTH, nWhich ) )
1073     {
1074         const SvxCharScaleWidthItem&rItem = static_cast<const SvxCharScaleWidthItem&>( rSet.Get( nWhich ) );
1075         SetFontWidthScale( rItem.GetValue() );
1076     }
1077 
1078     Invalidate();
1079 }
1080 
1081 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1082