Title: [205373] trunk
Revision
205373
Author
mmaxfi...@apple.com
Date
2016-09-02 14:43:45 -0700 (Fri, 02 Sep 2016)

Log Message

[Cocoa] Distinguish between paint advances and base advances
https://bugs.webkit.org/show_bug.cgi?id=160892

Reviewed by Simon Fraser.

Source/WebCore:

This patch introduces the concept of a layout (or "base") advance which is distinct
from a painting advance. In extremely complicated scripts such as Urdu, it is common
for a glyph advance to be negative in the horizontal direction, and have large advances
in the vertical direction. In particular, in cursive scripts, the glyph placement is
only indirectly related to where the actual characters lie. Conceptually, these glyph
locations are correct for painting, but are not correct when performing width
measurements.

In many text engines, glyph shaping actually can be split into two phases: adjusting
advances, and then placing glyphs relative to those advances. The secondary glyph
placement step is much more context-sensitive than the first step. In addition, when
multiple glyphs combine to form a character, it is common for one glyph to own the
full base advance for the character, and for the other glyphs in the character to
have zero base advances. (Then, in the glyph placement phase, the other glyphs get
placed all around.)

Because of the context-insensitivity of the base advances, it is valuable to use
these for text measurement. Then, when we want to paint, we should add in the extra
origins. This dramatically improves the layout of complex fonts like Noto Nastaliq.

This patch migrates WebKit to use this two-phase shaping.

No new tests just yet, because I have to create a font which exercises the
advanced glyph placement support.

* platform/graphics/GlyphBuffer.h:
(WebCore::GlyphBufferAdvance::setHeight):
(WebCore::GlyphBufferAdvance::setWidth): Deleted.
* platform/graphics/TextRun.h:
(WebCore::TextRun::TextRun):
(WebCore::TextRun::shouldDisableLayoutSpecificAdvances):
(WebCore::TextRun::setShouldDisableLayoutSpecificAdvances):
(WebCore::TextRun::spacingDisabled): Deleted.
(WebCore::TextRun::setCharacterScanForCodePath): Deleted.
* platform/graphics/cocoa/FontCascadeCocoa.mm:
(WebCore::FontCascade::getGlyphsAndAdvancesForComplexText):
* platform/graphics/mac/ComplexTextController.cpp:
(WebCore::ComplexTextController::ComplexTextController):
(WebCore::ComplexTextController::offsetForPosition):
(WebCore::ComplexTextController::collectComplexTextRuns):
(WebCore::ComplexTextController::ComplexTextRun::setIsNonMonotonic):
(WebCore::ComplexTextController::runWidthSoFarFraction):
(WebCore::ComplexTextController::advance):
(WebCore::ComplexTextController::adjustGlyphsAndAdvances):
* platform/graphics/mac/ComplexTextController.h:
(WebCore::ComplexTextController::ComplexTextRun::create):
(WebCore::ComplexTextController::ComplexTextRun::baseAdvances):
(WebCore::ComplexTextController::ComplexTextRun::glyphOrigins):
(WebCore::ComplexTextController::useLayoutSpecificAdvances):
(WebCore::ComplexTextController::finalRoundingWidth): Deleted.
(WebCore::ComplexTextController::ComplexTextRun::advances): Deleted.
* platform/graphics/mac/ComplexTextControllerCoreText.mm:
(SOFT_LINK):
(WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun):
(WebCore::ComplexTextController::collectComplexTextRunsForCharacters):
* platform/spi/cocoa/CoreTextSPI.h:

LayoutTests:

Update tests. There are some expected (small) changes in metrics due to this patch.

* platform/mac-elcapitan/css2.1/t051202-c26-psudo-nest-00-c-expected.png: Copied from LayoutTests/platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.png.
* platform/mac-elcapitan/css2.1/t051202-c26-psudo-nest-00-c-expected.txt: Copied from LayoutTests/platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.txt.
* platform/mac-elcapitan/css2.1/t1508-c527-font-00-b-expected.png: Copied from LayoutTests/platform/mac/css2.1/t1508-c527-font-00-b-expected.png.
* platform/mac-elcapitan/css2.1/t1508-c527-font-00-b-expected.txt: Added.
* platform/mac-elcapitan/fast/inline/absolute-positioned-inline-in-centred-block-expected.png: Copied from LayoutTests/platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.png.
* platform/mac-elcapitan/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt: Copied from LayoutTests/platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt.
* platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.png:
* platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.txt:
* platform/mac/css2.1/t1508-c527-font-00-b-expected.png:
* platform/mac/css2.1/t1508-c527-font-00-b-expected.txt: Added.
* platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.png:
* platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (205372 => 205373)


--- trunk/LayoutTests/ChangeLog	2016-09-02 21:41:58 UTC (rev 205372)
+++ trunk/LayoutTests/ChangeLog	2016-09-02 21:43:45 UTC (rev 205373)
@@ -1,3 +1,25 @@
+2016-09-02  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [Cocoa] Distinguish between paint advances and base advances
+        https://bugs.webkit.org/show_bug.cgi?id=160892
+
+        Reviewed by Simon Fraser.
+
+        Update tests. There are some expected (small) changes in metrics due to this patch.
+
+        * platform/mac-elcapitan/css2.1/t051202-c26-psudo-nest-00-c-expected.png: Copied from LayoutTests/platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.png.
+        * platform/mac-elcapitan/css2.1/t051202-c26-psudo-nest-00-c-expected.txt: Copied from LayoutTests/platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.txt.
+        * platform/mac-elcapitan/css2.1/t1508-c527-font-00-b-expected.png: Copied from LayoutTests/platform/mac/css2.1/t1508-c527-font-00-b-expected.png.
+        * platform/mac-elcapitan/css2.1/t1508-c527-font-00-b-expected.txt: Added.
+        * platform/mac-elcapitan/fast/inline/absolute-positioned-inline-in-centred-block-expected.png: Copied from LayoutTests/platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.png.
+        * platform/mac-elcapitan/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt: Copied from LayoutTests/platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt.
+        * platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.png:
+        * platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.txt:
+        * platform/mac/css2.1/t1508-c527-font-00-b-expected.png:
+        * platform/mac/css2.1/t1508-c527-font-00-b-expected.txt: Added.
+        * platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.png:
+        * platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt:
+
 2016-09-02  Chris Dumez  <cdu...@apple.com>
 
         Unreviewed, roll out r205354 because it caused JSC test failures

Modified: trunk/LayoutTests/platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.png


(Binary files differ)

Modified: trunk/LayoutTests/platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.txt (205372 => 205373)


--- trunk/LayoutTests/platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.txt	2016-09-02 21:41:58 UTC (rev 205372)
+++ trunk/LayoutTests/platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.txt	2016-09-02 21:43:45 UTC (rev 205373)
@@ -56,13 +56,13 @@
         RenderInline {STRONG} at (0,0) size 111x18
           RenderText {#text} at (130,15) size 111x18
             text run at (130,15) width 111: "two characters"
-        RenderText {#text} at (240,15) size 452x18
-          text run at (240,15) width 121: " in this paragraph "
-          text run at (360,15) width 332: "(a double-quote mark and a capital 'T') should be "
-        RenderInline {STRONG} at (0,0) size 89x18
-          RenderText {#text} at (691,15) size 89x18
-            text run at (691,15) width 45: "200% "
-            text run at (735,15) width 45: "bigger"
+        RenderText {#text} at (240,15) size 451x18
+          text run at (240,15) width 120: " in this paragraph "
+          text run at (359,15) width 332: "(a double-quote mark and a capital 'T') should be "
+        RenderInline {STRONG} at (0,0) size 90x18
+          RenderText {#text} at (690,15) size 90x18
+            text run at (690,15) width 45: "200% "
+            text run at (734,15) width 46: "bigger"
         RenderText {#text} at (0,37) size 223x18
           text run at (0,37) width 223: "than the rest of the paragraph, and "
         RenderInline {STRONG} at (0,0) size 34x18

Modified: trunk/LayoutTests/platform/mac/css2.1/t1508-c527-font-00-b-expected.png


(Binary files differ)

Added: trunk/LayoutTests/platform/mac/css2.1/t1508-c527-font-00-b-expected.txt (0 => 205373)


--- trunk/LayoutTests/platform/mac/css2.1/t1508-c527-font-00-b-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac/css2.1/t1508-c527-font-00-b-expected.txt	2016-09-02 21:43:45 UTC (rev 205373)
@@ -0,0 +1,23 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x101
+  RenderBlock {HTML} at (0,0) size 800x101
+    RenderBody {BODY} at (8,13) size 784x75 [color=#000080]
+      RenderBlock {P} at (0,0) size 784x75
+        RenderText {#text} at (0,0) size 616x15
+          text run at (0,0) width 616: "This text should be 13px Helvetica in small-caps and italicized. There should be a small gap between each line. "
+        RenderInline {SPAN} at (0,0) size 781x75 [color=#C0C0C0]
+          RenderText {#text} at (615,0) size 781x75
+            text run at (615,0) width 166: "dummy text dummy text dummy"
+            text run at (0,15) width 195: "text dummy text dummy text dummy "
+            text run at (194,15) width 390: "text dummy text dummy text dummy text dummy text dummy text dummy "
+            text run at (583,15) width 192: "text dummy text dummy text dummy"
+            text run at (0,30) width 195: "text dummy text dummy text dummy "
+            text run at (194,30) width 390: "text dummy text dummy text dummy text dummy text dummy text dummy "
+            text run at (583,30) width 192: "text dummy text dummy text dummy"
+            text run at (0,45) width 195: "text dummy text dummy text dummy "
+            text run at (194,45) width 390: "text dummy text dummy text dummy text dummy text dummy text dummy "
+            text run at (583,45) width 192: "text dummy text dummy text dummy"
+            text run at (0,60) width 195: "text dummy text dummy text dummy "
+            text run at (194,60) width 349: "text dummy text dummy text dummy text dummy text dummy text"
+        RenderText {#text} at (0,0) size 0x0
Property changes on: trunk/LayoutTests/platform/mac/css2.1/t1508-c527-font-00-b-expected.txt
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Added: svn:keywords

+Author Date Id Rev URL \ No newline at end of property

Modified: trunk/LayoutTests/platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.png


(Binary files differ)

Modified: trunk/LayoutTests/platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt (205372 => 205373)


--- trunk/LayoutTests/platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt	2016-09-02 21:41:58 UTC (rev 205372)
+++ trunk/LayoutTests/platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt	2016-09-02 21:43:45 UTC (rev 205373)
@@ -6,5 +6,5 @@
       RenderBlock {DIV} at (0,0) size 784x0
 layer at (250,562) size 303x28
   RenderBlock (positioned) {FONT} at (250,562) size 303x28
-    RenderText {#text} at (0,0) size 303x28
-      text run at (0,0) width 303: "Hello World, And Stuff!"
+    RenderText {#text} at (0,0) size 302x28
+      text run at (0,0) width 302: "Hello World, And Stuff!"

Copied: trunk/LayoutTests/platform/mac-elcapitan/css2.1/t051202-c26-psudo-nest-00-c-expected.png (from rev 205372, trunk/LayoutTests/platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.png)


(Binary files differ)

Copied: trunk/LayoutTests/platform/mac-elcapitan/css2.1/t051202-c26-psudo-nest-00-c-expected.txt (from rev 205372, trunk/LayoutTests/platform/mac/css2.1/t051202-c26-psudo-nest-00-c-expected.txt) (0 => 205373)


--- trunk/LayoutTests/platform/mac-elcapitan/css2.1/t051202-c26-psudo-nest-00-c-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac-elcapitan/css2.1/t051202-c26-psudo-nest-00-c-expected.txt	2016-09-02 21:43:45 UTC (rev 205373)
@@ -0,0 +1,137 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x455
+  RenderBlock {HTML} at (0,0) size 800x455
+    RenderBody {BODY} at (8,16) size 784x431 [color=#0000FF]
+      RenderBlock {P} at (0,0) size 784x238
+        RenderInline (generated) at (0,0) size 88x166 [color=#00FFFF]
+          RenderText {#text} at (0,0) size 88x166
+            text run at (0,0) width 88: "T"
+        RenderText {#text} at (87,87) size 59x55
+          text run at (87,87) width 59: "he "
+        RenderInline {STRONG} at (0,0) size 205x55
+          RenderText {#text} at (145,87) size 205x55
+            text run at (145,87) width 205: "first letter"
+        RenderText {#text} at (349,87) size 780x97
+          text run at (349,87) width 431: " of this paragraph, and"
+          text run at (0,166) width 61: "only that "
+          text run at (60,166) width 98: "one, should be "
+        RenderInline {STRONG} at (0,0) size 88x18
+          RenderText {#text} at (157,166) size 88x18
+            text run at (157,166) width 88: "600% bigger"
+        RenderText {#text} at (244,166) size 527x18
+          text run at (244,166) width 138: " than the normal text "
+          text run at (381,166) width 390: "(300% bigger than the rest of first line of this paragraph) and"
+        RenderInline {STRONG} at (0,0) size 34x18
+          RenderText {#text} at (0,184) size 34x18
+            text run at (0,184) width 34: "aqua"
+        RenderText {#text} at (33,184) size 113x18
+          text run at (33,184) width 113: ", while the entire "
+        RenderInline {STRONG} at (0,0) size 57x18
+          RenderText {#text} at (145,184) size 57x18
+            text run at (145,184) width 57: "first line"
+        RenderText {#text} at (201,184) size 71x18
+          text run at (201,184) width 5: " "
+          text run at (205,184) width 67: "should be "
+        RenderInline {STRONG} at (0,0) size 89x18
+          RenderText {#text} at (271,184) size 89x18
+            text run at (271,184) width 89: "300% bigger"
+        RenderText {#text} at (359,184) size 113x18
+          text run at (359,184) width 113: " than normal and "
+        RenderInline {STRONG} at (0,0) size 25x18
+          RenderText {#text} at (471,184) size 25x18
+            text run at (471,184) width 25: "teal"
+        RenderText {#text} at (495,184) size 778x54
+          text run at (495,184) width 281: ". If this precise combination does not occur,"
+          text run at (0,202) width 421: "then the user agent has failed this test. Remember that in order to "
+          text run at (420,202) width 358: "ensure a complete test, the paragraph must be displayed"
+          text run at (0,220) width 57: "on more "
+          text run at (56,220) width 149: "than one line. (TEST1)"
+      RenderBlock {P} at (0,254) size 784x73
+        RenderInline (generated) at (0,0) size 33x37 [color=#00FFFF]
+          RenderText {#text} at (0,0) size 33x37
+            text run at (0,0) width 33: "\"T"
+        RenderText {#text} at (32,15) size 99x18
+          text run at (32,15) width 99: "est\": The first "
+        RenderInline {STRONG} at (0,0) size 111x18
+          RenderText {#text} at (130,15) size 111x18
+            text run at (130,15) width 111: "two characters"
+        RenderText {#text} at (240,15) size 452x18
+          text run at (240,15) width 121: " in this paragraph "
+          text run at (360,15) width 332: "(a double-quote mark and a capital 'T') should be "
+        RenderInline {STRONG} at (0,0) size 89x18
+          RenderText {#text} at (691,15) size 89x18
+            text run at (691,15) width 45: "200% "
+            text run at (735,15) width 45: "bigger"
+        RenderText {#text} at (0,37) size 223x18
+          text run at (0,37) width 223: "than the rest of the paragraph, and "
+        RenderInline {STRONG} at (0,0) size 34x18
+          RenderText {#text} at (222,37) size 34x18
+            text run at (222,37) width 34: "aqua"
+        RenderText {#text} at (255,37) size 151x18
+          text run at (255,37) width 151: ". In addition, the entire "
+        RenderInline {STRONG} at (0,0) size 58x18
+          RenderText {#text} at (405,37) size 58x18
+            text run at (405,37) width 33: "first "
+            text run at (437,37) width 26: "line"
+        RenderText {#text} at (462,37) size 98x18
+          text run at (462,37) width 98: " should be in a "
+        RenderInline {STRONG} at (0,0) size 163x18
+          RenderText {#text} at (559,37) size 163x18
+            text run at (559,37) width 138: "small-caps font and "
+            text run at (696,37) width 26: "teal"
+        RenderText {#text} at (721,37) size 738x36
+          text run at (721,37) width 5: "."
+          text run at (0,55) width 323: "Remember that in order to ensure a complete test, "
+          text run at (322,55) width 416: "the paragraph must be displayed on more than one line. (TEST2)"
+      RenderBlock {P} at (0,343) size 784x54
+        RenderInline (generated) at (0,0) size 10x18 [color=#00FFFF]
+          RenderText {#text} at (0,0) size 10x18
+            text run at (0,0) width 10: "T"
+        RenderText {#text} at (9,0) size 20x18
+          text run at (9,0) width 20: "he "
+        RenderInline {STRONG} at (0,0) size 69x18
+          RenderText {#text} at (28,0) size 69x18
+            text run at (28,0) width 69: "first letter"
+        RenderText {#text} at (96,0) size 306x18
+          text run at (96,0) width 209: " of this paragraph, and only that "
+          text run at (304,0) width 98: "one, should be "
+        RenderInline {STRONG} at (0,0) size 35x18
+          RenderText {#text} at (401,0) size 35x18
+            text run at (401,0) width 35: "aqua"
+        RenderText {#text} at (435,0) size 112x18
+          text run at (435,0) width 112: ", while the entire "
+        RenderInline {STRONG} at (0,0) size 58x18
+          RenderText {#text} at (546,0) size 58x18
+            text run at (546,0) width 58: "first line"
+        RenderText {#text} at (603,0) size 71x18
+          text run at (603,0) width 71: " should be "
+        RenderInline {STRONG} at (0,0) size 26x18
+          RenderText {#text} at (673,0) size 26x18
+            text run at (673,0) width 26: "teal"
+        RenderText {#text} at (698,0) size 770x54
+          text run at (698,0) width 23: ". If "
+          text run at (720,0) width 24: "this"
+          text run at (0,18) width 384: "precise combination does not occur, then the user agent has "
+          text run at (383,18) width 387: "failed this test. Remember that in order to ensure a complete"
+          text run at (0,36) width 31: "test, "
+          text run at (30,36) width 416: "the paragraph must be displayed on more than one line. (TEST3)"
+      RenderBlock {DIV} at (0,413) size 784x18
+        RenderText {#text} at (0,0) size 168x18
+          text run at (0,0) width 168: "You should see the words "
+        RenderInline {STRONG} at (0,0) size 68x18
+          RenderText {#text} at (167,0) size 68x18
+            text run at (167,0) width 68: "\"TEST1\""
+        RenderText {#text} at (234,0) size 9x18
+          text run at (234,0) width 9: ", "
+        RenderInline {STRONG} at (0,0) size 68x18
+          RenderText {#text} at (242,0) size 68x18
+            text run at (242,0) width 68: "\"TEST2\""
+        RenderText {#text} at (309,0) size 36x18
+          text run at (309,0) width 36: ", and "
+        RenderInline {STRONG} at (0,0) size 67x18
+          RenderText {#text} at (344,0) size 67x18
+            text run at (344,0) width 67: "\"TEST3\""
+        RenderText {#text} at (410,0) size 241x18
+          text run at (410,0) width 89: " at the end of "
+          text run at (498,0) width 153: "three paragraphs above."

Copied: trunk/LayoutTests/platform/mac-elcapitan/css2.1/t1508-c527-font-00-b-expected.png (from rev 205372, trunk/LayoutTests/platform/mac/css2.1/t1508-c527-font-00-b-expected.png)


(Binary files differ)

Added: trunk/LayoutTests/platform/mac-elcapitan/css2.1/t1508-c527-font-00-b-expected.txt (0 => 205373)


--- trunk/LayoutTests/platform/mac-elcapitan/css2.1/t1508-c527-font-00-b-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac-elcapitan/css2.1/t1508-c527-font-00-b-expected.txt	2016-09-02 21:43:45 UTC (rev 205373)
@@ -0,0 +1,23 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x101
+  RenderBlock {HTML} at (0,0) size 800x101
+    RenderBody {BODY} at (8,13) size 784x75 [color=#000080]
+      RenderBlock {P} at (0,0) size 784x75
+        RenderText {#text} at (0,0) size 617x15
+          text run at (0,0) width 617: "This text should be 13px Helvetica in small-caps and italicized. There should be a small gap between each line. "
+        RenderInline {SPAN} at (0,0) size 781x75 [color=#C0C0C0]
+          RenderText {#text} at (616,0) size 781x75
+            text run at (616,0) width 165: "dummy text dummy text dummy"
+            text run at (0,15) width 195: "text dummy text dummy text dummy "
+            text run at (194,15) width 390: "text dummy text dummy text dummy text dummy text dummy text dummy "
+            text run at (583,15) width 192: "text dummy text dummy text dummy"
+            text run at (0,30) width 195: "text dummy text dummy text dummy "
+            text run at (194,30) width 390: "text dummy text dummy text dummy text dummy text dummy text dummy "
+            text run at (583,30) width 192: "text dummy text dummy text dummy"
+            text run at (0,45) width 195: "text dummy text dummy text dummy "
+            text run at (194,45) width 390: "text dummy text dummy text dummy text dummy text dummy text dummy "
+            text run at (583,45) width 192: "text dummy text dummy text dummy"
+            text run at (0,60) width 195: "text dummy text dummy text dummy "
+            text run at (194,60) width 349: "text dummy text dummy text dummy text dummy text dummy text"
+        RenderText {#text} at (0,0) size 0x0
Property changes on: trunk/LayoutTests/platform/mac-elcapitan/css2.1/t1508-c527-font-00-b-expected.txt
___________________________________________________________________

Added: svn:eol-style

+native \ No newline at end of property

Added: svn:keywords

+Author Date Id Rev URL \ No newline at end of property

Copied: trunk/LayoutTests/platform/mac-elcapitan/fast/inline/absolute-positioned-inline-in-centred-block-expected.png (from rev 205372, trunk/LayoutTests/platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.png)


(Binary files differ)

Copied: trunk/LayoutTests/platform/mac-elcapitan/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt (from rev 205372, trunk/LayoutTests/platform/mac/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt) (0 => 205373)


--- trunk/LayoutTests/platform/mac-elcapitan/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/platform/mac-elcapitan/fast/inline/absolute-positioned-inline-in-centred-block-expected.txt	2016-09-02 21:43:45 UTC (rev 205373)
@@ -0,0 +1,10 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x0
+layer at (250,562) size 303x28
+  RenderBlock (positioned) {FONT} at (250,562) size 303x28
+    RenderText {#text} at (0,0) size 303x28
+      text run at (0,0) width 303: "Hello World, And Stuff!"

Modified: trunk/Source/WebCore/ChangeLog (205372 => 205373)


--- trunk/Source/WebCore/ChangeLog	2016-09-02 21:41:58 UTC (rev 205372)
+++ trunk/Source/WebCore/ChangeLog	2016-09-02 21:43:45 UTC (rev 205373)
@@ -1,3 +1,67 @@
+2016-09-02  Myles C. Maxfield  <mmaxfi...@apple.com>
+
+        [Cocoa] Distinguish between paint advances and base advances
+        https://bugs.webkit.org/show_bug.cgi?id=160892
+
+        Reviewed by Simon Fraser.
+
+        This patch introduces the concept of a layout (or "base") advance which is distinct
+        from a painting advance. In extremely complicated scripts such as Urdu, it is common
+        for a glyph advance to be negative in the horizontal direction, and have large advances
+        in the vertical direction. In particular, in cursive scripts, the glyph placement is
+        only indirectly related to where the actual characters lie. Conceptually, these glyph
+        locations are correct for painting, but are not correct when performing width
+        measurements.
+
+        In many text engines, glyph shaping actually can be split into two phases: adjusting
+        advances, and then placing glyphs relative to those advances. The secondary glyph
+        placement step is much more context-sensitive than the first step. In addition, when
+        multiple glyphs combine to form a character, it is common for one glyph to own the
+        full base advance for the character, and for the other glyphs in the character to
+        have zero base advances. (Then, in the glyph placement phase, the other glyphs get
+        placed all around.)
+
+        Because of the context-insensitivity of the base advances, it is valuable to use
+        these for text measurement. Then, when we want to paint, we should add in the extra
+        origins. This dramatically improves the layout of complex fonts like Noto Nastaliq.
+
+        This patch migrates WebKit to use this two-phase shaping.
+
+        No new tests just yet, because I have to create a font which exercises the
+        advanced glyph placement support.
+
+        * platform/graphics/GlyphBuffer.h:
+        (WebCore::GlyphBufferAdvance::setHeight):
+        (WebCore::GlyphBufferAdvance::setWidth): Deleted.
+        * platform/graphics/TextRun.h:
+        (WebCore::TextRun::TextRun):
+        (WebCore::TextRun::shouldDisableLayoutSpecificAdvances):
+        (WebCore::TextRun::setShouldDisableLayoutSpecificAdvances):
+        (WebCore::TextRun::spacingDisabled): Deleted.
+        (WebCore::TextRun::setCharacterScanForCodePath): Deleted.
+        * platform/graphics/cocoa/FontCascadeCocoa.mm:
+        (WebCore::FontCascade::getGlyphsAndAdvancesForComplexText):
+        * platform/graphics/mac/ComplexTextController.cpp:
+        (WebCore::ComplexTextController::ComplexTextController):
+        (WebCore::ComplexTextController::offsetForPosition):
+        (WebCore::ComplexTextController::collectComplexTextRuns):
+        (WebCore::ComplexTextController::ComplexTextRun::setIsNonMonotonic):
+        (WebCore::ComplexTextController::runWidthSoFarFraction):
+        (WebCore::ComplexTextController::advance):
+        (WebCore::ComplexTextController::adjustGlyphsAndAdvances):
+        * platform/graphics/mac/ComplexTextController.h:
+        (WebCore::ComplexTextController::ComplexTextRun::create):
+        (WebCore::ComplexTextController::ComplexTextRun::baseAdvances):
+        (WebCore::ComplexTextController::ComplexTextRun::glyphOrigins):
+        (WebCore::ComplexTextController::useLayoutSpecificAdvances):
+        (WebCore::ComplexTextController::finalRoundingWidth): Deleted.
+        (WebCore::ComplexTextController::ComplexTextRun::advances): Deleted.
+        * platform/graphics/mac/ComplexTextControllerCoreText.mm:
+        (SOFT_LINK):
+        (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun):
+        (WebCore::ComplexTextController::collectComplexTextRunsForCharacters):
+        * platform/spi/cocoa/CoreTextSPI.h:
+
 2016-09-02  Chris Dumez  <cdu...@apple.com>
 
         Unreviewed, roll out r205354 because it caused JSC test failures

Modified: trunk/Source/WebCore/platform/graphics/GlyphBuffer.h (205372 => 205373)


--- trunk/Source/WebCore/platform/graphics/GlyphBuffer.h	2016-09-02 21:41:58 UTC (rev 205372)
+++ trunk/Source/WebCore/platform/graphics/GlyphBuffer.h	2016-09-02 21:43:45 UTC (rev 205373)
@@ -67,6 +67,7 @@
     }
 
     void setWidth(CGFloat width) { this->CGSize::width = width; }
+    void setHeight(CGFloat height) { this->CGSize::height = height; }
     CGFloat width() const { return this->CGSize::width; }
     CGFloat height() const { return this->CGSize::height; }
 };

Modified: trunk/Source/WebCore/platform/graphics/cocoa/FontCascadeCocoa.mm (205372 => 205373)


--- trunk/Source/WebCore/platform/graphics/cocoa/FontCascadeCocoa.mm	2016-09-02 21:41:58 UTC (rev 205372)
+++ trunk/Source/WebCore/platform/graphics/cocoa/FontCascadeCocoa.mm	2016-09-02 21:43:45 UTC (rev 205373)
@@ -514,7 +514,7 @@
     float afterWidth = controller.runWidthSoFar();
 
     if (run.rtl()) {
-        initialAdvance = controller.totalWidth() + controller.finalRoundingWidth() - afterWidth + controller.leadingExpansion();
+        initialAdvance = controller.totalWidth() - afterWidth + controller.leadingExpansion();
         glyphBuffer.reverse(0, glyphBuffer.size());
     } else
         initialAdvance = beforeWidth;

Modified: trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp (205372 => 205373)


--- trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp	2016-09-02 21:41:58 UTC (rev 205372)
+++ trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.cpp	2016-09-02 21:43:45 UTC (rev 205373)
@@ -107,28 +107,13 @@
 }
 
 ComplexTextController::ComplexTextController(const FontCascade& font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const Font*>* fallbackFonts, bool forTextEmphasis)
-    : m_font(font)
+    : m_fallbackFonts(fallbackFonts)
+    , m_font(font)
     , m_run(run)
-    , m_isLTROnly(true)
+    , m_end(run.length())
+    , m_expansion(run.expansion())
     , m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
     , m_forTextEmphasis(forTextEmphasis)
-    , m_currentCharacter(0)
-    , m_end(run.length())
-    , m_totalWidth(0)
-    , m_runWidthSoFar(0)
-    , m_numGlyphsSoFar(0)
-    , m_currentRun(0)
-    , m_glyphInCurrentRun(0)
-    , m_characterInCurrentGlyph(0)
-    , m_finalRoundingWidth(0)
-    , m_expansion(run.expansion())
-    , m_leadingExpansion(0)
-    , m_fallbackFonts(fallbackFonts)
-    , m_minGlyphBoundingBoxX(std::numeric_limits<float>::max())
-    , m_maxGlyphBoundingBoxX(std::numeric_limits<float>::min())
-    , m_minGlyphBoundingBoxY(std::numeric_limits<float>::max())
-    , m_maxGlyphBoundingBoxY(std::numeric_limits<float>::min())
-    , m_lastRoundingGlyph(0)
 {
     if (!m_expansion)
         m_expansionPerOpportunity = 0;
@@ -158,7 +143,7 @@
     m_runWidthSoFar = m_leadingExpansion;
 }
 
-int ComplexTextController::offsetForPosition(float h, bool includePartialGlyphs)
+unsigned ComplexTextController::offsetForPosition(float h, bool includePartialGlyphs)
 {
     if (h >= m_totalWidth)
         return m_run.ltr() ? m_end : 0;
@@ -176,7 +161,7 @@
         const ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
         for (unsigned j = 0; j < complexTextRun.glyphCount(); ++j) {
             size_t index = offsetIntoAdjustedGlyphs + j;
-            CGFloat adjustedAdvance = m_adjustedAdvances[index].width;
+            CGFloat adjustedAdvance = m_adjustedBaseAdvances[index].width;
             if (!index)
                 adjustedAdvance += complexTextRun.initialAdvance().width;
             if (x < adjustedAdvance) {
@@ -188,8 +173,7 @@
                     hitGlyphEnd = std::max<CFIndex>(hitGlyphStart, j > 0 ? complexTextRun.indexAt(j - 1) : static_cast<CFIndex>(complexTextRun.indexEnd()));
 
                 // FIXME: Instead of dividing the glyph's advance equally between the characters, this
-                // could use the glyph's "ligature carets". However, there is no Core Text API to get the
-                // ligature carets.
+                // could use the glyph's "ligature carets". This is available in CoreText via CTFontGetLigatureCaretPositions().
                 CFIndex hitIndex = hitGlyphStart + (hitGlyphEnd - hitGlyphStart) * (m_run.ltr() ? x / adjustedAdvance : 1 - x / adjustedAdvance);
                 int stringLength = complexTextRun.stringLength();
                 TextBreakIterator* cursorPositionIterator = cursorMovementIterator(StringView(complexTextRun.characters(), stringLength));
@@ -217,7 +201,7 @@
                     clusterWidth = adjustedAdvance;
                     int firstGlyphBeforeCluster = j - 1;
                     while (firstGlyphBeforeCluster >= 0 && complexTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
-                        CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
+                        CGFloat width = m_adjustedBaseAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
                         clusterWidth += width;
                         x += width;
                         firstGlyphBeforeCluster--;
@@ -224,7 +208,7 @@
                     }
                     unsigned firstGlyphAfterCluster = j + 1;
                     while (firstGlyphAfterCluster < complexTextRun.glyphCount() && complexTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) {
-                        clusterWidth += m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width;
+                        clusterWidth += m_adjustedBaseAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width;
                         firstGlyphAfterCluster++;
                     }
                 } else {
@@ -323,10 +307,11 @@
     // We break up glyph run generation for the string by Font.
     const UChar* cp;
 
+    Vector<String> stringsFor8BitRuns;
     if (m_run.is8Bit()) {
         String stringFor8BitRun = String::make16BitFrom8BitSource(m_run.characters8(), m_run.length());
-        cp = stringFor8BitRun.characters16();
-        m_stringsFor8BitRuns.append(stringFor8BitRun);
+        stringsFor8BitRuns.append(WTFMove(stringFor8BitRun));
+        cp = stringsFor8BitRuns.last().characters16();
     } else
         cp = m_run.characters16();
 
@@ -428,6 +413,7 @@
         }
     }
 
+    ASSERT(m_end >= indexOfFontTransition);
     unsigned itemLength = m_end - indexOfFontTransition;
     if (itemLength) {
         unsigned itemStart = indexOfFontTransition;
@@ -463,7 +449,7 @@
     }
 
     m_glyphEndOffsets.grow(m_glyphCount);
-    for (size_t i = 0; i < m_glyphCount; ++i) {
+    for (unsigned i = 0; i < m_glyphCount; ++i) {
         CFIndex nextMappedIndex = m_indexEnd;
         for (size_t j = indexAt(i) + 1; j < m_stringLength; ++j) {
             if (mappedIndices[j]) {
@@ -530,9 +516,28 @@
     return indexOfCurrentRun(leftmostGlyph);
 }
 
+float ComplexTextController::runWidthSoFarFraction(unsigned glyphStartOffset, unsigned glyphEndOffset, unsigned oldCharacterInCurrentGlyph, GlyphIterationStyle iterationStyle) const
+{
+    // FIXME: Instead of dividing the glyph's advance equally between the characters, this
+    // could use the glyph's "ligature carets". This is available in CoreText via CTFontGetLigatureCaretPositions().
+    if (glyphStartOffset == glyphEndOffset) {
+        // When there are multiple glyphs per character we need to advance by the full width of the glyph.
+        ASSERT(m_characterInCurrentGlyph == oldCharacterInCurrentGlyph);
+        return 1;
+    }
+
+    if (iterationStyle == ByWholeGlyphs) {
+        if (!oldCharacterInCurrentGlyph)
+            return 1;
+        return 0;
+    }
+
+    return static_cast<float>(m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset);
+}
+
 void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer, GlyphIterationStyle iterationStyle, HashSet<const Font*>* fallbackFonts)
 {
-    if (static_cast<int>(offset) > m_end)
+    if (offset > m_end)
         offset = m_end;
 
     if (offset <= m_currentCharacter) {
@@ -562,7 +567,14 @@
         // When leftmostGlyph is 0, it represents the first glyph to draw, taking into
         // account the text direction.
         if (glyphBuffer && !leftmostGlyph) {
-            glyphBuffer->setInitialAdvance(complexTextRun.initialAdvance());
+            CGSize initialAdvance = complexTextRun.initialAdvance();
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+            unsigned index = ltr ? 0 : m_glyphOrigins.size() - 1;
+            initialAdvance.width += m_glyphOrigins[index].x;
+            initialAdvance.height += m_glyphOrigins[index].y;
+#endif
+            glyphBuffer->setInitialAdvance(initialAdvance);
+
             glyphBuffer->setLeadingExpansion(m_leadingExpansion);
         }
 
@@ -577,28 +589,25 @@
             } else
                 glyphEndOffset = complexTextRun.endOffsetAt(g);
 
-            CGSize adjustedAdvance = m_adjustedAdvances[k];
+            CGSize adjustedBaseAdvance = m_adjustedBaseAdvances[k];
 
             if (glyphStartOffset + complexTextRun.stringLocation() >= m_currentCharacter)
                 return;
 
-            if (glyphBuffer && !m_characterInCurrentGlyph)
-                glyphBuffer->add(m_adjustedGlyphs[k], &complexTextRun.font(), adjustedAdvance, complexTextRun.indexAt(m_glyphInCurrentRun));
+            if (glyphBuffer && !m_characterInCurrentGlyph) {
+                GlyphBufferAdvance paintAdvance = adjustedBaseAdvance;
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+                if (k + 1 < m_adjustedBaseAdvances.size()) {
+                    paintAdvance.setWidth(paintAdvance.width() + m_glyphOrigins[k + 1].x - m_glyphOrigins[k].x);
+                    paintAdvance.setHeight(paintAdvance.height() - m_glyphOrigins[k + 1].y + m_glyphOrigins[k].y);
+                }
+#endif
+                glyphBuffer->add(m_adjustedGlyphs[k], &complexTextRun.font(), paintAdvance, complexTextRun.indexAt(m_glyphInCurrentRun));
+            }
 
             unsigned oldCharacterInCurrentGlyph = m_characterInCurrentGlyph;
             m_characterInCurrentGlyph = std::min(m_currentCharacter - complexTextRun.stringLocation(), glyphEndOffset) - glyphStartOffset;
-            // FIXME: Instead of dividing the glyph's advance equally between the characters, this
-            // could use the glyph's "ligature carets". However, there is no Core Text API to get the
-            // ligature carets.
-            if (glyphStartOffset == glyphEndOffset) {
-                // When there are multiple glyphs per character we need to advance by the full width of the glyph.
-                ASSERT(m_characterInCurrentGlyph == oldCharacterInCurrentGlyph);
-                m_runWidthSoFar += adjustedAdvance.width;
-            } else if (iterationStyle == ByWholeGlyphs) {
-                if (!oldCharacterInCurrentGlyph)
-                    m_runWidthSoFar += adjustedAdvance.width;
-            } else
-                m_runWidthSoFar += adjustedAdvance.width * (m_characterInCurrentGlyph - oldCharacterInCurrentGlyph) / (glyphEndOffset - glyphStartOffset);
+            m_runWidthSoFar += adjustedBaseAdvance.width * runWidthSoFarFraction(glyphStartOffset, glyphEndOffset, oldCharacterInCurrentGlyph, iterationStyle);
 
             if (glyphEndOffset + complexTextRun.stringLocation() > m_currentCharacter)
                 return;
@@ -617,8 +626,6 @@
         currentRunIndex = incrementCurrentRun(leftmostGlyph);
         m_glyphInCurrentRun = 0;
     }
-    if (!m_run.ltr() && m_numGlyphsSoFar == m_adjustedAdvances.size())
-        m_runWidthSoFar += m_finalRoundingWidth;
 }
 
 static inline std::pair<bool, bool> expansionLocation(bool ideograph, bool treatAsSpace, bool ltr, bool isAfterExpansion, bool forbidLeadingExpansion, bool forbidTrailingExpansion, bool forceLeadingExpansion, bool forceTrailingExpansion)
@@ -656,6 +663,7 @@
     bool runForcesTrailingExpansion = (m_run.expansionBehavior() & TrailingExpansionMask) == ForceTrailingExpansion;
     bool runForbidsLeadingExpansion = (m_run.expansionBehavior() & LeadingExpansionMask) == ForbidLeadingExpansion;
     bool runForbidsTrailingExpansion = (m_run.expansionBehavior() & TrailingExpansionMask) == ForbidTrailingExpansion;
+
     // We are iterating in glyph order, not string order. Compare this to WidthIterator::advanceInternal()
     for (size_t r = 0; r < runCount; ++r) {
         ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
@@ -664,11 +672,11 @@
 
         // Represent the initial advance for a text run by adjusting the advance
         // of the last glyph of the previous text run in the glyph buffer.
-        if (r && m_adjustedAdvances.size()) {
-            CGSize previousAdvance = m_adjustedAdvances.last();
+        if (r && m_adjustedBaseAdvances.size()) {
+            CGSize previousAdvance = m_adjustedBaseAdvances.last();
             previousAdvance.width += complexTextRun.initialAdvance().width;
             previousAdvance.height -= complexTextRun.initialAdvance().height;
-            m_adjustedAdvances[m_adjustedAdvances.size() - 1] = previousAdvance;
+            m_adjustedBaseAdvances[m_adjustedBaseAdvances.size() - 1] = previousAdvance;
         }
         widthSinceLastCommit += complexTextRun.initialAdvance().width;
 
@@ -676,7 +684,7 @@
             m_isLTROnly = false;
 
         const CGGlyph* glyphs = complexTextRun.glyphs();
-        const CGSize* advances = complexTextRun.advances();
+        const CGSize* advances = complexTextRun.baseAdvances();
 
         bool lastRun = r + 1 == runCount;
         float spaceWidth = font.spaceWidth() - font.syntheticBoldOffset();
@@ -750,10 +758,10 @@
                             // Increase previous width
                             m_expansion -= m_expansionPerOpportunity;
                             m_totalWidth += m_expansionPerOpportunity;
-                            if (m_adjustedAdvances.isEmpty())
+                            if (m_adjustedBaseAdvances.isEmpty())
                                 m_leadingExpansion = m_expansionPerOpportunity;
                             else
-                                m_adjustedAdvances.last().width += m_expansionPerOpportunity;
+                                m_adjustedBaseAdvances.last().width += m_expansionPerOpportunity;
                         }
                         if (expandRight) {
                             m_expansion -= m_expansionPerOpportunity;
@@ -777,7 +785,10 @@
                 glyph = 0;
 
             advance.height *= -1;
-            m_adjustedAdvances.append(advance);
+            m_adjustedBaseAdvances.append(advance);
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+            m_glyphOrigins.append(complexTextRun.glyphOrigins()[i]);
+#endif
             m_adjustedGlyphs.append(glyph);
             
             FloatRect glyphBounds = font.boundsForGlyph(glyph);

Modified: trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.h (205372 => 205373)


--- trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.h	2016-09-02 21:41:58 UTC (rev 205372)
+++ trunk/Source/WebCore/platform/graphics/mac/ComplexTextController.h	2016-09-02 21:43:45 UTC (rev 205373)
@@ -32,6 +32,8 @@
 #include <wtf/Vector.h>
 #include <wtf/text/WTFString.h>
 
+#define USE_LAYOUT_SPECIFIC_ADVANCES ((PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 90000))
+
 typedef unsigned short CGGlyph;
 
 typedef const struct __CTRun * CTRunRef;
@@ -56,7 +58,7 @@
     void advance(unsigned to, GlyphBuffer* = nullptr, GlyphIterationStyle = IncludePartialGlyphs, HashSet<const Font*>* fallbackFonts = nullptr);
 
     // Compute the character offset for a given x coordinate.
-    int offsetForPosition(float x, bool includePartialGlyphs);
+    unsigned offsetForPosition(float x, bool includePartialGlyphs);
 
     // Returns the width of everything we've consumed so far.
     float runWidthSoFar() const { return m_runWidthSoFar; }
@@ -63,8 +65,6 @@
 
     float totalWidth() const { return m_totalWidth; }
 
-    float finalRoundingWidth() const { return m_finalRoundingWidth; }
-
     float minGlyphBoundingBoxX() const { return m_minGlyphBoundingBoxX; }
     float maxGlyphBoundingBoxX() const { return m_maxGlyphBoundingBoxX; }
     float minGlyphBoundingBoxY() const { return m_minGlyphBoundingBoxY; }
@@ -95,8 +95,20 @@
         CFIndex indexEnd() const { return m_indexEnd; }
         CFIndex endOffsetAt(size_t i) const { ASSERT(!m_isMonotonic); return m_glyphEndOffsets[i]; }
         const CGGlyph* glyphs() const { return m_glyphs; }
+
+        /*
+         *                                              X (Paint glyph position)   X (Paint glyph position)   X (Paint glyph position)
+         *                                             7                          7                          7
+         *                                            /                          /                          /
+         *                                           / (Glyph origin)           / (Glyph origin)           / (Glyph origin)
+         *                                          /                          /                          /
+         *                                         /                          /                          /
+         *                X-----------------------X--------------------------X--------------------------X---->...
+         * (text position ^)  (initial advance)          (base advance)             (base advance)
+         */
         CGSize initialAdvance() const { return m_initialAdvance; }
-        const CGSize* advances() const { return m_advances; }
+        const CGSize* baseAdvances() const { return m_baseAdvances; }
+        const CGPoint* glyphOrigins() const { return m_glyphOrigins.data(); }
         bool isLTR() const { return m_isLTR; }
         bool isMonotonic() const { return m_isMonotonic; }
         void setIsNonMonotonic();
@@ -105,21 +117,22 @@
         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);
 
-        unsigned m_glyphCount;
+        Vector<CGSize, 64> m_baseAdvancesVector;
+        Vector<CGPoint, 64> m_glyphOrigins;
+        Vector<CGGlyph, 64> m_glyphsVector;
+        Vector<CFIndex, 64> m_glyphEndOffsets;
+        Vector<CFIndex, 64> m_coreTextIndicesVector;
+        CGSize m_initialAdvance;
         const Font& m_font;
         const UChar* m_characters;
-        unsigned m_stringLocation;
         size_t m_stringLength;
-        Vector<CFIndex, 64> m_coreTextIndicesVector;
         const CFIndex* m_coreTextIndices;
+        const CGGlyph* m_glyphs;
+        const CGSize* m_baseAdvances;
         CFIndex m_indexBegin;
         CFIndex m_indexEnd;
-        Vector<CFIndex, 64> m_glyphEndOffsets;
-        Vector<CGGlyph, 64> m_glyphsVector;
-        const CGGlyph* m_glyphs;
-        CGSize m_initialAdvance;
-        Vector<CGSize, 64> m_advancesVector;
-        const CGSize* m_advances;
+        unsigned m_glyphCount;
+        unsigned m_stringLocation;
         bool m_isLTR;
         bool m_isMonotonic;
     };
@@ -135,18 +148,12 @@
     unsigned indexOfCurrentRun(unsigned& leftmostGlyph);
     unsigned incrementCurrentRun(unsigned& leftmostGlyph);
 
-    // The initial capacity of these vectors was selected as being the smallest power of two greater than
-    // the average (3.5) plus one standard deviation (7.5) of nonzero sizes used on Arabic Wikipedia.
-    Vector<unsigned, 16> m_runIndices;
-    Vector<unsigned, 16> m_glyphCountFromStartToIndex;
+    float runWidthSoFarFraction(unsigned glyphStartOffset, unsigned glyphEndOffset, unsigned oldCharacterInCurrentGlyph, GlyphIterationStyle) const;
 
-    const FontCascade& m_font;
-    const TextRun& m_run;
-    bool m_isLTROnly;
-    bool m_mayUseNaturalWritingDirection;
-    bool m_forTextEmphasis;
+    Vector<CGSize, 256> m_adjustedBaseAdvances;
+    Vector<CGPoint, 256> m_glyphOrigins;
+    Vector<CGGlyph, 256> m_adjustedGlyphs;
 
-    Vector<String> m_stringsFor8BitRuns;
     Vector<UChar, 256> m_smallCapsBuffer;
 
     // There is a 3-level hierarchy here. At the top, we are interested in m_run.string(). We partition that string
@@ -156,34 +163,41 @@
     // relative to m_run.string(). ComplexTextRun::indexAt() returns to the offset of a codepoint relative to
     // its Line. ComplexTextRun::glyphs() and ComplexTextRun::advances() refer to glyphs relative to the ComplexTextRun.
     // The length of the entire TextRun is m_run.length()
-    Vector<RetainPtr<CTLineRef>> m_coreTextLines;
     Vector<RefPtr<ComplexTextRun>, 16> m_complexTextRuns;
-    Vector<CGSize, 256> m_adjustedAdvances;
-    Vector<CGGlyph, 256> m_adjustedGlyphs;
- 
-    unsigned m_currentCharacter;
-    int m_end;
 
-    CGFloat m_totalWidth;
+    // The initial capacity of these vectors was selected as being the smallest power of two greater than
+    // the average (3.5) plus one standard deviation (7.5) of nonzero sizes used on Arabic Wikipedia.
+    Vector<unsigned, 16> m_runIndices;
+    Vector<unsigned, 16> m_glyphCountFromStartToIndex;
 
-    float m_runWidthSoFar;
-    unsigned m_numGlyphsSoFar;
-    size_t m_currentRun;
-    unsigned m_glyphInCurrentRun;
-    unsigned m_characterInCurrentGlyph;
-    float m_finalRoundingWidth;
-    float m_expansion;
-    float m_expansionPerOpportunity;
-    float m_leadingExpansion;
+    Vector<RetainPtr<CTLineRef>> m_coreTextLines;
 
-    HashSet<const Font*>* m_fallbackFonts;
+    HashSet<const Font*>* m_fallbackFonts { nullptr };
 
-    float m_minGlyphBoundingBoxX;
-    float m_maxGlyphBoundingBoxX;
-    float m_minGlyphBoundingBoxY;
-    float m_maxGlyphBoundingBoxY;
+    const FontCascade& m_font;
+    const TextRun& m_run;
+ 
+    unsigned m_currentCharacter { 0 };
+    unsigned m_end { 0 };
 
-    unsigned m_lastRoundingGlyph;
+    float m_totalWidth { 0 };
+    float m_runWidthSoFar { 0 };
+    unsigned m_numGlyphsSoFar { 0 };
+    unsigned m_currentRun { 0 };
+    unsigned m_glyphInCurrentRun { 0 };
+    unsigned m_characterInCurrentGlyph { 0 };
+    float m_expansion { 0 };
+    float m_expansionPerOpportunity { 0 };
+    float m_leadingExpansion { 0 };
+
+    float m_minGlyphBoundingBoxX { std::numeric_limits<float>::max() };
+    float m_maxGlyphBoundingBoxX { std::numeric_limits<float>::min() };
+    float m_minGlyphBoundingBoxY { std::numeric_limits<float>::max() };
+    float m_maxGlyphBoundingBoxY { std::numeric_limits<float>::min() };
+
+    bool m_isLTROnly { true };
+    bool m_mayUseNaturalWritingDirection { false };
+    bool m_forTextEmphasis { false };
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm (205372 => 205373)


--- trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm	2016-09-02 21:41:58 UTC (rev 205372)
+++ trunk/Source/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.mm	2016-09-02 21:43:45 UTC (rev 205373)
@@ -29,6 +29,7 @@
 #include "CoreTextSPI.h"
 #include "FontCache.h"
 #include "FontCascade.h"
+#include "SoftLinking.h"
 #include "TextRun.h"
 #include "WebCoreSystemInterface.h"
 #include <wtf/WeakPtr.h>
@@ -39,6 +40,12 @@
 #include <ApplicationServices/ApplicationServices.h>
 #endif
 
+#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101100) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED < 90000)
+SOFT_LINK_FRAMEWORK(CoreText);
+SOFT_LINK(CoreText, CTRunGetBaseAdvancesAndOrigins, void, (CTRunRef run, CFRange range, CGSize baseAdvances[], CGPoint origins[]), (run, range, baseAdvances, origins))
+#endif
+
+
 // Note: CTFontDescriptorRefs can live forever in caches inside CoreText, so this object can too.
 @interface WebCascadeList : NSArray {
     @private
@@ -100,13 +107,13 @@
 namespace WebCore {
 
 ComplexTextController::ComplexTextRun::ComplexTextRun(CTRunRef ctRun, const Font& font, const UChar* characters, unsigned stringLocation, size_t stringLength, CFRange runRange)
-    : m_font(font)
+    : m_initialAdvance(CTRunGetInitialAdvance(ctRun))
+    , m_font(font)
     , m_characters(characters)
-    , m_stringLocation(stringLocation)
     , m_stringLength(stringLength)
     , m_indexBegin(runRange.location)
     , m_indexEnd(runRange.location + runRange.length)
-    , m_initialAdvance(CTRunGetInitialAdvance(ctRun))
+    , m_stringLocation(stringLocation)
     , m_isLTR(!(CTRunGetStatus(ctRun) & kCTRunStatusRightToLeft))
     , m_isMonotonic(true)
 {
@@ -125,24 +132,31 @@
         m_glyphs = m_glyphsVector.data();
     }
 
-    m_advances = CTRunGetAdvancesPtr(ctRun);
-    if (!m_advances) {
-        m_advancesVector.grow(m_glyphCount);
-        CTRunGetAdvances(ctRun, CFRangeMake(0, 0), m_advancesVector.data());
-        m_advances = m_advancesVector.data();
+#if USE_LAYOUT_SPECIFIC_ADVANCES
+    m_baseAdvancesVector.grow(m_glyphCount);
+    m_glyphOrigins.grow(m_glyphCount);
+    CTRunGetBaseAdvancesAndOrigins(ctRun, CFRangeMake(0, 0), m_baseAdvancesVector.data(), m_glyphOrigins.data());
+    m_baseAdvances = m_baseAdvancesVector.data();
+#else
+    m_baseAdvances = CTRunGetAdvancesPtr(ctRun);
+    if (!m_baseAdvances) {
+        m_baseAdvancesVector.grow(m_glyphCount);
+        CTRunGetAdvances(ctRun, CFRangeMake(0, 0), m_baseAdvancesVector.data());
+        m_baseAdvances = m_baseAdvancesVector.data();
     }
+#endif
 }
 
 // Missing glyphs run constructor. Core Text will not generate a run of missing glyphs, instead falling back on
 // glyphs from LastResort. We want to use the primary font's missing glyph in order to match the fast text code path.
 ComplexTextController::ComplexTextRun::ComplexTextRun(const Font& font, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
-    : m_font(font)
+    : m_initialAdvance(CGSizeZero)
+    , m_font(font)
     , m_characters(characters)
-    , m_stringLocation(stringLocation)
     , m_stringLength(stringLength)
     , m_indexBegin(0)
     , m_indexEnd(stringLength)
-    , m_initialAdvance(CGSizeZero)
+    , m_stringLocation(stringLocation)
     , m_isLTR(ltr)
     , m_isMonotonic(true)
 {
@@ -150,10 +164,8 @@
     unsigned r = 0;
     while (r < m_stringLength) {
         m_coreTextIndicesVector.uncheckedAppend(r);
-        if (U_IS_LEAD(m_characters[r]) && r + 1 < m_stringLength && U_IS_TRAIL(m_characters[r + 1]))
-            r += 2;
-        else
-            r++;
+        UChar32 character;
+        U16_NEXT(m_characters, r, m_stringLength, character);
     }
     m_glyphCount = m_coreTextIndicesVector.size();
     if (!ltr) {
@@ -165,8 +177,8 @@
     // Synthesize a run of missing glyphs.
     m_glyphsVector.fill(0, m_glyphCount);
     m_glyphs = m_glyphsVector.data();
-    m_advancesVector.fill(CGSizeMake(m_font.widthForGlyph(0), 0), m_glyphCount);
-    m_advances = m_advancesVector.data();
+    m_baseAdvancesVector.fill(CGSizeMake(m_font.widthForGlyph(0), 0), m_glyphCount);
+    m_baseAdvances = m_baseAdvancesVector.data();
 }
 
 struct ProviderInfo {

Modified: trunk/Source/WebCore/platform/spi/cocoa/CoreTextSPI.h (205372 => 205373)


--- trunk/Source/WebCore/platform/spi/cocoa/CoreTextSPI.h	2016-09-02 21:41:58 UTC (rev 205372)
+++ trunk/Source/WebCore/platform/spi/cocoa/CoreTextSPI.h	2016-09-02 21:43:45 UTC (rev 205373)
@@ -68,6 +68,7 @@
 
 CGSize CTRunGetInitialAdvance(CTRunRef run);
 CTLineRef CTLineCreateWithUniCharProvider(CTUniCharProviderCallback provide, CTUniCharDisposeCallback dispose, void* refCon);
+void CTRunGetBaseAdvancesAndOrigins(CTRunRef, CFRange, CGSize baseAdvances[], CGPoint origins[]);
 CTTypesetterRef CTTypesetterCreateWithUniCharProviderAndOptions(CTUniCharProviderCallback provide, CTUniCharDisposeCallback dispose, void* refCon, CFDictionaryRef options);
 bool CTFontGetVerticalGlyphsForCharacters(CTFontRef, const UniChar characters[], CGGlyph glyphs[], CFIndex count);
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to