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 "SimpleFontData.h"
     34 
     35 #include "ChromiumBridge.h"
     36 #include "Font.h"
     37 #include "FontCache.h"
     38 #include "FloatRect.h"
     39 #include "FontDescription.h"
     40 #include <wtf/MathExtras.h>
     41 
     42 #include <unicode/uchar.h>
     43 #include <unicode/unorm.h>
     44 #include <objidl.h>
     45 #include <mlang.h>
     46 
     47 namespace WebCore {
     48 
     49 static inline float scaleEmToUnits(float x, int unitsPerEm)
     50 {
     51     return unitsPerEm ? x / static_cast<float>(unitsPerEm) : x;
     52 }
     53 
     54 void SimpleFontData::platformInit()
     55 {
     56     HDC dc = GetDC(0);
     57     HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
     58 
     59     TEXTMETRIC textMetric = {0};
     60     if (!GetTextMetrics(dc, &textMetric)) {
     61         if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) {
     62             // Retry GetTextMetrics.
     63             // FIXME: Handle gracefully the error if this call also fails.
     64             // See http://crbug.com/6401.
     65             if (!GetTextMetrics(dc, &textMetric))
     66                 LOG_ERROR("Unable to get the text metrics after second attempt");
     67         }
     68     }
     69 
     70     m_avgCharWidth = textMetric.tmAveCharWidth;
     71     m_maxCharWidth = textMetric.tmMaxCharWidth;
     72 
     73     m_ascent = textMetric.tmAscent;
     74     m_descent = textMetric.tmDescent;
     75     m_lineGap = textMetric.tmExternalLeading;
     76     m_xHeight = m_ascent * 0.56f;  // Best guess for xHeight for non-Truetype fonts.
     77 
     78     OUTLINETEXTMETRIC outlineTextMetric;
     79     if (GetOutlineTextMetrics(dc, sizeof(outlineTextMetric), &outlineTextMetric) > 0) {
     80         // This is a TrueType font.  We might be able to get an accurate xHeight.
     81         GLYPHMETRICS glyphMetrics = {0};
     82         MAT2 identityMatrix = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
     83         DWORD len = GetGlyphOutlineW(dc, 'x', GGO_METRICS, &glyphMetrics, 0, 0, &identityMatrix);
     84         if (len != GDI_ERROR && glyphMetrics.gmBlackBoxY > 0)
     85             m_xHeight = static_cast<float>(glyphMetrics.gmBlackBoxY);
     86     }
     87 
     88     m_lineSpacing = m_ascent + m_descent + m_lineGap;
     89 
     90     SelectObject(dc, oldFont);
     91     ReleaseDC(0, dc);
     92 }
     93 
     94 void SimpleFontData::platformCharWidthInit()
     95 {
     96     // charwidths are set in platformInit.
     97 }
     98 
     99 void SimpleFontData::platformDestroy()
    100 {
    101     // We don't hash this on Win32, so it's effectively owned by us.
    102     delete m_smallCapsFontData;
    103     m_smallCapsFontData = 0;
    104 }
    105 
    106 SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
    107 {
    108     if (!m_smallCapsFontData) {
    109         LOGFONT winFont;
    110         GetObject(m_platformData.hfont(), sizeof(LOGFONT), &winFont);
    111         float smallCapsSize = 0.70f * fontDescription.computedSize();
    112         // Unlike WebKit trunk, we don't multiply the size by 32.  That seems
    113         // to be some kind of artifact of their CG backend, or something.
    114         winFont.lfHeight = -lroundf(smallCapsSize);
    115         HFONT hfont = CreateFontIndirect(&winFont);
    116         m_smallCapsFontData =
    117             new SimpleFontData(FontPlatformData(hfont, smallCapsSize));
    118     }
    119     return m_smallCapsFontData;
    120 }
    121 
    122 bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
    123 {
    124   // This used to be implemented with IMLangFontLink2, but since that code has
    125   // been disabled, this would always return false anyway.
    126   return false;
    127 }
    128 
    129 void SimpleFontData::determinePitch()
    130 {
    131     // TEXTMETRICS have this.  Set m_treatAsFixedPitch based off that.
    132     HDC dc = GetDC(0);
    133     HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
    134 
    135     // Yes, this looks backwards, but the fixed pitch bit is actually set if the font
    136     // is *not* fixed pitch.  Unbelievable but true.
    137     TEXTMETRIC textMetric = {0};
    138     if (!GetTextMetrics(dc, &textMetric)) {
    139         if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) {
    140             // Retry GetTextMetrics.
    141             // FIXME: Handle gracefully the error if this call also fails.
    142             // See http://crbug.com/6401.
    143             if (!GetTextMetrics(dc, &textMetric))
    144                 LOG_ERROR("Unable to get the text metrics after second attempt");
    145         }
    146     }
    147 
    148     m_treatAsFixedPitch = ((textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
    149 
    150     SelectObject(dc, oldFont);
    151     ReleaseDC(0, dc);
    152 }
    153 
    154 float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
    155 {
    156     HDC dc = GetDC(0);
    157     HGDIOBJ oldFont = SelectObject(dc, m_platformData.hfont());
    158 
    159     int width = 0;
    160     if (!GetCharWidthI(dc, glyph, 1, 0, &width)) {
    161         // Ask the browser to preload the font and retry.
    162         if (ChromiumBridge::ensureFontLoaded(m_platformData.hfont())) {
    163             // FIXME: Handle gracefully the error if this call also fails.
    164             // See http://crbug.com/6401.
    165             if (!GetCharWidthI(dc, glyph, 1, 0, &width))
    166                 LOG_ERROR("Unable to get the char width after second attempt");
    167         }
    168     }
    169 
    170     SelectObject(dc, oldFont);
    171     ReleaseDC(0, dc);
    172 
    173     return static_cast<float>(width);
    174 }
    175 
    176 }  // namespace WebCore
    177