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

#ifndef SkTextureCompressor_Blitter_DEFINED
#define SkTextureCompressor_Blitter_DEFINED

#include "SkTypes.h"
#include "SkBlitter.h"

namespace SkTextureCompressor {

// Ostensibly, SkBlitter::BlitRect is supposed to set a rect of pixels to full
// alpha. This becomes problematic when using compressed texture blitters, since
// the rect rarely falls along block boundaries. The proper way to handle this is
// to update the compressed encoding of a block by resetting the proper parameters
// (and even recompressing the block) where a rect falls inbetween block boundaries.
// PEDANTIC_BLIT_RECT attempts to do this by requiring the struct passed to
// SkTCompressedAlphaBlitter to implement an UpdateBlock function call.
//
// However, the way that BlitRect gets used almost exclusively is to bracket inverse
// fills for paths. In other words, the top few rows and bottom few rows of a path
// that's getting inverse filled are called using blitRect. The rest are called using
// the standard blitAntiH. As a result, we can just call  blitAntiH with a faux RLE
// of full alpha values, and then check in our flush() call that we don't run off the
// edge of the buffer. This is why we do not need this flag to be turned on.
//
// NOTE: This code is unfinished, but is inteded as a starting point if an when
// bugs are introduced from the existing code.
#define PEDANTIC_BLIT_RECT 0

// This class implements a blitter that blits directly into a buffer that will
// be used as an compressed alpha texture. We compute this buffer by
// buffering scan lines and then outputting them all at once. The number of
// scan lines buffered is controlled by kBlockSize
//
// The CompressorType is a struct with a bunch of static methods that provides
// the specialized compression functionality of the blitter. A complete CompressorType
// will implement the following static functions;
//
// struct CompressorType {
//     // The function used to compress an A8 block. The layout of the
//     // block is also expected to be in column-major order.
//     static void CompressA8Vertical(uint8_t* dst, const uint8_t block[]);
//
//     // The function used to compress an A8 block. The layout of the
//     // block is also expected to be in row-major order.
//     static void CompressA8Horizontal(uint8_t* dst, const uint8_t* src, int srcRowBytes);
//
#if PEDANTIC_BLIT_RECT
//     // The function used to update an already compressed block. This will
//     // most likely be implementation dependent. The mask variable will have
//     // 0xFF in positions where the block should be updated and 0 in positions
//     // where it shouldn't. src contains an uncompressed buffer of pixels.
//     static void UpdateBlock(uint8_t* dst, const uint8_t* src, int srcRowBytes, 
//                             const uint8_t* mask);
#endif
// };
template<int BlockDim, int EncodedBlockSize, typename CompressorType>
class SkTCompressedAlphaBlitter : public SkBlitter {
public:
    SkTCompressedAlphaBlitter(int width, int height, void *compressedBuffer)
        // 0x7FFE is one minus the largest positive 16-bit int. We use it for
        // debugging to make sure that we're properly setting the nextX distance
        // in flushRuns(). 
#ifdef SK_DEBUG
        : fCalledOnceWithNonzeroY(false)
        , fBlitMaskCalled(false),
#else
        :
#endif
        kLongestRun(0x7FFE), kZeroAlpha(0)
        , fNextRun(0)
        , fWidth(width)
        , fHeight(height)
        , fBuffer(compressedBuffer)
        {
            SkASSERT((width % BlockDim) == 0);
            SkASSERT((height % BlockDim) == 0);
        }

    virtual ~SkTCompressedAlphaBlitter() { this->flushRuns(); }

    // Blit a horizontal run of one or more pixels.
    void blitH(int x, int y, int width) override {
        // This function is intended to be called from any standard RGB
        // buffer, so we should never encounter it. However, if some code
        // path does end up here, then this needs to be investigated.
        SkFAIL("Not implemented!");
    }

    // Blit a horizontal run of antialiased pixels; runs[] is a *sparse*
    // zero-terminated run-length encoding of spans of constant alpha values.
    void blitAntiH(int x, int y,
                   const SkAlpha antialias[],
                   const int16_t runs[]) override {
        SkASSERT(0 == x);

        // Make sure that the new row to blit is either the first
        // row that we're blitting, or it's exactly the next scan row
        // since the last row that we blit. This is to ensure that when
        // we go to flush the runs, that they are all the same four
        // runs.
        if (fNextRun > 0 &&
            ((x != fBufferedRuns[fNextRun-1].fX) ||
             (y-1 != fBufferedRuns[fNextRun-1].fY))) {
            this->flushRuns();
        }

        // Align the rows to a block boundary. If we receive rows that
        // are not on a block boundary, then fill in the preceding runs
        // with zeros. We do this by producing a single RLE that says
        // that we have 0x7FFE pixels of zero (0x7FFE = 32766).
        const int row = BlockDim * (y / BlockDim);
        while ((row + fNextRun) < y) {
            fBufferedRuns[fNextRun].fAlphas = &kZeroAlpha;
            fBufferedRuns[fNextRun].fRuns = &kLongestRun;
            fBufferedRuns[fNextRun].fX = 0;
            fBufferedRuns[fNextRun].fY = row + fNextRun;
            ++fNextRun;
        }

        // Make sure that our assumptions aren't violated...
        SkASSERT(fNextRun == (y % BlockDim));
        SkASSERT(fNextRun == 0 || fBufferedRuns[fNextRun - 1].fY < y);

        // Set the values of the next run
        fBufferedRuns[fNextRun].fAlphas = antialias;
        fBufferedRuns[fNextRun].fRuns = runs;
        fBufferedRuns[fNextRun].fX = x;
        fBufferedRuns[fNextRun].fY = y;

        // If we've output a block of scanlines in a row that don't violate our
        // assumptions, then it's time to flush them...
        if (BlockDim == ++fNextRun) {
            this->flushRuns();
        }
    }
    
    // Blit a vertical run of pixels with a constant alpha value.
    void blitV(int x, int y, int height, SkAlpha alpha) override {
        // This function is currently not implemented. It is not explicitly
        // required by the contract, but if at some time a code path runs into
        // this function (which is entirely possible), it needs to be implemented.
        //
        // TODO (krajcevski):
        // This function will be most easily implemented in one of two ways:
        // 1. Buffer each vertical column value and then construct a list
        //    of alpha values and output all of the blocks at once. This only
        //    requires a write to the compressed buffer
        // 2. Replace the indices of each block with the proper indices based
        //    on the alpha value. This requires a read and write of the compressed
        //    buffer, but much less overhead.
        SkFAIL("Not implemented!");
    }

    // Blit a solid rectangle one or more pixels wide. It's assumed that blitRect
    // is called as a way to bracket blitAntiH where above and below the path the
    // called path just needs a solid rectangle to fill in the mask.
#ifdef SK_DEBUG
    bool fCalledOnceWithNonzeroY;
#endif
    void blitRect(int x, int y, int width, int height) override {

        // Assumptions:
        SkASSERT(0 == x);
        SkASSERT(width <= fWidth);

        // Make sure that we're only ever bracketing calls to blitAntiH.
        SkASSERT((0 == y) || (!fCalledOnceWithNonzeroY && (fCalledOnceWithNonzeroY = true)));
        
#if !(PEDANTIC_BLIT_RECT)
        for (int i = 0; i < height; ++i) {
            const SkAlpha kFullAlpha = 0xFF;
            this->blitAntiH(x, y+i, &kFullAlpha, &kLongestRun);
        }
#else
        const int startBlockX = (x / BlockDim) * BlockDim;
        const int startBlockY = (y / BlockDim) * BlockDim;

        const int endBlockX = ((x + width) / BlockDim) * BlockDim;
        const int endBlockY = ((y + height) / BlockDim) * BlockDim;

        // If start and end are the same, then we only need to update a single block...
        if (startBlockY == endBlockY && startBlockX == endBlockX) {
            uint8_t mask[BlockDim*BlockDim];
            memset(mask, 0, sizeof(mask));

            const int xoff = x - startBlockX;
            SkASSERT((xoff + width) <= BlockDim);

            const int yoff = y - startBlockY;
            SkASSERT((yoff + height) <= BlockDim);
            
            for (int j = 0; j < height; ++j) {
                memset(mask + (j + yoff)*BlockDim + xoff, 0xFF, width);
            }

            uint8_t* dst = this->getBlock(startBlockX, startBlockY);
            CompressorType::UpdateBlock(dst, mask, BlockDim, mask);

        // If start and end are the same in the y dimension, then we can freely update an
        // entire row of blocks...
        } else if (startBlockY == endBlockY) {

            this->updateBlockRow(x, y, width, height, startBlockY, startBlockX, endBlockX);

        // Similarly, if the start and end are in the same column, then we can just update
        // an entire column of blocks...
        } else if (startBlockX == endBlockX) {

            this->updateBlockCol(x, y, width, height, startBlockX, startBlockY, endBlockY);

        // Otherwise, the rect spans a non-trivial region of blocks, and we have to construct
        // a kind of 9-patch to update each of the pieces of the rect. The top and bottom
        // rows are updated using updateBlockRow, and the left and right columns are updated
        // using updateBlockColumn. Anything in the middle is simply memset to an opaque block
        // encoding.
        } else {

            const int innerStartBlockX = startBlockX + BlockDim;
            const int innerStartBlockY = startBlockY + BlockDim;

            // Blit top row
            const int topRowHeight = innerStartBlockY - y;
            this->updateBlockRow(x, y, width, topRowHeight, startBlockY,
                                 startBlockX, endBlockX);

            // Advance y
            y += topRowHeight;
            height -= topRowHeight;

            // Blit middle
            if (endBlockY > innerStartBlockY) {

                // Update left row
                this->updateBlockCol(x, y, innerStartBlockX - x, endBlockY, startBlockY,
                                     startBlockX, innerStartBlockX);

                // Update the middle with an opaque encoding...
                uint8_t mask[BlockDim*BlockDim];
                memset(mask, 0xFF, sizeof(mask));

                uint8_t opaqueEncoding[EncodedBlockSize];
                CompressorType::CompressA8Horizontal(opaqueEncoding, mask, BlockDim);

                for (int j = innerStartBlockY; j < endBlockY; j += BlockDim) {
                    uint8_t* opaqueDst = this->getBlock(innerStartBlockX, j);
                    for (int i = innerStartBlockX; i < endBlockX; i += BlockDim) {
                        memcpy(opaqueDst, opaqueEncoding, EncodedBlockSize);
                        opaqueDst += EncodedBlockSize;
                    }
                }

                // If we need to update the right column, do that too
                if (x + width > endBlockX) {
                    this->updateBlockCol(endBlockX, y, x + width - endBlockX, endBlockY,
                                         endBlockX, innerStartBlockY, endBlockY);
                }

                // Advance y
                height = y + height - endBlockY;
                y = endBlockY;
            }

            // If we need to update the last row, then do that, too.
            if (height > 0) {
                this->updateBlockRow(x, y, width, height, endBlockY,
                                     startBlockX, endBlockX);
            }
        }
#endif
    }

    // Blit a rectangle with one alpha-blended column on the left,
    // width (zero or more) opaque pixels, and one alpha-blended column
    // on the right. The result will always be at least two pixels wide.
    void blitAntiRect(int x, int y, int width, int height,
                      SkAlpha leftAlpha, SkAlpha rightAlpha) override {
        // This function is currently not implemented. It is not explicitly
        // required by the contract, but if at some time a code path runs into
        // this function (which is entirely possible), it needs to be implemented.
        //
        // TODO (krajcevski):
        // This function will be most easily implemented as follows:
        // 1. If width/height are smaller than a block, then update the
        //    indices of the affected blocks.
        // 2. If width/height are larger than a block, then construct a 9-patch
        //    of block encodings that represent the rectangle, and write them
        //    to the compressed buffer as necessary. Whether or not the blocks
        //    are overwritten by zeros or just their indices are updated is up
        //    to debate.
        SkFAIL("Not implemented!");
    }

    // Blit a pattern of pixels defined by a rectangle-clipped mask; We make an
    // assumption here that if this function gets called, then it will replace all
    // of the compressed texture blocks that it touches. Hence, two separate calls
    // to blitMask that have clips next to one another will cause artifacts. Most
    // of the time, however, this function gets called because constructing the mask
    // was faster than constructing the RLE for blitAntiH, and this function will
    // only be called once.
#ifdef SK_DEBUG
    bool fBlitMaskCalled;
#endif
    void blitMask(const SkMask& mask, const SkIRect& clip) override {

        // Assumptions:
        SkASSERT(!fBlitMaskCalled);
        SkDEBUGCODE(fBlitMaskCalled = true);
        SkASSERT(SkMask::kA8_Format == mask.fFormat);
        SkASSERT(mask.fBounds.contains(clip));

        // Start from largest block boundary less than the clip boundaries.
        const int startI = BlockDim * (clip.left() / BlockDim);
        const int startJ = BlockDim * (clip.top() / BlockDim);

        for (int j = startJ; j < clip.bottom(); j += BlockDim) {

            // Get the destination for this block row
            uint8_t* dst = this->getBlock(startI, j);
            for (int i = startI; i < clip.right(); i += BlockDim) {

                // At this point, the block should intersect the clip.
                SkASSERT(SkIRect::IntersectsNoEmptyCheck(
                             SkIRect::MakeXYWH(i, j, BlockDim, BlockDim), clip));

                // Do we need to pad it?
                if (i < clip.left() || j < clip.top() ||
                    i + BlockDim > clip.right() || j + BlockDim > clip.bottom()) {

                    uint8_t block[BlockDim*BlockDim];
                    memset(block, 0, sizeof(block));

                    const int startX = SkMax32(i, clip.left());
                    const int startY = SkMax32(j, clip.top());

                    const int endX = SkMin32(i + BlockDim, clip.right());
                    const int endY = SkMin32(j + BlockDim, clip.bottom());

                    for (int y = startY; y < endY; ++y) {
                        const int col = startX - i;
                        const int row = y - j;
                        const int valsWide = endX - startX;
                        SkASSERT(valsWide <= BlockDim);
                        SkASSERT(0 <= col && col < BlockDim);
                        SkASSERT(0 <= row && row < BlockDim);
                        memcpy(block + row*BlockDim + col,
                               mask.getAddr8(startX, j + row), valsWide);
                    }

                    CompressorType::CompressA8Horizontal(dst, block, BlockDim);
                } else {
                    // Otherwise, just compress it.
                    uint8_t*const src = mask.getAddr8(i, j);
                    const uint32_t rb = mask.fRowBytes;
                    CompressorType::CompressA8Horizontal(dst, src, rb);
                }

                dst += EncodedBlockSize;
            }
        }
    }

    // If the blitter just sets a single value for each pixel, return the
    // bitmap it draws into, and assign value. If not, return NULL and ignore
    // the value parameter.
    const SkBitmap* justAnOpaqueColor(uint32_t* value) override {
        return NULL;
    }

    /**
     * Compressed texture blitters only really work correctly if they get
     * BlockDim rows at a time. That being said, this blitter tries it's best
     * to preserve semantics if blitAntiH doesn't get called in too many
     * weird ways...
     */
    int requestRowsPreserved() const override { return BlockDim; }

private:
    static const int kPixelsPerBlock = BlockDim * BlockDim;

    // The longest possible run of pixels that this blitter will receive.
    // This is initialized in the constructor to 0x7FFE, which is one less
    // than the largest positive 16-bit integer. We make sure that it's one
    // less for debugging purposes. We also don't make this variable static
    // in order to make sure that we can construct a valid pointer to it.
    const int16_t kLongestRun;

    // Usually used in conjunction with kLongestRun. This is initialized to
    // zero.
    const SkAlpha kZeroAlpha;

    // This is the information that we buffer whenever we're asked to blit
    // a row with this blitter.
    struct BufferedRun {
        const SkAlpha* fAlphas;
        const int16_t* fRuns;
        int fX, fY;
    } fBufferedRuns[BlockDim];

    // The next row [0, BlockDim) that we need to blit.
    int fNextRun;

    // The width and height of the image that we're blitting
    const int fWidth;
    const int fHeight;

    // The compressed buffer that we're blitting into. It is assumed that the buffer
    // is large enough to store a compressed image of size fWidth*fHeight.
    void* const fBuffer;

    // Various utility functions
    int blocksWide() const { return fWidth / BlockDim; }
    int blocksTall() const { return fHeight / BlockDim; }
    int totalBlocks() const { return (fWidth * fHeight) / kPixelsPerBlock; }

    // Returns the block index for the block containing pixel (x, y). Block
    // indices start at zero and proceed in raster order.
    int getBlockOffset(int x, int y) const {
        SkASSERT(x < fWidth);
        SkASSERT(y < fHeight);
        const int blockCol = x / BlockDim;
        const int blockRow = y / BlockDim;
        return blockRow * this->blocksWide() + blockCol;
    }

    // Returns a pointer to the block containing pixel (x, y)
    uint8_t *getBlock(int x, int y) const {
        uint8_t* ptr = reinterpret_cast<uint8_t*>(fBuffer);
        return ptr + EncodedBlockSize*this->getBlockOffset(x, y);
    }

    // Updates the block whose columns are stored in block. curAlphai is expected
    // to store the alpha values that will be placed within each of the columns in
    // the range [col, col+colsLeft).
    typedef uint32_t Column[BlockDim/4];
    typedef uint32_t Block[BlockDim][BlockDim/4];
    inline void updateBlockColumns(Block block, const int col,
                                   const int colsLeft, const Column curAlphai) {
        SkASSERT(block);
        SkASSERT(col + colsLeft <= BlockDim);

        for (int i = col; i < (col + colsLeft); ++i) {
            memcpy(block[i], curAlphai, sizeof(Column));
        }
    }

    // The following function writes the buffered runs to compressed blocks.
    // If fNextRun < BlockDim, then we fill the runs that we haven't buffered with
    // the constant zero buffer.
    void flushRuns() {
        // If we don't have any runs, then just return.
        if (0 == fNextRun) {
            return;
        }

#ifndef NDEBUG
        // Make sure that if we have any runs, they all match
        for (int i = 1; i < fNextRun; ++i) {
            SkASSERT(fBufferedRuns[i].fY == fBufferedRuns[i-1].fY + 1);
            SkASSERT(fBufferedRuns[i].fX == fBufferedRuns[i-1].fX);
        }
#endif

        // If we don't have as many runs as we have rows, fill in the remaining
        // runs with constant zeros.
        for (int i = fNextRun; i < BlockDim; ++i) {
            fBufferedRuns[i].fY = fBufferedRuns[0].fY + i;
            fBufferedRuns[i].fX = fBufferedRuns[0].fX;
            fBufferedRuns[i].fAlphas = &kZeroAlpha;
            fBufferedRuns[i].fRuns = &kLongestRun;
        }

        // Make sure that our assumptions aren't violated.
        SkASSERT(fNextRun > 0 && fNextRun <= BlockDim);
        SkASSERT((fBufferedRuns[0].fY % BlockDim) == 0);

        // The following logic walks BlockDim rows at a time and outputs compressed
        // blocks to the buffer passed into the constructor.
        // We do the following:
        //
        //      c1 c2 c3 c4
        // -----------------------------------------------------------------------
        // ... |  |  |  |  |  ----> fBufferedRuns[0]
        // -----------------------------------------------------------------------
        // ... |  |  |  |  |  ----> fBufferedRuns[1]
        // -----------------------------------------------------------------------
        // ... |  |  |  |  |  ----> fBufferedRuns[2]
        // -----------------------------------------------------------------------
        // ... |  |  |  |  |  ----> fBufferedRuns[3]
        // -----------------------------------------------------------------------
        // 
        // curX -- the macro X value that we've gotten to.
        // c[BlockDim] -- the buffers that represent the columns of the current block
        //                  that we're operating on
        // curAlphaColumn -- buffer containing the column of alpha values from fBufferedRuns.
        // nextX -- for each run, the next point at which we need to update curAlphaColumn
        //          after the value of curX.
        // finalX -- the minimum of all the nextX values.
        //
        // curX advances to finalX outputting any blocks that it passes along
        // the way. Since finalX will not change when we reach the end of a
        // run, the termination criteria will be whenever curX == finalX at the
        // end of a loop.

        // Setup:
        Block block;
        sk_bzero(block, sizeof(block));

        Column curAlphaColumn;
        sk_bzero(curAlphaColumn, sizeof(curAlphaColumn));

        SkAlpha *curAlpha = reinterpret_cast<SkAlpha*>(&curAlphaColumn);

        int nextX[BlockDim];
        for (int i = 0; i < BlockDim; ++i) {
            nextX[i] = 0x7FFFFF;
        }

        uint8_t* outPtr = this->getBlock(fBufferedRuns[0].fX, fBufferedRuns[0].fY);

        // Populate the first set of runs and figure out how far we need to
        // advance on the first step
        int curX = 0;
        int finalX = 0xFFFFF;
        for (int i = 0; i < BlockDim; ++i) {
            nextX[i] = *(fBufferedRuns[i].fRuns);
            curAlpha[i] = *(fBufferedRuns[i].fAlphas);

            finalX = SkMin32(nextX[i], finalX);
        }

        // Make sure that we have a valid right-bound X value
        SkASSERT(finalX < 0xFFFFF);

        // If the finalX is the longest run, then just blit until we have
        // width...
        if (kLongestRun == finalX) {
            finalX = fWidth;
        }

        // Run the blitter...
        while (curX != finalX) {
            SkASSERT(finalX >= curX);

            // Do we need to populate the rest of the block?
            if ((finalX - (BlockDim*(curX / BlockDim))) >= BlockDim) {
                const int col = curX % BlockDim;
                const int colsLeft = BlockDim - col;
                SkASSERT(curX + colsLeft <= finalX);

                this->updateBlockColumns(block, col, colsLeft, curAlphaColumn);

                // Write this block
                CompressorType::CompressA8Vertical(outPtr, reinterpret_cast<uint8_t*>(block));
                outPtr += EncodedBlockSize;
                curX += colsLeft;
            }

            // If we can advance even further, then just keep memsetting the block
            if ((finalX - curX) >= BlockDim) {
                SkASSERT((curX % BlockDim) == 0);

                const int col = 0;
                const int colsLeft = BlockDim;

                this->updateBlockColumns(block, col, colsLeft, curAlphaColumn);

                // While we can keep advancing, just keep writing the block.
                uint8_t lastBlock[EncodedBlockSize];
                CompressorType::CompressA8Vertical(lastBlock, reinterpret_cast<uint8_t*>(block));
                while((finalX - curX) >= BlockDim) {
                    memcpy(outPtr, lastBlock, EncodedBlockSize);
                    outPtr += EncodedBlockSize;
                    curX += BlockDim;
                }
            }

            // If we haven't advanced within the block then do so.
            if (curX < finalX) {
                const int col = curX % BlockDim;
                const int colsLeft = finalX - curX;

                this->updateBlockColumns(block, col, colsLeft, curAlphaColumn);
                curX += colsLeft;
            }

            SkASSERT(curX == finalX);

            // Figure out what the next advancement is...
            if (finalX < fWidth) {
                for (int i = 0; i < BlockDim; ++i) {
                    if (nextX[i] == finalX) {
                        const int16_t run = *(fBufferedRuns[i].fRuns);
                        fBufferedRuns[i].fRuns += run;
                        fBufferedRuns[i].fAlphas += run;
                        curAlpha[i] = *(fBufferedRuns[i].fAlphas);
                        nextX[i] += *(fBufferedRuns[i].fRuns);
                    }
                }

                finalX = 0xFFFFF;
                for (int i = 0; i < BlockDim; ++i) {
                    finalX = SkMin32(nextX[i], finalX);
                }
            } else {
                curX = finalX;
            }
        }

        // If we didn't land on a block boundary, output the block...
        if ((curX % BlockDim) > 0) {
#ifdef SK_DEBUG
            for (int i = 0; i < BlockDim; ++i) {
                SkASSERT(nextX[i] == kLongestRun || nextX[i] == curX);
            }
#endif
            const int col = curX % BlockDim;
            const int colsLeft = BlockDim - col;

            memset(curAlphaColumn, 0, sizeof(curAlphaColumn));
            this->updateBlockColumns(block, col, colsLeft, curAlphaColumn);

            CompressorType::CompressA8Vertical(outPtr, reinterpret_cast<uint8_t*>(block));
        }

        fNextRun = 0;
    }

#if PEDANTIC_BLIT_RECT
    void updateBlockRow(int x, int y, int width, int height,
                        int blockRow, int startBlockX, int endBlockX) {
        if (0 == width || 0 == height || startBlockX == endBlockX) {
            return;
        }

        uint8_t* dst = this->getBlock(startBlockX, BlockDim * (y / BlockDim));

        // One horizontal strip to update
        uint8_t mask[BlockDim*BlockDim];
        memset(mask, 0, sizeof(mask));

        // Update the left cap
        int blockX = startBlockX;
        const int yoff = y - blockRow;
        for (int j = 0; j < height; ++j) {
            const int xoff = x - blockX;
            memset(mask + (j + yoff)*BlockDim + xoff, 0xFF, BlockDim - xoff);
        }
        CompressorType::UpdateBlock(dst, mask, BlockDim, mask);
        dst += EncodedBlockSize;
        blockX += BlockDim;

        // Update the middle
        if (blockX < endBlockX) {
            for (int j = 0; j < height; ++j) {
                memset(mask + (j + yoff)*BlockDim, 0xFF, BlockDim);
            }
            while (blockX < endBlockX) {
                CompressorType::UpdateBlock(dst, mask, BlockDim, mask);
                dst += EncodedBlockSize;
                blockX += BlockDim;
            }
        }

        SkASSERT(endBlockX == blockX);

        // Update the right cap (if we need to)
        if (x + width > endBlockX) {
            memset(mask, 0, sizeof(mask));
            for (int j = 0; j < height; ++j) {
                const int xoff = (x+width-blockX);
                memset(mask + (j+yoff)*BlockDim, 0xFF, xoff);
            }
            CompressorType::UpdateBlock(dst, mask, BlockDim, mask);
        }
    }

    void updateBlockCol(int x, int y, int width, int height,
                        int blockCol, int startBlockY, int endBlockY) {
        if (0 == width || 0 == height || startBlockY == endBlockY) {
            return;
        }

        // One vertical strip to update
        uint8_t mask[BlockDim*BlockDim];
        memset(mask, 0, sizeof(mask));
        const int maskX0 = x - blockCol;
        const int maskWidth = maskX0 + width;
        SkASSERT(maskWidth <= BlockDim);

        // Update the top cap
        int blockY = startBlockY;
        for (int j = (y - blockY); j < BlockDim; ++j) {
            memset(mask + maskX0 + j*BlockDim, 0xFF, maskWidth);
        }
        CompressorType::UpdateBlock(this->getBlock(blockCol, blockY), mask, BlockDim, mask);
        blockY += BlockDim;

        // Update middle
        if (blockY < endBlockY) {
            for (int j = 0; j < BlockDim; ++j) {
                memset(mask + maskX0 + j*BlockDim, 0xFF, maskWidth);
            }
            while (blockY < endBlockY) {
                CompressorType::UpdateBlock(this->getBlock(blockCol, blockY),
                                            mask, BlockDim, mask);
                blockY += BlockDim;
            }
        }

        SkASSERT(endBlockY == blockY);

        // Update bottom
        if (y + height > endBlockY) {
            for (int j = y+height; j < endBlockY + BlockDim; ++j) {
                memset(mask + (j-endBlockY)*BlockDim, 0, BlockDim);
            }
            CompressorType::UpdateBlock(this->getBlock(blockCol, blockY),
                                        mask, BlockDim, mask);
        }
    }
#endif  // PEDANTIC_BLIT_RECT

};

}  // namespace SkTextureCompressor

#endif  // SkTextureCompressor_Blitter_DEFINED
