<rdar://problem/8446709> Allow inter-ideograph justification for CJK
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Jan 2011 01:39:27 +0000 (01:39 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Jan 2011 01:39:27 +0000 (01:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=53184

Reviewed by Dave Hyatt.

Source/WebCore:

Tests: fast/text/justify-ideograph-complex.html
       fast/text/justify-ideograph-simple.html
       fast/text/justify-ideograph-vertical.html

* html/canvas/CanvasRenderingContext2D.cpp:
(WebCore::CanvasRenderingContext2D::drawTextInternal): Corrected the type of the third parameter
passed to the TextRun constructor and added the trailingExpansionBehavior parameter.
* platform/graphics/Font.cpp:
(WebCore::Font::expansionOpportunityCount): Added. Returns the number of expansion opportunities
for text justification. On entry, isAfterExpansion says whether an expansion opportunity exists
before the first character. On return, isAfterExpansion says whether an expansion opportunity
exists after the last character.
* platform/graphics/Font.h:
* platform/graphics/GlyphBuffer.h:
(WebCore::GlyphBuffer::expandLastAdvance): Added.
* platform/graphics/TextRun.h:
(WebCore::TextRun::TextRun): Added a TrailingExpansionBehavior parameter to the constructors.
Renamed padding to expansion.
(WebCore::TextRun::expansion): Renamed padding() to this.
(WebCore::TextRun::allowsTrailingExpansion): Added this accessor.
* platform/graphics/WidthIterator.cpp:
(WebCore::WidthIterator::WidthIterator): Initialize m_isAfterExpansion. Use Font::expansionOpportunityCount()
and adjust the count if it includes a trailing expansion opportunity but the run disallows trailing
expansion.
(WebCore::WidthIterator::advance): Apply expansion before and after CJK ideographs.
(WebCore::WidthIterator::advanceOneCharacter): Changed to not clear the GlyphBuffer so that advance()
can expand the last advance if it is followed by a CJK ideograph.
* platform/graphics/WidthIterator.h: Renamed m_padding to m_expansion and m_padPerSpace
to m_expansionPerOpportunity.
* platform/graphics/chromium/FontChromiumWin.cpp:
(WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
* platform/graphics/chromium/FontLinux.cpp:
(WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
* platform/graphics/efl/FontEfl.cpp:
(WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
* platform/graphics/gtk/FontGtk.cpp:
(WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
* platform/graphics/haiku/FontHaiku.cpp:
(WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
* platform/graphics/mac/ComplexTextController.cpp:
(WebCore::ComplexTextController::ComplexTextController): Initialize m_isAfterExpansion. Use
Font::expansionOpportunityCount() and adjust the count if it includes a trailing expansion
opportunity but the run disallows trailing expansion.
(WebCore::ComplexTextController::adjustGlyphsAndAdvances): Moved the definition and initialization
of hasExtraSpacing outside the loop. Apply expansion before and after CJK ideographs.
* platform/graphics/mac/ComplexTextController.h: Renamed m_padding to m_expansion and m_padPerSpace
to m_expansionPerOpportunity.
* platform/graphics/mac/FontMac.mm:
(WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
* platform/graphics/qt/FontQt.cpp:
(WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
* platform/graphics/win/FontWin.cpp:
(WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
* platform/graphics/win/UniscribeController.cpp:
(WebCore::UniscribeController::UniscribeController): Updated for rename.
* platform/graphics/wince/FontWinCE.cpp:
(WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
* platform/graphics/wx/FontWx.cpp:
(WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
* rendering/EllipsisBox.cpp:
(WebCore::EllipsisBox::paint): Pass a TrailingExpansionBehavior to the TextRun constructor.
(WebCore::EllipsisBox::selectionRect): Ditto.
(WebCore::EllipsisBox::paintSelection): Ditto.
* rendering/InlineBox.h:
(WebCore::InlineBox::InlineBox): Renamed m_toAdd to m_expansion.
(WebCore::InlineBox::expansion): Renamed toAdd() to this.
* rendering/InlineTextBox.cpp:
(WebCore::InlineTextBox::selectionRect): Pass a TrailingExpansionBehavior to the TextRun constructor.
(WebCore::InlineTextBox::paint): Ditto.
(WebCore::InlineTextBox::paintSelection): Ditto.
(WebCore::InlineTextBox::paintCompositionBackground): Ditto.
(WebCore::InlineTextBox::paintSpellingOrGrammarMarker): Ditto.
(WebCore::InlineTextBox::paintTextMatchMarker): Ditto.
(WebCore::InlineTextBox::computeRectForReplacementMarker): Ditto.
(WebCore::InlineTextBox::offsetForPosition): Ditto.
(WebCore::InlineTextBox::positionForOffset): Ditto.
* rendering/InlineTextBox.h:
(WebCore::InlineTextBox::setExpansion): Renamed setSpaceAdd() to this.
(WebCore::InlineTextBox::trailingExpansionBehavior): Added. Trailing expansion is allowed if this
is not the last leaf box on the line.
* rendering/RenderBlockLineLayout.cpp:
(WebCore::RenderBlock::computeInlineDirectionPositionsForLine): Keep expansion opportunity counts
in a vector instead of computing them twice. Discard the trailing expansion opportunity in the
last text box.
* rendering/RenderFileUploadControl.cpp:
(WebCore::RenderFileUploadControl::paintObject): Pass a TrailingExpansionBehavior to the TextRun constructor.
(WebCore::RenderFileUploadControl::computePreferredLogicalWidths): Ditto.
* rendering/RenderListBox.cpp:
(WebCore::RenderListBox::updateFromElement): Ditto.
(WebCore::RenderListBox::paintItemForeground): Ditto. Also corrected the type of the second parameter.
* rendering/RenderTextControl.cpp:
(WebCore::RenderTextControl::getAvgCharWidth): Ditto.
(WebCore::RenderTextControl::paintPlaceholder): Ditto.
* rendering/svg/SVGInlineTextBox.cpp:
(WebCore::SVGInlineTextBox::constructTextRun): Ditto.

Source/WebKit/chromium:

* src/WebTextRun.cpp:
(WebKit::WebTextRun::operator WebCore::TextRun): Added a TrailingExpansionBehavior parameter to the
RenderText constructor.

Source/WebKit2:

* WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp:
(WebKit::WebPopupMenu::setUpPlatformData): Added a TrailingExpansionBehavior parameter to the
RenderText constructor.

LayoutTests:

* fast/text/justify-ideograph-complex.html: Added.
* fast/text/justify-ideograph-simple.html: Added.
* fast/text/justify-ideograph-vertical.html: Added.
* platform/mac/fast/text/justify-ideograph-complex-expected.checksum: Added.
* platform/mac/fast/text/justify-ideograph-complex-expected.png: Added.
* platform/mac/fast/text/justify-ideograph-complex-expected.txt: Added.
* platform/mac/fast/text/justify-ideograph-simple-expected.checksum: Added.
* platform/mac/fast/text/justify-ideograph-simple-expected.png: Added.
* platform/mac/fast/text/justify-ideograph-simple-expected.txt: Added.
* platform/mac/fast/text/justify-ideograph-vertical-expected.checksum: Added.
* platform/mac/fast/text/justify-ideograph-vertical-expected.png: Added.
* platform/mac/fast/text/justify-ideograph-vertical-expected.txt: Added.

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

50 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/text/justify-ideograph-complex.html [new file with mode: 0644]
LayoutTests/fast/text/justify-ideograph-simple.html [new file with mode: 0644]
LayoutTests/fast/text/justify-ideograph-vertical.html [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/justify-ideograph-complex-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/justify-ideograph-complex-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/justify-ideograph-complex-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/justify-ideograph-simple-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/justify-ideograph-simple-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/justify-ideograph-simple-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/justify-ideograph-vertical-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/justify-ideograph-vertical-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/justify-ideograph-vertical-expected.txt [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
Source/WebCore/platform/chromium/PopupMenuChromium.cpp
Source/WebCore/platform/graphics/Font.cpp
Source/WebCore/platform/graphics/Font.h
Source/WebCore/platform/graphics/GlyphBuffer.h
Source/WebCore/platform/graphics/TextRun.h
Source/WebCore/platform/graphics/WidthIterator.cpp
Source/WebCore/platform/graphics/WidthIterator.h
Source/WebCore/platform/graphics/chromium/FontChromiumWin.cpp
Source/WebCore/platform/graphics/chromium/FontLinux.cpp
Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp
Source/WebCore/platform/graphics/efl/FontEfl.cpp
Source/WebCore/platform/graphics/gtk/FontGtk.cpp
Source/WebCore/platform/graphics/haiku/FontHaiku.cpp
Source/WebCore/platform/graphics/mac/ComplexTextController.cpp
Source/WebCore/platform/graphics/mac/ComplexTextController.h
Source/WebCore/platform/graphics/mac/FontMac.mm
Source/WebCore/platform/graphics/qt/FontQt.cpp
Source/WebCore/platform/graphics/win/FontWin.cpp
Source/WebCore/platform/graphics/win/UniscribeController.cpp
Source/WebCore/platform/graphics/wince/FontWinCE.cpp
Source/WebCore/platform/graphics/wx/FontWx.cpp
Source/WebCore/platform/win/PopupMenuWin.cpp
Source/WebCore/rendering/EllipsisBox.cpp
Source/WebCore/rendering/InlineBox.h
Source/WebCore/rendering/InlineTextBox.cpp
Source/WebCore/rendering/InlineTextBox.h
Source/WebCore/rendering/RenderBlockLineLayout.cpp
Source/WebCore/rendering/RenderFileUploadControl.cpp
Source/WebCore/rendering/RenderListBox.cpp
Source/WebCore/rendering/RenderTextControl.cpp
Source/WebCore/rendering/svg/SVGInlineTextBox.cpp
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/src/WebTextRun.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp

index 96d3b46..f44f256 100644 (file)
@@ -1,3 +1,23 @@
+2011-01-26  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Dave Hyatt.
+
+        <rdar://problem/8446709> Allow inter-ideograph justification for CJK
+        https://bugs.webkit.org/show_bug.cgi?id=53184
+
+        * fast/text/justify-ideograph-complex.html: Added.
+        * fast/text/justify-ideograph-simple.html: Added.
+        * fast/text/justify-ideograph-vertical.html: Added.
+        * platform/mac/fast/text/justify-ideograph-complex-expected.checksum: Added.
+        * platform/mac/fast/text/justify-ideograph-complex-expected.png: Added.
+        * platform/mac/fast/text/justify-ideograph-complex-expected.txt: Added.
+        * platform/mac/fast/text/justify-ideograph-simple-expected.checksum: Added.
+        * platform/mac/fast/text/justify-ideograph-simple-expected.png: Added.
+        * platform/mac/fast/text/justify-ideograph-simple-expected.txt: Added.
+        * platform/mac/fast/text/justify-ideograph-vertical-expected.checksum: Added.
+        * platform/mac/fast/text/justify-ideograph-vertical-expected.png: Added.
+        * platform/mac/fast/text/justify-ideograph-vertical-expected.txt: Added.
+
 2011-01-26  Martin Robinson  <mrobinson@igalia.com>
 
         Add the final set of CSS 2.1 GTK+ baselines.
diff --git a/LayoutTests/fast/text/justify-ideograph-complex.html b/LayoutTests/fast/text/justify-ideograph-complex.html
new file mode 100644 (file)
index 0000000..3ab3aeb
--- /dev/null
@@ -0,0 +1,10 @@
+<meta charset="utf-8">
+<style>
+    p { width: 550px; text-align: justify; font-size: 12px; font-family: 'Lucida Grande'; text-rendering: optimizelegibility; }
+</style>
+<p>【2009 年 11 月 4 日美國加州 Cupertino 訊】蘋果今天宣佈,全世界最大的應用程式商店 App Store,目前已擁有 100,000 多種來自全球開發人員的應用程式。全世界 77 個國家的 iPhone® 與 iPod touch® 用戶擁有 20 個類別的應用程式可供選擇,包括:遊戲、商用、新聞、運動、醫療、參考書籍、旅遊等等。截至目前為止,App Store 使用者下載次數已超過 20 億次,是目前全球最受歡迎的應用程式商店。
+<p>蘋果全球產品行銷資深副總裁 Philip Schiller 表示:「提供 100,000 多種應用程式可供選擇的 App Store,是全世界數千萬 iPhone 和 iPod touch 使用者令人稱羨的主要原因。iPhone SDK 創造了第一個優異的行動應用程式平台,客戶也非常喜愛開發人員所創作的應用程式。」</p>
+<p>EA Mobile 的 Worldwide Studios 副總裁 Travis Boatman 指出:「App Store 不僅徹底改變了行動遊戲產業的生態,而且還在持續演進。有了全球 5 千多萬的 iPhone 和 iPod touch 客戶為基礎,App Store 讓我們能夠開發受到廣大的客戶喜愛的高品質 EA 遊戲。」</p>
+<p>Smule 的執行長 Jeff Smith 表示:「我們的 I Am T-Pain 應用程式受到全球客戶的熱烈迴響,每日超過 10,000 次的下載遠遠超越我們的預期。App Store 給了我們一個獨特的商機,讓我們開創一個非常成功的事業,相信未來將更令人期待。」</p>
+<p>蘋果也持續開發新的功能來提升搜尋與探索的便利性,包括:Genius for Apps、App Store Essentials、子分類清單,以及更豐富而寶貴的客戶評論。隨著新版的 iTunes® 9 推出,現在您可以輕輕鬆鬆直接在 iTunes 當中整理您的應用程式,一旦同步之後,iPhone 或 iPod touch 就會自動出現您所安排的配置。</p>
+<p>今年夏天推出的 iPhone OS 3.0 為 iPhone 和 iPod touch 使用者提供了 100 多種全新的功能,包括:剪貼與拷貝;MMS;新增橫向檢視的 Mail、Text 和 Notes;立體聲 Bluetooth;搖一搖就隨機播放;電視節目分級保護控制;自動登入 Wi-Fi 熱點;以及 Push Notification 服務通知等等。這些新增功能受到客戶的廣大歡迎,截至目前為止,已經有超過 20 億次的 Push Notification 服務通知發送至 App Store 應用程式。此外,最近推出的應用程式內購買機制 (In-App Purchase),為領先的應用程式開發廠商提供了一種方式讓客戶直接從應用程式當中購買內容、訂閱項目及數位服務。</p>
diff --git a/LayoutTests/fast/text/justify-ideograph-simple.html b/LayoutTests/fast/text/justify-ideograph-simple.html
new file mode 100644 (file)
index 0000000..fce1668
--- /dev/null
@@ -0,0 +1,10 @@
+<meta charset="utf-8">
+<style>
+    p { width: 550px; text-align: justify; font-size: 12px; font-family: 'Lucida Grande'; }
+</style>
+<p>【2009 年 11 月 4 日美國加州 Cupertino 訊】蘋果今天宣佈,全世界最大的應用程式商店 App Store,目前已擁有 100,000 多種來自全球開發人員的應用程式。全世界 77 個國家的 iPhone® 與 iPod touch® 用戶擁有 20 個類別的應用程式可供選擇,包括:遊戲、商用、新聞、運動、醫療、參考書籍、旅遊等等。截至目前為止,App Store 使用者下載次數已超過 20 億次,是目前全球最受歡迎的應用程式商店。
+<p>蘋果全球產品行銷資深副總裁 Philip Schiller 表示:「提供 100,000 多種應用程式可供選擇的 App Store,是全世界數千萬 iPhone 和 iPod touch 使用者令人稱羨的主要原因。iPhone SDK 創造了第一個優異的行動應用程式平台,客戶也非常喜愛開發人員所創作的應用程式。」</p>
+<p>EA Mobile 的 Worldwide Studios 副總裁 Travis Boatman 指出:「App Store 不僅徹底改變了行動遊戲產業的生態,而且還在持續演進。有了全球 5 千多萬的 iPhone 和 iPod touch 客戶為基礎,App Store 讓我們能夠開發受到廣大的客戶喜愛的高品質 EA 遊戲。」</p>
+<p>Smule 的執行長 Jeff Smith 表示:「我們的 I Am T-Pain 應用程式受到全球客戶的熱烈迴響,每日超過 10,000 次的下載遠遠超越我們的預期。App Store 給了我們一個獨特的商機,讓我們開創一個非常成功的事業,相信未來將更令人期待。」</p>
+<p>蘋果也持續開發新的功能來提升搜尋與探索的便利性,包括:Genius for Apps、App Store Essentials、子分類清單,以及更豐富而寶貴的客戶評論。隨著新版的 iTunes® 9 推出,現在您可以輕輕鬆鬆直接在 iTunes 當中整理您的應用程式,一旦同步之後,iPhone 或 iPod touch 就會自動出現您所安排的配置。</p>
+<p>今年夏天推出的 iPhone OS 3.0 為 iPhone 和 iPod touch 使用者提供了 100 多種全新的功能,包括:剪貼與拷貝;MMS;新增橫向檢視的 Mail、Text 和 Notes;立體聲 Bluetooth;搖一搖就隨機播放;電視節目分級保護控制;自動登入 Wi-Fi 熱點;以及 Push Notification 服務通知等等。這些新增功能受到客戶的廣大歡迎,截至目前為止,已經有超過 20 億次的 Push Notification 服務通知發送至 App Store 應用程式。此外,最近推出的應用程式內購買機制 (In-App Purchase),為領先的應用程式開發廠商提供了一種方式讓客戶直接從應用程式當中購買內容、訂閱項目及數位服務。</p>
diff --git a/LayoutTests/fast/text/justify-ideograph-vertical.html b/LayoutTests/fast/text/justify-ideograph-vertical.html
new file mode 100644 (file)
index 0000000..5c87ba2
--- /dev/null
@@ -0,0 +1,12 @@
+<meta charset="utf-8">
+<style>
+    p { height: 550px; text-align: justify; font-size: 12px; font-family: 'Lucida Grande'; }
+</style>
+<div style="-webkit-writing-mode: vertical-rl; height: 550px;">
+<p>【2009 年 11 月 4 日美國加州 Cupertino 訊】蘋果今天宣佈,全世界最大的應用程式商店 App Store,目前已擁有 100,000 多種來自全球開發人員的應用程式。全世界 77 個國家的 iPhone® 與 iPod touch® 用戶擁有 20 個類別的應用程式可供選擇,包括:遊戲、商用、新聞、運動、醫療、參考書籍、旅遊等等。截至目前為止,App Store 使用者下載次數已超過 20 億次,是目前全球最受歡迎的應用程式商店。
+<p>蘋果全球產品行銷資深副總裁 Philip Schiller 表示:「提供 100,000 多種應用程式可供選擇的 App Store,是全世界數千萬 iPhone 和 iPod touch 使用者令人稱羨的主要原因。iPhone SDK 創造了第一個優異的行動應用程式平台,客戶也非常喜愛開發人員所創作的應用程式。」</p>
+<p>EA Mobile 的 Worldwide Studios 副總裁 Travis Boatman 指出:「App Store 不僅徹底改變了行動遊戲產業的生態,而且還在持續演進。有了全球 5 千多萬的 iPhone 和 iPod touch 客戶為基礎,App Store 讓我們能夠開發受到廣大的客戶喜愛的高品質 EA 遊戲。」</p>
+<p>Smule 的執行長 Jeff Smith 表示:「我們的 I Am T-Pain 應用程式受到全球客戶的熱烈迴響,每日超過 10,000 次的下載遠遠超越我們的預期。App Store 給了我們一個獨特的商機,讓我們開創一個非常成功的事業,相信未來將更令人期待。」</p>
+<p>蘋果也持續開發新的功能來提升搜尋與探索的便利性,包括:Genius for Apps、App Store Essentials、子分類清單,以及更豐富而寶貴的客戶評論。隨著新版的 iTunes® 9 推出,現在您可以輕輕鬆鬆直接在 iTunes 當中整理您的應用程式,一旦同步之後,iPhone 或 iPod touch 就會自動出現您所安排的配置。</p>
+<p>今年夏天推出的 iPhone OS 3.0 為 iPhone 和 iPod touch 使用者提供了 100 多種全新的功能,包括:剪貼與拷貝;MMS;新增橫向檢視的 Mail、Text 和 Notes;立體聲 Bluetooth;搖一搖就隨機播放;電視節目分級保護控制;自動登入 Wi-Fi 熱點;以及 Push Notification 服務通知等等。這些新增功能受到客戶的廣大歡迎,截至目前為止,已經有超過 20 億次的 Push Notification 服務通知發送至 App Store 應用程式。此外,最近推出的應用程式內購買機制 (In-App Purchase),為領先的應用程式開發廠商提供了一種方式讓客戶直接從應用程式當中購買內容、訂閱項目及數位服務。</p>
+</div>
diff --git a/LayoutTests/platform/mac/fast/text/justify-ideograph-complex-expected.checksum b/LayoutTests/platform/mac/fast/text/justify-ideograph-complex-expected.checksum
new file mode 100644 (file)
index 0000000..b3d7151
--- /dev/null
@@ -0,0 +1 @@
+0091eb5817d8785a9a9f3686f84932e6
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/text/justify-ideograph-complex-expected.png b/LayoutTests/platform/mac/fast/text/justify-ideograph-complex-expected.png
new file mode 100644 (file)
index 0000000..b634ceb
Binary files /dev/null and b/LayoutTests/platform/mac/fast/text/justify-ideograph-complex-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/text/justify-ideograph-complex-expected.txt b/LayoutTests/platform/mac/fast/text/justify-ideograph-complex-expected.txt
new file mode 100644 (file)
index 0000000..8cbc292
--- /dev/null
@@ -0,0 +1,41 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x580
+      RenderBlock {P} at (0,0) size 550x90
+        RenderText {#text} at (0,1) size 550x87
+          text run at (0,1) width 550: "\x{3010}2009 \x{5E74} 11 \x{6708} 4 \x{65E5}\x{7F8E}\x{570B}\x{52A0}\x{5DDE} Cupertino \x{8A0A}\x{3011}\x{860B}\x{679C}\x{4ECA}\x{5929}\x{5BA3}\x{4F48}\x{FF0C}\x{5168}\x{4E16}\x{754C}\x{6700}\x{5927}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5546}\x{5E97} App"
+          text run at (0,19) width 550: "Store\x{FF0C}\x{76EE}\x{524D}\x{5DF2}\x{64C1}\x{6709} 100,000 \x{591A}\x{7A2E}\x{4F86}\x{81EA}\x{5168}\x{7403}\x{958B}\x{767C}\x{4EBA}\x{54E1}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{3002}\x{5168}\x{4E16}\x{754C} 77 \x{500B}\x{570B}\x{5BB6}\x{7684} iPhone\x{AE} \x{8207}"
+          text run at (0,37) width 550: "iPod touch\x{AE} \x{7528}\x{6236}\x{64C1}\x{6709} 20 \x{500B}\x{985E}\x{5225}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{53EF}\x{4F9B}\x{9078}\x{64C7}\x{FF0C}\x{5305}\x{62EC}\x{FF1A}\x{904A}\x{6232}\x{3001}\x{5546}\x{7528}\x{3001}\x{65B0}\x{805E}\x{3001}\x{904B}\x{52D5}\x{3001}\x{91AB}\x{7642}\x{3001}\x{53C3}\x{8003}"
+          text run at (0,55) width 550: "\x{66F8}\x{7C4D}\x{3001}\x{65C5}\x{904A}\x{7B49}\x{7B49}\x{3002}\x{622A}\x{81F3}\x{76EE}\x{524D}\x{70BA}\x{6B62}\x{FF0C}App Store \x{4F7F}\x{7528}\x{8005}\x{4E0B}\x{8F09}\x{6B21}\x{6578}\x{5DF2}\x{8D85}\x{904E} 20 \x{5104}\x{6B21}\x{FF0C}\x{662F}\x{76EE}\x{524D}\x{5168}\x{7403}\x{6700}\x{53D7}\x{6B61}\x{8FCE}\x{7684}"
+          text run at (0,73) width 84: "\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5546}\x{5E97}\x{3002}"
+      RenderBlock {P} at (0,102) size 550x54
+        RenderText {#text} at (0,1) size 550x51
+          text run at (0,1) width 550: "\x{860B}\x{679C}\x{5168}\x{7403}\x{7522}\x{54C1}\x{884C}\x{92B7}\x{8CC7}\x{6DF1}\x{526F}\x{7E3D}\x{88C1} Philip Schiller \x{8868}\x{793A}\x{FF1A}\x{300C}\x{63D0}\x{4F9B} 100,000 \x{591A}\x{7A2E}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{53EF}\x{4F9B}\x{9078}\x{64C7}\x{7684} App"
+          text run at (0,19) width 550: "Store\x{FF0C}\x{662F}\x{5168}\x{4E16}\x{754C}\x{6578}\x{5343}\x{842C} iPhone \x{548C} iPod touch \x{4F7F}\x{7528}\x{8005}\x{4EE4}\x{4EBA}\x{7A31}\x{7FA8}\x{7684}\x{4E3B}\x{8981}\x{539F}\x{56E0}\x{3002}iPhone SDK \x{5275}\x{9020}\x{4E86}\x{7B2C}\x{4E00}"
+          text run at (0,37) width 408: "\x{500B}\x{512A}\x{7570}\x{7684}\x{884C}\x{52D5}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5E73}\x{53F0}\x{FF0C}\x{5BA2}\x{6236}\x{4E5F}\x{975E}\x{5E38}\x{559C}\x{611B}\x{958B}\x{767C}\x{4EBA}\x{54E1}\x{6240}\x{5275}\x{4F5C}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{3002}\x{300D}"
+      RenderBlock {P} at (0,168) size 550x54
+        RenderText {#text} at (0,1) size 550x51
+          text run at (0,1) width 550: "EA Mobile \x{7684} Worldwide Studios \x{526F}\x{7E3D}\x{88C1} Travis Boatman \x{6307}\x{51FA}\x{FF1A}\x{300C}App Store \x{4E0D}\x{50C5}\x{5FB9}\x{5E95}\x{6539}\x{8B8A}\x{4E86}\x{884C}\x{52D5}"
+          text run at (0,19) width 550: "\x{904A}\x{6232}\x{7522}\x{696D}\x{7684}\x{751F}\x{614B}\x{FF0C}\x{800C}\x{4E14}\x{9084}\x{5728}\x{6301}\x{7E8C}\x{6F14}\x{9032}\x{3002}\x{6709}\x{4E86}\x{5168}\x{7403} 5 \x{5343}\x{591A}\x{842C}\x{7684} iPhone \x{548C} iPod touch \x{5BA2}\x{6236}\x{70BA}\x{57FA}\x{790E}\x{FF0C}App"
+          text run at (0,37) width 345: "Store \x{8B93}\x{6211}\x{5011}\x{80FD}\x{5920}\x{958B}\x{767C}\x{53D7}\x{5230}\x{5EE3}\x{5927}\x{7684}\x{5BA2}\x{6236}\x{559C}\x{611B}\x{7684}\x{9AD8}\x{54C1}\x{8CEA} EA \x{904A}\x{6232}\x{3002}\x{300D}"
+      RenderBlock {P} at (0,234) size 550x54
+        RenderText {#text} at (0,1) size 550x51
+          text run at (0,1) width 550: "Smule \x{7684}\x{57F7}\x{884C}\x{9577} Jeff Smith \x{8868}\x{793A}\x{FF1A}\x{300C}\x{6211}\x{5011}\x{7684} I Am T-Pain \x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{53D7}\x{5230}\x{5168}\x{7403}\x{5BA2}\x{6236}\x{7684}\x{71B1}\x{70C8}\x{8FF4}\x{97FF}\x{FF0C}\x{6BCF}\x{65E5}\x{8D85}"
+          text run at (0,19) width 550: "\x{904E} 10,000 \x{6B21}\x{7684}\x{4E0B}\x{8F09}\x{9060}\x{9060}\x{8D85}\x{8D8A}\x{6211}\x{5011}\x{7684}\x{9810}\x{671F}\x{3002}App Store \x{7D66}\x{4E86}\x{6211}\x{5011}\x{4E00}\x{500B}\x{7368}\x{7279}\x{7684}\x{5546}\x{6A5F}\x{FF0C}\x{8B93}\x{6211}\x{5011}\x{958B}\x{5275}\x{4E00}\x{500B}\x{975E}\x{5E38}"
+          text run at (0,37) width 216: "\x{6210}\x{529F}\x{7684}\x{4E8B}\x{696D}\x{FF0C}\x{76F8}\x{4FE1}\x{672A}\x{4F86}\x{5C07}\x{66F4}\x{4EE4}\x{4EBA}\x{671F}\x{5F85}\x{3002}\x{300D}"
+      RenderBlock {P} at (0,300) size 550x72
+        RenderText {#text} at (0,1) size 550x69
+          text run at (0,1) width 550: "\x{860B}\x{679C}\x{4E5F}\x{6301}\x{7E8C}\x{958B}\x{767C}\x{65B0}\x{7684}\x{529F}\x{80FD}\x{4F86}\x{63D0}\x{5347}\x{641C}\x{5C0B}\x{8207}\x{63A2}\x{7D22}\x{7684}\x{4FBF}\x{5229}\x{6027}\x{FF0C}\x{5305}\x{62EC}\x{FF1A}Genius for Apps\x{3001}App Store"
+          text run at (0,19) width 550: "Essentials\x{3001}\x{5B50}\x{5206}\x{985E}\x{6E05}\x{55AE}\x{FF0C}\x{4EE5}\x{53CA}\x{66F4}\x{8C50}\x{5BCC}\x{800C}\x{5BF6}\x{8CB4}\x{7684}\x{5BA2}\x{6236}\x{8A55}\x{8AD6}\x{3002}\x{96A8}\x{8457}\x{65B0}\x{7248}\x{7684} iTunes\x{AE} 9 \x{63A8}\x{51FA}\x{FF0C}\x{73FE}\x{5728}\x{60A8}\x{53EF}\x{4EE5}\x{8F15}"
+          text run at (0,37) width 550: "\x{8F15}\x{9B06}\x{9B06}\x{76F4}\x{63A5}\x{5728} iTunes \x{7576}\x{4E2D}\x{6574}\x{7406}\x{60A8}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{FF0C}\x{4E00}\x{65E6}\x{540C}\x{6B65}\x{4E4B}\x{5F8C}\x{FF0C}iPhone \x{6216} iPod touch \x{5C31}\x{6703}\x{81EA}\x{52D5}\x{51FA}\x{73FE}\x{60A8}"
+          text run at (0,55) width 84: "\x{6240}\x{5B89}\x{6392}\x{7684}\x{914D}\x{7F6E}\x{3002}"
+      RenderBlock {P} at (0,384) size 550x108
+        RenderText {#text} at (0,1) size 550x105
+          text run at (0,1) width 550: "\x{4ECA}\x{5E74}\x{590F}\x{5929}\x{63A8}\x{51FA}\x{7684} iPhone OS 3.0 \x{70BA} iPhone \x{548C} iPod touch \x{4F7F}\x{7528}\x{8005}\x{63D0}\x{4F9B}\x{4E86} 100 \x{591A}\x{7A2E}\x{5168}\x{65B0}\x{7684}\x{529F}\x{80FD}\x{FF0C}\x{5305}"
+          text run at (0,19) width 550: "\x{62EC}\x{FF1A}\x{526A}\x{8CBC}\x{8207}\x{62F7}\x{8C9D}\x{FF1B}MMS\x{FF1B}\x{65B0}\x{589E}\x{6A6B}\x{5411}\x{6AA2}\x{8996}\x{7684} Mail\x{3001}Text \x{548C} Notes\x{FF1B}\x{7ACB}\x{9AD4}\x{8072} Bluetooth\x{FF1B}\x{6416}\x{4E00}\x{6416}\x{5C31}\x{96A8}\x{6A5F}\x{64AD}"
+          text run at (0,37) width 550: "\x{653E}\x{FF1B}\x{96FB}\x{8996}\x{7BC0}\x{76EE}\x{5206}\x{7D1A}\x{4FDD}\x{8B77}\x{63A7}\x{5236}\x{FF1B}\x{81EA}\x{52D5}\x{767B}\x{5165} Wi-Fi \x{71B1}\x{9EDE}\x{FF1B}\x{4EE5}\x{53CA} Push Notification \x{670D}\x{52D9}\x{901A}\x{77E5}\x{7B49}\x{7B49}\x{3002}\x{9019}\x{4E9B}\x{65B0}\x{589E}"
+          text run at (0,55) width 550: "\x{529F}\x{80FD}\x{53D7}\x{5230}\x{5BA2}\x{6236}\x{7684}\x{5EE3}\x{5927}\x{6B61}\x{8FCE}\x{FF0C}\x{622A}\x{81F3}\x{76EE}\x{524D}\x{70BA}\x{6B62}\x{FF0C}\x{5DF2}\x{7D93}\x{6709}\x{8D85}\x{904E} 20 \x{5104}\x{6B21}\x{7684} Push Notification \x{670D}\x{52D9}\x{901A}\x{77E5}\x{767C}\x{9001}\x{81F3}"
+          text run at (0,73) width 550: "App Store \x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{3002}\x{6B64}\x{5916}\x{FF0C}\x{6700}\x{8FD1}\x{63A8}\x{51FA}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5167}\x{8CFC}\x{8CB7}\x{6A5F}\x{5236} (In-App Purchase)\x{FF0C}\x{70BA}\x{9818}\x{5148}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}"
+          text run at (0,91) width 456: "\x{958B}\x{767C}\x{5EE0}\x{5546}\x{63D0}\x{4F9B}\x{4E86}\x{4E00}\x{7A2E}\x{65B9}\x{5F0F}\x{8B93}\x{5BA2}\x{6236}\x{76F4}\x{63A5}\x{5F9E}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{7576}\x{4E2D}\x{8CFC}\x{8CB7}\x{5167}\x{5BB9}\x{3001}\x{8A02}\x{95B1}\x{9805}\x{76EE}\x{53CA}\x{6578}\x{4F4D}\x{670D}\x{52D9}\x{3002}"
diff --git a/LayoutTests/platform/mac/fast/text/justify-ideograph-simple-expected.checksum b/LayoutTests/platform/mac/fast/text/justify-ideograph-simple-expected.checksum
new file mode 100644 (file)
index 0000000..d40bc89
--- /dev/null
@@ -0,0 +1 @@
+8494b6ff162ad9c96022a5f8fe2dc0d3
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/text/justify-ideograph-simple-expected.png b/LayoutTests/platform/mac/fast/text/justify-ideograph-simple-expected.png
new file mode 100644 (file)
index 0000000..fe4db76
Binary files /dev/null and b/LayoutTests/platform/mac/fast/text/justify-ideograph-simple-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/text/justify-ideograph-simple-expected.txt b/LayoutTests/platform/mac/fast/text/justify-ideograph-simple-expected.txt
new file mode 100644 (file)
index 0000000..8cbc292
--- /dev/null
@@ -0,0 +1,41 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x580
+      RenderBlock {P} at (0,0) size 550x90
+        RenderText {#text} at (0,1) size 550x87
+          text run at (0,1) width 550: "\x{3010}2009 \x{5E74} 11 \x{6708} 4 \x{65E5}\x{7F8E}\x{570B}\x{52A0}\x{5DDE} Cupertino \x{8A0A}\x{3011}\x{860B}\x{679C}\x{4ECA}\x{5929}\x{5BA3}\x{4F48}\x{FF0C}\x{5168}\x{4E16}\x{754C}\x{6700}\x{5927}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5546}\x{5E97} App"
+          text run at (0,19) width 550: "Store\x{FF0C}\x{76EE}\x{524D}\x{5DF2}\x{64C1}\x{6709} 100,000 \x{591A}\x{7A2E}\x{4F86}\x{81EA}\x{5168}\x{7403}\x{958B}\x{767C}\x{4EBA}\x{54E1}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{3002}\x{5168}\x{4E16}\x{754C} 77 \x{500B}\x{570B}\x{5BB6}\x{7684} iPhone\x{AE} \x{8207}"
+          text run at (0,37) width 550: "iPod touch\x{AE} \x{7528}\x{6236}\x{64C1}\x{6709} 20 \x{500B}\x{985E}\x{5225}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{53EF}\x{4F9B}\x{9078}\x{64C7}\x{FF0C}\x{5305}\x{62EC}\x{FF1A}\x{904A}\x{6232}\x{3001}\x{5546}\x{7528}\x{3001}\x{65B0}\x{805E}\x{3001}\x{904B}\x{52D5}\x{3001}\x{91AB}\x{7642}\x{3001}\x{53C3}\x{8003}"
+          text run at (0,55) width 550: "\x{66F8}\x{7C4D}\x{3001}\x{65C5}\x{904A}\x{7B49}\x{7B49}\x{3002}\x{622A}\x{81F3}\x{76EE}\x{524D}\x{70BA}\x{6B62}\x{FF0C}App Store \x{4F7F}\x{7528}\x{8005}\x{4E0B}\x{8F09}\x{6B21}\x{6578}\x{5DF2}\x{8D85}\x{904E} 20 \x{5104}\x{6B21}\x{FF0C}\x{662F}\x{76EE}\x{524D}\x{5168}\x{7403}\x{6700}\x{53D7}\x{6B61}\x{8FCE}\x{7684}"
+          text run at (0,73) width 84: "\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5546}\x{5E97}\x{3002}"
+      RenderBlock {P} at (0,102) size 550x54
+        RenderText {#text} at (0,1) size 550x51
+          text run at (0,1) width 550: "\x{860B}\x{679C}\x{5168}\x{7403}\x{7522}\x{54C1}\x{884C}\x{92B7}\x{8CC7}\x{6DF1}\x{526F}\x{7E3D}\x{88C1} Philip Schiller \x{8868}\x{793A}\x{FF1A}\x{300C}\x{63D0}\x{4F9B} 100,000 \x{591A}\x{7A2E}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{53EF}\x{4F9B}\x{9078}\x{64C7}\x{7684} App"
+          text run at (0,19) width 550: "Store\x{FF0C}\x{662F}\x{5168}\x{4E16}\x{754C}\x{6578}\x{5343}\x{842C} iPhone \x{548C} iPod touch \x{4F7F}\x{7528}\x{8005}\x{4EE4}\x{4EBA}\x{7A31}\x{7FA8}\x{7684}\x{4E3B}\x{8981}\x{539F}\x{56E0}\x{3002}iPhone SDK \x{5275}\x{9020}\x{4E86}\x{7B2C}\x{4E00}"
+          text run at (0,37) width 408: "\x{500B}\x{512A}\x{7570}\x{7684}\x{884C}\x{52D5}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5E73}\x{53F0}\x{FF0C}\x{5BA2}\x{6236}\x{4E5F}\x{975E}\x{5E38}\x{559C}\x{611B}\x{958B}\x{767C}\x{4EBA}\x{54E1}\x{6240}\x{5275}\x{4F5C}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{3002}\x{300D}"
+      RenderBlock {P} at (0,168) size 550x54
+        RenderText {#text} at (0,1) size 550x51
+          text run at (0,1) width 550: "EA Mobile \x{7684} Worldwide Studios \x{526F}\x{7E3D}\x{88C1} Travis Boatman \x{6307}\x{51FA}\x{FF1A}\x{300C}App Store \x{4E0D}\x{50C5}\x{5FB9}\x{5E95}\x{6539}\x{8B8A}\x{4E86}\x{884C}\x{52D5}"
+          text run at (0,19) width 550: "\x{904A}\x{6232}\x{7522}\x{696D}\x{7684}\x{751F}\x{614B}\x{FF0C}\x{800C}\x{4E14}\x{9084}\x{5728}\x{6301}\x{7E8C}\x{6F14}\x{9032}\x{3002}\x{6709}\x{4E86}\x{5168}\x{7403} 5 \x{5343}\x{591A}\x{842C}\x{7684} iPhone \x{548C} iPod touch \x{5BA2}\x{6236}\x{70BA}\x{57FA}\x{790E}\x{FF0C}App"
+          text run at (0,37) width 345: "Store \x{8B93}\x{6211}\x{5011}\x{80FD}\x{5920}\x{958B}\x{767C}\x{53D7}\x{5230}\x{5EE3}\x{5927}\x{7684}\x{5BA2}\x{6236}\x{559C}\x{611B}\x{7684}\x{9AD8}\x{54C1}\x{8CEA} EA \x{904A}\x{6232}\x{3002}\x{300D}"
+      RenderBlock {P} at (0,234) size 550x54
+        RenderText {#text} at (0,1) size 550x51
+          text run at (0,1) width 550: "Smule \x{7684}\x{57F7}\x{884C}\x{9577} Jeff Smith \x{8868}\x{793A}\x{FF1A}\x{300C}\x{6211}\x{5011}\x{7684} I Am T-Pain \x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{53D7}\x{5230}\x{5168}\x{7403}\x{5BA2}\x{6236}\x{7684}\x{71B1}\x{70C8}\x{8FF4}\x{97FF}\x{FF0C}\x{6BCF}\x{65E5}\x{8D85}"
+          text run at (0,19) width 550: "\x{904E} 10,000 \x{6B21}\x{7684}\x{4E0B}\x{8F09}\x{9060}\x{9060}\x{8D85}\x{8D8A}\x{6211}\x{5011}\x{7684}\x{9810}\x{671F}\x{3002}App Store \x{7D66}\x{4E86}\x{6211}\x{5011}\x{4E00}\x{500B}\x{7368}\x{7279}\x{7684}\x{5546}\x{6A5F}\x{FF0C}\x{8B93}\x{6211}\x{5011}\x{958B}\x{5275}\x{4E00}\x{500B}\x{975E}\x{5E38}"
+          text run at (0,37) width 216: "\x{6210}\x{529F}\x{7684}\x{4E8B}\x{696D}\x{FF0C}\x{76F8}\x{4FE1}\x{672A}\x{4F86}\x{5C07}\x{66F4}\x{4EE4}\x{4EBA}\x{671F}\x{5F85}\x{3002}\x{300D}"
+      RenderBlock {P} at (0,300) size 550x72
+        RenderText {#text} at (0,1) size 550x69
+          text run at (0,1) width 550: "\x{860B}\x{679C}\x{4E5F}\x{6301}\x{7E8C}\x{958B}\x{767C}\x{65B0}\x{7684}\x{529F}\x{80FD}\x{4F86}\x{63D0}\x{5347}\x{641C}\x{5C0B}\x{8207}\x{63A2}\x{7D22}\x{7684}\x{4FBF}\x{5229}\x{6027}\x{FF0C}\x{5305}\x{62EC}\x{FF1A}Genius for Apps\x{3001}App Store"
+          text run at (0,19) width 550: "Essentials\x{3001}\x{5B50}\x{5206}\x{985E}\x{6E05}\x{55AE}\x{FF0C}\x{4EE5}\x{53CA}\x{66F4}\x{8C50}\x{5BCC}\x{800C}\x{5BF6}\x{8CB4}\x{7684}\x{5BA2}\x{6236}\x{8A55}\x{8AD6}\x{3002}\x{96A8}\x{8457}\x{65B0}\x{7248}\x{7684} iTunes\x{AE} 9 \x{63A8}\x{51FA}\x{FF0C}\x{73FE}\x{5728}\x{60A8}\x{53EF}\x{4EE5}\x{8F15}"
+          text run at (0,37) width 550: "\x{8F15}\x{9B06}\x{9B06}\x{76F4}\x{63A5}\x{5728} iTunes \x{7576}\x{4E2D}\x{6574}\x{7406}\x{60A8}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{FF0C}\x{4E00}\x{65E6}\x{540C}\x{6B65}\x{4E4B}\x{5F8C}\x{FF0C}iPhone \x{6216} iPod touch \x{5C31}\x{6703}\x{81EA}\x{52D5}\x{51FA}\x{73FE}\x{60A8}"
+          text run at (0,55) width 84: "\x{6240}\x{5B89}\x{6392}\x{7684}\x{914D}\x{7F6E}\x{3002}"
+      RenderBlock {P} at (0,384) size 550x108
+        RenderText {#text} at (0,1) size 550x105
+          text run at (0,1) width 550: "\x{4ECA}\x{5E74}\x{590F}\x{5929}\x{63A8}\x{51FA}\x{7684} iPhone OS 3.0 \x{70BA} iPhone \x{548C} iPod touch \x{4F7F}\x{7528}\x{8005}\x{63D0}\x{4F9B}\x{4E86} 100 \x{591A}\x{7A2E}\x{5168}\x{65B0}\x{7684}\x{529F}\x{80FD}\x{FF0C}\x{5305}"
+          text run at (0,19) width 550: "\x{62EC}\x{FF1A}\x{526A}\x{8CBC}\x{8207}\x{62F7}\x{8C9D}\x{FF1B}MMS\x{FF1B}\x{65B0}\x{589E}\x{6A6B}\x{5411}\x{6AA2}\x{8996}\x{7684} Mail\x{3001}Text \x{548C} Notes\x{FF1B}\x{7ACB}\x{9AD4}\x{8072} Bluetooth\x{FF1B}\x{6416}\x{4E00}\x{6416}\x{5C31}\x{96A8}\x{6A5F}\x{64AD}"
+          text run at (0,37) width 550: "\x{653E}\x{FF1B}\x{96FB}\x{8996}\x{7BC0}\x{76EE}\x{5206}\x{7D1A}\x{4FDD}\x{8B77}\x{63A7}\x{5236}\x{FF1B}\x{81EA}\x{52D5}\x{767B}\x{5165} Wi-Fi \x{71B1}\x{9EDE}\x{FF1B}\x{4EE5}\x{53CA} Push Notification \x{670D}\x{52D9}\x{901A}\x{77E5}\x{7B49}\x{7B49}\x{3002}\x{9019}\x{4E9B}\x{65B0}\x{589E}"
+          text run at (0,55) width 550: "\x{529F}\x{80FD}\x{53D7}\x{5230}\x{5BA2}\x{6236}\x{7684}\x{5EE3}\x{5927}\x{6B61}\x{8FCE}\x{FF0C}\x{622A}\x{81F3}\x{76EE}\x{524D}\x{70BA}\x{6B62}\x{FF0C}\x{5DF2}\x{7D93}\x{6709}\x{8D85}\x{904E} 20 \x{5104}\x{6B21}\x{7684} Push Notification \x{670D}\x{52D9}\x{901A}\x{77E5}\x{767C}\x{9001}\x{81F3}"
+          text run at (0,73) width 550: "App Store \x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{3002}\x{6B64}\x{5916}\x{FF0C}\x{6700}\x{8FD1}\x{63A8}\x{51FA}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5167}\x{8CFC}\x{8CB7}\x{6A5F}\x{5236} (In-App Purchase)\x{FF0C}\x{70BA}\x{9818}\x{5148}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}"
+          text run at (0,91) width 456: "\x{958B}\x{767C}\x{5EE0}\x{5546}\x{63D0}\x{4F9B}\x{4E86}\x{4E00}\x{7A2E}\x{65B9}\x{5F0F}\x{8B93}\x{5BA2}\x{6236}\x{76F4}\x{63A5}\x{5F9E}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{7576}\x{4E2D}\x{8CFC}\x{8CB7}\x{5167}\x{5BB9}\x{3001}\x{8A02}\x{95B1}\x{9805}\x{76EE}\x{53CA}\x{6578}\x{4F4D}\x{670D}\x{52D9}\x{3002}"
diff --git a/LayoutTests/platform/mac/fast/text/justify-ideograph-vertical-expected.checksum b/LayoutTests/platform/mac/fast/text/justify-ideograph-vertical-expected.checksum
new file mode 100644 (file)
index 0000000..48b36e0
--- /dev/null
@@ -0,0 +1 @@
+6d792716aa1326d1482fd6c3aea0ea2d
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/text/justify-ideograph-vertical-expected.png b/LayoutTests/platform/mac/fast/text/justify-ideograph-vertical-expected.png
new file mode 100644 (file)
index 0000000..05f7025
Binary files /dev/null and b/LayoutTests/platform/mac/fast/text/justify-ideograph-vertical-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/text/justify-ideograph-vertical-expected.txt b/LayoutTests/platform/mac/fast/text/justify-ideograph-vertical-expected.txt
new file mode 100644 (file)
index 0000000..28c75a4
--- /dev/null
@@ -0,0 +1,43 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 450x550
+        RenderBlock {P} at (0,12) size 90x550
+          RenderText {#text} at (1,0) size 87x550
+            text run at (1,0) width 550: "\x{3010}2009 \x{5E74} 11 \x{6708} 4 \x{65E5}\x{7F8E}\x{570B}\x{52A0}\x{5DDE} Cupertino \x{8A0A}\x{3011}\x{860B}\x{679C}\x{4ECA}\x{5929}\x{5BA3}\x{4F48}\x{FF0C}\x{5168}\x{4E16}\x{754C}\x{6700}\x{5927}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5546}\x{5E97} App"
+            text run at (19,0) width 550: "Store\x{FF0C}\x{76EE}\x{524D}\x{5DF2}\x{64C1}\x{6709} 100,000 \x{591A}\x{7A2E}\x{4F86}\x{81EA}\x{5168}\x{7403}\x{958B}\x{767C}\x{4EBA}\x{54E1}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{3002}\x{5168}\x{4E16}\x{754C} 77 \x{500B}\x{570B}\x{5BB6}\x{7684} iPhone\x{AE}"
+            text run at (37,0) width 550: "\x{8207} iPod touch\x{AE} \x{7528}\x{6236}\x{64C1}\x{6709} 20 \x{500B}\x{985E}\x{5225}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{53EF}\x{4F9B}\x{9078}\x{64C7}\x{FF0C}\x{5305}\x{62EC}\x{FF1A}\x{904A}\x{6232}\x{3001}\x{5546}\x{7528}\x{3001}\x{65B0}\x{805E}\x{3001}\x{904B}\x{52D5}\x{3001}\x{91AB}"
+            text run at (55,0) width 550: "\x{7642}\x{3001}\x{53C3}\x{8003}\x{66F8}\x{7C4D}\x{3001}\x{65C5}\x{904A}\x{7B49}\x{7B49}\x{3002}\x{622A}\x{81F3}\x{76EE}\x{524D}\x{70BA}\x{6B62}\x{FF0C}App Store \x{4F7F}\x{7528}\x{8005}\x{4E0B}\x{8F09}\x{6B21}\x{6578}\x{5DF2}\x{8D85}\x{904E} 20 \x{5104}\x{6B21}\x{FF0C}\x{662F}\x{76EE}\x{524D}\x{5168}"
+            text run at (73,0) width 158: "\x{7403}\x{6700}\x{53D7}\x{6B61}\x{8FCE}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5546}\x{5E97}\x{3002}"
+        RenderBlock {P} at (90,12) size 54x550
+          RenderText {#text} at (1,0) size 51x550
+            text run at (1,0) width 550: "\x{860B}\x{679C}\x{5168}\x{7403}\x{7522}\x{54C1}\x{884C}\x{92B7}\x{8CC7}\x{6DF1}\x{526F}\x{7E3D}\x{88C1} Philip Schiller \x{8868}\x{793A}\x{FF1A}\x{300C}\x{63D0}\x{4F9B} 100,000 \x{591A}\x{7A2E}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{53EF}\x{4F9B}\x{9078}\x{64C7}\x{7684}"
+            text run at (19,0) width 550: "App Store\x{FF0C}\x{662F}\x{5168}\x{4E16}\x{754C}\x{6578}\x{5343}\x{842C} iPhone \x{548C} iPod touch \x{4F7F}\x{7528}\x{8005}\x{4EE4}\x{4EBA}\x{7A31}\x{7FA8}\x{7684}\x{4E3B}\x{8981}\x{539F}\x{56E0}\x{3002}iPhone SDK \x{5275}"
+            text run at (37,0) width 460: "\x{9020}\x{4E86}\x{7B2C}\x{4E00}\x{500B}\x{512A}\x{7570}\x{7684}\x{884C}\x{52D5}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5E73}\x{53F0}\x{FF0C}\x{5BA2}\x{6236}\x{4E5F}\x{975E}\x{5E38}\x{559C}\x{611B}\x{958B}\x{767C}\x{4EBA}\x{54E1}\x{6240}\x{5275}\x{4F5C}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{3002}\x{300D}"
+        RenderBlock {P} at (144,12) size 54x550
+          RenderText {#text} at (1,0) size 51x550
+            text run at (1,0) width 550: "EA Mobile \x{7684} Worldwide Studios \x{526F}\x{7E3D}\x{88C1} Travis Boatman \x{6307}\x{51FA}\x{FF1A}\x{300C}App Store \x{4E0D}\x{50C5}\x{5FB9}\x{5E95}\x{6539}\x{8B8A}\x{4E86}\x{884C}"
+            text run at (19,0) width 550: "\x{52D5}\x{904A}\x{6232}\x{7522}\x{696D}\x{7684}\x{751F}\x{614B}\x{FF0C}\x{800C}\x{4E14}\x{9084}\x{5728}\x{6301}\x{7E8C}\x{6F14}\x{9032}\x{3002}\x{6709}\x{4E86}\x{5168}\x{7403} 5 \x{5343}\x{591A}\x{842C}\x{7684} iPhone \x{548C} iPod touch \x{5BA2}\x{6236}\x{70BA}\x{57FA}"
+            text run at (37,0) width 400: "\x{790E}\x{FF0C}App Store \x{8B93}\x{6211}\x{5011}\x{80FD}\x{5920}\x{958B}\x{767C}\x{53D7}\x{5230}\x{5EE3}\x{5927}\x{7684}\x{5BA2}\x{6236}\x{559C}\x{611B}\x{7684}\x{9AD8}\x{54C1}\x{8CEA} EA \x{904A}\x{6232}\x{3002}\x{300D}"
+        RenderBlock {P} at (198,12) size 54x550
+          RenderText {#text} at (1,0) size 51x550
+            text run at (1,0) width 550: "Smule \x{7684}\x{57F7}\x{884C}\x{9577} Jeff Smith \x{8868}\x{793A}\x{FF1A}\x{300C}\x{6211}\x{5011}\x{7684} I Am T-Pain \x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{53D7}\x{5230}\x{5168}\x{7403}\x{5BA2}\x{6236}\x{7684}\x{71B1}\x{70C8}\x{8FF4}\x{97FF}\x{FF0C}\x{6BCF}"
+            text run at (19,0) width 550: "\x{65E5}\x{8D85}\x{904E} 10,000 \x{6B21}\x{7684}\x{4E0B}\x{8F09}\x{9060}\x{9060}\x{8D85}\x{8D8A}\x{6211}\x{5011}\x{7684}\x{9810}\x{671F}\x{3002}App Store \x{7D66}\x{4E86}\x{6211}\x{5011}\x{4E00}\x{500B}\x{7368}\x{7279}\x{7684}\x{5546}\x{6A5F}\x{FF0C}\x{8B93}\x{6211}\x{5011}\x{958B}"
+            text run at (37,0) width 278: "\x{5275}\x{4E00}\x{500B}\x{975E}\x{5E38}\x{6210}\x{529F}\x{7684}\x{4E8B}\x{696D}\x{FF0C}\x{76F8}\x{4FE1}\x{672A}\x{4F86}\x{5C07}\x{66F4}\x{4EE4}\x{4EBA}\x{671F}\x{5F85}\x{3002}\x{300D}"
+        RenderBlock {P} at (252,12) size 72x550
+          RenderText {#text} at (1,0) size 69x550
+            text run at (1,0) width 550: "\x{860B}\x{679C}\x{4E5F}\x{6301}\x{7E8C}\x{958B}\x{767C}\x{65B0}\x{7684}\x{529F}\x{80FD}\x{4F86}\x{63D0}\x{5347}\x{641C}\x{5C0B}\x{8207}\x{63A2}\x{7D22}\x{7684}\x{4FBF}\x{5229}\x{6027}\x{FF0C}\x{5305}\x{62EC}\x{FF1A}Genius for Apps\x{3001}App Store"
+            text run at (19,0) width 550: "Essentials\x{3001}\x{5B50}\x{5206}\x{985E}\x{6E05}\x{55AE}\x{FF0C}\x{4EE5}\x{53CA}\x{66F4}\x{8C50}\x{5BCC}\x{800C}\x{5BF6}\x{8CB4}\x{7684}\x{5BA2}\x{6236}\x{8A55}\x{8AD6}\x{3002}\x{96A8}\x{8457}\x{65B0}\x{7248}\x{7684} iTunes\x{AE} 9 \x{63A8}\x{51FA}\x{FF0C}\x{73FE}\x{5728}\x{60A8}"
+            text run at (37,0) width 550: "\x{53EF}\x{4EE5}\x{8F15}\x{8F15}\x{9B06}\x{9B06}\x{76F4}\x{63A5}\x{5728} iTunes \x{7576}\x{4E2D}\x{6574}\x{7406}\x{60A8}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{FF0C}\x{4E00}\x{65E6}\x{540C}\x{6B65}\x{4E4B}\x{5F8C}\x{FF0C}iPhone \x{6216} iPod touch \x{5C31}\x{6703}"
+            text run at (55,0) width 146: "\x{81EA}\x{52D5}\x{51FA}\x{73FE}\x{60A8}\x{6240}\x{5B89}\x{6392}\x{7684}\x{914D}\x{7F6E}\x{3002}"
+        RenderBlock {P} at (324,12) size 126x550
+          RenderText {#text} at (1,0) size 123x550
+            text run at (1,0) width 550: "\x{4ECA}\x{5E74}\x{590F}\x{5929}\x{63A8}\x{51FA}\x{7684} iPhone OS 3.0 \x{70BA} iPhone \x{548C} iPod touch \x{4F7F}\x{7528}\x{8005}\x{63D0}\x{4F9B}\x{4E86} 100 \x{591A}\x{7A2E}\x{5168}\x{65B0}\x{7684}\x{529F}\x{80FD}\x{FF0C}"
+            text run at (19,0) width 550: "\x{5305}\x{62EC}\x{FF1A}\x{526A}\x{8CBC}\x{8207}\x{62F7}\x{8C9D}\x{FF1B}MMS\x{FF1B}\x{65B0}\x{589E}\x{6A6B}\x{5411}\x{6AA2}\x{8996}\x{7684} Mail\x{3001}Text \x{548C} Notes\x{FF1B}\x{7ACB}\x{9AD4}\x{8072} Bluetooth\x{FF1B}\x{6416}\x{4E00}\x{6416}\x{5C31}"
+            text run at (37,0) width 550: "\x{96A8}\x{6A5F}\x{64AD}\x{653E}\x{FF1B}\x{96FB}\x{8996}\x{7BC0}\x{76EE}\x{5206}\x{7D1A}\x{4FDD}\x{8B77}\x{63A7}\x{5236}\x{FF1B}\x{81EA}\x{52D5}\x{767B}\x{5165} Wi-Fi \x{71B1}\x{9EDE}\x{FF1B}\x{4EE5}\x{53CA} Push Notification \x{670D}\x{52D9}\x{901A}\x{77E5}\x{7B49}"
+            text run at (55,0) width 550: "\x{7B49}\x{3002}\x{9019}\x{4E9B}\x{65B0}\x{589E}\x{529F}\x{80FD}\x{53D7}\x{5230}\x{5BA2}\x{6236}\x{7684}\x{5EE3}\x{5927}\x{6B61}\x{8FCE}\x{FF0C}\x{622A}\x{81F3}\x{76EE}\x{524D}\x{70BA}\x{6B62}\x{FF0C}\x{5DF2}\x{7D93}\x{6709}\x{8D85}\x{904E} 20 \x{5104}\x{6B21}\x{7684} Push"
+            text run at (73,0) width 550: "Notification \x{670D}\x{52D9}\x{901A}\x{77E5}\x{767C}\x{9001}\x{81F3} App Store \x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{3002}\x{6B64}\x{5916}\x{FF0C}\x{6700}\x{8FD1}\x{63A8}\x{51FA}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{5167}\x{8CFC}\x{8CB7}\x{6A5F}\x{5236} (In-"
+            text run at (91,0) width 550: "App Purchase)\x{FF0C}\x{70BA}\x{9818}\x{5148}\x{7684}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{958B}\x{767C}\x{5EE0}\x{5546}\x{63D0}\x{4F9B}\x{4E86}\x{4E00}\x{7A2E}\x{65B9}\x{5F0F}\x{8B93}\x{5BA2}\x{6236}\x{76F4}\x{63A5}\x{5F9E}\x{61C9}\x{7528}\x{7A0B}\x{5F0F}\x{7576}\x{4E2D}\x{8CFC}\x{8CB7}\x{5167}"
+            text run at (109,0) width 146: "\x{5BB9}\x{3001}\x{8A02}\x{95B1}\x{9805}\x{76EE}\x{53CA}\x{6578}\x{4F4D}\x{670D}\x{52D9}\x{3002}"
index 26a98c3..545ea65 100644 (file)
@@ -1,3 +1,106 @@
+2011-01-26  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Dave Hyatt.
+
+        <rdar://problem/8446709> Allow inter-ideograph justification for CJK
+        https://bugs.webkit.org/show_bug.cgi?id=53184
+
+        Tests: fast/text/justify-ideograph-complex.html
+               fast/text/justify-ideograph-simple.html
+               fast/text/justify-ideograph-vertical.html
+
+        * html/canvas/CanvasRenderingContext2D.cpp:
+        (WebCore::CanvasRenderingContext2D::drawTextInternal): Corrected the type of the third parameter
+        passed to the TextRun constructor and added the trailingExpansionBehavior parameter.
+        * platform/graphics/Font.cpp:
+        (WebCore::Font::expansionOpportunityCount): Added. Returns the number of expansion opportunities
+        for text justification. On entry, isAfterExpansion says whether an expansion opportunity exists
+        before the first character. On return, isAfterExpansion says whether an expansion opportunity
+        exists after the last character.
+        * platform/graphics/Font.h: 
+        * platform/graphics/GlyphBuffer.h:
+        (WebCore::GlyphBuffer::expandLastAdvance): Added.
+        * platform/graphics/TextRun.h:
+        (WebCore::TextRun::TextRun): Added a TrailingExpansionBehavior parameter to the constructors.
+        Renamed padding to expansion.
+        (WebCore::TextRun::expansion): Renamed padding() to this.
+        (WebCore::TextRun::allowsTrailingExpansion): Added this accessor.
+        * platform/graphics/WidthIterator.cpp:
+        (WebCore::WidthIterator::WidthIterator): Initialize m_isAfterExpansion. Use Font::expansionOpportunityCount()
+        and adjust the count if it includes a trailing expansion opportunity but the run disallows trailing
+        expansion.
+        (WebCore::WidthIterator::advance): Apply expansion before and after CJK ideographs.
+        (WebCore::WidthIterator::advanceOneCharacter): Changed to not clear the GlyphBuffer so that advance()
+        can expand the last advance if it is followed by a CJK ideograph.
+        * platform/graphics/WidthIterator.h: Renamed m_padding to m_expansion and m_padPerSpace
+        to m_expansionPerOpportunity.
+        * platform/graphics/chromium/FontChromiumWin.cpp:
+        (WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
+        * platform/graphics/chromium/FontLinux.cpp:
+        (WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
+        * platform/graphics/efl/FontEfl.cpp:
+        (WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
+        * platform/graphics/gtk/FontGtk.cpp:
+        (WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
+        * platform/graphics/haiku/FontHaiku.cpp:
+        (WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
+        * platform/graphics/mac/ComplexTextController.cpp:
+        (WebCore::ComplexTextController::ComplexTextController): Initialize m_isAfterExpansion. Use
+        Font::expansionOpportunityCount() and adjust the count if it includes a trailing expansion
+        opportunity but the run disallows trailing expansion.
+        (WebCore::ComplexTextController::adjustGlyphsAndAdvances): Moved the definition and initialization
+        of hasExtraSpacing outside the loop. Apply expansion before and after CJK ideographs.
+        * platform/graphics/mac/ComplexTextController.h: Renamed m_padding to m_expansion and m_padPerSpace
+        to m_expansionPerOpportunity.
+        * platform/graphics/mac/FontMac.mm:
+        (WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
+        * platform/graphics/qt/FontQt.cpp:
+        (WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
+        * platform/graphics/win/FontWin.cpp:
+        (WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
+        * platform/graphics/win/UniscribeController.cpp:
+        (WebCore::UniscribeController::UniscribeController): Updated for rename.
+        * platform/graphics/wince/FontWinCE.cpp:
+        (WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
+        * platform/graphics/wx/FontWx.cpp:
+        (WebCore::Font::canExpandAroundIdeographsInComplexText): Added.
+        * rendering/EllipsisBox.cpp:
+        (WebCore::EllipsisBox::paint): Pass a TrailingExpansionBehavior to the TextRun constructor.
+        (WebCore::EllipsisBox::selectionRect): Ditto.
+        (WebCore::EllipsisBox::paintSelection): Ditto.
+        * rendering/InlineBox.h:
+        (WebCore::InlineBox::InlineBox): Renamed m_toAdd to m_expansion.
+        (WebCore::InlineBox::expansion): Renamed toAdd() to this.
+        * rendering/InlineTextBox.cpp:
+        (WebCore::InlineTextBox::selectionRect): Pass a TrailingExpansionBehavior to the TextRun constructor.
+        (WebCore::InlineTextBox::paint): Ditto.
+        (WebCore::InlineTextBox::paintSelection): Ditto.
+        (WebCore::InlineTextBox::paintCompositionBackground): Ditto.
+        (WebCore::InlineTextBox::paintSpellingOrGrammarMarker): Ditto.
+        (WebCore::InlineTextBox::paintTextMatchMarker): Ditto.
+        (WebCore::InlineTextBox::computeRectForReplacementMarker): Ditto.
+        (WebCore::InlineTextBox::offsetForPosition): Ditto.
+        (WebCore::InlineTextBox::positionForOffset): Ditto.
+        * rendering/InlineTextBox.h:
+        (WebCore::InlineTextBox::setExpansion): Renamed setSpaceAdd() to this.
+        (WebCore::InlineTextBox::trailingExpansionBehavior): Added. Trailing expansion is allowed if this
+        is not the last leaf box on the line.
+        * rendering/RenderBlockLineLayout.cpp:
+        (WebCore::RenderBlock::computeInlineDirectionPositionsForLine): Keep expansion opportunity counts
+        in a vector instead of computing them twice. Discard the trailing expansion opportunity in the
+        last text box.
+        * rendering/RenderFileUploadControl.cpp:
+        (WebCore::RenderFileUploadControl::paintObject): Pass a TrailingExpansionBehavior to the TextRun constructor.
+        (WebCore::RenderFileUploadControl::computePreferredLogicalWidths): Ditto.
+        * rendering/RenderListBox.cpp:
+        (WebCore::RenderListBox::updateFromElement): Ditto.
+        (WebCore::RenderListBox::paintItemForeground): Ditto. Also corrected the type of the second parameter.
+        * rendering/RenderTextControl.cpp:
+        (WebCore::RenderTextControl::getAvgCharWidth): Ditto.
+        (WebCore::RenderTextControl::paintPlaceholder): Ditto.
+        * rendering/svg/SVGInlineTextBox.cpp:
+        (WebCore::SVGInlineTextBox::constructTextRun): Ditto.
+
 2011-01-26  Andy Estes  <aestes@apple.com>
 
         Rubber-stamped by Darin Adler.
index e87deaa..e5bf352 100644 (file)
@@ -1771,7 +1771,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo
 
     unsigned length = text.length();
     const UChar* string = text.characters();
-    TextRun textRun(string, length, 0, 0, 0, rtl, override, false, false);
+    TextRun textRun(string, length, false, 0, 0, TextRun::AllowTrailingExpansion, rtl, override, false, false);
 
     // Draw the item text at the correct point.
     FloatPoint location(x, y);
@@ -1793,7 +1793,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo
         break;
     }
 
-    float width = font.width(TextRun(text, false, 0, 0, rtl, override));
+    float width = font.width(TextRun(text, false, 0, 0, TextRun::AllowTrailingExpansion, rtl, override));
 
     TextAlign align = state().m_textAlign;
     if (align == StartTextAlign)
index b0e70fd..b446d7f 100644 (file)
@@ -973,7 +973,7 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd
     else if (m_settings.itemTextDirectionalityHint ==
              PopupContainerSettings::FirstStrongDirectionalCharacterDirection)
         rtl = itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft;
-    TextRun textRun(itemText.characters(), itemText.length(), false, 0, 0, rtl);
+    TextRun textRun(itemText.characters(), itemText.length(), false, 0, 0, TextRun::AllowTrailingExpansion, rtl);
     // If the text is right-to-left, make it right-aligned by adjusting its
     // beginning position.
     if (rightAligned)
@@ -1001,7 +1001,7 @@ void PopupListBox::paintRow(GraphicsContext* gc, const IntRect& rect, int rowInd
     // Draw the the label if applicable.
     if (itemLabel.isEmpty())
         return;
-    TextRun labelTextRun(itemLabel.characters(), itemLabel.length(), false, 0, 0, rtl);
+    TextRun labelTextRun(itemLabel.characters(), itemLabel.length(), false, 0, 0, TextRun::AllowTrailingExpansion, rtl);
     if (rightAligned)
         textX = max(0, m_popupClient->clientPaddingLeft() - m_popupClient->clientInsetLeft());
     else
index 394de35..67f2b26 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
  *           (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2010, 2011 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
@@ -293,7 +293,7 @@ Font::CodePath Font::codePath(const TextRun& run) const
         return s_codePath;
 
 #if PLATFORM(QT)
-    if (run.padding() || run.rtl() || isSmallCaps() || wordSpacing() || letterSpacing())
+    if (run.expansion() || run.rtl() || isSmallCaps() || wordSpacing() || letterSpacing())
         return Complex;
 #endif
 
@@ -458,6 +458,33 @@ bool Font::isCJKIdeographOrSymbol(UChar32 c)
     return isCJKIdeograph(c);
 }
 
+unsigned Font::expansionOpportunityCount(const UChar* characters, size_t length, bool& isAfterExpansion)
+{
+    static bool expandAroundIdeographs = canExpandAroundIdeographsInComplexText();
+    unsigned count = 0;
+    for (size_t i = 0; i < length; ++i) {
+        UChar32 character = characters[i];
+        if (treatAsSpace(character)) {
+            count++;
+            isAfterExpansion = true;
+            continue;
+        }
+        if (U16_IS_LEAD(character) && i + 1 < length && U16_IS_TRAIL(characters[i + 1])) {
+            character = U16_GET_SUPPLEMENTARY(character, characters[i + 1]);
+            i++;
+        }
+        if (expandAroundIdeographs && isCJKIdeograph(character)) {
+            if (!isAfterExpansion)
+                count++;
+            count++;
+            isAfterExpansion = true;
+            continue;
+        }
+        isAfterExpansion = false;
+    }
+    return count;
+}
+
 bool Font::canReceiveTextEmphasis(UChar32 c)
 {
     CharCategory category = Unicode::category(c);
index ac1777a..30047ed 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
  *           (C) 2000 Antti Koivisto (koivisto@kde.org)
  *           (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006, 2007, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2007, 2010, 2011 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Holger Hans Peter Freyther
  *
  * This library is free software; you can redistribute it and/or
@@ -142,7 +142,9 @@ public:
 
     static bool isCJKIdeograph(UChar32);
     static bool isCJKIdeographOrSymbol(UChar32);
-    
+
+    static unsigned expansionOpportunityCount(const UChar*, size_t length, bool& isAfterExpansion);
+
 #if PLATFORM(QT)
     QFont font() const;
 #endif
@@ -177,6 +179,7 @@ private:
     bool getEmphasisMarkGlyphData(const AtomicString&, GlyphData&) const;
 
     static bool canReturnFallbackFontsForComplexText();
+    static bool canExpandAroundIdeographsInComplexText();
 
     CodePath codePath(const TextRun&) const;
 
index 6f1fe7b..7aac1e3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2009, 2011 Apple Inc. All rights reserved.
  * Copyright (C) 2007-2008 Torch Mobile Inc.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -187,7 +187,20 @@ public:
         m_advances.append(advance);
     }
 #endif
-    
+
+    void expandLastAdvance(float width)
+    {
+        ASSERT(!isEmpty());
+        GlyphBufferAdvance& lastAdvance = m_advances.last();
+#if PLATFORM(CG) || (PLATFORM(WX) && OS(DARWIN))
+        lastAdvance.width += width;
+#elif OS(WINCE)
+        lastAdvance += width;
+#else
+        lastAdvance += FloatSize(width, 0);
+#endif
+    }
+
 private:
     Vector<const SimpleFontData*, 2048> m_fontData;
     Vector<GlyphBufferGlyph, 2048> m_glyphs;
index dce5535..ef434bd 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
  *           (C) 2000 Antti Koivisto (koivisto@kde.org)
  *           (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2003, 2006, 2007 Apple Computer, Inc.
+ * Copyright (C) 2003, 2006, 2007, 2011 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
@@ -33,12 +33,18 @@ class RenderSVGResource;
 
 class TextRun {
 public:
-    TextRun(const UChar* c, int len, bool allowTabs = false, int xpos = 0, int padding = 0, bool rtl = false, bool directionalOverride = false,
+    enum TrailingExpansionBehavior {
+        AllowTrailingExpansion,
+        ForbidTrailingExpansion
+    };
+
+    TextRun(const UChar* c, int len, bool allowTabs = false, int xpos = 0, int expansion = 0, TrailingExpansionBehavior trailingExpansionBehavior = AllowTrailingExpansion, bool rtl = false, bool directionalOverride = false,
               bool applyRunRounding = true, bool applyWordRounding = true)
         : m_characters(c)
         , m_len(len)
         , m_xpos(xpos)
-        , m_padding(padding)
+        , m_expansion(expansion)
+        , m_trailingExpansionBehavior(trailingExpansionBehavior)
 #if ENABLE(SVG)
         , m_horizontalGlyphStretch(1)
 #endif
@@ -55,12 +61,13 @@ public:
     {
     }
 
-    TextRun(const String& s, bool allowTabs = false, int xpos = 0, int padding = 0, bool rtl = false, bool directionalOverride = false,
+    TextRun(const String& s, bool allowTabs = false, int xpos = 0, int expansion = 0, TrailingExpansionBehavior trailingExpansionBehavior = AllowTrailingExpansion, bool rtl = false, bool directionalOverride = false,
               bool applyRunRounding = true, bool applyWordRounding = true)
         : m_characters(s.characters())
         , m_len(s.length())
         , m_xpos(xpos)
-        , m_padding(padding)
+        , m_expansion(expansion)
+        , m_trailingExpansionBehavior(trailingExpansionBehavior)
 #if ENABLE(SVG)
         , m_horizontalGlyphStretch(1)
 #endif
@@ -92,7 +99,8 @@ public:
 
     bool allowTabs() const { return m_allowTabs; }
     int xPos() const { return m_xpos; }
-    int padding() const { return m_padding; }
+    int expansion() const { return m_expansion; }
+    bool allowsTrailingExpansion() const { return m_trailingExpansionBehavior == AllowTrailingExpansion; }
     bool rtl() const { return m_rtl; }
     bool ltr() const { return !m_rtl; }
     bool directionalOverride() const { return m_directionalOverride; }
@@ -121,7 +129,8 @@ private:
     // start of the containing block. In the case of right alignment or center alignment, left start of
     // the text line is not the same as left start of the containing block.
     int m_xpos;  
-    int m_padding;
+    int m_expansion;
+    TrailingExpansionBehavior m_trailingExpansionBehavior;
 #if ENABLE(SVG)
     float m_horizontalGlyphStretch;
 #endif
index 412c86e..4b27e91 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Holger Hans Peter Freyther
  *
  * This library is free software; you can redistribute it and/or
@@ -47,6 +47,7 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const
     , m_end(run.length())
     , m_currentCharacter(0)
     , m_runWidthSoFar(0)
+    , m_isAfterExpansion(true)
     , m_finalRoundingWidth(0)
     , m_fallbackFonts(fallbackFonts)
     , m_accountForGlyphBounds(accountForGlyphBounds)
@@ -58,20 +59,19 @@ WidthIterator::WidthIterator(const Font* font, const TextRun& run, HashSet<const
 {
     // If the padding is non-zero, count the number of spaces in the run
     // and divide that by the padding for per space addition.
-    m_padding = m_run.padding();
-    if (!m_padding)
-        m_padPerSpace = 0;
+    m_expansion = m_run.expansion();
+    if (!m_expansion)
+        m_expansionPerOpportunity = 0;
     else {
-        int numSpaces = 0;
-        for (int i = 0; i < run.length(); i++) {
-            if (Font::treatAsSpace(m_run[i]))
-                numSpaces++;
-        }
+        bool isAfterExpansion = true;
+        unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters(), m_end, isAfterExpansion);
+        if (isAfterExpansion && !m_run.allowsTrailingExpansion())
+            expansionOpportunityCount--;
 
-        if (!numSpaces)
-            m_padPerSpace = 0;
+        if (!expansionOpportunityCount)
+            m_expansionPerOpportunity = 0;
         else
-            m_padPerSpace = m_padding / numSpaces;
+            m_expansionPerOpportunity = m_expansion / expansionOpportunityCount;
     }
 }
 
@@ -84,7 +84,7 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
     const UChar* cp = m_run.data(currentCharacter);
 
     bool rtl = m_run.rtl();
-    bool hasExtraSpacing = (m_font->letterSpacing() || m_font->wordSpacing() || m_padding) && !m_run.spacingDisabled();
+    bool hasExtraSpacing = (m_font->letterSpacing() || m_font->wordSpacing() || m_expansion) && !m_run.spacingDisabled();
 
     float widthSinceLastRounding = m_runWidthSoFar;
     m_runWidthSoFar = floorf(m_runWidthSoFar);
@@ -173,26 +173,33 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
             if (width && m_font->letterSpacing())
                 width += m_font->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 (m_padding) {
-                    // Use left over padding if not evenly divisible by number of spaces.
-                    if (m_padding < m_padPerSpace) {
-                        width += m_padding;
-                        m_padding = 0;
-                    } else {
-                        float previousPadding = m_padding;
-                        m_padding -= m_padPerSpace;
-                        width += roundf(previousPadding) - roundf(m_padding);
+            static bool expandAroundIdeographs = Font::canExpandAroundIdeographsInComplexText();
+            bool treatAsSpace = Font::treatAsSpace(c);
+            if (treatAsSpace || (expandAroundIdeographs && Font::isCJKIdeograph(c))) {
+                // Distribute the run's total expansion evenly over all expansion opportunities in the run.
+                if (m_expansion && (m_run.allowsTrailingExpansion() || currentCharacter + clusterLength < static_cast<size_t>(m_run.length()))) {
+                    float previousExpansion = m_expansion;
+                    if (!treatAsSpace && !m_isAfterExpansion) {
+                        // Take the expansion opportunity before this ideograph.
+                        m_expansion -= m_expansionPerOpportunity;
+                        int expansion = roundf(previousExpansion) - roundf(m_expansion);
+                        m_runWidthSoFar += expansion;
+                        if (glyphBuffer)
+                            glyphBuffer->expandLastAdvance(expansion);
+                        previousExpansion = m_expansion;
                     }
-                }
+                    m_expansion -= m_expansionPerOpportunity;
+                    width += roundf(previousExpansion) - roundf(m_expansion);
+                    m_isAfterExpansion = true;
+                } else
+                    m_isAfterExpansion = false;
 
                 // Account for word spacing.
                 // We apply additional space between "words" by adding width to the space character.
-                if (currentCharacter != 0 && !Font::treatAsSpace(cp[-1]) && m_font->wordSpacing())
+                if (treatAsSpace && currentCharacter && !Font::treatAsSpace(cp[-1]) && m_font->wordSpacing())
                     width += m_font->wordSpacing();
-            }
+            } else
+                m_isAfterExpansion = false;
         }
 
         if (m_accountForGlyphBounds) {
@@ -260,13 +267,13 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
 
 bool WidthIterator::advanceOneCharacter(float& width, GlyphBuffer* glyphBuffer)
 {
-    glyphBuffer->clear();
+    int oldSize = glyphBuffer->size();
     advance(m_currentCharacter + 1, glyphBuffer);
     float w = 0;
-    for (int i = 0; i < glyphBuffer->size(); ++i)
+    for (int i = oldSize; i < glyphBuffer->size(); ++i)
         w += glyphBuffer->advanceAt(i);
     width = w;
-    return !glyphBuffer->isEmpty();
+    return glyphBuffer->size() > oldSize;
 }
 
 UChar32 WidthIterator::normalizeVoicingMarks(int currentCharacter)
index 8b3c067..2b4f051 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003, 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2006, 2008, 2011 Apple Inc. All rights reserved.
  * Copyright (C) 2008 Holger Hans Peter Freyther
  *
  * This library is free software; you can redistribute it and/or
@@ -50,8 +50,9 @@ struct WidthIterator {
 
     unsigned m_currentCharacter;
     float m_runWidthSoFar;
-    float m_padding;
-    float m_padPerSpace;
+    float m_expansion;
+    float m_expansionPerOpportunity;
+    bool m_isAfterExpansion;
     float m_finalRoundingWidth;
 
 private:
index d7c2eb6..e57a84c 100644 (file)
@@ -369,6 +369,11 @@ bool Font::canReturnFallbackFontsForComplexText()
     return false;
 }
 
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+    return false;
+}
+
 void Font::drawGlyphs(GraphicsContext* graphicsContext,
                       const SimpleFontData* font,
                       const GlyphBuffer& glyphBuffer,
index 822bbbb..823dbc9 100644 (file)
@@ -55,6 +55,11 @@ bool Font::canReturnFallbackFontsForComplexText()
     return false;
 }
 
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+    return false;
+}
+
 static bool isCanvasMultiLayered(SkCanvas* canvas)
 {
     SkCanvas::LayerIter layerIterator(canvas, false);
@@ -204,7 +209,7 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
     ComplexTextController controller(run, point.x(), this);
     controller.setWordSpacingAdjustment(wordSpacing());
     controller.setLetterSpacingAdjustment(letterSpacing());
-    controller.setPadding(run.padding());
+    controller.setPadding(run.expansion());
 
     if (run.rtl()) {
         // FIXME: this causes us to shape the text twice -- once to compute the width and then again
@@ -213,7 +218,7 @@ void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
         controller.reset(point.x() + controller.widthOfFullRun());
         // We need to set the padding again because ComplexTextController layout consumed the value.
         // Fixing the above problem would help here too.
-        controller.setPadding(run.padding());
+        controller.setPadding(run.expansion());
     }
 
     while (controller.nextScriptRun()) {
@@ -241,7 +246,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
     ComplexTextController controller(run, 0, this);
     controller.setWordSpacingAdjustment(wordSpacing());
     controller.setLetterSpacingAdjustment(letterSpacing());
-    controller.setPadding(run.padding());
+    controller.setPadding(run.expansion());
     return controller.widthOfFullRun();
 }
 
@@ -275,11 +280,11 @@ int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
     ComplexTextController controller(run, 0, this);
     controller.setWordSpacingAdjustment(wordSpacing());
     controller.setLetterSpacingAdjustment(letterSpacing());
-    controller.setPadding(run.padding());
+    controller.setPadding(run.expansion());
     if (run.rtl()) {
         // See FIXME in drawComplexText.
         controller.reset(controller.widthOfFullRun());
-        controller.setPadding(run.padding());
+        controller.setPadding(run.expansion());
     }
 
     unsigned basePosition = 0;
@@ -326,11 +331,11 @@ FloatRect Font::selectionRectForComplexText(const TextRun& run,
     ComplexTextController controller(run, 0, this);
     controller.setWordSpacingAdjustment(wordSpacing());
     controller.setLetterSpacingAdjustment(letterSpacing());
-    controller.setPadding(run.padding());
+    controller.setPadding(run.expansion());
     if (run.rtl()) {
         // See FIXME in drawComplexText.
         controller.reset(controller.widthOfFullRun());
-        controller.setPadding(run.padding());
+        controller.setPadding(run.expansion());
     }
 
     // Iterate through the script runs in logical order, searching for the run covering the positions of interest.
index a8b44c1..c060b43 100644 (file)
@@ -55,10 +55,10 @@ UniscribeHelperTextRun::UniscribeHelperTextRun(const TextRun& run,
 
     init();
 
-    // Padding is the amount to add to make justification happen. This
+    // Expansion is the amount to add to make justification happen. This
     // should be done after Init() so all the runs are already measured.
-    if (run.padding() > 0)
-        justify(run.padding());
+    if (run.expansion() > 0)
+        justify(run.expansion());
 }
 
 UniscribeHelperTextRun::UniscribeHelperTextRun(
index d3ca183..83cc7ff 100644 (file)
@@ -50,6 +50,11 @@ bool Font::canReturnFallbackFontsForComplexText()
     return false;
 }
 
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+    return false;
+}
+
 float Font::floatWidthForComplexText(const TextRun&, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
 {
     notImplemented();
index 4d6f509..216fb56 100644 (file)
@@ -215,6 +215,11 @@ bool Font::canReturnFallbackFontsForComplexText()
     return false;
 }
 
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+    return false;
+}
+
 static void drawGlyphsShadow(GraphicsContext* graphicsContext, cairo_t* context, const FloatPoint& point, PangoLayoutLine* layoutLine, PangoRegionType renderRegion)
 {
     ContextShadow* shadow = graphicsContext->contextShadow();
index 819fecb..5a1a1d0 100644 (file)
@@ -65,6 +65,11 @@ bool Font::canReturnFallbackFontsForComplexText()
     return false;
 }
 
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+    return false;
+}
+
 void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font,
                       const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
 {
index bb1a30a..fa198ab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -71,7 +71,8 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru
     , m_glyphInCurrentRun(0)
     , m_characterInCurrentGlyph(0)
     , m_finalRoundingWidth(0)
-    , m_padding(run.padding())
+    , m_expansion(run.expansion())
+    , m_afterExpansion(true)
     , m_fallbackFonts(fallbackFonts)
     , m_minGlyphBoundingBoxX(numeric_limits<float>::max())
     , m_maxGlyphBoundingBoxX(numeric_limits<float>::min())
@@ -79,19 +80,18 @@ ComplexTextController::ComplexTextController(const Font* font, const TextRun& ru
     , m_maxGlyphBoundingBoxY(numeric_limits<float>::min())
     , m_lastRoundingGlyph(0)
 {
-    if (!m_padding)
-        m_padPerSpace = 0;
+    if (!m_expansion)
+        m_expansionPerOpportunity = 0;
     else {
-        int numSpaces = 0;
-        for (int s = 0; s < m_run.length(); s++) {
-            if (Font::treatAsSpace(m_run[s]))
-                numSpaces++;
-        }
+        bool isAfterExpansion = true;
+        unsigned expansionOpportunityCount = Font::expansionOpportunityCount(m_run.characters(), m_end, isAfterExpansion);
+        if (isAfterExpansion && !m_run.allowsTrailingExpansion())
+            expansionOpportunityCount--;
 
-        if (!numSpaces)
-            m_padPerSpace = 0;
+        if (!expansionOpportunityCount)
+            m_expansionPerOpportunity = 0;
         else
-            m_padPerSpace = m_padding / numSpaces;
+            m_expansionPerOpportunity = m_expansion / expansionOpportunityCount;
     }
 
     collectComplexTextRuns();
@@ -422,6 +422,7 @@ void ComplexTextController::adjustGlyphsAndAdvances()
 {
     CGFloat widthSinceLastRounding = 0;
     size_t runCount = m_complexTextRuns.size();
+    bool hasExtraSpacing = (m_font.letterSpacing() || m_font.wordSpacing() || m_expansion) && !m_run.spacingDisabled();
     for (size_t r = 0; r < runCount; ++r) {
         ComplexTextRun& complexTextRun = *m_complexTextRuns[r];
         unsigned glyphCount = complexTextRun.glyphCount();
@@ -434,7 +435,6 @@ void ComplexTextController::adjustGlyphsAndAdvances()
         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();
         CGPoint glyphOrigin = CGPointZero;
         CFIndex lastCharacterIndex = m_run.ltr() ? numeric_limits<CFIndex>::min() : numeric_limits<CFIndex>::max();
         bool isMonotonic = true;
@@ -490,25 +490,29 @@ void ComplexTextController::adjustGlyphsAndAdvances()
                     advance.width += m_font.letterSpacing();
 
                 // Handle justification and word-spacing.
-                if (treatAsSpace) {
-                    // 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 {
-                            float previousPadding = m_padding;
-                            m_padding -= m_padPerSpace;
-                            advance.width += roundf(previousPadding) - roundf(m_padding);
+                if (treatAsSpace || Font::isCJKIdeograph(ch)) {
+                    // Distribute the run's total expansion evenly over all expansion opportunities in the run.
+                    if (m_expansion && (!lastGlyph || m_run.allowsTrailingExpansion())) {
+                        float previousExpansion = m_expansion;
+                        if (!treatAsSpace && !m_afterExpansion) {
+                            // Take the expansion opportunity before this ideograph.
+                            m_expansion -= m_expansionPerOpportunity;
+                            int expansion = roundf(previousExpansion) - roundf(m_expansion);
+                            m_totalWidth += expansion;
+                            m_adjustedAdvances.last().width += expansion;
+                            previousExpansion = m_expansion;
                         }
-                    }
+                        m_expansion -= m_expansionPerOpportunity;
+                        advance.width += roundf(previousExpansion) - roundf(m_expansion);
+                        m_afterExpansion = true;
+                    } else
+                        m_afterExpansion = false;
 
                     // Account for word-spacing.
-                    if (characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing())
+                    if (treatAsSpace && characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing())
                         advance.width += m_font.wordSpacing();
-                }
+                } else
+                    m_afterExpansion = false;
             }
 
             // Deal with the float/integer impedance mismatch between CG and WebCore. "Words" (characters 
index f97dc92..63f93a2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -177,8 +177,9 @@ private:
     unsigned m_glyphInCurrentRun;
     unsigned m_characterInCurrentGlyph;
     float m_finalRoundingWidth;
-    float m_padding;
-    float m_padPerSpace;
+    float m_expansion;
+    float m_expansionPerOpportunity;
+    bool m_afterExpansion;
 
     HashSet<const SimpleFontData*>* m_fallbackFonts;
 
index f7d71ef..acd7562 100644 (file)
@@ -47,6 +47,11 @@ bool Font::canReturnFallbackFontsForComplexText()
     return true;
 }
 
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+    return true;
+}
+
 static void showGlyphsWithAdvances(const SimpleFontData* font, CGContextRef context, const CGGlyph* glyphs, const CGSize* advances, size_t count)
 {
     const FontPlatformData& platformData = font->platformData();
index 778a13f..818096f 100644 (file)
@@ -61,14 +61,14 @@ static const QString fromRawDataWithoutRef(const String& string, int start = 0,
 static QTextLine setupLayout(QTextLayout* layout, const TextRun& style)
 {
     int flags = style.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
-    if (style.padding())
+    if (style.expansion())
         flags |= Qt::TextJustificationForced;
     layout->setFlags(flags);
     layout->beginLayout();
     QTextLine line = layout->createLine();
     line.setLineWidth(INT_MAX/256);
-    if (style.padding())
-        line.setLineWidth(line.naturalTextWidth() + style.padding());
+    if (style.expansion())
+        line.setLineWidth(line.naturalTextWidth() + style.expansion());
     layout->endLayout();
     return line;
 }
@@ -196,7 +196,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
                 p->save();
                 p->setPen(ctxShadow->m_color);
                 p->translate(ctxShadow->offset());
-                p->drawText(pt, string, flags, run.padding());
+                p->drawText(pt, string, flags, run.expansion());
                 p->restore();
             } else {
                 QFontMetrics fm(font);
@@ -210,7 +210,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
                     // Since it will be blurred anyway, we don't care about render hints.
                     shadowPainter->setFont(p->font());
                     shadowPainter->setPen(ctxShadow->m_color);
-                    shadowPainter->drawText(pt, string, flags, run.padding());
+                    shadowPainter->drawText(pt, string, flags, run.expansion());
                     ctxShadow->endShadowLayer(ctx);
                 }
             }
@@ -243,7 +243,7 @@ static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const Float
     if (ctx->textDrawingMode() & TextModeFill) {
         QPen previousPen = p->pen();
         p->setPen(textFillPen);
-        p->drawText(pt, string, flags, run.padding());
+        p->drawText(pt, string, flags, run.expansion());
         p->setPen(previousPen);
     }
 }
@@ -308,7 +308,7 @@ float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer
     if (treatAsSpace(run[0]))
         w -= m_wordSpacing;
 
-    return w + run.padding();
+    return w + run.expansion();
 #else
     Q_ASSERT(false);
     return 0;
@@ -324,7 +324,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
         return 0;
 
     if (run.length() == 1 && treatAsSpace(run[0]))
-        return QFontMetrics(font()).width(space) + run.padding();
+        return QFontMetrics(font()).width(space) + run.expansion();
 
     String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
     QString string = fromRawDataWithoutRef(sanitized);
@@ -334,7 +334,7 @@ float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFon
     if (treatAsSpace(run[0]))
         w -= m_wordSpacing;
 
-    return w + run.padding();
+    return w + run.expansion();
 }
 
 int Font::offsetForPositionForSimpleText(const TextRun& run, float position, bool includePartialGlyphs) const
@@ -413,6 +413,11 @@ bool Font::canReturnFallbackFontsForComplexText()
     return false;
 }
 
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+    return false;
+}
+
 bool Font::primaryFontHasGlyphForCharacter(UChar32) const
 {
     notImplemented();
index cdb2fd2..47c44bc 100644 (file)
@@ -45,6 +45,11 @@ bool Font::canReturnFallbackFontsForComplexText()
     return true;
 }
 
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+    return false;
+}
+
 FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h,
                                             int from, int to) const
 {
index dac6c3e..60651b5 100644 (file)
@@ -49,7 +49,7 @@ UniscribeController::UniscribeController(const Font* font, const TextRun& run, H
     , m_end(run.length())
     , m_currentCharacter(0)
     , m_runWidthSoFar(0)
-    , m_padding(run.padding())
+    , m_padding(run.expansion())
     , m_computingOffsetPosition(false)
     , m_includePartialGlyphs(false)
     , m_offsetX(0)
index 5a4c8da..6d39012 100644 (file)
@@ -112,7 +112,7 @@ static int generateComponents(TextRunComponents* components, const Font &font, c
 {
     int letterSpacing = font.letterSpacing();
     int wordSpacing = font.wordSpacing();
-    int padding = run.padding();
+    int padding = run.expansion();
     int numSpaces = 0;
     if (padding) {
         for (int i = 0; i < run.length(); i++)
@@ -340,4 +340,9 @@ bool Font::canReturnFallbackFontsForComplexText()
     return false;
 }
 
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+    return false;
+}
+
 } // namespace WebCore
index c01e249..5233d43 100644 (file)
@@ -57,6 +57,15 @@ bool Font::canReturnFallbackFontsForComplexText()
 #endif
 }
 
+bool Font::canExpandAroundIdeographsInComplexText()
+{
+#if OS(DARWIN)
+    return true;
+#else
+    return false;
+#endif
+}
+
 void Font::drawGlyphs(GraphicsContext* graphicsContext, const SimpleFontData* font, const GlyphBuffer& glyphBuffer, 
                       int from, int numGlyphs, const FloatPoint& point) const
 {
index 3d96658..322afb1 100644 (file)
@@ -632,7 +632,7 @@ void PopupMenuWin::paint(const IntRect& damageRect, HDC hdc)
             
         unsigned length = itemText.length();
         const UChar* string = itemText.characters();
-        TextRun textRun(string, length, false, 0, 0, itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft);
+        TextRun textRun(string, length, false, 0, 0, TextRun::AllowTrailingExpansion, itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft);
 
         context.setFillColor(optionTextColor, ColorSpaceDeviceRGB);
         
index 958569c..db66b43 100644 (file)
@@ -53,7 +53,7 @@ void EllipsisBox::paint(PaintInfo& paintInfo, int tx, int ty)
     }
 
     const String& str = m_str;
-    context->drawText(style->font(), TextRun(str.characters(), str.length(), false, 0, 0, false, style->visuallyOrdered()), IntPoint(m_x + tx, m_y + ty + style->fontMetrics().ascent()));
+    context->drawText(style->font(), TextRun(str.characters(), str.length(), false, 0, 0, TextRun::AllowTrailingExpansion, false, style->visuallyOrdered()), IntPoint(m_x + tx, m_y + ty + style->fontMetrics().ascent()));
 
     // Restore the regular fill color.
     if (textColor != context->fillColor())
@@ -74,7 +74,7 @@ IntRect EllipsisBox::selectionRect(int tx, int ty)
 {
     RenderStyle* style = m_renderer->style(m_firstLine);
     const Font& f = style->font();
-    return enclosingIntRect(f.selectionRectForText(TextRun(m_str.characters(), m_str.length(), false, 0, 0, false, style->visuallyOrdered()),
+    return enclosingIntRect(f.selectionRectForText(TextRun(m_str.characters(), m_str.length(), false, 0, 0, TextRun::AllowTrailingExpansion, false, style->visuallyOrdered()),
             IntPoint(m_x + tx, m_y + ty + root()->selectionTop()), root()->selectionHeight()));
 }
 
@@ -94,7 +94,7 @@ void EllipsisBox::paintSelection(GraphicsContext* context, int tx, int ty, Rende
     int y = root()->selectionTop();
     int h = root()->selectionHeight();
     context->clip(IntRect(m_x + tx, y + ty, m_logicalWidth, h));
-    context->drawHighlightForText(font, TextRun(m_str.characters(), m_str.length(), false, 0, 0, false, style->visuallyOrdered()),
+    context->drawHighlightForText(font, TextRun(m_str.characters(), m_str.length(), false, 0, 0, TextRun::AllowTrailingExpansion, false, style->visuallyOrdered()),
         IntPoint(m_x + tx, m_y + ty + y), h, c, style->colorSpace());
     context->restore();
 }
index 5b3f682..d486ec0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 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
@@ -61,7 +61,7 @@ public:
         , m_determinedIfPrevOnLineExists(false)
         , m_nextOnLineExists(false)
         , m_prevOnLineExists(false)
-        , m_toAdd(0)
+        , m_expansion(0)
 #ifndef NDEBUG
         , m_hasBadParent(false)
 #endif
@@ -95,7 +95,7 @@ public:
         , m_determinedIfPrevOnLineExists(false)
         , m_nextOnLineExists(false)
         , m_prevOnLineExists(false)
-        , m_toAdd(0)
+        , m_expansion(0)
 #ifndef NDEBUG
         , m_hasBadParent(false)
 #endif
@@ -290,7 +290,7 @@ public:
 
     void setHasBadParent();
 
-    int toAdd() const { return m_toAdd; }
+    int expansion() const { return m_expansion; }
     
     bool visibleToHitTesting() const { return renderer()->style()->visibility() == VISIBLE && renderer()->style()->pointerEvents() != PE_NONE; }
     
@@ -348,7 +348,7 @@ protected:
     mutable bool m_determinedIfPrevOnLineExists : 1;
     mutable bool m_nextOnLineExists : 1;
     mutable bool m_prevOnLineExists : 1;
-    int m_toAdd : 11; // for justified text
+    int m_expansion : 11; // for justified text
 
 #ifndef NDEBUG
 private:
index 8a92450..b574cd1 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * (C) 1999 Lars Knoll (knoll@kde.org)
  * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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
@@ -40,7 +40,6 @@
 #include "RenderRubyText.h"
 #include "RenderTheme.h"
 #include "Text.h"
-#include "TextRun.h"
 #include "break_lines.h"
 #include <wtf/AlwaysInline.h>
 
@@ -163,7 +162,7 @@ IntRect InlineTextBox::selectionRect(int tx, int ty, int startPos, int endPos)
         ePos = len;
     }
 
-    IntRect r = enclosingIntRect(f.selectionRectForText(TextRun(characters, len, textObj->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride),
+    IntRect r = enclosingIntRect(f.selectionRectForText(TextRun(characters, len, textObj->allowTabs(), textPos(), m_expansion, trailingExpansionBehavior(), !isLeftToRightDirection(), m_dirOverride),
                                                         IntPoint(), selHeight, sPos, ePos));
                                                         
     int logicalWidth = r.width();
@@ -608,7 +607,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty)
     if (hasHyphen())
         adjustCharactersAndLengthForHyphen(charactersWithHyphen, styleToUse, characters, length);
 
-    TextRun textRun(characters, length, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || styleToUse->visuallyOrdered());
+    TextRun textRun(characters, length, textRenderer()->allowTabs(), textPos(), m_expansion, trailingExpansionBehavior(), !isLeftToRightDirection(), m_dirOverride || styleToUse->visuallyOrdered());
 
     int sPos = 0;
     int ePos = 0;
@@ -762,7 +761,7 @@ void InlineTextBox::paintSelection(GraphicsContext* context, const IntPoint& box
     int selHeight = selectionHeight();
     IntPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
     context->clip(IntRect(localOrigin, IntSize(m_logicalWidth, selHeight)));
-    context->drawHighlightForText(font, TextRun(characters, length, textRenderer()->allowTabs(), textPos(), m_toAdd
+    context->drawHighlightForText(font, TextRun(characters, length, textRenderer()->allowTabs(), textPos(), m_expansion, trailingExpansionBehavior()
                                   !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()),
                                   localOrigin, selHeight, c, style->colorSpace(), sPos, ePos);
     context->restore();
@@ -786,7 +785,7 @@ void InlineTextBox::paintCompositionBackground(GraphicsContext* context, const I
     int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
     int selHeight = selectionHeight();
     IntPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
-    context->drawHighlightForText(font, TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd,
+    context->drawHighlightForText(font, TextRun(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_expansion, trailingExpansionBehavior(),
                                   !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()),
                                   localOrigin, selHeight, c, style->colorSpace(), sPos, ePos);
     context->restore();
@@ -948,7 +947,7 @@ void InlineTextBox::paintSpellingOrGrammarMarker(GraphicsContext* pt, const IntP
         int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
         int selHeight = selectionHeight();
         IntPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY);
-        TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered());
+        TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_expansion, trailingExpansionBehavior(), !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered());
          
         IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, selHeight, startPosition, endPosition));
         start = markerRect.x() - startPoint.x();
@@ -992,7 +991,7 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const IntPoint& bo
 
     int sPos = max(marker.startOffset - m_start, (unsigned)0);
     int ePos = min(marker.endOffset - m_start, (unsigned)m_len);    
-    TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered());
+    TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_expansion, trailingExpansionBehavior(), !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered());
     
     // Always compute and store the rect associated with this marker. The computed rect is in absolute coordinates.
     IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, IntPoint(m_x, selectionTop()), selHeight, sPos, ePos));
@@ -1020,7 +1019,7 @@ void InlineTextBox::computeRectForReplacementMarker(const DocumentMarker& marker
     
     int sPos = max(marker.startOffset - m_start, (unsigned)0);
     int ePos = min(marker.endOffset - m_start, (unsigned)m_len);    
-    TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered());
+    TextRun run(textRenderer()->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_expansion, trailingExpansionBehavior(), !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered());
     IntPoint startPoint = IntPoint(m_x, y);
     
     // Compute and store the rect associated with this marker.
@@ -1185,7 +1184,7 @@ int InlineTextBox::offsetForPosition(int lineOffset, bool includePartialGlyphs)
     RenderStyle* style = text->style(m_firstLine);
     const Font* f = &style->font();
     int offset = f->offsetForPosition(TextRun(textRenderer()->text()->characters() + m_start, m_len,
-        textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()),
+        textRenderer()->allowTabs(), textPos(), m_expansion, trailingExpansionBehavior(), !isLeftToRightDirection(), m_dirOverride || style->visuallyOrdered()),
         lineOffset - logicalLeft(), includePartialGlyphs);
     if (blockIsInOppositeDirection && (!offset || offset == m_len))
         return !offset ? m_len : 0;
@@ -1205,7 +1204,7 @@ int InlineTextBox::positionForOffset(int offset) const
     int from = !isLeftToRightDirection() ? offset - m_start : 0;
     int to = !isLeftToRightDirection() ? m_len : offset - m_start;
     // FIXME: Do we need to add rightBearing here?
-    return enclosingIntRect(f.selectionRectForText(TextRun(text->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_toAdd, !isLeftToRightDirection(), m_dirOverride),
+    return enclosingIntRect(f.selectionRectForText(TextRun(text->text()->characters() + m_start, m_len, textRenderer()->allowTabs(), textPos(), m_expansion, trailingExpansionBehavior(), !isLeftToRightDirection(), m_dirOverride),
                                                    IntPoint(logicalLeft(), 0), 0, from, to)).right();
 }
 
index 8a4cd72..724ef82 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * (C) 1999 Lars Knoll (knoll@kde.org)
  * (C) 2000 Dirk Mueller (mueller@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2009, 2010, 2011 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
@@ -25,6 +25,7 @@
 
 #include "InlineBox.h"
 #include "RenderText.h" // so textRenderer() can be inline
+#include "TextRun.h"
 
 namespace WebCore {
 
@@ -109,7 +110,7 @@ private:
 public:
     virtual bool isLineBreak() const;
 
-    void setSpaceAdd(int add) { m_logicalWidth -= m_toAdd; m_toAdd = add; m_logicalWidth += m_toAdd; }
+    void setExpansion(int expansion) { m_logicalWidth -= m_expansion; m_expansion = expansion; m_logicalWidth += m_expansion; }
 
 private:
     virtual bool isInlineTextBox() const { return true; }    
@@ -156,6 +157,8 @@ private:
     void paintSpellingOrGrammarMarker(GraphicsContext*, const IntPoint& boxOrigin, const DocumentMarker&, RenderStyle*, const Font&, bool grammar);
     void paintTextMatchMarker(GraphicsContext*, const IntPoint& boxOrigin, const DocumentMarker&, RenderStyle*, const Font&);
     void computeRectForReplacementMarker(const DocumentMarker&, RenderStyle*, const Font&);
+
+    TextRun::TrailingExpansionBehavior trailingExpansionBehavior() const { return m_expansion && nextLeafChild() ? TextRun::AllowTrailingExpansion : TextRun::ForbidTrailingExpansion; }
 };
 
 inline RenderText* InlineTextBox::textRenderer() const
index 2637bc0..cdfcaa0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
- * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All right reserved.
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
  * Copyright (C) 2010 Google Inc. All rights reserved.
  *
  * This library is free software; you can redistribute it and/or
@@ -310,7 +310,9 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
     int availableLogicalWidth = availableLogicalWidthForLine(logicalHeight(), firstLine);
     int totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth();
     bool needsWordSpacing = false;
-    unsigned numSpaces = 0;
+    unsigned expansionOpportunityCount = 0;
+    bool isAfterExpansion = true;
+    Vector<unsigned, 16> expansionOpportunities;
     ETextAlign textAlign = style()->textAlign();
 
     for (BidiRun* r = firstRun; r; r = r->next()) {
@@ -322,12 +324,9 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
             RenderText* rt = toRenderText(r->m_object);
 
             if (textAlign == JUSTIFY && r != trailingSpaceRun) {
-                const UChar* characters = rt->characters();
-                for (int i = r->m_start; i < r->m_stop; i++) {
-                    UChar c = characters[i];
-                    if (Font::treatAsSpace(c))
-                        numSpaces++;
-                }
+                unsigned opportunitiesInRun = Font::expansionOpportunityCount(rt->characters() + r->m_start, r->m_stop - r->m_start, isAfterExpansion);
+                expansionOpportunities.append(opportunitiesInRun);
+                expansionOpportunityCount += opportunitiesInRun;
             }
 
             if (int length = rt->textLength()) {
@@ -354,16 +353,24 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
                 GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(static_cast<InlineTextBox*>(r->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).first;
                 it->second.second = glyphOverflow;
             }
-        } else if (!r->m_object->isRenderInline()) {
-            RenderBox* renderBox = toRenderBox(r->m_object);
-            renderBox->computeLogicalWidth();
-            r->m_box->setLogicalWidth(logicalWidthForChild(renderBox));
-            totalLogicalWidth += marginStartForChild(renderBox) + marginEndForChild(renderBox);
+        } else {
+            isAfterExpansion = false;
+            if (!r->m_object->isRenderInline()) {
+                RenderBox* renderBox = toRenderBox(r->m_object);
+                renderBox->computeLogicalWidth();
+                r->m_box->setLogicalWidth(logicalWidthForChild(renderBox));
+                totalLogicalWidth += marginStartForChild(renderBox) + marginEndForChild(renderBox);
+            }
         }
 
         totalLogicalWidth += r->m_box->logicalWidth();
     }
 
+    if (isAfterExpansion && !expansionOpportunities.isEmpty()) {
+        expansionOpportunities.last()--;
+        expansionOpportunityCount--;
+    }
+
     // Armed with the total width of the line (without justification),
     // we now examine our text-align property in order to determine where to position the
     // objects horizontally.  The total width of the line can be increased if we end up
@@ -385,7 +392,7 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
             }
             break;
         case JUSTIFY:
-            if (numSpaces && !reachedEnd && !lineBox->endsWithBreak()) {
+            if (expansionOpportunityCount && !reachedEnd && !lineBox->endsWithBreak()) {
                 if (trailingSpaceRun) {
                     totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
                     trailingSpaceRun->m_box->setLogicalWidth(0);
@@ -394,7 +401,7 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
             }
             // fall through
         case TAAUTO:
-            numSpaces = 0;
+            expansionOpportunityCount = 0;
             // for right to left fall through to right aligned
             if (style()->isLeftToRightDirection()) {
                 if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun)
@@ -436,31 +443,26 @@ void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox,
             break;
     }
 
-    if (numSpaces) {
+    if (expansionOpportunityCount) {
+        size_t i = 0;
         for (BidiRun* r = firstRun; r; r = r->next()) {
             if (!r->m_box || r == trailingSpaceRun)
                 continue;
 
-            int spaceAdd = 0;
             if (r->m_object->isText()) {
-                unsigned spaces = 0;
-                const UChar* characters = toRenderText(r->m_object)->characters();
-                for (int i = r->m_start; i < r->m_stop; i++) {
-                    UChar c = characters[i];
-                    if (Font::treatAsSpace(c))
-                        spaces++;
-                }
+                unsigned opportunitiesInRun = expansionOpportunities[i++];
 
-                ASSERT(spaces <= numSpaces);
+                ASSERT(opportunitiesInRun <= expansionOpportunityCount);
 
                 // Only justify text if whitespace is collapsed.
                 if (r->m_object->style()->collapseWhiteSpace()) {
-                    spaceAdd = (availableLogicalWidth - totalLogicalWidth) * spaces / numSpaces;
-                    static_cast<InlineTextBox*>(r->m_box)->setSpaceAdd(spaceAdd);
-                    totalLogicalWidth += spaceAdd;
+                    InlineTextBox* textBox = static_cast<InlineTextBox*>(r->m_box);
+                    int expansion = (availableLogicalWidth - totalLogicalWidth) * opportunitiesInRun / expansionOpportunityCount;
+                    textBox->setExpansion(expansion);
+                    totalLogicalWidth += expansion;
                 }
-                numSpaces -= spaces;
-                if (!numSpaces)
+                expansionOpportunityCount -= opportunitiesInRun;
+                if (!expansionOpportunityCount)
                     break;
             }
         }
index aec55a8..5e33868 100644 (file)
@@ -216,7 +216,7 @@ void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, int tx, int ty)
         const String& displayedFilename = fileTextValue();
         unsigned length = displayedFilename.length();
         const UChar* string = displayedFilename.characters();
-        TextRun textRun(string, length, false, 0, 0, !style()->isLeftToRightDirection(), style()->unicodeBidi() == Override);
+        TextRun textRun(string, length, false, 0, 0, TextRun::AllowTrailingExpansion, !style()->isLeftToRightDirection(), style()->unicodeBidi() == Override);
         
         // Determine where the filename should be placed
         int contentLeft = tx + borderLeft() + paddingLeft();
@@ -273,7 +273,7 @@ void RenderFileUploadControl::computePreferredLogicalWidths()
         // Figure out how big the filename space needs to be for a given number of characters
         // (using "0" as the nominal character).
         const UChar ch = '0';
-        float charWidth = style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, false, false, false));
+        float charWidth = style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, TextRun::AllowTrailingExpansion, false, false, false));
         m_maxPreferredLogicalWidth = (int)ceilf(charWidth * defaultWidthNumChars);
     }
 
index fcd78bf..95214f7 100644 (file)
@@ -112,7 +112,7 @@ void RenderListBox::updateFromElement()
             }
                 
             if (!text.isEmpty()) {
-                float textWidth = itemFont.floatWidth(TextRun(text.impl(), 0, 0, 0, false, false, false, false));
+                float textWidth = itemFont.floatWidth(TextRun(text.impl(), false, 0, 0, TextRun::AllowTrailingExpansion, false, false, false, false));
                 width = max(width, textWidth);
             }
         }
@@ -331,7 +331,7 @@ void RenderListBox::paintItemForeground(PaintInfo& paintInfo, int tx, int ty, in
 
     unsigned length = itemText.length();
     const UChar* string = itemText.characters();
-    TextRun textRun(string, length, 0, 0, 0, !itemStyle->isLeftToRightDirection(), itemStyle->unicodeBidi() == Override, false, false);
+    TextRun textRun(string, length, false, 0, 0, TextRun::AllowTrailingExpansion, !itemStyle->isLeftToRightDirection(), itemStyle->unicodeBidi() == Override, false, false);
 
     // Draw the item text
     if (itemStyle->visibility() != HIDDEN)
index 91ed262..8b667ea 100644 (file)
@@ -544,7 +544,7 @@ float RenderTextControl::getAvgCharWidth(AtomicString family)
         return roundf(style()->font().primaryFont()->avgCharWidth());
 
     const UChar ch = '0'; 
-    return style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, false, false, false));
+    return style()->font().floatWidth(TextRun(&ch, 1, false, 0, 0, TextRun::AllowTrailingExpansion, false, false, false));
 }
 
 float RenderTextControl::scaleEmToUnits(int x) const
@@ -639,7 +639,7 @@ void RenderTextControl::paintPlaceholder(PaintInfo& paintInfo, int tx, int ty)
     paintInfo.context->setFillColor(placeholderStyle->visitedDependentColor(CSSPropertyColor), placeholderStyle->colorSpace());
     
     String placeholderText = static_cast<HTMLTextFormControlElement*>(node())->strippedPlaceholder();
-    TextRun textRun(placeholderText.characters(), placeholderText.length(), 0, 0, 0, !placeholderStyle->isLeftToRightDirection(), placeholderStyle->unicodeBidi() == Override, false, false);
+    TextRun textRun(placeholderText.characters(), placeholderText.length(), false, 0, 0, TextRun::AllowTrailingExpansion, !placeholderStyle->isLeftToRightDirection(), placeholderStyle->unicodeBidi() == Override, false, false);
     
     RenderBox* textRenderer = innerTextElement() ? innerTextElement()->renderBox() : 0;
     if (textRenderer) {
index 257a8c5..0df0420 100644 (file)
@@ -364,6 +364,7 @@ TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFrag
                 , false /* allowTabs */
                 , 0 /* xPos, only relevant with allowTabs=true */
                 , 0 /* padding, only relevant for justified text, not relevant for SVG */
+                , TextRun::AllowTrailingExpansion
                 , direction() == RTL
                 , m_dirOverride || style->visuallyOrdered() /* directionalOverride */);
 
index 17769f0..8e3502e 100644 (file)
@@ -1,3 +1,14 @@
+2011-01-26  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Dave Hyatt.
+
+        <rdar://problem/8446709> Allow inter-ideograph justification for CJK
+        https://bugs.webkit.org/show_bug.cgi?id=53184
+
+        * src/WebTextRun.cpp:
+        (WebKit::WebTextRun::operator WebCore::TextRun): Added a TrailingExpansionBehavior parameter to the
+        RenderText constructor.
+
 2011-01-26  Kenneth Russell  <kbr@google.com>
 
         Reviewed by James Robinson.
index 58d9fac..b8c6ccb 100644 (file)
@@ -39,7 +39,7 @@ namespace WebKit {
 
 WebTextRun::operator WebCore::TextRun() const
 {
-    return TextRun(text, false, 0, 0, rtl, directionalOverride);
+    return TextRun(text, false, 0, 0, TextRun::AllowTrailingExpansion, rtl, directionalOverride);
 }
 
 } // namespace WebKit
index 7f10b60..0db7350 100644 (file)
@@ -1,3 +1,14 @@
+2011-01-26  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Dave Hyatt.
+
+        <rdar://problem/8446709> Allow inter-ideograph justification for CJK
+        https://bugs.webkit.org/show_bug.cgi?id=53184
+
+        * WebProcess/WebCoreSupport/win/WebPopupMenuWin.cpp:
+        (WebKit::WebPopupMenu::setUpPlatformData): Added a TrailingExpansionBehavior parameter to the
+        RenderText constructor.
+
 2011-01-26  Jing Jin  <jjin@apple.com>
 
         Reviewed by Darin Adler.
index 9fdfe2f..e48bd01 100644 (file)
@@ -115,7 +115,7 @@ void WebPopupMenu::setUpPlatformData(const WebCore::IntRect& pageCoordinates, Pl
 
         unsigned length = itemText.length();
         const UChar* string = itemText.characters();
-        TextRun textRun(string, length, false, 0, 0, itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft);
+        TextRun textRun(string, length, false, 0, 0, TextRun::AllowTrailingExpansion, itemText.defaultWritingDirection() == WTF::Unicode::RightToLeft);
 
         notSelectedBackingStoreContext->setFillColor(optionTextColor, ColorSpaceDeviceRGB);
         selectedBackingStoreContext->setFillColor(activeOptionTextColor, ColorSpaceDeviceRGB);