| 1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_ATTRIBUTES_H_ |
| 6 | #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_ATTRIBUTES_H_ |
| 7 | |
| 8 | #include <memory> |
| 9 | |
| 10 | namespace flutter { |
| 11 | |
| 12 | // =========================================================================== |
| 13 | |
| 14 | // The base class for a family of DisplayList attribute classes. |
| 15 | // |
| 16 | // This class is designed to support the following properties for any |
| 17 | // attribute to facilitate the storage of the attribute in a DisplayList |
| 18 | // and for use in code that inspects or creates DisplayList objects: |
| 19 | // |
| 20 | // - Typed: |
| 21 | // Even though most references and pointers are passed around as the |
| 22 | // attribute's base class, a Type property can be queried using the |type| |
| 23 | // method to determine which type of the attribute is being used. For |
| 24 | // example, the Blend type of ColorFilter will return DlColorFilter::kBlend |
| 25 | // from its type method. |
| 26 | // |
| 27 | // - Inspectable: |
| 28 | // Any parameters required to full specify the action of the attribute are |
| 29 | // provided on the type-specific classes. |
| 30 | // |
| 31 | // - Safely Downcast: |
| 32 | // For the subclasses that have specific data to query, methods are |
| 33 | // provided to safely downcast the reference for inspection. The down |
| 34 | // casting method will either return a pointer to the instance with |
| 35 | // its type-specific class type, or nullptr if it is executed on the |
| 36 | // wrong type of instance. |
| 37 | // (eg. DlColorFilter::asBlend() or DlMaskFilter::asBlur()) |
| 38 | // |
| 39 | // - Immutable: |
| 40 | // Neither the base class or any of the subclasses specify any mutation |
| 41 | // methods. Instances are often passed around as const as a reminder, |
| 42 | // but the classes have no mutation methods anyway. |
| 43 | // |
| 44 | // - Flat and Embeddable: |
| 45 | // Bulk freed + bulk compared + zero memory fragmentation. |
| 46 | // |
| 47 | // All of these classes are designed to be stored in the DisplayList |
| 48 | // buffer allocated in-line with the rest of the data to avoid dangling |
| 49 | // pointers that require explicit freeing when the DisplayList goes |
| 50 | // away, or that fragment the memory needed to read the operations in |
| 51 | // the DisplayList. Furthermore, the data in the classes can be bulk |
| 52 | // compared using a |memcmp| when performing a |DisplayList::Equals|. |
| 53 | // |
| 54 | // - Passed by Pointer: |
| 55 | // The data shared via the |DlOpReceiver::set<Attribute>| calls are stored |
| 56 | // in the buffer itself and so their lifetime is controlled by the |
| 57 | // DisplayList. That memory cannot be shared as by a |shared_ptr| |
| 58 | // because the memory may be freed outside the control of the shared |
| 59 | // pointer. Creating a shared version of the object would require a |
| 60 | // new instantiation which we'd like to avoid on every dispatch call, |
| 61 | // so a raw (const) pointer is shared in those dispatch calls instead, |
| 62 | // with all of the responsibilities of non-ownership in the called method. |
| 63 | // |
| 64 | // But, for methods that need to keep a copy of the data... |
| 65 | // |
| 66 | // - Shared_Ptr-able: |
| 67 | // The classes support a method to return a |std::shared_ptr| version of |
| 68 | // themselves, safely instantiating a new copy of the object into a |
| 69 | // shared_ptr using |std::make_shared|. For those receiver objects |
| 70 | // that may want to hold on to the contents of the object (typically |
| 71 | // in a |current_attribute_| field), they can obtain a shared_ptr |
| 72 | // copy safely and easily using the |shared| method. |
| 73 | |
| 74 | // =========================================================================== |
| 75 | |
| 76 | // |D| is the base type for the attribute |
| 77 | // (i.e. DlColorFilter, etc.) |
| 78 | // |T| is the enum that describes the specific subclasses |
| 79 | // (i.e DlColorFilterType, etc.) |
| 80 | template <class D, typename T> |
| 81 | class DlAttribute { |
| 82 | public: |
| 83 | // Return the recognized specific type of the attribute. |
| 84 | virtual T type() const = 0; |
| 85 | |
| 86 | // Return the size of the instantiated data (typically used to allocate) |
| 87 | // storage in the DisplayList buffer. |
| 88 | virtual size_t size() const = 0; |
| 89 | |
| 90 | // Return a shared version of |this| attribute. The |shared_ptr| returned |
| 91 | // will reference a copy of this object so that the lifetime of the shared |
| 92 | // version is not tied to the storage of this particular instance. |
| 93 | virtual std::shared_ptr<D> shared() const = 0; |
| 94 | |
| 95 | // Perform a content aware |==| comparison of the Attribute. |
| 96 | bool operator==(D const& other) const { |
| 97 | return type() == other.type() && equals_(other); |
| 98 | } |
| 99 | // Perform a content aware |!=| comparison of the Attribute. |
| 100 | bool operator!=(D const& other) const { return !(*this == other); } |
| 101 | |
| 102 | virtual ~DlAttribute() = default; |
| 103 | |
| 104 | protected: |
| 105 | // Virtual comparison method to support |==| and |!=|. |
| 106 | virtual bool equals_(D const& other) const = 0; |
| 107 | }; |
| 108 | |
| 109 | } // namespace flutter |
| 110 | |
| 111 | #endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_ATTRIBUTES_H_ |
| 112 | |