Home | History | Annotate | Download | only in chromium
      1 /*
      2  * Copyright (c) 2008, 2009, Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 #include "config.h"
     32 #include "SimpleFontData.h"
     33 
     34 #include "Font.h"
     35 #include "FontCache.h"
     36 #include "FloatRect.h"
     37 #include "FontDescription.h"
     38 #include "Logging.h"
     39 #include "VDMXParser.h"
     40 
     41 #include "SkFontHost.h"
     42 #include "SkPaint.h"
     43 #include "SkTime.h"
     44 #include "SkTypeface.h"
     45 #include "SkTypes.h"
     46 
     47 namespace WebCore {
     48 
     49 // Smallcaps versions of fonts are 70% the size of the normal font.
     50 static const float smallCapsFraction = 0.7f;
     51 // This is the largest VDMX table which we'll try to load and parse.
     52 static const size_t maxVDMXTableSize = 1024 * 1024;  // 1 MB
     53 
     54 void SimpleFontData::platformInit()
     55 {
     56     SkPaint paint;
     57     SkPaint::FontMetrics metrics;
     58 
     59     m_platformData.setupPaint(&paint);
     60     paint.getFontMetrics(&metrics);
     61     const SkFontID fontID = m_platformData.uniqueID();
     62 
     63     static const uint32_t vdmxTag = SkSetFourByteTag('V', 'D', 'M', 'X');
     64     int pixelSize = m_platformData.size() + 0.5;
     65     int vdmxAscent, vdmxDescent;
     66     bool isVDMXValid = false;
     67 
     68     size_t vdmxSize = SkFontHost::GetTableSize(fontID, vdmxTag);
     69     if (vdmxSize && vdmxSize < maxVDMXTableSize) {
     70         uint8_t* vdmxTable = (uint8_t*) fastMalloc(vdmxSize);
     71         if (vdmxTable
     72             && SkFontHost::GetTableData(fontID, vdmxTag, 0, vdmxSize, vdmxTable) == vdmxSize
     73             && parseVDMX(&vdmxAscent, &vdmxDescent, vdmxTable, vdmxSize, pixelSize))
     74             isVDMXValid = true;
     75         fastFree(vdmxTable);
     76     }
     77 
     78     // Beware those who step here: This code is designed to match Win32 font
     79     // metrics *exactly*.
     80     if (isVDMXValid) {
     81         m_ascent = vdmxAscent;
     82         m_descent = -vdmxDescent;
     83     } else {
     84         SkScalar height = -metrics.fAscent + metrics.fDescent + metrics.fLeading;
     85         m_ascent = SkScalarRound(-metrics.fAscent);
     86         m_descent = SkScalarRound(height) - m_ascent;
     87     }
     88 
     89     if (metrics.fXHeight)
     90         m_xHeight = metrics.fXHeight;
     91     else {
     92         // hack taken from the Windows port
     93         m_xHeight = static_cast<float>(m_ascent) * 0.56;
     94     }
     95 
     96     m_lineGap = SkScalarRound(metrics.fLeading);
     97     m_lineSpacing = m_ascent + m_descent + m_lineGap;
     98 
     99     // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
    100     // calculated for us, but we need to calculate m_maxCharWidth and
    101     // m_avgCharWidth in order for text entry widgets to be sized correctly.
    102 
    103     SkScalar xRange = metrics.fXMax - metrics.fXMin;
    104     m_maxCharWidth = SkScalarRound(xRange * SkScalarRound(m_platformData.size()));
    105 
    106     if (metrics.fAvgCharWidth)
    107         m_avgCharWidth = SkScalarRound(metrics.fAvgCharWidth);
    108     else {
    109         m_avgCharWidth = m_xHeight;
    110 
    111         GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
    112 
    113         if (glyphPageZero) {
    114             static const UChar32 x_char = 'x';
    115             const Glyph xGlyph = glyphPageZero->glyphDataForCharacter(x_char).glyph;
    116 
    117             if (xGlyph)
    118                 m_avgCharWidth = widthForGlyph(xGlyph);
    119         }
    120     }
    121 }
    122 
    123 void SimpleFontData::platformCharWidthInit()
    124 {
    125     // charwidths are set in platformInit.
    126 }
    127 
    128 void SimpleFontData::platformDestroy()
    129 {
    130     delete m_smallCapsFontData;
    131     m_smallCapsFontData = 0;
    132 }
    133 
    134 SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
    135 {
    136     if (!m_smallCapsFontData) {
    137         const float smallCapsSize = lroundf(fontDescription.computedSize() * smallCapsFraction);
    138         m_smallCapsFontData = new SimpleFontData(FontPlatformData(m_platformData, smallCapsSize));
    139     }
    140 
    141     return m_smallCapsFontData;
    142 }
    143 
    144 bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
    145 {
    146     SkPaint paint;
    147     static const unsigned maxBufferCount = 64;
    148     uint16_t glyphs[maxBufferCount];
    149 
    150     m_platformData.setupPaint(&paint);
    151     paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
    152 
    153     while (length > 0) {
    154         int n = SkMin32(length, SK_ARRAY_COUNT(glyphs));
    155 
    156         // textToGlyphs takes a byte count so we double the character count.
    157         int count = paint.textToGlyphs(characters, n * 2, glyphs);
    158         for (int i = 0; i < count; i++) {
    159             if (0 == glyphs[i])
    160                 return false;       // missing glyph
    161         }
    162 
    163         characters += n;
    164         length -= n;
    165     }
    166 
    167     return true;
    168 }
    169 
    170 void SimpleFontData::determinePitch()
    171 {
    172     m_treatAsFixedPitch = platformData().isFixedPitch();
    173 }
    174 
    175 float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
    176 {
    177     SkASSERT(sizeof(glyph) == 2);   // compile-time assert
    178 
    179     SkPaint paint;
    180 
    181     m_platformData.setupPaint(&paint);
    182 
    183     paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    184     SkScalar width = paint.measureText(&glyph, 2);
    185 
    186     return SkScalarToFloat(width);
    187 }
    188 
    189 }  // namespace WebCore
    190