
/*
 * Copyright 2013 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */


#ifndef SkBitmapFilter_DEFINED
#define SkBitmapFilter_DEFINED

#include "SkMath.h"

// size of the precomputed bitmap filter tables for high quality filtering.
// Used to precompute the shape of the filter kernel.
// Table size chosen from experiments to see where I could start to see a difference.

#define SKBITMAP_FILTER_TABLE_SIZE 128

class SkBitmapFilter {
  public:
      SkBitmapFilter(float width)
      : fWidth(width), fInvWidth(1.f/width) {
          fPrecomputed = false;
          fLookupMultiplier = this->invWidth() * (SKBITMAP_FILTER_TABLE_SIZE-1);
      }

      SkFixed lookup(float x) const {
          if (!fPrecomputed) {
              precomputeTable();
          }
          int filter_idx = int(sk_float_abs(x * fLookupMultiplier));
          SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE);
          return fFilterTable[filter_idx];
      }

      SkScalar lookupScalar(float x) const {
          if (!fPrecomputed) {
              precomputeTable();
          }
          int filter_idx = int(sk_float_abs(x * fLookupMultiplier));
          SkASSERT(filter_idx < SKBITMAP_FILTER_TABLE_SIZE);
          return fFilterTableScalar[filter_idx];
      }

      float width() const { return fWidth; }
      float invWidth() const { return fInvWidth; }
      virtual float evaluate(float x) const = 0;
      virtual ~SkBitmapFilter() {}

      static SkBitmapFilter* Allocate();
  protected:
      float fWidth;
      float fInvWidth;

      float fLookupMultiplier;

      mutable bool fPrecomputed;
      mutable SkFixed fFilterTable[SKBITMAP_FILTER_TABLE_SIZE];
      mutable SkScalar fFilterTableScalar[SKBITMAP_FILTER_TABLE_SIZE];
  private:
      void precomputeTable() const {
          fPrecomputed = true;
          SkFixed *ftp = fFilterTable;
          SkScalar *ftpScalar = fFilterTableScalar;
          for (int x = 0; x < SKBITMAP_FILTER_TABLE_SIZE; ++x) {
              float fx = ((float)x + .5f) * this->width() / SKBITMAP_FILTER_TABLE_SIZE;
              float filter_value = evaluate(fx);
              *ftpScalar++ = SkFloatToScalar(filter_value);
              *ftp++ = SkFloatToFixed(filter_value);
          }
      }
};

class SkMitchellFilter: public SkBitmapFilter {
  public:
      SkMitchellFilter(float b, float c, float width=2.0f)
      : SkBitmapFilter(width), B(b), C(c) {
      }

      virtual float evaluate(float x) const SK_OVERRIDE {
          x = fabsf(x);
          if (x > 2.f) {
              return 0;
          } else if (x > 1.f) {
              return ((-B - 6*C) * x*x*x + (6*B + 30*C) * x*x +
                      (-12*B - 48*C) * x + (8*B + 24*C)) * (1.f/6.f);
          } else {
              return ((12 - 9*B - 6*C) * x*x*x +
                      (-18 + 12*B + 6*C) * x*x +
                      (6 - 2*B)) * (1.f/6.f);
          }
      }
  protected:
      float B, C;
};

class SkGaussianFilter: public SkBitmapFilter {
  public:
      SkGaussianFilter(float a, float width=2.0f)
      : SkBitmapFilter(width), alpha(a), expWidth(expf(-alpha * width * width)) {
      }

      virtual float evaluate(float x) const SK_OVERRIDE {
          return SkTMax(0.f, float(expf(-alpha*x*x) - expWidth));
      }
  protected:
      float alpha, expWidth;
};

class SkTriangleFilter: public SkBitmapFilter {
  public:
      SkTriangleFilter(float width=1)
      : SkBitmapFilter(width) {
      }

      virtual float evaluate(float x) const SK_OVERRIDE {
          return SkTMax(0.f, fWidth - fabsf(x));
      }
  protected:
};

class SkBoxFilter: public SkBitmapFilter {
  public:
      SkBoxFilter(float width=0.5f)
      : SkBitmapFilter(width) {
      }

      virtual float evaluate(float x) const SK_OVERRIDE {
          return (x >= -fWidth && x < fWidth) ? 1.0f : 0.0f;
      }
  protected:
};

class SkHammingFilter: public SkBitmapFilter {
public:
    SkHammingFilter(float width=1.f)
    : SkBitmapFilter(width) {
    }
    virtual float evaluate(float x) const SK_OVERRIDE {
        if (x <= -fWidth || x >= fWidth) {
            return 0.0f;  // Outside of the window.
        }
        if (x > -FLT_EPSILON && x < FLT_EPSILON) {
            return 1.0f;  // Special case the sinc discontinuity at the origin.
        }
        const float xpi = x * static_cast<float>(SK_ScalarPI);

        return ((sk_float_sin(xpi) / xpi) *  // sinc(x)
                (0.54f + 0.46f * sk_float_cos(xpi / fWidth)));  // hamming(x)
    }
};

class SkLanczosFilter: public SkBitmapFilter {
  public:
      SkLanczosFilter(float width=3.f)
      : SkBitmapFilter(width) {
      }

      virtual float evaluate(float x) const SK_OVERRIDE {
          if (x <= -fWidth || x >= fWidth) {
              return 0.0f;  // Outside of the window.
          }
          if (x > -FLT_EPSILON && x < FLT_EPSILON) {
              return 1.0f;  // Special case the discontinuity at the origin.
          }
          float xpi = x * static_cast<float>(SK_ScalarPI);
          return (sk_float_sin(xpi) / xpi) *  // sinc(x)
                  sk_float_sin(xpi / fWidth) / (xpi / fWidth);  // sinc(x/fWidth)
      }
};


#endif
