#include "config.h"
#include "Font.h"
#include "FontCache.h"
#include "FloatRect.h"
#include "FontDescription.h"
#include <wtf/MathExtras.h>
#include <unicode/uchar.h>
#include <unicode/unorm.h>
#include <cairo.h>
#include <cairo-win32.h>
#include <mlang.h>
namespace WebCore
{
void FontData::platformInit()
{
m_isMLangFont = false;
HDC dc = GetDC(0);
SaveDC(dc);
cairo_scaled_font_t* scaledFont = m_font.scaledFont();
const double metricsMultiplier = cairo_win32_scaled_font_get_metrics_factor(scaledFont) * m_font.size();
cairo_win32_scaled_font_select_font(scaledFont, dc);
TEXTMETRIC tm;
GetTextMetrics(dc, &tm);
m_ascent = lroundf(tm.tmAscent * metricsMultiplier);
m_descent = lroundf(tm.tmDescent * metricsMultiplier);
m_xHeight = m_ascent * 0.56f; m_lineGap = lroundf(tm.tmExternalLeading * metricsMultiplier);
m_lineSpacing = m_ascent + m_descent + m_lineGap;
OUTLINETEXTMETRIC otm;
if (GetOutlineTextMetrics(dc, sizeof(otm), &otm) > 0) {
GLYPHMETRICS gm;
MAT2 mat = { 1, 0, 0, 1 }; DWORD len = GetGlyphOutlineW(dc, 'x', GGO_METRICS, &gm, 0, 0, &mat);
if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0)
m_xHeight = gm.gmptGlyphOrigin.y * metricsMultiplier;
}
cairo_win32_scaled_font_done_font(scaledFont);
RestoreDC(dc, -1);
ReleaseDC(0, dc);
}
void FontData::platformDestroy()
{
cairo_font_face_destroy(m_font.fontFace());
cairo_scaled_font_destroy(m_font.scaledFont());
if (m_isMLangFont) {
IMLangFontLink2* langFontLink = FontCache::getFontLinkInterface();
if (langFontLink)
langFontLink->ReleaseFont(m_font.hfont());
} else
DeleteObject(m_font.hfont());
delete m_smallCapsFontData;
}
FontData* FontData::smallCapsFontData(const FontDescription& fontDescription) const
{
if (!m_smallCapsFontData) {
LOGFONT winfont;
GetObject(m_font.hfont(), sizeof(LOGFONT), &winfont);
int smallCapsHeight = lroundf(0.70f * fontDescription.computedSize());
winfont.lfHeight = -smallCapsHeight;
HFONT hfont = CreateFontIndirect(&winfont);
m_smallCapsFontData = new FontData(FontPlatformData(hfont, smallCapsHeight));
}
return m_smallCapsFontData;
}
bool FontData::containsCharacters(const UChar* characters, int length) const
{
HDC dc = GetDC(0);
SaveDC(dc);
SelectObject(dc, m_font.hfont());
WORD* glyphBuffer = new WORD[length];
GetGlyphIndices(dc, characters, length, glyphBuffer, GGI_MARK_NONEXISTING_GLYPHS);
RestoreDC(dc, -1);
ReleaseDC(0, dc);
for (unsigned i = 0; i < length; i++) {
if (glyphBuffer[i] == 0xFFFFFFFF) {
delete []glyphBuffer;
return false;
}
}
delete []glyphBuffer;
return true;
}
void FontData::determinePitch()
{
HDC dc = GetDC((HWND)0);
SaveDC(dc);
SelectObject(dc, m_font.hfont());
TEXTMETRIC tm;
GetTextMetrics(dc, &tm);
m_treatAsFixedPitch = ((tm.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
RestoreDC(dc, -1);
ReleaseDC(0, dc);
}
float FontData::platformWidthForGlyph(Glyph glyph) const
{
HDC dc = GetDC(0);
SaveDC(dc);
cairo_scaled_font_t* scaledFont = m_font.scaledFont();
cairo_win32_scaled_font_select_font(scaledFont, dc);
int width;
GetCharWidthI(dc, glyph, 1, 0, &width);
cairo_win32_scaled_font_done_font(scaledFont);
RestoreDC(dc, -1);
ReleaseDC(0, dc);
const double metricsMultiplier = cairo_win32_scaled_font_get_metrics_factor(scaledFont) * m_font.size();
return width * metricsMultiplier;
}
}