remove assert looking for new compatibilityMode DOCX
[LibreOffice.git] / svx / source / dialog / fntctrl.cxx
blobad9c5fc62c4969b149da814bb3ff4dee5adde389
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 <optional>
31 #include <svtools/colorcfg.hxx>
32 #include <svtools/sampletext.hxx>
34 #include <svx/fntctrl.hxx>
35 #include <svx/svxids.hrc>
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>
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
67 #define TEXT_WIDTH 80
70 // small helper functions to set fonts
72 namespace
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)
96 if (!nHeight)
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();
121 struct ScriptInfo
123 tools::Long textWidth;
124 SvtScriptType scriptType;
125 sal_Int32 changePos;
126 ScriptInfo(SvtScriptType scrptType, sal_Int32 position)
127 : textWidth(0)
128 , scriptType(scrptType)
129 , changePos(position)
134 } // end anonymous namespace
136 class FontPrevWin_Impl
138 friend class SvxFontPrevWindow;
140 SvxFont maFont;
141 VclPtr<Printer> mpPrinter;
142 bool mbDelPrinter;
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;
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;
164 bool mbTwoLines : 1;
165 bool mbUseFontNameAsText : 1;
166 bool mbTextInited : 1;
168 bool m_bCJKEnabled;
169 bool m_bCTLEnabled;
172 public:
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)
186 m_bCJKEnabled = SvtCJKOptions::IsAnyEnabled();
187 m_bCTLEnabled = SvtCTLOptions::IsCTLFontEnabled();
188 mxBackColor = svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
189 Invalidate100PercentFontWidth();
192 ~FontPrevWin_Impl()
194 if (mbDelPrinter)
195 mpPrinter.disposeAndClear();
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);
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;
270 sal_uInt16 nIdx = 0;
271 sal_Int32 nStart = 0;
272 sal_Int32 nEnd;
273 size_t nCnt = maScriptChanges.size();
275 if (nCnt)
277 nEnd = maScriptChanges[nIdx].changePos;
278 aScript = maScriptChanges[nIdx].scriptType;
280 else
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;
289 mnAscent = 0;
290 tools::Long nCJKAscent = 0;
291 tools::Long nCTLAscent = 0;
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;
304 maScriptChanges[nIdx++].textWidth = nWidth;
305 nTxtWidth += nWidth;
307 switch (aScript)
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);
319 if (nEnd < maText.getLength() && nIdx < nCnt)
321 nStart = nEnd;
322 nEnd = maScriptChanges[nIdx].changePos;
323 aScript = maScriptChanges[nIdx].scriptType;
325 else
326 break;
328 while(true);
330 nHeight -= mnAscent;
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;
346 nHeight += mnAscent;
348 Size aTxtSize(nTxtWidth, nHeight);
349 return aTxtSize;
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.
359 void FontPrevWin_Impl::DrawPrev(vcl::RenderContext& rRenderContext, Printer* _pPrinter, Point &rPt, const SvxFont& rInFont)
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();
368 if (nCnt)
370 nEnd = maScriptChanges[nIdx].changePos;
371 aScript = maScriptChanges[nIdx].scriptType;
373 else
375 nEnd = maText.getLength();
376 aScript = SvtScriptType::LATIN;
380 const SvxFont& rFont = (aScript == SvtScriptType::ASIAN)
381 ? maCJKFont
382 : ((aScript == SvtScriptType::COMPLEX)
383 ? maCTLFont
384 : rInFont);
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)
392 nStart = nEnd;
393 nEnd = maScriptChanges[nIdx].changePos;
394 aScript = maScriptChanges[nIdx].scriptType;
396 else
397 break;
399 while(true);
400 _pPrinter->SetFont(aOldFont);
404 bool FontPrevWin_Impl::SetFontWidthScale(sal_uInt16 nScale)
406 if (mnFontWidthScale != nScale)
408 mnFontWidthScale = nScale;
409 return true;
412 return false;
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)
437 sal_uInt16 nWhich;
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 )
451 sal_uInt16 nWhich;
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();
491 if (pSh)
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);
503 Invalidate();
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();
553 Invalidate();
556 void SvxFontPrevWindow::SetColor(const Color &rColor)
558 pImpl->mxColor = rColor;
559 Invalidate();
562 void SvxFontPrevWindow::ResetColor()
564 pImpl->mxColor.reset();
565 Invalidate();
568 void SvxFontPrevWindow::SetTextLineColor(const Color &rColor)
570 pImpl->mxTextLineColor = rColor;
571 Invalidate();
574 void SvxFontPrevWindow::SetOverlineColor(const Color &rColor)
576 pImpl->mxOverlineColor = rColor;
577 Invalidate();
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;
593 if (!IsEnabled())
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);
603 else
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);
625 else
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);
653 if (nSpaceIdx != -1)
654 pImpl->maText = pImpl->maText.copy(0, nSpaceIdx);
655 else
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);
685 if (pImpl->mxColor)
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;
708 nY += nStdAscent;
710 if (IsTwoLines())
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);
754 _nX += nTextWidth;
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);
763 else
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))
799 Invalidate();
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 )
821 sal_uInt16 nWhich;
822 tools::Long nH;
823 if (GetWhich(rSet, nSlot, nWhich))
825 nH = OutputDevice::LogicToLogic(static_cast<const SvxFontHeightItem&>(rSet.Get(nWhich)).GetHeight(),
826 rSet.GetPool()->GetMetric(nWhich),
827 MapUnit::MapTwip);
829 else
830 nH = 240;// as default 12pt
832 rFont.SetFontSize(Size(0, nH));
835 void SvxFontPrevWindow::SetFontLang(const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont)
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);
846 void SvxFontPrevWindow::SetFromItemSet(const SfxItemSet &rSet, bool bPreviewBackgroundToCharacter)
848 sal_uInt16 nWhich;
849 SvxFont& rFont = GetFont();
850 SvxFont& rCJKFont = GetCJKFont();
851 SvxFont& rCTLFont = GetCTLFont();
853 // Preview string
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 );
860 else
861 SetFontNameAsPreviewText();
864 // Underline
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();
871 else
872 eUnderline = LINESTYLE_NONE;
874 rFont.SetUnderline( eUnderline );
875 rCJKFont.SetUnderline( eUnderline );
876 rCTLFont.SetUnderline( eUnderline );
878 // Overline
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();
885 else
886 eOverline = LINESTYLE_NONE;
888 rFont.SetOverline( eOverline );
889 rCJKFont.SetOverline( eOverline );
890 rCTLFont.SetOverline( eOverline );
892 // Strikeout
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();
899 else
900 eStrikeout = STRIKEOUT_NONE;
902 rFont.SetStrikeout( eStrikeout );
903 rCJKFont.SetStrikeout( eStrikeout );
904 rCTLFont.SetStrikeout( eStrikeout );
906 // WordLineMode
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() );
915 // Emphasis
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 );
925 // Relief
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 );
935 // Effects
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 );
946 // Outline
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 );
956 // Shadow
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 );
966 // Background
967 bool bTransparent;
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 );
977 else
978 bTransparent = true;
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;
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 );
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 );
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 );
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 );
1024 // Color
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
1037 // Kerning
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 );
1047 // Escapement
1048 const sal_uInt8 nProp = 100;
1049 short nEsc;
1050 sal_uInt8 nEscProp;
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;
1062 else
1064 nEsc = 0;
1065 nEscProp = 100;
1067 SetPrevFontEscapement( rFont, nProp, nEscProp, nEsc );
1068 SetPrevFontEscapement( rCJKFont, nProp, nEscProp, nEsc );
1069 SetPrevFontEscapement( rCTLFont, nProp, nEscProp, nEsc );
1071 // Font width scale
1072 if( GetWhich( rSet, SID_ATTR_CHAR_SCALEWIDTH, nWhich ) )
1074 const SvxCharScaleWidthItem&rItem = static_cast<const SvxCharScaleWidthItem&>( rSet.Get( nWhich ) );
1075 SetFontWidthScale( rItem.GetValue() );
1078 Invalidate();
1081 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */