/*
 * Copyright (c) 2012 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "sky/engine/config.h"
#include "sky/engine/platform/fonts/harfbuzz/HarfBuzzFace.h"

#include "hb-ot.h"
#include "hb.h"
#include "sky/engine/platform/fonts/FontPlatformData.h"

namespace blink {

const hb_tag_t HarfBuzzFace::vertTag = HB_TAG('v', 'e', 'r', 't');
const hb_tag_t HarfBuzzFace::vrt2Tag = HB_TAG('v', 'r', 't', '2');

// Though we have FontCache class, which provides the cache mechanism for
// WebKit's font objects, we also need additional caching layer for HarfBuzz
// to reduce the memory consumption because hb_face_t should be associated with
// underling font data (e.g. CTFontRef, FTFace).

class FaceCacheEntry : public RefCounted<FaceCacheEntry> {
public:
    static PassRefPtr<FaceCacheEntry> create(hb_face_t* face)
    {
        ASSERT(face);
        return adoptRef(new FaceCacheEntry(face));
    }
    ~FaceCacheEntry()
    {
        hb_face_destroy(m_face);
    }

    hb_face_t* face() { return m_face; }
    HashMap<uint32_t, uint16_t>* glyphCache() { return &m_glyphCache; }

private:
    explicit FaceCacheEntry(hb_face_t* face)
        : m_face(face)
    { }

    hb_face_t* m_face;
    HashMap<uint32_t, uint16_t> m_glyphCache;
};

typedef HashMap<uint64_t, RefPtr<FaceCacheEntry>, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t> > HarfBuzzFaceCache;

static HarfBuzzFaceCache* harfBuzzFaceCache()
{
    DEFINE_STATIC_LOCAL(HarfBuzzFaceCache, s_harfBuzzFaceCache, ());
    return &s_harfBuzzFaceCache;
}

HarfBuzzFace::HarfBuzzFace(FontPlatformData* platformData, uint64_t uniqueID)
    : m_platformData(platformData)
    , m_uniqueID(uniqueID)
    , m_scriptForVerticalText(HB_SCRIPT_INVALID)
{
    HarfBuzzFaceCache::AddResult result = harfBuzzFaceCache()->add(m_uniqueID, nullptr);
    if (result.isNewEntry)
        result.storedValue->value = FaceCacheEntry::create(createFace());
    result.storedValue->value->ref();
    m_face = result.storedValue->value->face();
    m_glyphCacheForFaceCacheEntry = result.storedValue->value->glyphCache();
}

HarfBuzzFace::~HarfBuzzFace()
{
    HarfBuzzFaceCache::iterator result = harfBuzzFaceCache()->find(m_uniqueID);
    ASSERT_WITH_SECURITY_IMPLICATION(result != harfBuzzFaceCache()->end());
    ASSERT(result.get()->value->refCount() > 1);
    result.get()->value->deref();
    if (result.get()->value->refCount() == 1)
        harfBuzzFaceCache()->remove(m_uniqueID);
}

static hb_script_t findScriptForVerticalGlyphSubstitution(hb_face_t* face)
{
    static const unsigned maxCount = 32;

    unsigned scriptCount = maxCount;
    hb_tag_t scriptTags[maxCount];
    hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCount, scriptTags);
    for (unsigned scriptIndex = 0; scriptIndex < scriptCount; ++scriptIndex) {
        unsigned languageCount = maxCount;
        hb_tag_t languageTags[maxCount];
        hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, scriptIndex, 0, &languageCount, languageTags);
        for (unsigned languageIndex = 0; languageIndex < languageCount; ++languageIndex) {
            unsigned featureIndex;
            if (hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scriptIndex, languageIndex, HarfBuzzFace::vertTag, &featureIndex)
                || hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scriptIndex, languageIndex, HarfBuzzFace::vrt2Tag, &featureIndex))
                return hb_ot_tag_to_script(scriptTags[scriptIndex]);
        }
    }
    return HB_SCRIPT_INVALID;
}

void HarfBuzzFace::setScriptForVerticalGlyphSubstitution(hb_buffer_t* buffer)
{
    if (m_scriptForVerticalText == HB_SCRIPT_INVALID)
        m_scriptForVerticalText = findScriptForVerticalGlyphSubstitution(m_face);
    hb_buffer_set_script(buffer, m_scriptForVerticalText);
}

} // namespace blink
