Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/drawinglayer/processor2d/baseprocessor2d.hxx
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
#ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX
21
#define INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX
22
23
#include <drawinglayer/drawinglayerdllapi.h>
24
25
#include <drawinglayer/primitive2d/Primitive2DVisitor.hxx>
26
#include <drawinglayer/geometry/viewinformation2d.hxx>
27
28
namespace drawinglayer::primitive2d { class BasePrimitive2D; }
29
namespace drawinglayer::primitive2d { class Primitive2DContainer; }
30
31
namespace drawinglayer::processor2d
32
    {
33
        /** BaseProcessor2D class
34
35
            Base class for all C++ implementations of instances which process
36
            primitives.
37
38
            Instances which process primitives can be renderers, but also stuff
39
            for HitTests, BoundRect calculations and/or animation processing. The
40
            main usage are renderers, but they are supposed to handle any primitive
41
            processing.
42
43
            The base implementation is constructed with a ViewInformation2D which
44
            is accessible throughout the processor implementations. The idea is
45
            to construct any processor with a given ViewInformation2D. To be able
46
            to handle primitives which need to change the current transformation
47
            (as e.g. TransformPrimitive2D) it is allowed for the processor implementation
48
            to change its local value using setViewInformation2D.
49
50
            The basic processing method is process(..) which gets handed over the
51
            sequence of primitives to process. For convenience of the C++ implementations,
52
            the default implementation of process(..) maps all accesses to primitives to
53
            single calls to processBasePrimitive2D(..) where the primitive in question is
54
            already casted to the C++ implementation class.
55
56
            The process(..) implementation makes a complete iteration over the given
57
            sequence of primitives. If the Primitive is not derived from BasePrimitive2D
58
            and thus not part of the C++ implementations, it converts ViewInformation2D
59
            to the corresponding API implementation (a uno::Sequence< beans::PropertyValue >)
60
            and recursively calls the method process(..) at the primitive with the decomposition
61
            derived from that primitive. This is the preparation to handle unknown implementations
62
            of the css::graphic::XPrimitive2D interface in the future.
63
64
            So, to implement a basic processor, it is necessary to override and implement the
65
            processBasePrimitive2D(..) method. A minimal renderer has to support the
66
            Basic Primitives (see baseprimitive2d.hxx) and the Grouping Primitives (see
67
            groupprimitive2d.hxx). These are (currently):
68
69
            Basic Primitives:
70
71
            - BitmapPrimitive2D (bitmap data, possibly with transparency)
72
            - PointArrayPrimitive2D (single points)
73
            - PolygonHairlinePrimitive2D (hairline curves/polygons)
74
            - PolyPolygonColorPrimitive2D (colored polygons)
75
76
            Grouping Primitives:
77
78
            - TransparencePrimitive2D (objects with freely defined transparence)
79
            - InvertPrimitive2D (for XOR)
80
            - MaskPrimitive2D (for masking)
81
            - ModifiedColorPrimitive2D (for a stack of color modifications)
82
            - TransformPrimitive2D (for a transformation stack)
83
84
            A processor doing so is a minimal processor. Of course a processor may
85
            handle any higher-level primitive (that has a decomposition implementation)
86
            for more direct data access or performance reasons, too.
87
88
            The main part of a processBasePrimitive2D implementation is a switch..case
89
            construct, looking like the following:
90
91
            void foo::processBasePrimitive2D(const BasePrimitive2D& rCandidate)
92
            {
93
                switch(rCandidate.getPrimitive2DID())
94
                {
95
                    case PRIMITIVE2D_ID_??? :
96
                    {
97
                        // process PRIMITIVE2D_ID_??? here...
98
99
                        ...
100
101
                        break;
102
                    }
103
104
                    ...
105
106
                    default :
107
                    {
108
                        // process recursively
109
                        process(rCandidate.get2DDecomposition(getViewInformation2D()));
110
                        break;
111
                    }
112
                }
113
            }
114
115
            The default case makes the processor work with all complex primitives
116
            by recursively using their decomposition.
117
118
            You can also add a case for ignoring primitives by using:
119
120
                    case PRIMITIVE2D_ID_...IGNORE.A.. :
121
                    case PRIMITIVE2D_ID_...IGNORE.B.. :
122
                    case PRIMITIVE2D_ID_...IGNORE.C.. :
123
                    {
124
                        // ignore these primitives by neither processing nor
125
                        // recursively processing their decomposition
126
                        break;
127
                    }
128
129
            Another useful case is embedding the processing of a complex primitive by
130
            bracketing it with some actions:
131
132
                    case PRIMITIVE2D_ID_SOME_TEXT :
133
                    {
134
                        // encapsulate e.g. with changing local variables, e.g.
135
                        // sometimes it's good to know if a basic primitive is
136
                        // part of a text, especially when not handling the text
137
                        // self but by purpose want to handle the decomposed
138
                        // geometries in the processor
139
                        startText();
140
                        process(rCandidate.get2DDecomposition(getViewInformation2D()));
141
                        endText();
142
                        break;
143
                    }
144
145
            As an example a processor collecting the outlines of a sequence of primitives
146
            only needs to handle some Basic Primitives and create outline and collect
147
            outline polygons e.g. for primitives with area like BitmapPrimitive2D (a
148
            rectangle) and PolyPolygonColorPrimitive2D. When also handling the Grouping
149
            Primitives MaskPrimitive2D (e.g. ignoring its content, using the mask polyPolygon)
150
            and TransformPrimitive2D (to have the correct local transformation), a processor
151
            creating the outline can be written using just four (4) primitives. As a tipp, it can
152
            be helpful to add many for the purpose not interesting higher level primitives
153
            to not force their decomposition to be created and/or parsed.
154
         */
155
        class DRAWINGLAYER_DLLPUBLIC BaseProcessor2D : public  drawinglayer::primitive2d::Primitive2DDecompositionVisitor
156
        {
157
        private:
158
            /// The ViewInformation2D itself. It's private to isolate accesses to it
159
            geometry::ViewInformation2D                     maViewInformation2D;
160
161
        protected:
162
            /*  callback method to allow the implementations to react on changes
163
                to the current ViewInformation2D if needed (e.g. when your impl/
164
                derivation needs to react on AA change)
165
             */
166
0
            virtual void onViewInformation2DChanged() {}
167
168
            /*  as tooling, the process() implementation takes over API handling and calls this
169
                virtual render method when the primitive implementation is BasePrimitive2D-based.
170
                Default implementation does nothing
171
             */
172
            virtual void processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate);
173
174
            void process(const primitive2d::BasePrimitive2D& rCandidate);
175
176
            // Primitive2DDecompositionVisitor
177
            virtual void visit(const primitive2d::Primitive2DReference&) override final;
178
            virtual void visit(const primitive2d::Primitive2DContainer&) override final;
179
            virtual void visit(primitive2d::Primitive2DContainer&&) override final;
180
181
        public:
182
            /// constructor/destructor
183
            explicit BaseProcessor2D(geometry::ViewInformation2D aViewInformation);
184
            virtual ~BaseProcessor2D();
185
186
            /// the central processing method
187
            void process(const primitive2d::Primitive2DContainer& rSource);
188
189
            /// data read/write access to ViewInformation2D
190
378k
            const geometry::ViewInformation2D& getViewInformation2D() const { return maViewInformation2D; }
191
            void setViewInformation2D(const geometry::ViewInformation2D& rNew);
192
        };
193
194
} // end of namespace drawinglayer::processor2d
195
196
197
#endif //INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX
198
199
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */