#ifndef GlyphPage_h
#define GlyphPage_h
#include "platform/PlatformExport.h"
#include "platform/fonts/Glyph.h"
#include <string.h>
#include "wtf/PassRefPtr.h"
#include "wtf/RefCounted.h"
#include "wtf/RefPtr.h"
#include "wtf/unicode/Unicode.h"
namespace WebCore {
class SimpleFontData;
class GlyphPageTreeNode;
struct GlyphData {
GlyphData(Glyph g = 0, const SimpleFontData* f = 0)
: glyph(g)
, fontData(f)
{
}
Glyph glyph;
const SimpleFontData* fontData;
};
#if COMPILER(MSVC)
#pragma warning(push)
#pragma warning(disable: 4200)
#endif
class PLATFORM_EXPORT GlyphPage : public RefCounted<GlyphPage> {
public:
static PassRefPtr<GlyphPage> createForMixedFontData(GlyphPageTreeNode* owner)
{
void* slot = fastMalloc(sizeof(GlyphPage) + sizeof(SimpleFontData*) * GlyphPage::size);
return adoptRef(new (slot) GlyphPage(owner));
}
static PassRefPtr<GlyphPage> createForSingleFontData(GlyphPageTreeNode* owner, const SimpleFontData* fontData)
{
ASSERT(fontData);
return adoptRef(new GlyphPage(owner, fontData));
}
PassRefPtr<GlyphPage> createCopiedSystemFallbackPage(GlyphPageTreeNode* owner) const
{
RefPtr<GlyphPage> page = GlyphPage::createForMixedFontData(owner);
memcpy(page->m_glyphs, m_glyphs, sizeof(m_glyphs));
if (hasPerGlyphFontData())
memcpy(page->m_perGlyphFontData, m_perGlyphFontData, sizeof(SimpleFontData*) * GlyphPage::size);
else {
for (size_t i = 0; i < GlyphPage::size; ++i) {
page->m_perGlyphFontData[i] = m_glyphs[i] ? m_fontDataForAllGlyphs : 0;
}
}
return page.release();
}
~GlyphPage() { }
static const size_t size = 256;
static unsigned indexForCharacter(UChar32 c) { return c % GlyphPage::size; }
ALWAYS_INLINE GlyphData glyphDataForCharacter(UChar32 c) const
{
return glyphDataForIndex(indexForCharacter(c));
}
ALWAYS_INLINE GlyphData glyphDataForIndex(unsigned index) const
{
ASSERT_WITH_SECURITY_IMPLICATION(index < size);
Glyph glyph = m_glyphs[index];
if (hasPerGlyphFontData())
return GlyphData(glyph, m_perGlyphFontData[index]);
return GlyphData(glyph, glyph ? m_fontDataForAllGlyphs : 0);
}
ALWAYS_INLINE Glyph glyphForCharacter(UChar32 c) const
{
return glyphAt(indexForCharacter(c));
}
ALWAYS_INLINE Glyph glyphAt(unsigned index) const
{
ASSERT_WITH_SECURITY_IMPLICATION(index < size);
return m_glyphs[index];
}
ALWAYS_INLINE const SimpleFontData* fontDataForCharacter(UChar32 c) const
{
unsigned index = indexForCharacter(c);
if (hasPerGlyphFontData())
return m_perGlyphFontData[index];
return m_glyphs[index] ? m_fontDataForAllGlyphs : 0;
}
void setGlyphDataForCharacter(UChar32 c, Glyph g, const SimpleFontData* f)
{
setGlyphDataForIndex(indexForCharacter(c), g, f);
}
void setGlyphDataForIndex(unsigned index, Glyph glyph, const SimpleFontData* fontData)
{
ASSERT_WITH_SECURITY_IMPLICATION(index < size);
m_glyphs[index] = glyph;
if (hasPerGlyphFontData()) {
m_perGlyphFontData[index] = glyph ? fontData : 0;
return;
}
ASSERT(!glyph || fontData == m_fontDataForAllGlyphs);
}
void setGlyphDataForIndex(unsigned index, const GlyphData& glyphData)
{
setGlyphDataForIndex(index, glyphData.glyph, glyphData.fontData);
}
void removeFontDataFromSystemFallbackPage(const SimpleFontData* fontData)
{
ASSERT(hasPerGlyphFontData());
for (size_t i = 0; i < size; ++i) {
if (m_perGlyphFontData[i] == fontData) {
m_glyphs[i] = 0;
m_perGlyphFontData[i] = 0;
}
}
}
GlyphPageTreeNode* owner() const { return m_owner; }
bool fill(unsigned offset, unsigned length, UChar* characterBuffer, unsigned bufferLength, const SimpleFontData*);
private:
explicit GlyphPage(GlyphPageTreeNode* owner, const SimpleFontData* fontDataForAllGlyphs = 0)
: m_fontDataForAllGlyphs(fontDataForAllGlyphs)
, m_owner(owner)
{
memset(m_glyphs, 0, sizeof(m_glyphs));
if (hasPerGlyphFontData())
memset(m_perGlyphFontData, 0, sizeof(SimpleFontData*) * GlyphPage::size);
}
bool hasPerGlyphFontData() const { return !m_fontDataForAllGlyphs; }
const SimpleFontData* m_fontDataForAllGlyphs;
GlyphPageTreeNode* m_owner;
Glyph m_glyphs[size];
const SimpleFontData* m_perGlyphFontData[0];
};
#if COMPILER(MSVC)
#pragma warning(pop)
#endif
}
#endif