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

#ifndef GrGlyph_DEFINED
#define GrGlyph_DEFINED

#include "GrDrawOpAtlas.h"
#include "GrRect.h"
#include "GrTypes.h"

#include "SkChecksum.h"
#include "SkFixed.h"
#include "SkPath.h"

struct GrGlyph {
    enum MaskStyle {
        kCoverage_MaskStyle,
        kDistance_MaskStyle
    };

    static GrMaskFormat FormatFromSkGlyph(const SkGlyph& glyph) {
        SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
        switch (format) {
            case SkMask::kBW_Format:
            case SkMask::kSDF_Format:
                // fall through to kA8 -- we store BW and SDF glyphs in our 8-bit cache
            case SkMask::kA8_Format:
                return kA8_GrMaskFormat;
            case SkMask::k3D_Format:
                return kA8_GrMaskFormat; // ignore the mul and add planes, just use the mask
            case SkMask::kLCD16_Format:
                return kA565_GrMaskFormat;
            case SkMask::kARGB32_Format:
                return kARGB_GrMaskFormat;
            default:
                SkDEBUGFAIL("unsupported SkMask::Format");
                return kA8_GrMaskFormat;
        }
    }

    static GrIRect16 BoundsFromSkGlyph(const SkGlyph& glyph) {
        return GrIRect16::MakeXYWH(glyph.fLeft,
                                   glyph.fTop,
                                   glyph.fWidth,
                                   glyph.fHeight);
    }

    static MaskStyle MaskStyleFromSkGlyph(const SkGlyph& skGlyph) {
        return (SkMask::Format)skGlyph.fMaskFormat == SkMask::kSDF_Format
           ? GrGlyph::MaskStyle::kDistance_MaskStyle
           : GrGlyph::MaskStyle::kCoverage_MaskStyle;
    }

    GrGlyph(const SkGlyph& skGlyph)
        : fPackedID{skGlyph.getPackedID()}
        , fMaskFormat{FormatFromSkGlyph(skGlyph)}
        , fMaskStyle{MaskStyleFromSkGlyph(skGlyph)}
        , fBounds{BoundsFromSkGlyph(skGlyph)} {}


    SkRect destRect(SkPoint origin) {
        return SkRect::MakeXYWH(
                SkIntToScalar(fBounds.fLeft) + origin.x(),
                SkIntToScalar(fBounds.fTop)  + origin.y(),
                SkIntToScalar(fBounds.width()),
                SkIntToScalar(fBounds.height()));
    }

    SkRect destRect(SkPoint origin, SkScalar textScale) {
        if (fMaskStyle == kCoverage_MaskStyle) {
            return SkRect::MakeXYWH(
                    SkIntToScalar(fBounds.fLeft)    * textScale + origin.x(),
                    SkIntToScalar(fBounds.fTop)     * textScale + origin.y(),
                    SkIntToScalar(fBounds.width())  * textScale,
                    SkIntToScalar(fBounds.height()) * textScale);
        } else {
            return SkRect::MakeXYWH(
                    (SkIntToScalar(fBounds.fLeft) + SK_DistanceFieldInset) * textScale + origin.x(),
                    (SkIntToScalar(fBounds.fTop)  + SK_DistanceFieldInset) * textScale + origin.y(),
                    (SkIntToScalar(fBounds.width())  - 2 * SK_DistanceFieldInset) * textScale,
                    (SkIntToScalar(fBounds.height()) - 2 * SK_DistanceFieldInset) * textScale);
        }
    }

    int width() const { return fBounds.width(); }
    int height() const { return fBounds.height(); }
    uint32_t pageIndex() const { return GrDrawOpAtlas::GetPageIndexFromID(fID); }
    MaskStyle maskStyle() const { return fMaskStyle; }

    // GetKey and Hash for the the hash table.
    static const SkPackedGlyphID& GetKey(const GrGlyph& glyph) {
        return glyph.fPackedID;
    }

    static uint32_t Hash(SkPackedGlyphID key) {
        return SkChecksum::Mix(key.hash());
    }

    const SkPackedGlyphID  fPackedID;
    const GrMaskFormat     fMaskFormat;
    const MaskStyle        fMaskStyle;
    const GrIRect16        fBounds;
    SkIPoint16             fAtlasLocation{0, 0};
    GrDrawOpAtlas::AtlasID fID{GrDrawOpAtlas::kInvalidAtlasID};
};

#endif
