Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/drawinglayer/source/primitive2d/textlayoutdevice.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <sal/config.h>
21
22
#include <algorithm>
23
24
#include <com/sun/star/uno/XComponentContext.hpp>
25
26
#include <basegfx/matrix/b2dhommatrixtools.hxx>
27
#include <drawinglayer/attribute/fontattribute.hxx>
28
#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
29
#include <comphelper/processfactory.hxx>
30
#include <comphelper/unique_disposing_ptr.hxx>
31
#include <osl/diagnose.h>
32
#include <tools/gen.hxx>
33
#include <vcl/kernarray.hxx>
34
#include <vcl/timer.hxx>
35
#include <vcl/virdev.hxx>
36
#include <vcl/font.hxx>
37
#include <vcl/metric.hxx>
38
#include <i18nlangtag/languagetag.hxx>
39
#include <vcl/svapp.hxx>
40
#include <vcl/vcllayout.hxx>
41
#include <vcl/glyphitemcache.hxx>
42
43
namespace drawinglayer::primitive2d
44
{
45
namespace
46
{
47
class ImpTimedRefDev;
48
49
// VDev RevDevice provider
50
51
//the scoped_timed_RefDev owns an ImpTimeRefDev and releases it on dtor
52
//or disposing of the default XComponentContext which causes the underlying
53
//OutputDevice to get released
54
55
//The ImpTimerRefDev itself, if the timeout ever gets hit, will call
56
//reset on the scoped_timed_RefDev to release the ImpTimerRefDev early
57
//if it's unused for a few minutes
58
class scoped_timed_RefDev : public comphelper::unique_disposing_ptr<ImpTimedRefDev>
59
{
60
public:
61
    scoped_timed_RefDev()
62
5
        : comphelper::unique_disposing_ptr<ImpTimedRefDev>(
63
5
              (css::uno::Reference<css::lang::XComponent>(
64
5
                  ::comphelper::getProcessComponentContext(), css::uno::UNO_QUERY_THROW)))
65
5
    {
66
5
    }
67
};
68
69
class the_scoped_timed_RefDev : public rtl::Static<scoped_timed_RefDev, the_scoped_timed_RefDev>
70
{
71
};
72
73
class ImpTimedRefDev : public Timer
74
{
75
    scoped_timed_RefDev& mrOwnerOfMe;
76
    VclPtr<VirtualDevice> mpVirDev;
77
    sal_uInt32 mnUseCount;
78
79
public:
80
    explicit ImpTimedRefDev(scoped_timed_RefDev& rOwnerofMe);
81
    virtual ~ImpTimedRefDev() override;
82
    virtual void Invoke() override;
83
84
    VirtualDevice& acquireVirtualDevice();
85
    void releaseVirtualDevice();
86
};
87
88
ImpTimedRefDev::ImpTimedRefDev(scoped_timed_RefDev& rOwnerOfMe)
89
5
    : Timer("drawinglayer ImpTimedRefDev destroy mpVirDev")
90
5
    , mrOwnerOfMe(rOwnerOfMe)
91
5
    , mpVirDev(nullptr)
92
5
    , mnUseCount(0)
93
5
{
94
5
    SetTimeout(3L * 60L * 1000L); // three minutes
95
5
    Start();
96
5
}
97
98
ImpTimedRefDev::~ImpTimedRefDev()
99
5
{
100
5
    OSL_ENSURE(0 == mnUseCount, "destruction of a still used ImpTimedRefDev (!)");
101
5
    const SolarMutexGuard aSolarGuard;
102
5
    mpVirDev.disposeAndClear();
103
5
}
104
105
void ImpTimedRefDev::Invoke()
106
0
{
107
    // for obvious reasons, do not call anything after this
108
0
    mrOwnerOfMe.reset();
109
0
}
110
111
VirtualDevice& ImpTimedRefDev::acquireVirtualDevice()
112
1.61k
{
113
1.61k
    if (!mpVirDev)
114
5
    {
115
5
        mpVirDev = VclPtr<VirtualDevice>::Create();
116
5
        mpVirDev->SetReferenceDevice(VirtualDevice::RefDevMode::MSO1);
117
5
    }
118
119
1.61k
    if (!mnUseCount)
120
1.61k
    {
121
1.61k
        Stop();
122
1.61k
    }
123
124
1.61k
    mnUseCount++;
125
126
1.61k
    return *mpVirDev;
127
1.61k
}
128
129
void ImpTimedRefDev::releaseVirtualDevice()
130
1.61k
{
131
1.61k
    OSL_ENSURE(mnUseCount, "mismatch call number to releaseVirtualDevice() (!)");
132
1.61k
    mnUseCount--;
133
134
1.61k
    if (!mnUseCount)
135
1.61k
    {
136
1.61k
        Start();
137
1.61k
    }
138
1.61k
}
139
140
VirtualDevice& acquireGlobalVirtualDevice()
141
1.61k
{
142
1.61k
    scoped_timed_RefDev& rStdRefDevice = the_scoped_timed_RefDev::get();
143
144
1.61k
    if (!rStdRefDevice)
145
5
        rStdRefDevice.reset(new ImpTimedRefDev(rStdRefDevice));
146
147
1.61k
    return rStdRefDevice->acquireVirtualDevice();
148
1.61k
}
149
150
void releaseGlobalVirtualDevice()
151
1.61k
{
152
1.61k
    scoped_timed_RefDev& rStdRefDevice = the_scoped_timed_RefDev::get();
153
154
1.61k
    OSL_ENSURE(rStdRefDevice,
155
1.61k
               "releaseGlobalVirtualDevice() without prior acquireGlobalVirtualDevice() call(!)");
156
1.61k
    rStdRefDevice->releaseVirtualDevice();
157
1.61k
}
158
159
} // end of anonymous namespace
160
161
TextLayouterDevice::TextLayouterDevice()
162
1.61k
    : mrDevice(acquireGlobalVirtualDevice())
163
1.61k
{
164
    // tdf#168002 activate SubpixelPositioning for al TextLayouterDevice-calls
165
1.61k
    mrDevice.setSubpixelPositioning(true);
166
1.61k
}
167
168
TextLayouterDevice::~TextLayouterDevice()
169
1.61k
{
170
1.61k
    suppress_fun_call_w_exception(releaseGlobalVirtualDevice());
171
1.61k
}
172
173
void TextLayouterDevice::setFont(const vcl::Font& rFont)
174
1.61k
{
175
1.61k
    mrDevice.SetFont(rFont);
176
1.61k
    mnFontScalingFixX = 1.0;
177
1.61k
    mnFontScalingFixY = 1.0;
178
1.61k
}
179
180
void TextLayouterDevice::setFontAttribute(const attribute::FontAttribute& rFontAttribute,
181
                                          double fFontScaleX, double fFontScaleY,
182
                                          const css::lang::Locale& rLocale)
183
1.61k
{
184
1.61k
    vcl::Font aFont
185
1.61k
        = getVclFontFromFontAttribute(rFontAttribute, fFontScaleX, fFontScaleY, 0.0, rLocale);
186
1.61k
    setFont(aFont);
187
1.61k
    Size aFontSize = aFont.GetFontSize();
188
1.61k
    if (aFontSize.Height())
189
1.61k
    {
190
1.61k
        mnFontScalingFixY = fFontScaleY / aFontSize.Height();
191
        // aFontSize.Width() is 0 for uninformly scaled fonts: see getVclFontFromFontAttribute
192
1.61k
        mnFontScalingFixX
193
1.61k
            = fFontScaleX / (aFontSize.Width() ? aFontSize.Width() : aFontSize.Height());
194
1.61k
    }
195
0
    else
196
0
    {
197
0
        mnFontScalingFixX = mnFontScalingFixY = 1.0;
198
0
    }
199
1.61k
}
200
201
void TextLayouterDevice::setLayoutMode(vcl::text::ComplexTextLayoutFlags nTextLayoutMode)
202
0
{
203
0
    mrDevice.SetLayoutMode(nTextLayoutMode);
204
0
}
205
206
vcl::text::ComplexTextLayoutFlags TextLayouterDevice::getLayoutMode() const
207
0
{
208
0
    return mrDevice.GetLayoutMode();
209
0
}
210
211
void TextLayouterDevice::setTextColor(const basegfx::BColor& rColor)
212
0
{
213
0
    mrDevice.SetTextColor(Color(rColor));
214
0
}
215
216
double TextLayouterDevice::getOverlineOffset() const
217
0
{
218
0
    const ::FontMetric aMetric = mrDevice.GetFontMetric();
219
0
    double fRet = (aMetric.GetInternalLeading() / 2.0) - aMetric.GetAscent();
220
0
    return fRet * mnFontScalingFixY;
221
0
}
222
223
double TextLayouterDevice::getUnderlineOffset() const
224
0
{
225
0
    const ::FontMetric aMetric = mrDevice.GetFontMetric();
226
0
    double fRet = aMetric.GetDescent() / 2.0;
227
0
    return fRet * mnFontScalingFixY;
228
0
}
229
230
double TextLayouterDevice::getStrikeoutOffset() const
231
0
{
232
0
    const ::FontMetric aMetric = mrDevice.GetFontMetric();
233
0
    double fRet = (aMetric.GetAscent() - aMetric.GetInternalLeading()) / 3.0;
234
0
    return fRet * mnFontScalingFixY;
235
0
}
236
237
double TextLayouterDevice::getOverlineHeight() const
238
0
{
239
0
    const ::FontMetric aMetric = mrDevice.GetFontMetric();
240
0
    double fRet = aMetric.GetInternalLeading() / 2.5;
241
0
    return fRet * mnFontScalingFixY;
242
0
}
243
244
double TextLayouterDevice::getUnderlineHeight() const
245
0
{
246
0
    const ::FontMetric aMetric = mrDevice.GetFontMetric();
247
0
    double fRet = aMetric.GetDescent() / 4.0;
248
0
    return fRet * mnFontScalingFixY;
249
0
}
250
251
double TextLayouterDevice::getTextHeight() const
252
0
{
253
0
    return mrDevice.GetTextHeightDouble() * mnFontScalingFixY;
254
0
}
255
256
double TextLayouterDevice::getTextWidth(const OUString& rText, sal_uInt32 nIndex,
257
                                        sal_uInt32 nLength) const
258
0
{
259
0
    return mrDevice.GetTextWidthDouble(rText, nIndex, nLength) * mnFontScalingFixX;
260
0
}
261
262
void TextLayouterDevice::getTextOutlines(basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector,
263
                                         const OUString& rText, sal_uInt32 nIndex,
264
                                         sal_uInt32 nLength, const std::vector<double>& rDXArray,
265
                                         const std::vector<sal_Bool>& rKashidaArray) const
266
400
{
267
400
    const sal_uInt32 nDXArrayCount(rDXArray.size());
268
400
    sal_uInt32 nTextLength(nLength);
269
400
    const sal_uInt32 nStringLength(rText.getLength());
270
271
400
    if (nTextLength + nIndex > nStringLength)
272
0
    {
273
0
        nTextLength = nStringLength - nIndex;
274
0
    }
275
276
400
    if (nDXArrayCount)
277
400
    {
278
400
        OSL_ENSURE(nDXArrayCount == nTextLength,
279
400
                   "DXArray size does not correspond to text portion size (!)");
280
281
400
        mrDevice.GetTextOutlines(rB2DPolyPolyVector, rText, nIndex, nIndex, nLength, 0, rDXArray,
282
400
                                 rKashidaArray);
283
400
    }
284
0
    else
285
0
    {
286
0
        mrDevice.GetTextOutlines(rB2DPolyPolyVector, rText, nIndex, nIndex, nLength);
287
0
    }
288
400
    if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0)
289
400
        || !rtl_math_approxEqual(mnFontScalingFixX, 1.0))
290
0
    {
291
0
        auto scale = basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, mnFontScalingFixY);
292
0
        for (auto& poly : rB2DPolyPolyVector)
293
0
            poly.transform(scale);
294
0
    }
295
400
}
296
297
basegfx::B2DRange TextLayouterDevice::getTextBoundRect(const OUString& rText, sal_uInt32 nIndex,
298
                                                       sal_uInt32 nLength) const
299
1.21k
{
300
1.21k
    sal_uInt32 nTextLength(nLength);
301
1.21k
    const sal_uInt32 nStringLength(rText.getLength());
302
303
1.21k
    if (nTextLength + nIndex > nStringLength)
304
0
    {
305
0
        nTextLength = nStringLength - nIndex;
306
0
    }
307
308
1.21k
    if (nTextLength)
309
1.21k
    {
310
1.21k
        basegfx::B2DRange aRect;
311
1.21k
        mrDevice.GetTextBoundRect(aRect, rText, nIndex, nIndex, nLength);
312
1.21k
        if (!rtl_math_approxEqual(mnFontScalingFixY, 1.0)
313
1.21k
            || !rtl_math_approxEqual(mnFontScalingFixX, 1.0))
314
0
        {
315
0
            aRect.transform(
316
0
                basegfx::utils::createScaleB2DHomMatrix(mnFontScalingFixX, mnFontScalingFixY));
317
0
        }
318
1.21k
        return aRect;
319
1.21k
    }
320
321
0
    return basegfx::B2DRange();
322
1.21k
}
323
324
double TextLayouterDevice::getFontAscent() const
325
0
{
326
0
    const ::FontMetric aMetric = mrDevice.GetFontMetric();
327
0
    return aMetric.GetAscent() * mnFontScalingFixY;
328
0
}
329
330
double TextLayouterDevice::getFontDescent() const
331
0
{
332
0
    const ::FontMetric aMetric = mrDevice.GetFontMetric();
333
0
    return aMetric.GetDescent() * mnFontScalingFixY;
334
0
}
335
336
void TextLayouterDevice::addTextRectActions(const ::tools::Rectangle& rRectangle,
337
                                            const OUString& rText, DrawTextFlags nStyle,
338
                                            GDIMetaFile& rGDIMetaFile) const
339
0
{
340
0
    mrDevice.AddTextRectActions(rRectangle, rText, nStyle, rGDIMetaFile);
341
0
}
342
343
std::vector<double> TextLayouterDevice::getTextArray(const OUString& rText, sal_uInt32 nIndex,
344
                                                     sal_uInt32 nLength, bool bCaret) const
345
0
{
346
0
    std::vector<double> aRetval;
347
0
    sal_uInt32 nTextLength(nLength);
348
0
    const sal_uInt32 nStringLength(rText.getLength());
349
350
0
    if (nTextLength + nIndex > nStringLength)
351
0
    {
352
0
        nTextLength = nStringLength - nIndex;
353
0
    }
354
355
0
    if (nTextLength)
356
0
    {
357
0
        KernArray aArray;
358
0
        mrDevice.GetTextArray(rText, &aArray, nIndex, nTextLength, bCaret);
359
0
        aRetval.reserve(aArray.size());
360
0
        for (size_t i = 0, nEnd = aArray.size(); i < nEnd; ++i)
361
0
            aRetval.push_back(aArray[i] * mnFontScalingFixX);
362
0
    }
363
364
0
    return aRetval;
365
0
}
366
367
std::unique_ptr<SalLayout>
368
TextLayouterDevice::getSalLayout(const OUString& rText, sal_uInt32 nIndex, sal_uInt32 nLength,
369
                                 const basegfx::B2DPoint& rStartPoint, const KernArray& rDXArray,
370
                                 std::span<const sal_Bool> pKashidaAry) const
371
0
{
372
0
    const SalLayoutGlyphs* pGlyphs(
373
0
        SalLayoutGlyphsCache::self()->GetLayoutGlyphs(&mrDevice, rText, nIndex, nLength));
374
0
    const Point aStartPoint(basegfx::fround<tools::Long>(rStartPoint.getX()),
375
0
                            basegfx::fround<tools::Long>(rStartPoint.getY()));
376
0
    return mrDevice.ImplLayout(rText, nIndex, nLength, aStartPoint, 0, rDXArray, pKashidaAry,
377
0
                               SalLayoutFlags::NONE, nullptr, pGlyphs);
378
0
}
379
380
void TextLayouterDevice::createEmphasisMarks(
381
    const SalLayout& rSalLayout, TextEmphasisMark aTextEmphasisMark, bool bAbove,
382
    const std::function<void(const basegfx::B2DPoint&, const basegfx::B2DPolyPolygon&, bool,
383
                             const tools::Rectangle&, const tools::Rectangle&)>& rCallback) const
384
0
{
385
0
    FontEmphasisMark nEmphasisMark(FontEmphasisMark::NONE);
386
0
    double fEmphasisHeight(getTextHeight() * (250.0 / 1000.0));
387
388
0
    switch (aTextEmphasisMark)
389
0
    {
390
0
        case TEXT_FONT_EMPHASIS_MARK_DOT:
391
0
            nEmphasisMark = FontEmphasisMark::Dot;
392
0
            break;
393
0
        case TEXT_FONT_EMPHASIS_MARK_CIRCLE:
394
0
            nEmphasisMark = FontEmphasisMark::Circle;
395
0
            break;
396
0
        case TEXT_FONT_EMPHASIS_MARK_DISC:
397
0
            nEmphasisMark = FontEmphasisMark::Disc;
398
0
            break;
399
0
        case TEXT_FONT_EMPHASIS_MARK_ACCENT:
400
0
            nEmphasisMark = FontEmphasisMark::Accent;
401
0
            break;
402
0
        default:
403
0
            break;
404
0
    }
405
406
0
    if (bAbove)
407
0
        nEmphasisMark |= FontEmphasisMark::PosAbove;
408
0
    else
409
0
        nEmphasisMark |= FontEmphasisMark::PosBelow;
410
411
0
    mrDevice.createEmphasisMarks(nEmphasisMark, static_cast<tools::Long>(fEmphasisHeight),
412
0
                                 rSalLayout, rCallback);
413
0
}
414
415
// helper methods for vcl font handling
416
417
vcl::Font getVclFontFromFontAttribute(const attribute::FontAttribute& rFontAttribute,
418
                                      double fFontScaleX, double fFontScaleY, double fFontRotation,
419
                                      const css::lang::Locale& rLocale)
420
2.42k
{
421
    // detect FontScaling
422
2.42k
    const sal_uInt32 nHeight(basegfx::fround(fabs(fFontScaleY)));
423
2.42k
    const sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX)));
424
2.42k
    const bool bFontIsScaled(nHeight != nWidth);
425
426
#ifdef _WIN32
427
    // for WIN32 systems, start with creating an unscaled font. If FontScaling
428
    // is wanted, that width needs to be adapted using FontMetric again to get a
429
    // width of the unscaled font
430
    vcl::Font aRetval(rFontAttribute.getFamilyName(), rFontAttribute.getStyleName(),
431
                      Size(0, nHeight));
432
#else
433
    // for non-WIN32 systems things are easier since these accept a Font creation
434
    // with initially nWidth != nHeight for FontScaling. Despite that, use zero for
435
    // FontWidth when no scaling is used to explicitly have that zero when e.g. the
436
    // Font would be recorded in a MetaFile (The MetaFile FontAction WILL record a
437
    // set FontWidth; import that in a WIN32 system, and trouble is there)
438
2.42k
    vcl::Font aRetval(rFontAttribute.getFamilyName(), rFontAttribute.getStyleName(),
439
2.42k
                      Size(bFontIsScaled ? std::max<sal_uInt32>(nWidth, 1) : 0, nHeight));
440
2.42k
#endif
441
    // define various other FontAttribute
442
2.42k
    aRetval.SetAlignment(ALIGN_BASELINE);
443
2.42k
    aRetval.SetCharSet(rFontAttribute.getSymbol() ? RTL_TEXTENCODING_SYMBOL
444
2.42k
                                                  : RTL_TEXTENCODING_UNICODE);
445
2.42k
    aRetval.SetVertical(rFontAttribute.getVertical());
446
2.42k
    aRetval.SetWeight(static_cast<FontWeight>(rFontAttribute.getWeight()));
447
2.42k
    aRetval.SetItalic(rFontAttribute.getItalic() ? ITALIC_NORMAL : ITALIC_NONE);
448
2.42k
    aRetval.SetOutline(rFontAttribute.getOutline());
449
2.42k
    aRetval.SetPitch(rFontAttribute.getMonospaced() ? PITCH_FIXED : PITCH_VARIABLE);
450
2.42k
    aRetval.SetLanguage(LanguageTag::convertToLanguageType(rLocale, false));
451
452
#ifdef _WIN32
453
    // for WIN32 systems, correct the FontWidth if FontScaling is used
454
    if (bFontIsScaled && nHeight > 0)
455
    {
456
        const FontMetric aUnscaledFontMetric(
457
            Application::GetDefaultDevice()->GetFontMetric(aRetval));
458
459
        if (aUnscaledFontMetric.GetAverageFontWidth() > 0)
460
        {
461
            const double fScaleFactor(static_cast<double>(nWidth) / static_cast<double>(nHeight));
462
            const sal_uInt32 nScaledWidth(basegfx::fround(
463
                static_cast<double>(aUnscaledFontMetric.GetAverageFontWidth()) * fScaleFactor));
464
            aRetval.SetAverageFontWidth(nScaledWidth);
465
        }
466
    }
467
#endif
468
    // handle FontRotation (if defined)
469
2.42k
    if (!basegfx::fTools::equalZero(fFontRotation))
470
8
    {
471
8
        int aRotate10th(-basegfx::rad2deg<10>(fFontRotation));
472
8
        aRetval.SetOrientation(Degree10(aRotate10th % 3600));
473
8
    }
474
475
2.42k
    return aRetval;
476
2.42k
}
477
478
attribute::FontAttribute getFontAttributeFromVclFont(basegfx::B2DVector& o_rSize,
479
                                                     const vcl::Font& rFont, bool bRTL,
480
                                                     bool bBiDiStrong)
481
1.21k
{
482
1.21k
    const attribute::FontAttribute aRetval(
483
1.21k
        rFont.GetFamilyName(), rFont.GetStyleName(), static_cast<sal_uInt16>(rFont.GetWeight()),
484
1.21k
        RTL_TEXTENCODING_SYMBOL == rFont.GetCharSet(), rFont.IsVertical(),
485
1.21k
        ITALIC_NONE != rFont.GetItalic(), PITCH_FIXED == rFont.GetPitch(), rFont.IsOutline(), bRTL,
486
1.21k
        bBiDiStrong);
487
    // TODO: eKerning
488
489
    // set FontHeight and init to no FontScaling
490
1.21k
    o_rSize.setY(std::max<tools::Long>(rFont.GetFontSize().getHeight(), 0));
491
1.21k
    o_rSize.setX(o_rSize.getY());
492
493
#ifdef _WIN32
494
    // for WIN32 systems, the FontScaling at the Font is detected by
495
    // checking that FontWidth != 0. When FontScaling is used, WIN32
496
    // needs to do extra stuff to detect the correct width (since it's
497
    // zero and not equal the font height) and its relationship to
498
    // the height
499
    if (rFont.GetFontSize().getWidth() > 0)
500
    {
501
        vcl::Font aUnscaledFont(rFont);
502
        aUnscaledFont.SetAverageFontWidth(0);
503
        const FontMetric aUnscaledFontMetric(
504
            Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont));
505
506
        if (aUnscaledFontMetric.GetAverageFontWidth() > 0)
507
        {
508
            const double fScaleFactor(
509
                static_cast<double>(rFont.GetFontSize().getWidth())
510
                / static_cast<double>(aUnscaledFontMetric.GetAverageFontWidth()));
511
            o_rSize.setX(fScaleFactor * o_rSize.getY());
512
        }
513
    }
514
#else
515
    // For non-WIN32 systems the detection is the same, but the value
516
    // is easier achieved since width == height is interpreted as no
517
    // scaling. Ergo, Width == 0 means width == height, and width != 0
518
    // means the scaling is in the direct relation of width to height
519
1.21k
    if (rFont.GetFontSize().getWidth() > 0)
520
10
    {
521
10
        o_rSize.setX(static_cast<double>(rFont.GetFontSize().getWidth()));
522
10
    }
523
1.21k
#endif
524
1.21k
    return aRetval;
525
1.21k
}
526
527
} // end of namespace
528
529
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */