
/*
 * 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++ = 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
