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