| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2009 Google Inc. All rights reserved. | 2 * Copyright (C) 2009 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "platform/fonts/opentype/OpenTypeSanitizer.h" | 31 #include "platform/fonts/WebFontDecoder.h" |
| 32 | 32 |
| 33 #include "hb.h" | |
| 34 #include "ots-memory-stream.h" | |
| 35 #include "platform/Histogram.h" | 33 #include "platform/Histogram.h" |
| 36 #include "platform/SharedBuffer.h" | 34 #include "platform/SharedBuffer.h" |
| 37 #include "platform/TraceEvent.h" | 35 #include "platform/TraceEvent.h" |
| 36 #include "platform/fonts/FontCache.h" |
| 38 #include "public/platform/Platform.h" | 37 #include "public/platform/Platform.h" |
| 38 #include "third_party/harfbuzz-ng/src/hb.h" |
| 39 #include "third_party/ots/include/ots-memory-stream.h" |
| 40 #include "third_party/skia/include/core/SkStream.h" |
| 39 #include "wtf/CurrentTime.h" | 41 #include "wtf/CurrentTime.h" |
| 40 | 42 |
| 41 #include <stdarg.h> | 43 #include <stdarg.h> |
| 42 | 44 |
| 43 namespace blink { | 45 namespace blink { |
| 44 | 46 |
| 45 static void recordDecodeSpeedHistogram(SharedBuffer* buffer, double decodeTime,
size_t decodedSize) | 47 namespace { |
| 46 { | |
| 47 if (decodeTime <= 0) | |
| 48 return; | |
| 49 | 48 |
| 50 double kbPerSecond = decodedSize / (1000 * decodeTime); | 49 class BlinkOTSContext final : public ots::OTSContext { |
| 51 if (buffer->size() >= 4) { | 50 DISALLOW_NEW(); |
| 52 const char* data = buffer->data(); | 51 public: |
| 53 if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F'
) { | |
| 54 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, woffHistogram,
new CustomCountHistogram("WebFont.DecodeSpeed.WOFF", 1000, 300000, 50)); | |
| 55 woffHistogram.count(kbPerSecond); | |
| 56 return; | |
| 57 } | |
| 58 | 52 |
| 59 if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == '2'
) { | 53 void Message(int level, const char *format, ...) override; |
| 60 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, woff2Histogram
, new CustomCountHistogram("WebFont.DecodeSpeed.WOFF2", 1000, 300000, 50)); | 54 ots::TableAction GetTableAction(uint32_t tag) override; |
| 61 woff2Histogram.count(kbPerSecond); | 55 const String& getErrorString() { return m_errorString; } |
| 62 return; | |
| 63 } | |
| 64 } | |
| 65 | 56 |
| 66 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, sfntHistogram, new Cus
tomCountHistogram("WebFont.DecodeSpeed.SFNT", 1000, 300000, 50)); | 57 private: |
| 67 sfntHistogram.count(kbPerSecond); | 58 String m_errorString; |
| 68 } | 59 }; |
| 69 | |
| 70 PassRefPtr<SharedBuffer> OpenTypeSanitizer::sanitize() | |
| 71 { | |
| 72 if (!m_buffer) { | |
| 73 setErrorString("Empty Buffer"); | |
| 74 return nullptr; | |
| 75 } | |
| 76 | |
| 77 // This is the largest web font size which we'll try to transcode. | |
| 78 static const size_t maxWebFontSize = 30 * 1024 * 1024; // 30 MB | |
| 79 if (m_buffer->size() > maxWebFontSize) { | |
| 80 setErrorString("Web font size more than 30MB"); | |
| 81 return nullptr; | |
| 82 } | |
| 83 | |
| 84 // A transcoded font is usually smaller than an original font. | |
| 85 // However, it can be slightly bigger than the original one due to | |
| 86 // name table replacement and/or padding for glyf table. | |
| 87 // | |
| 88 // With WOFF fonts, however, we'll be decompressing, so the result can be | |
| 89 // much larger than the original. | |
| 90 | |
| 91 ots::ExpandingMemoryStream output(m_buffer->size(), maxWebFontSize); | |
| 92 double start = currentTime(); | |
| 93 BlinkOTSContext otsContext; | |
| 94 | |
| 95 TRACE_EVENT_BEGIN0("blink", "DecodeFont"); | |
| 96 bool ok = otsContext.Process(&output, reinterpret_cast<const uint8_t*>(m_buf
fer->data()), m_buffer->size()); | |
| 97 TRACE_EVENT_END0("blink", "DecodeFont"); | |
| 98 | |
| 99 if (!ok) { | |
| 100 setErrorString(otsContext.getErrorString()); | |
| 101 return nullptr; | |
| 102 } | |
| 103 | |
| 104 const size_t transcodeLen = output.Tell(); | |
| 105 recordDecodeSpeedHistogram(m_buffer, currentTime() - start, transcodeLen); | |
| 106 return SharedBuffer::create(static_cast<unsigned char*>(output.get()), trans
codeLen); | |
| 107 } | |
| 108 | |
| 109 bool OpenTypeSanitizer::supportsFormat(const String& format) | |
| 110 { | |
| 111 return equalIgnoringCase(format, "woff") || equalIgnoringCase(format, "woff2
"); | |
| 112 } | |
| 113 | 60 |
| 114 void BlinkOTSContext::Message(int level, const char *format, ...) | 61 void BlinkOTSContext::Message(int level, const char *format, ...) |
| 115 { | 62 { |
| 116 va_list args; | 63 va_list args; |
| 117 va_start(args, format); | 64 va_start(args, format); |
| 118 | 65 |
| 119 #if COMPILER(MSVC) | 66 #if COMPILER(MSVC) |
| 120 int result = _vscprintf(format, args); | 67 int result = _vscprintf(format, args); |
| 121 #else | 68 #else |
| 122 char ch; | 69 char ch; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 166 case gdefTag: | 113 case gdefTag: |
| 167 case gposTag: | 114 case gposTag: |
| 168 case gsubTag: | 115 case gsubTag: |
| 169 #endif | 116 #endif |
| 170 return ots::TABLE_ACTION_PASSTHRU; | 117 return ots::TABLE_ACTION_PASSTHRU; |
| 171 default: | 118 default: |
| 172 return ots::TABLE_ACTION_DEFAULT; | 119 return ots::TABLE_ACTION_DEFAULT; |
| 173 } | 120 } |
| 174 } | 121 } |
| 175 | 122 |
| 123 void recordDecodeSpeedHistogram(const char* data, size_t length, double decodeTi
me, size_t decodedSize) |
| 124 { |
| 125 if (decodeTime <= 0) |
| 126 return; |
| 127 |
| 128 double kbPerSecond = decodedSize / (1000 * decodeTime); |
| 129 if (length >= 4) { |
| 130 if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == 'F'
) { |
| 131 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, woffHistogram,
new CustomCountHistogram("WebFont.DecodeSpeed.WOFF", 1000, 300000, 50)); |
| 132 woffHistogram.count(kbPerSecond); |
| 133 return; |
| 134 } |
| 135 |
| 136 if (data[0] == 'w' && data[1] == 'O' && data[2] == 'F' && data[3] == '2'
) { |
| 137 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, woff2Histogram
, new CustomCountHistogram("WebFont.DecodeSpeed.WOFF2", 1000, 300000, 50)); |
| 138 woff2Histogram.count(kbPerSecond); |
| 139 return; |
| 140 } |
| 141 } |
| 142 |
| 143 DEFINE_THREAD_SAFE_STATIC_LOCAL(CustomCountHistogram, sfntHistogram, new Cus
tomCountHistogram("WebFont.DecodeSpeed.SFNT", 1000, 300000, 50)); |
| 144 sfntHistogram.count(kbPerSecond); |
| 145 } |
| 146 |
| 147 } // namespace |
| 148 |
| 149 // static |
| 150 bool WebFontDecoder::supportsFormat(const String& format) |
| 151 { |
| 152 return equalIgnoringCase(format, "woff") || equalIgnoringCase(format, "woff2
"); |
| 153 } |
| 154 |
| 155 PassRefPtr<SkTypeface> WebFontDecoder::decode(SharedBuffer* buffer) |
| 156 { |
| 157 if (!buffer) { |
| 158 setErrorString("Empty Buffer"); |
| 159 return nullptr; |
| 160 } |
| 161 |
| 162 // This is the largest web font size which we'll try to transcode. |
| 163 // TODO(bashi): 30MB seems low. Update the limit if necessary. |
| 164 static const size_t maxWebFontSize = 30 * 1024 * 1024; // 30 MB |
| 165 if (buffer->size() > maxWebFontSize) { |
| 166 setErrorString("Web font size more than 30MB"); |
| 167 return nullptr; |
| 168 } |
| 169 |
| 170 // Most web fonts are compressed, so the result can be much larger than |
| 171 // the original. |
| 172 ots::ExpandingMemoryStream output(buffer->size(), maxWebFontSize); |
| 173 double start = currentTime(); |
| 174 BlinkOTSContext otsContext; |
| 175 const char* data = buffer->data(); |
| 176 |
| 177 TRACE_EVENT_BEGIN0("blink", "DecodeFont"); |
| 178 bool ok = otsContext.Process(&output, reinterpret_cast<const uint8_t*>(data)
, buffer->size()); |
| 179 TRACE_EVENT_END0("blink", "DecodeFont"); |
| 180 |
| 181 if (!ok) { |
| 182 setErrorString(otsContext.getErrorString()); |
| 183 return nullptr; |
| 184 } |
| 185 |
| 186 const size_t decodedLength = output.Tell(); |
| 187 recordDecodeSpeedHistogram(data, buffer->size(), currentTime() - start, deco
dedLength); |
| 188 |
| 189 sk_sp<SkData> skData = SkData::MakeWithCopy(output.get(), decodedLength); |
| 190 SkMemoryStream* stream = new SkMemoryStream(skData); |
| 191 #if OS(WIN) |
| 192 RefPtr<SkTypeface> typeface = adoptRef(FontCache::fontCache()->fontManager()
->createFromStream(stream)); |
| 193 #else |
| 194 RefPtr<SkTypeface> typeface = adoptRef(SkTypeface::CreateFromStream(stream))
; |
| 195 #endif |
| 196 if (!typeface) { |
| 197 setErrorString("Not a valid font data"); |
| 198 return nullptr; |
| 199 } |
| 200 |
| 201 return typeface.release(); |
| 202 } |
| 203 |
| 176 } // namespace blink | 204 } // namespace blink |
| OLD | NEW |