
/*
 * 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 "SkPackBits.h"
#include "SkPath.h"
#include "SkPathMeasure.h"
#include "SkRandom.h"
#include "SkRegion.h"
#include "SkShader.h"
#include "SkUtils.h"
#include "SkColorPriv.h"
#include "SkColorFilter.h"
#include "SkTypeface.h"
#include "SkAvoidXfermode.h"

#define REPEAT_COUNT    0

static const char gText[] = "Hamburgefons";

static bool gDevKern;

static void rand_text(char text[], SkRandom& rand, size_t count) {
    for (size_t i = 0; i < count; i++) {
        text[i] = rand.nextU() & 0x7F;
    }
}

static SkScalar sum_widths(const SkScalar widths[], int count) {
    SkScalar w = 0;
    for (int i = 0; i < count; i++) {
        w += widths[i];
    }
    return w;
}

static void test_measure(const SkPaint& paint) {
    char        text[256];
    SkScalar    widths[256];
    SkRect      rects[256];
    SkRect      bounds;
    int         count = 256;
    
    SkRandom rand;
    
    for (int i = 0; i < 100; i++) {
        rand_text(text, rand, 256);
        paint.getTextWidths(text, count, widths, NULL);
        SkDEBUGCODE(SkScalar tw0 = sum_widths(widths, count);)
        paint.getTextWidths(text, count, widths, rects);
        SkDEBUGCODE(SkScalar tw1 = sum_widths(widths, count);)
        SkASSERT(tw0 == tw1);

        SkDEBUGCODE(SkScalar w0 = paint.measureText(text, count, NULL);)
        SkDEBUGCODE(SkScalar w1 = paint.measureText(text, count, &bounds);)
        SkASSERT(w0 == w1);
        SkASSERT(w0 == tw0);
        
        SkRect r = rects[0];
        SkScalar x = 0;
        for (int j = 1; j < count; j++) {
            x += widths[j-1];
            rects[j].offset(x, 0);
            r.join(rects[j]);
        }
        SkASSERT(r == bounds);
        
        if (r != bounds) {
            printf("flags=%x i=%d [%g %g %g %g] [%g %g %g %g]\n",
                   paint.getFlags(), i,
                   SkScalarToFloat(r.fLeft),
                   SkScalarToFloat(r.fTop),
                   SkScalarToFloat(r.fRight),
                   SkScalarToFloat(r.fBottom),
                   SkScalarToFloat(bounds.fLeft),
                   SkScalarToFloat(bounds.fTop),
                   SkScalarToFloat(bounds.fRight),
                   SkScalarToFloat(bounds.fBottom));
        }
    }
}

static void test_measure() {
    SkPaint paint;
    
    for (int i = 0; i <= SkPaint::kAllFlags; i++) {
        paint.setFlags(i);
        test_measure(paint);
    }
}

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

static void test_textBounds(SkCanvas* canvas) {
//    canvas->scale(SK_Scalar1/2, SK_Scalar1/2);
    
//    canvas->rotate(SkIntToScalar(30));

    gDevKern = !gDevKern;

    SkScalar x = SkIntToScalar(50);
    SkScalar y = SkIntToScalar(150);
    SkScalar w[100];
    SkRect   r[100], bounds;
    
    SkPaint paint;
    paint.setTextSize(SkIntToScalar(64));
    paint.setAntiAlias(true);
    paint.setDevKernText(gDevKern);
    
    (void)paint.measureText(gText, strlen(gText), &bounds);
    paint.setColor(SK_ColorGREEN);
    bounds.offset(x, y);
    canvas->drawRect(bounds, paint);

    int count = paint.getTextWidths(gText, strlen(gText), w, r);

    paint.setColor(SK_ColorRED);
    for (int i = 0; i < count; i++) {
        r[i].offset(x, y);
        canvas->drawRect(r[i], paint);
        x += w[i];
    }
    x = SkIntToScalar(50);
    paint.setColor(gDevKern ? SK_ColorDKGRAY : SK_ColorBLACK);
    canvas->drawText(gText, strlen(gText), x, y, paint);
}

static void create_src(SkBitmap* bitmap, SkBitmap::Config config) {
    bitmap->setConfig(config, 100, 100);
    bitmap->allocPixels();
    bitmap->eraseColor(0);
    
    SkCanvas    canvas(*bitmap);
    SkPaint     paint;

    paint.setAntiAlias(true);
    canvas.drawCircle(SkIntToScalar(50), SkIntToScalar(50),
                      SkIntToScalar(50), paint);
}

static void blur(SkBitmap* dst, const SkBitmap& src, SkScalar radius) {
    *dst = src;
}

static void test_bitmap_blur(SkCanvas* canvas) {
    SkBitmap    src, dst;
    
    create_src(&src, SkBitmap::kARGB_8888_Config);
    blur(&dst, src, SkIntToScalar(4));
    
    SkPaint paint;
    
    paint.setColor(SK_ColorRED);

    canvas->drawBitmap(dst, SkIntToScalar(30), SkIntToScalar(60), &paint);
}

static SkScalar getpathlen(const SkPath& path) {
    SkPathMeasure   meas(path, false);
    return meas.getLength();
}

static void test_textpathmatrix(SkCanvas* canvas) {
    SkPaint paint;
    SkPath  path;
    SkMatrix matrix;
    
    path.moveTo(SkIntToScalar(200), SkIntToScalar(300));
    path.quadTo(SkIntToScalar(400), SkIntToScalar(100),
                SkIntToScalar(600), SkIntToScalar(300));

    paint.setAntiAlias(true);
    
    paint.setStyle(SkPaint::kStroke_Style);
 //   canvas->drawPath(path, paint);
    paint.setStyle(SkPaint::kFill_Style);
    paint.setTextSize(SkIntToScalar(48));
    paint.setTextAlign(SkPaint::kRight_Align);
    
    const char* text = "Reflection";
    size_t      len = strlen(text);
    SkScalar    pathLen = getpathlen(path);

    canvas->drawTextOnPath(text, len, path, NULL, paint);
    
    paint.setColor(SK_ColorRED);
    matrix.setScale(-SK_Scalar1, SK_Scalar1);
    matrix.postTranslate(pathLen, 0);
    canvas->drawTextOnPath(text, len, path, &matrix, paint);
    
    paint.setColor(SK_ColorBLUE);
    matrix.setScale(SK_Scalar1, -SK_Scalar1);
    canvas->drawTextOnPath(text, len, path, &matrix, paint);
    
    paint.setColor(SK_ColorGREEN);
    matrix.setScale(-SK_Scalar1, -SK_Scalar1);
    matrix.postTranslate(pathLen, 0);
    canvas->drawTextOnPath(text, len, path, &matrix, paint);
}

class TextOnPathView : public SampleView {
public:
    SkPath      fPath;
    SkScalar    fHOffset;

	TextOnPathView() {
        SkRect r;
        r.set(SkIntToScalar(100), SkIntToScalar(100),
              SkIntToScalar(300), SkIntToScalar(300));
        fPath.addOval(r);
        fPath.offset(SkIntToScalar(200), 0);

        fHOffset = SkIntToScalar(50);
    }

protected:
    // overrides from SkEventSink
    virtual bool onQuery(SkEvent* evt) {
        if (SampleCode::TitleQ(*evt)) {
            SampleCode::TitleR(evt, "Text On Path");
            return true;
        }
        return this->INHERITED::onQuery(evt);
    }
    
    virtual void onDrawContent(SkCanvas* canvas) {
        SkPaint paint;
        
        paint.setAntiAlias(true);
        paint.setTextSize(SkIntToScalar(50));

        for (int j = 0; j < REPEAT_COUNT; j++) {
            SkScalar x = fHOffset;

            paint.setColor(SK_ColorBLACK);
            canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath,
                                     x, paint.getTextSize()/2, paint);

            paint.setColor(SK_ColorRED);
            canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath,
                                     x + SkIntToScalar(50), 0, paint);

            paint.setColor(SK_ColorBLUE);
            canvas->drawTextOnPathHV(gText, sizeof(gText)-1, fPath,
                         x + SkIntToScalar(100), -paint.getTextSize()/2, paint);
        }
        
        paint.setColor(SK_ColorGREEN);
        paint.setStyle(SkPaint::kStroke_Style);
//        canvas->drawPath(fPath, paint);
        
        canvas->translate(0, SkIntToScalar(100));
        test_textpathmatrix(canvas);
        
        if (REPEAT_COUNT > 1)
            this->inval(NULL);
    }
    
    virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) {
        fHints += 1;
        this->inval(NULL);
        return this->INHERITED::onFindClickHandler(x, y);
    }
    
    virtual bool onClick(Click* click) {
        return this->INHERITED::onClick(click);
    }
    
private:
    int fHints;
    typedef SampleView INHERITED;
};

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

static SkView* MyFactory() {
    return new TextOnPathView;
}

static SkViewRegister reg(MyFactory);
