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