15bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com
2f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/*
35bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * Copyright 2006 The Android Open Source Project
4f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com *
55bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * Use of this source code is governed by a BSD-style license that can be
65bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com * found in the LICENSE file.
7f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com */
8f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
95bb6825f10d64834ad1d1d967f590aebae285360epoger@google.com
10f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#ifndef SkMaskFilter_DEFINED
11f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#define SkMaskFilter_DEFINED
12f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
13f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#include "SkFlattenable.h"
14f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#include "SkMask.h"
15ddd97b8f3489ebec7dd4f910f60f8ff1abe662cfjunov@chromium.org#include "SkPaint.h"
16f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
1788e6fa4b028e00821af249b74e8f6ba8bfb6161fsenorblanco@chromium.orgclass GrContext;
18b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.comclass SkBitmap;
19f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comclass SkBlitter;
20f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comclass SkBounder;
21f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comclass SkMatrix;
22f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comclass SkPath;
23e4da18ed69645153fb8b8de303fe2138f75ff9f1reed@google.comclass SkRasterClip;
24f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.comclass SkRRect;
25f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
26f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com/** \class SkMaskFilter
27f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
28f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    SkMaskFilter is the base class for object that perform transformations on
29f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    an alpha-channel mask before drawing it. A subclass of SkMaskFilter may be
30f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    installed into a SkPaint. Once there, each time a primitive is drawn, it
31f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    is first scan converted into a SkMask::kA8_Format mask, and handed to the
32f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    filter, calling its filterMask() method. If this returns true, then the
33f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    new mask is used to render into the device.
34f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
35f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    Blur and emboss are implemented as subclasses of SkMaskFilter.
36f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com*/
37596b4bf3487a924fd07099284a01545774c0936ebungeman@google.comclass SK_API SkMaskFilter : public SkFlattenable {
38f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.compublic:
394f0673f27c2dbb98a7cfebb87d1a5cf3ab5924derobertphillips@google.com    SK_DECLARE_INST_COUNT(SkMaskFilter)
404f0673f27c2dbb98a7cfebb87d1a5cf3ab5924derobertphillips@google.com
41f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    SkMaskFilter() {}
42f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
43f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    /** Returns the format of the resulting mask that this subclass will return
44f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        when its filterMask() method is called.
45f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    */
465161389e01c398f9bcb7ebd796e3570efc701775reed@google.com    virtual SkMask::Format getFormat() const = 0;
47f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
48f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    /** Create a new mask by filter the src mask.
49f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        If src.fImage == null, then do not allocate or create the dst image
50f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        but do fill out the other fields in dstMask.
51f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        If you do allocate a dst image, use SkMask::AllocImage()
52f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        If this returns false, dst mask is ignored.
53f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        @param  dst the result of the filter. If src.fImage == null, dst should not allocate its image
54f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        @param src the original image to be filtered.
55f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        @param matrix the CTM
56f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        @param margin   if not null, return the buffer dx/dy need when calculating the effect. Used when
57f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com                        drawing a clipped object to know how much larger to allocate the src before
58f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com                        applying the filter. If returning false, ignore this parameter.
59f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com        @return true if the dst mask was correctly created.
60f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    */
6117dbad75668e4504b634364f25526804f07579ffmike@reedtribe.org    virtual bool filterMask(SkMask* dst, const SkMask& src, const SkMatrix&,
625161389e01c398f9bcb7ebd796e3570efc701775reed@google.com                            SkIPoint* margin) const;
63f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
64b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com#if SK_SUPPORT_GPU
65b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com    /**
66b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  Returns true if the filter can be expressed a single-pass
67b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  GrEffect, used to process this filter on the GPU, or false if
68b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  not.
69b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *
70b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  If effect is non-NULL, a new GrEffect instance is stored
71b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  in it.  The caller assumes ownership of the stage, and it is up to the
72b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  caller to unref it.
73b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     */
74b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com    virtual bool asNewEffect(GrEffectRef** effect, GrTexture*) const;
756838c30b64c0834eca4808e52b7542800ba9639areed@google.com
76b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com    /**
77b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  Returns true if the filter can be processed on the GPU.  This is most
78b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  often used for multi-pass effects, where intermediate results must be
79b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  rendered to textures.  For single-pass effects, use asNewEffect().
80b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *
81b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  'maskRect' returns the device space portion of the mask the the filter
82b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  needs. The mask passed into 'filterMaskGPU' should have the same extent
83b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  as 'maskRect' but be translated to the upper-left corner of the mask
84b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  (i.e., (maskRect.fLeft, maskRect.fTop) appears at (0, 0) in the mask).
85b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     */
86aa51a24007d37f53161fd0d37dd3ae9385ba64f4skia.committer@gmail.com    virtual bool canFilterMaskGPU(const SkRect& devBounds,
87b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com                                  const SkIRect& clipBounds,
88b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com                                  const SkMatrix& ctm,
89b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com                                  SkRect* maskRect) const;
90b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com
91b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com    /**
92b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  Perform this mask filter on the GPU.  This is most often used for
93b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  multi-pass effects, where intermediate results must be rendered to
94b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  textures.  For single-pass effects, use asNewEffect().  'src' is the
95b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  source image for processing, as a texture-backed bitmap.  'result' is
96b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  the destination bitmap, which should contain a texture-backed pixelref
97b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  on success. 'maskRect' should be the rect returned from canFilterMaskGPU.
98b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     */
99b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com    bool filterMaskGPU(GrContext* context,
100aa51a24007d37f53161fd0d37dd3ae9385ba64f4skia.committer@gmail.com                       const SkBitmap& src,
101aa51a24007d37f53161fd0d37dd3ae9385ba64f4skia.committer@gmail.com                       const SkRect& maskRect,
102b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com                       SkBitmap* result) const;
1036838c30b64c0834eca4808e52b7542800ba9639areed@google.com
1046838c30b64c0834eca4808e52b7542800ba9639areed@google.com    /**
105b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  This flavor of 'filterMaskGPU' provides a more direct means of accessing
106b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  the filtering capabilities. Setting 'canOverwriteSrc' can allow some
107b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com     *  filters to skip the allocation of an additional texture.
1086838c30b64c0834eca4808e52b7542800ba9639areed@google.com     */
109aa51a24007d37f53161fd0d37dd3ae9385ba64f4skia.committer@gmail.com    virtual bool filterMaskGPU(GrTexture* src,
110aa51a24007d37f53161fd0d37dd3ae9385ba64f4skia.committer@gmail.com                               const SkRect& maskRect,
111b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com                               GrTexture** result,
112b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com                               bool canOverwriteSrc) const;
113b7bac7a8e47433ff63f465764708cb1a7c1dbfe4robertphillips@google.com#endif
1146838c30b64c0834eca4808e52b7542800ba9639areed@google.com
115dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com    /**
116dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com     * The fast bounds function is used to enable the paint to be culled early
117dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com     * in the drawing pipeline. This function accepts the current bounds of the
118dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com     * paint as its src param and the filter adjust those bounds using its
119dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com     * current mask and returns the result using the dest param. Callers are
120dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com     * allowed to provide the same struct for both src and dest so each
121dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com     * implementation must accomodate that behavior.
122dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com     *
123dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com     *  The default impl calls filterMask with the src mask having no image,
124dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com     *  but subclasses may override this if they can compute the rect faster.
125dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com     */
1265161389e01c398f9bcb7ebd796e3570efc701775reed@google.com    virtual void computeFastBounds(const SkRect& src, SkRect* dest) const;
127dc09cfb005daa2cb697782fed0eacbe70fe775c7reed@google.com
1289400375ea917539e64492350377cfa688473c4a1robertphillips@google.com    SkDEVCODE(virtual void toString(SkString* str) const = 0;)
1294035169372231efab50ead6ca20b4f4156146373commit-bot@chromium.org    SK_DEFINE_FLATTENABLE_TYPE(SkMaskFilter)
1309400375ea917539e64492350377cfa688473c4a1robertphillips@google.com
131f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.comprotected:
132f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com    // empty for now, but lets get our subclass to remember to init us for the future
133e133d6ad314603114c7ef80423391f65cbb599d7djsollen@google.com    SkMaskFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
134e4da18ed69645153fb8b8de303fe2138f75ff9f1reed@google.com
135311825d7199b715b715349edd00c3c97a96534fcreed@google.com    enum FilterReturn {
136311825d7199b715b715349edd00c3c97a96534fcreed@google.com        kFalse_FilterReturn,
137311825d7199b715b715349edd00c3c97a96534fcreed@google.com        kTrue_FilterReturn,
138311825d7199b715b715349edd00c3c97a96534fcreed@google.com        kUnimplemented_FilterReturn
139311825d7199b715b715349edd00c3c97a96534fcreed@google.com    };
140311825d7199b715b715349edd00c3c97a96534fcreed@google.com
14136568f626bfc620aed42fc8f7b5b255139dd51b7reed@google.com    struct NinePatch {
14236568f626bfc620aed42fc8f7b5b255139dd51b7reed@google.com        SkMask      fMask;      // fBounds must have [0,0] in its top-left
14336568f626bfc620aed42fc8f7b5b255139dd51b7reed@google.com        SkIRect     fOuterRect; // width/height must be >= fMask.fBounds'
14436568f626bfc620aed42fc8f7b5b255139dd51b7reed@google.com        SkIPoint    fCenter;    // identifies center row/col for stretching
14536568f626bfc620aed42fc8f7b5b255139dd51b7reed@google.com    };
14636568f626bfc620aed42fc8f7b5b255139dd51b7reed@google.com
147311825d7199b715b715349edd00c3c97a96534fcreed@google.com    /**
148311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  Override if your subclass can filter a rect, and return the answer as
149311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  a ninepatch mask to be stretched over the returned outerRect. On success
150311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  return kTrue_FilterReturn. On failure (e.g. out of memory) return
151311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  kFalse_FilterReturn. If the normal filterMask() entry-point should be
152311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  called (the default) return kUnimplemented_FilterReturn.
153311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *
154311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  By convention, the caller will take the center rol/col from the returned
155311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  mask as the slice it can replicate horizontally and vertically as we
156311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  stretch the mask to fit inside outerRect. It is an error for outerRect
157311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  to be smaller than the mask's bounds. This would imply that the width
158311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  and height of the mask should be odd. This is not required, just that
159311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  the caller will call mask.fBounds.centerX() and centerY() to find the
160311825d7199b715b715349edd00c3c97a96534fcreed@google.com     *  strips that will be replicated.
161311825d7199b715b715349edd00c3c97a96534fcreed@google.com     */
16236568f626bfc620aed42fc8f7b5b255139dd51b7reed@google.com    virtual FilterReturn filterRectsToNine(const SkRect[], int count,
16336568f626bfc620aed42fc8f7b5b255139dd51b7reed@google.com                                           const SkMatrix&,
16436568f626bfc620aed42fc8f7b5b255139dd51b7reed@google.com                                           const SkIRect& clipBounds,
1655161389e01c398f9bcb7ebd796e3570efc701775reed@google.com                                           NinePatch*) const;
166f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com    /**
167f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com     *  Similar to filterRectsToNine, except it performs the work on a round rect.
168f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com     */
169f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com    virtual FilterReturn filterRRectToNine(const SkRRect&, const SkMatrix&,
170f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com                                           const SkIRect& clipBounds,
171f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com                                           NinePatch*) const;
172311825d7199b715b715349edd00c3c97a96534fcreed@google.com
173e4da18ed69645153fb8b8de303fe2138f75ff9f1reed@google.comprivate:
174e4da18ed69645153fb8b8de303fe2138f75ff9f1reed@google.com    friend class SkDraw;
175e4da18ed69645153fb8b8de303fe2138f75ff9f1reed@google.com
176e4da18ed69645153fb8b8de303fe2138f75ff9f1reed@google.com    /** Helper method that, given a path in device space, will rasterize it into a kA8_Format mask
177e4da18ed69645153fb8b8de303fe2138f75ff9f1reed@google.com     and then call filterMask(). If this returns true, the specified blitter will be called
178e4da18ed69645153fb8b8de303fe2138f75ff9f1reed@google.com     to render that mask. Returns false if filterMask() returned false.
179e4da18ed69645153fb8b8de303fe2138f75ff9f1reed@google.com     This method is not exported to java.
180e4da18ed69645153fb8b8de303fe2138f75ff9f1reed@google.com     */
181e4da18ed69645153fb8b8de303fe2138f75ff9f1reed@google.com    bool filterPath(const SkPath& devPath, const SkMatrix& devMatrix,
182ddd97b8f3489ebec7dd4f910f60f8ff1abe662cfjunov@chromium.org                    const SkRasterClip&, SkBounder*, SkBlitter* blitter,
1835161389e01c398f9bcb7ebd796e3570efc701775reed@google.com                    SkPaint::Style style) const;
184e133d6ad314603114c7ef80423391f65cbb599d7djsollen@google.com
185f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com    /** Helper method that, given a roundRect in device space, will rasterize it into a kA8_Format
186f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com     mask and then call filterMask(). If this returns true, the specified blitter will be called
187f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com     to render that mask. Returns false if filterMask() returned false.
188f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com     */
189f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com    bool filterRRect(const SkRRect& devRRect, const SkMatrix& devMatrix,
190f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com                     const SkRasterClip&, SkBounder*, SkBlitter* blitter,
191f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com                     SkPaint::Style style) const;
192f86f9e16a98e3789e047dd649cedbca9349d4c86scroggo@google.com
193e133d6ad314603114c7ef80423391f65cbb599d7djsollen@google.com    typedef SkFlattenable INHERITED;
194f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com};
195f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com
196f0d6bf5df07d5ce620678074da0c05aacc28e44reed@android.com#endif
197