180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2006 The Android Open Source Project
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkBitmap.h"
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMask.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef ClearLow3Bits_DEFINED
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define ClearLow3Bits_DEFINED
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    #define ClearLow3Bits(x)    ((unsigned)(x) >> 3 << 3)
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_BLITBWMASK_NAME          name of function(const SkBitmap& bitmap, const SkMask& mask, const SkIRect& clip, SK_BLITBWMASK_ARGS)
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_BLITBWMASK_ARGS          list of additional arguments to SK_BLITBWMASK_NAME, beginning with a comma
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_BLITBWMASK_BLIT8         name of function(U8CPU byteMask, SK_BLITBWMASK_DEVTYPE* dst, int x, int y)
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_BLITBWMASK_GETADDR       either getAddr32 or getAddr16 or getAddr8
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_BLITBWMASK_DEVTYPE       either U32 or U16 or U8
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru*/
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void SK_BLITBWMASK_NAME(const SkBitmap& bitmap, const SkMask& srcMask, const SkIRect& clip SK_BLITBWMASK_ARGS)
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(clip.fRight <= srcMask.fBounds.fRight);
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int cx = clip.fLeft;
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int cy = clip.fTop;
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    int maskLeft = srcMask.fBounds.fLeft;
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned mask_rowBytes = srcMask.fRowBytes;
34096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    size_t bitmap_rowBytes = bitmap.rowBytes();
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    unsigned height = clip.height();
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(mask_rowBytes != 0);
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(bitmap_rowBytes != 0);
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SkASSERT(height != 0);
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    const uint8_t* bits = srcMask.getAddr1(cx, cy);
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    SK_BLITBWMASK_DEVTYPE* device = bitmap.SK_BLITBWMASK_GETADDR(cx, cy);
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (cx == maskLeft && clip.fRight == srcMask.fBounds.fRight)
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        do {
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SK_BLITBWMASK_DEVTYPE* dst = device;
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            unsigned rb = mask_rowBytes;
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            do {
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                U8CPU mask = *bits++;
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_BLITBWMASK_BLIT8(mask, dst);
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst += 8;
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } while (--rb != 0);
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            device = (SK_BLITBWMASK_DEVTYPE*)((char*)device + bitmap_rowBytes);
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } while (--height != 0);
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    else
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    {
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int left_edge = cx - maskLeft;
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(left_edge >= 0);
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int rite_edge = clip.fRight - maskLeft;
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        SkASSERT(rite_edge > left_edge);
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int left_mask = 0xFF >> (left_edge & 7);
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int rite_mask = 0xFF << (8 - (rite_edge & 7));
667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        rite_mask &= 0xFF;  // only want low-8 bits of mask
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        int full_runs = (rite_edge >> 3) - ((left_edge + 7) >> 3);
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // check for empty right mask, so we don't read off the end (or go slower than we need to)
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (rite_mask == 0)
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        {
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(full_runs >= 0);
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            full_runs -= 1;
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            rite_mask = 0xFF;
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (left_mask == 0xFF)
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            full_runs -= 1;
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // back up manually so we can keep in sync with our byte-aligned src
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // and not trigger an assert from the getAddr## function
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        device -= left_edge & 7;
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (full_runs < 0)
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        {
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            left_mask &= rite_mask;
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            SkASSERT(left_mask != 0);
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            do {
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                U8CPU mask = *bits & left_mask;
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_BLITBWMASK_BLIT8(mask, device);
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                bits += mask_rowBytes;
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                device = (SK_BLITBWMASK_DEVTYPE*)((char*)device + bitmap_rowBytes);
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } while (--height != 0);
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        else
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        {
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            do {
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                int runs = full_runs;
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_BLITBWMASK_DEVTYPE* dst = device;
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                const uint8_t* b = bits;
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                U8CPU   mask;
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                mask = *b++ & left_mask;
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_BLITBWMASK_BLIT8(mask, dst);
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                dst += 8;
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                while (--runs >= 0)
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                {
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    mask = *b++;
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    SK_BLITBWMASK_BLIT8(mask, dst);
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                    dst += 8;
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                }
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                mask = *b & rite_mask;
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                SK_BLITBWMASK_BLIT8(mask, dst);
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                bits += mask_rowBytes;
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                device = (SK_BLITBWMASK_DEVTYPE*)((char*)device + bitmap_rowBytes);
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            } while (--height != 0);
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#undef SK_BLITBWMASK_NAME
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#undef SK_BLITBWMASK_ARGS
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#undef SK_BLITBWMASK_BLIT8
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#undef SK_BLITBWMASK_GETADDR
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#undef SK_BLITBWMASK_DEVTYPE
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#undef SK_BLITBWMASK_DOROWSETUP
129