Modified: trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.h (211293 => 211294)
--- trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.h 2017-01-27 19:37:05 UTC (rev 211293)
+++ trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.h 2017-01-27 20:28:11 UTC (rev 211294)
@@ -58,8 +58,11 @@
public:
ComplexTextController(const FontCascade&, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const Font*>* fallbackFonts = 0, bool forTextEmphasis = false);
+ class ComplexTextRun;
+ WEBCORE_EXPORT ComplexTextController(const FontCascade&, const TextRun&, Vector<Ref<ComplexTextRun>>&);
+
// Advance and emit glyphs up to the specified character.
- void advance(unsigned to, GlyphBuffer* = nullptr, GlyphIterationStyle = IncludePartialGlyphs, HashSet<const Font*>* fallbackFonts = nullptr);
+ WEBCORE_EXPORT void advance(unsigned to, GlyphBuffer* = nullptr, GlyphIterationStyle = IncludePartialGlyphs, HashSet<const Font*>* fallbackFonts = nullptr);
// Compute the character offset for a given x coordinate.
unsigned offsetForPosition(float x, bool includePartialGlyphs);
@@ -75,8 +78,7 @@
float maxGlyphBoundingBoxY() const { return m_maxGlyphBoundingBoxY; }
float leadingExpansion() const { return m_leadingExpansion; }
-
-private:
+
class ComplexTextRun : public RefCounted<ComplexTextRun> {
public:
static Ref<ComplexTextRun> create(CTRunRef ctRun, const Font& font, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange)
@@ -89,6 +91,11 @@
return adoptRef(*new ComplexTextRun(font, characters, stringLocation, stringLength, ltr));
}
+ static Ref<ComplexTextRun> createForTesting(Vector<CGSize> advances, Vector<CGPoint> origins, Vector<CGGlyph> glyphs, Vector<CFIndex> stringIndices, CGSize initialAdvance, const Font& font, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange, bool ltr)
+ {
+ return adoptRef(*new ComplexTextRun(advances, origins, glyphs, stringIndices, initialAdvance, font, characters, stringLocation, stringLength, runRange, ltr));
+ }
+
unsigned glyphCount() const { return m_glyphCount; }
const Font& font() const { return m_font; }
const UChar* characters() const { return m_characters; }
@@ -120,6 +127,7 @@
private:
ComplexTextRun(CTRunRef, const Font&, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange);
ComplexTextRun(const Font&, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr);
+ WEBCORE_EXPORT ComplexTextRun(Vector<CGSize> advances, Vector<CGPoint> origins, Vector<CGGlyph> glyphs, Vector<CFIndex> stringIndices, CGSize initialAdvance, const Font&, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange, bool ltr);
Vector<CGSize, 64> m_baseAdvancesVector;
Vector<CGPoint, 64> m_glyphOrigins;
@@ -138,8 +146,10 @@
unsigned m_glyphCount;
unsigned m_stringLocation;
bool m_isLTR;
- bool m_isMonotonic;
+ bool m_isMonotonic { true };
};
+private:
+ void finishConstruction();
static unsigned stringBegin(const ComplexTextRun& run) { return run.stringLocation() + run.indexBegin(); }
static unsigned stringEnd(const ComplexTextRun& run) { return run.stringLocation() + run.indexEnd(); }
Modified: trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm (211293 => 211294)
--- trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm 2017-01-27 19:37:05 UTC (rev 211293)
+++ trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm 2017-01-27 20:28:11 UTC (rev 211294)
@@ -111,14 +111,14 @@
, m_font(font)
, m_characters(characters)
, m_stringLength(stringLength)
+ , m_coreTextIndices(CTRunGetStringIndicesPtr(ctRun))
+ , m_glyphs(CTRunGetGlyphsPtr(ctRun))
, m_indexBegin(runRange.location)
, m_indexEnd(runRange.location + runRange.length)
+ , m_glyphCount(CTRunGetGlyphCount(ctRun))
, m_stringLocation(stringLocation)
, m_isLTR(!(CTRunGetStatus(ctRun) & kCTRunStatusRightToLeft))
- , m_isMonotonic(true)
{
- m_glyphCount = CTRunGetGlyphCount(ctRun);
- m_coreTextIndices = CTRunGetStringIndicesPtr(ctRun);
if (!m_coreTextIndices) {
m_coreTextIndicesVector.grow(m_glyphCount);
CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), m_coreTextIndicesVector.data());
@@ -125,7 +125,6 @@
m_coreTextIndices = m_coreTextIndicesVector.data();
}
- m_glyphs = CTRunGetGlyphsPtr(ctRun);
if (!m_glyphs) {
m_glyphsVector.grow(m_glyphCount);
CTRunGetGlyphs(ctRun, CFRangeMake(0, 0), m_glyphsVector.data());
@@ -161,7 +160,6 @@
, m_indexEnd(stringLength)
, m_stringLocation(stringLocation)
, m_isLTR(ltr)
- , m_isMonotonic(true)
{
m_coreTextIndicesVector.reserveInitialCapacity(m_stringLength);
unsigned r = 0;
@@ -184,6 +182,27 @@
m_baseAdvances = m_baseAdvancesVector.data();
}
+
+ComplexTextController::ComplexTextRun::ComplexTextRun(Vector<CGSize> advances, Vector<CGPoint> origins, Vector<CGGlyph> glyphs, Vector<CFIndex> stringIndices, CGSize initialAdvance, const Font& font, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange, bool ltr)
+ : m_baseAdvancesVector(advances)
+ , m_glyphOrigins(origins)
+ , m_glyphsVector(glyphs)
+ , m_coreTextIndicesVector(stringIndices)
+ , m_initialAdvance(initialAdvance)
+ , m_font(font)
+ , m_characters(characters)
+ , m_stringLength(stringLength)
+ , m_coreTextIndices(m_coreTextIndicesVector.data())
+ , m_glyphs(m_glyphsVector.data())
+ , m_baseAdvances(m_baseAdvancesVector.data())
+ , m_indexBegin(runRange.location)
+ , m_indexEnd(runRange.location + runRange.length)
+ , m_glyphCount(glyphs.size())
+ , m_stringLocation(stringLocation)
+ , m_isLTR(ltr)
+{
+}
+
struct ProviderInfo {
const UChar* cp;
unsigned length;
Added: trunk/Tools/TestWebKitAPI/Tests/WebCore/ComplexTextController.cpp (0 => 211294)
--- trunk/Tools/TestWebKitAPI/Tests/WebCore/ComplexTextController.cpp (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebCore/ComplexTextController.cpp 2017-01-27 20:28:11 UTC (rev 211294)
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <_javascript_Core/InitializeThreading.h>
+#include <WebCore/ComplexTextController.h>
+#include <WebCore/FontCascade.h>
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
+
+using namespace WebCore;
+
+namespace TestWebKitAPI {
+
+class ComplexTextControllerTest : public testing::Test {
+public:
+ virtual void SetUp()
+ {
+ WTF::initializeMainThread();
+ JSC::initializeThreading();
+ RunLoop::initializeMainRunLoop();
+ }
+};
+
+TEST_F(ComplexTextControllerTest, DISABLED_InitialAdvanceWithLeftRunInRTL)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("Times");
+ description.setComputedSize(80);
+ FontCascade font(description);
+ font.update(nullptr);
+ auto spaceWidth = font.primaryFont().spaceWidth();
+
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+ Vector<CGSize> advances = { CGSizeZero, CGSizeMake(21.640625, 0.0), CGSizeMake(42.3046875, 0.0), CGSizeMake(55.8984375, 0.0), CGSizeMake(22.34375, 0.0) };
+ Vector<CGPoint> origins = { CGPointMake(-15.15625, 18.046875), CGPointZero, CGPointZero, CGPointZero, CGPointZero };
+#else
+ Vector<CGSize> advances = { CGSizeMake(15.15625, -18.046875), CGSizeMake(21.640625, 0.0), CGSizeMake(42.3046875, 0.0), CGSizeMake(55.8984375, 0.0), CGSizeMake(22.34375, 0.0) };
+ Vector<CGPoint> origins = { };
+#endif
+
+ CGSize initialAdvance = CGSizeMake(-15.15625, 18.046875);
+
+ UChar characters[] = { 0x644, 0x637, 0x641, 0x627, 0x64b, 0x20 };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength));
+ Ref<ComplexTextController::ComplexTextRun> run1 = ComplexTextController::ComplexTextRun::createForTesting({ CGSizeMake(21.875, 0) }, { CGPointZero }, { 5 }, { 5 }, CGSizeZero, font.primaryFont(), characters, 0, charactersLength, CFRangeMake(5, 1), false);
+ Ref<ComplexTextController::ComplexTextRun> run2 = ComplexTextController::ComplexTextRun::createForTesting(advances, origins, { 193, 377, 447, 431, 458 }, { 4, 3, 2, 1, 0 }, initialAdvance, font.primaryFont(), characters, 0, charactersLength, CFRangeMake(0, 5), false);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run1));
+ runs.append(WTFMove(run2));
+ ComplexTextController controller(font, textRun, runs);
+
+ CGFloat totalWidth = 0;
+ for (size_t i = 1; i < advances.size(); ++i)
+ totalWidth += advances[i].width;
+ EXPECT_NEAR(controller.totalWidth(), spaceWidth + totalWidth, 0.0001);
+ GlyphBuffer glyphBuffer;
+ controller.advance(0, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(1, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), advances[4].width, 0.0001);
+ controller.advance(6, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), spaceWidth + totalWidth, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().width(), 0, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().height(), 0, 0.0001);
+ EXPECT_EQ(glyphBuffer.size(), 6U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width(), advances[4].width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(1).width(), advances[3].width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(2).width(), advances[2].width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(3).width(), advances[1].width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(4).width(), -initialAdvance.width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(5).width(), spaceWidth + initialAdvance.width, 0.0001);
+}
+
+TEST_F(ComplexTextControllerTest, DISABLED_InitialAdvanceInRTL)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("Times");
+ description.setComputedSize(80);
+ FontCascade font(description);
+ font.update(nullptr);
+
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+ Vector<CGSize> advances = { CGSizeZero, CGSizeMake(21.640625, 0.0), CGSizeMake(42.3046875, 0.0), CGSizeMake(55.8984375, 0.0), CGSizeMake(22.34375, 0.0) };
+ Vector<CGPoint> origins = { CGPointMake(-15.15625, 18.046875), CGPointZero, CGPointZero, CGPointZero, CGPointZero };
+#else
+ Vector<CGSize> advances = { CGSizeMake(15.15625, -18.046875), CGSizeMake(21.640625, 0.0), CGSizeMake(42.3046875, 0.0), CGSizeMake(55.8984375, 0.0), CGSizeMake(22.34375, 0.0) };
+ Vector<CGPoint> origins = { };
+#endif
+
+ CGSize initialAdvance = CGSizeMake(-15.15625, 18.046875);
+
+ UChar characters[] = { 0x644, 0x637, 0x641, 0x627, 0x64b };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength));
+ Ref<ComplexTextController::ComplexTextRun> run = ComplexTextController::ComplexTextRun::createForTesting(advances, origins, { 193, 377, 447, 431, 458 }, { 4, 3, 2, 1, 0 }, initialAdvance, font.primaryFont(), characters, 0, charactersLength, CFRangeMake(0, 5), false);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run));
+ ComplexTextController controller(font, textRun, runs);
+
+ CGFloat totalWidth = 0;
+ for (size_t i = 1; i < advances.size(); ++i)
+ totalWidth += advances[i].width;
+ EXPECT_NEAR(controller.totalWidth(), totalWidth, 0.0001);
+ GlyphBuffer glyphBuffer;
+ controller.advance(0, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(1, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), advances[4].width, 0.0001);
+ controller.advance(5, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), totalWidth, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().width(), initialAdvance.width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().height(), initialAdvance.height, 0.0001);
+ EXPECT_EQ(glyphBuffer.size(), 5U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width(), advances[4].width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(1).width(), advances[3].width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(2).width(), advances[2].width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(3).width(), advances[1].width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(4).width(), -initialAdvance.width, 0.0001);
+}
+
+TEST_F(ComplexTextControllerTest, DISABLED_InitialAdvanceWithLeftRunInLTR)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("LucidaGrande");
+ description.setComputedSize(80);
+ FontCascade font(description);
+ font.update(nullptr);
+ auto spaceWidth = font.primaryFont().spaceWidth();
+
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+ Vector<CGSize> advances = { CGSizeMake(76.347656, 0.000000), CGSizeMake(0.000000, 0.000000) };
+ Vector<CGPoint> origins = { CGPointZero, CGPointMake(-23.281250, -8.398438) };
+#else
+ Vector<CGSize> advances = { CGSizeMake(53.066406, -8.398438), CGSizeMake(23.281250, 8.398438) };
+ Vector<CGPoint> origins = { };
+#endif
+
+ CGSize initialAdvance = CGSizeMake(28.144531, 0);
+
+ UChar characters[] = { 0x20, 0x61, 0x20e3 };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength));
+ Ref<ComplexTextController::ComplexTextRun> run1 = ComplexTextController::ComplexTextRun::createForTesting({ CGSizeMake(spaceWidth, 0) }, { CGPointZero }, { 5 }, { 0 }, CGSizeZero, font.primaryFont(), characters, 0, charactersLength, CFRangeMake(0, 1), true);
+ Ref<ComplexTextController::ComplexTextRun> run2 = ComplexTextController::ComplexTextRun::createForTesting(advances, origins, { 68, 1471 }, { 1, 2 }, initialAdvance, font.primaryFont(), characters, 0, charactersLength, CFRangeMake(1, 2), true);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run1));
+ runs.append(WTFMove(run2));
+ ComplexTextController controller(font, textRun, runs);
+
+ EXPECT_NEAR(controller.totalWidth(), spaceWidth + 76.347656 + initialAdvance.width, 0.0001);
+ GlyphBuffer glyphBuffer;
+ controller.advance(0, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(1, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), spaceWidth, 0.0001);
+ controller.advance(2, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), spaceWidth + advances[0].width + initialAdvance.width, 0.0001);
+ controller.advance(3, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), spaceWidth + 76.347656 + initialAdvance.width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().width(), 0, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().height(), 0, 0.0001);
+ EXPECT_EQ(glyphBuffer.size(), 3U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width(), spaceWidth + initialAdvance.width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(1).width(), 53.066406, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(2).width(), 23.281250, 0.0001);
+}
+
+TEST_F(ComplexTextControllerTest, DISABLED_InitialAdvanceInLTR)
+{
+ FontCascadeDescription description;
+ description.setOneFamily("LucidaGrande");
+ description.setComputedSize(80);
+ FontCascade font(description);
+ font.update(nullptr);
+
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+ Vector<CGSize> advances = { CGSizeMake(76.347656, 0.000000), CGSizeMake(0.000000, 0.000000) };
+ Vector<CGPoint> origins = { CGPointZero, CGPointMake(-23.281250, -8.398438) };
+#else
+ Vector<CGSize> advances = { CGSizeMake(53.066406, -8.398438), CGSizeMake(23.281250, 8.398438) };
+ Vector<CGPoint> origins = { };
+#endif
+
+ CGSize initialAdvance = CGSizeMake(28.144531, 0);
+
+ UChar characters[] = { 0x61, 0x20e3 };
+ size_t charactersLength = WTF_ARRAY_LENGTH(characters);
+ TextRun textRun(StringView(characters, charactersLength));
+ Ref<ComplexTextController::ComplexTextRun> run = ComplexTextController::ComplexTextRun::createForTesting(advances, origins, { 68, 1471 }, { 0, 1 }, initialAdvance, font.primaryFont(), characters, 0, charactersLength, CFRangeMake(0, 2), true);
+ Vector<Ref<ComplexTextController::ComplexTextRun>> runs;
+ runs.append(WTFMove(run));
+ ComplexTextController controller(font, textRun, runs);
+
+ EXPECT_NEAR(controller.totalWidth(), 76.347656 + initialAdvance.width, 0.0001);
+ GlyphBuffer glyphBuffer;
+ controller.advance(0, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 0, 0.0001);
+ controller.advance(1, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), advances[0].width + initialAdvance.width, 0.0001);
+ controller.advance(2, &glyphBuffer);
+ EXPECT_NEAR(controller.runWidthSoFar(), 76.347656 + initialAdvance.width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().width(), initialAdvance.width, 0.0001);
+ EXPECT_NEAR(glyphBuffer.initialAdvance().height(), initialAdvance.height, 0.0001);
+ EXPECT_EQ(glyphBuffer.size(), 2U);
+ EXPECT_NEAR(glyphBuffer.advanceAt(0).width(), 53.066406, 0.0001);
+ EXPECT_NEAR(glyphBuffer.advanceAt(1).width(), 23.281250, 0.0001);
+}
+
+}