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 #pragma once 21 22 #include <drawinglayer/drawinglayerdllapi.h> 23 24 #include <cppuhelper/compbase.hxx> 25 #include <drawinglayer/primitive2d/Primitive2DContainer.hxx> 26 #include <com/sun/star/util/XAccounting.hpp> 27 #include <cppuhelper/basemutex.hxx> 28 #include <basegfx/range/b2drange.hxx> 29 30 /** defines ImplPrimitive2DIDBlock 31 Added to be able to simply change identification stuff later, e.g. add 32 an identification string and/or ID to the interface and to the implementation 33 ATM used to delclare implement getPrimitive2DID() 34 */ 35 36 #define ImplPrimitive2DIDBlock(TheClass, TheID) \ 37 sal_uInt32 TheClass::getPrimitive2DID() const { return TheID; } 38 39 namespace drawinglayer::geometry 40 { 41 class ViewInformation2D; 42 } 43 44 namespace drawinglayer::primitive2d 45 { 46 typedef cppu::WeakComponentImplHelper<css::graphic::XPrimitive2D, css::util::XAccounting> 47 BasePrimitive2DImplBase; 48 49 /** BasePrimitive2D class 50 51 Baseclass for all C++ implementations of css::graphic::XPrimitive2D 52 53 This class is strongly virtual due to the lack of getPrimitiveID() implementation. 54 This is by purpose, this base class shall not be incarnated and be used directly as 55 a XPrimitive2D. 56 57 It is noncopyable to make clear that a primitive is a read-only 58 instance and copying or changing values is not intended. The idea is to hold all data 59 needed for visualisation of this primitive in unchangeable form. 60 61 It is derived from cppu::BaseMutex to have a Mutex at hand; in a base 62 implementation this may not be needed, but e.g. when buffering at last decomposition 63 in a local member, multiple threads may try to decompose at the same time, so locking 64 is needed to avoid race conditions seen from the UNO object implementation. 65 66 A method to get a simplified representation is provided by get2DDecomposition. The 67 default implementation returns an empty sequence. The idea is that processors 68 using this primitive and do not know it, may get the decomposition and process 69 these instead. An example is e.g. a fat line, who's decomposition may contain 70 the geometric representation of that line using filled polygon primitives. When 71 the renderer knows how to handle fat lines, he may process this primitive directly; 72 if not he can use the decomposition. With this functionality, renderers may operate by 73 knowing only a small set of primitives. 74 75 When a primitive does not implement get2DDecomposition, it is called a 'Basic Primitive' and 76 belongs to the set of primitives which a processor should be able to handle. Practice 77 will define this minimal sets of primitives. When defined and the concept is proved, 78 unique UNO APIs may be defined/implemented for these set to allow more intense work 79 with primitives using UNO. 80 81 Current Basic 2D Primitives are: 82 83 - BitmapPrimitive2D (bitmap data, evtl. with transparence) 84 - PointArrayPrimitive2D (single points) 85 - PolygonHairlinePrimitive2D (hairline curves/polygons) 86 - PolyPolygonColorPrimitive2D (colored polygons) 87 88 UPDATE: MetafilePrimitive2D (VCL Metafile) is taken off this list since 89 it is implemented with the integration of CWS aw078 into DV300m69. 90 91 All other implemented primitives have a defined decomposition and can thus be 92 decomposed down to this small set. 93 94 A renderer implementing support for this minimal set of primitives can completely 95 render primitive-based visualisations. Of course, he also has to take states into account 96 which are represented by GroupPrimitive2D derivations, see groupprimitive2d.hxx 97 98 To support getting the geometric BoundRect, getB2DRange is used. The default 99 implementation will use the get2DDecomposition result and merge a range from the 100 entries. Thus, an implementation is only necessary for the Basic Primitives, but 101 of course speedups are possible (and are used) by implementing the method at higher-level 102 primitives. 103 104 For primitive identification, getPrimitiveID is used currently in this implementations 105 to allow a fast switch/case processing. This needs a unique identifier mechanism which 106 currently uses defines (see drawinglayer_primitivetypes2d.hxx). For UNO primitive API 107 it will be needed to add a unique descriptor (Name?) later to the API. 108 109 This base implementation provides mappings from the methods from XPrimitive2D 110 (getDecomposition/getRange) to the appropriate methods in the C++ implementations 111 (get2DDecomposition/getB2DRange). The PropertyValue ViewParameters is converted to 112 the appropriate C++ implementation class ViewInformation2D. 113 114 This base class does not implement any buffering; e.g. buffering the decomposition 115 and/or the range. These may be buffered anytime since the definition is that the primitive 116 is read-only and thus unchangeable. This implies that the decomposition and/or getting 117 the range will lead to the same result as last time, under the precondition that 118 the parameter ViewInformation2D is the same as the last one. This is usually the case 119 for view-independent primitives which are defined by not using ViewInformation2D 120 in their get2DDecomposition/getB2DRange implementations. 121 */ 122 class DRAWINGLAYER_DLLPUBLIC BasePrimitive2D : protected cppu::BaseMutex, 123 public BasePrimitive2DImplBase 124 { 125 BasePrimitive2D(const BasePrimitive2D&) = delete; 126 BasePrimitive2D& operator=(const BasePrimitive2D&) = delete; 127 128 public: 129 // constructor/destructor 130 BasePrimitive2D(); 131 virtual ~BasePrimitive2D() override; 132 133 /** the ==operator is mainly needed to allow testing newly-created primitives against their last 134 incarnation which buffers/holds the made decompositions. The default implementation 135 uses getPrimitive2DID()-calls to test if it's the same ID at last. 136 Overridden implementations are then based on this implementation 137 */ 138 virtual bool operator==(const BasePrimitive2D& rPrimitive) const; operator !=(const BasePrimitive2D & rPrimitive) const139 bool operator!=(const BasePrimitive2D& rPrimitive) const { return !operator==(rPrimitive); } 140 141 /// The default implementation will use getDecomposition results to create the range 142 virtual basegfx::B2DRange 143 getB2DRange(const geometry::ViewInformation2D& rViewInformation) const; 144 145 /** provide unique ID for fast identifying of known primitive implementations in renderers. These use 146 the defines from drawinglayer_primitivetypes2d.hxx to define unique IDs. 147 */ 148 virtual sal_uInt32 getPrimitive2DID() const = 0; 149 150 /// The default implementation will return an empty sequence 151 virtual void get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, 152 const geometry::ViewInformation2D& rViewInformation) const; 153 154 // Methods from XPrimitive2D 155 156 /** The getDecomposition implementation for UNO API will use getDecomposition from this implementation. It 157 will construct a ViewInformation2D from the ViewParameters for that purpose 158 */ 159 virtual css::uno::Sequence<::css::uno::Reference<::css::graphic::XPrimitive2D>> SAL_CALL 160 getDecomposition(const css::uno::Sequence<css::beans::PropertyValue>& rViewParameters) override; 161 162 /** The getRange implementation for UNO API will use getRange from this implementation. It 163 will construct a ViewInformation2D from the ViewParameters for that purpose 164 */ 165 virtual css::geometry::RealRectangle2D SAL_CALL 166 getRange(const css::uno::Sequence<css::beans::PropertyValue>& rViewParameters) override; 167 168 // XAccounting 169 virtual sal_Int64 SAL_CALL estimateUsage() override; 170 }; 171 172 /** BufferedDecompositionPrimitive2D class 173 174 Baseclass for all C++ implementations of css::graphic::XPrimitive2D 175 which want to buffer the decomposition result 176 177 Buffering the decomposition is the most-used buffering and is thus used my most 178 primitive implementations which support a decomposition as base class. 179 180 The buffering is done by holding the last decomposition in the local parameter 181 maBuffered2DDecomposition. The default implementation of get2DDecomposition checks 182 if maBuffered2DDecomposition is empty. If yes, it uses create2DDecomposition 183 to create the content. In all cases, maBuffered2DDecomposition is returned. 184 185 For view-dependent primitives derived from Primitive2DBufferDecomposition more needs 186 to be done when the decomposition depends on parts of the parameter ViewInformation2D. 187 This defines a standard method for processing these: 188 189 Implement a view-dependent get2DDecomposition doing the following steps: 190 (a) Locally extract needed parameters from ViewInformation2D to new, local parameters 191 (this may be a complete local copy of ViewInformation2D) 192 (b) If a buffered decomposition exists, ckeck if one of the new local parameters 193 differs from the corresponding locally remembered (as member) ones. If yes, 194 clear maBuffered2DDecomposition 195 (d) call baseclass::get2DDecomposition which will use create2DDecomposition 196 to fill maBuffered2DDecomposition if it's empty 197 (e) copy the new local parameters to the corresponding locally remembered ones 198 to identify if a new decomposition is needed at the next call 199 (f) return maBuffered2DDecomposition 200 */ 201 class DRAWINGLAYER_DLLPUBLIC BufferedDecompositionPrimitive2D : public BasePrimitive2D 202 { 203 private: 204 /// a sequence used for buffering the last create2DDecomposition() result 205 Primitive2DContainer maBuffered2DDecomposition; 206 207 /// When a shadow wraps a list of primitives, this primitive wants to influence the transparency 208 /// of the shadow. 209 sal_uInt16 mnTransparenceForShadow = 0; 210 211 protected: 212 /** access methods to maBuffered2DDecomposition. The usage of this methods may allow 213 later thread-safe stuff to be added if needed. Only to be used by getDecomposition() 214 implementations for buffering the last decomposition. 215 */ getBuffered2DDecomposition() const216 const Primitive2DContainer& getBuffered2DDecomposition() const 217 { 218 return maBuffered2DDecomposition; 219 } setBuffered2DDecomposition(const Primitive2DContainer & rNew)220 void setBuffered2DDecomposition(const Primitive2DContainer& rNew) 221 { 222 maBuffered2DDecomposition = rNew; 223 } 224 225 /** method which is to be used to implement the local decomposition of a 2D primitive. */ 226 virtual void 227 create2DDecomposition(Primitive2DContainer& rContainer, 228 const geometry::ViewInformation2D& rViewInformation) const = 0; 229 230 public: 231 // constructor/destructor 232 BufferedDecompositionPrimitive2D(); 233 234 /** The getDecomposition default implementation will on demand use create2DDecomposition() if 235 maBuffered2DDecomposition is empty. It will set maBuffered2DDecomposition to this obtained decomposition 236 to buffer it. If the decomposition is also ViewInformation2D-dependent, this method needs to be 237 overridden and the ViewInformation2D for the last decomposition need to be remembered, too, and 238 be used in the next call to decide if the buffered decomposition may be reused or not. 239 */ 240 virtual void 241 get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, 242 const geometry::ViewInformation2D& rViewInformation) const override; 243 setTransparenceForShadow(sal_uInt16 nTransparenceForShadow)244 void setTransparenceForShadow(sal_uInt16 nTransparenceForShadow) 245 { 246 mnTransparenceForShadow = nTransparenceForShadow; 247 } 248 getTransparenceForShadow() const249 sal_uInt16 getTransparenceForShadow() const { return mnTransparenceForShadow; } 250 }; 251 252 } // end of namespace drawinglayer::primitive2d 253 254 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 255