10bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch/*
20bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2006, 2007 Apple Inc.  All rights reserved.
30bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2007-2009 Torch Mobile, Inc.
40bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *
50bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Redistribution and use in source and binary forms, with or without
60bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * modification, are permitted provided that the following conditions
70bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * are met:
80bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *
90bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 1.  Redistributions of source code must retain the above copyright
100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     notice, this list of conditions and the following disclaimer.
110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 2.  Redistributions in binary form must reproduce the above copyright
120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     notice, this list of conditions and the following disclaimer in the
130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     documentation and/or other materials provided with the distribution.
140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     its contributors may be used to endorse or promote products derived
160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *     from this software without specific prior written permission.
170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch *
180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch */
290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "config.h"
310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "SimpleFontData.h"
320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "FloatRect.h"
340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "Font.h"
350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "FontCache.h"
360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "FontDescription.h"
370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include <mlang.h>
382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include <wtf/MathExtras.h>
390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochnamespace WebCore {
410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochextern HDC g_screenDC;
430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid SimpleFontData::platformInit()
450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!m_platformData.isValid())
470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    const TEXTMETRIC& tm = m_platformData.metrics();
500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_isSystemFont = m_platformData.isSystemFont();
510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float ascent = (tm.tmAscent * m_platformData.size() + 36) / 72.0f;
532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float descent = (tm.tmDescent * m_platformData.size() + 36) / 72.0f;
542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float lineGap = (tm.tmExternalLeading * m_platformData.size() + 36) / 72.0f;
552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_fontMetrics.setAscent(ascent);
562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_fontMetrics.setDescent(descent);
572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_fontMetrics.setLineGap(lineGap);
582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    m_fontMetrics.setXHeight(ascent * 0.56f);
600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid SimpleFontData::platformDestroy()
630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
64f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
65f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
66f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochSimpleFontData* SimpleFontData::scaledFontData(const FontDescription& fontDescription, float scaleFactor) const
67f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
68f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    FontDescription fontDesc(fontDescription);
69f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    fontDesc.setComputedSize(lroundf(scaleFactor * fontDesc.computedSize()));
70f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    fontDesc.setSpecifiedSize(lroundf(scaleFactor * fontDesc.specifiedSize()));
71f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    fontDesc.setKeywordSize(lroundf(scaleFactor * fontDesc.keywordSize()));
72f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    FontPlatformData* result = fontCache()->getCachedFontPlatformData(fontDesc, m_platformData.family());
73f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return result ? new SimpleFontData(*result) : 0;
740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochSimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
78f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_derivedFontData)
79f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_derivedFontData = DerivedFontData::create(isCustomFont());
80f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_derivedFontData->smallCaps)
81f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_derivedFontData->smallCaps = scaledFontData(fontDescription, .7);
82f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
83f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return m_derivedFontData->smallCaps.get();
84f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
85f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
86f05b935882198ccf7d81675736e3aeb089c5113aBen MurdochSimpleFontData* SimpleFontData::emphasisMarkFontData(const FontDescription& fontDescription) const
87f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
88f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_derivedFontData)
89f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_derivedFontData = DerivedFontData::create(isCustomFont());
90f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!m_derivedFontData->emphasisMark)
91f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        m_derivedFontData->emphasisMark = scaledFontData(fontDescription, .5);
92f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
93f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return m_derivedFontData->emphasisMark.get();
940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochDWORD getKnownFontCodePages(const wchar_t* family);
970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool SimpleFontData::containsCharacters(const UChar* characters, int length) const
990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_platformData.isDisabled())
1010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return true;
1020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // FIXME: Microsoft documentation seems to imply that characters can be output using a given font and DC
1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // merely by testing code page intersection.  This seems suspect though.  Can't a font only partially
1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // cover a given code page?
1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // FIXME: in the case that we failed to get the interface, still use the font.
1080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if defined(IMLANG_FONT_LINK) && (IMLANG_FONT_LINK == 2)
1090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    IMLangFontLink2* langFontLink = fontCache()->getFontLinkInterface();
1100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#else
1110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    IMLangFontLink* langFontLink = fontCache()->getFontLinkInterface();
1120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#endif
1130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!langFontLink)
1140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return true;
1150bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    DWORD fontCodePages = m_platformData.codePages();
1170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!fontCodePages)
1180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return false;
1190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    DWORD acpCodePages = 0;
1210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    langFontLink->CodePageToCodePages(CP_ACP, &acpCodePages);
1220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    DWORD actualCodePages;
1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    long numCharactersProcessed;
1250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    while (length) {
1260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        langFontLink->GetStrCodePages(characters, length, acpCodePages, &actualCodePages, &numCharactersProcessed);
1270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (actualCodePages && !(actualCodePages & fontCodePages))
1280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return false;
1290bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        length -= numCharactersProcessed;
1310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        characters += numCharactersProcessed;
1320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
1330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return true;
1350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1360bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid SimpleFontData::determinePitch()
1380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!m_platformData.isValid())
1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
1410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    const TEXTMETRIC& tm = m_platformData.metrics();
1430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // Yes, this looks backwards, but the fixed pitch bit is actually set if the font
1450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // is *not* fixed pitch.  Unbelievable but true.
1460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_treatAsFixedPitch = !(tm.tmPitchAndFamily & TMPF_FIXED_PITCH);
1470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1480bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
14921939df44de1705786c545cd1bf519d47250322dBen MurdochFloatRect SimpleFontData::platformBoundsForGlyph(Glyph) const
15021939df44de1705786c545cd1bf519d47250322dBen Murdoch{
15121939df44de1705786c545cd1bf519d47250322dBen Murdoch    return FloatRect();
15221939df44de1705786c545cd1bf519d47250322dBen Murdoch}
15321939df44de1705786c545cd1bf519d47250322dBen Murdoch
1540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochfloat SimpleFontData::platformWidthForGlyph(Glyph glyph) const
1550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_platformData.isDisabled())
1570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return 0;
1580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    HGDIOBJ hOldFont = SelectObject(g_screenDC, m_platformData.hfont());
1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    SIZE fontSize;
1620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    wchar_t c = glyph;
1630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    GetTextExtentPoint32(g_screenDC, &c, 1, &fontSize);
1640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    SelectObject(g_screenDC, hOldFont);
1660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return (float)fontSize.cx * (float)m_platformData.size() / 72.f;
1680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid SimpleFontData::platformCharWidthInit()
1720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!m_platformData.isValid())
1740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return;
1750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    const TEXTMETRIC& tm = m_platformData.metrics();
1770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_avgCharWidth = (tm.tmAveCharWidth * m_platformData.size() + 36) / 72;
1780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_maxCharWidth = (tm.tmMaxCharWidth * m_platformData.size() + 36) / 72;
1790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
18168513a70bcd92384395513322f1b801e7bf9c729Steve Block} // namespace WebCore
182