// Copyright 2018 Google LLC
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
#ifndef SkPDFGlyphUse_DEFINED
#define SkPDFGlyphUse_DEFINED

#include "include/core/SkTypes.h"
#include "src/utils/SkBitSet.h"

class SkPDFGlyphUse {
public:
    SkPDFGlyphUse() : fBitSet(0) {}
    SkPDFGlyphUse(SkGlyphID firstNonZero, SkGlyphID lastGlyph)
        : fBitSet(lastGlyph - firstNonZero + 2)
        , fFirstNonZero(firstNonZero)
        , fLastGlyph(lastGlyph) { SkASSERT(firstNonZero >= 1); }
    ~SkPDFGlyphUse() = default;
    SkPDFGlyphUse(SkPDFGlyphUse&&) = default;
    SkPDFGlyphUse& operator=(SkPDFGlyphUse&&) = default;

    SkGlyphID firstNonZero() const { return fFirstNonZero; }
    SkGlyphID lastGlyph() const { return fLastGlyph; }
    void set(SkGlyphID gid) { fBitSet.set(this->toCode(gid)); }
    bool has(SkGlyphID gid) const { return fBitSet.test(this->toCode(gid)); }

    template<typename FN>
    void getSetValues(FN f) const {
        if (fFirstNonZero == 1) {
            return fBitSet.forEachSetIndex(std::move(f));
        }
        size_t offset = fFirstNonZero - 1;
        fBitSet.forEachSetIndex([&f, offset](size_t v) { f(v == 0 ? v : v + offset); });
    }

private:
    SkBitSet fBitSet;
    SkGlyphID fFirstNonZero = 0;
    SkGlyphID fLastGlyph = 0;

    size_t toCode(SkGlyphID gid) const {
        if (gid == 0 || fFirstNonZero == 1) {
            return gid;
        }
        SkASSERT(gid >= fFirstNonZero && gid <= fLastGlyph);
        return gid - fFirstNonZero + 1;
    }
    SkPDFGlyphUse(const SkPDFGlyphUse&) = delete;
    SkPDFGlyphUse& operator=(const SkPDFGlyphUse&) = delete;
};
#endif  // SkPDFGlyphUse_DEFINED
