18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/*
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2006 The Android Open Source Project
38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifndef SkFlattenable_DEFINED
98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SkFlattenable_DEFINED
108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkRefCnt.h"
128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgclass SkReadBuffer;
148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgclass SkWriteBuffer;
158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
169fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#define SK_SUPPORT_LEGACY_DEEPFLATTENING
179fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
189fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed/*
199fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  Flattening is straight-forward:
209fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *      1. call getFactory() so we have a function-ptr to recreate the subclass
219fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *      2. call flatten(buffer) to write out enough data for the factory to read
229fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *
239fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  Unflattening is easy for the caller: new_instance = factory(buffer)
249fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *
259fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  The complexity of supporting this is as follows.
269fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *
279fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  If your subclass wants to control unflattening, use this macro in your declaration:
289fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *      SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS
299fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  This will provide a getFactory(), and require that the subclass implements CreateProc.
309fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *
319fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  For older buffers (before the DEEPFLATTENING change, the macros below declare
329fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  a thin factory DeepCreateProc. It checks the version of the buffer, and if it is pre-deep,
339fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  then it calls through to a (usually protected) constructor, passing the buffer.
349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed *  If the buffer is newer, then it directly calls the "real" factory: CreateProc.
359fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed */
36d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com
37a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com#define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() static void InitializeFlattenables();
38d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com
39d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(flattenable) \
40a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com    void flattenable::InitializeFlattenables() {
41a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com
42d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END \
43d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com    }
44d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com
45ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com#define SK_DECLARE_UNFLATTENABLE_OBJECT() \
46c2eae4795478ab134a2315b1a9ff2c5de1d049e4robertphillips@google.com    virtual Factory getFactory() const SK_OVERRIDE { return NULL; }
47ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com
489fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
499fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
509fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkFlattenable::Registrar(#flattenable, flattenable::DeepCreateProc, \
519fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                             flattenable::GetFlattenableType());
529fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
539fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable)    \
549fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    private:                                                                \
559fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    static SkFlattenable* CreateProc(SkReadBuffer&);                        \
569fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    static SkFlattenable* DeepCreateProc(SkReadBuffer& buffer) {            \
579fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        if (NeedsDeepUnflatten(buffer)) {                                   \
589fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed            return SkNEW_ARGS(flattenable, (buffer));                       \
599fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        }                                                                   \
609fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return CreateProc(buffer);                                          \
619fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }                                                                       \
629fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    friend class SkPrivateEffectInitializer;                                \
639fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    public:                                                                 \
649fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    virtual Factory getFactory() const SK_OVERRIDE {return DeepCreateProc;}
659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#else
669fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
679fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    SkFlattenable::Registrar(#flattenable, flattenable::CreateProc, \
689fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed                             flattenable::GetFlattenableType());
699fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
709fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable)    \
719fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    private:                                                                \
729fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    static SkFlattenable* CreateProc(SkReadBuffer&);                        \
739fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    friend class SkPrivateEffectInitializer;                                \
749fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    public:                                                                 \
759fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    virtual Factory getFactory() const SK_OVERRIDE { return CreateProc; }
769fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
779fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
789fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed// If your subclass will *never* need to be unflattened, declare this.
799fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#define SK_DECLARE_NOT_FLATTENABLE_PROCS(flattenable)   \
809fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    virtual Factory getFactory() const SK_OVERRIDE { return ReturnNullCreateProc; }
81ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com
82c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org/** For SkFlattenable derived objects with a valid type
83c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    This macro should only be used in base class objects in core
84c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org  */
85c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#define SK_DEFINE_FLATTENABLE_TYPE(flattenable) \
86c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    static Type GetFlattenableType() { \
87c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        return k##flattenable##_Type; \
88c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
89c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/** \class SkFlattenable
91fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkFlattenable is the base class for objects that need to be flattened
938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com into a data stream for either transport or as part of the key to the
948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com font cache.
958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com */
967ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgclass SK_API SkFlattenable : public SkRefCnt {
978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.compublic:
98c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    enum Type {
99c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        kSkColorFilter_Type,
100c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        kSkDrawLooper_Type,
101c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        kSkImageFilter_Type,
102c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        kSkMaskFilter_Type,
103c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        kSkPathEffect_Type,
104c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        kSkPixelRef_Type,
105c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        kSkRasterizer_Type,
106c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        kSkShader_Type,
10783f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org        kSkUnused_Type,     // used to be SkUnitMapper
108c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        kSkXfermode_Type,
109c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    };
110c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
11115e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com    SK_DECLARE_INST_COUNT(SkFlattenable)
11215e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
1138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    typedef SkFlattenable* (*Factory)(SkReadBuffer&);
114fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkFlattenable() {}
116fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    /** Implement this to return a factory function pointer that can be called
1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     to recreate your class given a buffer (previously written to by your
1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     override of flatten().
1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com     */
121c2eae4795478ab134a2315b1a9ff2c5de1d049e4robertphillips@google.com    virtual Factory getFactory() const = 0;
122fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
123c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    /** Returns the name of the object's class
124c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org      */
125c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    const char* getTypeName() const { return FactoryToName(getFactory()); }
126c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static Factory NameToFactory(const char name[]);
1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    static const char* FactoryToName(Factory);
129c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    static bool NameToType(const char name[], Type* type);
130c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
131c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    static void Register(const char name[], Factory, Type);
132a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    class Registrar {
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    public:
135c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        Registrar(const char name[], Factory factory, Type type) {
136c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org            SkFlattenable::Register(name, factory, type);
1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        }
1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    };
139a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com
1409fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    /**
1419fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed     *  Override this if your subclass needs to record data that it will need to recreate itself
1429fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed     *  from its CreateProc (returned by getFactory()).
14354924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com     */
1449fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    virtual void flatten(SkWriteBuffer&) const {}
1458b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org
1468b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgprotected:
1479fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
1489fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    static bool NeedsDeepUnflatten(const SkReadBuffer&);
1498b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    SkFlattenable(SkReadBuffer&) {}
1509fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif
1519fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed
1529fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    static SkFlattenable* ReturnNullCreateProc(SkReadBuffer&) {
1539fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed        return NULL;
1549fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed    }
155d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com
156d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comprivate:
157c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    static void InitializeFlattenablesIfNeeded();
1589d0c6ecb8440e8e546881a4ff850eb6333f24541caryclark@google.com
1599d0c6ecb8440e8e546881a4ff850eb6333f24541caryclark@google.com    friend class SkGraphics;
16015e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com
16115e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com    typedef SkRefCnt INHERITED;
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com};
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif
165