11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2006 The Android Open Source Project
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 */
81cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifndef SkBitmapSampler_DEFINED
110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define SkBitmapSampler_DEFINED
120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBitmap.h"
140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPaint.h"
150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkShader.h"
160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projecttypedef int (*SkTileModeProc)(int value, unsigned max);
180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectclass SkBitmapSampler {
200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectpublic:
210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkBitmapSampler(const SkBitmap&, bool filter, SkShader::TileMode tmx, SkShader::TileMode tmy);
220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual ~SkBitmapSampler() {}
230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkBitmap&     getBitmap() const { return fBitmap; }
250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool                getFilterBitmap() const { return fFilterBitmap; }
260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkShader::TileMode  getTileModeX() const { return fTileModeX; }
270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkShader::TileMode  getTileModeY() const { return fTileModeY; }
280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    /** Given a pixel center at [x,y], return the color sample
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    */
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual SkPMColor sample(SkFixed x, SkFixed y) const = 0;
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    virtual void setPaint(const SkPaint& paint);
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // This is the factory for finding an optimal subclass
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    static SkBitmapSampler* Create(const SkBitmap&, bool filter,
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                   SkShader::TileMode tmx, SkShader::TileMode tmy);
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectprotected:
400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    const SkBitmap&     fBitmap;
410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    uint16_t            fMaxX, fMaxY;
420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    bool                fFilterBitmap;
430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkShader::TileMode  fTileModeX;
440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkShader::TileMode  fTileModeY;
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTileModeProc      fTileProcX;
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkTileModeProc      fTileProcY;
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // illegal
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkBitmapSampler& operator=(const SkBitmapSampler&);
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project};
510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int fixed_clamp(SkFixed x)
530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (x >> 16)
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        x = 0xFFFF;
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (x < 0)
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        x = 0;
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (x >> 16)
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (x < 0)
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            x = 0;
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            x = 0xFFFF;
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return x;
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////////////
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int fixed_repeat(SkFixed x)
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return x & 0xFFFF;
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int fixed_mirror(SkFixed x)
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFixed s = x << 15 >> 31;
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (x ^ s) & 0xFFFF;
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline bool is_pow2(int count)
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(count > 0);
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (count & (count - 1)) == 0;
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int do_clamp(int index, unsigned max)
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((int)max >= 0);
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (index > (int)max)
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        index = max;
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (index < 0)
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        index = 0;
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if ((unsigned)index > max)
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (index < 0)
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            index = 0;
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            index = max;
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return index;
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int do_repeat_mod(int index, unsigned max)
1130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((int)max >= 0);
1150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if ((unsigned)index > max)
1170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1180910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (index < 0)
1190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            index = max - (~index % (max + 1));
1200910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
1210910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            index = index % (max + 1);
1220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return index;
1240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int do_repeat_pow2(int index, unsigned max)
1270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((int)max >= 0 && is_pow2(max + 1));
1290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return index & max;
1310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int do_mirror_mod(int index, unsigned max)
1340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((int)max >= 0);
1360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // have to handle negatives so that
1380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // -1 -> 0, -2 -> 1, -3 -> 2, etc.
1390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // so we can't just cal abs
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    index ^= index >> 31;
1410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1420910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if ((unsigned)index > max)
1430910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
1440910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        int mod = (max + 1) << 1;
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        index = index % mod;
1460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if ((unsigned)index > max)
1470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            index = mod - index - 1;
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return index;
1500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1510910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1520910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline int do_mirror_pow2(int index, unsigned max)
1530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1540910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT((int)max >= 0 && is_pow2(max + 1));
1550910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int s = (index & (max + 1)) - 1;
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    s = ~(s >> 31);
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // at this stage, s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (index ^ s) & max;
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
163