blob: 679f640d3c4012a7868486f9a02bdef4b3325d5f [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00003 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00004 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00006 */
7
8#ifndef SkFlattenable_DEFINED
9#define SkFlattenable_DEFINED
10
11#include "SkRefCnt.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000012
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000013class SkReadBuffer;
14class SkWriteBuffer;
reed@android.com8a1c16f2008-12-17 15:59:43 +000015
reed9fa60da2014-08-21 07:59:51 -070016#define SK_SUPPORT_LEGACY_DEEPFLATTENING
17
18/*
19 * Flattening is straight-forward:
20 * 1. call getFactory() so we have a function-ptr to recreate the subclass
21 * 2. call flatten(buffer) to write out enough data for the factory to read
22 *
23 * Unflattening is easy for the caller: new_instance = factory(buffer)
24 *
25 * The complexity of supporting this is as follows.
26 *
27 * If your subclass wants to control unflattening, use this macro in your declaration:
28 * SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS
29 * This will provide a getFactory(), and require that the subclass implements CreateProc.
30 *
31 * For older buffers (before the DEEPFLATTENING change, the macros below declare
32 * a thin factory DeepCreateProc. It checks the version of the buffer, and if it is pre-deep,
33 * then it calls through to a (usually protected) constructor, passing the buffer.
34 * If the buffer is newer, then it directly calls the "real" factory: CreateProc.
35 */
djsollen@google.coma2ca41e2012-03-23 19:00:34 +000036
37#define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() static void InitializeFlattenables();
38
39#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(flattenable) \
40 void flattenable::InitializeFlattenables() {
41
caryclark@google.comd26147a2011-12-15 14:16:43 +000042#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END \
43 }
44
djsollen@google.comba28d032012-03-26 17:57:35 +000045#define SK_DECLARE_UNFLATTENABLE_OBJECT() \
robertphillips@google.comc2eae472013-10-21 12:26:10 +000046 virtual Factory getFactory() const SK_OVERRIDE { return NULL; }
djsollen@google.comba28d032012-03-26 17:57:35 +000047
reed9fa60da2014-08-21 07:59:51 -070048#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
49#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
50 SkFlattenable::Registrar(#flattenable, flattenable::DeepCreateProc, \
51 flattenable::GetFlattenableType());
52
53#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \
54 private: \
55 static SkFlattenable* CreateProc(SkReadBuffer&); \
56 static SkFlattenable* DeepCreateProc(SkReadBuffer& buffer) { \
57 if (NeedsDeepUnflatten(buffer)) { \
58 return SkNEW_ARGS(flattenable, (buffer)); \
59 } \
60 return CreateProc(buffer); \
61 } \
62 friend class SkPrivateEffectInitializer; \
63 public: \
64 virtual Factory getFactory() const SK_OVERRIDE {return DeepCreateProc;}
65#else
66#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
67 SkFlattenable::Registrar(#flattenable, flattenable::CreateProc, \
68 flattenable::GetFlattenableType());
69
70#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \
71 private: \
72 static SkFlattenable* CreateProc(SkReadBuffer&); \
73 friend class SkPrivateEffectInitializer; \
74 public: \
75 virtual Factory getFactory() const SK_OVERRIDE { return CreateProc; }
76#endif
77
78// If your subclass will *never* need to be unflattened, declare this.
79#define SK_DECLARE_NOT_FLATTENABLE_PROCS(flattenable) \
80 virtual Factory getFactory() const SK_OVERRIDE { return ReturnNullCreateProc; }
djsollen@google.comba28d032012-03-26 17:57:35 +000081
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +000082/** For SkFlattenable derived objects with a valid type
83 This macro should only be used in base class objects in core
84 */
85#define SK_DEFINE_FLATTENABLE_TYPE(flattenable) \
86 static Type GetFlattenableType() { \
87 return k##flattenable##_Type; \
88 }
89
reed@android.com8a1c16f2008-12-17 15:59:43 +000090/** \class SkFlattenable
rmistry@google.comfbfcd562012-08-23 18:09:54 +000091
reed@android.com8a1c16f2008-12-17 15:59:43 +000092 SkFlattenable is the base class for objects that need to be flattened
93 into a data stream for either transport or as part of the key to the
94 font cache.
95 */
ctguil@chromium.org7ffb1b22011-03-15 21:27:08 +000096class SK_API SkFlattenable : public SkRefCnt {
reed@android.com8a1c16f2008-12-17 15:59:43 +000097public:
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +000098 enum Type {
99 kSkColorFilter_Type,
100 kSkDrawLooper_Type,
101 kSkImageFilter_Type,
102 kSkMaskFilter_Type,
103 kSkPathEffect_Type,
104 kSkPixelRef_Type,
105 kSkRasterizer_Type,
106 kSkShader_Type,
commit-bot@chromium.org83f23d82014-05-22 12:27:41 +0000107 kSkUnused_Type, // used to be SkUnitMapper
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000108 kSkXfermode_Type,
109 };
110
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +0000111 SK_DECLARE_INST_COUNT(SkFlattenable)
112
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000113 typedef SkFlattenable* (*Factory)(SkReadBuffer&);
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000114
reed@android.com8a1c16f2008-12-17 15:59:43 +0000115 SkFlattenable() {}
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000116
reed@android.com8a1c16f2008-12-17 15:59:43 +0000117 /** Implement this to return a factory function pointer that can be called
118 to recreate your class given a buffer (previously written to by your
119 override of flatten().
120 */
robertphillips@google.comc2eae472013-10-21 12:26:10 +0000121 virtual Factory getFactory() const = 0;
rmistry@google.comfbfcd562012-08-23 18:09:54 +0000122
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000123 /** Returns the name of the object's class
124 */
125 const char* getTypeName() const { return FactoryToName(getFactory()); }
126
reed@android.com8a1c16f2008-12-17 15:59:43 +0000127 static Factory NameToFactory(const char name[]);
128 static const char* FactoryToName(Factory);
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000129 static bool NameToType(const char name[], Type* type);
130
131 static void Register(const char name[], Factory, Type);
djsollen@google.coma2ca41e2012-03-23 19:00:34 +0000132
reed@android.com8a1c16f2008-12-17 15:59:43 +0000133 class Registrar {
134 public:
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000135 Registrar(const char name[], Factory factory, Type type) {
136 SkFlattenable::Register(name, factory, type);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137 }
138 };
djsollen@google.coma2ca41e2012-03-23 19:00:34 +0000139
reed9fa60da2014-08-21 07:59:51 -0700140 /**
141 * Override this if your subclass needs to record data that it will need to recreate itself
142 * from its CreateProc (returned by getFactory()).
djsollen@google.com54924242012-03-29 15:18:04 +0000143 */
reed9fa60da2014-08-21 07:59:51 -0700144 virtual void flatten(SkWriteBuffer&) const {}
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000145
146protected:
reed9fa60da2014-08-21 07:59:51 -0700147#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
148 static bool NeedsDeepUnflatten(const SkReadBuffer&);
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000149 SkFlattenable(SkReadBuffer&) {}
reed9fa60da2014-08-21 07:59:51 -0700150#endif
151
152 static SkFlattenable* ReturnNullCreateProc(SkReadBuffer&) {
153 return NULL;
154 }
caryclark@google.comd26147a2011-12-15 14:16:43 +0000155
156private:
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000157 static void InitializeFlattenablesIfNeeded();
caryclark@google.com9d0c6ec2011-12-20 20:26:56 +0000158
159 friend class SkGraphics;
robertphillips@google.com15e9d3e2012-06-21 20:25:03 +0000160
161 typedef SkRefCnt INHERITED;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000162};
163
reed@android.com8a1c16f2008-12-17 15:59:43 +0000164#endif