/*
 * This file is part of the internal font implementation.  It should not be included by anyone other than
 * FontMac.cpp, FontWin.cpp and Font.cpp.
 *
 * Copyright (C) 2006 Apple Computer, Inc.
 * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
 * Copyright (C) 2007 Holger Hans Peter Freyther
 * Copyright (C) 2007 Pioneer Research Center USA, Inc.
 * All rights reserved.
 * Copyright (C) 2009, 2010, 2011 Espial Group Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 *
 */

#ifndef FontPlatformData_h
#define FontPlatformData_h

#include "GlyphBuffer.h"
#include "FontDescription.h"
#include "FontBaseline.h"
#include "FontMetrics.h"
#if USE(HARFBUZZ_NG)
#include "HarfBuzzNGFace.h"
#endif
#include "OpenTypeVerticalData.h"
#include "SharedBuffer.h"
#include "Timer.h"
#include <wtf/HashMap.h>
#include <wtf/Vector.h>
#include <cairo.h>
#include <cairo-ft.h>
#include <fontconfig/fcfreetype.h>
#include <OwnPtrCairo.h>
#include <RefPtrCairo.h>

#if USE(OPENVG)
#error "should use openvg/FontPlatformData.h"
#endif

class HarfBuzzNGFace;

namespace WebCore {

typedef HashMap<UChar32, UChar32> FontCharReplaceMap;

class GraphicsContext;
class GlyphBuffer;
class GlyphPage;
class FloatPoint;
class TextRun;

void setBMLFontMode(bool);

void setFontAntialiased(bool);

FT_UInt getFreeTypeCharIndex (FT_Face face, FcChar32 ucs4);

class FontPlatformData {
	WTF_MAKE_FAST_ALLOCATED;
public:
    FontPlatformData(const FontDescription&, bool bold, bool italic);
    FontPlatformData(const FontDescription&, cairo_font_face_t* fontFace, bool bold, bool italic);
    FontPlatformData(const FontDescription&, FcPattern*, const String& familyName = String());
    
    FontPlatformData(const FontPlatformData&);
    FontPlatformData& operator=(const FontPlatformData&);
    
    FontPlatformData smallCapsFontData(const FontDescription& fontDescription) const;
    
    FontMetrics metrics() const;
        
    static int totalCachedScaledFonts();

    void drawGlyphs(GraphicsContext*, const GlyphBuffer&, int from, int numGlyphs, const FloatPoint&);
    		
    ~FontPlatformData();

#if USE(HARFBUZZ_NG)
    HarfBuzzNGFace* harfbuzzFace() const;
#endif

    unsigned hash() const;
    
    static bool init();

    bool isFixedPitch() const { return m_fixedWidth; }
    float size() const { return m_fontDescription.computedSize(); }
    bool syntheticBold() const { return m_syntheticBold; }
    bool syntheticOblique() const { return m_syntheticOblique; }
    void setSyntheticOblique(bool);
    bool hasCompatibleCharmap();

    const FontDescription& fontDescription() const { return m_fontDescription; }
    const String& familyName() const { return m_familyName; }

    FontOrientation orientation() const { return m_fontDescription.orientation(); }
    void setOrientation(FontOrientation);
    PassRefPtr<SharedBuffer> openTypeTable(uint32_t table) const;
    PassRefPtr<OpenTypeVerticalData> verticalData() const;
    
    cairo_scaled_font_t* scaledFont() const { return m_scaledFont.get(); }

    FcPattern* fcPattern() const { return m_pattern.get(); }
    
    float syntheticBoldOffset() const { return syntheticBold() ? 1.0f : 0.f; }
    
    bool operator==(const FontPlatformData&) const;
    
#ifndef NDEBUG
    String description() const;
#endif

    FontCharReplaceMap& charReplaceMap() { return m_charReplaceMap; }
    const FontCharReplaceMap& charReplaceMap() const { return m_charReplaceMap; }
    
    void cacheScaledFont(cairo_scaled_font_t* scaledFont);

private:
    void buildScaledFont(cairo_font_face_t*);

    void clearCachedScaledFonts();

    void cachePruneTimerCallback(Timer<FontPlatformData>*);

    RefPtr<FcPattern> m_pattern;
    RefPtr<cairo_scaled_font_t> m_scaledFont;
    RefPtr<cairo_font_face_t> m_fontFace;

#if USE(HARFBUZZ_NG)
    mutable RefPtr<HarfBuzzNGFace> m_harfbuzzFace;
#endif

    Vector<std::pair<cairo_scaled_font_t*, double> > m_cachedScaledFonts;
    Timer<FontPlatformData> m_cachePruneTimer;

    FontDescription m_fontDescription;
    String m_familyName;
    bool m_syntheticBold : 1;
    bool m_syntheticOblique : 1;
    bool m_fixedWidth : 1;
    mutable float m_spaceWidth;

    FontCharReplaceMap m_charReplaceMap;

public:
    mutable OwnPtr<FcFontSet> m_fallbacks;
};

inline bool FontPlatformData::operator==(const FontPlatformData& other) const
{
    // FcPatternEqual does not support null pointers as arguments.
    if ((m_pattern && !other.m_pattern)
        || (!m_pattern && other.m_pattern)
        || (m_pattern != other.m_pattern && !FcPatternEqual(m_pattern.get(), other.m_pattern.get())))
        return false;

    return m_scaledFont == other.m_scaledFont
        && m_fontDescription.computedSize() == other.m_fontDescription.computedSize()
        && m_fontDescription.computedHorizontalSize() == other.m_fontDescription.computedHorizontalSize()
        && m_fontDescription.stretch() == other.m_fontDescription.stretch()
        && m_fontDescription.fontSizeClamp() == other.m_fontDescription.fontSizeClamp()
        && m_syntheticOblique == other.m_syntheticOblique
        && m_fontDescription.orientation() == other.m_fontDescription.orientation()
        && m_syntheticBold == other.m_syntheticBold;
}

}

#endif
