summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/harfbuzz/ng
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/harfbuzz/ng')
-rw-r--r--Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp83
-rw-r--r--Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h9
-rw-r--r--Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp6
-rw-r--r--Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp9
-rw-r--r--Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp60
-rw-r--r--Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp59
6 files changed, 149 insertions, 77 deletions
diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp
index 7dd048b3b..50dbd81bd 100644
--- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp
+++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.cpp
@@ -32,17 +32,44 @@
#include "HarfBuzzNGFace.h"
#include "FontPlatformData.h"
+#include "hb-ot.h"
#include "hb.h"
-#include <wtf/HashMap.h>
namespace WebCore {
+const hb_tag_t HarfBuzzNGFace::vertTag = HB_TAG('v', 'e', 'r', 't');
+const hb_tag_t HarfBuzzNGFace::vrt2Tag = HB_TAG('v', 'r', 't', '2');
+
// Though we have FontCache class, which provides the cache mechanism for
// WebKit's font objects, we also need additional caching layer for HarfBuzz
// to reduce the memory consumption because hb_face_t should be associated with
// underling font data (e.g. CTFontRef, FTFace).
-typedef pair<hb_face_t*, unsigned> FaceCacheEntry;
-typedef HashMap<uint64_t, FaceCacheEntry, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t> > HarfBuzzNGFaceCache;
+
+class FaceCacheEntry : public RefCounted<FaceCacheEntry> {
+public:
+ static PassRefPtr<FaceCacheEntry> create(hb_face_t* face)
+ {
+ ASSERT(face);
+ return adoptRef(new FaceCacheEntry(face));
+ }
+ ~FaceCacheEntry()
+ {
+ hb_face_destroy(m_face);
+ }
+
+ hb_face_t* face() { return m_face; }
+ HashMap<uint32_t, uint16_t>* glyphCache() { return &m_glyphCache; }
+
+private:
+ explicit FaceCacheEntry(hb_face_t* face)
+ : m_face(face)
+ { }
+
+ hb_face_t* m_face;
+ HashMap<uint32_t, uint16_t> m_glyphCache;
+};
+
+typedef HashMap<uint64_t, RefPtr<FaceCacheEntry>, WTF::IntHash<uint64_t>, WTF::UnsignedWithZeroKeyHashTraits<uint64_t> > HarfBuzzNGFaceCache;
static HarfBuzzNGFaceCache* harfbuzzFaceCache()
{
@@ -53,28 +80,52 @@ static HarfBuzzNGFaceCache* harfbuzzFaceCache()
HarfBuzzNGFace::HarfBuzzNGFace(FontPlatformData* platformData, uint64_t uniqueID)
: m_platformData(platformData)
, m_uniqueID(uniqueID)
+ , m_scriptForVerticalText(HB_SCRIPT_INVALID)
{
- HarfBuzzNGFaceCache::iterator result = harfbuzzFaceCache()->find(m_uniqueID);
- if (result == harfbuzzFaceCache()->end()) {
- m_face = createFace();
- ASSERT(m_face);
- harfbuzzFaceCache()->set(m_uniqueID, FaceCacheEntry(m_face, 1));
- } else {
- ++(result.get()->second.second);
- m_face = result.get()->second.first;
- }
+ HarfBuzzNGFaceCache::AddResult result = harfbuzzFaceCache()->add(m_uniqueID, 0);
+ if (result.isNewEntry)
+ result.iterator->value = FaceCacheEntry::create(createFace());
+ result.iterator->value->ref();
+ m_face = result.iterator->value->face();
+ m_glyphCacheForFaceCacheEntry = result.iterator->value->glyphCache();
}
HarfBuzzNGFace::~HarfBuzzNGFace()
{
HarfBuzzNGFaceCache::iterator result = harfbuzzFaceCache()->find(m_uniqueID);
ASSERT(result != harfbuzzFaceCache()->end());
- ASSERT(result.get()->second.second > 0);
- --(result.get()->second.second);
- if (!(result.get()->second.second)) {
- hb_face_destroy(result.get()->second.first);
+ ASSERT(result.get()->value->refCount() > 1);
+ result.get()->value->deref();
+ if (result.get()->value->refCount() == 1)
harfbuzzFaceCache()->remove(m_uniqueID);
+}
+
+static hb_script_t findScriptForVerticalGlyphSubstitution(hb_face_t* face)
+{
+ static const unsigned maxCount = 32;
+
+ unsigned scriptCount = maxCount;
+ hb_tag_t scriptTags[maxCount];
+ hb_ot_layout_table_get_script_tags(face, HB_OT_TAG_GSUB, 0, &scriptCount, scriptTags);
+ for (unsigned scriptIndex = 0; scriptIndex < scriptCount; ++scriptIndex) {
+ unsigned languageCount = maxCount;
+ hb_tag_t languageTags[maxCount];
+ hb_ot_layout_script_get_language_tags(face, HB_OT_TAG_GSUB, scriptIndex, 0, &languageCount, languageTags);
+ for (unsigned languageIndex = 0; languageIndex < languageCount; ++languageIndex) {
+ unsigned featureIndex;
+ if (hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scriptIndex, languageIndex, HarfBuzzNGFace::vertTag, &featureIndex)
+ || hb_ot_layout_language_find_feature(face, HB_OT_TAG_GSUB, scriptIndex, languageIndex, HarfBuzzNGFace::vrt2Tag, &featureIndex))
+ return hb_ot_tag_to_script(scriptTags[scriptIndex]);
+ }
}
+ return HB_SCRIPT_INVALID;
+}
+
+void HarfBuzzNGFace::setScriptForVerticalGlyphSubstitution(hb_buffer_t* buffer)
+{
+ if (m_scriptForVerticalText == HB_SCRIPT_INVALID)
+ m_scriptForVerticalText = findScriptForVerticalGlyphSubstitution(m_face);
+ hb_buffer_set_script(buffer, m_scriptForVerticalText);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h
index cbc8f8ed4..360daf9cf 100644
--- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h
+++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFace.h
@@ -33,6 +33,7 @@
#include <hb.h>
+#include <wtf/HashMap.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
@@ -43,6 +44,9 @@ class FontPlatformData;
class HarfBuzzNGFace : public RefCounted<HarfBuzzNGFace> {
public:
+ static const hb_tag_t vertTag;
+ static const hb_tag_t vrt2Tag;
+
static PassRefPtr<HarfBuzzNGFace> create(FontPlatformData* platformData, uint64_t uniqueID)
{
return adoptRef(new HarfBuzzNGFace(platformData, uniqueID));
@@ -51,6 +55,8 @@ public:
hb_font_t* createFont();
+ void setScriptForVerticalGlyphSubstitution(hb_buffer_t*);
+
private:
HarfBuzzNGFace(FontPlatformData*, uint64_t);
@@ -59,6 +65,9 @@ private:
FontPlatformData* m_platformData;
uint64_t m_uniqueID;
hb_face_t* m_face;
+ WTF::HashMap<uint32_t, uint16_t>* m_glyphCacheForFaceCacheEntry;
+
+ hb_script_t m_scriptForVerticalText;
};
}
diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp
index 52fca7baf..2db3d2780 100644
--- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp
+++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCairo.cpp
@@ -155,9 +155,7 @@ static hb_font_funcs_t* harfbuzzCairoTextGetFontFuncs()
static hb_blob_t* harfbuzzCairoGetTable(hb_face_t*, hb_tag_t tag, void* userData)
{
- FontPlatformData* font = reinterpret_cast<FontPlatformData*>(userData);
-
- cairo_scaled_font_t* scaledFont = font->scaledFont();
+ cairo_scaled_font_t* scaledFont = reinterpret_cast<cairo_scaled_font_t*>(userData);
if (!scaledFont)
return 0;
@@ -186,7 +184,7 @@ static hb_blob_t* harfbuzzCairoGetTable(hb_face_t*, hb_tag_t tag, void* userData
hb_face_t* HarfBuzzNGFace::createFace()
{
- hb_face_t* face = hb_face_create_for_tables(harfbuzzCairoGetTable, m_platformData, 0);
+ hb_face_t* face = hb_face_create_for_tables(harfbuzzCairoGetTable, m_platformData->scaledFont(), 0);
ASSERT(face);
return face;
}
diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp
index f2baba73f..e4c65cd41 100644
--- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp
+++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceCoreText.cpp
@@ -108,10 +108,7 @@ static void releaseTableData(void* userData)
static hb_blob_t* harfbuzzCoreTextGetTable(hb_face_t* face, hb_tag_t tag, void* userData)
{
- FontPlatformData* platformData = reinterpret_cast<FontPlatformData*>(userData);
- // It seems that CTFontCopyTable of MacOSX10.5 sdk doesn't work for
- // OpenType layout tables(GDEF, GSUB, GPOS). Use CGFontCopyTableForTag instead.
- CGFontRef cgFont = platformData->cgFont();
+ CGFontRef cgFont = reinterpret_cast<CGFontRef>(userData);
CFDataRef cfData = CGFontCopyTableForTag(cgFont, tag);
if (!cfData)
return 0;
@@ -125,7 +122,9 @@ static hb_blob_t* harfbuzzCoreTextGetTable(hb_face_t* face, hb_tag_t tag, void*
hb_face_t* HarfBuzzNGFace::createFace()
{
- hb_face_t* face = hb_face_create_for_tables(harfbuzzCoreTextGetTable, m_platformData, 0);
+ // It seems that CTFontCopyTable of MacOSX10.5 sdk doesn't work for
+ // OpenType layout tables(GDEF, GSUB, GPOS). Use CGFontCopyTableForTag instead.
+ hb_face_t* face = hb_face_create_for_tables(harfbuzzCoreTextGetTable, m_platformData->cgFont(), 0);
ASSERT(face);
return face;
}
diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp
index 53acb292c..5d39efa73 100644
--- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp
+++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzNGFaceSkia.cpp
@@ -43,12 +43,21 @@
#include "SkUtils.h"
#include "hb.h"
+#include <wtf/HashMap.h>
namespace WebCore {
// Our implementation of the callbacks which Harfbuzz requires by using Skia
// calls. See the Harfbuzz source for references about what these callbacks do.
+struct HarfBuzzFontData {
+ HarfBuzzFontData(WTF::HashMap<uint32_t, uint16_t>* glyphCacheForFaceCacheEntry)
+ : m_glyphCacheForFaceCacheEntry(glyphCacheForFaceCacheEntry)
+ { }
+ SkPaint m_paint;
+ WTF::HashMap<uint32_t, uint16_t>* m_glyphCacheForFaceCacheEntry;
+};
+
static hb_position_t SkiaScalarToHarfbuzzPosition(SkScalar value)
{
return SkScalarToFixed(value);
@@ -56,8 +65,7 @@ static hb_position_t SkiaScalarToHarfbuzzPosition(SkScalar value)
static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint, hb_position_t* width, hb_glyph_extents_t* extents)
{
- if (codepoint > 0xFFFF)
- return;
+ ASSERT(codepoint <= 0xFFFF);
paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
SkScalar skWidth;
@@ -78,23 +86,27 @@ static void SkiaGetGlyphWidthAndExtents(SkPaint* paint, hb_codepoint_t codepoint
static hb_bool_t harfbuzzGetGlyph(hb_font_t* hbFont, void* fontData, hb_codepoint_t unicode, hb_codepoint_t variationSelector, hb_codepoint_t* glyph, void* userData)
{
- SkPaint* paint = reinterpret_cast<SkPaint*>(fontData);
-
- paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
- uint16_t text[4];
- size_t length = SkUTF16_FromUnichar(unicode, text);
- uint16_t glyph16;
- paint->textToGlyphs(text, length, &glyph16);
- *glyph = glyph16;
+ HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData);
+
+ WTF::HashMap<uint32_t, uint16_t>::AddResult result = hbFontData->m_glyphCacheForFaceCacheEntry->add(unicode, 0);
+ if (result.isNewEntry) {
+ SkPaint* paint = &hbFontData->m_paint;
+ paint->setTextEncoding(SkPaint::kUTF32_TextEncoding);
+ uint16_t glyph16;
+ paint->textToGlyphs(&unicode, sizeof(hb_codepoint_t), &glyph16);
+ result.iterator->value = glyph16;
+ *glyph = glyph16;
+ }
+ *glyph = result.iterator->value;
return !!*glyph;
}
static hb_position_t harfbuzzGetGlyphHorizontalAdvance(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, void* userData)
{
- SkPaint* paint = reinterpret_cast<SkPaint*>(fontData);
+ HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData);
hb_position_t advance = 0;
- SkiaGetGlyphWidthAndExtents(paint, glyph, &advance, 0);
+ SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, &advance, 0);
return advance;
}
@@ -107,9 +119,9 @@ static hb_bool_t harfbuzzGetGlyphHorizontalOrigin(hb_font_t* hbFont, void* fontD
static hb_bool_t harfbuzzGetGlyphExtents(hb_font_t* hbFont, void* fontData, hb_codepoint_t glyph, hb_glyph_extents_t* extents, void* userData)
{
- SkPaint* paint = reinterpret_cast<SkPaint*>(fontData);
+ HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(fontData);
- SkiaGetGlyphWidthAndExtents(paint, glyph, 0, extents);
+ SkiaGetGlyphWidthAndExtents(&hbFontData->m_paint, glyph, 0, extents);
return true;
}
@@ -132,16 +144,16 @@ static hb_font_funcs_t* harfbuzzSkiaGetFontFuncs()
static hb_blob_t* harfbuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* userData)
{
- FontPlatformData* font = reinterpret_cast<FontPlatformData*>(userData);
+ SkFontID uniqueID = static_cast<SkFontID>(reinterpret_cast<uint64_t>(userData));
- const size_t tableSize = SkFontHost::GetTableSize(font->uniqueID(), tag);
+ const size_t tableSize = SkFontHost::GetTableSize(uniqueID, tag);
if (!tableSize)
return 0;
char* buffer = reinterpret_cast<char*>(fastMalloc(tableSize));
if (!buffer)
return 0;
- size_t actualSize = SkFontHost::GetTableData(font->uniqueID(), tag, 0, tableSize, buffer);
+ size_t actualSize = SkFontHost::GetTableData(uniqueID, tag, 0, tableSize, buffer);
if (tableSize != actualSize) {
fastFree(buffer);
return 0;
@@ -151,25 +163,25 @@ static hb_blob_t* harfbuzzSkiaGetTable(hb_face_t* face, hb_tag_t tag, void* user
HB_MEMORY_MODE_WRITABLE, buffer, fastFree);
}
-static void destroyPaint(void* userData)
+static void destroyHarfBuzzFontData(void* userData)
{
- SkPaint* paint = reinterpret_cast<SkPaint*>(userData);
- delete paint;
+ HarfBuzzFontData* hbFontData = reinterpret_cast<HarfBuzzFontData*>(userData);
+ delete hbFontData;
}
hb_face_t* HarfBuzzNGFace::createFace()
{
- hb_face_t* face = hb_face_create_for_tables(harfbuzzSkiaGetTable, m_platformData, 0);
+ hb_face_t* face = hb_face_create_for_tables(harfbuzzSkiaGetTable, reinterpret_cast<void*>(m_platformData->uniqueID()), 0);
ASSERT(face);
return face;
}
hb_font_t* HarfBuzzNGFace::createFont()
{
+ HarfBuzzFontData* hbFontData = new HarfBuzzFontData(m_glyphCacheForFaceCacheEntry);
+ m_platformData->setupPaint(&hbFontData->m_paint);
hb_font_t* font = hb_font_create(m_face);
- SkPaint* paint = new SkPaint;
- m_platformData->setupPaint(paint);
- hb_font_set_funcs(font, harfbuzzSkiaGetFontFuncs(), paint, destroyPaint);
+ hb_font_set_funcs(font, harfbuzzSkiaGetFontFuncs(), hbFontData, destroyHarfBuzzFontData);
float size = m_platformData->size();
int scale = SkiaScalarToHarfbuzzPosition(size);
hb_font_set_scale(font, scale, scale);
diff --git a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp
index 9e55fc411..796b37c95 100644
--- a/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp
+++ b/Source/WebCore/platform/graphics/harfbuzz/ng/HarfBuzzShaper.cpp
@@ -87,10 +87,6 @@ void HarfBuzzShaper::HarfBuzzRun::applyShapeResult(hb_buffer_t* harfbuzzBuffer)
m_advances.resize(m_numGlyphs);
m_glyphToCharacterIndexes.resize(m_numGlyphs);
m_offsets.resize(m_numGlyphs);
-
- hb_glyph_info_t* infos = hb_buffer_get_glyph_infos(harfbuzzBuffer, 0);
- for (unsigned i = 0; i < m_numGlyphs; ++i)
- m_glyphToCharacterIndexes[i] = infos[i].cluster;
}
void HarfBuzzShaper::HarfBuzzRun::setGlyphAndPositions(unsigned index, uint16_t glyphId, float advance, float offsetX, float offsetY)
@@ -204,18 +200,27 @@ void HarfBuzzShaper::setDrawRange(int from, int to)
void HarfBuzzShaper::setFontFeatures()
{
- FontFeatureSettings* settings = m_font->fontDescription().featureSettings();
+ const FontDescription& description = m_font->fontDescription();
+ if (description.orientation() == Vertical) {
+ static hb_feature_t vert = { HarfBuzzNGFace::vertTag, 1, 0, static_cast<unsigned>(-1) };
+ static hb_feature_t vrt2 = { HarfBuzzNGFace::vrt2Tag, 1, 0, static_cast<unsigned>(-1) };
+ m_features.append(vert);
+ m_features.append(vrt2);
+ }
+
+ FontFeatureSettings* settings = description.featureSettings();
if (!settings)
return;
unsigned numFeatures = settings->size();
- m_features.resize(numFeatures);
for (unsigned i = 0; i < numFeatures; ++i) {
+ hb_feature_t feature;
const UChar* tag = settings->at(i).tag().characters();
- m_features[i].tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]);
- m_features[i].value = settings->at(i).value();
- m_features[i].start = 0;
- m_features[i].end = static_cast<unsigned>(-1);
+ feature.tag = HB_TAG(tag[0], tag[1], tag[2], tag[3]);
+ feature.value = settings->at(i).value();
+ feature.start = 0;
+ feature.end = static_cast<unsigned>(-1);
+ m_features.append(feature);
}
}
@@ -240,20 +245,6 @@ FloatPoint HarfBuzzShaper::adjustStartPoint(const FloatPoint& point)
return point + m_startOffset;
}
-static const SimpleFontData* fontDataForCombiningCharacterSequence(const Font* font, const UChar* characters, size_t length)
-{
- UErrorCode error = U_ZERO_ERROR;
- Vector<UChar, 4> normalizedCharacters(length);
- int32_t normalizedLength = unorm_normalize(characters, length, UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], length, &error);
- // Should fallback if we have an error or no composition occurred.
- if (U_FAILURE(error) || (static_cast<size_t>(normalizedLength) == length))
- return 0;
- UChar32 normalizedCharacter;
- size_t index = 0;
- U16_NEXT(&normalizedCharacters[0], index, static_cast<size_t>(normalizedLength), normalizedCharacter);
- return font->glyphDataForCharacter(normalizedCharacter, false).fontData;
-}
-
bool HarfBuzzShaper::collectHarfBuzzRuns()
{
const UChar* normalizedBufferEnd = m_normalizedBuffer.get() + m_normalizedBufferLength;
@@ -278,6 +269,7 @@ bool HarfBuzzShaper::collectHarfBuzzRuns()
for (iterator.advance(clusterLength); iterator.consume(character, clusterLength); iterator.advance(clusterLength)) {
if (Font::treatAsZeroWidthSpace(character))
continue;
+
if (U_GET_GC_MASK(character) & U_GC_M_MASK) {
int markLength = clusterLength;
const UChar* markCharactersEnd = iterator.characters() + clusterLength;
@@ -290,11 +282,12 @@ bool HarfBuzzShaper::collectHarfBuzzRuns()
markLength += nextCharacterLength;
markCharactersEnd += nextCharacterLength;
}
- nextFontData = fontDataForCombiningCharacterSequence(m_font, currentCharacterPosition, markCharactersEnd - currentCharacterPosition);
- if (nextFontData)
+
+ if (currentFontData->canRenderCombiningCharacterSequence(currentCharacterPosition, markCharactersEnd - currentCharacterPosition)) {
clusterLength = markLength;
- else
- nextFontData = m_font->glyphDataForCharacter(character, false).fontData;
+ continue;
+ }
+ nextFontData = m_font->glyphDataForCharacter(character, false).fontData;
} else
nextFontData = m_font->glyphDataForCharacter(character, false).fontData;
@@ -305,6 +298,7 @@ bool HarfBuzzShaper::collectHarfBuzzRuns()
break;
if (nextScript == USCRIPT_INHERITED)
nextScript = currentScript;
+ currentCharacterPosition = iterator.characters();
}
unsigned numCharactersOfCurrentRun = iterator.currentCharacter() - startIndexOfCurrentRun;
m_harfbuzzRuns.append(HarfBuzzRun::create(currentFontData, startIndexOfCurrentRun, numCharactersOfCurrentRun, m_run.direction()));
@@ -340,7 +334,12 @@ bool HarfBuzzShaper::shapeHarfBuzzRuns()
HarfBuzzNGFace* face = platformData->harfbuzzFace();
if (!face)
return false;
+
+ if (m_font->fontDescription().orientation() == Vertical)
+ face->setScriptForVerticalGlyphSubstitution(harfbuzzBuffer.get());
+
HarfBuzzScopedPtr<hb_font_t> harfbuzzFont(face->createFont(), hb_font_destroy);
+
hb_shape(harfbuzzFont.get(), harfbuzzBuffer.get(), m_features.isEmpty() ? 0 : m_features.data(), m_features.size());
currentRun->applyShapeResult(harfbuzzBuffer.get());
@@ -361,6 +360,7 @@ void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb
hb_glyph_position_t* glyphPositions = hb_buffer_get_glyph_positions(harfbuzzBuffer, 0);
unsigned numGlyphs = currentRun->numGlyphs();
+ uint16_t* glyphToCharacterIndexes = currentRun->glyphToCharacterIndexes();
float totalAdvance = 0;
// HarfBuzz returns the shaping result in visual order. We need not to flip for RTL.
@@ -374,6 +374,9 @@ void HarfBuzzShaper::setGlyphPositionsForHarfBuzzRun(HarfBuzzRun* currentRun, hb
unsigned currentCharacterIndex = currentRun->startIndex() + glyphInfos[i].cluster;
bool isClusterEnd = runEnd || glyphInfos[i].cluster != glyphInfos[i + 1].cluster;
float spacing = 0;
+
+ glyphToCharacterIndexes[i] = glyphInfos[i].cluster;
+
if (isClusterEnd && !Font::treatAsZeroWidthSpace(m_normalizedBuffer[currentCharacterIndex]))
spacing += m_letterSpacing;