
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"
#include "SkGradientShader.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkImageEncoder.h"
#include "SkPath.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkXfermode.h"
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkTime.h"
#include "SkTypeface.h"

#include "SkStream.h"

static void make_image(SkBitmap* bm, SkBitmap::Config config, int configIndex) {
    const int   width = 98;
    const int   height = 100;
    SkBitmap    device;
    
    device.setConfig(SkBitmap::kARGB_8888_Config, width, height);
    device.allocPixels();

    SkCanvas    canvas(device);
    SkPaint     paint;
    
    paint.setAntiAlias(true);
    canvas.drawColor(SK_ColorRED);
    paint.setColor(SK_ColorBLUE);
    canvas.drawCircle(SkIntToScalar(width)/2, SkIntToScalar(height)/2,
                      SkIntToScalar(width)/2, paint);

    bm->setConfig(config, width, height);
    switch (config) {
        case SkBitmap::kARGB_8888_Config:
            bm->swap(device);
            break;
        case SkBitmap::kRGB_565_Config: {
            bm->allocPixels();
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    *bm->getAddr16(x, y) = SkPixel32ToPixel16(*device.getAddr32(x, y));
                }
            }
            break;
        }
        case SkBitmap::kIndex8_Config: {
            SkPMColor colors[256];
            for (int i = 0; i < 256; i++) {
                if (configIndex & 1) {
                    colors[i] = SkPackARGB32(255-i, 0, 0, 255-i);
                } else {
                    colors[i] = SkPackARGB32(0xFF, i, 0, 255-i);
                }
            }
            SkColorTable* ctable = new SkColorTable(colors, 256);
            bm->allocPixels(ctable);
            ctable->unref();
            
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                    *bm->getAddr8(x, y) = SkGetPackedR32(*device.getAddr32(x, y));
                }
            }
            break;
        }
        default:
            break;
    }
}

// configs to build the original bitmap in. Can be at most these 3
static const SkBitmap::Config gConfigs[] = {
    SkBitmap::kARGB_8888_Config,
    SkBitmap::kRGB_565_Config,
    SkBitmap::kIndex8_Config,   // opaque
    SkBitmap::kIndex8_Config    // alpha
};

static const char* const gConfigLabels[] = {
    "8888", "565", "Index8",  "Index8 alpha"
};

// types to encode into. Can be at most these 3. Must match up with gExt[]
static const SkImageEncoder::Type gTypes[] = {
    SkImageEncoder::kJPEG_Type,
    SkImageEncoder::kPNG_Type
};

// must match up with gTypes[]
static const char* const gExt[] = {
    ".jpg", ".png"
};

static const char* gPath = "/encoded/";

static void make_name(SkString* name, int config, int ext) {
    name->set(gPath);
    name->append(gConfigLabels[config]);
    name->append(gExt[ext]);
}

#include <sys/stat.h>

class EncodeView : public SampleView {
public:
    SkBitmap*   fBitmaps;
    size_t      fBitmapCount;

	EncodeView() {
    #if 1
        (void)mkdir(gPath, S_IRWXU | S_IRWXG | S_IRWXO);
        
        fBitmapCount = SK_ARRAY_COUNT(gConfigs);
        fBitmaps = new SkBitmap[fBitmapCount];
        for (size_t i = 0; i < fBitmapCount; i++) {
            make_image(&fBitmaps[i], gConfigs[i], i);
            
            for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++) {
                SkString path;
                make_name(&path, i, j);
                
                // remove any previous run of this file
                remove(path.c_str());
                
                SkImageEncoder* codec = SkImageEncoder::Create(gTypes[j]);
                if (NULL == codec ||
                        !codec->encodeFile(path.c_str(), fBitmaps[i], 100)) {
                    SkDebugf("------ failed to encode %s\n", path.c_str());
                    remove(path.c_str());   // remove any partial file
                }
                delete codec;
            }
        }
    #else
        fBitmaps = NULL;
        fBitmapCount = 0;
    #endif
        this->setBGColor(0xFFDDDDDD);
    }
    
    virtual ~EncodeView() {
        delete[] fBitmaps;
    }
    
protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "ImageEncoder");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }
    
    virtual void onDrawContent(SkCanvas* canvas) {
        if (fBitmapCount == 0) {
            return;
        }
        
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setTextAlign(SkPaint::kCenter_Align);
        
        canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
        
        SkScalar x = 0, y = 0, maxX = 0;
        const int SPACER = 10;
        
        for (size_t i = 0; i < fBitmapCount; i++) {
            canvas->drawText(gConfigLabels[i], strlen(gConfigLabels[i]),
                             x + SkIntToScalar(fBitmaps[i].width()) / 2, 0,
                             paint);
            y = paint.getTextSize();

            canvas->drawBitmap(fBitmaps[i], x, y);
            
            SkScalar yy = y;
            for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++) {
                yy += SkIntToScalar(fBitmaps[i].height() + 10);

                SkBitmap bm;
                SkString name;
                
                make_name(&name, i, j);
                
                SkImageDecoder::DecodeFile(name.c_str(), &bm);
                canvas->drawBitmap(bm, x, yy);
            }
            
            x += SkIntToScalar(fBitmaps[i].width() + SPACER);
            if (x > maxX) {
                maxX = x;
            }
        }

        y = (paint.getTextSize() + SkIntToScalar(fBitmaps[0].height())) * 3 / 2;
        x = maxX + SkIntToScalar(10);
        paint.setTextAlign(SkPaint::kLeft_Align);

        for (size_t j = 0; j < SK_ARRAY_COUNT(gExt); j++) {
            canvas->drawText(gExt[j], strlen(gExt[j]), x, y, paint);
            y += SkIntToScalar(fBitmaps[0].height() + SPACER);
        }
    }
    
    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
        this->inval(NULL);
        return this->INHERITED::onFindClickHandler(x, y);
    }
    
private:
    typedef SampleView INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory() { return new EncodeView; }
static SkViewRegister reg(MyFactory);

