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

#include "gm.h"

#include "SkCanvas.h"
#include "SkPoint.h"
#include "SkTextBlob.h"
#include "SkTDArray.h"

namespace  {

enum Pos {
    kDefault_Pos = 0,
    kScalar_Pos  = 1,
    kPoint_Pos   = 2,
};

const struct BlobCfg {
    unsigned count;
    Pos      pos;
    SkScalar scale;
} blobConfigs[][3][3] = {
    {
        { { 1024, kDefault_Pos, 1 }, { 0, kDefault_Pos, 0 }, { 0, kDefault_Pos, 0 } },
        { { 1024,  kScalar_Pos, 1 }, { 0,  kScalar_Pos, 0 }, { 0,  kScalar_Pos, 0 } },
        { { 1024,   kPoint_Pos, 1 }, { 0,   kPoint_Pos, 0 }, { 0,   kPoint_Pos, 0 } },
    },
    {
        { { 4, kDefault_Pos, 1},     { 4, kDefault_Pos, 1},  { 4, kDefault_Pos, 1} },
        { { 4,  kScalar_Pos, 1},     { 4,  kScalar_Pos, 1},  { 4,  kScalar_Pos, 1} },
        { { 4,   kPoint_Pos, 1},     { 4,   kPoint_Pos, 1},  { 4,   kPoint_Pos, 1} },
    },

    {
        { { 4, kDefault_Pos, 1},     { 4, kDefault_Pos, 1},  { 4,  kScalar_Pos, 1} },
        { { 4,  kScalar_Pos, 1},     { 4,  kScalar_Pos, 1},  { 4,   kPoint_Pos, 1} },
        { { 4,   kPoint_Pos, 1},     { 4,   kPoint_Pos, 1},  { 4, kDefault_Pos, 1} },
    },

    {
        { { 4, kDefault_Pos, 1},     { 4,  kScalar_Pos, 1},  { 4,   kPoint_Pos, 1} },
        { { 4,  kScalar_Pos, 1},     { 4,   kPoint_Pos, 1},  { 4, kDefault_Pos, 1} },
        { { 4,   kPoint_Pos, 1},     { 4, kDefault_Pos, 1},  { 4,  kScalar_Pos, 1} },
    },
};

const SkScalar kFontSize = 16;
}

class TextBlobGM : public skiagm::GM {
public:
    TextBlobGM(const char* txt) {
        SkPaint p;
        size_t txtLen = strlen(txt);
        int glyphCount = p.textToGlyphs(txt, txtLen, NULL);

        fGlyphs.append(glyphCount);
        p.textToGlyphs(txt, txtLen, fGlyphs.begin());
    }

protected:
    virtual SkString onShortName() SK_OVERRIDE {
        return SkString("textblob");
    }

    virtual SkISize onISize() SK_OVERRIDE {
        return SkISize::Make(640, 480);
    }

    virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
        for (unsigned b = 0; b < SK_ARRAY_COUNT(blobConfigs); ++b) {
            SkAutoTUnref<const SkTextBlob> blob(makeBlob(b));

            SkPaint p;
            p.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
            p.setTextSize(kFontSize);
            p.setAntiAlias(true);
            p.setSubpixelText(true);

            SkPoint offset = SkPoint::Make(SkIntToScalar(10 + 300 * (b % 2)),
                                           SkIntToScalar(20 + 150 * (b / 2)));

            canvas->drawTextBlob(blob, offset.x(), offset.y(), p);

            p.setColor(SK_ColorBLUE);
            p.setStyle(SkPaint::kStroke_Style);
            SkRect box = blob->bounds();
            box.offset(offset);
            canvas->drawRect(box, p);

        }
    }

private:
    const SkTextBlob* makeBlob(unsigned blobIndex) {
        SkTextBlobBuilder builder;

        SkPaint font;
        font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);

        for (unsigned l = 0; l < SK_ARRAY_COUNT(blobConfigs[blobIndex]); ++l) {
            unsigned currentGlyph = 0;

            for (unsigned c = 0; c < SK_ARRAY_COUNT(blobConfigs[blobIndex][l]); ++c) {
                const BlobCfg* cfg = &blobConfigs[blobIndex][l][c];
                unsigned count = cfg->count;

                if (count > fGlyphs.count() - currentGlyph) {
                    count = fGlyphs.count() - currentGlyph;
                }
                if (0 == count) {
                    break;
                }

                font.setTextSize(kFontSize * cfg->scale);
                const SkScalar advanceX = font.getTextSize() * 0.85f;
                const SkScalar advanceY = font.getTextSize() * 1.5f;

                SkPoint offset = SkPoint::Make(currentGlyph * advanceX + c * advanceX,
                                               advanceY * l);
                switch (cfg->pos) {
                case kDefault_Pos: {
                    const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, count,
                                                                               offset.x(),
                                                                               offset.y());
                    memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
                } break;
                case kScalar_Pos: {
                    const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPosH(font, count,
                                                                                   offset.y());
                    SkTDArray<SkScalar> pos;
                    for (unsigned i = 0; i < count; ++i) {
                        *pos.append() = offset.x() + i * advanceX;
                    }

                    memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
                    memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar));
                } break;
                case kPoint_Pos: {
                    const SkTextBlobBuilder::RunBuffer& buf = builder.allocRunPos(font, count);

                    SkTDArray<SkScalar> pos;
                    for (unsigned i = 0; i < count; ++i) {
                        *pos.append() = offset.x() + i * advanceX;
                        *pos.append() = offset.y() + i * (advanceY / count);
                    }

                    memcpy(buf.glyphs, fGlyphs.begin() + currentGlyph, count * sizeof(uint16_t));
                    memcpy(buf.pos, pos.begin(), count * sizeof(SkScalar) * 2);
                } break;
                default:
                    SkFAIL("unhandled pos value");
                }

                currentGlyph += count;
            }
        }

        return builder.build();
    }

    SkTDArray<uint16_t> fGlyphs;

    typedef skiagm::GM INHERITED;
};

DEF_GM( return SkNEW_ARGS(TextBlobGM, ("hamburgefons")); )
