Source/WebCore/ChangeLog

 12012-06-04 Kenichi Ishibashi <bashi@chromium.org>
 2
 3 [Chromium] Implement font shaping with font-feature-settings on Mac
 4 https://bugs.webkit.org/show_bug.cgi?id=69826
 5
 6 Reviewed by Tony Chang.
 7
 8 Add HarfBuzz-ng text shaper.
 9 Chromium mac port uses it as secondary text shaper to support OpenType features.
 10 HarfBuzz-ng is only used when -webkit-font-feature-settings is specified and
 11 corresponding font is not an AAT font.
 12
 13 No new tests. css3/font-feature-settings-rendering.html should pass on Chromium mac port.
 14
 15 * WebCore.gyp/WebCore.gyp: Added harfbuzz-ng dependencies.
 16 * WebCore.gypi: Added harfbuzz-ng files.
 17 * platform/graphics/FontPlatformData.h:
 18 (FontPlatformData): Added m_harfbuzzFace.
 19 * platform/graphics/cocoa/FontPlatformDataCocoa.mm:
 20 (WebCore::FontPlatformData::platformDataInit): Copy m_harfbuzzFace.
 21 (WebCore::FontPlatformData::platformDataAssign): Ditto.
 22 (WebCore):
 23 (WebCore::isAATFont):
 24 (WebCore::FontPlatformData::harfbuzzFace):
 25 * platform/graphics/harfbuzz/ng/HarfBuzzFace.cpp: Added.
 26 (WebCore):
 27 (WebCore::harfbuzzFaceCache):
 28 (WebCore::HarfBuzzFace::HarfBuzzFace):
 29 (WebCore::HarfBuzzFace::~HarfBuzzFace):
 30 * platform/graphics/harfbuzz/ng/HarfBuzzFace.h: Added.
 31 (WebCore):
 32 (HarfBuzzFace):
 33 (WebCore::HarfBuzzFace::create):
 34 * platform/graphics/harfbuzz/ng/HarfBuzzFaceCoreText.cpp: Added.
 35 (WebCore):
 36 (WebCore::floatToHarfBuzzPosition):
 37 (WebCore::getGlyph):
 38 (WebCore::getGlyphHorizontalAdvance):
 39 (WebCore::getGlyphHorizontalOrigin):
 40 (WebCore::getGlyphExtents):
 41 (WebCore::harfbuzzCoreTextGetFontFuncs):
 42 (WebCore::releaseTableData):
 43 (WebCore::harfbuzzCoreTextGetTable):
 44 (WebCore::HarfBuzzFace::createFace):
 45 (WebCore::HarfBuzzFace::createFont):
 46 (WebCore::HarfBuzzShaper::createGlyphBufferAdvance):
 47 * platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp: Added.
 48 (WebCore):
 49 (WebCore::harfbuzzPositionToFloat):
 50 (WebCore::HarfBuzzShaper::HarfBuzzRun::HarfBuzzRun):
 51 (WebCore::HarfBuzzShaper::HarfBuzzRun::setGlyphAndPositions):
 52 (WebCore::HarfBuzzShaper::HarfBuzzRun::characterIndexForXPosition):
 53 (WebCore::HarfBuzzShaper::HarfBuzzRun::xPositionForOffset):
 54 (WebCore::HarfBuzzShaper::HarfBuzzShaper):
 55 (WebCore::HarfBuzzShaper::~HarfBuzzShaper):
 56 (WebCore::HarfBuzzShaper::setFontFeatures):
 57 (WebCore::HarfBuzzShaper::shape):
 58 (WebCore::HarfBuzzShaper::setupHarfBuzzRun):
 59 (WebCore::HarfBuzzShaper::shapeHarfBuzzRun):
 60 (WebCore::HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun):
 61 (WebCore::HarfBuzzShaper::offsetForPosition):
 62 (WebCore::HarfBuzzShaper::selectionRect):
 63 * platform/graphics/harfbuzz/ng/HarfBuzzShaper.h: Added.
 64 (WebCore):
 65 (HarfBuzzShaper):
 66 (WebCore::HarfBuzzShaper::totalWidth):
 67 (HarfBuzzRun):
 68 (WebCore::HarfBuzzShaper::HarfBuzzRun::create):
 69 (WebCore::HarfBuzzShaper::HarfBuzzRun::setWidth):
 70 (WebCore::HarfBuzzShaper::HarfBuzzRun::numCharacters):
 71 (WebCore::HarfBuzzShaper::HarfBuzzRun::numGlyphs):
 72 (WebCore::HarfBuzzShaper::HarfBuzzRun::width):
 73 (WebCore::HarfBuzzShaper::HarfBuzzRun::rtl):
 74 * platform/graphics/mac/FontComplexTextMac.cpp:
 75 (WebCore):
 76 (WebCore::preferHarfBuzz): Added.
 77 (WebCore::Font::selectionRectForComplexText): Use HarfBuzzShaper if font-feature-settings exists.
 78 (WebCore::Font::drawComplexText): Ditto.
 79 (WebCore::Font::floatWidthForComplexText): Ditto.
 80 (WebCore::Font::offsetForPositionForComplexText): Ditto.
 81
1822012-06-04 Sheriff Bot <webkit.review.bot@gmail.com>
283
384 Unreviewed, rolling out r119393.

Source/WebCore/WebCore.gyp/WebCore.gyp

208208 '../platform/graphics/mac',
209209 '../platform/mac',
210210 '../platform/text/mac',
 211 '../platform/graphics/harfbuzz',
 212 '../platform/graphics/harfbuzz/ng',
211213 ],
212214 }],
213215 ['OS=="win"', {

15571559 ],
15581560 'dependencies': [
15591561 'webkit_system_interface',
 1562 '<(chromium_src_dir)/third_party/harfbuzz-ng/harfbuzz.gyp:harfbuzz-ng',
15601563 ],
15611564 'actions': [
15621565 {

16521655 ['exclude', 'platform/graphics/skia/GlyphPageTreeNodeSkia\\.cpp$'],
16531656 ['exclude', 'platform/graphics/skia/SimpleFontDataSkia\\.cpp$'],
16541657 ['exclude', 'platform/chromium/DragImageChromiumMac\\.cpp$'],
 1658
 1659 # Mac uses Harfbuzz-ng.
 1660 ['include', 'platform/graphics/harfbuzz/HarfBuzzShaperBase\\.(cpp|h)$'],
 1661 ['include', 'platform/graphics/harfbuzz/ng/HarfBuzzFaceCoreText\\.cpp$'],
 1662 ['include', 'platform/graphics/harfbuzz/ng/HarfBuzzFace\\.(cpp|h)$'],
 1663 ['include', 'platform/graphics/harfbuzz/ng/HarfBuzzShaper\\.(cpp|h)$'],
16551664 ],
16561665 },{ # OS!="mac"
16571666 'sources/': [

Source/WebCore/WebCore.gypi

39063906 'platform/graphics/harfbuzz/HarfBuzzSkia.h',
39073907 'platform/graphics/harfbuzz/HarfBuzzShaperBase.cpp',
39083908 'platform/graphics/harfbuzz/HarfBuzzShaperBase.h',
 3909 'platform/graphics/harfbuzz/ng/HarfBuzzFaceCoreText.cpp',
 3910 'platform/graphics/harfbuzz/ng/HarfBuzzFace.cpp',
 3911 'platform/graphics/harfbuzz/ng/HarfBuzzFace.h',
 3912 'platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp',
 3913 'platform/graphics/harfbuzz/ng/HarfBuzzShaper.h',
39093914 'platform/graphics/mac/ColorMac.mm',
39103915 'platform/graphics/mac/ComplexTextController.cpp',
39113916 'platform/graphics/mac/ComplexTextController.h',

Source/WebCore/platform/graphics/FontPlatformData.h

@@typedef const struct __CTFont* CTFontRef;
7272
7373#if PLATFORM(CHROMIUM) && OS(DARWIN)
7474#include "CrossProcessFontLoading.h"
 75#include "HarfBuzzFace.h"
7576#endif
7677
7778#if PLATFORM(WIN)

@@public:
255256 cairo_scaled_font_t* scaledFont() const { return m_scaledFont; }
256257#endif
257258
 259#if PLATFORM(CHROMIUM) && OS(DARWIN)
 260 HarfBuzzFace* harfbuzzFace();
 261#endif
 262
258263 unsigned hash() const
259264 {
260265#if PLATFORM(WIN) && !USE(CAIRO)

@@private:
358363
359364#if PLATFORM(CHROMIUM) && OS(DARWIN)
360365 RefPtr<MemoryActivatedFont> m_inMemoryFont;
 366 RefPtr<HarfBuzzFace> m_harfbuzzFace;
361367#endif
362368
363369 bool m_isColorBitmapFont;

Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm

@@void FontPlatformData::platformDataInit(const FontPlatformData& f)
9292
9393#if PLATFORM(CHROMIUM) && OS(DARWIN)
9494 m_inMemoryFont = f.m_inMemoryFont;
 95 m_harfbuzzFace = f.m_harfbuzzFace;
9596#endif
9697}
9798

@@const FontPlatformData& FontPlatformData::platformDataAssign(const FontPlatformD
108109 m_CTFont = f.m_CTFont;
109110#if PLATFORM(CHROMIUM) && OS(DARWIN)
110111 m_inMemoryFont = f.m_inMemoryFont;
 112 m_harfbuzzFace = f.m_harfbuzzFace;
111113#endif
112114 return *this;
113115}

@@CTFontRef FontPlatformData::ctFont() const
297299 return m_CTFont.get();
298300}
299301
 302#if PLATFORM(CHROMIUM) && OS(DARWIN)
 303static bool isAATFont(CTFontRef ctFont)
 304{
 305 CFDataRef table = CTFontCopyTable(ctFont, kCTFontTableMort, kCTFontOptionsDefault);
 306 if (table) {
 307 CFRelease(table);
 308 return true;
 309 }
 310 table = CTFontCopyTable(ctFont, kCTFontTableMorx, kCTFontOptionsDefault);
 311 if (table) {
 312 CFRelease(table);
 313 return true;
 314 }
 315 return false;
 316}
 317
 318HarfBuzzFace* FontPlatformData::harfbuzzFace()
 319{
 320 CTFontRef font = ctFont();
 321 // HarfBuzz can't handle AAT font
 322 if (isAATFont(font))
 323 return 0;
 324
 325 if (!m_harfbuzzFace) {
 326 uint64_t uniqueID = reinterpret_cast<uintptr_t>(font);
 327 m_harfbuzzFace = HarfBuzzFace::create(const_cast<FontPlatformData*>(this), uniqueID);
 328 }
 329 return m_harfbuzzFace.get();
 330}
 331#endif
 332
300333#ifndef NDEBUG
301334String FontPlatformData::description() const
302335{

Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzFace.cpp

 1/*
 2 * Copyright (c) 2012 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 "HarfBuzzFace.h"
 33
 34#include "FontPlatformData.h"
 35#include "hb.h"
 36#include <wtf/HashMap.h>
 37
 38namespace WebCore {
 39
 40// Though we have FontCache class, which provides the cache mechanism for
 41// WebKit's font objects, we also need additional caching layer for HarfBuzz
 42// to reduce the memory consumption because hb_face_t should be associated with
 43// underling font data (e.g. CTFontRef, FTFace).
 44typedef pair<hb_face_t*, unsigned> FaceCacheEntry;
 45typedef HashMap<uint64_t, FaceCacheEntry, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t> > HarfBuzzFaceCache;
 46
 47static HarfBuzzFaceCache* harfbuzzFaceCache()
 48{
 49 DEFINE_STATIC_LOCAL(HarfBuzzFaceCache, s_harfbuzzFaceCache, ());
 50 return &s_harfbuzzFaceCache;
 51}
 52
 53HarfBuzzFace::HarfBuzzFace(FontPlatformData* platformData, uint64_t uniqueID)
 54 : m_platformData(platformData)
 55 , m_uniqueID(uniqueID)
 56{
 57 HarfBuzzFaceCache::iterator result = harfbuzzFaceCache()->find(m_uniqueID);
 58 if (result == harfbuzzFaceCache()->end()) {
 59 m_face = createFace();
 60 ASSERT(m_face);
 61 harfbuzzFaceCache()->set(m_uniqueID, FaceCacheEntry(m_face, 1));
 62 } else {
 63 ++(result.get()->second.second);
 64 m_face = result.get()->second.first;
 65 }
 66}
 67
 68HarfBuzzFace::~HarfBuzzFace()
 69{
 70 HarfBuzzFaceCache::iterator result = harfbuzzFaceCache()->find(m_uniqueID);
 71 ASSERT(result != harfbuzzFaceCache()->end());
 72 ASSERT(result.get()->second.second > 0);
 73 --(result.get()->second.second);
 74 if (!(result.get()->second.second)) {
 75 hb_face_destroy(result.get()->second.first);
 76 harfbuzzFaceCache()->remove(m_uniqueID);
 77 }
 78}
 79
 80} // namespace WebCore

Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzFace.h

 1/*
 2 * Copyright (c) 2012 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#ifndef HarfBuzzFace_h
 32#define HarfBuzzFace_h
 33
 34#include <wtf/PassRefPtr.h>
 35#include <wtf/RefCounted.h>
 36#include <wtf/RefPtr.h>
 37
 38struct _hb_face_t;
 39typedef _hb_face_t hb_face_t;
 40struct _hb_font_t;
 41typedef _hb_font_t hb_font_t;
 42
 43namespace WebCore {
 44
 45class FontPlatformData;
 46
 47class HarfBuzzFace : public RefCounted<HarfBuzzFace> {
 48public:
 49 static PassRefPtr<HarfBuzzFace> create(FontPlatformData* platformData, uint64_t uniqueID)
 50 {
 51 return adoptRef(new HarfBuzzFace(platformData, uniqueID));
 52 }
 53 ~HarfBuzzFace();
 54
 55 hb_font_t* createFont();
 56
 57private:
 58 HarfBuzzFace(FontPlatformData*, uint64_t);
 59
 60 hb_face_t* createFace();
 61
 62 FontPlatformData* m_platformData;
 63 uint64_t m_uniqueID;
 64 hb_face_t* m_face;
 65};
 66
 67}
 68
 69#endif // HarfBuzzFace_h

Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzFaceCoreText.cpp

 1/*
 2 * Copyright (c) 2012 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 "HarfBuzzFace.h"
 33
 34#include "CoreText/CoreText.h"
 35#include "FontPlatformData.h"
 36#include "HarfBuzzShaper.h"
 37#include "SimpleFontData.h"
 38
 39#include "hb.h"
 40
 41namespace WebCore {
 42
 43static hb_position_t floatToHarfBuzzPosition(CGFloat value)
 44{
 45 return static_cast<hb_position_t>(value * (1 << 16));
 46}
 47
 48static hb_bool_t getGlyph(hb_font_t* hbFont, void* fontData, hb_codepoint_t unicode, hb_codepoint_t variationSelector, hb_codepoint_t* glyph, void* userData)
 49{
 50 CTFontRef ctFont = reinterpret_cast<FontPlatformData*>(fontData)->ctFont();
 51 UniChar characters[4];
 52 CGGlyph cgGlyphs[4];
 53 size_t length = 0;
 54 U16_APPEND_UNSAFE(characters, length, unicode);
 55 if (!CTFontGetGlyphsForCharacters(ctFont, characters, cgGlyphs, length))
 56 return false;
 57 *glyph = cgGlyphs[0];
 58 return true;
 59}
 60
 61static hb_position_t getGlyphHorizontalAdvance(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, void* userData)
 62{
 63 CTFontRef ctFont = reinterpret_cast<FontPlatformData*>(fontData)->ctFont();
 64 CGGlyph cgGlyph = glyph;
 65 CGFloat advance = CTFontGetAdvancesForGlyphs(ctFont, kCTFontHorizontalOrientation, &cgGlyph, 0, 1);
 66 return floatToHarfBuzzPosition(advance);
 67}
 68
 69static hb_bool_t getGlyphHorizontalOrigin(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, hb_position_t* x, hb_position_t* y, void* userData)
 70{
 71 return true;
 72}
 73
 74static hb_bool_t getGlyphExtents(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, hb_glyph_extents_t* extents, void* userData)
 75{
 76 CTFontRef ctFont = reinterpret_cast<FontPlatformData*>(fontData)->ctFont();
 77 CGRect cgRect;
 78 CGGlyph cgGlyph = glyph;
 79 if (CTFontGetBoundingRectsForGlyphs(ctFont, kCTFontDefaultOrientation, &cgGlyph, &cgRect, 1) == CGRectNull)
 80 return false;
 81 extents->x_bearing = floatToHarfBuzzPosition(cgRect.origin.x);
 82 extents->y_bearing = -floatToHarfBuzzPosition(cgRect.origin.y);
 83 extents->width = floatToHarfBuzzPosition(cgRect.size.width);
 84 extents->height = floatToHarfBuzzPosition(cgRect.size.height);
 85 return true;
 86}
 87
 88static hb_font_funcs_t* harfbuzzCoreTextGetFontFuncs()
 89{
 90 static hb_font_funcs_t* harfbuzzCoreTextFontFuncs = 0;
 91
 92 if (!harfbuzzCoreTextFontFuncs) {
 93 harfbuzzCoreTextFontFuncs = hb_font_funcs_create();
 94 hb_font_funcs_set_glyph_func(harfbuzzCoreTextFontFuncs, getGlyph, 0, 0);
 95 hb_font_funcs_set_glyph_h_advance_func(harfbuzzCoreTextFontFuncs, getGlyphHorizontalAdvance, 0, 0);
 96 hb_font_funcs_set_glyph_h_origin_func(harfbuzzCoreTextFontFuncs, getGlyphHorizontalOrigin, 0, 0);
 97 hb_font_funcs_set_glyph_extents_func(harfbuzzCoreTextFontFuncs, getGlyphExtents, 0, 0);
 98 hb_font_funcs_make_immutable(harfbuzzCoreTextFontFuncs);
 99 }
 100 return harfbuzzCoreTextFontFuncs;
 101}
 102
 103static void releaseTableData(void* userData)
 104{
 105 CFDataRef cfData = reinterpret_cast<CFDataRef>(userData);
 106 CFRelease(cfData);
 107}
 108
 109static hb_blob_t* harfbuzzCoreTextGetTable(hb_face_t* face, hb_tag_t tag, void* userData)
 110{
 111 FontPlatformData* platformData = reinterpret_cast<FontPlatformData*>(userData);
 112 CTFontRef ctFont = platformData->ctFont();
 113 CFDataRef cfData = CTFontCopyTable(ctFont, tag, kCTFontTableOptionNoOptions);
 114 if (!cfData)
 115 return 0;
 116
 117 const char* data = reinterpret_cast<const char*>(CFDataGetBytePtr(cfData));
 118 const size_t length = CFDataGetLength(cfData);
 119 if (!data || !length)
 120 return 0;
 121 return hb_blob_create(data, length, HB_MEMORY_MODE_READONLY, reinterpret_cast<void*>(const_cast<__CFData*>(cfData)), releaseTableData);
 122}
 123
 124hb_face_t* HarfBuzzFace::createFace()
 125{
 126 hb_face_t* face = hb_face_create_for_tables(harfbuzzCoreTextGetTable, m_platformData, 0);
 127 ASSERT(face);
 128 return face;
 129}
 130
 131hb_font_t* HarfBuzzFace::createFont()
 132{
 133 hb_font_t* font = hb_font_create(m_face);
 134 hb_font_set_funcs(font, harfbuzzCoreTextGetFontFuncs(), m_platformData, 0);
 135 const float size = m_platformData->m_size;
 136 hb_font_set_ppem(font, size, size);
 137 const int scale = (1 << 16) * static_cast<int>(size);
 138 hb_font_set_scale(font, scale, scale);
 139 hb_font_make_immutable(font);
 140 return font;
 141}
 142
 143GlyphBufferAdvance HarfBuzzShaper::createGlyphBufferAdvance(float width, float height)
 144{
 145 return CGSizeMake(width, height);
 146}
 147
 148} // namespace WebCore

Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp

 1/*
 2 * Copyright (c) 2012 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 "HarfBuzzShaper.h"
 33
 34#include "Font.h"
 35#include "SurrogatePairAwareTextIterator.h"
 36#include "TextRun.h"
 37#include "hb-icu.h"
 38#include <unicode/normlzr.h>
 39#include <unicode/uchar.h>
 40#include <wtf/MathExtras.h>
 41#include <wtf/Vector.h>
 42#include <wtf/unicode/Unicode.h>
 43
 44namespace WebCore {
 45
 46static inline float harfbuzzPositionToFloat(hb_position_t value)
 47{
 48 return static_cast<float>(value) / (1 << 16);
 49}
 50
 51HarfBuzzShaper::HarfBuzzRun::HarfBuzzRun(unsigned numCharacters, TextDirection direction, hb_buffer_t* harfbuzzBuffer)
 52 : m_numCharacters(numCharacters)
 53 , m_direction(direction)
 54{
 55 m_numGlyphs = hb_buffer_get_length(harfbuzzBuffer);
 56 m_glyphs.resize(m_numGlyphs);
 57 m_advances.resize(m_numGlyphs);
 58 m_offsets.resize(m_numGlyphs);
 59 m_glyphToCharacterIndex.resize(m_numGlyphs);
 60 m_logClusters.resize(m_numCharacters);
 61
 62 hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(harfbuzzBuffer, 0);
 63 for (unsigned i = 0; i < m_numGlyphs; ++i)
 64 m_glyphToCharacterIndex[i] = infos[i].cluster;
 65
 66 // Fill logical clusters
 67 unsigned index = 0;
 68 while (index < m_numGlyphs) {
 69 unsigned nextIndex = index + 1;
 70 while (nextIndex < m_numGlyphs && infos[index].cluster == infos[nextIndex].cluster)
 71 ++nextIndex;
 72 if (rtl()) {
 73 int nextCluster = nextIndex < m_numGlyphs ? infos[nextIndex].cluster : -1;
 74 for (int j = infos[index].cluster; j > nextCluster; --j)
 75 m_logClusters[j] = index;
 76 } else {
 77 unsigned nextCluster = nextIndex < m_numGlyphs ? infos[nextIndex].cluster : m_numCharacters;
 78 for (unsigned j = infos[index].cluster; j < nextCluster; ++j)
 79 m_logClusters[j] = index;
 80 }
 81 index = nextIndex;
 82 }
 83}
 84
 85void HarfBuzzShaper::HarfBuzzRun::setGlyphAndPositions(unsigned index, uint16_t glyphId, float x, float y, float advance)
 86{
 87 m_glyphs[index] = glyphId;
 88 m_offsets[index].set(x, y);
 89 m_advances[index] = advance;
 90}
 91
 92int HarfBuzzShaper::HarfBuzzRun::characterIndexForXPosition(int targetX)
 93{
 94 ASSERT(static_cast<unsigned>(targetX) <= m_width);
 95 int currentX = 0;
 96 float prevAdvance = 0;
 97 for (unsigned i = 0; i < m_numGlyphs; ++i) {
 98 float currentAdvance = m_advances[i] / 2.0;
 99 int nextX = currentX + roundf(prevAdvance + currentAdvance);
 100 if (currentX <= targetX && targetX <= nextX)
 101 return m_glyphToCharacterIndex[i] + (rtl() ? 1 : 0);
 102 currentX = nextX;
 103 prevAdvance = currentAdvance;
 104 }
 105
 106 return rtl() ? 0 : m_numCharacters;
 107}
 108
 109int HarfBuzzShaper::HarfBuzzRun::xPositionForOffset(unsigned offset)
 110{
 111 ASSERT(offset < m_numCharacters);
 112 unsigned glyphIndex = m_logClusters[offset];
 113 ASSERT(glyphIndex < m_numGlyphs);
 114 float position = m_offsets[glyphIndex].x();
 115 if (rtl())
 116 position += m_advances[glyphIndex];
 117 return roundf(position);
 118}
 119
 120HarfBuzzShaper::HarfBuzzShaper(const Font* font, const TextRun& run)
 121 : HarfBuzzShaperBase(font, run)
 122 , m_startIndexOfCurrentRun(0)
 123 , m_numCharactersOfCurrentRun(0)
 124 , m_harfbuzzBuffer(0)
 125{
 126 setNormalizedBuffer();
 127 setFontFeatures();
 128}
 129
 130HarfBuzzShaper::~HarfBuzzShaper()
 131{
 132 if (m_harfbuzzBuffer)
 133 hb_buffer_destroy(m_harfbuzzBuffer);
 134}
 135
 136void HarfBuzzShaper::setFontFeatures()
 137{
 138 FontFeatureSettings* settings = m_font->fontDescription().featureSettings();
 139 if (!settings)
 140 return;
 141
 142 unsigned numFeatures = settings->size();
 143 m_features.resize(numFeatures);
 144 for (unsigned i = 0; i < numFeatures; ++i) {
 145 const UChar* tag = settings->at(i).tag().characters();
 146 m_features[i].tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]);
 147 m_features[i].value = settings->at(i).value();
 148 m_features[i].start = 0;
 149 m_features[i].end = static_cast<unsigned>(-1);
 150 }
 151}
 152
 153bool HarfBuzzShaper::shape(GlyphBuffer* glyphBuffer)
 154{
 155 m_totalWidth = 0;
 156 while (setupHarfBuzzRun()) {
 157 if (!shapeHarfBuzzRun())
 158 return false;
 159 setGlyphPositionsForHarfBuzzRun(glyphBuffer);
 160 }
 161
 162 if (!m_harfbuzzRuns.size())
 163 return false;
 164
 165 return true;
 166}
 167
 168bool HarfBuzzShaper::setupHarfBuzzRun()
 169{
 170 m_startIndexOfCurrentRun += m_numCharactersOfCurrentRun;
 171
 172 // Iterate through the text to take the largest range that stays within
 173 // a single font.
 174 int endOfRunIndex = m_normalizedBufferLength - m_startIndexOfCurrentRun;
 175 SurrogatePairAwareTextIterator iterator(m_normalizedBuffer.get() + m_startIndexOfCurrentRun, 0, endOfRunIndex, endOfRunIndex);
 176 UChar32 character;
 177 unsigned clusterLength = 0;
 178 if (!iterator.consume(character, clusterLength))
 179 return false;
 180
 181 m_currentFontData = m_font->glyphDataForCharacter(character, false).fontData;
 182 UErrorCode errorCode = U_ZERO_ERROR;
 183 UScriptCode currentScript = uscript_getScript(character, &errorCode);
 184 if (U_FAILURE(errorCode))
 185 return false;
 186 if (currentScript == USCRIPT_INHERITED)
 187 currentScript = USCRIPT_COMMON;
 188 for (iterator.advance(clusterLength); iterator.consume(character, clusterLength); iterator.advance(clusterLength)) {
 189 const SimpleFontData* nextFontData = m_font->glyphDataForCharacter(character, false).fontData;
 190 if (nextFontData != m_currentFontData)
 191 break;
 192 UScriptCode nextScript = uscript_getScript(character, &errorCode);
 193 if (U_FAILURE(errorCode))
 194 return false;
 195 if (currentScript == nextScript || nextScript == USCRIPT_INHERITED || nextScript == USCRIPT_COMMON)
 196 continue;
 197 if (currentScript == USCRIPT_COMMON)
 198 currentScript = nextScript;
 199 else
 200 break;
 201 }
 202 m_numCharactersOfCurrentRun = iterator.currentCharacter();
 203
 204 if (!m_harfbuzzBuffer) {
 205 m_harfbuzzBuffer = hb_buffer_create();
 206 hb_buffer_set_unicode_funcs(m_harfbuzzBuffer, hb_icu_get_unicode_funcs());
 207 } else
 208 hb_buffer_reset(m_harfbuzzBuffer);
 209 hb_buffer_set_script(m_harfbuzzBuffer, hb_icu_script_to_script(currentScript));
 210
 211 // WebKit always sets direction to LTR during width calculation.
 212 // We only set direction when direction is explicitly set to RTL so that
 213 // preventng wrong width calculation.
 214 if (m_run.rtl())
 215 hb_buffer_set_direction(m_harfbuzzBuffer, HB_DIRECTION_RTL);
 216
 217 // Determine whether this run needs to be converted to small caps.
 218 // nextScriptRun() will always send us a run of the same case, because a
 219 // case change while in small-caps mode always results in different
 220 // FontData, so we only need to check the first character's case.
 221 if (m_font->isSmallCaps() && u_islower(m_normalizedBuffer[m_startIndexOfCurrentRun])) {
 222 String upperText = String(m_normalizedBuffer.get() + m_startIndexOfCurrentRun, m_numCharactersOfCurrentRun);
 223 upperText.makeUpper();
 224 m_currentFontData = m_font->glyphDataForCharacter(upperText[0], false, SmallCapsVariant).fontData;
 225 hb_buffer_add_utf16(m_harfbuzzBuffer, upperText.characters(), m_numCharactersOfCurrentRun, 0, m_numCharactersOfCurrentRun);
 226 } else
 227 hb_buffer_add_utf16(m_harfbuzzBuffer, m_normalizedBuffer.get() + m_startIndexOfCurrentRun, m_numCharactersOfCurrentRun, 0, m_numCharactersOfCurrentRun);
 228
 229 return true;
 230}
 231
 232bool HarfBuzzShaper::shapeHarfBuzzRun()
 233{
 234 FontPlatformData* platformData = const_cast<FontPlatformData*>(&m_currentFontData->platformData());
 235 HarfBuzzFace* face = platformData->harfbuzzFace();
 236 if (!face)
 237 return false;
 238 hb_font_t* harfbuzzFont = face->createFont();
 239 hb_shape(harfbuzzFont, m_harfbuzzBuffer, m_features.size() > 0 ? m_features.data() : 0, m_features.size());
 240 hb_font_destroy(harfbuzzFont);
 241 m_harfbuzzRuns.append(HarfBuzzRun::create(m_numCharactersOfCurrentRun, m_run.direction(), m_harfbuzzBuffer));
 242 return true;
 243}
 244
 245void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(GlyphBuffer* glyphBuffer)
 246{
 247 hb_glyph_info_t* glyphInfos = hb_buffer_get_glyph_infos(m_harfbuzzBuffer, 0);
 248 hb_glyph_position_t* glyphPositions = hb_buffer_get_glyph_positions(m_harfbuzzBuffer, 0);
 249 HarfBuzzRun* currentRun = m_harfbuzzRuns.last().get();
 250
 251 unsigned numGlyphs = currentRun->numGlyphs();
 252 float totalAdvance = 0;
 253 float nextOffsetX = harfbuzzPositionToFloat(glyphPositions[0].x_offset);
 254 float nextOffsetY = -harfbuzzPositionToFloat(glyphPositions[0].y_offset);
 255 // HarfBuzz returns the shaping result in visual order. We need not to flip them for RTL.
 256 for (size_t i = 0; i < numGlyphs; ++i) {
 257 bool runEnd = i + 1 == numGlyphs;
 258 uint16_t glyph = glyphInfos[i].codepoint;
 259 float offsetX = nextOffsetX;
 260 float offsetY = nextOffsetY;
 261 float advance = harfbuzzPositionToFloat(glyphPositions[i].x_advance);
 262 nextOffsetX = runEnd ? 0 : harfbuzzPositionToFloat(glyphPositions[i + 1].x_offset);
 263 nextOffsetY = runEnd ? 0 : -harfbuzzPositionToFloat(glyphPositions[i + 1].y_offset);
 264
 265 unsigned currentCharacterIndex = m_startIndexOfCurrentRun + glyphInfos[i].cluster;
 266 bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1].cluster;
 267 float spacing = isClusterEnd ? m_letterSpacing : 0;
 268
 269 if (isClusterEnd && isWordEnd(currentCharacterIndex))
 270 spacing += determineWordBreakSpacing();
 271
 272 if (m_currentFontData->isZeroWidthSpaceGlyph(glyph)) {
 273 currentRun->setGlyphAndPositions(i, glyph, 0, 0, 0);
 274 if (glyphBuffer)
 275 glyphBuffer->add(glyph, m_currentFontData, createGlyphBufferAdvance(0, 0));
 276 continue;
 277 }
 278
 279 advance += spacing;
 280 currentRun->setGlyphAndPositions(i, glyph, totalAdvance + offsetX, offsetY, advance);
 281 if (glyphBuffer) {
 282 float glyphAdvanceX = advance + nextOffsetX - offsetX;
 283 float glyphAdvanceY = nextOffsetY - offsetY;
 284 glyphBuffer->add(glyph, m_currentFontData, createGlyphBufferAdvance(glyphAdvanceX, glyphAdvanceY));
 285 }
 286
 287 totalAdvance += advance;
 288 }
 289 currentRun->setWidth(totalAdvance > 0.0 ? totalAdvance : 0.0);
 290 m_totalWidth += currentRun->width();
 291}
 292
 293int HarfBuzzShaper::offsetForPosition(float targetX)
 294{
 295 int charactersSoFar = 0;
 296 int currentX = 0;
 297
 298 if (m_run.rtl()) {
 299 charactersSoFar = m_normalizedBufferLength;
 300 for (int i = m_harfbuzzRuns.size() - 1; i >= 0; --i) {
 301 charactersSoFar -= m_harfbuzzRuns[i]->numCharacters();
 302 int nextX = currentX + m_harfbuzzRuns[i]->width();
 303 if (currentX <= targetX && targetX <= nextX) {
 304 // The x value in question is within this script run.
 305 const unsigned index = m_harfbuzzRuns[i]->characterIndexForXPosition(targetX - currentX);
 306 return charactersSoFar + index;
 307 }
 308 currentX = nextX;
 309 }
 310 } else {
 311 for (unsigned i = 0; i < m_harfbuzzRuns.size(); ++i) {
 312 int nextX = currentX + m_harfbuzzRuns[i]->width();
 313 if (currentX <= targetX && targetX <= nextX) {
 314 const unsigned index = m_harfbuzzRuns[i]->characterIndexForXPosition(targetX - currentX);
 315 return charactersSoFar + index;
 316 }
 317 charactersSoFar += m_harfbuzzRuns[i]->numCharacters();
 318 currentX = nextX;
 319 }
 320 }
 321
 322 return charactersSoFar;
 323}
 324
 325FloatRect HarfBuzzShaper::selectionRect(const FloatPoint& point, int height, int from, int to)
 326{
 327 int fromX = -1, toX = -1;
 328 int currentX = 0;
 329 // Iterate through the script runs in logical order, searching for the run covering the positions of interest.
 330 for (unsigned i = 0; i < m_harfbuzzRuns.size(); ++i) {
 331 int numCharacters = m_harfbuzzRuns[i]->numCharacters();
 332 if (fromX == -1 && from >= 0 && from < numCharacters)
 333 fromX = m_harfbuzzRuns[i]->xPositionForOffset(from) + currentX;
 334 else
 335 from -= numCharacters;
 336
 337 if (toX == -1 && to >= 0 && to < numCharacters)
 338 toX = m_harfbuzzRuns[i]->xPositionForOffset(to) + currentX;
 339 else
 340 to -= numCharacters;
 341
 342 if (fromX != -1 && toX != -1)
 343 break;
 344 currentX += m_harfbuzzRuns[i]->width();
 345 }
 346
 347 // The position in question might be just after the text.
 348 if (fromX == -1)
 349 fromX = 0;
 350 if (toX == -1)
 351 toX = m_run.rtl() ? 0 : m_totalWidth;
 352
 353 ASSERT(fromX != -1 && toX != -1);
 354
 355 if (fromX < toX)
 356 return FloatRect(point.x() + fromX, point.y(), toX - fromX, height);
 357 return FloatRect(point.x() + toX, point.y(), fromX - toX, height);
 358}
 359
 360} // namespace WebCore

Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.h

 1/*
 2 * Copyright (C) 2012 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#ifndef HarfBuzzShaper_h
 32#define HarfBuzzShaper_h
 33
 34#include "FloatPoint.h"
 35#include "GlyphBuffer.h"
 36#include "HarfBuzzShaperBase.h"
 37#include "TextRun.h"
 38#include "hb.h"
 39#include <wtf/HashSet.h>
 40#include <wtf/OwnPtr.h>
 41#include <wtf/PassOwnPtr.h>
 42#include <wtf/Vector.h>
 43
 44namespace WebCore {
 45
 46class Font;
 47class SimpleFontData;
 48
 49class HarfBuzzShaper : public HarfBuzzShaperBase {
 50public:
 51 HarfBuzzShaper(const Font*, const TextRun&);
 52 virtual ~HarfBuzzShaper();
 53
 54 bool shape(GlyphBuffer* = 0);
 55 float totalWidth() { return m_totalWidth; }
 56 int offsetForPosition(float targetX);
 57 FloatRect selectionRect(const FloatPoint&, int height, int from, int to);
 58
 59private:
 60 class HarfBuzzRun {
 61 public:
 62 static PassOwnPtr<HarfBuzzRun> create(unsigned numCharacters, TextDirection direction, hb_buffer_t* buffer)
 63 {
 64 return adoptPtr(new HarfBuzzRun(numCharacters, direction, buffer));
 65 }
 66
 67 void setGlyphAndPositions(unsigned index, uint16_t glyphId, float x, float y, float);
 68 void setWidth(float width) { m_width = width; }
 69
 70 int characterIndexForXPosition(int targetX);
 71 int xPositionForOffset(unsigned offset);
 72
 73 unsigned numCharacters() const { return m_numCharacters; }
 74 unsigned numGlyphs() const { return m_numGlyphs; }
 75 float width() { return m_width; }
 76
 77 private:
 78 HarfBuzzRun(unsigned numCharacters, TextDirection, hb_buffer_t*);
 79 bool rtl() { return m_direction == RTL; }
 80
 81 size_t m_numCharacters;
 82 unsigned m_numGlyphs;
 83 TextDirection m_direction;
 84 Vector<uint16_t, 256> m_glyphs;
 85 Vector<float, 256> m_advances;
 86 Vector<FloatPoint, 256> m_offsets;
 87 Vector<uint16_t, 256> m_logClusters;
 88 Vector<uint16_t, 256> m_glyphToCharacterIndex;
 89 float m_width;
 90 };
 91
 92 void setFontFeatures();
 93
 94 bool setupHarfBuzzRun();
 95 bool shapeHarfBuzzRun();
 96 void setGlyphPositionsForHarfBuzzRun(GlyphBuffer*);
 97
 98 GlyphBufferAdvance createGlyphBufferAdvance(float, float);
 99
 100 Vector<hb_feature_t, 4> m_features;
 101 unsigned m_startIndexOfCurrentRun;
 102 unsigned m_numCharactersOfCurrentRun;
 103 const SimpleFontData* m_currentFontData;
 104 hb_buffer_t* m_harfbuzzBuffer;
 105 Vector<OwnPtr<HarfBuzzRun>, 16> m_harfbuzzRuns;
 106
 107 float m_totalWidth;
 108};
 109
 110} // namespace WebCore
 111
 112#endif // HarfBuzzShaper_h

Source/WebCore/platform/graphics/mac/FontComplexTextMac.cpp

3434#include "TextRun.h"
3535#include <wtf/MathExtras.h>
3636
 37#if PLATFORM(CHROMIUM)
 38#include "HarfBuzzShaper.h"
 39#endif
 40
3741using namespace std;
3842
3943namespace WebCore {
4044
 45#if PLATFORM(CHROMIUM)
 46static bool preferHarfBuzz(const Font* font)
 47{
 48 const FontDescription& description = font->fontDescription();
 49 return description.featureSettings() && description.featureSettings()->size() > 0;
 50}
 51#endif
 52
4153FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h,
4254 int from, int to) const
4355{
 56#if PLATFORM(CHROMIUM)
 57 if (preferHarfBuzz(this)) {
 58 HarfBuzzShaper shaper(this, run);
 59 if (shaper.shape())
 60 return shaper.selectionRect(point, h, from, to);
 61 }
 62#endif
4463 ComplexTextController controller(this, run);
4564 controller.advance(from);
4665 float beforeWidth = controller.runWidthSoFar();

@@float Font::getGlyphsAndAdvancesForComplexText(const TextRun& run, int from, int
82101
83102void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
84103{
 104#if PLATFORM(CHROMIUM)
 105 if (preferHarfBuzz(this)) {
 106 GlyphBuffer glyphBuffer;
 107 HarfBuzzShaper shaper(this, run);
 108 if (shaper.shape(&glyphBuffer)) {
 109 drawGlyphBuffer(context, run, glyphBuffer, point);
 110 return;
 111 }
 112 }
 113#endif
85114 // This glyph buffer holds our glyphs + advances + font data for each glyph.
86115 GlyphBuffer glyphBuffer;
87116

@@void Font::drawEmphasisMarksForComplexText(GraphicsContext* context, const TextR
109138
110139float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
111140{
 141#if PLATFORM(CHROMIUM)
 142 if (preferHarfBuzz(this)) {
 143 HarfBuzzShaper shaper(this, run);
 144 if (shaper.shape())
 145 return shaper.totalWidth();
 146 }
 147#endif
112148 ComplexTextController controller(this, run, true, fallbackFonts);
113149 if (glyphOverflow) {
114150 glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));

@@float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
121157
122158int Font::offsetForPositionForComplexText(const TextRun& run, float x, bool includePartialGlyphs) const
123159{
 160#if PLATFORM(CHROMIUM)
 161 if (preferHarfBuzz(this)) {
 162 HarfBuzzShaper shaper(this, run);
 163 if (shaper.shape())
 164 return shaper.offsetForPosition(x);
 165 }
 166#endif
124167 ComplexTextController controller(this, run);
125168 return controller.offsetForPosition(x, includePartialGlyphs);
126169}

LayoutTests/ChangeLog

 12012-06-04 Kenichi Ishibashi <bashi@chromium.org>
 2
 3 [Chromium] Implement font shaping with font-feature-settings on Mac
 4 https://bugs.webkit.org/show_bug.cgi?id=69826
 5
 6 Reviewed by Tony Chang.
 7
 8 Added the expectation for sss3/font-feature-settings-rendering.html.
 9
 10 * platform/chromium-mac/css3/font-feature-settings-rendering-expected.png: Added.
 11 * platform/chromium-mac/css3/font-feature-settings-rendering-expected.txt: Added.
 12 * platform/chromium/TestExpectations: Removed css3/font-feature-settings-rendering.html.
 13
1142012-06-04 Sheriff Bot <webkit.review.bot@gmail.com>
215
316 Unreviewed, rolling out r119393.

LayoutTests/platform/chromium-mac/css3/font-feature-settings-rendering-expected.png


Added

ecfa965be6c30ea0c8fb7ad3bd5d0d22

LayoutTests/platform/chromium-mac/css3/font-feature-settings-rendering-expected.txt

 1layer at (0,0) size 800x600
 2 RenderView at (0,0) size 800x600
 3layer at (0,0) size 800x600
 4 RenderBlock {HTML} at (0,0) size 800x600
 5 RenderBody {BODY} at (8,8) size 784x584
 6 RenderBlock {P} at (0,0) size 784x36
 7 RenderText {#text} at (0,0) size 783x36
 8 text run at (0,0) width 243: "Test for font-feature-settings property. "
 9 text run at (243,0) width 540: "The first word of the following three words should be displayed like \"WebKit\", while"
 10 text run at (0,18) width 267: "others should be displayed as black boxes."
 11 RenderBlock {DIV} at (0,52) size 784x17
 12 RenderText {#text} at (0,0) size 31x16
 13 text run at (0,0) width 31: "WebKit"
 14 RenderBlock {DIV} at (0,69) size 784x17
 15 RenderText {#text} at (0,0) size 96x16
 16 text run at (0,0) width 96: "WebKit"
 17 RenderBlock {DIV} at (0,86) size 784x17
 18 RenderText {#text} at (0,0) size 96x16
 19 text run at (0,0) width 96: "WebKit"

LayoutTests/platform/chromium/TestExpectations

@@BUGCR97716 : fast/clip/overflow-border-radius-combinations.html = IMAGE
28712871// Caused by r92618
28722872BUGWK65874 : fast/js/preventExtensions.html = TEXT
28732873
2874 BUGWK63796 MAC : css3/font-feature-settings-rendering.html = MISSING FAIL
2875 
28762874BUGWK66417 WIN LINUX : fast/text/midword-break-before-surrogate-pair-2.html = IMAGE+TEXT
28772875
28782876BUGWK66419 : http/tests/misc/authentication-redirect-1/authentication-sent-to-redirect-cross-origin.html = TEXT