Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / svx / source / dialog / fntctrl.cxx
blob69cc90171979c8623355facc6986b7f894e6a112
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
29 #include <vector>
30 #include <deque>
31 #include <optional>
32 #include <svtools/colorcfg.hxx>
33 #include <svtools/sampletext.hxx>
35 #include <svx/fntctrl.hxx>
36 #include <svx/svxids.hrc>
38 // Item set includes
39 #include <svl/itemset.hxx>
40 #include <svl/itempool.hxx>
41 #include <svl/stritem.hxx>
42 #include <svl/cjkoptions.hxx>
43 #include <svl/ctloptions.hxx>
45 #include <editeng/editeng.hxx>
46 #include <editeng/colritem.hxx>
47 #include <editeng/fontitem.hxx>
48 #include <editeng/editids.hrc>
49 #include <editeng/postitem.hxx>
50 #include <editeng/udlnitem.hxx>
51 #include <editeng/crossedoutitem.hxx>
52 #include <editeng/contouritem.hxx>
53 #include <editeng/wghtitem.hxx>
54 #include <editeng/fhgtitem.hxx>
55 #include <editeng/shdditem.hxx>
56 #include <editeng/escapementitem.hxx>
57 #include <editeng/wrlmitem.hxx>
58 #include <editeng/cmapitem.hxx>
59 #include <editeng/kernitem.hxx>
60 #include <editeng/brushitem.hxx>
61 #include <editeng/emphasismarkitem.hxx>
62 #include <editeng/charreliefitem.hxx>
63 #include <editeng/charscaleitem.hxx>
64 #include <editeng/langitem.hxx>
66 //TODO: remove this and calculate off the actual size of text, not
67 //an arbitrary number of characters
68 #define TEXT_WIDTH 80
70 using namespace ::com::sun::star::uno;
71 using namespace ::com::sun::star::lang;
74 // small helper functions to set fonts
76 namespace
78 void scaleFontWidth(vcl::Font& rFont, vcl::RenderContext const & rRenderContext,tools::Long& n100PercentFont)
80 rFont.SetAverageFontWidth(0);
81 n100PercentFont = rRenderContext.GetFontMetric(rFont).GetAverageFontWidth();
84 void initFont(vcl::Font& rFont)
86 rFont.SetTransparent(true);
87 rFont.SetAlignment(ALIGN_BASELINE);
90 void setFontSize(vcl::Font& rFont)
92 Size aSize(rFont.GetFontSize());
93 aSize.setHeight( (aSize.Height() * 3) / 5 );
94 aSize.setWidth( (aSize.Width() * 3) / 5 );
95 rFont.SetFontSize(aSize);
98 void calcFontHeightAnyAscent(vcl::RenderContext& rRenderContext, const vcl::Font& rFont, tools::Long& nHeight, tools::Long& nAscent)
100 if (!nHeight)
102 rRenderContext.SetFont(rFont);
103 FontMetric aMetric(rRenderContext.GetFontMetric());
104 nHeight = aMetric.GetLineHeight();
105 nAscent = aMetric.GetAscent();
109 void setFont(const SvxFont& rNewFont, SvxFont& rImplFont)
111 rImplFont = rNewFont;
112 rImplFont.SetTransparent(true);
113 rImplFont.SetAlignment(ALIGN_BASELINE);
117 * removes line feeds and carriage returns from string
118 * returns if param is empty
120 OUString removeCRLF(const OUString& rText)
122 return rText.replace(0xa, ' ').replace(0xd, ' ').trim();
125 struct ScriptInfo
127 tools::Long textWidth;
128 SvtScriptType scriptType;
129 sal_Int32 changePos;
130 ScriptInfo(SvtScriptType scrptType, sal_Int32 position)
131 : textWidth(0)
132 , scriptType(scrptType)
133 , changePos(position)
138 } // end anonymous namespace
140 class FontPrevWin_Impl
142 friend class SvxFontPrevWindow;
144 SvxFont maFont;
145 VclPtr<Printer> mpPrinter;
146 bool mbDelPrinter;
148 std::vector<ScriptInfo> maScriptChanges;
149 SvxFont maCJKFont;
150 SvxFont maCTLFont;
151 OUString maText;
152 OUString maScriptText;
153 std::optional<Color> mxColor;
154 std::optional<Color> mxBackColor;
155 std::optional<Color> mxTextLineColor;
156 std::optional<Color> mxOverlineColor;
157 tools::Long mnAscent;
158 sal_Unicode mcStartBracket;
159 sal_Unicode mcEndBracket;
161 tools::Long mn100PercentFontWidth; // initial -1 -> not set yet
162 tools::Long mn100PercentFontWidthCJK;
163 tools::Long mn100PercentFontWidthCTL;
164 sal_uInt16 mnFontWidthScale;
166 bool mbSelection : 1;
167 bool mbGetSelection : 1;
168 bool mbTwoLines : 1;
169 bool mbUseFontNameAsText : 1;
170 bool mbTextInited : 1;
172 bool m_bCJKEnabled;
173 bool m_bCTLEnabled;
176 public:
177 FontPrevWin_Impl() :
178 mpPrinter(nullptr),
179 mbDelPrinter(false),
180 mnAscent(0),
181 mcStartBracket(0),
182 mcEndBracket(0),
183 mnFontWidthScale(100),
184 mbSelection(false),
185 mbGetSelection(false),
186 mbTwoLines(false),
187 mbUseFontNameAsText(false),
188 mbTextInited(false)
190 m_bCJKEnabled = SvtCJKOptions::IsAnyEnabled();
191 m_bCTLEnabled = SvtCTLOptions::IsCTLFontEnabled();
192 mxBackColor = svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
193 Invalidate100PercentFontWidth();
196 ~FontPrevWin_Impl()
198 if (mbDelPrinter)
199 mpPrinter.disposeAndClear();
202 void CheckScript();
203 Size CalcTextSize(vcl::RenderContext& rRenderContext, OutputDevice const * pPrinter, const SvxFont& rFont);
204 void DrawPrev(vcl::RenderContext& rRenderContext, Printer* pPrinter, Point& rPt, const SvxFont& rFont);
206 bool SetFontWidthScale(sal_uInt16 nScaleInPercent);
207 inline void Invalidate100PercentFontWidth();
208 inline bool Is100PercentFontWidthValid() const;
209 void ScaleFontWidth(vcl::RenderContext const & rRenderContext);
210 // scales rNonCJKFont and aCJKFont depending on nFontWidthScale and
211 // sets the 100%-Font-Widths
214 inline void FontPrevWin_Impl::Invalidate100PercentFontWidth()
216 mn100PercentFontWidth = mn100PercentFontWidthCJK = mn100PercentFontWidthCTL = -1;
219 inline bool FontPrevWin_Impl::Is100PercentFontWidthValid() const
221 DBG_ASSERT( ( mn100PercentFontWidth == -1 && mn100PercentFontWidthCJK == -1 ) ||
222 ( mn100PercentFontWidth != -1 && mn100PercentFontWidthCJK != -1 ) ||
223 ( mn100PercentFontWidth == -1 && mn100PercentFontWidthCTL == -1 ) ||
224 ( mn100PercentFontWidth != -1 && mn100PercentFontWidthCTL != -1 ),
225 "*FontPrevWin_Impl::Is100PercentFontWidthValid(): 100PercentFontWidth's not synchronous" );
226 return mn100PercentFontWidth != -1;
230 * evaluates the scripttypes of the actual string.
231 * Afterwards the positions of script change are notified in aScriptChg,
232 * the scripttypes in aScriptType.
233 * The aTextWidth array will be filled with zero.
235 void FontPrevWin_Impl::CheckScript()
237 assert(!maText.isEmpty()); // must have a preview text here!
238 if (maText == maScriptText)
240 return; // already initialized
243 maScriptText = maText;
244 maScriptChanges.clear();
246 auto aEditEngine = EditEngine(nullptr);
247 aEditEngine.SetText(maScriptText);
249 auto aScript = aEditEngine.GetScriptType({ 0, 0, 0, 0 });
250 for (sal_Int32 i = 1; i <= maScriptText.getLength(); i++)
252 auto aNextScript = aEditEngine.GetScriptType({ 0, i, 0, i });
253 if (aNextScript != aScript)
254 maScriptChanges.emplace_back(aScript, i - 1);
255 if (i == maScriptText.getLength())
256 maScriptChanges.emplace_back(aScript, i);
257 aScript = aNextScript;
262 * Size FontPrevWin_Impl::CalcTextSize(..)
263 * fills the aTextWidth array with the text width of every part
264 * of the actual string without a script change inside.
265 * For Latin parts the given rFont will be used,
266 * for Asian parts the aCJKFont.
267 * The returned size contains the whole string.
268 * The member nAscent is calculated to the maximal ascent of all used fonts.
271 Size FontPrevWin_Impl::CalcTextSize(vcl::RenderContext& rRenderContext, OutputDevice const * _pPrinter, const SvxFont& rInFont)
273 SvtScriptType aScript;
274 sal_uInt16 nIdx = 0;
275 sal_Int32 nStart = 0;
276 sal_Int32 nEnd;
277 size_t nCnt = maScriptChanges.size();
279 if (nCnt)
281 nEnd = maScriptChanges[nIdx].changePos;
282 aScript = maScriptChanges[nIdx].scriptType;
284 else
286 nEnd = maText.getLength();
287 aScript = SvtScriptType::LATIN;
289 tools::Long nTxtWidth = 0;
290 tools::Long nCJKHeight = 0;
291 tools::Long nCTLHeight = 0;
292 tools::Long nHeight = 0;
293 mnAscent = 0;
294 tools::Long nCJKAscent = 0;
295 tools::Long nCTLAscent = 0;
299 const SvxFont& rFont = (aScript == SvtScriptType::ASIAN) ?
300 maCJKFont :
301 ((aScript == SvtScriptType::COMPLEX) ?
302 maCTLFont :
303 rInFont);
304 tools::Long nWidth = rFont.GetTextSize(*_pPrinter, maText, nStart, nEnd - nStart).Width();
305 if (nIdx >= maScriptChanges.size())
306 break;
308 maScriptChanges[nIdx++].textWidth = nWidth;
309 nTxtWidth += nWidth;
311 switch (aScript)
313 case SvtScriptType::ASIAN:
314 calcFontHeightAnyAscent(rRenderContext, maCJKFont, nCJKHeight, nCJKAscent);
315 break;
316 case SvtScriptType::COMPLEX:
317 calcFontHeightAnyAscent(rRenderContext, maCTLFont, nCTLHeight, nCTLAscent);
318 break;
319 default:
320 calcFontHeightAnyAscent(rRenderContext, rFont, nHeight, mnAscent);
323 if (nEnd < maText.getLength() && nIdx < nCnt)
325 nStart = nEnd;
326 nEnd = maScriptChanges[nIdx].changePos;
327 aScript = maScriptChanges[nIdx].scriptType;
329 else
330 break;
332 while(true);
334 nHeight -= mnAscent;
335 nCJKHeight -= nCJKAscent;
336 nCTLHeight -= nCTLAscent;
338 if (nHeight < nCJKHeight)
339 nHeight = nCJKHeight;
341 if (mnAscent < nCJKAscent)
342 mnAscent = nCJKAscent;
344 if (nHeight < nCTLHeight)
345 nHeight = nCTLHeight;
347 if (mnAscent < nCTLAscent)
348 mnAscent = nCTLAscent;
350 nHeight += mnAscent;
352 Size aTxtSize(nTxtWidth, nHeight);
353 return aTxtSize;
357 * void FontPrevWin_Impl::DrawPrev(..)
358 * calls SvxFont::DrawPrev(..) for every part of the string without a script
359 * change inside, for Asian parts the aCJKFont will be used, otherwise the
360 * given rFont.
363 void FontPrevWin_Impl::DrawPrev(vcl::RenderContext& rRenderContext, Printer* _pPrinter, Point &rPt, const SvxFont& rInFont)
365 vcl::Font aOldFont = _pPrinter->GetFont();
366 SvtScriptType aScript;
367 sal_uInt16 nIdx = 0;
368 sal_Int32 nStart = 0;
369 sal_Int32 nEnd;
370 size_t nCnt = maScriptChanges.size();
372 if (nCnt)
374 nEnd = maScriptChanges[nIdx].changePos;
375 aScript = maScriptChanges[nIdx].scriptType;
377 else
379 nEnd = maText.getLength();
380 aScript = SvtScriptType::LATIN;
384 const SvxFont& rFont = (aScript == SvtScriptType::ASIAN)
385 ? maCJKFont
386 : ((aScript == SvtScriptType::COMPLEX)
387 ? maCTLFont
388 : rInFont);
389 _pPrinter->SetFont(rFont);
391 rFont.DrawPrev(&rRenderContext, _pPrinter, rPt, maText, nStart, nEnd - nStart);
393 rPt.AdjustX(maScriptChanges[nIdx++].textWidth);
394 if (nEnd < maText.getLength() && nIdx < nCnt)
396 nStart = nEnd;
397 nEnd = maScriptChanges[nIdx].changePos;
398 aScript = maScriptChanges[nIdx].scriptType;
400 else
401 break;
403 while(true);
404 _pPrinter->SetFont(aOldFont);
408 bool FontPrevWin_Impl::SetFontWidthScale(sal_uInt16 nScale)
410 if (mnFontWidthScale != nScale)
412 mnFontWidthScale = nScale;
413 return true;
416 return false;
419 void FontPrevWin_Impl::ScaleFontWidth(vcl::RenderContext const & rOutDev)
421 if (!Is100PercentFontWidthValid())
423 scaleFontWidth(maFont, rOutDev, mn100PercentFontWidth);
424 scaleFontWidth(maCJKFont, rOutDev, mn100PercentFontWidthCJK);
425 scaleFontWidth(maCTLFont, rOutDev, mn100PercentFontWidthCTL);
428 maFont.SetAverageFontWidth(mn100PercentFontWidth * mnFontWidthScale / 100);
429 maCJKFont.SetAverageFontWidth(mn100PercentFontWidthCJK * mnFontWidthScale / 100);
430 maCTLFont.SetAverageFontWidth(mn100PercentFontWidthCTL * mnFontWidthScale / 100);
433 static bool GetWhich (const SfxItemSet& rSet, sal_uInt16 nSlot, sal_uInt16& rWhich)
435 rWhich = rSet.GetPool()->GetWhich(nSlot);
436 return rSet.GetItemState(rWhich) >= SfxItemState::DEFAULT;
439 static void SetPrevFont(const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont)
441 sal_uInt16 nWhich;
442 if (GetWhich(rSet, nSlot, nWhich))
444 const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(rSet.Get(nWhich));
445 rFont.SetFamily(rFontItem.GetFamily());
446 rFont.SetFamilyName(rFontItem.GetFamilyName());
447 rFont.SetPitch(rFontItem.GetPitch());
448 rFont.SetCharSet(rFontItem.GetCharSet());
449 rFont.SetStyleName(rFontItem.GetStyleName());
453 static void SetPrevFontStyle( const SfxItemSet& rSet, sal_uInt16 nPosture, sal_uInt16 nWeight, SvxFont& rFont )
455 sal_uInt16 nWhich;
456 if( GetWhich( rSet, nPosture, nWhich ) )
458 const SvxPostureItem& rItem = static_cast<const SvxPostureItem&>( rSet.Get( nWhich ) );
459 rFont.SetItalic( rItem.GetValue() != ITALIC_NONE ? ITALIC_NORMAL : ITALIC_NONE );
462 if( GetWhich( rSet, nWeight, nWhich ) )
464 const SvxWeightItem& rItem = static_cast<const SvxWeightItem&>( rSet.Get( nWhich ) );
465 rFont.SetWeight( rItem.GetValue() != WEIGHT_NORMAL ? WEIGHT_BOLD : WEIGHT_NORMAL );
469 static void SetPrevFontEscapement(SvxFont& rFont, sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc)
471 rFont.SetPropr(nProp);
472 rFont.SetProprRel(nEscProp);
473 rFont.SetEscapement(nEsc);
476 void SvxFontPrevWindow::ApplySettings(vcl::RenderContext& rRenderContext)
478 Color aBgColor = svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
479 Color aFgColor = svtools::ColorConfig().GetColorValue(svtools::FONTCOLOR, false).nColor;
480 if (aFgColor == COL_AUTO)
481 aFgColor = aBgColor.IsDark() ? COL_WHITE : COL_BLACK;
482 rRenderContext.SetBackground(aBgColor);
483 rRenderContext.SetTextColor(aFgColor);
486 void SvxFontPrevWindow::SetDrawingArea(weld::DrawingArea* pDrawingArea)
488 CustomWidgetController::SetDrawingArea(pDrawingArea);
489 Size aPrefSize(getPreviewStripSize(pDrawingArea->get_ref_device()));
490 pDrawingArea->set_size_request(aPrefSize.Width(), aPrefSize.Height());
492 pImpl.reset(new FontPrevWin_Impl);
493 SfxViewShell* pSh = SfxViewShell::Current();
495 if (pSh)
496 pImpl->mpPrinter = pSh->GetPrinter();
498 if (!pImpl->mpPrinter)
500 pImpl->mpPrinter = VclPtr<Printer>::Create();
501 pImpl->mbDelPrinter = true;
503 initFont(pImpl->maFont);
504 initFont(pImpl->maCJKFont);
505 initFont(pImpl->maCTLFont);
507 Invalidate();
510 SvxFontPrevWindow::SvxFontPrevWindow()
514 SvxFontPrevWindow::~SvxFontPrevWindow()
518 SvxFont& SvxFontPrevWindow::GetCTLFont()
520 return pImpl->maCTLFont;
523 SvxFont& SvxFontPrevWindow::GetCJKFont()
525 return pImpl->maCJKFont;
528 SvxFont& SvxFontPrevWindow::GetFont()
530 pImpl->Invalidate100PercentFontWidth(); // because the user might change the size
531 return pImpl->maFont;
534 const SvxFont& SvxFontPrevWindow::GetFont() const
536 return pImpl->maFont;
539 void SvxFontPrevWindow::SetPreviewText( const OUString& rString )
541 pImpl->maText = rString;
542 pImpl->mbTextInited = true;
545 void SvxFontPrevWindow::SetFontNameAsPreviewText()
547 pImpl->mbUseFontNameAsText = true;
550 void SvxFontPrevWindow::SetFont( const SvxFont& rNormalOutFont, const SvxFont& rCJKOutFont, const SvxFont& rCTLFont )
552 setFont(rNormalOutFont, pImpl->maFont);
553 setFont(rCJKOutFont, pImpl->maCJKFont);
554 setFont(rCTLFont, pImpl->maCTLFont);
556 pImpl->Invalidate100PercentFontWidth();
557 Invalidate();
560 void SvxFontPrevWindow::SetColor(const Color &rColor)
562 pImpl->mxColor = rColor;
563 Invalidate();
566 void SvxFontPrevWindow::ResetColor()
568 pImpl->mxColor.reset();
569 Invalidate();
572 void SvxFontPrevWindow::SetTextLineColor(const Color &rColor)
574 pImpl->mxTextLineColor = rColor;
575 Invalidate();
578 void SvxFontPrevWindow::SetOverlineColor(const Color &rColor)
580 pImpl->mxOverlineColor = rColor;
581 Invalidate();
584 void SvxFontPrevWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
586 rRenderContext.Push(vcl::PushFlags::ALL);
587 rRenderContext.SetMapMode(MapMode(MapUnit::MapTwip));
589 ApplySettings(rRenderContext);
590 rRenderContext.Erase();
592 Printer* pPrinter = pImpl->mpPrinter;
593 const SvxFont& rFont = pImpl->maFont;
594 const SvxFont& rCJKFont = pImpl->maCJKFont;
595 const SvxFont& rCTLFont = pImpl->maCTLFont;
597 if (!IsEnabled())
599 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
600 const Size aLogSize(rRenderContext.GetOutputSize());
602 tools::Rectangle aRect(Point(0, 0), aLogSize);
603 rRenderContext.SetLineColor();
604 rRenderContext.SetFillColor(rStyleSettings.GetWindowColor());
605 rRenderContext.DrawRect(aRect);
607 else
609 if (!pImpl->mbSelection && !pImpl->mbTextInited)
611 using namespace css::i18n::ScriptType;
613 SfxViewShell* pSh = SfxViewShell::Current();
615 if (pSh && !pImpl->mbGetSelection && !pImpl->mbUseFontNameAsText)
617 pImpl->maText = removeCRLF(pSh->GetSelectionText(/*bCompleteWords*/false, /*bOnlyASample*/true));
618 pImpl->mbGetSelection = true;
619 pImpl->mbSelection = !(pImpl->maText.isEmpty());
622 if (!pImpl->mbSelection || pImpl->mbUseFontNameAsText)
624 //If we're showing multiple sample texts, then they're all
625 //sample texts. If only showing Latin, continue to use
626 //the fontname as the preview
627 if ((pImpl->m_bCJKEnabled) || (pImpl->m_bCTLEnabled))
628 pImpl->maText = makeRepresentativeTextForFont(LATIN, rFont);
629 else
630 pImpl->maText = rFont.GetFamilyName();
632 if (pImpl->m_bCJKEnabled)
634 if (!pImpl->maText.isEmpty())
635 pImpl->maText += " ";
636 pImpl->maText += makeRepresentativeTextForFont(ASIAN, rCJKFont);
639 if (pImpl->m_bCTLEnabled)
641 if (!pImpl->maText.isEmpty())
642 pImpl->maText += " ";
643 pImpl->maText += makeRepresentativeTextForFont(COMPLEX, rCTLFont);
647 if (pImpl->maText.isEmpty())
648 { // fdo#58427: still no text? let's try that one...
649 pImpl->maText = makeRepresentativeTextForFont(LATIN, rFont);
652 pImpl->maText = removeCRLF(pImpl->maText);
654 if (pImpl->maText.getLength() > (TEXT_WIDTH - 1))
656 const sal_Int32 nSpaceIdx = pImpl->maText.indexOf(" ", TEXT_WIDTH);
657 if (nSpaceIdx != -1)
658 pImpl->maText = pImpl->maText.copy(0, nSpaceIdx);
659 else
660 pImpl->maText = pImpl->maText.copy(0, (TEXT_WIDTH - 1));
664 // calculate text width scaling
665 pImpl->ScaleFontWidth(rRenderContext);
667 pImpl->CheckScript();
668 Size aTxtSize = pImpl->CalcTextSize(rRenderContext, pPrinter, rFont);
670 const Size aLogSize(rRenderContext.GetOutputSize());
672 tools::Long nX = aLogSize.Width() / 2 - aTxtSize.Width() / 2;
673 tools::Long nY = aLogSize.Height() / 2 - aTxtSize.Height() / 2;
675 if (nY + pImpl->mnAscent > aLogSize.Height())
676 nY = aLogSize.Height() - pImpl->mnAscent;
678 if (pImpl->mxBackColor)
680 tools::Rectangle aRect(Point(0, 0), aLogSize);
681 Color aLineCol = rRenderContext.GetLineColor();
682 Color aFillCol = rRenderContext.GetFillColor();
683 rRenderContext.SetLineColor();
684 rRenderContext.SetFillColor(*pImpl->mxBackColor);
685 rRenderContext.DrawRect(aRect);
686 rRenderContext.SetLineColor(aLineCol);
687 rRenderContext.SetFillColor(aFillCol);
689 if (pImpl->mxColor)
691 tools::Rectangle aRect(Point(nX, nY), aTxtSize);
692 Color aLineCol = rRenderContext.GetLineColor();
693 Color aFillCol = rRenderContext.GetFillColor();
694 rRenderContext.SetLineColor();
695 rRenderContext.SetFillColor(*pImpl->mxColor);
696 rRenderContext.DrawRect(aRect);
697 rRenderContext.SetLineColor(aLineCol);
698 rRenderContext.SetFillColor(aFillCol);
701 if (pImpl->mxTextLineColor)
703 rRenderContext.SetTextLineColor(*pImpl->mxTextLineColor);
706 if (pImpl->mxOverlineColor)
708 rRenderContext.SetOverlineColor(*pImpl->mxOverlineColor);
711 tools::Long nStdAscent = pImpl->mnAscent;
712 nY += nStdAscent;
714 if (IsTwoLines())
716 SvxFont aSmallFont(rFont);
717 Size aOldSize = pImpl->maCJKFont.GetFontSize();
718 setFontSize(aSmallFont);
719 setFontSize(pImpl->maCJKFont);
721 tools::Long nStartBracketWidth = 0;
722 tools::Long nEndBracketWidth = 0;
723 tools::Long nTextWidth = 0;
724 if (pImpl->mcStartBracket)
726 OUString sBracket(pImpl->mcStartBracket);
727 nStartBracketWidth = rFont.GetTextSize(*pPrinter, sBracket).Width();
729 if (pImpl->mcEndBracket)
731 OUString sBracket(pImpl->mcEndBracket);
732 nEndBracketWidth = rFont.GetTextSize(*pPrinter, sBracket).Width();
734 nTextWidth = pImpl->CalcTextSize(rRenderContext, pPrinter, aSmallFont).Width();
735 tools::Long nResultWidth = nStartBracketWidth;
736 nResultWidth += nEndBracketWidth;
737 nResultWidth += nTextWidth;
739 tools::Long _nX = (aLogSize.Width() - nResultWidth) / 2;
740 rRenderContext.DrawLine(Point(0, nY), Point(_nX, nY));
741 rRenderContext.DrawLine(Point(_nX + nResultWidth, nY), Point(aLogSize.Width(), nY));
743 tools::Long nSmallAscent = pImpl->mnAscent;
744 tools::Long nOffset = (nStdAscent - nSmallAscent) / 2;
746 if (pImpl->mcStartBracket)
748 OUString sBracket(pImpl->mcStartBracket);
749 rFont.DrawPrev(&rRenderContext, pPrinter, Point(_nX, nY - nOffset - 4), sBracket);
750 _nX += nStartBracketWidth;
753 Point aTmpPoint1(_nX, nY - nSmallAscent - 2);
754 Point aTmpPoint2(_nX, nY);
755 pImpl->DrawPrev(rRenderContext, pPrinter, aTmpPoint1, aSmallFont);
756 pImpl->DrawPrev(rRenderContext, pPrinter, aTmpPoint2, aSmallFont);
758 _nX += nTextWidth;
759 if (pImpl->mcEndBracket)
761 Point aTmpPoint( _nX + 1, nY - nOffset - 4);
762 OUString sBracket(pImpl->mcEndBracket);
763 rFont.DrawPrev(&rRenderContext, pPrinter, aTmpPoint, sBracket);
765 pImpl->maCJKFont.SetFontSize(aOldSize);
767 else
770 Color aLineCol = rRenderContext.GetLineColor();
772 rRenderContext.SetLineColor(rFont.GetColor());
773 rRenderContext.DrawLine(Point(0, nY), Point(nX, nY));
774 rRenderContext.DrawLine(Point(nX + aTxtSize.Width(), nY), Point(aLogSize.Width(), nY));
775 rRenderContext.SetLineColor(aLineCol);
777 Point aTmpPoint(nX, nY);
778 pImpl->DrawPrev(rRenderContext, pPrinter, aTmpPoint, rFont);
781 rRenderContext.Pop();
784 bool SvxFontPrevWindow::IsTwoLines() const
786 return pImpl->mbTwoLines;
789 void SvxFontPrevWindow::SetTwoLines(bool bSet)
791 pImpl->mbTwoLines = bSet;
794 void SvxFontPrevWindow::SetBrackets(sal_Unicode cStart, sal_Unicode cEnd)
796 pImpl->mcStartBracket = cStart;
797 pImpl->mcEndBracket = cEnd;
800 void SvxFontPrevWindow::SetFontWidthScale( sal_uInt16 n )
802 if (pImpl->SetFontWidthScale(n))
803 Invalidate();
806 void SvxFontPrevWindow::AutoCorrectFontColor()
808 Color aColor(COL_AUTO);
809 if ( pImpl->mxBackColor ) aColor = *pImpl->mxBackColor;
810 const bool bIsDark(aColor.IsDark());
812 aColor = pImpl->maFont.GetColor();
813 if (aColor == COL_AUTO)
814 pImpl->maFont.SetColor( bIsDark ? COL_WHITE : COL_BLACK );
815 aColor = pImpl->maCJKFont.GetColor();
816 if (aColor == COL_AUTO)
817 pImpl->maCJKFont.SetColor( bIsDark ? COL_WHITE : COL_BLACK );
818 aColor = pImpl->maCTLFont.GetColor();
819 if (aColor == COL_AUTO)
820 pImpl->maCTLFont.SetColor( bIsDark ? COL_WHITE : COL_BLACK );
823 void SvxFontPrevWindow::SetFontSize( const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont )
825 sal_uInt16 nWhich;
826 tools::Long nH;
827 if (GetWhich(rSet, nSlot, nWhich))
829 nH = OutputDevice::LogicToLogic(static_cast<const SvxFontHeightItem&>(rSet.Get(nWhich)).GetHeight(),
830 rSet.GetPool()->GetMetric(nWhich),
831 MapUnit::MapTwip);
833 else
834 nH = 240;// as default 12pt
836 rFont.SetFontSize(Size(0, nH));
839 void SvxFontPrevWindow::SetFontLang(const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont)
841 sal_uInt16 nWhich;
842 LanguageType nLang;
843 if( GetWhich( rSet, nSlot, nWhich ) )
844 nLang = static_cast<const SvxLanguageItem&>(rSet.Get(nWhich)).GetLanguage();
845 else
846 nLang = LANGUAGE_NONE;
847 rFont.SetLanguage(nLang);
850 void SvxFontPrevWindow::SetFromItemSet(const SfxItemSet &rSet, bool bPreviewBackgroundToCharacter)
852 sal_uInt16 nWhich;
853 SvxFont& rFont = GetFont();
854 SvxFont& rCJKFont = GetCJKFont();
855 SvxFont& rCTLFont = GetCTLFont();
857 // Preview string
858 if( GetWhich( rSet, SID_CHAR_DLG_PREVIEW_STRING, nWhich ) )
860 const SfxStringItem& rItem = static_cast<const SfxStringItem&>( rSet.Get( nWhich ) );
861 const OUString& aString = rItem.GetValue();
862 if( !aString.isEmpty() )
863 SetPreviewText( aString );
864 else
865 SetFontNameAsPreviewText();
868 // Underline
869 FontLineStyle eUnderline;
870 if( GetWhich( rSet, SID_ATTR_CHAR_UNDERLINE, nWhich ) )
872 const SvxUnderlineItem& rItem = static_cast<const SvxUnderlineItem&>( rSet.Get( nWhich ) );
873 eUnderline = rItem.GetValue();
875 else
876 eUnderline = LINESTYLE_NONE;
878 rFont.SetUnderline( eUnderline );
879 rCJKFont.SetUnderline( eUnderline );
880 rCTLFont.SetUnderline( eUnderline );
882 // Overline
883 FontLineStyle eOverline;
884 if( GetWhich( rSet, SID_ATTR_CHAR_OVERLINE, nWhich ) )
886 const SvxOverlineItem& rItem = static_cast<const SvxOverlineItem&>( rSet.Get( nWhich ) );
887 eOverline = rItem.GetValue();
889 else
890 eOverline = LINESTYLE_NONE;
892 rFont.SetOverline( eOverline );
893 rCJKFont.SetOverline( eOverline );
894 rCTLFont.SetOverline( eOverline );
896 // Strikeout
897 FontStrikeout eStrikeout;
898 if( GetWhich( rSet, SID_ATTR_CHAR_STRIKEOUT, nWhich ) )
900 const SvxCrossedOutItem& rItem = static_cast<const SvxCrossedOutItem&>( rSet.Get( nWhich ) );
901 eStrikeout = rItem.GetValue();
903 else
904 eStrikeout = STRIKEOUT_NONE;
906 rFont.SetStrikeout( eStrikeout );
907 rCJKFont.SetStrikeout( eStrikeout );
908 rCTLFont.SetStrikeout( eStrikeout );
910 // WordLineMode
911 if( GetWhich( rSet, SID_ATTR_CHAR_WORDLINEMODE, nWhich ) )
913 const SvxWordLineModeItem& rItem = static_cast<const SvxWordLineModeItem&>( rSet.Get( nWhich ) );
914 rFont.SetWordLineMode( rItem.GetValue() );
915 rCJKFont.SetWordLineMode( rItem.GetValue() );
916 rCTLFont.SetWordLineMode( rItem.GetValue() );
919 // Emphasis
920 if( GetWhich( rSet, SID_ATTR_CHAR_EMPHASISMARK, nWhich ) )
922 const SvxEmphasisMarkItem& rItem = static_cast<const SvxEmphasisMarkItem&>( rSet.Get( nWhich ) );
923 FontEmphasisMark eMark = rItem.GetEmphasisMark();
924 rFont.SetEmphasisMark( eMark );
925 rCJKFont.SetEmphasisMark( eMark );
926 rCTLFont.SetEmphasisMark( eMark );
929 // Relief
930 if( GetWhich( rSet, SID_ATTR_CHAR_RELIEF, nWhich ) )
932 const SvxCharReliefItem& rItem = static_cast<const SvxCharReliefItem&>( rSet.Get( nWhich ) );
933 FontRelief eFontRelief = rItem.GetValue();
934 rFont.SetRelief( eFontRelief );
935 rCJKFont.SetRelief( eFontRelief );
936 rCTLFont.SetRelief( eFontRelief );
939 // Effects
940 if( GetWhich( rSet, SID_ATTR_CHAR_CASEMAP, nWhich ) )
942 const SvxCaseMapItem& rItem = static_cast<const SvxCaseMapItem&>( rSet.Get( nWhich ) );
943 SvxCaseMap eCaseMap = rItem.GetValue();
944 rFont.SetCaseMap( eCaseMap );
945 rCJKFont.SetCaseMap( eCaseMap );
946 // #i78474# small caps do not exist in CTL fonts
947 rCTLFont.SetCaseMap( eCaseMap == SvxCaseMap::SmallCaps ? SvxCaseMap::NotMapped : eCaseMap );
950 // Outline
951 if( GetWhich( rSet, SID_ATTR_CHAR_CONTOUR, nWhich ) )
953 const SvxContourItem& rItem = static_cast<const SvxContourItem&>( rSet.Get( nWhich ) );
954 bool bOutline = rItem.GetValue();
955 rFont.SetOutline( bOutline );
956 rCJKFont.SetOutline( bOutline );
957 rCTLFont.SetOutline( bOutline );
960 // Shadow
961 if( GetWhich( rSet, SID_ATTR_CHAR_SHADOWED, nWhich ) )
963 const SvxShadowedItem& rItem = static_cast<const SvxShadowedItem&>( rSet.Get( nWhich ) );
964 bool bShadow = rItem.GetValue();
965 rFont.SetShadow( bShadow );
966 rCJKFont.SetShadow( bShadow );
967 rCTLFont.SetShadow( bShadow );
970 // Background
971 bool bTransparent;
972 if( GetWhich( rSet, bPreviewBackgroundToCharacter ? SID_ATTR_BRUSH : SID_ATTR_BRUSH_CHAR, nWhich ) )
974 const SvxBrushItem& rBrush = static_cast<const SvxBrushItem&>( rSet.Get( nWhich ) );
975 const Color& rColor = rBrush.GetColor();
976 bTransparent = rColor.IsTransparent();
977 rFont.SetFillColor( rColor );
978 rCJKFont.SetFillColor( rColor );
979 rCTLFont.SetFillColor( rColor );
981 else
982 bTransparent = true;
984 rFont.SetTransparent( bTransparent );
985 rCJKFont.SetTransparent( bTransparent );
986 rCTLFont.SetTransparent( bTransparent );
988 if( !bPreviewBackgroundToCharacter )
990 bool bBackColorFound = false;
991 if( GetWhich( rSet, SID_ATTR_BRUSH, nWhich ) )
993 const SvxBrushItem& rBrush = static_cast<const SvxBrushItem&>( rSet.Get( nWhich ) );
994 if (GPOS_NONE == rBrush.GetGraphicPos())
996 const Color& rBrushColor = rBrush.GetColor();
997 if (rBrushColor != COL_TRANSPARENT)
999 pImpl->mxBackColor = rBrush.GetColor();
1000 bBackColorFound = true;
1004 if (!bBackColorFound)
1005 pImpl->mxBackColor = svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
1008 // Font
1009 SetPrevFont( rSet, SID_ATTR_CHAR_FONT, rFont );
1010 SetPrevFont( rSet, SID_ATTR_CHAR_CJK_FONT, rCJKFont );
1011 SetPrevFont( rSet, SID_ATTR_CHAR_CTL_FONT, rCTLFont );
1013 // Style
1014 SetPrevFontStyle( rSet, SID_ATTR_CHAR_POSTURE, SID_ATTR_CHAR_WEIGHT, rFont );
1015 SetPrevFontStyle( rSet, SID_ATTR_CHAR_CJK_POSTURE, SID_ATTR_CHAR_CJK_WEIGHT, rCJKFont );
1016 SetPrevFontStyle( rSet, SID_ATTR_CHAR_CTL_POSTURE, SID_ATTR_CHAR_CTL_WEIGHT, rCTLFont );
1018 // Size
1019 SetFontSize( rSet, SID_ATTR_CHAR_FONTHEIGHT, rFont );
1020 SetFontSize( rSet, SID_ATTR_CHAR_CJK_FONTHEIGHT, rCJKFont );
1021 SetFontSize( rSet, SID_ATTR_CHAR_CTL_FONTHEIGHT, rCTLFont );
1023 // Language
1024 SetFontLang( rSet, SID_ATTR_CHAR_LANGUAGE, rFont );
1025 SetFontLang( rSet, SID_ATTR_CHAR_CJK_LANGUAGE, rCJKFont );
1026 SetFontLang( rSet, SID_ATTR_CHAR_CTL_LANGUAGE, rCTLFont );
1028 // Color
1029 if( GetWhich( rSet, SID_ATTR_CHAR_COLOR, nWhich ) )
1031 const SvxColorItem& rItem = static_cast<const SvxColorItem&>( rSet.Get( nWhich ) );
1032 Color aCol( rItem.GetValue() );
1033 rFont.SetColor( aCol );
1035 rCJKFont.SetColor( aCol );
1036 rCTLFont.SetColor( aCol );
1038 AutoCorrectFontColor(); // handle color COL_AUTO
1041 // Kerning
1042 if( GetWhich( rSet, SID_ATTR_CHAR_KERNING, nWhich ) )
1044 const SvxKerningItem& rItem = static_cast<const SvxKerningItem&>( rSet.Get( nWhich ) );
1045 short nKern = static_cast<short>(OutputDevice::LogicToLogic(rItem.GetValue(), rSet.GetPool()->GetMetric(nWhich), MapUnit::MapTwip));
1046 rFont.SetFixKerning( nKern );
1047 rCJKFont.SetFixKerning( nKern );
1048 rCTLFont.SetFixKerning( nKern );
1051 // Escapement
1052 const sal_uInt8 nProp = 100;
1053 short nEsc;
1054 sal_uInt8 nEscProp;
1055 if( GetWhich( rSet, SID_ATTR_CHAR_ESCAPEMENT, nWhich ) )
1057 const SvxEscapementItem& rItem = static_cast<const SvxEscapementItem&>( rSet.Get( nWhich ) );
1058 nEsc = rItem.GetEsc();
1059 nEscProp = rItem.GetProportionalHeight();
1061 if( nEsc == DFLT_ESC_AUTO_SUPER )
1062 nEsc = DFLT_ESC_SUPER;
1063 else if( nEsc == DFLT_ESC_AUTO_SUB )
1064 nEsc = DFLT_ESC_SUB;
1066 else
1068 nEsc = 0;
1069 nEscProp = 100;
1071 SetPrevFontEscapement( rFont, nProp, nEscProp, nEsc );
1072 SetPrevFontEscapement( rCJKFont, nProp, nEscProp, nEsc );
1073 SetPrevFontEscapement( rCTLFont, nProp, nEscProp, nEsc );
1075 // Font width scale
1076 if( GetWhich( rSet, SID_ATTR_CHAR_SCALEWIDTH, nWhich ) )
1078 const SvxCharScaleWidthItem&rItem = static_cast<const SvxCharScaleWidthItem&>( rSet.Get( nWhich ) );
1079 SetFontWidthScale( rItem.GetValue() );
1082 Invalidate();
1085 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */