summaryrefslogtreecommitdiffstats
path: root/svx/source/dialog/fntctrl.cxx
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--svx/source/dialog/fntctrl.cxx1089
1 files changed, 1089 insertions, 0 deletions
diff --git a/svx/source/dialog/fntctrl.cxx b/svx/source/dialog/fntctrl.cxx
new file mode 100644
index 000000000..393fc4e68
--- /dev/null
+++ b/svx/source/dialog/fntctrl.cxx
@@ -0,0 +1,1089 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sfx2/dialoghelper.hxx>
+#include <sfx2/viewsh.hxx>
+#include <sfx2/printer.hxx>
+#include <vcl/metric.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/settings.hxx>
+#include <unicode/uchar.h>
+#include <com/sun/star/uno/Reference.h>
+#include <com/sun/star/i18n/BreakIterator.hpp>
+#include <comphelper/processfactory.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hpp>
+
+#include <vector>
+#include <deque>
+#include <optional>
+#include <svtools/colorcfg.hxx>
+#include <svtools/sampletext.hxx>
+
+#include <svx/fntctrl.hxx>
+#include <svx/svxids.hrc>
+
+// Item set includes
+#include <svl/itemset.hxx>
+#include <svl/itempool.hxx>
+#include <svl/stritem.hxx>
+#include <svl/cjkoptions.hxx>
+#include <svl/ctloptions.hxx>
+
+#include <editeng/colritem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/editids.hrc>
+#include <editeng/postitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/contouritem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/escapementitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/emphasismarkitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/langitem.hxx>
+
+//TODO: remove this and calculate off the actual size of text, not
+//an arbitrary number of characters
+#define TEXT_WIDTH 80
+
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using ::com::sun::star::i18n::XBreakIterator;
+using ::com::sun::star::i18n::BreakIterator;
+
+
+// small helper functions to set fonts
+
+namespace
+{
+void scaleFontWidth(vcl::Font& rFont, vcl::RenderContext const & rRenderContext,tools::Long& n100PercentFont)
+{
+ rFont.SetAverageFontWidth(0);
+ n100PercentFont = rRenderContext.GetFontMetric(rFont).GetAverageFontWidth();
+}
+
+void initFont(vcl::Font& rFont)
+{
+ rFont.SetTransparent(true);
+ rFont.SetAlignment(ALIGN_BASELINE);
+}
+
+void setFontSize(vcl::Font& rFont)
+{
+ Size aSize(rFont.GetFontSize());
+ aSize.setHeight( (aSize.Height() * 3) / 5 );
+ aSize.setWidth( (aSize.Width() * 3) / 5 );
+ rFont.SetFontSize(aSize);
+}
+
+void calcFontHeightAnyAscent(vcl::RenderContext& rRenderContext, const vcl::Font& rFont, tools::Long& nHeight, tools::Long& nAscent)
+{
+ if (!nHeight)
+ {
+ rRenderContext.SetFont(rFont);
+ FontMetric aMetric(rRenderContext.GetFontMetric());
+ nHeight = aMetric.GetLineHeight();
+ nAscent = aMetric.GetAscent();
+ }
+}
+
+void setFont(const SvxFont& rNewFont, SvxFont& rImplFont)
+{
+ rImplFont = rNewFont;
+ rImplFont.SetTransparent(true);
+ rImplFont.SetAlignment(ALIGN_BASELINE);
+}
+
+/*
+ * removes line feeds and carriage returns from string
+ * returns if param is empty
+ */
+OUString removeCRLF(const OUString& rText)
+{
+ return rText.replace(0xa, ' ').replace(0xd, ' ').trim();
+}
+
+} // end anonymous namespace
+
+class FontPrevWin_Impl
+{
+ friend class SvxFontPrevWindow;
+
+ SvxFont maFont;
+ VclPtr<Printer> mpPrinter;
+ bool mbDelPrinter;
+
+ Reference <XBreakIterator> mxBreak;
+ std::vector<tools::Long> maTextWidth;
+ std::deque<sal_Int32> maScriptChg;
+ std::vector<sal_uInt16> maScriptType;
+ SvxFont maCJKFont;
+ SvxFont maCTLFont;
+ OUString maText;
+ OUString maScriptText;
+ std::optional<Color> mxColor;
+ std::optional<Color> mxBackColor;
+ std::optional<Color> mxTextLineColor;
+ std::optional<Color> mxOverlineColor;
+ tools::Long mnAscent;
+ sal_Unicode mcStartBracket;
+ sal_Unicode mcEndBracket;
+
+ tools::Long mn100PercentFontWidth; // initial -1 -> not set yet
+ tools::Long mn100PercentFontWidthCJK;
+ tools::Long mn100PercentFontWidthCTL;
+ sal_uInt16 mnFontWidthScale;
+
+ bool mbSelection : 1;
+ bool mbGetSelection : 1;
+ bool mbTwoLines : 1;
+ bool mbUseFontNameAsText : 1;
+ bool mbTextInited : 1;
+
+ bool m_bCJKEnabled;
+ bool m_bCTLEnabled;
+
+
+public:
+ FontPrevWin_Impl() :
+ mpPrinter(nullptr),
+ mbDelPrinter(false),
+ mnAscent(0),
+ mcStartBracket(0),
+ mcEndBracket(0),
+ mnFontWidthScale(100),
+ mbSelection(false),
+ mbGetSelection(false),
+ mbTwoLines(false),
+ mbUseFontNameAsText(false),
+ mbTextInited(false)
+ {
+ m_bCJKEnabled = SvtCJKOptions::IsAnyEnabled();
+ m_bCTLEnabled = SvtCTLOptions().IsCTLFontEnabled();
+ mxBackColor = svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
+ Invalidate100PercentFontWidth();
+ }
+
+ ~FontPrevWin_Impl()
+ {
+ if (mbDelPrinter)
+ mpPrinter.disposeAndClear();
+ }
+
+ void CheckScript();
+ Size CalcTextSize(vcl::RenderContext& rRenderContext, OutputDevice const * pPrinter, const SvxFont& rFont);
+ void DrawPrev(vcl::RenderContext& rRenderContext, Printer* pPrinter, Point& rPt, const SvxFont& rFont);
+
+ bool SetFontWidthScale(sal_uInt16 nScaleInPercent);
+ inline void Invalidate100PercentFontWidth();
+ inline bool Is100PercentFontWidthValid() const;
+ void ScaleFontWidth(vcl::RenderContext const & rRenderContext);
+ // scales rNonCJKFont and aCJKFont depending on nFontWidthScale and
+ // sets the 100%-Font-Widths
+};
+
+inline void FontPrevWin_Impl::Invalidate100PercentFontWidth()
+{
+ mn100PercentFontWidth = mn100PercentFontWidthCJK = mn100PercentFontWidthCTL = -1;
+}
+
+inline bool FontPrevWin_Impl::Is100PercentFontWidthValid() const
+{
+ DBG_ASSERT( ( mn100PercentFontWidth == -1 && mn100PercentFontWidthCJK == -1 ) ||
+ ( mn100PercentFontWidth != -1 && mn100PercentFontWidthCJK != -1 ) ||
+ ( mn100PercentFontWidth == -1 && mn100PercentFontWidthCTL == -1 ) ||
+ ( mn100PercentFontWidth != -1 && mn100PercentFontWidthCTL != -1 ),
+ "*FontPrevWin_Impl::Is100PercentFontWidthValid(): 100PercentFontWidth's not synchronous" );
+ return mn100PercentFontWidth != -1;
+}
+
+/*
+ * evaluates the scripttypes of the actual string.
+ * Afterwards the positions of script change are notified in aScriptChg,
+ * the scripttypes in aScriptType.
+ * The aTextWidth array will be filled with zero.
+ */
+void FontPrevWin_Impl::CheckScript()
+{
+ assert(!maText.isEmpty()); // must have a preview text here!
+ if (maText == maScriptText)
+ {
+ return; // already initialized
+ }
+
+ maScriptText = maText;
+
+ maScriptChg.clear();
+ maScriptType.clear();
+ maTextWidth.clear();
+
+ if (!mxBreak.is())
+ {
+ Reference<XComponentContext> xContext = ::comphelper::getProcessComponentContext();
+ mxBreak = BreakIterator::create(xContext);
+ }
+
+ sal_uInt16 nScript = 0;
+ sal_Int32 nChg = 0;
+
+ while (nChg < maText.getLength())
+ {
+ nScript = mxBreak->getScriptType(maText, nChg);
+ nChg = mxBreak->endOfScript(maText, nChg, nScript);
+ if (nChg < maText.getLength() && nChg > 0 &&
+ (css::i18n::ScriptType::WEAK ==
+ mxBreak->getScriptType(maText, nChg - 1)))
+ {
+ int8_t nType = u_charType(maText[nChg]);
+ if (nType == U_NON_SPACING_MARK || nType == U_ENCLOSING_MARK ||
+ nType == U_COMBINING_SPACING_MARK)
+ {
+ maScriptChg.push_back(nChg - 1);
+ }
+ else
+ {
+ maScriptChg.push_back(nChg);
+ }
+ }
+ else
+ {
+ maScriptChg.push_back(nChg);
+ }
+ maScriptType.push_back(nScript);
+ maTextWidth.push_back(0);
+ }
+}
+
+/*
+ * Size FontPrevWin_Impl::CalcTextSize(..)
+ * fills the aTextWidth array with the text width of every part
+ * of the actual string without a script change inside.
+ * For Latin parts the given rFont will be used,
+ * for Asian parts the aCJKFont.
+ * The returned size contains the whole string.
+ * The member nAscent is calculated to the maximal ascent of all used fonts.
+ */
+
+Size FontPrevWin_Impl::CalcTextSize(vcl::RenderContext& rRenderContext, OutputDevice const * _pPrinter, const SvxFont& rInFont)
+{
+ sal_uInt16 nScript;
+ sal_uInt16 nIdx = 0;
+ sal_Int32 nStart = 0;
+ sal_Int32 nEnd;
+ size_t nCnt = maScriptChg.size();
+
+ if (nCnt)
+ {
+ nEnd = maScriptChg[nIdx];
+ nScript = maScriptType[nIdx];
+ }
+ else
+ {
+ nEnd = maText.getLength();
+ nScript = css::i18n::ScriptType::LATIN;
+ }
+ tools::Long nTxtWidth = 0;
+ tools::Long nCJKHeight = 0;
+ tools::Long nCTLHeight = 0;
+ tools::Long nHeight = 0;
+ mnAscent = 0;
+ tools::Long nCJKAscent = 0;
+ tools::Long nCTLAscent = 0;
+
+ do
+ {
+ const SvxFont& rFont = (nScript == css::i18n::ScriptType::ASIAN) ?
+ maCJKFont :
+ ((nScript == css::i18n::ScriptType::COMPLEX) ?
+ maCTLFont :
+ rInFont);
+ tools::Long nWidth = rFont.GetTextSize(*_pPrinter, maText, nStart, nEnd - nStart).Width();
+ if (nIdx >= maTextWidth.size())
+ break;
+
+ maTextWidth[nIdx++] = nWidth;
+ nTxtWidth += nWidth;
+
+ switch (nScript)
+ {
+ case css::i18n::ScriptType::ASIAN:
+ calcFontHeightAnyAscent(rRenderContext, maCJKFont, nCJKHeight, nCJKAscent);
+ break;
+ case css::i18n::ScriptType::COMPLEX:
+ calcFontHeightAnyAscent(rRenderContext, maCTLFont, nCTLHeight, nCTLAscent);
+ break;
+ default:
+ calcFontHeightAnyAscent(rRenderContext, rFont, nHeight, mnAscent);
+ }
+
+ if (nEnd < maText.getLength() && nIdx < nCnt)
+ {
+ nStart = nEnd;
+ nEnd = maScriptChg[nIdx];
+ nScript = maScriptType[nIdx];
+ }
+ else
+ break;
+ }
+ while(true);
+
+ nHeight -= mnAscent;
+ nCJKHeight -= nCJKAscent;
+ nCTLHeight -= nCTLAscent;
+
+ if (nHeight < nCJKHeight)
+ nHeight = nCJKHeight;
+
+ if (mnAscent < nCJKAscent)
+ mnAscent = nCJKAscent;
+
+ if (nHeight < nCTLHeight)
+ nHeight = nCTLHeight;
+
+ if (mnAscent < nCTLAscent)
+ mnAscent = nCTLAscent;
+
+ nHeight += mnAscent;
+
+ Size aTxtSize(nTxtWidth, nHeight);
+ return aTxtSize;
+}
+
+/*
+ * void FontPrevWin_Impl::DrawPrev(..)
+ * calls SvxFont::DrawPrev(..) for every part of the string without a script
+ * change inside, for Asian parts the aCJKFont will be used, otherwise the
+ * given rFont.
+ */
+
+void FontPrevWin_Impl::DrawPrev(vcl::RenderContext& rRenderContext, Printer* _pPrinter, Point &rPt, const SvxFont& rInFont)
+{
+ vcl::Font aOldFont = _pPrinter->GetFont();
+ sal_uInt16 nScript;
+ sal_uInt16 nIdx = 0;
+ sal_Int32 nStart = 0;
+ sal_Int32 nEnd;
+ size_t nCnt = maScriptChg.size();
+ if (nCnt)
+ {
+ nEnd = maScriptChg[nIdx];
+ nScript = maScriptType[nIdx];
+ }
+ else
+ {
+ nEnd = maText.getLength();
+ nScript = css::i18n::ScriptType::LATIN;
+ }
+ do
+ {
+ const SvxFont& rFont = (nScript == css::i18n::ScriptType::ASIAN)
+ ? maCJKFont
+ : ((nScript == css::i18n::ScriptType::COMPLEX)
+ ? maCTLFont
+ : rInFont);
+ _pPrinter->SetFont(rFont);
+
+ rFont.DrawPrev(&rRenderContext, _pPrinter, rPt, maText, nStart, nEnd - nStart);
+
+ rPt.AdjustX(maTextWidth[nIdx++] );
+ if (nEnd < maText.getLength() && nIdx < nCnt)
+ {
+ nStart = nEnd;
+ nEnd = maScriptChg[nIdx];
+ nScript = maScriptType[nIdx];
+ }
+ else
+ break;
+ }
+ while(true);
+ _pPrinter->SetFont(aOldFont);
+}
+
+
+bool FontPrevWin_Impl::SetFontWidthScale(sal_uInt16 nScale)
+{
+ if (mnFontWidthScale != nScale)
+ {
+ mnFontWidthScale = nScale;
+ return true;
+ }
+
+ return false;
+}
+
+void FontPrevWin_Impl::ScaleFontWidth(vcl::RenderContext const & rOutDev)
+{
+ if (!Is100PercentFontWidthValid())
+ {
+ scaleFontWidth(maFont, rOutDev, mn100PercentFontWidth);
+ scaleFontWidth(maCJKFont, rOutDev, mn100PercentFontWidthCJK);
+ scaleFontWidth(maCTLFont, rOutDev, mn100PercentFontWidthCTL);
+ }
+
+ maFont.SetAverageFontWidth(mn100PercentFontWidth * mnFontWidthScale / 100);
+ maCJKFont.SetAverageFontWidth(mn100PercentFontWidthCJK * mnFontWidthScale / 100);
+ maCTLFont.SetAverageFontWidth(mn100PercentFontWidthCTL * mnFontWidthScale / 100);
+}
+
+static bool GetWhich (const SfxItemSet& rSet, sal_uInt16 nSlot, sal_uInt16& rWhich)
+{
+ rWhich = rSet.GetPool()->GetWhich(nSlot);
+ return rSet.GetItemState(rWhich) >= SfxItemState::DEFAULT;
+}
+
+static void SetPrevFont(const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont)
+{
+ sal_uInt16 nWhich;
+ if (GetWhich(rSet, nSlot, nWhich))
+ {
+ const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(rSet.Get(nWhich));
+ rFont.SetFamily(rFontItem.GetFamily());
+ rFont.SetFamilyName(rFontItem.GetFamilyName());
+ rFont.SetPitch(rFontItem.GetPitch());
+ rFont.SetCharSet(rFontItem.GetCharSet());
+ rFont.SetStyleName(rFontItem.GetStyleName());
+ }
+}
+
+static void SetPrevFontStyle( const SfxItemSet& rSet, sal_uInt16 nPosture, sal_uInt16 nWeight, SvxFont& rFont )
+{
+ sal_uInt16 nWhich;
+ if( GetWhich( rSet, nPosture, nWhich ) )
+ {
+ const SvxPostureItem& rItem = static_cast<const SvxPostureItem&>( rSet.Get( nWhich ) );
+ rFont.SetItalic( rItem.GetValue() != ITALIC_NONE ? ITALIC_NORMAL : ITALIC_NONE );
+ }
+
+ if( GetWhich( rSet, nWeight, nWhich ) )
+ {
+ const SvxWeightItem& rItem = static_cast<const SvxWeightItem&>( rSet.Get( nWhich ) );
+ rFont.SetWeight( rItem.GetValue() != WEIGHT_NORMAL ? WEIGHT_BOLD : WEIGHT_NORMAL );
+ }
+}
+
+static void SetPrevFontEscapement(SvxFont& rFont, sal_uInt8 nProp, sal_uInt8 nEscProp, short nEsc)
+{
+ rFont.SetPropr(nProp);
+ rFont.SetProprRel(nEscProp);
+ rFont.SetEscapement(nEsc);
+}
+
+void SvxFontPrevWindow::ApplySettings(vcl::RenderContext& rRenderContext)
+{
+ rRenderContext.SetTextColor( svtools::ColorConfig().GetColorValue(svtools::FONTCOLOR).nColor );
+ rRenderContext.SetBackground( svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor );
+}
+
+void SvxFontPrevWindow::SetDrawingArea(weld::DrawingArea* pDrawingArea)
+{
+ CustomWidgetController::SetDrawingArea(pDrawingArea);
+ Size aPrefSize(getPreviewStripSize(pDrawingArea->get_ref_device()));
+ pDrawingArea->set_size_request(aPrefSize.Width(), aPrefSize.Height());
+
+ pImpl.reset(new FontPrevWin_Impl);
+ SfxViewShell* pSh = SfxViewShell::Current();
+
+ if (pSh)
+ pImpl->mpPrinter = pSh->GetPrinter();
+
+ if (!pImpl->mpPrinter)
+ {
+ pImpl->mpPrinter = VclPtr<Printer>::Create();
+ pImpl->mbDelPrinter = true;
+ }
+ initFont(pImpl->maFont);
+ initFont(pImpl->maCJKFont);
+ initFont(pImpl->maCTLFont);
+
+ Invalidate();
+}
+
+SvxFontPrevWindow::SvxFontPrevWindow()
+{
+}
+
+SvxFontPrevWindow::~SvxFontPrevWindow()
+{
+}
+
+SvxFont& SvxFontPrevWindow::GetCTLFont()
+{
+ return pImpl->maCTLFont;
+}
+
+SvxFont& SvxFontPrevWindow::GetCJKFont()
+{
+ return pImpl->maCJKFont;
+}
+
+SvxFont& SvxFontPrevWindow::GetFont()
+{
+ pImpl->Invalidate100PercentFontWidth(); // because the user might change the size
+ return pImpl->maFont;
+}
+
+const SvxFont& SvxFontPrevWindow::GetFont() const
+{
+ return pImpl->maFont;
+}
+
+void SvxFontPrevWindow::SetPreviewText( const OUString& rString )
+{
+ pImpl->maText = rString;
+ pImpl->mbTextInited = true;
+}
+
+void SvxFontPrevWindow::SetFontNameAsPreviewText()
+{
+ pImpl->mbUseFontNameAsText = true;
+}
+
+void SvxFontPrevWindow::SetFont( const SvxFont& rNormalOutFont, const SvxFont& rCJKOutFont, const SvxFont& rCTLFont )
+{
+ setFont(rNormalOutFont, pImpl->maFont);
+ setFont(rCJKOutFont, pImpl->maCJKFont);
+ setFont(rCTLFont, pImpl->maCTLFont);
+
+ pImpl->Invalidate100PercentFontWidth();
+ Invalidate();
+}
+
+void SvxFontPrevWindow::SetColor(const Color &rColor)
+{
+ pImpl->mxColor = rColor;
+ Invalidate();
+}
+
+void SvxFontPrevWindow::ResetColor()
+{
+ pImpl->mxColor.reset();
+ Invalidate();
+}
+
+void SvxFontPrevWindow::SetTextLineColor(const Color &rColor)
+{
+ pImpl->mxTextLineColor = rColor;
+ Invalidate();
+}
+
+void SvxFontPrevWindow::SetOverlineColor(const Color &rColor)
+{
+ pImpl->mxOverlineColor = rColor;
+ Invalidate();
+}
+
+void SvxFontPrevWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle&)
+{
+ rRenderContext.Push(vcl::PushFlags::ALL);
+ rRenderContext.SetMapMode(MapMode(MapUnit::MapTwip));
+
+ ApplySettings(rRenderContext);
+
+ Printer* pPrinter = pImpl->mpPrinter;
+ const SvxFont& rFont = pImpl->maFont;
+ const SvxFont& rCJKFont = pImpl->maCJKFont;
+ const SvxFont& rCTLFont = pImpl->maCTLFont;
+
+ if (!IsEnabled())
+ {
+ const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
+ const Size aLogSize(rRenderContext.GetOutputSize());
+
+ tools::Rectangle aRect(Point(0, 0), aLogSize);
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(rStyleSettings.GetWindowColor());
+ rRenderContext.DrawRect(aRect);
+ }
+ else
+ {
+ if (!pImpl->mbSelection && !pImpl->mbTextInited)
+ {
+ using namespace css::i18n::ScriptType;
+
+ SfxViewShell* pSh = SfxViewShell::Current();
+
+ if (pSh && !pImpl->mbGetSelection && !pImpl->mbUseFontNameAsText)
+ {
+ pImpl->maText = removeCRLF(pSh->GetSelectionText(/*bCompleteWords*/false, /*bOnlyASample*/true));
+ pImpl->mbGetSelection = true;
+ pImpl->mbSelection = !(pImpl->maText.isEmpty());
+ }
+
+ if (!pImpl->mbSelection || pImpl->mbUseFontNameAsText)
+ {
+ //If we're showing multiple sample texts, then they're all
+ //sample texts. If only showing Latin, continue to use
+ //the fontname as the preview
+ if ((pImpl->m_bCJKEnabled) || (pImpl->m_bCTLEnabled))
+ pImpl->maText = makeRepresentativeTextForFont(LATIN, rFont);
+ else
+ pImpl->maText = rFont.GetFamilyName();
+
+ if (pImpl->m_bCJKEnabled)
+ {
+ if (!pImpl->maText.isEmpty())
+ pImpl->maText += " ";
+ pImpl->maText += makeRepresentativeTextForFont(ASIAN, rCJKFont);
+
+ }
+ if (pImpl->m_bCTLEnabled)
+ {
+ if (!pImpl->maText.isEmpty())
+ pImpl->maText += " ";
+ pImpl->maText += makeRepresentativeTextForFont(COMPLEX, rCTLFont);
+ }
+ }
+
+ if (pImpl->maText.isEmpty())
+ { // fdo#58427: still no text? let's try that one...
+ pImpl->maText = makeRepresentativeTextForFont(LATIN, rFont);
+ }
+
+ pImpl->maText = removeCRLF(pImpl->maText);
+
+ if (pImpl->maText.getLength() > (TEXT_WIDTH - 1))
+ {
+ const sal_Int32 nSpaceIdx = pImpl->maText.indexOf(" ", TEXT_WIDTH);
+ if (nSpaceIdx != -1)
+ pImpl->maText = pImpl->maText.copy(0, nSpaceIdx);
+ else
+ pImpl->maText = pImpl->maText.copy(0, (TEXT_WIDTH - 1));
+ }
+ }
+
+ // calculate text width scaling
+ pImpl->ScaleFontWidth(rRenderContext);
+
+ pImpl->CheckScript();
+ Size aTxtSize = pImpl->CalcTextSize(rRenderContext, pPrinter, rFont);
+
+ const Size aLogSize(rRenderContext.GetOutputSize());
+
+ tools::Long nX = aLogSize.Width() / 2 - aTxtSize.Width() / 2;
+ tools::Long nY = aLogSize.Height() / 2 - aTxtSize.Height() / 2;
+
+ if (nY + pImpl->mnAscent > aLogSize.Height())
+ nY = aLogSize.Height() - pImpl->mnAscent;
+
+ if (pImpl->mxBackColor)
+ {
+ tools::Rectangle aRect(Point(0, 0), aLogSize);
+ Color aLineCol = rRenderContext.GetLineColor();
+ Color aFillCol = rRenderContext.GetFillColor();
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(*pImpl->mxBackColor);
+ rRenderContext.DrawRect(aRect);
+ rRenderContext.SetLineColor(aLineCol);
+ rRenderContext.SetFillColor(aFillCol);
+ }
+ if (pImpl->mxColor)
+ {
+ tools::Rectangle aRect(Point(nX, nY), aTxtSize);
+ Color aLineCol = rRenderContext.GetLineColor();
+ Color aFillCol = rRenderContext.GetFillColor();
+ rRenderContext.SetLineColor();
+ rRenderContext.SetFillColor(*pImpl->mxColor);
+ rRenderContext.DrawRect(aRect);
+ rRenderContext.SetLineColor(aLineCol);
+ rRenderContext.SetFillColor(aFillCol);
+ }
+
+ if (pImpl->mxTextLineColor)
+ {
+ rRenderContext.SetTextLineColor(*pImpl->mxTextLineColor);
+ }
+
+ if (pImpl->mxOverlineColor)
+ {
+ rRenderContext.SetOverlineColor(*pImpl->mxOverlineColor);
+ }
+
+ tools::Long nStdAscent = pImpl->mnAscent;
+ nY += nStdAscent;
+
+ if (IsTwoLines())
+ {
+ SvxFont aSmallFont(rFont);
+ Size aOldSize = pImpl->maCJKFont.GetFontSize();
+ setFontSize(aSmallFont);
+ setFontSize(pImpl->maCJKFont);
+
+ tools::Long nStartBracketWidth = 0;
+ tools::Long nEndBracketWidth = 0;
+ tools::Long nTextWidth = 0;
+ if (pImpl->mcStartBracket)
+ {
+ OUString sBracket(pImpl->mcStartBracket);
+ nStartBracketWidth = rFont.GetTextSize(*pPrinter, sBracket).Width();
+ }
+ if (pImpl->mcEndBracket)
+ {
+ OUString sBracket(pImpl->mcEndBracket);
+ nEndBracketWidth = rFont.GetTextSize(*pPrinter, sBracket).Width();
+ }
+ nTextWidth = pImpl->CalcTextSize(rRenderContext, pPrinter, aSmallFont).Width();
+ tools::Long nResultWidth = nStartBracketWidth;
+ nResultWidth += nEndBracketWidth;
+ nResultWidth += nTextWidth;
+
+ tools::Long _nX = (aLogSize.Width() - nResultWidth) / 2;
+ rRenderContext.DrawLine(Point(0, nY), Point(_nX, nY));
+ rRenderContext.DrawLine(Point(_nX + nResultWidth, nY), Point(aLogSize.Width(), nY));
+
+ tools::Long nSmallAscent = pImpl->mnAscent;
+ tools::Long nOffset = (nStdAscent - nSmallAscent) / 2;
+
+ if (pImpl->mcStartBracket)
+ {
+ OUString sBracket(pImpl->mcStartBracket);
+ rFont.DrawPrev(&rRenderContext, pPrinter, Point(_nX, nY - nOffset - 4), sBracket);
+ _nX += nStartBracketWidth;
+ }
+
+ Point aTmpPoint1(_nX, nY - nSmallAscent - 2);
+ Point aTmpPoint2(_nX, nY);
+ pImpl->DrawPrev(rRenderContext, pPrinter, aTmpPoint1, aSmallFont);
+ pImpl->DrawPrev(rRenderContext, pPrinter, aTmpPoint2, aSmallFont);
+
+ _nX += nTextWidth;
+ if (pImpl->mcEndBracket)
+ {
+ Point aTmpPoint( _nX + 1, nY - nOffset - 4);
+ OUString sBracket(pImpl->mcEndBracket);
+ rFont.DrawPrev(&rRenderContext, pPrinter, aTmpPoint, sBracket);
+ }
+ pImpl->maCJKFont.SetFontSize(aOldSize);
+ }
+ else
+ {
+
+ Color aLineCol = rRenderContext.GetLineColor();
+
+ rRenderContext.SetLineColor(rFont.GetColor());
+ rRenderContext.DrawLine(Point(0, nY), Point(nX, nY));
+ rRenderContext.DrawLine(Point(nX + aTxtSize.Width(), nY), Point(aLogSize.Width(), nY));
+ rRenderContext.SetLineColor(aLineCol);
+
+ Point aTmpPoint(nX, nY);
+ pImpl->DrawPrev(rRenderContext, pPrinter, aTmpPoint, rFont);
+ }
+ }
+ rRenderContext.Pop();
+}
+
+bool SvxFontPrevWindow::IsTwoLines() const
+{
+ return pImpl->mbTwoLines;
+}
+
+void SvxFontPrevWindow::SetTwoLines(bool bSet)
+{
+ pImpl->mbTwoLines = bSet;
+}
+
+void SvxFontPrevWindow::SetBrackets(sal_Unicode cStart, sal_Unicode cEnd)
+{
+ pImpl->mcStartBracket = cStart;
+ pImpl->mcEndBracket = cEnd;
+}
+
+void SvxFontPrevWindow::SetFontWidthScale( sal_uInt16 n )
+{
+ if (pImpl->SetFontWidthScale(n))
+ Invalidate();
+}
+
+void SvxFontPrevWindow::AutoCorrectFontColor()
+{
+ Color aColor(COL_AUTO);
+ if ( pImpl->mxBackColor ) aColor = *pImpl->mxBackColor;
+ const bool bIsDark(aColor.IsDark());
+
+ aColor = pImpl->maFont.GetColor();
+ if (aColor == COL_AUTO)
+ pImpl->maFont.SetColor( bIsDark ? COL_WHITE : COL_BLACK );
+ aColor = pImpl->maCJKFont.GetColor();
+ if (aColor == COL_AUTO)
+ pImpl->maCJKFont.SetColor( bIsDark ? COL_WHITE : COL_BLACK );
+ aColor = pImpl->maCTLFont.GetColor();
+ if (aColor == COL_AUTO)
+ pImpl->maCTLFont.SetColor( bIsDark ? COL_WHITE : COL_BLACK );
+}
+
+void SvxFontPrevWindow::SetFontSize( const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont )
+{
+ sal_uInt16 nWhich;
+ tools::Long nH;
+ if (GetWhich(rSet, nSlot, nWhich))
+ {
+ nH = OutputDevice::LogicToLogic(static_cast<const SvxFontHeightItem&>(rSet.Get(nWhich)).GetHeight(),
+ rSet.GetPool()->GetMetric(nWhich),
+ MapUnit::MapTwip);
+ }
+ else
+ nH = 240;// as default 12pt
+
+ rFont.SetFontSize(Size(0, nH));
+}
+
+void SvxFontPrevWindow::SetFontLang(const SfxItemSet& rSet, sal_uInt16 nSlot, SvxFont& rFont)
+{
+ sal_uInt16 nWhich;
+ LanguageType nLang;
+ if( GetWhich( rSet, nSlot, nWhich ) )
+ nLang = static_cast<const SvxLanguageItem&>(rSet.Get(nWhich)).GetLanguage();
+ else
+ nLang = LANGUAGE_NONE;
+ rFont.SetLanguage(nLang);
+}
+
+void SvxFontPrevWindow::SetFromItemSet(const SfxItemSet &rSet, bool bPreviewBackgroundToCharacter)
+{
+ sal_uInt16 nWhich;
+ SvxFont& rFont = GetFont();
+ SvxFont& rCJKFont = GetCJKFont();
+ SvxFont& rCTLFont = GetCTLFont();
+
+ // Preview string
+ if( GetWhich( rSet, SID_CHAR_DLG_PREVIEW_STRING, nWhich ) )
+ {
+ const SfxStringItem& rItem = static_cast<const SfxStringItem&>( rSet.Get( nWhich ) );
+ const OUString& aString = rItem.GetValue();
+ if( !aString.isEmpty() )
+ SetPreviewText( aString );
+ else
+ SetFontNameAsPreviewText();
+ }
+
+ // Underline
+ FontLineStyle eUnderline;
+ if( GetWhich( rSet, SID_ATTR_CHAR_UNDERLINE, nWhich ) )
+ {
+ const SvxUnderlineItem& rItem = static_cast<const SvxUnderlineItem&>( rSet.Get( nWhich ) );
+ eUnderline = rItem.GetValue();
+ }
+ else
+ eUnderline = LINESTYLE_NONE;
+
+ rFont.SetUnderline( eUnderline );
+ rCJKFont.SetUnderline( eUnderline );
+ rCTLFont.SetUnderline( eUnderline );
+
+ // Overline
+ FontLineStyle eOverline;
+ if( GetWhich( rSet, SID_ATTR_CHAR_OVERLINE, nWhich ) )
+ {
+ const SvxOverlineItem& rItem = static_cast<const SvxOverlineItem&>( rSet.Get( nWhich ) );
+ eOverline = rItem.GetValue();
+ }
+ else
+ eOverline = LINESTYLE_NONE;
+
+ rFont.SetOverline( eOverline );
+ rCJKFont.SetOverline( eOverline );
+ rCTLFont.SetOverline( eOverline );
+
+ // Strikeout
+ FontStrikeout eStrikeout;
+ if( GetWhich( rSet, SID_ATTR_CHAR_STRIKEOUT, nWhich ) )
+ {
+ const SvxCrossedOutItem& rItem = static_cast<const SvxCrossedOutItem&>( rSet.Get( nWhich ) );
+ eStrikeout = rItem.GetValue();
+ }
+ else
+ eStrikeout = STRIKEOUT_NONE;
+
+ rFont.SetStrikeout( eStrikeout );
+ rCJKFont.SetStrikeout( eStrikeout );
+ rCTLFont.SetStrikeout( eStrikeout );
+
+ // WordLineMode
+ if( GetWhich( rSet, SID_ATTR_CHAR_WORDLINEMODE, nWhich ) )
+ {
+ const SvxWordLineModeItem& rItem = static_cast<const SvxWordLineModeItem&>( rSet.Get( nWhich ) );
+ rFont.SetWordLineMode( rItem.GetValue() );
+ rCJKFont.SetWordLineMode( rItem.GetValue() );
+ rCTLFont.SetWordLineMode( rItem.GetValue() );
+ }
+
+ // Emphasis
+ if( GetWhich( rSet, SID_ATTR_CHAR_EMPHASISMARK, nWhich ) )
+ {
+ const SvxEmphasisMarkItem& rItem = static_cast<const SvxEmphasisMarkItem&>( rSet.Get( nWhich ) );
+ FontEmphasisMark eMark = rItem.GetEmphasisMark();
+ rFont.SetEmphasisMark( eMark );
+ rCJKFont.SetEmphasisMark( eMark );
+ rCTLFont.SetEmphasisMark( eMark );
+ }
+
+ // Relief
+ if( GetWhich( rSet, SID_ATTR_CHAR_RELIEF, nWhich ) )
+ {
+ const SvxCharReliefItem& rItem = static_cast<const SvxCharReliefItem&>( rSet.Get( nWhich ) );
+ FontRelief eFontRelief = rItem.GetValue();
+ rFont.SetRelief( eFontRelief );
+ rCJKFont.SetRelief( eFontRelief );
+ rCTLFont.SetRelief( eFontRelief );
+ }
+
+ // Effects
+ if( GetWhich( rSet, SID_ATTR_CHAR_CASEMAP, nWhich ) )
+ {
+ const SvxCaseMapItem& rItem = static_cast<const SvxCaseMapItem&>( rSet.Get( nWhich ) );
+ SvxCaseMap eCaseMap = rItem.GetValue();
+ rFont.SetCaseMap( eCaseMap );
+ rCJKFont.SetCaseMap( eCaseMap );
+ // #i78474# small caps do not exist in CTL fonts
+ rCTLFont.SetCaseMap( eCaseMap == SvxCaseMap::SmallCaps ? SvxCaseMap::NotMapped : eCaseMap );
+ }
+
+ // Outline
+ if( GetWhich( rSet, SID_ATTR_CHAR_CONTOUR, nWhich ) )
+ {
+ const SvxContourItem& rItem = static_cast<const SvxContourItem&>( rSet.Get( nWhich ) );
+ bool bOutline = rItem.GetValue();
+ rFont.SetOutline( bOutline );
+ rCJKFont.SetOutline( bOutline );
+ rCTLFont.SetOutline( bOutline );
+ }
+
+ // Shadow
+ if( GetWhich( rSet, SID_ATTR_CHAR_SHADOWED, nWhich ) )
+ {
+ const SvxShadowedItem& rItem = static_cast<const SvxShadowedItem&>( rSet.Get( nWhich ) );
+ bool bShadow = rItem.GetValue();
+ rFont.SetShadow( bShadow );
+ rCJKFont.SetShadow( bShadow );
+ rCTLFont.SetShadow( bShadow );
+ }
+
+ // Background
+ bool bTransparent;
+ if( GetWhich( rSet, bPreviewBackgroundToCharacter ? SID_ATTR_BRUSH : SID_ATTR_BRUSH_CHAR, nWhich ) )
+ {
+ const SvxBrushItem& rBrush = static_cast<const SvxBrushItem&>( rSet.Get( nWhich ) );
+ const Color& rColor = rBrush.GetColor();
+ bTransparent = rColor.IsTransparent();
+ rFont.SetFillColor( rColor );
+ rCJKFont.SetFillColor( rColor );
+ rCTLFont.SetFillColor( rColor );
+ }
+ else
+ bTransparent = true;
+
+ rFont.SetTransparent( bTransparent );
+ rCJKFont.SetTransparent( bTransparent );
+ rCTLFont.SetTransparent( bTransparent );
+
+ if( !bPreviewBackgroundToCharacter )
+ {
+ if( GetWhich( rSet, SID_ATTR_BRUSH, nWhich ) )
+ {
+ const SvxBrushItem& rBrush = static_cast<const SvxBrushItem&>( rSet.Get( nWhich ) );
+ if( GPOS_NONE == rBrush.GetGraphicPos() )
+ pImpl->mxBackColor = rBrush.GetColor();
+ }
+ }
+
+ // Font
+ SetPrevFont( rSet, SID_ATTR_CHAR_FONT, rFont );
+ SetPrevFont( rSet, SID_ATTR_CHAR_CJK_FONT, rCJKFont );
+ SetPrevFont( rSet, SID_ATTR_CHAR_CTL_FONT, rCTLFont );
+
+ // Style
+ SetPrevFontStyle( rSet, SID_ATTR_CHAR_POSTURE, SID_ATTR_CHAR_WEIGHT, rFont );
+ SetPrevFontStyle( rSet, SID_ATTR_CHAR_CJK_POSTURE, SID_ATTR_CHAR_CJK_WEIGHT, rCJKFont );
+ SetPrevFontStyle( rSet, SID_ATTR_CHAR_CTL_POSTURE, SID_ATTR_CHAR_CTL_WEIGHT, rCTLFont );
+
+ // Size
+ SetFontSize( rSet, SID_ATTR_CHAR_FONTHEIGHT, rFont );
+ SetFontSize( rSet, SID_ATTR_CHAR_CJK_FONTHEIGHT, rCJKFont );
+ SetFontSize( rSet, SID_ATTR_CHAR_CTL_FONTHEIGHT, rCTLFont );
+
+ // Language
+ SetFontLang( rSet, SID_ATTR_CHAR_LANGUAGE, rFont );
+ SetFontLang( rSet, SID_ATTR_CHAR_CJK_LANGUAGE, rCJKFont );
+ SetFontLang( rSet, SID_ATTR_CHAR_CTL_LANGUAGE, rCTLFont );
+
+ // Color
+ if( GetWhich( rSet, SID_ATTR_CHAR_COLOR, nWhich ) )
+ {
+ const SvxColorItem& rItem = static_cast<const SvxColorItem&>( rSet.Get( nWhich ) );
+ Color aCol( rItem.GetValue() );
+ rFont.SetColor( aCol );
+
+ rCJKFont.SetColor( aCol );
+ rCTLFont.SetColor( aCol );
+
+ AutoCorrectFontColor(); // handle color COL_AUTO
+ }
+
+ // Kerning
+ if( GetWhich( rSet, SID_ATTR_CHAR_KERNING, nWhich ) )
+ {
+ const SvxKerningItem& rItem = static_cast<const SvxKerningItem&>( rSet.Get( nWhich ) );
+ short nKern = static_cast<short>(OutputDevice::LogicToLogic(rItem.GetValue(), rSet.GetPool()->GetMetric(nWhich), MapUnit::MapTwip));
+ rFont.SetFixKerning( nKern );
+ rCJKFont.SetFixKerning( nKern );
+ rCTLFont.SetFixKerning( nKern );
+ }
+
+ // Escapement
+ const sal_uInt8 nProp = 100;
+ short nEsc;
+ sal_uInt8 nEscProp;
+ if( GetWhich( rSet, SID_ATTR_CHAR_ESCAPEMENT, nWhich ) )
+ {
+ const SvxEscapementItem& rItem = static_cast<const SvxEscapementItem&>( rSet.Get( nWhich ) );
+ nEsc = rItem.GetEsc();
+ nEscProp = rItem.GetProportionalHeight();
+
+ if( nEsc == DFLT_ESC_AUTO_SUPER )
+ nEsc = DFLT_ESC_SUPER;
+ else if( nEsc == DFLT_ESC_AUTO_SUB )
+ nEsc = DFLT_ESC_SUB;
+ }
+ else
+ {
+ nEsc = 0;
+ nEscProp = 100;
+ }
+ SetPrevFontEscapement( rFont, nProp, nEscProp, nEsc );
+ SetPrevFontEscapement( rCJKFont, nProp, nEscProp, nEsc );
+ SetPrevFontEscapement( rCTLFont, nProp, nEscProp, nEsc );
+
+ // Font width scale
+ if( GetWhich( rSet, SID_ATTR_CHAR_SCALEWIDTH, nWhich ) )
+ {
+ const SvxCharScaleWidthItem&rItem = static_cast<const SvxCharScaleWidthItem&>( rSet.Get( nWhich ) );
+ SetFontWidthScale( rItem.GetValue() );
+ }
+
+ Invalidate();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */