[SCM] WebKit Debian packaging branch, webkit-1.2, updated. upstream/1.1.90-6072-g9a69373

mitz at apple.com mitz at apple.com
Wed Apr 7 23:14:09 UTC 2010


The following commit has been merged in the webkit-1.2 branch:
commit 71c630486272b94facdda2523b80bbeebed7582d
Author: mitz at apple.com <mitz at apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Thu Oct 29 05:35:36 2009 +0000

    WebCore: Share code between the ATSUI- and Core Text-based Font implementations by doing the
    following:
    - Generalize CoreTextController as ComplexTextController, keeping the Core Text-specific
      parts in ComplexTextControllerCoreText.cpp.
    - Generalize FontMacCoreText as FontComplexTextMac using ComplexTextController
    - Implement ATSUI-specific parts of ComplexTextController in ComplexTextControllerATSUI.
    - Remove FontMacATSUI.
    
    Reviewed by Sam Weinig.
    
    * WebCore.xcodeproj/project.pbxproj: Removed CoreTextController.{cpp,h}, FontMacATSUI.mm,
    and FontMacCoreText.cpp, and added ComplexTextController.{cpp,h},
    ComplexTextControllerATSUI.cpp, ComplexTextControllerCoreText.cpp, and
    FontComplexTextMac.cpp.
    
    * platform/graphics/mac/ComplexTextController.cpp: Copied from CoreTextController.cpp and
    kept the non-Core Text-specific bits.
    (WebCore::ComplexTextController::ComplexTextController): Updated for renames, including
    its own.
    (WebCore::ComplexTextController::offsetForPosition): Updated for renames and for
    m_complexTextRuns holding references instead of objects.
    (WebCore::ComplexTextController::collectComplexTextRuns): Updated for renames, including
    its own.
    (WebCore::ComplexTextController::advance): Updated for renames.
    (WebCore::ComplexTextController::adjustGlyphsAndAdvances): Updated for renames and for
    m_complexTextRuns holding references instead of objects, and changed to use the glyphs()
    and advances() accessors.
    
    * platform/graphics/mac/ComplexTextController.h: Copied from CoreTextController.h and
    renamed CoreTextController to ComplexTextController and CoreTextRun to ComplexTextRun. Made
    the latter RefCounted, added ATSUI-specific members to it, and made some other members
    Core Text-specific. Renamed m_coreTextRuns to m_complexTextRuns and made it hold references
    rather than objects.
    (WebCore::ComplexTextController::ComplexTextRun::create):
    (WebCore::ComplexTextController::ComplexTextRun::glyphs):
    (WebCore::ComplexTextController::ComplexTextRun::advances):
    
    * platform/graphics/mac/ComplexTextControllerATSUI.cpp: Added. Includes ATSUI-specific
    parts of the ComplexTextController implementation.
    (WebCore::ComplexTextController::ComplexTextRun::overrideLayoutOperation): This ATSUI
    callback populates the ComplexTextRun’s glyphs, advances and indices vectors. It is invoked
    when the ComplexTextRun constructor calls ATSUGetGlyphBounds().
    (WebCore::isArabicLamWithAlefLigature): Helper function, copied from FontMacATSUI.mm.
    (WebCore::shapeArabic): Helper function, adapted from FontMacATSUI.mm.
    (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun): Sets up the
    ATSUTextLayout, substituting the text buffer if necessary for things like shaping Arabic,
    mirroring glyphs or directionality overrides, then calls ATSUGetGlyphBounds() in order to
    get the glyphs, advances and indices vectors populated.
    (WebCore::fontHasMirroringInfo): Helper function, copied from FontMacATSUI.mm.
    (WebCore::disableLigatures): Ditto.
    (WebCore::initializeATSUStyle): Ditto, somewhat cleaned up and simplified.
    (WebCore::ComplexTextController::collectComplexTextRunsForCharacters): Constructs
    ComplexTextRuns, either missing-glyphs ones or ATSUTextLayout-based ones.
    
    * platform/graphics/mac/ComplexTextControllerCoreText.cpp: Copied from
    CoreTextController.cpp and kept the Core Text-specific bits.
    (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun): Updated for renames,
    including its own, and moved the code to initialize m_glyphs and m_advances here. Previously
    this was done in adjustGlyphsAndAdvances().
    (WebCore::ComplexTextController::collectComplexTextRunsForCharacters): Updated for renames,
    including its own.
    * platform/graphics/mac/CoreTextController.cpp: Removed.
    * platform/graphics/mac/CoreTextController.h: Removed.
    * platform/graphics/mac/FontComplexTextMac.cpp: Renamed FontMacCoreText.cpp to this.
    (WebCore::Font::selectionRectForComplexText): Changed to use ComplexTextController instead
    of CoreTextController.
    (WebCore::Font::drawComplexText): Ditto.
    (WebCore::Font::floatWidthForComplexText): Ditto.
    (WebCore::Font::offsetForPositionForComplexText): Ditto.
    * platform/graphics/mac/FontMacATSUI.mm: Removed.
    * platform/graphics/mac/FontMacCoreText.cpp: Removed.
    
    LayoutTests: Removed Leopard-specific result after changing ATSUI missing-glyph behavior to match the
    Core Text and fast code paths' behavior.
    
    * platform/mac-leopard/fast/text/international/khmer-selection-expected.txt: Removed.
    
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@50259 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 5220076..55b7e3f 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,10 @@
+2009-10-28  Dan Bernstein  <mitz at apple.com>
+
+        Removed Leopard-specific result after changing ATSUI missing-glyph behavior to match the
+        Core Text and fast code paths' behavior.
+
+        * platform/mac-leopard/fast/text/international/khmer-selection-expected.txt: Removed.
+
 2009-10-28  Andrew Scherkus  <scherkus at chromium.org>
 
         Reviewed by Eric Carlson.
diff --git a/LayoutTests/platform/mac-leopard/fast/text/international/khmer-selection-expected.txt b/LayoutTests/platform/mac-leopard/fast/text/international/khmer-selection-expected.txt
deleted file mode 100644
index 14756cb..0000000
--- a/LayoutTests/platform/mac-leopard/fast/text/international/khmer-selection-expected.txt
+++ /dev/null
@@ -1,46 +0,0 @@
-layer at (0,0) size 800x600
-  RenderView at (0,0) size 800x600
-layer at (0,0) size 800x120
-  RenderBlock {HTML} at (0,0) size 800x120
-    RenderBody {BODY} at (8,16) size 784x88
-      RenderBlock {P} at (0,0) size 784x18
-        RenderInline {NOBR} at (0,0) size 408x18
-          RenderInline {B} at (0,0) size 72x18
-            RenderText {#text} at (0,0) size 72x18
-              text run at (0,0) width 72: "\x{179C}\x{17C9}\x{17C2}\x{1794}"
-          RenderText {#text} at (72,0) size 4x18
-            text run at (72,0) width 4: " "
-          RenderInline {A} at (0,0) size 108x18 [color=#0000EE]
-            RenderText {#text} at (76,0) size 108x18
-              text run at (76,0) width 108: "\x{179A}\x{17BC}\x{1794}\x{1797}\x{17B6}\x{1796}"
-          RenderText {#text} at (184,0) size 4x18
-            text run at (184,0) width 4: " "
-          RenderInline {A} at (0,0) size 90x18 [color=#0000EE]
-            RenderText {#text} at (188,0) size 90x18
-              text run at (188,0) width 90: "\x{1780}\x{17D2}\x{179A}\x{17BB}\x{1798}"
-          RenderText {#text} at (278,0) size 4x18
-            text run at (278,0) width 4: " "
-          RenderInline {A} at (0,0) size 126x18 [color=#0000EE]
-            RenderText {#text} at (282,0) size 126x18
-              text run at (282,0) width 126: "\x{1790}\x{178F}\x{17AF}\x{1780}\x{179F}\x{17B6}\x{179A}"
-        RenderText {#text} at (0,0) size 0x0
-      RenderBlock {P} at (0,34) size 784x54
-        RenderText {#text} at (0,0) size 532x18
-          text run at (0,0) width 532: "Some Harfbuzz shapers will output cluster logs which suggest that some glyphs had "
-        RenderInline {I} at (0,0) size 16x18
-          RenderText {#text} at (532,0) size 16x18
-            text run at (532,0) width 16: "no"
-        RenderText {#text} at (548,0) size 765x36
-          text run at (548,0) width 217: " contributing code points. This test"
-          text run at (0,18) width 174: "contains such text and uses "
-        RenderInline {TT} at (0,0) size 88x15
-          RenderText {#text} at (174,20) size 88x15
-            text run at (174,20) width 88: "eventSender"
-        RenderText {#text} at (262,18) size 442x18
-          text run at (262,18) width 442: " to select the text. You should see some of the above text selected and "
-        RenderInline {TT} at (0,0) size 80x15
-          RenderText {#text} at (704,20) size 80x15
-            text run at (704,20) width 80: "test_shell"
-        RenderText {#text} at (0,36) size 252x18
-          text run at (0,36) width 252: "shouldn't trigger any assertions or crash."
-caret: position 0 of child 0 {#text} of child 0 {B} of child 1 {NOBR} of child 1 {P} of child 1 {BODY} of child 1 {HTML} of document
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 1727089..e59d9bd 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,77 @@
+2009-10-28  Dan Bernstein  <mitz at apple.com>
+
+        Reviewed by Sam Weinig.
+
+        Share code between the ATSUI- and Core Text-based Font implementations by doing the
+        following:
+        - Generalize CoreTextController as ComplexTextController, keeping the Core Text-specific
+          parts in ComplexTextControllerCoreText.cpp.
+        - Generalize FontMacCoreText as FontComplexTextMac using ComplexTextController
+        - Implement ATSUI-specific parts of ComplexTextController in ComplexTextControllerATSUI.
+        - Remove FontMacATSUI.
+
+        * WebCore.xcodeproj/project.pbxproj: Removed CoreTextController.{cpp,h}, FontMacATSUI.mm,
+        and FontMacCoreText.cpp, and added ComplexTextController.{cpp,h},
+        ComplexTextControllerATSUI.cpp, ComplexTextControllerCoreText.cpp, and
+        FontComplexTextMac.cpp.
+
+        * platform/graphics/mac/ComplexTextController.cpp: Copied from CoreTextController.cpp and
+        kept the non-Core Text-specific bits.
+        (WebCore::ComplexTextController::ComplexTextController): Updated for renames, including
+        its own.
+        (WebCore::ComplexTextController::offsetForPosition): Updated for renames and for
+        m_complexTextRuns holding references instead of objects.
+        (WebCore::ComplexTextController::collectComplexTextRuns): Updated for renames, including
+        its own.
+        (WebCore::ComplexTextController::advance): Updated for renames.
+        (WebCore::ComplexTextController::adjustGlyphsAndAdvances): Updated for renames and for
+        m_complexTextRuns holding references instead of objects, and changed to use the glyphs()
+        and advances() accessors.
+
+        * platform/graphics/mac/ComplexTextController.h: Copied from CoreTextController.h and
+        renamed CoreTextController to ComplexTextController and CoreTextRun to ComplexTextRun. Made
+        the latter RefCounted, added ATSUI-specific members to it, and made some other members
+        Core Text-specific. Renamed m_coreTextRuns to m_complexTextRuns and made it hold references
+        rather than objects.
+        (WebCore::ComplexTextController::ComplexTextRun::create):
+        (WebCore::ComplexTextController::ComplexTextRun::glyphs):
+        (WebCore::ComplexTextController::ComplexTextRun::advances):
+
+        * platform/graphics/mac/ComplexTextControllerATSUI.cpp: Added. Includes ATSUI-specific
+        parts of the ComplexTextController implementation. 
+        (WebCore::ComplexTextController::ComplexTextRun::overrideLayoutOperation): This ATSUI
+        callback populates the ComplexTextRun’s glyphs, advances and indices vectors. It is invoked
+        when the ComplexTextRun constructor calls ATSUGetGlyphBounds().
+        (WebCore::isArabicLamWithAlefLigature): Helper function, copied from FontMacATSUI.mm.
+        (WebCore::shapeArabic): Helper function, adapted from FontMacATSUI.mm.
+        (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun): Sets up the
+        ATSUTextLayout, substituting the text buffer if necessary for things like shaping Arabic,
+        mirroring glyphs or directionality overrides, then calls ATSUGetGlyphBounds() in order to
+        get the glyphs, advances and indices vectors populated.
+        (WebCore::fontHasMirroringInfo): Helper function, copied from FontMacATSUI.mm.
+        (WebCore::disableLigatures): Ditto.
+        (WebCore::initializeATSUStyle): Ditto, somewhat cleaned up and simplified.
+        (WebCore::ComplexTextController::collectComplexTextRunsForCharacters): Constructs
+        ComplexTextRuns, either missing-glyphs ones or ATSUTextLayout-based ones.
+
+        * platform/graphics/mac/ComplexTextControllerCoreText.cpp: Copied from
+        CoreTextController.cpp and kept the Core Text-specific bits.
+        (WebCore::ComplexTextController::ComplexTextRun::ComplexTextRun): Updated for renames,
+        including its own, and moved the code to initialize m_glyphs and m_advances here. Previously
+        this was done in adjustGlyphsAndAdvances().
+        (WebCore::ComplexTextController::collectComplexTextRunsForCharacters): Updated for renames,
+        including its own.
+        * platform/graphics/mac/CoreTextController.cpp: Removed.
+        * platform/graphics/mac/CoreTextController.h: Removed.
+        * platform/graphics/mac/FontComplexTextMac.cpp: Renamed FontMacCoreText.cpp to this.
+        (WebCore::Font::selectionRectForComplexText): Changed to use ComplexTextController instead
+        of CoreTextController.
+        (WebCore::Font::drawComplexText): Ditto.
+        (WebCore::Font::floatWidthForComplexText): Ditto.
+        (WebCore::Font::offsetForPositionForComplexText): Ditto.
+        * platform/graphics/mac/FontMacATSUI.mm: Removed.
+        * platform/graphics/mac/FontMacCoreText.cpp: Removed.
+
 2009-10-27  Chris Fleizach  <cfleizach at apple.com>
 
         Reviewed by Darin Adler.
diff --git a/WebCore/WebCore.xcodeproj/project.pbxproj b/WebCore/WebCore.xcodeproj/project.pbxproj
index 7f8f811..4ea17c3 100644
--- a/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -664,10 +664,6 @@
 		371F53E90D2704F900ECE0D5 /* CSSUnicodeRangeValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 371F53E70D2704F900ECE0D5 /* CSSUnicodeRangeValue.h */; };
 		371F53EA0D2704F900ECE0D5 /* CSSUnicodeRangeValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 371F53E80D2704F900ECE0D5 /* CSSUnicodeRangeValue.cpp */; };
 		37202199106213C600F25C4B /* FontSmoothingMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 37202198106213C600F25C4B /* FontSmoothingMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
-		3724CA570E68A7E400DB4384 /* CoreTextController.h in Headers */ = {isa = PBXBuildFile; fileRef = 3724CA540E68A7E400DB4384 /* CoreTextController.h */; };
-		3724CA580E68A7E400DB4384 /* CoreTextController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3724CA550E68A7E400DB4384 /* CoreTextController.cpp */; };
-		3724CA590E68A7E400DB4384 /* FontMacATSUI.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3724CA560E68A7E400DB4384 /* FontMacATSUI.mm */; };
-		3724CA7E0E68B20500DB4384 /* FontMacCoreText.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3724CA7D0E68B20500DB4384 /* FontMacCoreText.cpp */; };
 		3744570F0DB05FA500AE0992 /* SVGGlyphMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 3744570E0DB05FA500AE0992 /* SVGGlyphMap.h */; };
 		3774ABA50FA21EB400AD7DE9 /* OverlapTestRequestClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 3774ABA30FA21EB400AD7DE9 /* OverlapTestRequestClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		377C4CDF1014E9F600B9AE42 /* PlaceholderDocument.h in Headers */ = {isa = PBXBuildFile; fileRef = 377C4CDD1014E9F600B9AE42 /* PlaceholderDocument.h */; };
@@ -677,6 +673,11 @@
 		37919C240B7D188600A56998 /* PositionIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = 37919C220B7D188600A56998 /* PositionIterator.h */; settings = {ATTRIBUTES = (); }; };
 		37ACCE420DA2980F0089E602 /* FontRenderingMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 37ACCE410DA2980F0089E602 /* FontRenderingMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		37ACCF690DA414E70089E602 /* FontDescription.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37ACCE620DA2AA960089E602 /* FontDescription.cpp */; };
+		37C2360B1097EDED00EF9F72 /* FontComplexTextMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37C2360A1097EDED00EF9F72 /* FontComplexTextMac.cpp */; };
+		37C236101097EE7700EF9F72 /* ComplexTextController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37C2360E1097EE7700EF9F72 /* ComplexTextController.cpp */; };
+		37C236111097EE7700EF9F72 /* ComplexTextController.h in Headers */ = {isa = PBXBuildFile; fileRef = 37C2360F1097EE7700EF9F72 /* ComplexTextController.h */; };
+		37C238211098C84200EF9F72 /* ComplexTextControllerATSUI.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37C2381F1098C84200EF9F72 /* ComplexTextControllerATSUI.cpp */; };
+		37C238221098C84200EF9F72 /* ComplexTextControllerCoreText.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 37C238201098C84200EF9F72 /* ComplexTextControllerCoreText.cpp */; };
 		37F818FD0D657606005E1F05 /* WebCoreURLResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 37F818FB0D657606005E1F05 /* WebCoreURLResponse.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		37F818FE0D657606005E1F05 /* WebCoreURLResponse.mm in Sources */ = {isa = PBXBuildFile; fileRef = 37F818FC0D657606005E1F05 /* WebCoreURLResponse.mm */; };
 		41002CCD0F66EDEF009E660D /* ScriptFunctionCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 41002CCB0F66EDEF009E660D /* ScriptFunctionCall.h */; };
@@ -5875,10 +5876,6 @@
 		371F53E70D2704F900ECE0D5 /* CSSUnicodeRangeValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSUnicodeRangeValue.h; sourceTree = "<group>"; };
 		371F53E80D2704F900ECE0D5 /* CSSUnicodeRangeValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSUnicodeRangeValue.cpp; sourceTree = "<group>"; };
 		37202198106213C600F25C4B /* FontSmoothingMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FontSmoothingMode.h; sourceTree = "<group>"; };
-		3724CA540E68A7E400DB4384 /* CoreTextController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreTextController.h; sourceTree = "<group>"; };
-		3724CA550E68A7E400DB4384 /* CoreTextController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CoreTextController.cpp; sourceTree = "<group>"; };
-		3724CA560E68A7E400DB4384 /* FontMacATSUI.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FontMacATSUI.mm; sourceTree = "<group>"; };
-		3724CA7D0E68B20500DB4384 /* FontMacCoreText.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontMacCoreText.cpp; sourceTree = "<group>"; };
 		3744570E0DB05FA500AE0992 /* SVGGlyphMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SVGGlyphMap.h; sourceTree = "<group>"; };
 		3774ABA30FA21EB400AD7DE9 /* OverlapTestRequestClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OverlapTestRequestClient.h; sourceTree = "<group>"; };
 		377C4CDD1014E9F600B9AE42 /* PlaceholderDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PlaceholderDocument.h; sourceTree = "<group>"; };
@@ -5888,6 +5885,11 @@
 		37919C220B7D188600A56998 /* PositionIterator.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PositionIterator.h; sourceTree = "<group>"; };
 		37ACCE410DA2980F0089E602 /* FontRenderingMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FontRenderingMode.h; sourceTree = "<group>"; };
 		37ACCE620DA2AA960089E602 /* FontDescription.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontDescription.cpp; sourceTree = "<group>"; };
+		37C2360A1097EDED00EF9F72 /* FontComplexTextMac.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FontComplexTextMac.cpp; sourceTree = "<group>"; };
+		37C2360E1097EE7700EF9F72 /* ComplexTextController.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ComplexTextController.cpp; sourceTree = "<group>"; };
+		37C2360F1097EE7700EF9F72 /* ComplexTextController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComplexTextController.h; sourceTree = "<group>"; };
+		37C2381F1098C84200EF9F72 /* ComplexTextControllerATSUI.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ComplexTextControllerATSUI.cpp; sourceTree = "<group>"; };
+		37C238201098C84200EF9F72 /* ComplexTextControllerCoreText.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ComplexTextControllerCoreText.cpp; sourceTree = "<group>"; };
 		37F818FB0D657606005E1F05 /* WebCoreURLResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebCoreURLResponse.h; sourceTree = "<group>"; };
 		37F818FC0D657606005E1F05 /* WebCoreURLResponse.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebCoreURLResponse.mm; sourceTree = "<group>"; };
 		41002CCB0F66EDEF009E660D /* ScriptFunctionCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScriptFunctionCall.h; sourceTree = "<group>"; };
@@ -14002,17 +14004,18 @@
 				49C7B9FE1042D38C0009D447 /* Canvas3DLayer.mm */,
 				EDE3A4FF0C7A430600956A37 /* ColorMac.h */,
 				B275354A0B053814002CE64F /* ColorMac.mm */,
-				3724CA550E68A7E400DB4384 /* CoreTextController.cpp */,
-				3724CA540E68A7E400DB4384 /* CoreTextController.h */,
+				37C2360E1097EE7700EF9F72 /* ComplexTextController.cpp */,
+				37C2360F1097EE7700EF9F72 /* ComplexTextController.h */,
+				37C2381F1098C84200EF9F72 /* ComplexTextControllerATSUI.cpp */,
+				37C238201098C84200EF9F72 /* ComplexTextControllerCoreText.cpp */,
 				B275354B0B053814002CE64F /* FloatPointMac.mm */,
 				B275354C0B053814002CE64F /* FloatRectMac.mm */,
 				B275354D0B053814002CE64F /* FloatSizeMac.mm */,
 				B2AFFC740D00A5C10030074D /* FontCacheMac.mm */,
+				37C2360A1097EDED00EF9F72 /* FontComplexTextMac.cpp */,
 				B2AFFC750D00A5C10030074D /* FontCustomPlatformData.cpp */,
 				B2AFFC760D00A5C10030074D /* FontCustomPlatformData.h */,
 				B2AFFC780D00A5C10030074D /* FontMac.mm */,
-				3724CA560E68A7E400DB4384 /* FontMacATSUI.mm */,
-				3724CA7D0E68B20500DB4384 /* FontMacCoreText.cpp */,
 				B2AFFC790D00A5C10030074D /* FontPlatformData.h */,
 				B2AFFC7A0D00A5C10030074D /* FontPlatformDataMac.mm */,
 				B2AFFC7B0D00A5C10030074D /* GlyphPageTreeNodeMac.cpp */,
@@ -15815,7 +15818,6 @@
 				D8B6152F1032495100C8554A /* Cookie.h in Headers */,
 				9352088209BD45E900F2038D /* CookieJar.h in Headers */,
 				FE6FD4880F676E5700092873 /* Coordinates.h in Headers */,
-				3724CA570E68A7E400DB4384 /* CoreTextController.h in Headers */,
 				A80E6D040A1989CA007FB8C5 /* Counter.h in Headers */,
 				BC5EB9790E82069200B25965 /* CounterContent.h in Headers */,
 				BC5EB9510E82056B00B25965 /* CounterDirectives.h in Headers */,
@@ -18068,6 +18070,7 @@
 				7553CFE8108F473F00EA281E /* TimelineRecordFactory.h in Headers */,
 				BC97E23A109144950010D361 /* HTMLAllCollection.h in Headers */,
 				BC97E413109154FA0010D361 /* JSHTMLAllCollection.h in Headers */,
+				37C236111097EE7700EF9F72 /* ComplexTextController.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -18422,6 +18425,9 @@
 				B22279620D00BF220071B782 /* ColorDistance.cpp in Sources */,
 				B27535770B053814002CE64F /* ColorMac.mm in Sources */,
 				6550B6A1099DF0270090D781 /* Comment.cpp in Sources */,
+				37C236101097EE7700EF9F72 /* ComplexTextController.cpp in Sources */,
+				37C238211098C84200EF9F72 /* ComplexTextControllerATSUI.cpp in Sources */,
+				37C238221098C84200EF9F72 /* ComplexTextControllerCoreText.cpp in Sources */,
 				316FE1150E6E1DA700BF6088 /* CompositeAnimation.cpp in Sources */,
 				93309DDC099E64920056E581 /* CompositeEditCommand.cpp in Sources */,
 				BC0B36A40CD3C67C00AC7EB5 /* Console.cpp in Sources */,
@@ -18434,7 +18440,6 @@
 				06027CB30B1CC03D00884B2D /* ContextMenuItemMac.mm in Sources */,
 				93B6A0EA0B0BCA8400F5027A /* ContextMenuMac.mm in Sources */,
 				9352087709BD453400F2038D /* CookieJar.mm in Sources */,
-				3724CA580E68A7E400DB4384 /* CoreTextController.cpp in Sources */,
 				BC5EB9500E82056B00B25965 /* CounterDirectives.cpp in Sources */,
 				9392F1500AD1862300691BD4 /* CounterNode.cpp in Sources */,
 				D0B0556909C6700100307E43 /* CreateLinkCommand.cpp in Sources */,
@@ -18845,6 +18850,7 @@
 				B2C3DA600D006CD600EF6F26 /* Font.cpp in Sources */,
 				B2C3DA620D006CD600EF6F26 /* FontCache.cpp in Sources */,
 				B2AFFC7C0D00A5C10030074D /* FontCacheMac.mm in Sources */,
+				37C2360B1097EDED00EF9F72 /* FontComplexTextMac.cpp in Sources */,
 				B2AFFC7D0D00A5C10030074D /* FontCustomPlatformData.cpp in Sources */,
 				371F4F410D25B9AF00ECE0D5 /* FontData.cpp in Sources */,
 				37ACCF690DA414E70089E602 /* FontDescription.cpp in Sources */,
@@ -18853,8 +18859,6 @@
 				A80E6CEC0A1989CA007FB8C5 /* FontFamilyValue.cpp in Sources */,
 				72626E020EF022FE00A07E20 /* FontFastPath.cpp in Sources */,
 				B2AFFC800D00A5C10030074D /* FontMac.mm in Sources */,
-				3724CA590E68A7E400DB4384 /* FontMacATSUI.mm in Sources */,
-				3724CA7E0E68B20500DB4384 /* FontMacCoreText.cpp in Sources */,
 				B2AFFC820D00A5C10030074D /* FontPlatformDataMac.mm in Sources */,
 				A80E6CF10A1989CA007FB8C5 /* FontValue.cpp in Sources */,
 				D05CED290A40BB2C00C5AF38 /* FormatBlockCommand.cpp in Sources */,
diff --git a/WebCore/platform/graphics/mac/ComplexTextController.cpp b/WebCore/platform/graphics/mac/ComplexTextController.cpp
new file mode 100644
index 0000000..826496b
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ComplexTextController.cpp
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 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 "ComplexTextController.h"
+
+#include "CharacterNames.h"
+#include "Font.h"
+#include "TextBreakIterator.h"
+
+namespace WebCore {
+
+static inline CGFloat roundCGFloat(CGFloat f)
+{
+    if (sizeof(CGFloat) == sizeof(float))
+        return roundf(static_cast<float>(f));
+    return static_cast<CGFloat>(round(f));
+}
+
+static inline CGFloat ceilCGFloat(CGFloat f)
+{
+    if (sizeof(CGFloat) == sizeof(float))
+        return ceilf(static_cast<float>(f));
+    return static_cast<CGFloat>(ceil(f));
+}
+
+ComplexTextController::ComplexTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts)
+    : m_font(*font)
+    , m_run(run)
+    , m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
+    , m_currentCharacter(0)
+    , m_end(run.length())
+    , m_totalWidth(0)
+    , m_runWidthSoFar(0)
+    , m_numGlyphsSoFar(0)
+    , m_currentRun(0)
+    , m_glyphInCurrentRun(0)
+    , m_finalRoundingWidth(0)
+    , m_fallbackFonts(fallbackFonts)
+    , m_lastRoundingGlyph(0)
+{
+    m_padding = m_run.padding();
+    if (!m_padding)
+        m_padPerSpace = 0;
+    else {
+        float numSpaces = 0;
+        for (int s = 0; s < m_run.length(); s++)
+            if (Font::treatAsSpace(m_run[s]))
+                numSpaces++;
+
+        if (numSpaces == 0)
+            m_padPerSpace = 0;
+        else
+            m_padPerSpace = ceilf(m_run.padding() / numSpaces);
+    }
+
+    collectComplexTextRuns();
+    adjustGlyphsAndAdvances();
+}
+
+int ComplexTextController::offsetForPosition(int h, bool includePartialGlyphs)
+{
+    // FIXME: For positions occurring within a ligature, we should return the closest "ligature caret" or
+    // approximate it by dividing the width of the ligature by the number of characters it encompasses.
+    // However, Core Text does not expose a low-level API for directly finding
+    // out how many characters a ligature encompasses (the "attachment count").
+    if (h >= m_totalWidth)
+        return m_run.ltr() ? m_end : 0;
+    if (h < 0)
+        return m_run.ltr() ? 0 : m_end;
+
+    CGFloat x = h;
+
+    size_t runCount = m_complexTextRuns.size();
+    size_t offsetIntoAdjustedGlyphs = 0;
+
+    for (size_t r = 0; r < runCount; ++r) {
+        const ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
+        for (unsigned j = 0; j < complexTextRun.glyphCount(); ++j) {
+            CGFloat adjustedAdvance = m_adjustedAdvances[offsetIntoAdjustedGlyphs + j].width;
+            if (x <= adjustedAdvance) {
+                CFIndex hitIndex = complexTextRun.indexAt(j);
+                int stringLength = complexTextRun.stringLength();
+                TextBreakIterator* cursorPositionIterator = cursorMovementIterator(complexTextRun.characters(), stringLength);
+                int clusterStart;
+                if (isTextBreak(cursorPositionIterator, hitIndex))
+                    clusterStart = hitIndex;
+                else {
+                    clusterStart = textBreakPreceding(cursorPositionIterator, hitIndex);
+                    if (clusterStart == TextBreakDone)
+                        clusterStart = 0;
+                }
+
+                if (!includePartialGlyphs)
+                    return complexTextRun.stringLocation() + clusterStart;
+
+                int clusterEnd = textBreakFollowing(cursorPositionIterator, hitIndex);
+                if (clusterEnd == TextBreakDone)
+                    clusterEnd = stringLength;
+
+                CGFloat clusterWidth = adjustedAdvance;
+                // FIXME: The search stops at the boundaries of complexTextRun. In theory, it should go on into neighboring ComplexTextRuns
+                // derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no
+                // reordering and on font fallback should occur within a CTLine.
+                if (clusterEnd - clusterStart > 1) {
+                    int firstGlyphBeforeCluster = j - 1;
+                    while (firstGlyphBeforeCluster >= 0 && complexTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
+                        CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
+                        clusterWidth += width;
+                        x += width;
+                        firstGlyphBeforeCluster--;
+                    }
+                    unsigned firstGlyphAfterCluster = j + 1;
+                    while (firstGlyphAfterCluster < complexTextRun.glyphCount() && complexTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && complexTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) {
+                        clusterWidth += m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width;
+                        firstGlyphAfterCluster++;
+                    }
+                }
+                if (x <= clusterWidth / 2)
+                    return complexTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd);
+                else
+                    return complexTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart);
+            }
+            x -= adjustedAdvance;
+        }
+        offsetIntoAdjustedGlyphs += complexTextRun.glyphCount();
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+void ComplexTextController::collectComplexTextRuns()
+{
+    if (!m_end)
+        return;
+
+    // We break up glyph run generation for the string by FontData and (if needed) the use of small caps.
+    const UChar* cp = m_run.characters();
+    bool hasTrailingSoftHyphen = m_run[m_end - 1] == softHyphen;
+
+    if (m_font.isSmallCaps() || hasTrailingSoftHyphen)
+        m_smallCapsBuffer.resize(m_end);
+
+    unsigned indexOfFontTransition = m_run.rtl() ? m_end - 1 : 0;
+    const UChar* curr = m_run.rtl() ? cp + m_end  - 1 : cp;
+    const UChar* end = m_run.rtl() ? cp - 1 : cp + m_end;
+
+    // FIXME: Using HYPHEN-MINUS rather than HYPHEN because Times has a HYPHEN-MINUS glyph that looks like its
+    // SOFT-HYPHEN glyph, and has no HYPHEN glyph.
+    static const UChar hyphen = '-';
+
+    if (hasTrailingSoftHyphen && m_run.rtl()) {
+        collectComplexTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
+        indexOfFontTransition--;
+        curr--;
+    }
+
+    GlyphData glyphData;
+    GlyphData nextGlyphData;
+
+    bool isSurrogate = U16_IS_SURROGATE(*curr);
+    if (isSurrogate) {
+        if (m_run.ltr()) {
+            if (!U16_IS_SURROGATE_LEAD(curr[0]) || curr + 1 == end || !U16_IS_TRAIL(curr[1]))
+                return;
+            nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[0], curr[1]), false);
+        } else {
+            if (!U16_IS_TRAIL(curr[0]) || curr -1 == end || !U16_IS_SURROGATE_LEAD(curr[-1]))
+                return;
+            nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[-1], curr[0]), false);
+        }
+    } else
+        nextGlyphData = m_font.glyphDataForCharacter(*curr, false);
+
+    UChar newC = 0;
+
+    bool isSmallCaps;
+    bool nextIsSmallCaps = !isSurrogate && m_font.isSmallCaps() && !(U_GET_GC_MASK(*curr) & U_GC_M_MASK) && (newC = u_toupper(*curr)) != *curr;
+
+    if (nextIsSmallCaps)
+        m_smallCapsBuffer[curr - cp] = newC;
+
+    while (true) {
+        curr = m_run.rtl() ? curr - (isSurrogate ? 2 : 1) : curr + (isSurrogate ? 2 : 1);
+        if (curr == end)
+            break;
+
+        glyphData = nextGlyphData;
+        isSmallCaps = nextIsSmallCaps;
+        int index = curr - cp;
+        isSurrogate = U16_IS_SURROGATE(*curr);
+        UChar c = *curr;
+        bool forceSmallCaps = !isSurrogate && isSmallCaps && (U_GET_GC_MASK(c) & U_GC_M_MASK);
+        if (isSurrogate) {
+            if (m_run.ltr()) {
+                if (!U16_IS_SURROGATE_LEAD(curr[0]) || curr + 1 == end || !U16_IS_TRAIL(curr[1]))
+                    return;
+                nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[0], curr[1]), false);
+            } else {
+                if (!U16_IS_TRAIL(curr[0]) || curr -1 == end || !U16_IS_SURROGATE_LEAD(curr[-1]))
+                    return;
+                nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[-1], curr[0]), false);
+            }
+        } else
+            nextGlyphData = m_font.glyphDataForCharacter(*curr, false, forceSmallCaps);
+
+        if (!isSurrogate && m_font.isSmallCaps()) {
+            nextIsSmallCaps = forceSmallCaps || (newC = u_toupper(c)) != c;
+            if (nextIsSmallCaps)
+                m_smallCapsBuffer[index] = forceSmallCaps ? c : newC;
+        }
+
+        if (nextGlyphData.fontData != glyphData.fontData || nextIsSmallCaps != isSmallCaps || !nextGlyphData.glyph != !glyphData.glyph) {
+            int itemStart = m_run.rtl() ? index + 1 : indexOfFontTransition;
+            int itemLength = m_run.rtl() ? indexOfFontTransition - index : index - indexOfFontTransition;
+            collectComplexTextRunsForCharacters((isSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, glyphData.glyph ? glyphData.fontData : 0);
+            indexOfFontTransition = index;
+        }
+    }
+
+    int itemLength = m_run.rtl() ? indexOfFontTransition + 1 : m_end - indexOfFontTransition - (hasTrailingSoftHyphen ? 1 : 0);
+    if (itemLength) {
+        int itemStart = m_run.rtl() ? 0 : indexOfFontTransition;
+        collectComplexTextRunsForCharacters((nextIsSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, nextGlyphData.glyph ? nextGlyphData.fontData : 0);
+    }
+
+    if (hasTrailingSoftHyphen && m_run.ltr())
+        collectComplexTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
+}
+
+void ComplexTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
+{
+    // FIXME: For offsets falling inside a ligature, we should advance only as far as the appropriate "ligature caret"
+    // or divide the width of the ligature by the number of offsets it encompasses and make an advance proportional
+    // to the offsets into the ligature. However, Core Text does not expose a low-level API for
+    // directly finding out how many characters a ligature encompasses (the "attachment count").
+    if (static_cast<int>(offset) > m_end)
+        offset = m_end;
+
+    if (offset <= m_currentCharacter)
+        return;
+
+    m_currentCharacter = offset;
+
+    size_t runCount = m_complexTextRuns.size();
+
+    bool ltr = m_run.ltr();
+
+    unsigned k = ltr ? m_numGlyphsSoFar : m_adjustedGlyphs.size() - 1 - m_numGlyphsSoFar;
+    while (m_currentRun < runCount) {
+        const ComplexTextRun& complexTextRun = *m_complexTextRuns[ltr ? m_currentRun : runCount - 1 - m_currentRun];
+        size_t glyphCount = complexTextRun.glyphCount();
+        unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun;
+        while (m_glyphInCurrentRun < glyphCount) {
+            if (complexTextRun.indexAt(g) + complexTextRun.stringLocation() >= m_currentCharacter)
+                return;
+            CGSize adjustedAdvance = m_adjustedAdvances[k];
+            if (glyphBuffer)
+                glyphBuffer->add(m_adjustedGlyphs[k], complexTextRun.fontData(), adjustedAdvance);
+            m_runWidthSoFar += adjustedAdvance.width;
+            m_numGlyphsSoFar++;
+            m_glyphInCurrentRun++;
+            if (ltr) {
+                g++;
+                k++;
+            } else {
+                g--;
+                k--;
+            }
+        }
+        m_currentRun++;
+        m_glyphInCurrentRun = 0;
+    }
+    if (!ltr && m_numGlyphsSoFar == m_adjustedAdvances.size())
+        m_runWidthSoFar += m_finalRoundingWidth;
+}
+
+void ComplexTextController::adjustGlyphsAndAdvances()
+{
+    size_t runCount = m_complexTextRuns.size();
+    for (size_t r = 0; r < runCount; ++r) {
+        const ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
+        unsigned glyphCount = complexTextRun.glyphCount();
+        const SimpleFontData* fontData = complexTextRun.fontData();
+
+        const CGGlyph* glyphs = complexTextRun.glyphs();
+        const CGSize* advances = complexTextRun.advances();
+
+        bool lastRun = r + 1 == runCount;
+        const UChar* cp = complexTextRun.characters();
+        CGFloat roundedSpaceWidth = roundCGFloat(fontData->spaceWidth());
+        bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances();
+        bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_padding) && !m_run.spacingDisabled();
+
+
+        for (unsigned i = 0; i < glyphCount; i++) {
+            CFIndex characterIndex = complexTextRun.indexAt(i);
+            UChar ch = *(cp + characterIndex);
+            bool lastGlyph = lastRun && i + 1 == glyphCount;
+            UChar nextCh;
+            if (lastGlyph)
+                nextCh = ' ';
+            else if (i + 1 < glyphCount)
+                nextCh = *(cp + complexTextRun.indexAt(i + 1));
+            else
+                nextCh = *(m_complexTextRuns[r + 1]->characters() + m_complexTextRuns[r + 1]->indexAt(0));
+
+            bool treatAsSpace = Font::treatAsSpace(ch);
+            CGGlyph glyph = treatAsSpace ? fontData->spaceGlyph() : glyphs[i];
+            CGSize advance = treatAsSpace ? CGSizeMake(fontData->spaceWidth(), advances[i].height) : advances[i];
+
+            if (ch == '\t' && m_run.allowTabs()) {
+                float tabWidth = m_font.tabWidth();
+                advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth, tabWidth);
+            } else if (ch == zeroWidthSpace || Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) {
+                advance.width = 0;
+                glyph = fontData->spaceGlyph();
+            }
+
+            float roundedAdvanceWidth = roundf(advance.width);
+            if (roundsAdvances)
+                advance.width = roundedAdvanceWidth;
+
+            advance.width += fontData->syntheticBoldOffset();
+
+            // We special case spaces in two ways when applying word rounding.
+            // First, we round spaces to an adjusted width in all fonts.
+            // Second, in fixed-pitch fonts we ensure that all glyphs that
+            // match the width of the space glyph have the same width as the space glyph.
+            if (roundedAdvanceWidth == roundedSpaceWidth && (fontData->pitch() == FixedPitch || glyph == fontData->spaceGlyph()) && m_run.applyWordRounding())
+                advance.width = fontData->adjustedSpaceWidth();
+
+            if (hasExtraSpacing) {
+                // If we're a glyph with an advance, go ahead and add in letter-spacing.
+                // That way we weed out zero width lurkers.  This behavior matches the fast text code path.
+                if (advance.width && m_font.letterSpacing())
+                    advance.width += m_font.letterSpacing();
+
+                // Handle justification and word-spacing.
+                if (glyph == fontData->spaceGlyph()) {
+                    // Account for padding. WebCore uses space padding to justify text.
+                    // We distribute the specified padding over the available spaces in the run.
+                    if (m_padding) {
+                        // Use leftover padding if not evenly divisible by number of spaces.
+                        if (m_padding < m_padPerSpace) {
+                            advance.width += m_padding;
+                            m_padding = 0;
+                        } else {
+                            advance.width += m_padPerSpace;
+                            m_padding -= m_padPerSpace;
+                        }
+                    }
+
+                    // Account for word-spacing.
+                    if (treatAsSpace && characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing())
+                        advance.width += m_font.wordSpacing();
+                }
+            }
+
+            // Deal with the float/integer impedance mismatch between CG and WebCore. "Words" (characters 
+            // followed by a character defined by isRoundingHackCharacter()) are always an integer width.
+            // We adjust the width of the last character of a "word" to ensure an integer width.
+            // Force characters that are used to determine word boundaries for the rounding hack
+            // to be integer width, so the following words will start on an integer boundary.
+            if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(ch))
+                advance.width = ceilCGFloat(advance.width);
+
+            // Check to see if the next character is a "rounding hack character", if so, adjust the
+            // width so that the total run width will be on an integer boundary.
+            if (m_run.applyWordRounding() && !lastGlyph && Font::isRoundingHackCharacter(nextCh) || m_run.applyRunRounding() && lastGlyph) {
+                CGFloat totalWidth = m_totalWidth + advance.width;
+                CGFloat extraWidth = ceilCGFloat(totalWidth) - totalWidth;
+                if (m_run.ltr())
+                    advance.width += extraWidth;
+                else {
+                    m_totalWidth += extraWidth;
+                    if (m_lastRoundingGlyph)
+                        m_adjustedAdvances[m_lastRoundingGlyph - 1].width += extraWidth;
+                    else
+                        m_finalRoundingWidth = extraWidth;
+                    m_lastRoundingGlyph = m_adjustedAdvances.size() + 1;
+                }
+            }
+
+            m_totalWidth += advance.width;
+            advance.height *= -1;
+            m_adjustedAdvances.append(advance);
+            m_adjustedGlyphs.append(glyph);
+        }
+    }
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/mac/ComplexTextController.h b/WebCore/platform/graphics/mac/ComplexTextController.h
new file mode 100644
index 0000000..7e4a439
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ComplexTextController.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 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.
+ */
+
+#ifndef ComplexTextController_h
+#define ComplexTextController_h
+
+#include "GlyphBuffer.h"
+#include <wtf/HashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RetainPtr.h>
+#include <wtf/Vector.h>
+#include <wtf/unicode/Unicode.h>
+
+namespace WebCore {
+
+class Font;
+class SimpleFontData;
+class TextRun;
+
+class ComplexTextController {
+public:
+    ComplexTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0);
+
+    // Advance and emit glyphs up to the specified character.
+    void advance(unsigned to, GlyphBuffer* = 0);
+
+    // Compute the character offset for a given x coordinate.
+    int offsetForPosition(int x, bool includePartialGlyphs);
+
+    // Returns the width of everything we've consumed so far.
+    float runWidthSoFar() const { return m_runWidthSoFar; }
+
+    float totalWidth() const { return m_totalWidth; }
+
+    // Extra width to the left of the leftmost glyph.
+    float finalRoundingWidth() const { return m_finalRoundingWidth; }
+
+private:
+    class ComplexTextRun : public RefCounted<ComplexTextRun> {
+    public:
+#if USE(CORE_TEXT)
+        static PassRefPtr<ComplexTextRun> create(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength)
+        {
+            return adoptRef(new ComplexTextRun(ctRun, fontData, characters, stringLocation, stringLength));
+        }
+#elif USE(ATSUI)
+        static PassRefPtr<ComplexTextRun> create(ATSUTextLayout atsuTextLayout, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride)
+        {
+            return adoptRef(new ComplexTextRun(atsuTextLayout, fontData, characters, stringLocation, stringLength, ltr, directionalOverride));
+        }
+#endif
+        static PassRefPtr<ComplexTextRun> create(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
+        {
+            return adoptRef(new ComplexTextRun(fontData, characters, stringLocation, stringLength, ltr));
+        }
+
+        unsigned glyphCount() const { return m_glyphCount; }
+        const SimpleFontData* fontData() const { return m_fontData; }
+        const UChar* characters() const { return m_characters; }
+        unsigned stringLocation() const { return m_stringLocation; }
+        size_t stringLength() const { return m_stringLength; }
+        CFIndex indexAt(size_t i) const { return m_indices[i]; }
+        const CGGlyph* glyphs() const { return m_glyphs; }
+        const CGSize* advances() const { return m_advances; }
+
+    private:
+#if USE(CORE_TEXT)
+        ComplexTextRun(CTRunRef, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength);
+#elif USE(ATSUI)
+        ComplexTextRun(ATSUTextLayout, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride);
+#endif
+        ComplexTextRun(const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr);
+
+#if USE(ATSUI)
+        static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef, URefCon, void*, ATSULayoutOperationCallbackStatus*);
+#endif
+
+#if USE(CORE_TEXT)
+        RetainPtr<CTRunRef> m_CTRun;
+#endif
+        unsigned m_glyphCount;
+        const SimpleFontData* m_fontData;
+        const UChar* m_characters;
+        unsigned m_stringLocation;
+        size_t m_stringLength;
+#if USE(CORE_TEXT)
+        RetainPtr<CFMutableDataRef> m_indicesData;
+        const CFIndex* m_indices;
+#elif USE(ATSUI)
+        Vector<CFIndex, 64> m_indices;
+#endif
+        Vector<CGGlyph, 64> m_glyphsVector;
+        const CGGlyph* m_glyphs;
+        Vector<CGSize, 64> m_advancesVector;
+        const CGSize* m_advances;
+        bool m_directionalOverride;
+    };
+
+    void collectComplexTextRuns();
+    void collectComplexTextRunsForCharacters(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*);
+    void adjustGlyphsAndAdvances();
+
+    const Font& m_font;
+    const TextRun& m_run;
+    bool m_mayUseNaturalWritingDirection;
+
+    Vector<UChar, 256> m_smallCapsBuffer;
+
+    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;
+
+    float m_runWidthSoFar;
+    unsigned m_numGlyphsSoFar;
+    size_t m_currentRun;
+    unsigned m_glyphInCurrentRun;
+    float m_finalRoundingWidth;
+    float m_padding;
+    float m_padPerSpace;
+
+    HashSet<const SimpleFontData*>* m_fallbackFonts;
+
+    unsigned m_lastRoundingGlyph;
+};
+
+} // namespace WebCore
+
+#endif // ComplexTextController_h
diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
new file mode 100644
index 0000000..7da1737
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ComplexTextControllerATSUI.cpp
@@ -0,0 +1,323 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll at kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto at kde.org)
+ *           (C) 2000 Dirk Mueller (mueller at kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "ComplexTextController.h"
+
+#if USE(ATSUI)
+
+#include "CharacterNames.h"
+#include "Font.h"
+#include "ShapeArabic.h"
+
+using namespace WTF::Unicode;
+
+namespace WebCore {
+
+OSStatus ComplexTextController::ComplexTextRun::overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef atsuLineRef, URefCon refCon, void*, ATSULayoutOperationCallbackStatus* callbackStatus)
+{
+    ComplexTextRun* complexTextRun = reinterpret_cast<ComplexTextRun*>(refCon);
+    OSStatus status;
+    ItemCount count;
+    ATSLayoutRecord *layoutRecords;
+
+    status = ATSUDirectGetLayoutDataArrayPtrFromLineRef(atsuLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, true, reinterpret_cast<void**>(&layoutRecords), &count);
+    if (status != noErr) {
+        *callbackStatus = kATSULayoutOperationCallbackStatusContinue;
+        return status;
+    }
+
+    count--;
+    ItemCount j = 0;
+    CFIndex indexOffset = 0;
+
+    if (complexTextRun->m_directionalOverride) {
+        j++;
+        count -= 2;
+        indexOffset = -1;
+    }
+
+    complexTextRun->m_glyphCount = count;
+    complexTextRun->m_glyphsVector.grow(count);
+    complexTextRun->m_glyphs = complexTextRun->m_glyphsVector.data();
+    complexTextRun->m_advancesVector.grow(count);
+    complexTextRun->m_advances = complexTextRun->m_advancesVector.data();
+    complexTextRun->m_indices.grow(count);
+
+    CGFloat lastX = FixedToFloat(layoutRecords[j].realPos);
+
+    for (ItemCount i = 0; i < count; ++i, ++j) {
+        complexTextRun->m_glyphsVector[i] = layoutRecords[j].glyphID;
+        complexTextRun->m_indices[i] = layoutRecords[j].originalOffset / 2 + indexOffset;
+        CGFloat x = FixedToFloat(layoutRecords[j + 1].realPos);
+        complexTextRun->m_advancesVector[i] = CGSizeMake(x - lastX, 0);
+        lastX = x;
+    }
+
+    status = ATSUDirectReleaseLayoutDataArrayPtr(atsuLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, reinterpret_cast<void**>(&layoutRecords));
+    *callbackStatus = kATSULayoutOperationCallbackStatusContinue;
+    return noErr;
+}
+
+static inline bool isArabicLamWithAlefLigature(UChar c)
+{
+    return c >= 0xfef5 && c <= 0xfefc;
+}
+
+static void shapeArabic(const UChar* source, UChar* dest, unsigned totalLength)
+{
+    unsigned shapingStart = 0;
+    while (shapingStart < totalLength) {
+        unsigned shapingEnd;
+        // We do not want to pass a Lam with Alef ligature followed by a space to the shaper,
+        // since we want to be able to identify this sequence as the result of shaping a Lam
+        // followed by an Alef and padding with a space.
+        bool foundLigatureSpace = false;
+        for (shapingEnd = shapingStart; !foundLigatureSpace && shapingEnd < totalLength - 1; ++shapingEnd)
+            foundLigatureSpace = isArabicLamWithAlefLigature(source[shapingEnd]) && source[shapingEnd + 1] == ' ';
+        shapingEnd++;
+
+        UErrorCode shapingError = U_ZERO_ERROR;
+        unsigned charsWritten = shapeArabic(source + shapingStart, shapingEnd - shapingStart, dest + shapingStart, shapingEnd - shapingStart, U_SHAPE_LETTERS_SHAPE | U_SHAPE_LENGTH_FIXED_SPACES_NEAR, &shapingError);
+
+        if (U_SUCCESS(shapingError) && charsWritten == shapingEnd - shapingStart) {
+            for (unsigned j = shapingStart; j < shapingEnd - 1; ++j) {
+                if (isArabicLamWithAlefLigature(dest[j]) && dest[j + 1] == ' ')
+                    dest[++j] = zeroWidthSpace;
+            }
+            if (foundLigatureSpace) {
+                dest[shapingEnd] = ' ';
+                shapingEnd++;
+            } else if (isArabicLamWithAlefLigature(dest[shapingEnd - 1])) {
+                // u_shapeArabic quirk: if the last two characters in the source string are a Lam and an Alef,
+                // the space is put at the beginning of the string, despite U_SHAPE_LENGTH_FIXED_SPACES_NEAR.
+                ASSERT(dest[shapingStart] == ' ');
+                dest[shapingStart] = zeroWidthSpace;
+            }
+        } else {
+            // Something went wrong. Abandon shaping and just copy the rest of the buffer.
+            LOG_ERROR("u_shapeArabic failed(%d)", shapingError);
+            shapingEnd = totalLength;
+            memcpy(dest + shapingStart, source + shapingStart, (shapingEnd - shapingStart) * sizeof(UChar));
+        }
+        shapingStart = shapingEnd;
+    }
+}
+
+ComplexTextController::ComplexTextRun::ComplexTextRun(ATSUTextLayout atsuTextLayout, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr, bool directionalOverride)
+    : m_fontData(fontData)
+    , m_characters(characters)
+    , m_stringLocation(stringLocation)
+    , m_stringLength(stringLength)
+    , m_directionalOverride(directionalOverride)
+{
+    OSStatus status;
+
+    status = ATSUSetTextLayoutRefCon(atsuTextLayout, reinterpret_cast<URefCon>(this));
+
+    ATSLineLayoutOptions lineLayoutOptions = kATSLineKeepSpacesOutOfMargin | kATSLineHasNoHangers;
+
+    Boolean rtl = !ltr;
+
+    Vector<UChar, 256> substituteCharacters;
+    bool shouldCheckForMirroring = !ltr && !fontData->m_ATSUMirrors;
+    bool shouldCheckForArabic = !fontData->shapesArabic();
+    bool shouldShapeArabic = false;
+
+    bool mirrored = false;
+    for (size_t i = 0; i < stringLength; ++i) {
+        if (shouldCheckForMirroring) {
+            UChar mirroredChar = u_charMirror(characters[i]);
+            if (mirroredChar != characters[i]) {
+                if (!mirrored) {
+                    mirrored = true;
+                    substituteCharacters.grow(stringLength);
+                    memcpy(substituteCharacters.data(), characters, stringLength * sizeof(UChar));
+                    ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
+                }
+                substituteCharacters[i] = mirroredChar;
+            }
+        }
+        if (shouldCheckForArabic && isArabicChar(characters[i])) {
+            shouldCheckForArabic = false;
+            shouldShapeArabic = true;
+        }
+    }
+
+    if (shouldShapeArabic) {
+        Vector<UChar, 256> shapedArabic(stringLength);
+        shapeArabic(substituteCharacters.isEmpty() ? characters : substituteCharacters.data(), shapedArabic.data(), stringLength);
+        substituteCharacters.swap(shapedArabic);
+        ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
+    }
+
+    if (directionalOverride) {
+        UChar override = ltr ? leftToRightOverride : rightToLeftOverride;
+        if (substituteCharacters.isEmpty()) {
+            substituteCharacters.grow(stringLength + 2);
+            substituteCharacters[0] = override;
+            memcpy(substituteCharacters.data() + 1, characters, stringLength * sizeof(UChar));
+            substituteCharacters[stringLength + 1] = popDirectionalFormatting;
+            ATSUTextMoved(atsuTextLayout, substituteCharacters.data());
+        } else {
+            substituteCharacters.prepend(override);
+            substituteCharacters.append(popDirectionalFormatting);
+        }
+        ATSUTextInserted(atsuTextLayout, 0, 2);
+    }
+
+    ATSULayoutOperationOverrideSpecifier overrideSpecifier;
+    overrideSpecifier.operationSelector = kATSULayoutOperationPostLayoutAdjustment;
+    overrideSpecifier.overrideUPP = overrideLayoutOperation;
+
+    ATSUAttributeTag tags[] = { kATSULineLayoutOptionsTag, kATSULineDirectionTag, kATSULayoutOperationOverrideTag };
+    ByteCount sizes[] = { sizeof(ATSLineLayoutOptions), sizeof(Boolean), sizeof(ATSULayoutOperationOverrideSpecifier) };
+    ATSUAttributeValuePtr values[] = { &lineLayoutOptions, &rtl, &overrideSpecifier };
+
+    status = ATSUSetLayoutControls(atsuTextLayout, 3, tags, sizes, values);
+
+    ItemCount boundsCount;
+    status = ATSUGetGlyphBounds(atsuTextLayout, 0, 0, 0, m_stringLength, kATSUseFractionalOrigins, 0, 0, &boundsCount);
+
+    status = ATSUDisposeTextLayout(atsuTextLayout);
+}
+
+ComplexTextController::ComplexTextRun::ComplexTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
+    : m_fontData(fontData)
+    , m_characters(characters)
+    , m_stringLocation(stringLocation)
+    , m_stringLength(stringLength)
+{
+    m_indices.reserveCapacity(stringLength);
+    unsigned r = 0;
+    while (r < stringLength) {
+        m_indices.uncheckedAppend(r);
+        if (U_IS_SURROGATE(characters[r])) {
+            ASSERT(r + 1 < stringLength);
+            ASSERT(U_IS_SURROGATE_LEAD(characters[r]));
+            ASSERT(U_IS_TRAIL(characters[r + 1]));
+            r += 2;
+        } else
+            r++;
+    }
+    m_glyphCount = m_indices.size();
+    if (!ltr) {
+        for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end)
+            std::swap(m_indices[r], m_indices[end]);
+    }
+
+    m_glyphsVector.fill(0, m_glyphCount);
+    m_glyphs = m_glyphsVector.data();
+    m_advancesVector.fill(CGSizeMake(fontData->widthForGlyph(0), 0), m_glyphCount);
+    m_advances = m_advancesVector.data();
+}
+
+static bool fontHasMirroringInfo(ATSUFontID fontID)
+{
+    ByteCount propTableSize;
+    OSStatus status = ATSFontGetTable(fontID, 'prop', 0, 0, 0, &propTableSize);
+    if (status == noErr)    // naively assume that if a 'prop' table exists then it contains mirroring info
+        return true;
+    else if (status != kATSInvalidFontTableAccess) // anything other than a missing table is logged as an error
+        LOG_ERROR("ATSFontGetTable failed (%ld)", status);
+
+    return false;
+}
+
+static void disableLigatures(const SimpleFontData* fontData, TextRenderingMode textMode)
+{
+    // Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are
+    // in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example.
+    // See bugzilla 5166.
+    if (textMode == OptimizeLegibility || textMode == GeometricPrecision || fontData->platformData().allowsLigatures())
+        return;
+
+    ATSUFontFeatureType featureTypes[] = { kLigaturesType };
+    ATSUFontFeatureSelector featureSelectors[] = { kCommonLigaturesOffSelector };
+    OSStatus status = ATSUSetFontFeatures(fontData->m_ATSUStyle, 1, featureTypes, featureSelectors);
+    if (status != noErr)
+        LOG_ERROR("ATSUSetFontFeatures failed (%ld) -- ligatures remain enabled", status);
+}
+
+static void initializeATSUStyle(const SimpleFontData* fontData, TextRenderingMode textMode)
+{
+    if (fontData->m_ATSUStyleInitialized)
+        return;
+
+    ATSUFontID fontID = fontData->platformData().m_atsuFontID;
+    if (!fontID) {
+        LOG_ERROR("unable to get ATSUFontID for %p", fontData->platformData().font());
+        return;
+    }
+
+    OSStatus status = ATSUCreateStyle(&fontData->m_ATSUStyle);
+    if (status != noErr)
+        LOG_ERROR("ATSUCreateStyle failed (%ld)", status);
+
+    Fixed fontSize = FloatToFixed(fontData->platformData().m_size);
+    Fract kerningInhibitFactor = FloatToFract(1);
+    static CGAffineTransform verticalFlip = CGAffineTransformMakeScale(1, -1);
+
+    ByteCount styleSizes[4] = { sizeof(fontSize), sizeof(fontID), sizeof(verticalFlip), sizeof(kerningInhibitFactor) };
+    ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag };
+    ATSUAttributeValuePtr styleValues[4] = { &fontSize, &fontID, &verticalFlip, &kerningInhibitFactor };
+
+    bool allowKerning = textMode == OptimizeLegibility || textMode == GeometricPrecision;
+    status = ATSUSetAttributes(fontData->m_ATSUStyle, allowKerning ? 3 : 4, styleTags, styleSizes, styleValues);
+    if (status != noErr)
+        LOG_ERROR("ATSUSetAttributes failed (%ld)", status);
+
+    fontData->m_ATSUMirrors = fontHasMirroringInfo(fontID);
+
+    disableLigatures(fontData, textMode);
+
+    fontData->m_ATSUStyleInitialized = true;
+}
+
+void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData)
+{
+    if (!fontData) {
+        // Create a run of missing glyphs from the primary font.
+        m_complexTextRuns.append(ComplexTextRun::create(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));
+        return;
+    }
+
+    if (m_fallbackFonts && fontData != m_font.primaryFont())
+        m_fallbackFonts->add(fontData);
+
+    initializeATSUStyle(fontData, m_font.fontDescription().textRenderingMode());
+
+    OSStatus status;
+    ATSUTextLayout atsuTextLayout;
+    UniCharCount runLength = length;
+
+    status = ATSUCreateTextLayoutWithTextPtr(cp, 0, length, length, 1, &runLength, &fontData->m_ATSUStyle, &atsuTextLayout);
+    if (status != noErr) {
+        LOG_ERROR("ATSUCreateTextLayoutWithTextPtr failed with error %ld", status);
+        return;
+    }
+    m_complexTextRuns.append(ComplexTextRun::create(atsuTextLayout, fontData, cp, stringLocation, length, m_run.ltr(), m_run.directionalOverride()));
+}
+
+} // namespace WebCore
+
+#endif // USE(ATSUI)
diff --git a/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
new file mode 100644
index 0000000..c9daf84
--- /dev/null
+++ b/WebCore/platform/graphics/mac/ComplexTextControllerCoreText.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 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 "ComplexTextController.h"
+
+#if USE(CORE_TEXT)
+
+#include "Font.h"
+
+namespace WebCore {
+
+ComplexTextController::ComplexTextRun::ComplexTextRun(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength)
+    : m_CTRun(ctRun)
+    , m_fontData(fontData)
+    , m_characters(characters)
+    , m_stringLocation(stringLocation)
+    , m_stringLength(stringLength)
+{
+    m_glyphCount = CTRunGetGlyphCount(m_CTRun.get());
+    m_indices = CTRunGetStringIndicesPtr(m_CTRun.get());
+    if (!m_indices) {
+        m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
+        CFDataIncreaseLength(m_indicesData.get(), m_glyphCount * sizeof(CFIndex));
+        m_indices = reinterpret_cast<const CFIndex*>(CFDataGetMutableBytePtr(m_indicesData.get()));
+        CTRunGetStringIndices(m_CTRun.get(), CFRangeMake(0, 0), const_cast<CFIndex*>(m_indices));
+    }
+
+    m_glyphs = CTRunGetGlyphsPtr(m_CTRun.get());
+    if (!m_glyphs) {
+        m_glyphsVector.grow(m_glyphCount);
+        CTRunGetGlyphs(m_CTRun.get(), CFRangeMake(0, 0), m_glyphsVector.data());
+        m_glyphs = m_glyphsVector.data();
+    }
+
+    m_advances = CTRunGetAdvancesPtr(m_CTRun.get());
+    if (!m_advances) {
+        m_advancesVector.grow(m_glyphCount);
+        CTRunGetAdvances(m_CTRun.get(), CFRangeMake(0, 0), m_advancesVector.data());
+        m_advances = m_advancesVector.data();
+    }
+
+}
+
+// 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 SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
+    : m_fontData(fontData)
+    , m_characters(characters)
+    , m_stringLocation(stringLocation)
+    , m_stringLength(stringLength)
+{
+    Vector<CFIndex, 16> indices;
+    unsigned r = 0;
+    while (r < stringLength) {
+        indices.append(r);
+        if (U_IS_SURROGATE(characters[r])) {
+            ASSERT(r + 1 < stringLength);
+            ASSERT(U_IS_SURROGATE_LEAD(characters[r]));
+            ASSERT(U_IS_TRAIL(characters[r + 1]));
+            r += 2;
+        } else
+            r++;
+    }
+    m_glyphCount = indices.size();
+    if (!ltr) {
+        for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end)
+            std::swap(indices[r], indices[end]);
+    }
+    m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
+    CFDataAppendBytes(m_indicesData.get(), reinterpret_cast<const UInt8*>(indices.data()), m_glyphCount * sizeof(CFIndex));
+    m_indices = reinterpret_cast<const CFIndex*>(CFDataGetBytePtr(m_indicesData.get()));
+
+    // Synthesize a run of missing glyphs.
+    m_glyphsVector.fill(0, m_glyphCount);
+    m_glyphs = m_glyphsVector.data();
+    m_advancesVector.fill(CGSizeMake(m_fontData->widthForGlyph(0), 0), m_glyphCount);
+    m_advances = m_advancesVector.data();
+}
+
+void ComplexTextController::collectComplexTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData)
+{
+    if (!fontData) {
+        // Create a run of missing glyphs from the primary font.
+        m_complexTextRuns.append(ComplexTextRun::create(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));
+        return;
+    }
+
+    if (m_fallbackFonts && fontData != m_font.primaryFont())
+        m_fallbackFonts->add(fontData);
+
+    RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull));
+
+    RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes(m_font.fontDescription().textRenderingMode())));
+
+    RetainPtr<CTTypesetterRef> typesetter;
+
+    if (!m_mayUseNaturalWritingDirection || m_run.directionalOverride()) {
+        static const void* optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel };
+        static const void* ltrOptionValues[] = { kCFBooleanFalse };
+        static const void* rtlOptionValues[] = { kCFBooleanTrue };
+        static CFDictionaryRef ltrTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, ltrOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+        static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+        typesetter.adoptCF(CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions));
+    } else
+        typesetter.adoptCF(CTTypesetterCreateWithAttributedString(attributedString.get()));
+
+    RetainPtr<CTLineRef> line(AdoptCF, CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0)));
+
+    CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
+
+    CFIndex runCount = CFArrayGetCount(runArray);
+
+    for (CFIndex r = 0; r < runCount; r++) {
+        CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
+        ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
+        m_complexTextRuns.append(ComplexTextRun::create(ctRun, fontData, cp, stringLocation, length));
+    }
+}
+
+} // namespace WebCore
+
+#endif // USE(CORE_TEXT)
diff --git a/WebCore/platform/graphics/mac/CoreTextController.cpp b/WebCore/platform/graphics/mac/CoreTextController.cpp
deleted file mode 100644
index b2682e4..0000000
--- a/WebCore/platform/graphics/mac/CoreTextController.cpp
+++ /dev/null
@@ -1,537 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 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. ``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
- * 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 "CoreTextController.h"
-
-#if USE(CORE_TEXT)
-
-#include "CharacterNames.h"
-#include "Font.h"
-#include "FontCache.h"
-#include "SimpleFontData.h"
-#include "TextBreakIterator.h"
-#include <wtf/MathExtras.h>
-
-using namespace std;
-
-namespace WebCore {
-
-static inline CGFloat roundCGFloat(CGFloat f)
-{
-    if (sizeof(CGFloat) == sizeof(float))
-        return roundf(static_cast<float>(f));
-    return static_cast<CGFloat>(round(f));
-}
-
-static inline CGFloat ceilCGFloat(CGFloat f)
-{
-    if (sizeof(CGFloat) == sizeof(float))
-        return ceilf(static_cast<float>(f));
-    return static_cast<CGFloat>(ceil(f));
-}
-
-CoreTextController::CoreTextRun::CoreTextRun(CTRunRef ctRun, const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength)
-    : m_CTRun(ctRun)
-    , m_fontData(fontData)
-    , m_characters(characters)
-    , m_stringLocation(stringLocation)
-    , m_stringLength(stringLength)
-{
-    m_glyphCount = CTRunGetGlyphCount(ctRun);
-    m_indices = CTRunGetStringIndicesPtr(ctRun);
-    if (!m_indices) {
-        m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
-        CFDataIncreaseLength(m_indicesData.get(), m_glyphCount * sizeof(CFIndex));
-        m_indices = reinterpret_cast<const CFIndex*>(CFDataGetMutableBytePtr(m_indicesData.get()));
-        CTRunGetStringIndices(ctRun, CFRangeMake(0, 0), const_cast<CFIndex*>(m_indices));
-    }
-}
-
-// 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.
-CoreTextController::CoreTextRun::CoreTextRun(const SimpleFontData* fontData, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr)
-    : m_fontData(fontData)
-    , m_characters(characters)
-    , m_stringLocation(stringLocation)
-    , m_stringLength(stringLength)
-{
-    Vector<CFIndex, 16> indices;
-    unsigned r = 0;
-    while (r < stringLength) {
-        indices.append(r);
-        if (U_IS_SURROGATE(characters[r])) {
-            ASSERT(r + 1 < stringLength);
-            ASSERT(U_IS_SURROGATE_LEAD(characters[r]));
-            ASSERT(U_IS_TRAIL(characters[r + 1]));
-            r += 2;
-        } else
-            r++;
-    }
-    m_glyphCount = indices.size();
-    if (!ltr) {
-        for (unsigned r = 0, end = m_glyphCount - 1; r < m_glyphCount / 2; ++r, --end)
-            std::swap(indices[r], indices[end]);
-    }
-    m_indicesData.adoptCF(CFDataCreateMutable(kCFAllocatorDefault, m_glyphCount * sizeof(CFIndex)));
-    CFDataAppendBytes(m_indicesData.get(), reinterpret_cast<const UInt8*>(indices.data()), m_glyphCount * sizeof(CFIndex));
-    m_indices = reinterpret_cast<const CFIndex*>(CFDataGetBytePtr(m_indicesData.get()));
-}
-
-CoreTextController::CoreTextController(const Font* font, const TextRun& run, bool mayUseNaturalWritingDirection, HashSet<const SimpleFontData*>* fallbackFonts)
-    : m_font(*font)
-    , m_run(run)
-    , m_mayUseNaturalWritingDirection(mayUseNaturalWritingDirection)
-    , m_currentCharacter(0)
-    , m_end(run.length())
-    , m_totalWidth(0)
-    , m_runWidthSoFar(0)
-    , m_numGlyphsSoFar(0)
-    , m_currentRun(0)
-    , m_glyphInCurrentRun(0)
-    , m_finalRoundingWidth(0)
-    , m_fallbackFonts(fallbackFonts)
-    , m_lastRoundingGlyph(0)
-{
-    m_padding = m_run.padding();
-    if (!m_padding)
-        m_padPerSpace = 0;
-    else {
-        float numSpaces = 0;
-        for (int s = 0; s < m_run.length(); s++)
-            if (Font::treatAsSpace(m_run[s]))
-                numSpaces++;
-
-        if (numSpaces == 0)
-            m_padPerSpace = 0;
-        else
-            m_padPerSpace = ceilf(m_run.padding() / numSpaces);
-    }
-
-    collectCoreTextRuns();
-    adjustGlyphsAndAdvances();
-}
-
-int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
-{
-    // FIXME: For positions occurring within a ligature, we should return the closest "ligature caret" or
-    // approximate it by dividing the width of the ligature by the number of characters it encompasses.
-    // However, Core Text does not expose a low-level API for directly finding
-    // out how many characters a ligature encompasses (the "attachment count").
-    if (h >= m_totalWidth)
-        return m_run.ltr() ? m_end : 0;
-    if (h < 0)
-        return m_run.ltr() ? 0 : m_end;
-
-    CGFloat x = h;
-
-    size_t runCount = m_coreTextRuns.size();
-    size_t offsetIntoAdjustedGlyphs = 0;
-
-    for (size_t r = 0; r < runCount; ++r) {
-        const CoreTextRun& coreTextRun = m_coreTextRuns[r];
-        for (unsigned j = 0; j < coreTextRun.glyphCount(); ++j) {
-            CGFloat adjustedAdvance = m_adjustedAdvances[offsetIntoAdjustedGlyphs + j].width;
-            if (x <= adjustedAdvance) {
-                CFIndex hitIndex = coreTextRun.indexAt(j);
-                int stringLength = coreTextRun.stringLength();
-                TextBreakIterator* cursorPositionIterator = cursorMovementIterator(coreTextRun.characters(), stringLength);
-                int clusterStart;
-                if (isTextBreak(cursorPositionIterator, hitIndex))
-                    clusterStart = hitIndex;
-                else {
-                    clusterStart = textBreakPreceding(cursorPositionIterator, hitIndex);
-                    if (clusterStart == TextBreakDone)
-                        clusterStart = 0;
-                }
-
-                if (!includePartialGlyphs)
-                    return coreTextRun.stringLocation() + clusterStart;
-
-                int clusterEnd = textBreakFollowing(cursorPositionIterator, hitIndex);
-                if (clusterEnd == TextBreakDone)
-                    clusterEnd = stringLength;
-
-                CGFloat clusterWidth = adjustedAdvance;
-                // FIXME: The search stops at the boundaries of coreTextRun. In theory, it should go on into neighboring CoreTextRuns
-                // derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no
-                // reordering and on font fallback should occur within a CTLine.
-                if (clusterEnd - clusterStart > 1) {
-                    int firstGlyphBeforeCluster = j - 1;
-                    while (firstGlyphBeforeCluster >= 0 && coreTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
-                        CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
-                        clusterWidth += width;
-                        x += width;
-                        firstGlyphBeforeCluster--;
-                    }
-                    unsigned firstGlyphAfterCluster = j + 1;
-                    while (firstGlyphAfterCluster < coreTextRun.glyphCount() && coreTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) {
-                        clusterWidth += m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width;
-                        firstGlyphAfterCluster++;
-                    }
-                }
-                if (x <= clusterWidth / 2)
-                    return coreTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd);
-                else
-                    return coreTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart);
-            }
-            x -= adjustedAdvance;
-        }
-        offsetIntoAdjustedGlyphs += coreTextRun.glyphCount();
-    }
-
-    ASSERT_NOT_REACHED();
-    return 0;
-}
-
-void CoreTextController::collectCoreTextRuns()
-{
-    if (!m_end)
-        return;
-
-    // We break up glyph run generation for the string by FontData and (if needed) the use of small caps.
-    const UChar* cp = m_run.characters();
-    bool hasTrailingSoftHyphen = m_run[m_end - 1] == softHyphen;
-
-    if (m_font.isSmallCaps() || hasTrailingSoftHyphen)
-        m_smallCapsBuffer.resize(m_end);
-
-    unsigned indexOfFontTransition = m_run.rtl() ? m_end - 1 : 0;
-    const UChar* curr = m_run.rtl() ? cp + m_end  - 1 : cp;
-    const UChar* end = m_run.rtl() ? cp - 1 : cp + m_end;
-
-    // FIXME: Using HYPHEN-MINUS rather than HYPHEN because Times has a HYPHEN-MINUS glyph that looks like its
-    // SOFT-HYPHEN glyph, and has no HYPHEN glyph.
-    static const UChar hyphen = '-';
-
-    if (hasTrailingSoftHyphen && m_run.rtl()) {
-        collectCoreTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
-        indexOfFontTransition--;
-        curr--;
-    }
-
-    GlyphData glyphData;
-    GlyphData nextGlyphData;
-
-    bool isSurrogate = U16_IS_SURROGATE(*curr);
-    if (isSurrogate) {
-        if (m_run.ltr()) {
-            if (!U16_IS_SURROGATE_LEAD(curr[0]) || curr + 1 == end || !U16_IS_TRAIL(curr[1]))
-                return;
-            nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[0], curr[1]), false);
-        } else {
-            if (!U16_IS_TRAIL(curr[0]) || curr -1 == end || !U16_IS_SURROGATE_LEAD(curr[-1]))
-                return;
-            nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[-1], curr[0]), false);
-        }
-    } else
-        nextGlyphData = m_font.glyphDataForCharacter(*curr, false);
-
-    UChar newC = 0;
-
-    bool isSmallCaps;
-    bool nextIsSmallCaps = !isSurrogate && m_font.isSmallCaps() && !(U_GET_GC_MASK(*curr) & U_GC_M_MASK) && (newC = u_toupper(*curr)) != *curr;
-
-    if (nextIsSmallCaps)
-        m_smallCapsBuffer[curr - cp] = newC;
-
-    while (true) {
-        curr = m_run.rtl() ? curr - (isSurrogate ? 2 : 1) : curr + (isSurrogate ? 2 : 1);
-        if (curr == end)
-            break;
-
-        glyphData = nextGlyphData;
-        isSmallCaps = nextIsSmallCaps;
-        int index = curr - cp;
-        isSurrogate = U16_IS_SURROGATE(*curr);
-        UChar c = *curr;
-        bool forceSmallCaps = !isSurrogate && isSmallCaps && (U_GET_GC_MASK(c) & U_GC_M_MASK);
-        if (isSurrogate) {
-            if (m_run.ltr()) {
-                if (!U16_IS_SURROGATE_LEAD(curr[0]) || curr + 1 == end || !U16_IS_TRAIL(curr[1]))
-                    return;
-                nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[0], curr[1]), false);
-            } else {
-                if (!U16_IS_TRAIL(curr[0]) || curr -1 == end || !U16_IS_SURROGATE_LEAD(curr[-1]))
-                    return;
-                nextGlyphData = m_font.glyphDataForCharacter(U16_GET_SUPPLEMENTARY(curr[-1], curr[0]), false);
-            }
-        } else
-            nextGlyphData = m_font.glyphDataForCharacter(*curr, false, forceSmallCaps);
-
-        if (!isSurrogate && m_font.isSmallCaps()) {
-            nextIsSmallCaps = forceSmallCaps || (newC = u_toupper(c)) != c;
-            if (nextIsSmallCaps)
-                m_smallCapsBuffer[index] = forceSmallCaps ? c : newC;
-        }
-
-        if (nextGlyphData.fontData != glyphData.fontData || nextIsSmallCaps != isSmallCaps || !nextGlyphData.glyph != !glyphData.glyph) {
-            int itemStart = m_run.rtl() ? index + 1 : indexOfFontTransition;
-            int itemLength = m_run.rtl() ? indexOfFontTransition - index : index - indexOfFontTransition;
-            collectCoreTextRunsForCharacters((isSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, glyphData.glyph ? glyphData.fontData : 0);
-            indexOfFontTransition = index;
-        }
-    }
-
-    int itemLength = m_run.rtl() ? indexOfFontTransition + 1 : m_end - indexOfFontTransition - (hasTrailingSoftHyphen ? 1 : 0);
-    if (itemLength) {
-        int itemStart = m_run.rtl() ? 0 : indexOfFontTransition;
-        collectCoreTextRunsForCharacters((nextIsSmallCaps ? m_smallCapsBuffer.data() : cp) + itemStart, itemLength, itemStart, nextGlyphData.glyph ? nextGlyphData.fontData : 0);
-    }
-
-    if (hasTrailingSoftHyphen && m_run.ltr())
-        collectCoreTextRunsForCharacters(&hyphen, 1, m_end - 1, m_font.glyphDataForCharacter(hyphen, false).fontData);
-}
-
-void CoreTextController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
-{
-    // FIXME: For offsets falling inside a ligature, we should advance only as far as the appropriate "ligature caret"
-    // or divide the width of the ligature by the number of offsets it encompasses and make an advance proportional
-    // to the offsets into the ligature. However, Core Text does not expose a low-level API for
-    // directly finding out how many characters a ligature encompasses (the "attachment count").
-    if (static_cast<int>(offset) > m_end)
-        offset = m_end;
-
-    if (offset <= m_currentCharacter)
-        return;
-
-    m_currentCharacter = offset;
-
-    size_t runCount = m_coreTextRuns.size();
-
-    bool ltr = m_run.ltr();
-
-    unsigned k = ltr ? m_numGlyphsSoFar : m_adjustedGlyphs.size() - 1 - m_numGlyphsSoFar;
-    while (m_currentRun < runCount) {
-        const CoreTextRun& coreTextRun = m_coreTextRuns[ltr ? m_currentRun : runCount - 1 - m_currentRun];
-        size_t glyphCount = coreTextRun.glyphCount();
-        unsigned g = ltr ? m_glyphInCurrentRun : glyphCount - 1 - m_glyphInCurrentRun;
-        while (m_glyphInCurrentRun < glyphCount) {
-            if (coreTextRun.indexAt(g) + coreTextRun.stringLocation() >= m_currentCharacter)
-                return;
-            CGSize adjustedAdvance = m_adjustedAdvances[k];
-            if (glyphBuffer)
-                glyphBuffer->add(m_adjustedGlyphs[k], coreTextRun.fontData(), adjustedAdvance);
-            m_runWidthSoFar += adjustedAdvance.width;
-            m_numGlyphsSoFar++;
-            m_glyphInCurrentRun++;
-            if (ltr) {
-                g++;
-                k++;
-            } else {
-                g--;
-                k--;
-            }
-        }
-        m_currentRun++;
-        m_glyphInCurrentRun = 0;
-    }
-    if (!ltr && m_numGlyphsSoFar == m_adjustedAdvances.size())
-        m_runWidthSoFar += m_finalRoundingWidth;
-}
-
-void CoreTextController::collectCoreTextRunsForCharacters(const UChar* cp, unsigned length, unsigned stringLocation, const SimpleFontData* fontData)
-{
-    if (!fontData) {
-        // Create a run of missing glyphs from the primary font.
-        m_coreTextRuns.append(CoreTextRun(m_font.primaryFont(), cp, stringLocation, length, m_run.ltr()));
-        return;
-    }
-
-    if (m_fallbackFonts && fontData != m_font.primaryFont())
-        m_fallbackFonts->add(fontData);
-
-    RetainPtr<CFStringRef> string(AdoptCF, CFStringCreateWithCharactersNoCopy(NULL, cp, length, kCFAllocatorNull));
-
-    RetainPtr<CFAttributedStringRef> attributedString(AdoptCF, CFAttributedStringCreate(NULL, string.get(), fontData->getCFStringAttributes(m_font.fontDescription().textRenderingMode())));
-
-    RetainPtr<CTTypesetterRef> typesetter;
-
-    if (!m_mayUseNaturalWritingDirection || m_run.directionalOverride()) {
-        static const void* optionKeys[] = { kCTTypesetterOptionForcedEmbeddingLevel };
-        static const void* ltrOptionValues[] = { kCFBooleanFalse };
-        static const void* rtlOptionValues[] = { kCFBooleanTrue };
-        static CFDictionaryRef ltrTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, ltrOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-        static CFDictionaryRef rtlTypesetterOptions = CFDictionaryCreate(kCFAllocatorDefault, optionKeys, rtlOptionValues, sizeof(optionKeys) / sizeof(*optionKeys), &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-        typesetter.adoptCF(CTTypesetterCreateWithAttributedStringAndOptions(attributedString.get(), m_run.ltr() ? ltrTypesetterOptions : rtlTypesetterOptions));
-    } else
-        typesetter.adoptCF(CTTypesetterCreateWithAttributedString(attributedString.get()));
-
-    RetainPtr<CTLineRef> line(AdoptCF, CTTypesetterCreateLine(typesetter.get(), CFRangeMake(0, 0)));
-
-    CFArrayRef runArray = CTLineGetGlyphRuns(line.get());
-
-    CFIndex runCount = CFArrayGetCount(runArray);
-
-    for (CFIndex r = 0; r < runCount; r++) {
-        CTRunRef ctRun = static_cast<CTRunRef>(CFArrayGetValueAtIndex(runArray, r));
-        ASSERT(CFGetTypeID(ctRun) == CTRunGetTypeID());
-        m_coreTextRuns.append(CoreTextRun(ctRun, fontData, cp, stringLocation, length));
-    }
-}
-
-void CoreTextController::adjustGlyphsAndAdvances()
-{
-    size_t runCount = m_coreTextRuns.size();
-    for (size_t r = 0; r < runCount; ++r) {
-        const CoreTextRun& coreTextRun = m_coreTextRuns[r];
-        unsigned glyphCount = coreTextRun.glyphCount();
-        const SimpleFontData* fontData = coreTextRun.fontData();
-
-        Vector<CGGlyph, 256> glyphsVector;
-        const CGGlyph* glyphs;
-
-        Vector<CGSize, 256> advancesVector;
-        const CGSize* advances;
-
-        if (coreTextRun.ctRun()) {
-            glyphs = CTRunGetGlyphsPtr(coreTextRun.ctRun());
-            if (!glyphs) {
-                glyphsVector.grow(glyphCount);
-                CTRunGetGlyphs(coreTextRun.ctRun(), CFRangeMake(0, 0), glyphsVector.data());
-                glyphs = glyphsVector.data();
-            }
-
-            advances = CTRunGetAdvancesPtr(coreTextRun.ctRun());
-            if (!advances) {
-                advancesVector.grow(glyphCount);
-                CTRunGetAdvances(coreTextRun.ctRun(), CFRangeMake(0, 0), advancesVector.data());
-                advances = advancesVector.data();
-            }
-        } else {
-            // Synthesize a run of missing glyphs.
-            glyphsVector.fill(0, glyphCount);
-            glyphs = glyphsVector.data();
-            advancesVector.fill(CGSizeMake(fontData->widthForGlyph(0), 0), glyphCount);
-            advances = advancesVector.data();
-        }
-
-        bool lastRun = r + 1 == runCount;
-        const UChar* cp = coreTextRun.characters();
-        CGFloat roundedSpaceWidth = roundCGFloat(fontData->spaceWidth());
-        bool roundsAdvances = !m_font.isPrinterFont() && fontData->platformData().roundsGlyphAdvances();
-        bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_padding) && !m_run.spacingDisabled();
-
-
-        for (unsigned i = 0; i < glyphCount; i++) {
-            CFIndex characterIndex = coreTextRun.indexAt(i);
-            UChar ch = *(cp + characterIndex);
-            bool lastGlyph = lastRun && i + 1 == glyphCount;
-            UChar nextCh;
-            if (lastGlyph)
-                nextCh = ' ';
-            else if (i + 1 < glyphCount)
-                nextCh = *(cp + coreTextRun.indexAt(i + 1));
-            else
-                nextCh = *(m_coreTextRuns[r + 1].characters() + m_coreTextRuns[r + 1].indexAt(0));
-
-            bool treatAsSpace = Font::treatAsSpace(ch);
-            CGGlyph glyph = treatAsSpace ? fontData->spaceGlyph() : glyphs[i];
-            CGSize advance = treatAsSpace ? CGSizeMake(fontData->spaceWidth(), advances[i].height) : advances[i];
-
-            if (ch == '\t' && m_run.allowTabs()) {
-                float tabWidth = m_font.tabWidth();
-                advance.width = tabWidth - fmodf(m_run.xPos() + m_totalWidth, tabWidth);
-            } else if (ch == zeroWidthSpace || Font::treatAsZeroWidthSpace(ch) && !treatAsSpace) {
-                advance.width = 0;
-                glyph = fontData->spaceGlyph();
-            }
-
-            float roundedAdvanceWidth = roundf(advance.width);
-            if (roundsAdvances)
-                advance.width = roundedAdvanceWidth;
-
-            advance.width += fontData->syntheticBoldOffset();
-
-            // We special case spaces in two ways when applying word rounding.
-            // First, we round spaces to an adjusted width in all fonts.
-            // Second, in fixed-pitch fonts we ensure that all glyphs that
-            // match the width of the space glyph have the same width as the space glyph.
-            if (roundedAdvanceWidth == roundedSpaceWidth && (fontData->pitch() == FixedPitch || glyph == fontData->spaceGlyph()) && m_run.applyWordRounding())
-                advance.width = fontData->adjustedSpaceWidth();
-
-            if (hasExtraSpacing) {
-                // If we're a glyph with an advance, go ahead and add in letter-spacing.
-                // That way we weed out zero width lurkers.  This behavior matches the fast text code path.
-                if (advance.width && m_font.letterSpacing())
-                    advance.width += m_font.letterSpacing();
-
-                // Handle justification and word-spacing.
-                if (glyph == fontData->spaceGlyph()) {
-                    // Account for padding. WebCore uses space padding to justify text.
-                    // We distribute the specified padding over the available spaces in the run.
-                    if (m_padding) {
-                        // Use leftover padding if not evenly divisible by number of spaces.
-                        if (m_padding < m_padPerSpace) {
-                            advance.width += m_padding;
-                            m_padding = 0;
-                        } else {
-                            advance.width += m_padPerSpace;
-                            m_padding -= m_padPerSpace;
-                        }
-                    }
-
-                    // Account for word-spacing.
-                    if (treatAsSpace && characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing())
-                        advance.width += m_font.wordSpacing();
-                }
-            }
-
-            // Deal with the float/integer impedance mismatch between CG and WebCore. "Words" (characters 
-            // followed by a character defined by isRoundingHackCharacter()) are always an integer width.
-            // We adjust the width of the last character of a "word" to ensure an integer width.
-            // Force characters that are used to determine word boundaries for the rounding hack
-            // to be integer width, so the following words will start on an integer boundary.
-            if (m_run.applyWordRounding() && Font::isRoundingHackCharacter(ch))
-                advance.width = ceilCGFloat(advance.width);
-
-            // Check to see if the next character is a "rounding hack character", if so, adjust the
-            // width so that the total run width will be on an integer boundary.
-            if (m_run.applyWordRounding() && !lastGlyph && Font::isRoundingHackCharacter(nextCh) || m_run.applyRunRounding() && lastGlyph) {
-                CGFloat totalWidth = m_totalWidth + advance.width;
-                CGFloat extraWidth = ceilCGFloat(totalWidth) - totalWidth;
-                if (m_run.ltr())
-                    advance.width += extraWidth;
-                else {
-                    m_totalWidth += extraWidth;
-                    if (m_lastRoundingGlyph)
-                        m_adjustedAdvances[m_lastRoundingGlyph - 1].width += extraWidth;
-                    else
-                        m_finalRoundingWidth = extraWidth;
-                    m_lastRoundingGlyph = m_adjustedAdvances.size() + 1;
-                }
-            }
-
-            m_totalWidth += advance.width;
-            advance.height *= -1;
-            m_adjustedAdvances.append(advance);
-            m_adjustedGlyphs.append(glyph);
-        }
-    }
-}
-
-} // namespace WebCore
-
-#endif // USE(CORE_TEXT)
diff --git a/WebCore/platform/graphics/mac/CoreTextController.h b/WebCore/platform/graphics/mac/CoreTextController.h
deleted file mode 100644
index 4dd6f93..0000000
--- a/WebCore/platform/graphics/mac/CoreTextController.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 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. ``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
- * 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. 
- */
-
-#ifndef CoreTextController_h
-#define CoreTextController_h
-
-#if USE(CORE_TEXT)
-
-#include "Font.h"
-#include "GlyphBuffer.h"
-#include <wtf/RetainPtr.h>
-#include <wtf/Vector.h>
-
-namespace WebCore {
-
-class CoreTextController {
-public:
-    CoreTextController(const Font*, const TextRun&, bool mayUseNaturalWritingDirection = false, HashSet<const SimpleFontData*>* fallbackFonts = 0);
-
-    // Advance and emit glyphs up to the specified character.
-    void advance(unsigned to, GlyphBuffer* = 0);
-
-    // Compute the character offset for a given x coordinate.
-    int offsetForPosition(int x, bool includePartialGlyphs);
-
-    // Returns the width of everything we've consumed so far.
-    float runWidthSoFar() const { return m_runWidthSoFar; }
-
-    float totalWidth() const { return m_totalWidth; }
-
-    // Extra width to the left of the leftmost glyph.
-    float finalRoundingWidth() const { return m_finalRoundingWidth; }
-
-private:
-    class CoreTextRun {
-    public:
-        CoreTextRun(CTRunRef, const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength);
-        CoreTextRun(const SimpleFontData*, const UChar* characters, unsigned stringLocation, size_t stringLength, bool ltr);
-
-        CTRunRef ctRun() const { return m_CTRun.get(); }
-        unsigned glyphCount() const { return m_glyphCount; }
-        const SimpleFontData* fontData() const { return m_fontData; }
-        const UChar* characters() const { return m_characters; }
-        unsigned stringLocation() const { return m_stringLocation; }
-        size_t stringLength() const { return m_stringLength; }
-        CFIndex indexAt(size_t i) const { return m_indices[i]; }
-
-    private:
-        RetainPtr<CTRunRef> m_CTRun;
-        unsigned m_glyphCount;
-        const SimpleFontData* m_fontData;
-        const UChar* m_characters;
-        unsigned m_stringLocation;
-        size_t m_stringLength;
-        const CFIndex* m_indices;
-        // Used only if CTRunGet*Ptr fails or if this is a missing glyphs run.
-        RetainPtr<CFMutableDataRef> m_indicesData;
-    };
-
-    void collectCoreTextRuns();
-    void collectCoreTextRunsForCharacters(const UChar*, unsigned length, unsigned stringLocation, const SimpleFontData*);
-    void adjustGlyphsAndAdvances();
-
-    const Font& m_font;
-    const TextRun& m_run;
-    bool m_mayUseNaturalWritingDirection;
-
-    Vector<UChar, 256> m_smallCapsBuffer;
-
-    Vector<CoreTextRun, 16> m_coreTextRuns;
-    Vector<CGSize, 256> m_adjustedAdvances;
-    Vector<CGGlyph, 256> m_adjustedGlyphs;
- 
-    unsigned m_currentCharacter;
-    int m_end;
-
-    CGFloat m_totalWidth;
-
-    float m_runWidthSoFar;
-    unsigned m_numGlyphsSoFar;
-    size_t m_currentRun;
-    unsigned m_glyphInCurrentRun;
-    float m_finalRoundingWidth;
-    float m_padding;
-    float m_padPerSpace;
-
-    HashSet<const SimpleFontData*>* m_fallbackFonts;
-
-    unsigned m_lastRoundingGlyph;
-};
-
-} // namespace WebCore
-#endif // USE(CORE_TEXT)
-#endif // CoreTextController_h
diff --git a/WebCore/platform/graphics/mac/FontComplexTextMac.cpp b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
new file mode 100644
index 0000000..0db2601
--- /dev/null
+++ b/WebCore/platform/graphics/mac/FontComplexTextMac.cpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 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 "Font.h"
+
+#include "ComplexTextController.h"
+#include "FontFallbackList.h"
+#include "GlyphBuffer.h"
+#include "GraphicsContext.h"
+#include "IntRect.h"
+#include "SimpleFontData.h"
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h,
+                                            int from, int to) const
+{
+    ComplexTextController controller(this, run);
+    controller.advance(from);
+    float beforeWidth = controller.runWidthSoFar();
+    controller.advance(to);
+    float afterWidth = controller.runWidthSoFar();
+
+    // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
+    if (run.rtl()) {
+        float totalWidth = controller.totalWidth();
+        return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
+    } 
+
+    return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
+}
+
+void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point,
+                           int from, int to) const
+{
+    // This glyph buffer holds our glyphs + advances + font data for each glyph.
+    GlyphBuffer glyphBuffer;
+
+    float startX = point.x();
+    ComplexTextController controller(this, run);
+    controller.advance(from);
+    float beforeWidth = controller.runWidthSoFar();
+    controller.advance(to, &glyphBuffer);
+    
+    // We couldn't generate any glyphs for the run.  Give up.
+    if (glyphBuffer.isEmpty())
+        return;
+    
+    float afterWidth = controller.runWidthSoFar();
+
+    if (run.rtl()) {
+        startX += controller.totalWidth() + controller.finalRoundingWidth() - afterWidth;
+        for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
+            glyphBuffer.swap(i, end);
+    } else
+        startX += beforeWidth;
+
+    // Draw the glyph buffer now at the starting point returned in startX.
+    FloatPoint startPoint(startX, point.y());
+    drawGlyphBuffer(context, glyphBuffer, run, startPoint);
+}
+
+float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
+{
+    ComplexTextController controller(this, run, true, fallbackFonts);
+    return controller.totalWidth();
+}
+
+int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const
+{
+    ComplexTextController controller(this, run);
+    return controller.offsetForPosition(x, includePartialGlyphs);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/mac/FontMacATSUI.mm b/WebCore/platform/graphics/mac/FontMacATSUI.mm
deleted file mode 100644
index 409bda4..0000000
--- a/WebCore/platform/graphics/mac/FontMacATSUI.mm
+++ /dev/null
@@ -1,635 +0,0 @@
-/*
- * Copyright (C) 1999 Lars Knoll (knoll at kde.org)
- *           (C) 1999 Antti Koivisto (koivisto at kde.org)
- *           (C) 2000 Dirk Mueller (mueller at kde.org)
- * Copyright (C) 2003, 2006 Apple Computer, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#import "config.h"
-#import "Font.h"
-
-#if USE(ATSUI)
-
-#import "CharacterNames.h"
-#import "GraphicsContext.h"
-#import "Logging.h"
-#import "ShapeArabic.h"
-#import "SimpleFontData.h"
-#import <AppKit/NSGraphicsContext.h>
-#import <wtf/OwnArrayPtr.h>
-
-#define SYNTHETIC_OBLIQUE_ANGLE 14
-
-#ifdef __LP64__
-#define URefCon void*
-#else
-#define URefCon UInt32
-#endif
-
-using namespace std;
-
-namespace WebCore {
-
-struct ATSULayoutParameters : Noncopyable
-{
-    ATSULayoutParameters(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts = 0)
-        : m_run(run)
-        , m_font(0)
-        , m_hasSyntheticBold(false)
-        , m_syntheticBoldPass(false)
-        , m_padPerSpace(0)
-        , m_fallbackFonts(fallbackFonts)
-    {
-    }
-
-    ~ATSULayoutParameters()
-    {
-        ATSUDisposeTextLayout(m_layout);
-    }
-
-    void initialize(const Font*, const GraphicsContext* = 0);
-
-    const TextRun& m_run;
-    
-    const Font* m_font;
-    
-    ATSUTextLayout m_layout;
-    OwnArrayPtr<const SimpleFontData*> m_fonts;
-    
-    OwnArrayPtr<UChar> m_charBuffer;
-    bool m_hasSyntheticBold;
-    bool m_syntheticBoldPass;
-    float m_padPerSpace;
-    HashSet<const SimpleFontData*>* m_fallbackFonts;
-};
-
-static TextRun copyRunForDirectionalOverrideIfNecessary(const TextRun& run, OwnArrayPtr<UChar>& charactersWithOverride)
-{
-    if (!run.directionalOverride())
-        return run;
-
-    charactersWithOverride.set(new UChar[run.length() + 2]);
-    charactersWithOverride[0] = run.rtl() ? rightToLeftOverride : leftToRightOverride;
-    memcpy(&charactersWithOverride[1], run.data(0), sizeof(UChar) * run.length());
-    charactersWithOverride[run.length() + 1] = popDirectionalFormatting;
-
-    TextRun result = run;
-    result.setText(charactersWithOverride.get(), run.length() + 2);
-    return result;
-}
-
-static bool fontHasMirroringInfo(ATSUFontID fontID)
-{
-    ByteCount propTableSize;
-    OSStatus status = ATSFontGetTable(fontID, 'prop', 0, 0, 0, &propTableSize);
-    if (status == noErr)    // naively assume that if a 'prop' table exists then it contains mirroring info
-        return true;
-    else if (status != kATSInvalidFontTableAccess) // anything other than a missing table is logged as an error
-        LOG_ERROR("ATSFontGetTable failed (%d)", status);
-
-    return false;
-}
-
-static void disableLigatures(const SimpleFontData* fontData, TextRenderingMode textMode)
-{
-    // Don't be too aggressive: if the font doesn't contain 'a', then assume that any ligatures it contains are
-    // in characters that always go through ATSUI, and therefore allow them. Geeza Pro is an example.
-    // See bugzilla 5166.
-    if (textMode == OptimizeLegibility || textMode == GeometricPrecision || fontData->platformData().allowsLigatures())
-        return;
-
-    ATSUFontFeatureType featureTypes[] = { kLigaturesType };
-    ATSUFontFeatureSelector featureSelectors[] = { kCommonLigaturesOffSelector };
-    OSStatus status = ATSUSetFontFeatures(fontData->m_ATSUStyle, 1, featureTypes, featureSelectors);
-    if (status != noErr)
-        LOG_ERROR("ATSUSetFontFeatures failed (%d) -- ligatures remain enabled", status);
-}
-
-static void initializeATSUStyle(const SimpleFontData* fontData, TextRenderingMode textMode)
-{
-    if (fontData->m_ATSUStyleInitialized)
-        return;
-
-    ATSUFontID fontID = fontData->platformData().m_atsuFontID;
-    if (!fontID) {
-        LOG_ERROR("unable to get ATSUFontID for %@", fontData->platformData().font());
-        return;
-    }
-
-    OSStatus status = ATSUCreateStyle(&fontData->m_ATSUStyle);
-    if (status != noErr)
-        // Who knows how many ATSU functions will crash when passed a NULL style...
-        LOG_ERROR("ATSUCreateStyle failed (%d)", status);
-
-    CGAffineTransform transform = CGAffineTransformMakeScale(1, -1);
-    if (fontData->platformData().m_syntheticOblique)
-        transform = CGAffineTransformConcat(transform, CGAffineTransformMake(1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, 0, 0));
-    Fixed fontSize = FloatToFixed(fontData->platformData().m_size);
-    ByteCount styleSizes[4] = { sizeof(Fixed), sizeof(ATSUFontID), sizeof(CGAffineTransform), sizeof(Fract) };
-    
-    bool allowKerning = textMode == OptimizeLegibility || textMode == GeometricPrecision;
-    if (!allowKerning) {
-        // Turn off automatic kerning until it is supported in the CG code path (bug 6136)
-        Fract kerningInhibitFactor = FloatToFract(1.0);
-        ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag };
-        ATSUAttributeValuePtr styleValues[4] = { &fontSize, &fontID, &transform, &kerningInhibitFactor };
-        status = ATSUSetAttributes(fontData->m_ATSUStyle, 4, styleTags, styleSizes, styleValues);
-        if (status != noErr)
-            LOG_ERROR("ATSUSetAttributes failed (%d)", status);
-    } else {
-        ATSUAttributeTag styleTags[3] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag };
-        ATSUAttributeValuePtr styleValues[3] = { &fontSize, &fontID, &transform, };
-        status = ATSUSetAttributes(fontData->m_ATSUStyle, 3, styleTags, styleSizes, styleValues);
-        if (status != noErr)
-            LOG_ERROR("ATSUSetAttributes failed (%d)", status);
-    }
-
-    fontData->m_ATSUMirrors = fontHasMirroringInfo(fontID);
-
-    // Turn off ligatures such as 'fi' to match the CG code path's behavior, until bug 6135 is fixed.
-    disableLigatures(fontData, textMode);
-
-    fontData->m_ATSUStyleInitialized = true;
-}
-
-static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector, ATSULineRef iLineRef, URefCon iRefCon, void*, ATSULayoutOperationCallbackStatus* oCallbackStatus)
-{
-    ATSULayoutParameters* params = reinterpret_cast<ATSULayoutParameters*>(iRefCon);
-    OSStatus status;
-    ItemCount count;
-    ATSLayoutRecord *layoutRecords;
-
-    if (params->m_run.applyWordRounding()) {
-        status = ATSUDirectGetLayoutDataArrayPtrFromLineRef(iLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, true, (void **)&layoutRecords, &count);
-        if (status != noErr) {
-            *oCallbackStatus = kATSULayoutOperationCallbackStatusContinue;
-            return status;
-        }
-        
-        Fixed lastNativePos = 0;
-        float lastAdjustedPos = 0;
-        const UChar* characters = params->m_charBuffer ? params->m_charBuffer.get() : params->m_run.characters();
-        const SimpleFontData** renderers = params->m_fonts.get();
-        const SimpleFontData* renderer;
-        const SimpleFontData* lastRenderer = 0;
-        ByteCount offset = layoutRecords[0].originalOffset;
-        UChar nextCh = *(UChar *)(((char *)characters)+offset);
-        bool shouldRound = false;
-        bool syntheticBoldPass = params->m_syntheticBoldPass;
-        Fixed syntheticBoldOffset = 0;
-        bool hasExtraSpacing = (params->m_font->letterSpacing() || params->m_font->wordSpacing() || params->m_run.padding()) && !params->m_run.spacingDisabled();
-        float padding = params->m_run.padding();
-        // In the CoreGraphics code path, the rounding hack is applied in logical order.
-        // Here it is applied in visual left-to-right order, which may be better.
-        ItemCount lastRoundingChar = 0;
-        ItemCount i;
-        for (i = 1; i < count; i++) {
-            bool isLastChar = i == count - 1;
-            renderer = renderers[offset / 2];
-            float width;
-            if (nextCh == zeroWidthSpace || Font::treatAsZeroWidthSpace(nextCh) && !Font::treatAsSpace(nextCh)) {
-                width = 0;
-                layoutRecords[i-1].glyphID = renderer->spaceGlyph();
-            } else {
-                width = FixedToFloat(layoutRecords[i].realPos - lastNativePos);
-                if (renderer != lastRenderer && width) {
-                    lastRenderer = renderer;
-                    // The CoreGraphics interpretation of NSFontAntialiasedIntegerAdvancementsRenderingMode seems
-                    // to be "round each glyph's width to the nearest integer". This is not the same as ATSUI
-                    // does in any of its device-metrics modes.
-                    shouldRound = renderer->platformData().roundsGlyphAdvances();
-                    if (syntheticBoldPass)
-                        syntheticBoldOffset = FloatToFixed(renderer->syntheticBoldOffset());
-                    if (params->m_fallbackFonts && renderer != params->m_font->primaryFont())
-                        params->m_fallbackFonts->add(renderer);
-                }
-                if (shouldRound)
-                    width = roundf(width);
-                width += renderer->syntheticBoldOffset();
-                if (renderer->pitch() == FixedPitch ? width == renderer->spaceWidth() : (layoutRecords[i-1].flags & kATSGlyphInfoIsWhiteSpace))
-                    width = renderer->adjustedSpaceWidth();
-            }
-            lastNativePos = layoutRecords[i].realPos;
-
-            if (hasExtraSpacing) {
-                if (width && params->m_font->letterSpacing())
-                    width +=params->m_font->letterSpacing();
-                if (Font::treatAsSpace(nextCh)) {
-                    if (params->m_run.padding()) {
-                        if (padding < params->m_padPerSpace) {
-                            width += padding;
-                            padding = 0;
-                        } else {
-                            width += params->m_padPerSpace;
-                            padding -= params->m_padPerSpace;
-                        }
-                    }
-                    if (offset != 0 && !Font::treatAsSpace(*((UChar *)(((char *)characters)+offset) - 1)) && params->m_font->wordSpacing())
-                        width += params->m_font->wordSpacing();
-                }
-            }
-
-            UChar ch = nextCh;
-            offset = layoutRecords[i].originalOffset;
-            // Use space for nextCh at the end of the loop so that we get inside the rounding hack code.
-            // We won't actually round unless the other conditions are satisfied.
-            nextCh = isLastChar ? ' ' : *(UChar *)(((char *)characters)+offset);
-
-            if (Font::isRoundingHackCharacter(ch))
-                width = ceilf(width);
-            lastAdjustedPos = lastAdjustedPos + width;
-            if (Font::isRoundingHackCharacter(nextCh) && (!isLastChar || params->m_run.applyRunRounding())){
-                if (params->m_run.ltr())
-                    lastAdjustedPos = ceilf(lastAdjustedPos);
-                else {
-                    float roundingWidth = ceilf(lastAdjustedPos) - lastAdjustedPos;
-                    Fixed rw = FloatToFixed(roundingWidth);
-                    ItemCount j;
-                    for (j = lastRoundingChar; j < i; j++)
-                        layoutRecords[j].realPos += rw;
-                    lastRoundingChar = i;
-                    lastAdjustedPos += roundingWidth;
-                }
-            }
-            if (syntheticBoldPass) {
-                if (syntheticBoldOffset)
-                    layoutRecords[i-1].realPos += syntheticBoldOffset;
-                else
-                    layoutRecords[i-1].glyphID = renderer->spaceGlyph();
-            }
-            layoutRecords[i].realPos = FloatToFixed(lastAdjustedPos);
-        }
-        
-        status = ATSUDirectReleaseLayoutDataArrayPtr(iLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void **)&layoutRecords);
-    }
-    *oCallbackStatus = kATSULayoutOperationCallbackStatusHandled;
-    return noErr;
-}
-
-static inline bool isArabicLamWithAlefLigature(UChar c)
-{
-    return c >= 0xfef5 && c <= 0xfefc;
-}
-
-static void shapeArabic(const UChar* source, UChar* dest, unsigned totalLength, unsigned shapingStart)
-{
-    while (shapingStart < totalLength) {
-        unsigned shapingEnd;
-        // We do not want to pass a Lam with Alef ligature followed by a space to the shaper,
-        // since we want to be able to identify this sequence as the result of shaping a Lam
-        // followed by an Alef and padding with a space.
-        bool foundLigatureSpace = false;
-        for (shapingEnd = shapingStart; !foundLigatureSpace && shapingEnd < totalLength - 1; ++shapingEnd)
-            foundLigatureSpace = isArabicLamWithAlefLigature(source[shapingEnd]) && source[shapingEnd + 1] == ' ';
-        shapingEnd++;
-
-        UErrorCode shapingError = U_ZERO_ERROR;
-        unsigned charsWritten = shapeArabic(source + shapingStart, shapingEnd - shapingStart, dest + shapingStart, shapingEnd - shapingStart, U_SHAPE_LETTERS_SHAPE | U_SHAPE_LENGTH_FIXED_SPACES_NEAR, &shapingError);
-
-        if (U_SUCCESS(shapingError) && charsWritten == shapingEnd - shapingStart) {
-            for (unsigned j = shapingStart; j < shapingEnd - 1; ++j) {
-                if (isArabicLamWithAlefLigature(dest[j]) && dest[j + 1] == ' ')
-                    dest[++j] = zeroWidthSpace;
-            }
-            if (foundLigatureSpace) {
-                dest[shapingEnd] = ' ';
-                shapingEnd++;
-            } else if (isArabicLamWithAlefLigature(dest[shapingEnd - 1])) {
-                // u_shapeArabic quirk: if the last two characters in the source string are a Lam and an Alef,
-                // the space is put at the beginning of the string, despite U_SHAPE_LENGTH_FIXED_SPACES_NEAR.
-                ASSERT(dest[shapingStart] == ' ');
-                dest[shapingStart] = zeroWidthSpace;
-            }
-        } else {
-            // Something went wrong. Abandon shaping and just copy the rest of the buffer.
-            LOG_ERROR("u_shapeArabic failed(%d)", shapingError);
-            shapingEnd = totalLength;
-            memcpy(dest + shapingStart, source + shapingStart, (shapingEnd - shapingStart) * sizeof(UChar));
-        }
-        shapingStart = shapingEnd;
-    }
-}
-
-void ATSULayoutParameters::initialize(const Font* font, const GraphicsContext* graphicsContext)
-{
-    m_font = font;
-    
-    const SimpleFontData* fontData = font->primaryFont();
-    m_fonts.set(new const SimpleFontData*[m_run.length()]);
-    if (font->isSmallCaps())
-        m_charBuffer.set(new UChar[m_run.length()]);
-    
-    ATSUTextLayout layout;
-    OSStatus status;
-    ATSULayoutOperationOverrideSpecifier overrideSpecifier;
-    
-    initializeATSUStyle(fontData, m_font->fontDescription().textRenderingMode());
-    
-    // FIXME: This is currently missing the following required features that the CoreGraphics code path has:
-    // - \n, \t, and nonbreaking space render as a space.
-
-    UniCharCount runLength = m_run.length();
-
-    if (m_charBuffer)
-        memcpy(m_charBuffer.get(), m_run.characters(), runLength * sizeof(UChar));
-    
-    status = ATSUCreateTextLayoutWithTextPtr(
-            (m_charBuffer ? m_charBuffer.get() : m_run.characters()),
-            0,        // offset
-            runLength,      // length
-            runLength,    // total length
-            1,              // styleRunCount
-            &runLength,     // length of style run
-            &fontData->m_ATSUStyle, 
-            &layout);
-    if (status != noErr)
-        LOG_ERROR("ATSUCreateTextLayoutWithTextPtr failed(%d)", status);
-    m_layout = layout;
-    ATSUSetTextLayoutRefCon(m_layout, (URefCon)this);
-
-    // FIXME: There are certain times when this method is called, when we don't have access to a GraphicsContext
-    // measuring text runs with floatWidthForComplexText is one example.
-    // ATSUI requires that we pass a valid CGContextRef to it when specifying kATSUCGContextTag (crashes when passed 0)
-    // ATSUI disables sub-pixel rendering if kATSUCGContextTag is not specified!  So we're in a bind.
-    // Sometimes [[NSGraphicsContext currentContext] graphicsPort] may return the wrong (or no!) context.  Nothing we can do about it (yet).
-    CGContextRef cgContext = graphicsContext ? graphicsContext->platformContext() : (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
-    
-    ATSLineLayoutOptions lineLayoutOptions = kATSLineKeepSpacesOutOfMargin | kATSLineHasNoHangers;
-    Boolean rtl = m_run.rtl();
-    overrideSpecifier.operationSelector = kATSULayoutOperationPostLayoutAdjustment;
-    overrideSpecifier.overrideUPP = overrideLayoutOperation;
-    ATSUAttributeTag tags[] = { kATSUCGContextTag, kATSULineLayoutOptionsTag, kATSULineDirectionTag, kATSULayoutOperationOverrideTag };
-    ByteCount sizes[] = { sizeof(CGContextRef), sizeof(ATSLineLayoutOptions), sizeof(Boolean), sizeof(ATSULayoutOperationOverrideSpecifier) };
-    ATSUAttributeValuePtr values[] = { &cgContext, &lineLayoutOptions, &rtl, &overrideSpecifier };
-    
-    status = ATSUSetLayoutControls(layout, (m_run.applyWordRounding() ? 4 : 3), tags, sizes, values);
-    if (status != noErr)
-        LOG_ERROR("ATSUSetLayoutControls failed(%d)", status);
-
-    status = ATSUSetTransientFontMatching(layout, YES);
-    if (status != noErr)
-        LOG_ERROR("ATSUSetTransientFontMatching failed(%d)", status);
-
-    m_hasSyntheticBold = false;
-    ATSUFontID ATSUSubstituteFont;
-    UniCharArrayOffset substituteOffset = 0;
-    UniCharCount substituteLength;
-    UniCharArrayOffset lastOffset;
-    const SimpleFontData* substituteFontData = 0;
-
-    while (substituteOffset < runLength) {
-        // FIXME: Using ATSUMatchFontsToText() here results in several problems: the CSS font family list is not necessarily followed for the 2nd
-        // and onwards unmatched characters; segmented fonts do not work correctly; behavior does not match the simple text and Uniscribe code
-        // paths. Change this function to use Font::glyphDataForCharacter() for each character instead. 
-        lastOffset = substituteOffset;
-        status = ATSUMatchFontsToText(layout, substituteOffset, kATSUToTextEnd, &ATSUSubstituteFont, &substituteOffset, &substituteLength);
-        if (status == kATSUFontsMatched || status == kATSUFontsNotMatched) {
-            const FontData* fallbackFontData = m_font->fontDataForCharacters(m_run.characters() + substituteOffset, substituteLength);
-            substituteFontData = fallbackFontData ? fallbackFontData->fontDataForCharacter(m_run[0]) : 0;
-            if (substituteFontData) {
-                initializeATSUStyle(substituteFontData, m_font->fontDescription().textRenderingMode());
-                if (substituteFontData->m_ATSUStyle)
-                    ATSUSetRunStyle(layout, substituteFontData->m_ATSUStyle, substituteOffset, substituteLength);
-            } else
-                substituteFontData = fontData;
-        } else {
-            substituteOffset = runLength;
-            substituteLength = 0;
-        }
-
-        bool shapedArabic = false;
-        bool isSmallCap = false;
-        UniCharArrayOffset firstSmallCap = 0;
-        const SimpleFontData *r = fontData;
-        UniCharArrayOffset i;
-        for (i = lastOffset;  ; i++) {
-            if (i == substituteOffset || i == substituteOffset + substituteLength) {
-                if (isSmallCap) {
-                    isSmallCap = false;
-                    initializeATSUStyle(r->smallCapsFontData(m_font->fontDescription()), m_font->fontDescription().textRenderingMode());
-                    ATSUSetRunStyle(layout, r->smallCapsFontData(m_font->fontDescription())->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
-                }
-                if (i == substituteOffset && substituteLength > 0)
-                    r = substituteFontData;
-                else
-                    break;
-            }
-            if (!shapedArabic && WTF::Unicode::isArabicChar(m_run[i]) && !r->shapesArabic()) {
-                shapedArabic = true;
-                if (!m_charBuffer) {
-                    m_charBuffer.set(new UChar[runLength]);
-                    memcpy(m_charBuffer.get(), m_run.characters(), i * sizeof(UChar));
-                    ATSUTextMoved(layout, m_charBuffer.get());
-                }
-                shapeArabic(m_run.characters(), m_charBuffer.get(), runLength, i);
-            }
-            if (m_run.rtl() && !r->m_ATSUMirrors) {
-                UChar mirroredChar = u_charMirror(m_run[i]);
-                if (mirroredChar != m_run[i]) {
-                    if (!m_charBuffer) {
-                        m_charBuffer.set(new UChar[runLength]);
-                        memcpy(m_charBuffer.get(), m_run.characters(), runLength * sizeof(UChar));
-                        ATSUTextMoved(layout, m_charBuffer.get());
-                    }
-                    m_charBuffer[i] = mirroredChar;
-                }
-            }
-            if (m_font->isSmallCaps()) {
-                const SimpleFontData* smallCapsData = r->smallCapsFontData(m_font->fontDescription());
-                UChar c = m_charBuffer[i];
-                UChar newC;
-                if (U_GET_GC_MASK(c) & U_GC_M_MASK)
-                    m_fonts[i] = isSmallCap ? smallCapsData : r;
-                else if (!u_isUUppercase(c) && (newC = u_toupper(c)) != c) {
-                    m_charBuffer[i] = newC;
-                    if (!isSmallCap) {
-                        isSmallCap = true;
-                        firstSmallCap = i;
-                    }
-                    m_fonts[i] = smallCapsData;
-                } else {
-                    if (isSmallCap) {
-                        isSmallCap = false;
-                        initializeATSUStyle(smallCapsData, m_font->fontDescription().textRenderingMode());
-                        ATSUSetRunStyle(layout, smallCapsData->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
-                    }
-                    m_fonts[i] = r;
-                }
-            } else
-                m_fonts[i] = r;
-            if (m_fonts[i]->syntheticBoldOffset())
-                m_hasSyntheticBold = true;
-        }
-        substituteOffset += substituteLength;
-    }
-    if (m_run.padding()) {
-        float numSpaces = 0;
-        unsigned k;
-        for (k = 0; k < runLength; k++)
-            if (Font::treatAsSpace(m_run[k]))
-                numSpaces++;
-
-        if (numSpaces == 0)
-            m_padPerSpace = 0;
-        else
-            m_padPerSpace = ceilf(m_run.padding() / numSpaces);
-    } else
-        m_padPerSpace = 0;
-}
-
-FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
-{
-    OwnArrayPtr<UChar> charactersWithOverride;
-    TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);
-    if (run.directionalOverride()) {
-        from++;
-        to++;
-    }
-
-    ATSULayoutParameters params(adjustedRun);
-    params.initialize(this);
-
-    ATSTrapezoid firstGlyphBounds;
-    ItemCount actualNumBounds;
-    
-    OSStatus status = ATSUGetGlyphBounds(params.m_layout, 0, 0, from, to - from, kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);
-    if (status != noErr || actualNumBounds != 1) {
-        static ATSTrapezoid zeroTrapezoid = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
-        firstGlyphBounds = zeroTrapezoid;
-    }
-    
-    float beforeWidth = min(FixedToFloat(firstGlyphBounds.lowerLeft.x), FixedToFloat(firstGlyphBounds.upperLeft.x));
-    float afterWidth = max(FixedToFloat(firstGlyphBounds.lowerRight.x), FixedToFloat(firstGlyphBounds.upperRight.x));
-    
-    FloatRect rect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
-
-    return rect;
-}
-
-void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run, const FloatPoint& point, int from, int to) const
-{
-    OSStatus status;
-    
-    int drawPortionLength = to - from;
-    OwnArrayPtr<UChar> charactersWithOverride;
-    TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);
-    if (run.directionalOverride())
-        from++;
-
-    ATSULayoutParameters params(adjustedRun);
-    params.initialize(this, graphicsContext);
-    
-    // ATSUI can't draw beyond -32768 to +32767 so we translate the CTM and tell ATSUI to draw at (0, 0).
-    CGContextRef context = graphicsContext->platformContext();
-    CGContextTranslateCTM(context, point.x(), point.y());
-
-    IntSize shadowSize;
-    int shadowBlur;
-    Color shadowColor;
-    graphicsContext->getShadow(shadowSize, shadowBlur, shadowColor);
-
-    bool hasSimpleShadow = graphicsContext->textDrawingMode() == cTextFill && shadowColor.isValid() && !shadowBlur;
-    if (hasSimpleShadow) {
-        // Paint simple shadows ourselves instead of relying on CG shadows, to avoid losing subpixel antialiasing.
-        graphicsContext->clearShadow();
-        Color fillColor = graphicsContext->fillColor();
-        Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255);
-        graphicsContext->setFillColor(shadowFillColor);
-        CGContextTranslateCTM(context, shadowSize.width(), shadowSize.height());
-        status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
-        if (status == noErr && params.m_hasSyntheticBold) {
-            // Force relayout for the bold pass
-            ATSUClearLayoutCache(params.m_layout, 0);
-            params.m_syntheticBoldPass = true;
-            status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
-            // Force relayout for the next pass
-            ATSUClearLayoutCache(params.m_layout, 0);
-            params.m_syntheticBoldPass = false;
-        }
-        CGContextTranslateCTM(context, -shadowSize.width(), -shadowSize.height());
-        graphicsContext->setFillColor(fillColor);
-    }
-
-    status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
-    if (status == noErr && params.m_hasSyntheticBold) {
-        // Force relayout for the bold pass
-        ATSUClearLayoutCache(params.m_layout, 0);
-        params.m_syntheticBoldPass = true;
-        status = ATSUDrawText(params.m_layout, from, drawPortionLength, 0, 0);
-    }
-    CGContextTranslateCTM(context, -point.x(), -point.y());
-
-    if (status != noErr)
-        // Nothing to do but report the error (dev build only).
-        LOG_ERROR("ATSUDrawText() failed(%d)", status);
-
-    if (hasSimpleShadow)
-        graphicsContext->setShadow(shadowSize, shadowBlur, shadowColor);
-}
-
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
-{
-    if (run.length() == 0)
-        return 0;
-
-    ATSULayoutParameters params(run, fallbackFonts);
-    params.initialize(this);
-    
-    OSStatus status;
-    
-    ATSTrapezoid firstGlyphBounds;
-    ItemCount actualNumBounds;
-    status = ATSUGetGlyphBounds(params.m_layout, 0, 0, 0, run.length(), kATSUseFractionalOrigins, 1, &firstGlyphBounds, &actualNumBounds);    
-    if (status != noErr)
-        LOG_ERROR("ATSUGetGlyphBounds() failed(%d)", status);
-    if (actualNumBounds != 1)
-        LOG_ERROR("unexpected result from ATSUGetGlyphBounds(): actualNumBounds(%d) != 1", actualNumBounds);
-
-    return max(FixedToFloat(firstGlyphBounds.upperRight.x), FixedToFloat(firstGlyphBounds.lowerRight.x)) -
-           min(FixedToFloat(firstGlyphBounds.upperLeft.x), FixedToFloat(firstGlyphBounds.lowerLeft.x));
-}
-
-int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool /*includePartialGlyphs*/) const
-{
-    OwnArrayPtr<UChar> charactersWithOverride;
-    TextRun adjustedRun = copyRunForDirectionalOverrideIfNecessary(run, charactersWithOverride);
-
-    ATSULayoutParameters params(adjustedRun);
-    params.initialize(this);
-
-    UniCharArrayOffset primaryOffset = 0;
-    
-    // FIXME: No idea how to avoid including partial glyphs.
-    // Not even sure if that's the behavior this yields now.
-    Boolean isLeading;
-    UniCharArrayOffset secondaryOffset = 0;
-    OSStatus status = ATSUPositionToOffset(params.m_layout, FloatToFixed(x), FloatToFixed(-1), &primaryOffset, &isLeading, &secondaryOffset);
-    unsigned offset;
-    if (status == noErr) {
-        offset = (unsigned)primaryOffset;
-        if (run.directionalOverride() && offset > 0)
-            offset--;
-    } else
-        // Failed to find offset!  Return 0 offset.
-        offset = 0;
-
-    return offset;
-}
-
-}
-#endif // USE(ATSUI)
diff --git a/WebCore/platform/graphics/mac/FontMacCoreText.cpp b/WebCore/platform/graphics/mac/FontMacCoreText.cpp
deleted file mode 100644
index 9dffc7a..0000000
--- a/WebCore/platform/graphics/mac/FontMacCoreText.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 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 COMPUTER, INC. ``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 COMPUTER, INC. OR
- * 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 "Font.h"
-
-#if USE(CORE_TEXT)
-
-#include "CoreTextController.h"
-#include "FontFallbackList.h"
-#include "GlyphBuffer.h"
-#include "GraphicsContext.h"
-#include "IntRect.h"
-#include "SimpleFontData.h"
-#include <wtf/MathExtras.h>
-
-namespace WebCore {
-
-FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h,
-                                            int from, int to) const
-{
-    CoreTextController controller(this, run);
-    controller.advance(from);
-    float beforeWidth = controller.runWidthSoFar();
-    controller.advance(to);
-    float afterWidth = controller.runWidthSoFar();
-
-    // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
-    if (run.rtl()) {
-        float totalWidth = controller.totalWidth();
-        return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
-    } 
-
-    return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
-}
-
-void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point,
-                           int from, int to) const
-{
-    // This glyph buffer holds our glyphs + advances + font data for each glyph.
-    GlyphBuffer glyphBuffer;
-
-    float startX = point.x();
-    CoreTextController controller(this, run);
-    controller.advance(from);
-    float beforeWidth = controller.runWidthSoFar();
-    controller.advance(to, &glyphBuffer);
-    
-    // We couldn't generate any glyphs for the run.  Give up.
-    if (glyphBuffer.isEmpty())
-        return;
-    
-    float afterWidth = controller.runWidthSoFar();
-
-    if (run.rtl()) {
-        startX += controller.totalWidth() + controller.finalRoundingWidth() - afterWidth;
-        for (int i = 0, end = glyphBuffer.size() - 1; i < glyphBuffer.size() / 2; ++i, --end)
-            glyphBuffer.swap(i, end);
-    } else
-        startX += beforeWidth;
-
-    // Draw the glyph buffer now at the starting point returned in startX.
-    FloatPoint startPoint(startX, point.y());
-    drawGlyphBuffer(context, glyphBuffer, run, startPoint);
-}
-
-float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts) const
-{
-    CoreTextController controller(this, run, true, fallbackFonts);
-    return controller.totalWidth();
-}
-
-int Font::offsetForPositionForComplexText(const TextRun& run, int x, bool includePartialGlyphs) const
-{
-    CoreTextController controller(this, run);
-    return controller.offsetForPosition(x, includePartialGlyphs);
-}
-
-}
-#endif // USE(CORE_TEXT)

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list