Bug 8880, remove the remaining drawing/hit testing code from
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 13 May 2006 06:41:23 +0000 (06:41 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 13 May 2006 06:41:23 +0000 (06:41 +0000)
        FontData.

        Reviewed by tim h

        * platform/Font.cpp:
        (WebCore::m_finalRoundingWidth):
        (WebCore::WidthIterator::advanceOneCharacter):
        (WebCore::Font::selectionRectForText):
        (WebCore::Font::selectionRectForSimpleText):
        (WebCore::Font::offsetForPosition):
        (WebCore::Font::offsetForPositionForSimpleText):
        * platform/Font.h:
        (WebCore::TextRun::makeComplete):
        * platform/FontData.h:
        * platform/GlyphBuffer.h:
        (WebCore::GlyphBuffer::clear):
        * platform/mac/FontData.mm:
        * platform/mac/FontMac.mm:
        (WebCore::Font::selectionRectForComplexText):
        (WebCore::Font::offsetForPositionForComplexText):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@14350 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/platform/Font.cpp
WebCore/platform/Font.h
WebCore/platform/FontData.h
WebCore/platform/GlyphBuffer.h
WebCore/platform/mac/FontData.mm
WebCore/platform/mac/FontMac.mm

index a66014a..730d6a1 100644 (file)
@@ -1,3 +1,27 @@
+2006-05-12  David Hyatt  <hyatt@apple.com>
+
+        Bug 8880, remove the remaining drawing/hit testing code from
+        FontData.
+
+        Reviewed by tim h
+
+        * platform/Font.cpp:
+        (WebCore::m_finalRoundingWidth):
+        (WebCore::WidthIterator::advanceOneCharacter):
+        (WebCore::Font::selectionRectForText):
+        (WebCore::Font::selectionRectForSimpleText):
+        (WebCore::Font::offsetForPosition):
+        (WebCore::Font::offsetForPositionForSimpleText):
+        * platform/Font.h:
+        (WebCore::TextRun::makeComplete):
+        * platform/FontData.h:
+        * platform/GlyphBuffer.h:
+        (WebCore::GlyphBuffer::clear):
+        * platform/mac/FontData.mm:
+        * platform/mac/FontMac.mm:
+        (WebCore::Font::selectionRectForComplexText):
+        (WebCore::Font::offsetForPositionForComplexText):
+
 2006-05-12  Kevin M. Ollivier  <kevino@theolliviers.com>
 
         Reviewed by Maciej.
index 6e84ee2..cfe90eb 100644 (file)
@@ -34,6 +34,7 @@
 #include "GlyphBuffer.h"
 
 #include <unicode/umachine.h>
+#include <unicode/unorm.h>
 
 namespace WebCore {
 
@@ -59,7 +60,8 @@ struct WidthIterator {
     WidthIterator(const Font* font, const TextRun& run, const TextStyle& style, const FontData* substituteFontData = 0);
 
     void advance(int to, GlyphBuffer* glyphBuffer = 0);
-
+    bool advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer = 0);
+    
     const Font* m_font;
 
     const TextRun& m_run;
@@ -106,7 +108,8 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, const TextSty
     if (run.from() == 0)
         m_widthToStart = 0;
     else {
-        TextRun completeRun(run.characters(), run.length());
+        TextRun completeRun(run);
+        completeRun.makeComplete();
         WidthIterator startPositionIterator(font, completeRun, style, substituteFontData);
         startPositionIterator.advance(run.from());
         m_widthToStart = startPositionIterator.m_runWidthSoFar;
@@ -274,6 +277,17 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
     m_finalRoundingWidth = lastRoundingWidth;
 }
 
+bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer)
+{
+    glyphBuffer->clear();
+    advance(m_currentCharacter + 1, glyphBuffer);
+    float w = 0;
+    for (int i = 0; i < glyphBuffer->size(); ++i)
+        w += glyphBuffer->advanceAt(i);
+    width = w;
+    return !glyphBuffer->isEmpty();
+}
+
 UChar32 WidthIterator::normalizeVoicingMarks()
 {
     int currentCharacter = m_currentCharacter;
@@ -522,6 +536,85 @@ float Font::floatWidthForSimpleText(const TextRun& run, const TextStyle& style,
     }
     return runWidth;
 }
+
+FloatRect Font::selectionRectForText(const TextRun& run, const TextStyle& style, const IntPoint& point, int h) const
+{
+    if (canUseGlyphCache(run))
+        return selectionRectForSimpleText(run, style, point, h);
+    return selectionRectForComplexText(run, style, point, h);
+}
+
+FloatRect Font::selectionRectForSimpleText(const TextRun& run, const TextStyle& style, const IntPoint& point, int h) const
+{
+    TextRun completeRun(run);
+    completeRun.makeComplete();
+
+    WidthIterator it(this, completeRun, style);
+    it.advance(run.from());
+    float beforeWidth = it.m_runWidthSoFar;
+    it.advance(run.to());
+    float afterWidth = it.m_runWidthSoFar;
+
+    // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
+    if (style.rtl()) {
+        it.advance(run.length());
+        float totalWidth = it.m_runWidthSoFar;
+        return FloatRect(point.x() + floorf(totalWidth - afterWidth), point.y(), roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), h);
+    } else {
+        return FloatRect(point.x() + floorf(beforeWidth), point.y(), roundf(afterWidth) - floorf(beforeWidth), h);
+    }
+}
+
+int Font::offsetForPosition(const TextRun& run, const TextStyle& style, int x, bool includePartialGlyphs) const
+{
+    if (canUseGlyphCache(run))
+        return offsetForPositionForSimpleText(run, style, x, includePartialGlyphs);
+    return offsetForPositionForComplexText(run, style, x, includePartialGlyphs);
+}
+
+int Font::offsetForPositionForSimpleText(const TextRun& run, const TextStyle& style, int x, bool includePartialGlyphs) const
+{
+    float delta = (float)x;
+
+    WidthIterator it(this, run, style);    
+    GlyphBuffer localGlyphBuffer;
+    unsigned offset;
+    if (style.rtl()) {
+        delta -= floatWidthForSimpleText(run, style, 0, 0, 0);
+        while (1) {
+            offset = it.m_currentCharacter;
+            float w;
+            if (!it.advanceOneCharacter(w, &localGlyphBuffer))
+                break;
+            delta += w;
+            if (includePartialGlyphs) {
+                if (delta - w / 2 >= 0)
+                    break;
+            } else {
+                if (delta >= 0)
+                    break;
+            }
+        }
+    } else {
+        while (1) {
+            offset = it.m_currentCharacter;
+            float w;
+            if (!it.advanceOneCharacter(w, &localGlyphBuffer))
+                break;
+            delta -= w;
+            if (includePartialGlyphs) {
+                if (delta + w / 2 <= 0)
+                    break;
+            } else {
+                if (delta <= 0)
+                    break;
+            }
+        }
+    }
+
+    return offset - run.from();
+}
+
 #endif
 
 }
index 404ef0e..0ad09de 100644 (file)
@@ -67,6 +67,7 @@ public:
 
     int adjustFrom(int from) const { return from == -1 ? 0 : from; }
     int adjustTo(int to) const { return to == -1 ? m_len : to; }
+    void makeComplete() { m_from = 0; m_to = m_len; }
 
     const UChar* characters() const { return m_characters; }
     int length() const { return m_len; }
@@ -193,6 +194,10 @@ private:
     void drawComplexText(GraphicsContext*, const TextRun&, const TextStyle&, const FloatPoint&) const;
     float floatWidthForSimpleText(const TextRun&, const TextStyle&, const FontData* substituteFont, float* startX, GlyphBuffer*) const;
     float floatWidthForComplexText(const TextRun&, const TextStyle&) const;
+    int offsetForPositionForSimpleText(const TextRun&, const TextStyle&, int position, bool includePartialGlyphs) const;
+    int offsetForPositionForComplexText(const TextRun&, const TextStyle&, int position, bool includePartialGlyphs) const;
+    FloatRect selectionRectForSimpleText(const TextRun&, const TextStyle&, const IntPoint&, int h) const;
+    FloatRect selectionRectForComplexText(const TextRun&, const TextStyle&, const IntPoint&, int h) const;
 
     friend struct WidthIterator;
     
index 0a53b5d..0a52b73 100644 (file)
  */
 
 #if __APPLE__
-typedef UInt16                          ATSGlyphRef;
-typedef struct OpaqueATSUStyle*         ATSUStyle;
+// FIXME: This is going to be cross-platform eventually, but for now we just compile on OS X.
 
-#if __OBJC__
-@class NSColor;
-#else
-class NSColor;
-#endif
-
-#include "FloatPoint.h"
 #include "FontPlatformData.h"
 #include "GlyphBuffer.h"
 
 // FIXME: Temporary.  Only needed to support API that's going to move.
-#include <unicode/uchar.h>
-#include <unicode/unorm.h>
+#include <unicode/umachine.h>
 
 namespace WebCore
 {
 
-class FloatRect;
-class Color;
 class FontDescription;
 
-struct WebCoreTextStyle
-{
-    NSColor *textColor;
-    NSColor *backgroundColor;
-    int letterSpacing;
-    int wordSpacing;
-    int padding;
-    int tabWidth;
-    int xpos;
-    NSString **families;
-    bool smallCaps;
-    bool rtl;
-    bool directionalOverride;
-    bool applyRunRounding;
-    bool applyWordRounding;
-    bool attemptFontSubstitution;
-};
-
-struct WebCoreTextRun
-{
-    const UniChar *characters;
-    unsigned int length;
-    int from;
-    int to;
-};
-
-struct WebCoreTextGeometry
-{
-    FloatPoint point;
-    float selectionY;
-    float selectionHeight;
-    bool useFontMetricsForSelectionYAndHeight;
-};
-
-void WebCoreInitializeTextRun(WebCoreTextRun *run, const UniChar *characters, unsigned int length, int from, int to);
-void WebCoreInitializeEmptyTextStyle(WebCoreTextStyle *style);
-void WebCoreInitializeEmptyTextGeometry(WebCoreTextGeometry *geometry);
-
 typedef struct WidthMap WidthMap;
 typedef struct GlyphMap GlyphMap;
 
@@ -105,12 +56,6 @@ public:
 
     float xHeight() const;
 
-    // drawing
-    FloatRect selectionRectForRun(const WebCoreTextRun* run, const WebCoreTextStyle* style, const WebCoreTextGeometry* geometry);
-
-    // selection point check 
-    int pointToOffset(const WebCoreTextRun* run, const WebCoreTextStyle* style, int x, bool includePartialGlyphs);
-
     // FIXME: These are temporary API and will eventually move to the fallback list.
     Glyph glyphForCharacter(const FontData **renderer, unsigned c) const;
     const FontData* findSubstituteFontData(const UChar* characters, unsigned numCharacters, const FontDescription&) const;
index 13343cb..da7d298 100644 (file)
@@ -53,6 +53,15 @@ public:
     bool isEmpty() const { return m_fontData.isEmpty(); }
     int size() const { return m_fontData.size(); }
     
+    void clear()
+    {
+        m_fontData.clear();
+#if __APPLE__
+        m_glyphs.clear();
+        m_advances.clear();
+#endif
+    }
+
 #if __APPLE__
     Glyph* glyphs(int from) const { return ((Glyph*)m_glyphs.data()) + from; }
     CGSize* advances(int from) const { return ((CGSize*)m_advances.data()) + from; }
index d095bac..7795d4f 100644 (file)
@@ -64,9 +64,6 @@ namespace WebCore
 // Should be more than enough for normal usage.
 #define NUM_SUBSTITUTE_FONT_MAPS 10
 
-// According to http://www.unicode.org/Public/UNIDATA/UCD.html#Canonical_Combining_Class_Values
-#define HIRAGANA_KATAKANA_VOICING_MARKS 8
-
 #define SPACE 0x0020
 #define NO_BREAK_SPACE 0x00A0
 #define ZERO_WIDTH_SPACE 0x200B
@@ -114,30 +111,6 @@ struct GlyphMap {
     GlyphEntry *glyphs;
 };
 
-typedef struct WidthIterator {
-    FontData *renderer;
-    const WebCoreTextRun *run;
-    const WebCoreTextStyle *style;
-    unsigned currentCharacter;
-    float runWidthSoFar;
-    float widthToStart;
-    float padding;
-    float padPerSpace;
-    float finalRoundingWidth;
-} WidthIterator;
-
-typedef struct ATSULayoutParameters
-{
-    const WebCoreTextRun *run;
-    const WebCoreTextStyle *style;
-    ATSUTextLayout layout;
-    FontData **renderers;
-    UniChar *charBuffer;
-    bool hasSyntheticBold;
-    bool syntheticBoldPass;
-    float padPerSpace;
-} ATSULayoutParameters;
-
 static const FontData *rendererForAlternateFont(const FontData *, FontPlatformData);
 
 static WidthMap *extendWidthMap(const FontData *, ATSGlyphRef);
@@ -146,67 +119,14 @@ static ATSGlyphRef extendGlyphMap(const FontData *, UChar32);
 static void freeWidthMap(WidthMap *);
 static void freeGlyphMap(GlyphMap *);
 
-// Measuring runs.
-static float CG_floatWidthForRun(FontData *, const WebCoreTextRun *, const WebCoreTextStyle *,
-    float *widthBuffer, FontData **rendererBuffer, CGGlyph *glyphBuffer, float *startPosition, int *numGlyphsResult);
-
-// Selection point detection in runs.
-static int CG_pointToOffset(FontData *, const WebCoreTextRun *, const WebCoreTextStyle *,
-    int x, bool includePartialGlyphs);
-static int ATSU_pointToOffset(FontData *, const WebCoreTextRun *, const WebCoreTextStyle *,
-    int x, bool includePartialGlyphs);
-
-// Selection rect.
-static NSRect CG_selectionRect(FontData *, const WebCoreTextRun *, const WebCoreTextStyle *, const WebCoreTextGeometry *);
-static NSRect ATSU_selectionRect(FontData *, const WebCoreTextRun *, const WebCoreTextStyle *, const WebCoreTextGeometry *);
-
 static bool setUpFont(FontData *);
 
-// Iterator functions
-static void initializeWidthIterator(WidthIterator *iterator, FontData *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style);
-static unsigned advanceWidthIterator(WidthIterator *iterator, unsigned offset, float *widths, FontData **renderersUsed, ATSGlyphRef *glyphsUsed);
-
 static bool fillStyleWithAttributes(ATSUStyle style, NSFont *theFont);
-static bool shouldUseATSU(const WebCoreTextRun *run);
 
 #if !ERROR_DISABLED
 static NSString *pathFromFont(NSFont *font);
 #endif
 
-static void createATSULayoutParameters(ATSULayoutParameters *params, FontData *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style);
-static void disposeATSULayoutParameters(ATSULayoutParameters *params);
-
-// Character property functions.
-
-void WebCoreInitializeTextRun(WebCoreTextRun *run, const UniChar *characters, unsigned int length, int from, int to)
-{
-    run->characters = characters;
-    run->length = length;
-    run->from = from;
-    run->to = to;
-}
-
-void WebCoreInitializeEmptyTextStyle(WebCoreTextStyle *style)
-{
-    style->textColor = nil;
-    style->backgroundColor = nil;
-    style->letterSpacing = 0;
-    style->wordSpacing = 0;
-    style->padding = 0;
-    style->families = nil;
-    style->smallCaps = NO;
-    style->rtl = NO;
-    style->directionalOverride = NO;
-    style->applyRunRounding = YES;
-    style->applyWordRounding = YES;
-    style->attemptFontSubstitution = YES;
-}
-
-void WebCoreInitializeEmptyTextGeometry(WebCoreTextGeometry *geometry)
-{
-    geometry->useFontMetricsForSelectionYAndHeight = YES;
-}
-
 // Map utility functions
 
 float FontData::widthForGlyph(Glyph glyph) const
@@ -234,121 +154,6 @@ float FontData::widthForGlyph(Glyph glyph) const
     return width;
 }
 
-static OSStatus overrideLayoutOperation(ATSULayoutOperationSelector iCurrentOperation, ATSULineRef iLineRef, UInt32 iRefCon, void *iOperationCallbackParameterPtr, ATSULayoutOperationCallbackStatus *oCallbackStatus)
-{
-    ATSULayoutParameters *params = (ATSULayoutParameters *)iRefCon;
-    OSStatus status;
-    ItemCount count;
-    ATSLayoutRecord *layoutRecords;
-    const WebCoreTextStyle *style = params->style;
-
-    if (style->applyWordRounding) {
-        status = ATSUDirectGetLayoutDataArrayPtrFromLineRef(iLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, true, (void **)&layoutRecords, &count);
-        if (status != noErr) {
-            *oCallbackStatus = kATSULayoutOperationCallbackStatusContinue;
-            return status;
-        }
-        
-        Fixed lastNativePos = 0;
-        float lastAdjustedPos = 0;
-        const WebCoreTextRun *run = params->run;
-        const UniChar *characters = run->characters + run->from;
-        FontData **renderers = params->renderers + run->from;
-        FontData *renderer;
-        FontData *lastRenderer = 0;
-        UniChar ch, nextCh;
-        ByteCount offset = layoutRecords[0].originalOffset;
-        nextCh = *(UniChar *)(((char *)characters)+offset);
-        bool shouldRound = false;
-        bool syntheticBoldPass = params->syntheticBoldPass;
-        Fixed syntheticBoldOffset = 0;
-        ATSGlyphRef spaceGlyph = 0;
-        bool hasExtraSpacing = style->letterSpacing | style->wordSpacing | style->padding;
-        float padding = style->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];
-            if (renderer != lastRenderer) {
-                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->m_font.font renderingMode] == NSFontAntialiasedIntegerAdvancementsRenderingMode;
-                if (syntheticBoldPass) {
-                    syntheticBoldOffset = FloatToFixed(renderer->m_syntheticBoldOffset);
-                    spaceGlyph = renderer->m_spaceGlyph;
-                }
-            }
-            float width = FixedToFloat(layoutRecords[i].realPos - lastNativePos);
-            lastNativePos = layoutRecords[i].realPos;
-            if (shouldRound)
-                width = roundf(width);
-            width += renderer->m_syntheticBoldOffset;
-            if (renderer->m_treatAsFixedPitch ? width == renderer->m_spaceWidth : (layoutRecords[i-1].flags & kATSGlyphInfoIsWhiteSpace))
-                width = renderer->m_adjustedSpaceWidth;
-
-            if (hasExtraSpacing) {
-                if (width && style->letterSpacing)
-                    width +=style->letterSpacing;
-                if (Font::treatAsSpace(nextCh)) {
-                    if (style->padding) {
-                        if (padding < params->padPerSpace) {
-                            width += padding;
-                            padding = 0;
-                        } else {
-                            width += params->padPerSpace;
-                            padding -= params->padPerSpace;
-                        }
-                    }
-                    if (offset != 0 && !Font::treatAsSpace(*((UniChar *)(((char *)characters)+offset) - 1)) && style->wordSpacing)
-                        width += style->wordSpacing;
-                }
-            }
-
-            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 ? ' ' : *(UniChar *)(((char *)characters)+offset);
-
-            if (Font::isRoundingHackCharacter(ch))
-                width = ceilf(width);
-            lastAdjustedPos = lastAdjustedPos + width;
-            if (Font::isRoundingHackCharacter(nextCh)
-                && (!isLastChar
-                    || style->applyRunRounding
-                    || (run->to < (int)run->length && Font::isRoundingHackCharacter(characters[run->to - run->from])))) {
-                if (!style->rtl)
-                    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 = spaceGlyph;
-            }
-            layoutRecords[i].realPos = FloatToFixed(lastAdjustedPos);
-        }
-        
-        status = ATSUDirectReleaseLayoutDataArrayPtr(iLineRef, kATSUDirectDataLayoutRecordATSLayoutRecordCurrent, (void **)&layoutRecords);
-    }
-    *oCallbackStatus = kATSULayoutOperationCallbackStatusHandled;
-    return noErr;
-}
-
 static NSString *webFallbackFontFamily(void)
 {
     static NSString *webFallbackFontFamily = nil;
@@ -484,21 +289,6 @@ float FontData::xHeight() const
     return [m_font.font xHeight];
 }
 
-FloatRect FontData::selectionRectForRun(const WebCoreTextRun* run, const WebCoreTextStyle* style, const WebCoreTextGeometry* geometry)
-{
-    if (shouldUseATSU(run))
-        return ATSU_selectionRect(this, run, style, geometry);
-    else
-        return CG_selectionRect(this, run, style, geometry);
-}
-
-int FontData::pointToOffset(const WebCoreTextRun* run, const WebCoreTextStyle* style, int x, bool includePartialGlyphs)
-{
-    if (shouldUseATSU(run))
-        return ATSU_pointToOffset(this, run, style, x, includePartialGlyphs);
-    return CG_pointToOffset(this, run, style, x, includePartialGlyphs);
-}
-
 FontData* FontData::smallCapsFontData() const
 {
     if (!m_smallCapsFontData) {
@@ -671,63 +461,6 @@ static NSString *pathFromFont(NSFont *font)
 
 #endif
 
-static NSRect CG_selectionRect(FontData *renderer, const WebCoreTextRun * run, const WebCoreTextStyle *style, const WebCoreTextGeometry *geometry)
-{
-    float yPos = geometry->useFontMetricsForSelectionYAndHeight
-        ? geometry->point.y() - renderer->ascent() - (renderer->lineGap() / 2) : geometry->selectionY;
-    float height = geometry->useFontMetricsForSelectionYAndHeight
-        ? renderer->lineSpacing() : geometry->selectionHeight;
-
-    WebCoreTextRun completeRun = *run;
-    completeRun.from = 0;
-    completeRun.to = run->length;
-
-    WidthIterator it;
-    initializeWidthIterator(&it, renderer, &completeRun, style);
-    
-    advanceWidthIterator(&it, run->from, 0, 0, 0);
-    float beforeWidth = it.runWidthSoFar;
-    advanceWidthIterator(&it, run->to, 0, 0, 0);
-    float afterWidth = it.runWidthSoFar;
-    // Using roundf() rather than ceilf() for the right edge as a compromise to ensure correct caret positioning
-    if (style->rtl) {
-        advanceWidthIterator(&it, run->length, 0, 0, 0);
-        float totalWidth = it.runWidthSoFar;
-        return NSMakeRect(geometry->point.x() + floorf(totalWidth - afterWidth), yPos, roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth), height);
-    } else {
-        return NSMakeRect(geometry->point.x() + floorf(beforeWidth), yPos, roundf(afterWidth) - floorf(beforeWidth), height);
-    }
-}
-
-static float CG_floatWidthForRun(FontData *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style, float *widthBuffer, FontData **rendererBuffer, CGGlyph *glyphBuffer, float *startPosition, int *numGlyphsResult)
-{
-    WidthIterator it;
-    WebCoreTextRun completeRun;
-    const WebCoreTextRun *aRun;
-    if (!style->rtl)
-        aRun = run;
-    else {
-        completeRun = *run;
-        completeRun.to = run->length;
-        aRun = &completeRun;
-    }
-    initializeWidthIterator(&it, renderer, aRun, style);
-    int numGlyphs = advanceWidthIterator(&it, run->to, widthBuffer, rendererBuffer, glyphBuffer);
-    float runWidth = it.runWidthSoFar;
-    if (startPosition) {
-        if (!style->rtl)
-            *startPosition = it.widthToStart;
-        else {
-            float finalRoundingWidth = it.finalRoundingWidth;
-            advanceWidthIterator(&it, run->length, 0, 0, 0);
-            *startPosition = it.runWidthSoFar - runWidth + finalRoundingWidth;
-        }
-    }
-    if (numGlyphsResult)
-        *numGlyphsResult = numGlyphs;
-    return runWidth;
-}
-
 void FontData::updateGlyphMapEntry(UChar c, ATSGlyphRef glyph, const FontData *substituteRenderer) const
 {
     GlyphMap *map;
@@ -885,385 +618,6 @@ static WidthMap *extendWidthMap(const FontData *renderer, ATSGlyphRef glyph)
     return map;
 }
 
-static void initializeATSUStyle(FontData *renderer)
-{
-    // The two NSFont calls in this method (pointSize and _atsFontID) do not raise exceptions.
-
-    if (!renderer->m_ATSUStyleInitialized) {
-        OSStatus status;
-        ByteCount propTableSize;
-        
-        status = ATSUCreateStyle(&renderer->m_ATSUStyle);
-        if (status != noErr)
-            LOG_ERROR("ATSUCreateStyle failed (%d)", status);
-    
-        ATSUFontID fontID = wkGetNSFontATSUFontId(renderer->m_font.font);
-        if (fontID == 0) {
-            ATSUDisposeStyle(renderer->m_ATSUStyle);
-            LOG_ERROR("unable to get ATSUFontID for %@", renderer->m_font.font);
-            return;
-        }
-        
-        CGAffineTransform transform = CGAffineTransformMakeScale(1, -1);
-        if (renderer->m_font.syntheticOblique)
-            transform = CGAffineTransformConcat(transform, CGAffineTransformMake(1, 0, -tanf(SYNTHETIC_OBLIQUE_ANGLE * acosf(0) / 90), 1, 0, 0)); 
-        Fixed fontSize = FloatToFixed([renderer->m_font.font pointSize]);
-        // Turn off automatic kerning until it is supported in the CG code path (6136 in bugzilla)
-        Fract kerningInhibitFactor = FloatToFract(1.0);
-        ATSUAttributeTag styleTags[4] = { kATSUSizeTag, kATSUFontTag, kATSUFontMatrixTag, kATSUKerningInhibitFactorTag };
-        ByteCount styleSizes[4] = { sizeof(Fixed), sizeof(ATSUFontID), sizeof(CGAffineTransform), sizeof(Fract) };
-        ATSUAttributeValuePtr styleValues[4] = { &fontSize, &fontID, &transform, &kerningInhibitFactor };
-        status = ATSUSetAttributes(renderer->m_ATSUStyle, 4, styleTags, styleSizes, styleValues);
-        if (status != noErr)
-            LOG_ERROR("ATSUSetAttributes failed (%d)", status);
-        status = ATSFontGetTable(fontID, 'prop', 0, 0, 0, &propTableSize);
-        if (status == noErr)    // naively assume that if a 'prop' table exists then it contains mirroring info
-            renderer->m_ATSUMirrors = true;
-        else if (status == kATSInvalidFontTableAccess)
-            renderer->m_ATSUMirrors = false;
-        else
-            LOG_ERROR("ATSFontGetTable failed (%d)", status);
-
-        // Turn off ligatures such as 'fi' to match the CG code path's behavior, until bugzilla 6135 is fixed.
-        // 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 ([[renderer->m_font.font coveredCharacterSet] characterIsMember:'a']) {
-            ATSUFontFeatureType featureTypes[] = { kLigaturesType };
-            ATSUFontFeatureSelector featureSelectors[] = { kCommonLigaturesOffSelector };
-            status = ATSUSetFontFeatures(renderer->m_ATSUStyle, 1, featureTypes, featureSelectors);
-        }
-
-        renderer->m_ATSUStyleInitialized = true;
-    }
-}
-
-static void createATSULayoutParameters(ATSULayoutParameters *params, FontData *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style)
-{
-    params->run = run;
-    params->style = style;
-    // FIXME: It is probably best to always allocate a buffer for RTL, since even if for this
-    // renderer ATSUMirrors is true, for a substitute renderer it might be false.
-    FontData** renderers = new FontData*[run->length];
-    params->renderers = renderers;
-    UniChar *charBuffer = (UniChar*)((style->smallCaps || (style->rtl && !renderer->m_ATSUMirrors)) ? new UniChar[run->length] : 0);
-    params->charBuffer = charBuffer;
-    params->syntheticBoldPass = false;
-
-    // The only Cocoa calls here are to NSGraphicsContext, which does not raise exceptions.
-
-    ATSUTextLayout layout;
-    OSStatus status;
-    ATSULayoutOperationOverrideSpecifier overrideSpecifier;
-    
-    initializeATSUStyle(renderer);
-    
-    // FIXME: This is currently missing the following required features that the CoreGraphics code path has:
-    // - \n, \t, and nonbreaking space render as a space.
-    // - Other control characters do not render (other code path uses zero-width spaces).
-
-    UniCharCount totalLength = run->length;
-    UniCharArrayOffset runTo = (run->to == -1 ? totalLength : (unsigned int)run->to);
-    UniCharArrayOffset runFrom = run->from;
-    
-    if (charBuffer)
-        memcpy(charBuffer, run->characters, totalLength * sizeof(UniChar));
-
-    UniCharCount runLength = runTo - runFrom;
-    
-    status = ATSUCreateTextLayoutWithTextPtr(
-            (charBuffer ? charBuffer : run->characters),
-            runFrom,        // offset
-            runLength,      // length
-            totalLength,    // total length
-            1,              // styleRunCount
-            &runLength,     // length of style run
-            &renderer->m_ATSUStyle, 
-            &layout);
-    if (status != noErr)
-        LOG_ERROR("ATSUCreateTextLayoutWithTextPtr failed(%d)", status);
-    params->layout = layout;
-    ATSUSetTextLayoutRefCon(layout, (UInt32)params);
-
-    CGContextRef cgContext = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
-    ATSLineLayoutOptions lineLayoutOptions = kATSLineKeepSpacesOutOfMargin | kATSLineHasNoHangers;
-    Boolean rtl = style->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, (style->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);
-
-    params->hasSyntheticBold = false;
-    ATSUFontID ATSUSubstituteFont;
-    UniCharArrayOffset substituteOffset = runFrom;
-    UniCharCount substituteLength;
-    UniCharArrayOffset lastOffset;
-    FontData *substituteRenderer = 0;
-
-    while (substituteOffset < runTo) {
-        lastOffset = substituteOffset;
-        status = ATSUMatchFontsToText(layout, substituteOffset, kATSUToTextEnd, &ATSUSubstituteFont, &substituteOffset, &substituteLength);
-        if (status == kATSUFontsMatched || status == kATSUFontsNotMatched) {
-            substituteRenderer = (FontData*)findSubstituteRenderer(renderer, run->characters+substituteOffset, substituteLength, style->families);
-            if (substituteRenderer) {
-                initializeATSUStyle(substituteRenderer);
-                if (substituteRenderer->m_ATSUStyle)
-                    ATSUSetRunStyle(layout, substituteRenderer->m_ATSUStyle, substituteOffset, substituteLength);
-            } else
-                substituteRenderer = renderer;
-        } else {
-            substituteOffset = runTo;
-            substituteLength = 0;
-        }
-
-        bool isSmallCap = false;
-        UniCharArrayOffset firstSmallCap = 0;
-        FontData *r = renderer;
-        UniCharArrayOffset i;
-        for (i = lastOffset;  ; i++) {
-            if (i == substituteOffset || i == substituteOffset + substituteLength) {
-                if (isSmallCap) {
-                    isSmallCap = false;
-                    initializeATSUStyle(r->smallCapsFontData());
-                    ATSUSetRunStyle(layout, r->smallCapsFontData()->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
-                }
-                if (i == substituteOffset && substituteLength > 0)
-                    r = substituteRenderer;
-                else
-                    break;
-            }
-            if (rtl && charBuffer && !r->m_ATSUMirrors)
-                charBuffer[i] = u_charMirror(charBuffer[i]);
-            if (style->smallCaps) {
-                UniChar c = charBuffer[i];
-                UniChar newC;
-                if (U_GET_GC_MASK(c) & U_GC_M_MASK)
-                    renderers[i] = isSmallCap ? r->smallCapsFontData() : r;
-                else if (!u_isUUppercase(c) && (newC = u_toupper(c)) != c) {
-                    charBuffer[i] = newC;
-                    if (!isSmallCap) {
-                        isSmallCap = true;
-                        firstSmallCap = i;
-                    }
-                    renderers[i] = r->smallCapsFontData();
-                } else {
-                    if (isSmallCap) {
-                        isSmallCap = false;
-                        initializeATSUStyle(r->smallCapsFontData());
-                        ATSUSetRunStyle(layout, r->smallCapsFontData()->m_ATSUStyle, firstSmallCap, i - firstSmallCap);
-                    }
-                    renderers[i] = r;
-                }
-            } else
-                renderers[i] = r;
-            if (renderers[i]->m_syntheticBoldOffset)
-                params->hasSyntheticBold = true;
-        }
-        substituteOffset += substituteLength;
-    }
-    if (style->padding) {
-        float numSpaces = 0;
-        unsigned k;
-        for (k = 0; k < totalLength; k++)
-            if (Font::treatAsSpace(run->characters[k]))
-                numSpaces++;
-
-        params->padPerSpace = ceilf(style->padding / numSpaces);
-    } else
-        params->padPerSpace = 0;
-}
-
-static void disposeATSULayoutParameters(ATSULayoutParameters *params)
-{
-    ATSUDisposeTextLayout(params->layout);
-    delete []params->charBuffer;
-    delete []params->renderers;
-}
-
-// Be sure to free the run.characters allocated by this function.
-static WebCoreTextRun addDirectionalOverride(const WebCoreTextRun *run, bool rtl)
-{
-    int from = run->from;
-    int to = run->to;
-    if (from == -1)
-        from = 0;
-    if (to == -1)
-        to = run->length;
-
-    UniChar *charactersWithOverride = new UniChar[run->length + 2];
-
-    charactersWithOverride[0] = rtl ? RIGHT_TO_LEFT_OVERRIDE : LEFT_TO_RIGHT_OVERRIDE;
-    memcpy(&charactersWithOverride[1], &run->characters[0], sizeof(UniChar) * run->length);
-    charactersWithOverride[run->length + 1] = POP_DIRECTIONAL_FORMATTING;
-
-    WebCoreTextRun runWithOverride;
-
-    runWithOverride.from = from + 1;
-    runWithOverride.to = to + 1;
-    runWithOverride.length = run->length + 2;
-    runWithOverride.characters = charactersWithOverride;
-
-    return runWithOverride;
-}
-
-static NSRect ATSU_selectionRect(FontData *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style, const WebCoreTextGeometry *geometry)
-{
-    int from = run->from;
-    int to = run->to;
-    if (from == -1)
-        from = 0;
-    if (to == -1)
-        to = run->length;
-        
-    WebCoreTextRun completeRun = *run;
-    completeRun.from = 0;
-    completeRun.to = run->length;
-    
-    WebCoreTextRun *aRun = &completeRun;
-    WebCoreTextRun swappedRun;
-    
-    if (style->directionalOverride) {
-        swappedRun = addDirectionalOverride(aRun, style->rtl);
-        aRun = &swappedRun;
-        from++;
-        to++;
-    }
-   
-    ATSULayoutParameters params;
-    createATSULayoutParameters(&params, renderer, aRun, style);
-    
-    ATSTrapezoid firstGlyphBounds;
-    ItemCount actualNumBounds;
-    
-    OSStatus status = ATSUGetGlyphBounds(params.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;
-    }
-    disposeATSULayoutParameters(&params);    
-    
-    float beforeWidth = MIN(FixedToFloat(firstGlyphBounds.lowerLeft.x), FixedToFloat(firstGlyphBounds.upperLeft.x));
-    float afterWidth = MAX(FixedToFloat(firstGlyphBounds.lowerRight.x), FixedToFloat(firstGlyphBounds.upperRight.x));
-    float yPos = geometry->useFontMetricsForSelectionYAndHeight
-        ? geometry->point.y() - renderer->ascent() : geometry->selectionY;
-    float height = geometry->useFontMetricsForSelectionYAndHeight
-        ? renderer->lineSpacing() : geometry->selectionHeight;
-
-    NSRect rect = NSMakeRect(geometry->point.x() + floorf(beforeWidth), yPos, roundf(afterWidth) - floorf(beforeWidth), height);
-
-    if (style->directionalOverride)
-        delete []swappedRun.characters;
-
-    return rect;
-}
-
-static int ATSU_pointToOffset(FontData *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style,
-    int x, bool includePartialGlyphs)
-{
-    const WebCoreTextRun *aRun = run;
-    WebCoreTextRun swappedRun;
-    
-    // Enclose in LRO/RLO - PDF to force ATSU to render visually.
-    if (style->directionalOverride) {
-        swappedRun = addDirectionalOverride(aRun, style->rtl);
-        aRun = &swappedRun;
-    }
-
-    ATSULayoutParameters params;
-    createATSULayoutParameters(&params, renderer, aRun, style);
-
-    UniCharArrayOffset primaryOffset = aRun->from;
-    
-    // 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.layout, FloatToFixed(x), FloatToFixed(-1), &primaryOffset, &isLeading, &secondaryOffset);
-    unsigned offset;
-    if (status == noErr) {
-        offset = (unsigned)primaryOffset;
-    } else {
-        // Failed to find offset!  Return 0 offset.
-        offset = 0;
-    }
-
-    disposeATSULayoutParameters(&params);
-    
-    if (style->directionalOverride)
-        delete []swappedRun.characters;
-
-    return offset - aRun->from;
-}
-
-static bool advanceWidthIteratorOneCharacter(WidthIterator *iterator, float *totalWidth)
-{
-    float widths[MAX_GLYPH_EXPANSION];
-    FontData *renderers[MAX_GLYPH_EXPANSION];
-    ATSGlyphRef glyphs[MAX_GLYPH_EXPANSION];            
-    unsigned numGlyphs = advanceWidthIterator(iterator, iterator->currentCharacter + 1, widths, renderers, glyphs);
-    unsigned i;
-    float w = 0;
-    for (i = 0; i < numGlyphs; ++i)
-        w += widths[i];
-    *totalWidth = w;
-    return numGlyphs != 0;
-}
-
-static int CG_pointToOffset(FontData *renderer, const WebCoreTextRun * run, const WebCoreTextStyle *style,
-    int x, bool includePartialGlyphs)
-{
-    float delta = (float)x;
-
-    WidthIterator it;    
-    initializeWidthIterator(&it, renderer, run, style);
-
-    unsigned offset;
-
-    if (style->rtl) {
-        delta -= CG_floatWidthForRun(renderer, run, style, 0, 0, 0, 0, 0);
-        while (1) {
-            offset = it.currentCharacter;
-            float w;
-            if (!advanceWidthIteratorOneCharacter(&it, &w))
-                break;
-            delta += w;
-            if (includePartialGlyphs) {
-                if (delta - w / 2 >= 0)
-                    break;
-            } else {
-                if (delta >= 0)
-                    break;
-            }
-        }
-    } else {
-        while (1) {
-            offset = it.currentCharacter;
-            float w;
-            if (!advanceWidthIteratorOneCharacter(&it, &w))
-                break;
-            delta -= w;
-            if (includePartialGlyphs) {
-                if (delta + w / 2 <= 0)
-                    break;
-            } else {
-                if (delta <= 0)
-                    break;
-            }
-        }
-    }
-
-    return offset - run->from;
-}
-
 static void freeWidthMap(WidthMap *map)
 {
     while (map) {
@@ -1302,247 +656,6 @@ Glyph FontData::glyphForCharacter(const FontData **renderer, unsigned c) const
     return extendGlyphMap(*renderer, c);
 }
 
-static void initializeWidthIterator(WidthIterator *iterator, FontData *renderer, const WebCoreTextRun *run, const WebCoreTextStyle *style) 
-{
-    iterator->renderer = renderer;
-    iterator->run = run;
-    iterator->style = style;
-    iterator->currentCharacter = run->from;
-    iterator->runWidthSoFar = 0;
-    iterator->finalRoundingWidth = 0;
-
-    // If the padding is non-zero, count the number of spaces in the run
-    // and divide that by the padding for per space addition.
-    if (!style->padding) {
-        iterator->padding = 0;
-        iterator->padPerSpace = 0;
-    } else {
-        float numSpaces = 0;
-        int k;
-        for (k = run->from; k < run->to; k++)
-            if (Font::treatAsSpace(run->characters[k]))
-                numSpaces++;
-
-        iterator->padding = style->padding;
-        iterator->padPerSpace = ceilf(iterator->padding / numSpaces);
-    }
-    
-    // Calculate width up to starting position of the run.  This is
-    // necessary to ensure that our rounding hacks are always consistently
-    // applied.
-    if (run->from == 0) {
-        iterator->widthToStart = 0;
-    } else {
-        WebCoreTextRun startPositionRun = *run;
-        startPositionRun.from = 0;
-        startPositionRun.to = run->length;
-        WidthIterator startPositionIterator;
-        initializeWidthIterator(&startPositionIterator, renderer, &startPositionRun, style);
-        advanceWidthIterator(&startPositionIterator, run->from, 0, 0, 0);
-        iterator->widthToStart = startPositionIterator.runWidthSoFar;
-    }
-}
-
-static UChar32 normalizeVoicingMarks(WidthIterator *iterator)
-{
-    unsigned currentCharacter = iterator->currentCharacter;
-    const WebCoreTextRun *run = iterator->run;
-    if (currentCharacter + 1 < (unsigned)run->to) {
-        if (u_getCombiningClass(run->characters[currentCharacter + 1]) == HIRAGANA_KATAKANA_VOICING_MARKS) {
-            // Normalize into composed form using 3.2 rules.
-            UChar normalizedCharacters[2] = { 0, 0 };
-            UErrorCode uStatus = (UErrorCode)0;                
-            int32_t resultLength = unorm_normalize(&run->characters[currentCharacter], 2,
-                UNORM_NFC, UNORM_UNICODE_3_2, &normalizedCharacters[0], 2, &uStatus);
-            if (resultLength == 1 && uStatus == 0)
-                return normalizedCharacters[0];
-        }
-    }
-    return 0;
-}
-
-static unsigned advanceWidthIterator(WidthIterator *iterator, unsigned offset, float *widths, FontData **renderersUsed, ATSGlyphRef *glyphsUsed)
-{
-    const WebCoreTextRun *run = iterator->run;
-    if (offset > (unsigned)run->to)
-        offset = run->to;
-
-    unsigned numGlyphs = 0;
-
-    unsigned currentCharacter = iterator->currentCharacter;
-    const UniChar *cp = &run->characters[currentCharacter];
-
-    const WebCoreTextStyle *style = iterator->style;
-    bool rtl = style->rtl;
-    bool needCharTransform = rtl || style->smallCaps;
-    bool hasExtraSpacing = style->letterSpacing || style->wordSpacing || style->padding;
-
-    float runWidthSoFar = iterator->runWidthSoFar;
-    float lastRoundingWidth = iterator->finalRoundingWidth;
-
-    while (currentCharacter < offset) {
-        UChar32 c = *cp;
-
-        unsigned clusterLength = 1;
-        if (c >= 0x3041) {
-            if (c <= 0x30FE) {
-                // Deal with Hiragana and Katakana voiced and semi-voiced syllables.
-                // Normalize into composed form, and then look for glyph with base + combined mark.
-                // Check above for character range to minimize performance impact.
-                UChar32 normalized = normalizeVoicingMarks(iterator);
-                if (normalized) {
-                    c = normalized;
-                    clusterLength = 2;
-                }
-            } else if (U16_IS_SURROGATE(c)) {
-                if (!U16_IS_SURROGATE_LEAD(c))
-                    break;
-
-                // Do we have a surrogate pair?  If so, determine the full Unicode (32 bit)
-                // code point before glyph lookup.
-                // Make sure we have another character and it's a low surrogate.
-                if (currentCharacter + 1 >= run->length)
-                    break;
-                UniChar low = cp[1];
-                if (!U16_IS_TRAIL(low))
-                    break;
-                c = U16_GET_SUPPLEMENTARY(c, low);
-                clusterLength = 2;
-            }
-        }
-
-        const FontData *renderer = iterator->renderer;
-
-        if (needCharTransform) {
-            if (rtl)
-                c = u_charMirror(c);
-
-            // If small-caps, convert lowercase to upper.
-            if (style->smallCaps && !u_isUUppercase(c)) {
-                UChar32 upperC = u_toupper(c);
-                if (upperC != c) {
-                    c = upperC;
-                    renderer = renderer->smallCapsFontData();
-                }
-            }
-        }
-
-        Glyph glyph = renderer->glyphForCharacter(&renderer, c);
-
-        // Now that we have glyph and font, get its width.
-        WebGlyphWidth width;
-        if (c == '\t' && style->tabWidth) {
-            width = style->tabWidth - fmodf(style->xpos + runWidthSoFar, style->tabWidth);
-        } else {
-            width = renderer->widthForGlyph(glyph);
-            // 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 characters that
-            // match the width of the space character have the same width as the space character.
-            if (width == renderer->m_spaceWidth && (renderer->m_treatAsFixedPitch || glyph == renderer->m_spaceGlyph) && style->applyWordRounding)
-                width = renderer->m_adjustedSpaceWidth;
-        }
-
-        // Try to find a substitute font if this font didn't have a glyph for a character in the
-        // string. If one isn't found we end up drawing and measuring the 0 glyph, usually a box.
-        if (glyph == 0 && style->attemptFontSubstitution) {
-            FontData *substituteRenderer = (FontData*)findSubstituteRenderer(renderer, cp, clusterLength, style->families);
-            if (substituteRenderer) {
-                WebCoreTextRun clusterRun = { cp, clusterLength, 0, clusterLength };
-                WebCoreTextStyle clusterStyle = *style;
-                clusterStyle.padding = 0;
-                clusterStyle.applyRunRounding = NO;
-                clusterStyle.attemptFontSubstitution = NO;
-                
-                int cNumGlyphs;
-                float localWidthBuffer[MAX_GLYPH_EXPANSION];
-                FontData *localRendererBuffer[MAX_GLYPH_EXPANSION];
-                ATSGlyphRef localGlyphBuffer[MAX_GLYPH_EXPANSION];            
-                CG_floatWidthForRun(substituteRenderer, &clusterRun, &clusterStyle, localWidthBuffer, localRendererBuffer, localGlyphBuffer, 0, &cNumGlyphs);
-                if (cNumGlyphs == 1) {
-                    assert(substituteRenderer == localRendererBuffer[0]);
-                    width = localWidthBuffer[0];
-                    glyph = localGlyphBuffer[0];
-                    renderer->updateGlyphMapEntry(c, glyph, substituteRenderer);
-                    renderer = substituteRenderer;
-                }
-            }
-        }
-
-        if (hasExtraSpacing) {
-            // Account for letter-spacing.
-            if (width && style->letterSpacing)
-                width += style->letterSpacing;
-
-            if (Font::treatAsSpace(c)) {
-                // Account for padding. WebCore uses space padding to justify text.
-                // We distribute the specified padding over the available spaces in the run.
-                if (style->padding) {
-                    // Use left over padding if not evenly divisible by number of spaces.
-                    if (iterator->padding < iterator->padPerSpace) {
-                        width += iterator->padding;
-                        iterator->padding = 0;
-                    } else {
-                        width += iterator->padPerSpace;
-                        iterator->padding -= iterator->padPerSpace;
-                    }
-                }
-
-                // Account for word spacing.
-                // We apply additional space between "words" by adding width to the space character.
-                if (currentCharacter != 0 && !Font::treatAsSpace(cp[-1]) && style->wordSpacing)
-                    width += style->wordSpacing;
-            }
-        }
-
-        // Advance past the character we just dealt with.
-        cp += clusterLength;
-        currentCharacter += clusterLength;
-
-        // Account for float/integer impedance mismatch between CG and KHTML. "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.
-        // If we move KHTML to floats we can remove this (and related) hacks.
-
-        float oldWidth = width;
-
-        // Force characters that are used to determine word boundaries for the rounding hack
-        // to be integer width, so following words will start on an integer boundary.
-        if (style->applyWordRounding && Font::isRoundingHackCharacter(c))
-            width = ceilf(width);
-
-        // Check to see if the next character is a "rounding hack character", if so, adjust
-        // width so that the total run width will be on an integer boundary.
-        if ((style->applyWordRounding && currentCharacter < run->length && Font::isRoundingHackCharacter(*cp))
-                || (style->applyRunRounding && currentCharacter >= (unsigned)run->to)) {
-            float totalWidth = iterator->widthToStart + runWidthSoFar + width;
-            width += ceilf(totalWidth) - totalWidth;
-        }
-
-        runWidthSoFar += width;
-
-        if (!widths) {
-            assert(!renderersUsed);
-            assert(!glyphsUsed);
-        } else {
-            assert(renderersUsed);
-            assert(glyphsUsed);
-            *widths++ = (rtl ? oldWidth + lastRoundingWidth : width);
-            *renderersUsed++ = (FontData*)renderer;
-            *glyphsUsed++ = glyph;
-        }
-
-        lastRoundingWidth = width - oldWidth;
-        ++numGlyphs;
-    }
-
-    iterator->currentCharacter = currentCharacter;
-    iterator->runWidthSoFar = runWidthSoFar;
-    iterator->finalRoundingWidth = lastRoundingWidth;
-
-    return numGlyphs;
-}
-
 static bool fillStyleWithAttributes(ATSUStyle style, NSFont *theFont)
 {
     if (!theFont)
@@ -1559,59 +672,4 @@ static bool fillStyleWithAttributes(ATSUStyle style, NSFont *theFont)
     return YES;
 }
 
-static bool shouldUseATSU(const WebCoreTextRun *run)
-{
-    if (Font::gAlwaysUseComplexPath)
-        return YES;
-        
-    const UniChar *characters = run->characters;
-    int to = run->to;
-    int i;
-    // Start from 0 since drawing and highlighting also measure the characters before run->from
-    for (i = 0; i < to; i++) {
-        UniChar c = characters[i];
-        if (c < 0x300)      // U+0300 through U+036F Combining diacritical marks
-            continue;
-        if (c <= 0x36F)
-            return YES;
-
-        if (c < 0x0591 || c == 0x05BE)     // U+0591 through U+05CF excluding U+05BE Hebrew combining marks, Hebrew punctuation Paseq, Sof Pasuq and Nun Hafukha
-            continue;
-        if (c <= 0x05CF)
-            return YES;
-
-        if (c < 0x0600)     // U+0600 through U+1059 Arabic, Syriac, Thaana, Devanagari, Bengali, Gurmukhi, Gujarati, Oriya, Tamil, Telugu, Kannada, Malayalam, Sinhala, Thai, Lao, Tibetan, Myanmar
-            continue;
-        if (c <= 0x1059)
-            return YES;
-
-        if (c < 0x1100)     // U+1100 through U+11FF Hangul Jamo (only Ancient Korean should be left here if you precompose; Modern Korean will be precomposed as a result of step A)
-            continue;
-        if (c <= 0x11FF)
-            return YES;
-
-        if (c < 0x1780)     // U+1780 through U+18AF Khmer, Mongolian
-            continue;
-        if (c <= 0x18AF)
-            return YES;
-
-        if (c < 0x1900)     // U+1900 through U+194F Limbu (Unicode 4.0)
-            continue;
-        if (c <= 0x194F)
-            return YES;
-
-        if (c < 0x20D0)     // U+20D0 through U+20FF Combining marks for symbols
-            continue;
-        if (c <= 0x20FF)
-            return YES;
-
-        if (c < 0xFE20)     // U+FE20 through U+FE2F Combining half marks
-            continue;
-        if (c <= 0xFE2F)
-            return YES;
-    }
-
-    return NO;
-}
-
 }
index 6f22049..72cf8b2 100644 (file)
@@ -484,32 +484,42 @@ const FontPlatformData& Font::platformFont() const
     return m_fontList->platformFont(fontDescription());
 }
 
-FloatRect Font::selectionRectForText(const TextRun& textRun, const TextStyle& textStyle, const IntPoint& point, int h) const
+FloatRect Font::selectionRectForComplexText(const TextRun& run, const TextStyle& style, const IntPoint& point, int h) const
 {
-    assert(m_fontList);
-
-    CREATE_FAMILY_ARRAY(fontDescription(), families);
-
-    WebCoreTextRun run;
-    WebCoreInitializeTextRun(&run, textRun.characters(), textRun.length(), textRun.from(), textRun.to());
-    WebCoreTextStyle style;
-    WebCoreInitializeEmptyTextStyle(&style);
-    style.rtl = textStyle.rtl();
-    style.directionalOverride = textStyle.directionalOverride();
-    style.letterSpacing = letterSpacing();
-    style.wordSpacing = wordSpacing();
-    style.smallCaps = fontDescription().smallCaps();
-    style.families = families;    
-    style.padding = textStyle.padding();
-    style.tabWidth = textStyle.tabWidth();
-    style.xpos = textStyle.xPos();
-    WebCoreTextGeometry geometry;
-    WebCoreInitializeEmptyTextGeometry(&geometry);
-    geometry.point = point;
-    geometry.selectionY = point.y();
-    geometry.selectionHeight = h;
-    geometry.useFontMetricsForSelectionYAndHeight = false;
-    return m_fontList->primaryFont(fontDescription())->selectionRectForRun(&run, &style, &geometry);
+    int from = run.from();
+    int to = run.to();
+        
+    TextRun completeRun(run);
+    completeRun.makeComplete();
+    
+    TextRun adjustedRun = style.directionalOverride() ? addDirectionalOverride(completeRun, style.rtl()) : completeRun;
+    if (style.directionalOverride()) {
+        from++;
+        to++;
+    }
+
+    ATSULayoutParameters params(adjustedRun, style);
+    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;
+    }
+    disposeATSULayoutParameters(&params);
+    
+    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);
+
+    if (style.directionalOverride())
+        delete []adjustedRun.characters();
+
+    return rect;
 }
 
 void Font::drawComplexText(GraphicsContext* graphicsContext, const TextRun& run, const TextStyle& style, const FloatPoint& point) const
@@ -575,27 +585,33 @@ float Font::floatWidthForComplexText(const TextRun& run, const TextStyle& style)
            MIN(FixedToFloat(firstGlyphBounds.upperLeft.x), FixedToFloat(firstGlyphBounds.lowerLeft.x));
 }
 
-int Font::offsetForPosition(const TextRun& textRun, const TextStyle& textStyle, int x, bool includePartialGlyphs) const
+int Font::offsetForPositionForComplexText(const TextRun& run, const TextStyle& style, int x, bool includePartialGlyphs) const
 {
-    assert(m_fontList);
-    CREATE_FAMILY_ARRAY(fontDescription(), families);
+    TextRun adjustedRun = style.directionalOverride() ? addDirectionalOverride(run, style.rtl()) : run;
+    
+    ATSULayoutParameters params(adjustedRun, style);
+    params.initialize(this);
+
+    UniCharArrayOffset primaryOffset = adjustedRun.from();
     
-    WebCoreTextRun run;
-    WebCoreInitializeTextRun(&run, textRun.characters(), textRun.length(), textRun.from(), textRun.to());
+    // 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;
+    else
+        // Failed to find offset!  Return 0 offset.
+        offset = 0;
+
+    disposeATSULayoutParameters(&params);
     
-    WebCoreTextStyle style;
-    WebCoreInitializeEmptyTextStyle(&style);
-    style.letterSpacing = letterSpacing();
-    style.wordSpacing = wordSpacing();
-    style.smallCaps = fontDescription().smallCaps();
-    style.families = families;
-    style.padding = textStyle.padding();
-    style.tabWidth = textStyle.tabWidth();
-    style.xpos = textStyle.xPos();
-    style.rtl = textStyle.rtl();
-    style.directionalOverride = textStyle.directionalOverride();
-
-    return m_fontList->primaryFont(fontDescription())->pointToOffset(&run, &style, x, includePartialGlyphs);
+    if (style.directionalOverride())
+        delete []adjustedRun.characters();
+
+    return offset - adjustedRun.from();
 }
 
 void Font::drawGlyphs(GraphicsContext* context, const FontData* font, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const