/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkShaper.h"
#include "SkStream.h"
#include "SkTextBlob.h"
#include "SkTypeface.h"

struct SkShaper::Impl {
    sk_sp<SkTypeface> fTypeface;
};

SkShaper::SkShaper(sk_sp<SkTypeface> tf) : fImpl(new Impl) {
    fImpl->fTypeface = tf ? std::move(tf) : SkTypeface::MakeDefault();
}

SkShaper::~SkShaper() {}

bool SkShaper::good() const { return true; }

// This example only uses public API, so we don't use SkUTF8_NextUnichar.
unsigned utf8_lead_byte_to_count(const char* ptr) {
    uint8_t c = *(const uint8_t*)ptr;
    SkASSERT(c <= 0xF7);
    SkASSERT((c & 0xC0) != 0x80);
    return (((0xE5 << 24) >> ((unsigned)c >> 4 << 1)) & 3) + 1;
}

SkPoint SkShaper::shape(SkTextBlobBuilder* builder,
                        const SkPaint& srcPaint,
                        const char* utf8text,
                        size_t textBytes,
                        bool leftToRight,
                        SkPoint point,
                        SkScalar width) const {
    sk_ignore_unused_variable(leftToRight);

    SkPaint paint(srcPaint);
    paint.setTypeface(fImpl->fTypeface);
    paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
    int glyphCount = paint.countText(utf8text, textBytes);
    if (glyphCount <= 0) {
        return point;
    }
    SkRect bounds;
    SkPaint::FontMetrics metrics;
    paint.getFontMetrics(&metrics);
    point.fY -= metrics.fAscent;
    (void)paint.measureText(utf8text, textBytes, &bounds);
    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    const SkTextBlobBuilder::RunBuffer& runBuffer =
        builder->allocRunTextPosH(paint, glyphCount, point.y(), textBytes, SkString(), &bounds);
    memcpy(runBuffer.utf8text, utf8text, textBytes);
    const char* txtPtr = utf8text;
    for (int i = 0; i < glyphCount; ++i) {
        // Each charater maps to exactly one glyph via SkGlyphCache::unicharToGlyph().
        runBuffer.clusters[i] = SkToU32(txtPtr - utf8text);
        txtPtr += utf8_lead_byte_to_count(txtPtr);
        SkASSERT(txtPtr <= utf8text + textBytes);
    }
    paint.setTextEncoding(SkPaint::kUTF8_TextEncoding);
    (void)paint.textToGlyphs(utf8text, textBytes, runBuffer.glyphs);
    (void)paint.getTextWidths(utf8text, textBytes, runBuffer.pos);
    SkScalar x = point.x();
    for (int i = 0; i < glyphCount; ++i) {
        SkScalar w = runBuffer.pos[i];
        runBuffer.pos[i] = x;
        x += w;
    }
    point.fY += metrics.fDescent + metrics.fLeading;

    return point;
}
