Coverage Report

Created: 2025-12-08 09:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/drawinglayer/source/primitive2d/textstrikeoutprimitive2d.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 <primitive2d/textstrikeoutprimitive2d.hxx>
21
#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
22
#include <drawinglayer/primitive2d/textprimitive2d.hxx>
23
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
24
#include <basegfx/polygon/b2dpolygon.hxx>
25
#include <basegfx/matrix/b2dhommatrixtools.hxx>
26
#include <drawinglayer/attribute/lineattribute.hxx>
27
#include <drawinglayer/primitive2d/PolygonStrokePrimitive2D.hxx>
28
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
29
#include <osl/diagnose.h>
30
#include <rtl/ustrbuf.hxx>
31
#include <utility>
32
33
34
namespace drawinglayer::primitive2d
35
{
36
        BaseTextStrikeoutPrimitive2D::BaseTextStrikeoutPrimitive2D(
37
            basegfx::B2DHomMatrix aObjectTransformation,
38
            double fWidth,
39
            const basegfx::BColor& rFontColor)
40
0
        :   maObjectTransformation(std::move(aObjectTransformation)),
41
0
            mfWidth(fWidth),
42
0
            maFontColor(rFontColor)
43
0
        {
44
0
        }
45
46
        bool BaseTextStrikeoutPrimitive2D::operator==( const BasePrimitive2D& rPrimitive ) const
47
0
        {
48
0
            if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
49
0
            {
50
0
                const BaseTextStrikeoutPrimitive2D& rCompare = static_cast<const BaseTextStrikeoutPrimitive2D&>(rPrimitive);
51
52
0
                return (getObjectTransformation() == rCompare.getObjectTransformation()
53
0
                    && getWidth() == rCompare.getWidth()
54
0
                    && getFontColor() == rCompare.getFontColor());
55
0
            }
56
57
0
            return false;
58
0
        }
59
60
61
        Primitive2DReference TextCharacterStrikeoutPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
62
0
        {
63
            // strikeout with character
64
0
            const OUString aSingleCharString(getStrikeoutChar());
65
0
            basegfx::B2DVector aScale, aTranslate;
66
0
            double fRotate, fShearX;
67
68
            // get decomposition
69
0
            getObjectTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
70
71
            // prepare TextLayouter
72
0
            TextLayouterDevice aTextLayouter;
73
74
0
            aTextLayouter.setFontAttribute(
75
0
                getFontAttribute(),
76
0
                aScale.getX(),
77
0
                aScale.getY(),
78
0
                getLocale());
79
80
0
            const double fStrikeCharWidth(aTextLayouter.getTextWidth(aSingleCharString, 0, 1));
81
0
            const double fStrikeCharCount(fabs(getWidth()/fStrikeCharWidth));
82
0
            const sal_uInt32 nStrikeCharCount(static_cast< sal_uInt32 >(fStrikeCharCount + 0.5));
83
0
            std::vector<double> aDXArray(nStrikeCharCount);
84
0
            OUStringBuffer aStrikeoutString;
85
86
0
            for(sal_uInt32 a(0); a < nStrikeCharCount; a++)
87
0
            {
88
0
                aStrikeoutString.append(aSingleCharString);
89
0
                aDXArray[a] = (a + 1) * fStrikeCharWidth;
90
0
            }
91
92
0
            auto len = aStrikeoutString.getLength();
93
0
            return
94
0
                new TextSimplePortionPrimitive2D(
95
0
                    getObjectTransformation(),
96
0
                    aStrikeoutString.makeStringAndClear(),
97
0
                    0,
98
0
                    len,
99
0
                    std::move(aDXArray),
100
0
                    {},
101
0
                    getFontAttribute(),
102
0
                    getLocale(),
103
0
                    getFontColor());
104
0
        }
105
106
        TextCharacterStrikeoutPrimitive2D::TextCharacterStrikeoutPrimitive2D(
107
            const basegfx::B2DHomMatrix& rObjectTransformation,
108
            double fWidth,
109
            const basegfx::BColor& rFontColor,
110
            sal_Unicode aStrikeoutChar,
111
            attribute::FontAttribute aFontAttribute,
112
            css::lang::Locale aLocale)
113
0
        :   BaseTextStrikeoutPrimitive2D(rObjectTransformation, fWidth, rFontColor),
114
0
            maStrikeoutChar(aStrikeoutChar),
115
0
            maFontAttribute(std::move(aFontAttribute)),
116
0
            maLocale(std::move(aLocale))
117
0
        {
118
0
        }
119
120
        bool TextCharacterStrikeoutPrimitive2D::operator==( const BasePrimitive2D& rPrimitive ) const
121
0
        {
122
0
            if(BaseTextStrikeoutPrimitive2D::operator==(rPrimitive))
123
0
            {
124
0
                const TextCharacterStrikeoutPrimitive2D& rCompare = static_cast<const TextCharacterStrikeoutPrimitive2D&>(rPrimitive);
125
126
0
                return (getStrikeoutChar() == rCompare.getStrikeoutChar()
127
0
                    && getFontAttribute() == rCompare.getFontAttribute()
128
0
                    && LocalesAreEqual(getLocale(), rCompare.getLocale()));
129
0
            }
130
131
0
            return false;
132
0
        }
133
134
        // provide unique ID
135
        sal_uInt32 TextCharacterStrikeoutPrimitive2D::getPrimitive2DID() const
136
0
        {
137
0
            return PRIMITIVE2D_ID_TEXTCHARACTERSTRIKEOUTPRIMITIVE2D;
138
0
        }
139
140
        Primitive2DReference TextGeometryStrikeoutPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const
141
0
        {
142
0
            OSL_ENSURE(TEXT_STRIKEOUT_SLASH != getTextStrikeout() && TEXT_STRIKEOUT_X != getTextStrikeout(),
143
0
                "Wrong TEXT_STRIKEOUT type; a TextCharacterStrikeoutPrimitive2D should be used (!)");
144
145
            // strikeout with geometry
146
0
            double fStrikeoutHeight(getHeight());
147
0
            double fStrikeoutOffset(getOffset());
148
0
            bool bDoubleLine(false);
149
150
            // get decomposition
151
0
            basegfx::B2DVector aScale, aTranslate;
152
0
            double fRotate, fShearX;
153
0
            getObjectTransformation().decompose(aScale, aTranslate, fRotate, fShearX);
154
155
            // set line attribute
156
0
            switch(getTextStrikeout())
157
0
            {
158
0
                default : // case primitive2d::TEXT_STRIKEOUT_SINGLE:
159
0
                {
160
0
                    break;
161
0
                }
162
0
                case primitive2d::TEXT_STRIKEOUT_DOUBLE:
163
0
                {
164
0
                    bDoubleLine = true;
165
0
                    break;
166
0
                }
167
0
                case primitive2d::TEXT_STRIKEOUT_BOLD:
168
0
                {
169
0
                    fStrikeoutHeight *= 2.0;
170
0
                    break;
171
0
                }
172
0
            }
173
174
0
            if(bDoubleLine)
175
0
            {
176
0
                fStrikeoutOffset -= 0.50 * fStrikeoutHeight;
177
0
                fStrikeoutHeight *= 0.64;
178
0
            }
179
180
            // create base polygon and new primitive
181
0
            basegfx::B2DPolygon aStrikeoutLine;
182
183
0
            aStrikeoutLine.append(basegfx::B2DPoint(0.0, -fStrikeoutOffset));
184
0
            aStrikeoutLine.append(basegfx::B2DPoint(getWidth(), -fStrikeoutOffset));
185
186
0
            const basegfx::B2DHomMatrix aUnscaledTransform(
187
0
                basegfx::utils::createShearXRotateTranslateB2DHomMatrix(
188
0
                    fShearX, fRotate, aTranslate));
189
190
0
            aStrikeoutLine.transform(aUnscaledTransform);
191
192
            // add primitive
193
0
            const attribute::LineAttribute aLineAttribute(getFontColor(), fStrikeoutHeight, basegfx::B2DLineJoin::NONE);
194
0
            Primitive2DReference xRetval = new PolygonStrokePrimitive2D(std::move(aStrikeoutLine), aLineAttribute);
195
196
0
            if(bDoubleLine)
197
0
            {
198
                // double line, create 2nd primitive with offset using TransformPrimitive based on
199
                // already created NewPrimitive
200
0
                const double fLineDist(2.0 * fStrikeoutHeight);
201
202
                // move base point of text to 0.0 and de-rotate
203
0
                basegfx::B2DHomMatrix aTransform(basegfx::utils::createTranslateB2DHomMatrix(
204
0
                    -aTranslate.getX(), -aTranslate.getY()));
205
0
                aTransform.rotate(-fRotate);
206
207
                // translate in Y by offset
208
0
                aTransform.translate(0.0, -fLineDist);
209
210
                // move back and rotate
211
0
                aTransform.rotate(fRotate);
212
0
                aTransform.translate(aTranslate.getX(), aTranslate.getY());
213
214
                // add original and transform primitive to a GroupPrimitive2D
215
0
                xRetval = new GroupPrimitive2D({
216
0
                    xRetval, new TransformPrimitive2D(
217
0
                        aTransform,
218
0
                        Primitive2DContainer{xRetval}) });
219
0
            }
220
221
0
            return xRetval;
222
0
        }
223
224
        TextGeometryStrikeoutPrimitive2D::TextGeometryStrikeoutPrimitive2D(
225
            const basegfx::B2DHomMatrix& rObjectTransformation,
226
            double fWidth,
227
            const basegfx::BColor& rFontColor,
228
            double fHeight,
229
            double fOffset,
230
            TextStrikeout eTextStrikeout)
231
0
        :   BaseTextStrikeoutPrimitive2D(rObjectTransformation, fWidth, rFontColor),
232
0
            mfHeight(fHeight),
233
0
            mfOffset(fOffset),
234
0
            meTextStrikeout(eTextStrikeout)
235
0
        {
236
0
        }
237
238
        bool TextGeometryStrikeoutPrimitive2D::operator==( const BasePrimitive2D& rPrimitive ) const
239
0
        {
240
0
            if(BaseTextStrikeoutPrimitive2D::operator==(rPrimitive))
241
0
            {
242
0
                const TextGeometryStrikeoutPrimitive2D& rCompare = static_cast<const TextGeometryStrikeoutPrimitive2D&>(rPrimitive);
243
244
0
                return (getHeight() == rCompare.getHeight()
245
0
                    && getOffset() == rCompare.getOffset()
246
0
                    && getTextStrikeout() == rCompare.getTextStrikeout());
247
0
            }
248
249
0
            return false;
250
0
        }
251
252
        // provide unique ID
253
        sal_uInt32 TextGeometryStrikeoutPrimitive2D::getPrimitive2DID() const
254
0
        {
255
0
            return PRIMITIVE2D_ID_TEXTGEOMETRYSTRIKEOUTPRIMITIVE2D;
256
0
        }
257
258
} // end of namespace
259
260
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */