Home | History | Annotate | Download | only in chromium
      1 /*
      2  * Copyright (C) 2006, 2007 Apple Inc. All Rights Reserved.
      3  * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are
      7  * met:
      8  *
      9  *     * Redistributions of source code must retain the above copyright
     10  * notice, this list of conditions and the following disclaimer.
     11  *     * Redistributions in binary form must reproduce the above
     12  * copyright notice, this list of conditions and the following disclaimer
     13  * in the documentation and/or other materials provided with the
     14  * distribution.
     15  *     * Neither the name of Google Inc. nor the names of its
     16  * contributors may be used to endorse or promote products derived from
     17  * this software without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include "config.h"
     33 #include "core/platform/graphics/SimpleFontData.h"
     34 
     35 #include <mlang.h>
     36 #include <objidl.h>
     37 #include <unicode/uchar.h>
     38 #include <unicode/unorm.h>
     39 #include "core/platform/graphics/FloatRect.h"
     40 #include "core/platform/graphics/Font.h"
     41 #include "core/platform/graphics/FontCache.h"
     42 #include "core/platform/graphics/FontDescription.h"
     43 #include "core/platform/graphics/chromium/FontPlatformDataChromiumWin.h"
     44 #include "core/platform/win/HWndDC.h"
     45 #include "wtf/MathExtras.h"
     46 
     47 namespace WebCore {
     48 
     49 void SimpleFontData::platformInit()
     50 {
     51     if (!m_platformData.size()) {
     52         m_fontMetrics.reset();
     53         m_avgCharWidth = 0;
     54         m_maxCharWidth = 0;
     55         return;
     56     }
     57 
     58     HWndDC dc(0);
     59     HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
     60 
     61     TEXTMETRIC textMetric = {0};
     62     if (!GetTextMetrics(dc, &textMetric)) {
     63         if (FontPlatformData::ensureFontLoaded(m_platformData.hfont())) {
     64             // Retry GetTextMetrics.
     65             // FIXME: Handle gracefully the error if this call also fails.
     66             // See http://crbug.com/6401.
     67             if (!GetTextMetrics(dc, &textMetric))
     68                 LOG_ERROR("Unable to get the text metrics after second attempt");
     69         }
     70     }
     71 
     72     m_avgCharWidth = textMetric.tmAveCharWidth;
     73     m_maxCharWidth = textMetric.tmMaxCharWidth;
     74 
     75     // FIXME: Access ascent/descent/lineGap with floating point precision.
     76     float ascent = textMetric.tmAscent;
     77     float descent = textMetric.tmDescent;
     78     float lineGap = textMetric.tmExternalLeading;
     79     float xHeight = ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
     80 
     81     OUTLINETEXTMETRIC outlineTextMetric;
     82     if (GetOutlineTextMetrics(dc, sizeof(outlineTextMetric), &outlineTextMetric) > 0) {
     83         m_fontMetrics.setUnitsPerEm(outlineTextMetric.otmEMSquare);
     84 
     85         // This is a TrueType font.  We might be able to get an accurate xHeight.
     86         GLYPHMETRICS glyphMetrics = {0};
     87         MAT2 identityMatrix = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
     88         DWORD len = GetGlyphOutlineW(dc, 'x', GGO_METRICS, &glyphMetrics, 0, 0, &identityMatrix);
     89         if (len != GDI_ERROR && glyphMetrics.gmBlackBoxY > 0)
     90             xHeight = static_cast<float>(glyphMetrics.gmBlackBoxY);
     91     }
     92 
     93     m_fontMetrics.setAscent(ascent);
     94     m_fontMetrics.setDescent(descent);
     95     m_fontMetrics.setLineGap(lineGap);
     96     m_fontMetrics.setXHeight(xHeight);
     97     m_fontMetrics.setLineSpacing(ascent + descent + lineGap);
     98 
     99     SelectObject(dc, oldFont);
    100 }
    101 
    102 void SimpleFontData::platformCharWidthInit()
    103 {
    104     // charwidths are set in platformInit.
    105 }
    106 
    107 void SimpleFontData::platformDestroy()
    108 {
    109 }
    110 
    111 PassRefPtr<SimpleFontData> SimpleFontData::platformCreateScaledFontData(const FontDescription& fontDescription, float scaleFactor) const
    112 {
    113     LOGFONT winFont;
    114     GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont);
    115     float scaledSize = scaleFactor * fontDescription.computedSize();
    116     winFont.lfHeight = -lroundf(scaledSize);
    117     HFONT hfont = CreateFontIndirect(&winFont);
    118     return SimpleFontData::create(FontPlatformData(hfont, scaledSize, m_platformData.orientation()), isCustomFont(), false);
    119 }
    120 
    121 bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
    122 {
    123   // This used to be implemented with IMLangFontLink2, but since that code has
    124   // been disabled, this would always return false anyway.
    125   return false;
    126 }
    127 
    128 void SimpleFontData::determinePitch()
    129 {
    130     m_treatAsFixedPitch = platformData().isFixedPitch();
    131 }
    132 
    133 FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
    134 {
    135     HWndDC hdc(0);
    136     SetGraphicsMode(hdc, GM_ADVANCED);
    137     HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
    138 
    139     GLYPHMETRICS gdiMetrics;
    140     static const MAT2 identity = { 0, 1,  0, 0,  0, 0,  0, 1 };
    141     if (GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity) == -1) {
    142         if (FontPlatformData::ensureFontLoaded(m_platformData.hfont())) {
    143             // Retry GetTextMetrics.
    144             // FIXME: Handle gracefully the error if this call also fails.
    145             // See http://crbug.com/6401.
    146             if (GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity) == -1)
    147                 LOG_ERROR("Unable to get the glyph metrics after second attempt");
    148         }
    149     }
    150 
    151     SelectObject(hdc, oldFont);
    152 
    153     return FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y,
    154         gdiMetrics.gmBlackBoxX, gdiMetrics.gmBlackBoxY);
    155 }
    156 
    157 float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
    158 {
    159     if (!m_platformData.size())
    160         return 0;
    161 
    162     HWndDC dc(0);
    163     HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
    164 
    165     int width = 0;
    166     if (!GetCharWidthI(dc, glyph, 1, 0, &width)) {
    167         // Ask the browser to preload the font and retry.
    168         if (FontPlatformData::ensureFontLoaded(m_platformData.hfont())) {
    169             // FIXME: Handle gracefully the error if this call also fails.
    170             // See http://crbug.com/6401.
    171             if (!GetCharWidthI(dc, glyph, 1, 0, &width))
    172                 LOG_ERROR("Unable to get the char width after second attempt");
    173         }
    174     }
    175 
    176     SelectObject(dc, oldFont);
    177 
    178     return static_cast<float>(width);
    179 }
    180 
    181 }  // namespace WebCore
    182