11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#ifndef SkGroupShape_DEFINED
940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#define SkGroupShape_DEFINED
1040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkMatrix.h"
1240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkShape.h"
1340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkTDArray.h"
1440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkThread.h"
1540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergertemplate <typename T> class SkTRefCnt : public T {
1740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerpublic:
1840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkTRefCnt() : fRefCnt(1) {}
1940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    ~SkTRefCnt() { SkASSERT(1 == fRefCnt); }
2040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
2140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int32_t getRefCnt() const { return fRefCnt; }
2240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
2340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    /** Increment the reference count. Must be balanced by a call to unref().
2440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger     */
2540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    void ref() const {
2640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(fRefCnt > 0);
2740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        sk_atomic_inc(&fRefCnt);
2840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
2940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
3040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    /** Decrement the reference count. If the reference count is 1 before the
3140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        decrement, then call delete on the object. Note that if this is the
3240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        case, then the object needs to have been allocated via new, and not on
3340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        the stack.
3440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger     */
3540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    void unref() const {
3640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkASSERT(fRefCnt > 0);
3740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (sk_atomic_dec(&fRefCnt) == 1) {
3840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            fRefCnt = 1;    // so our destructor won't complain
3940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkDELETE(this);
4040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
4140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
4240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    static void SafeRef(const SkTRefCnt* obj) {
4440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (obj) {
4540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            obj->ref();
4640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
4740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
4840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
4940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    static void SafeUnref(const SkTRefCnt* obj) {
5040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        if (obj) {
5140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            obj->unref();
5240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        }
5340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
5440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerprivate:
5640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    mutable int32_t fRefCnt;
5740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger};
5840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
5940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerclass SkMatrixRef : public SkTRefCnt<SkMatrix> {
6040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerpublic:
6140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkMatrixRef() { this->reset(); }
6240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    explicit SkMatrixRef(const SkMatrix& matrix) {
6340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkMatrix& m = *this;
6440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        m = matrix;
6540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
6640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkMatrix& operator=(const SkMatrix& matrix) {
6840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkMatrix& m = *this;
6940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        m = matrix;
7040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return m;
7140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
7240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger};
7340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerclass SkGroupShape : public SkShape {
7540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerpublic:
7640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkGroupShape();
7740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    virtual ~SkGroupShape();
7840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    /** Return the number of child shapes in this group
8040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger     */
8140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    int countShapes() const;
8240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
8340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    /** Return the shape at the specified index. Note this does not affect the
8440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        owner count of the index'd shape. If index is out of range, returns NULL
8540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger     */
8640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkShape* getShape(int index, SkMatrixRef** = NULL) const;
8740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
8840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    /** Helper function to return the matrixref of the specified shape.
8940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger     */
9040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkMatrixRef* getShapeMatrixRef(int index) const {
9140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkMatrixRef* mr = NULL;
9240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        (void)this->getShape(index, &mr);
9340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return mr;
9440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
9540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
9640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    /** Ref the specified shape, and insert it into the child list at the
9740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        specified index. If index == countShapes(), then the shape will be
9840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        appended to the child list, otherwise if index is out of range, the
9940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        shape is not added. Either way, the shape parameter is returned.
10040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
10140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        Child shapes are drawn in order, after the parent, so the shape at index
10240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        0 will be drawn first, and the shape at index countShapes() - 1 will be
10340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        drawn last.
10440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger     */
10540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    void addShape(int index, SkShape*, SkMatrixRef* = NULL);
10640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
10740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    void addShape(int index, SkShape* shape, const SkMatrix& matrix) {
10840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkMatrixRef* mr = SkNEW_ARGS(SkMatrixRef, (matrix));
10940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        this->addShape(index, shape, mr);
11040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        mr->unref();
11140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
11240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
11340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    /** Helper method to append a shape, passing countShapes() for the index
11440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger     */
11540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkShape* appendShape(SkShape* shape, SkMatrixRef* mr = NULL) {
11640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        this->addShape(this->countShapes(), shape, mr);
11740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return shape;
11840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
11940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
12040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkShape* appendShape(SkShape* shape, const SkMatrix& matrix) {
12140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        this->addShape(this->countShapes(), shape, matrix);
12240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        return shape;
12340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
12440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
12540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    /** Unref the specified index, and remove it from the child list. If index
12640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        is out of range, does nothing.
12740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger     */
12840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    void removeShape(int index);
12940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
13040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    /** Unrefs and removes all of the child shapes
13140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger     */
13240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    void removeAllShapes();
13340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
13440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // overrides
13540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    virtual Factory getFactory();
13640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    virtual void flatten(SkFlattenableWriteBuffer&);
13740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
13840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // public for Registrar
13940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    static SkFlattenable* CreateProc(SkFlattenableReadBuffer&);
14040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SK_DECLARE_FLATTENABLE_REGISTRAR()
1421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
14340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerprotected:
14440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // overrides
14540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    virtual void onDraw(SkCanvas*);
14640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
14740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkGroupShape(SkFlattenableReadBuffer&);
14840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
14940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerprivate:
15040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    struct Rec {
15140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkShape*     fShape;
15240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        SkMatrixRef* fMatrixRef;
15340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    };
15440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkTDArray<Rec> fList;
15540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
15640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    typedef SkShape INHERITED;
15740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger};
15840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
15940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#endif
160