Implement text-combine rendering code
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 31 Jan 2011 20:39:09 +0000 (20:39 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 31 Jan 2011 20:39:09 +0000 (20:39 +0000)
https://bugs.webkit.org/show_bug.cgi?id=50621

Patch by takano takumi <takano@apple.com> on 2011-01-31
Reviewed by Dave Hyatt.

Source/WebCore:

Test: fast/text/international/text-combine-image-test.html

* Android.mk: Added RenderCombineText.cpp/h
* CMakeLists.txt: Added RenderCombineText.cpp/h
* GNUmakefile.am: Added RenderCombineText.cpp/h
* WebCore.exp.in:
* WebCore.gypi: Added RenderCombineText.cpp/h
* WebCore.pro: Added RenderCombineText.cpp/h
* WebCore.vcproj/WebCore.vcproj: Added RenderCombineText.cpp/h
* WebCore.xcodeproj/project.pbxproj: Added RenderCombineText.cpp/h
* css/CSSFontFaceSource.cpp:
(WebCore::CSSFontFaceSource::getFontData):
- Added fontDescription.widthVariant to SimpleFontData creation.
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::applyProperty):
- Changed to set "Unique" flag to RenderStyle in case of TextCombine.
* dom/Text.cpp:
(WebCore::Text::createRenderer):
- Changed to create RenderCombineText in case of TextCombine.
* loader/cache/CachedFont.cpp:
(WebCore::CachedFont::platformDataFromCustomData):
- Added FontWidthVariant as an argument for FontPlatformData creation.
* loader/cache/CachedFont.h:
- Ditto.
* platform/graphics/Font.h:
(WebCore::Font::widthVariant):
- The accessor to FontWidthVariant member variable.
* platform/graphics/FontCache.cpp:
- Made cache to incorporate FontWidthVariant value.
(WebCore::FontPlatformDataCacheKey::FontPlatformDataCacheKey):
(WebCore::FontPlatformDataCacheKey::operator==):
(WebCore::computeHash):
(WebCore::FontCache::getCachedFontPlatformData):
* platform/graphics/FontDescription.h:
- Add a member variable that holds a width variant - none, half-width, third-width, and quarter-width.
(WebCore::FontDescription::FontDescription):
(WebCore::FontDescription::widthVariant):
(WebCore::FontDescription::setWidthVariant):
(WebCore::FontDescription::operator==):
* platform/graphics/FontWidthVariant.h: Added.
* platform/graphics/cairo/FontCustomPlatformData.h:
- Changed to carry FontWidthVariant value.
* platform/graphics/cocoa/FontPlatformData.h:
- Changed to carry FontWidthVariant value.
(WebCore::FontPlatformData::FontPlatformData):
(WebCore::FontPlatformData::widthVariant):
(WebCore::FontPlatformData::hash):
(WebCore::FontPlatformData::operator==):
* platform/graphics/cocoa/FontPlatformDataCocoa.mm:
(WebCore::FontPlatformData::FontPlatformData):
- Changed to carry FontWidthVariant value.
(WebCore::FontPlatformData::operator=):
- Ditto.
(WebCore::mapFontWidthVariantToCTFeatureSelector):
- A function to map a FontWidthVariant value to a CoreText's text spacing feature selector.
(WebCore::FontPlatformData::ctFont):
- Changed to create CTFont with text spacing variant based on FontWidthVariant.
* platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp:
(WebCore::FontCustomPlatformData::fontPlatformData):
- Changed to carry FontWidthVariant value.
* platform/graphics/haiku/FontCustomPlatformData.cpp:
(WebCore::FontCustomPlatformData::fontPlatformData):
- Changed to carry FontWidthVariant value.
* platform/graphics/haiku/FontCustomPlatformData.h:
* platform/graphics/mac/FontCacheMac.mm:
(WebCore::FontCache::createFontPlatformData):
- Changed to carry FontWidthVariant value.
* platform/graphics/mac/FontCustomPlatformData.cpp:
(WebCore::FontCustomPlatformData::fontPlatformData):
- Changed to carry FontWidthVariant value.
* platform/graphics/mac/FontCustomPlatformData.h:
- Ditto.
* platform/graphics/mac/GlyphPageTreeNodeMac.cpp:
(WebCore::shouldUseCoreText):
- Changed to skip CT path when width variant is specified.
* platform/graphics/pango/FontCustomPlatformDataPango.cpp:
(WebCore::FontCustomPlatformData::fontPlatformData):
- Ditto.
* platform/graphics/qt/FontCustomPlatformData.h:
- Ditto.
* platform/graphics/qt/FontCustomPlatformDataQt.cpp:
(WebCore::FontCustomPlatformData::fontPlatformData):
- Ditto.
* platform/graphics/skia/FontCustomPlatformData.cpp:
(WebCore::FontCustomPlatformData::fontPlatformData):
- Ditto.
* platform/graphics/skia/FontCustomPlatformData.h:
- Ditto.
* platform/graphics/win/FontCustomPlatformData.cpp:
(WebCore::FontCustomPlatformData::fontPlatformData):
- Ditto.
* platform/graphics/win/FontCustomPlatformData.h:
- Ditto.
* platform/graphics/win/FontCustomPlatformDataCairo.cpp:
- Ditto.
(WebCore::FontCustomPlatformData::fontPlatformData):
- Ditto.
* platform/graphics/win/FontCustomPlatformDataCairo.h:
- Ditto.
* platform/graphics/wince/FontCustomPlatformData.cpp:
(WebCore::FontCustomPlatformData::fontPlatformData):
- Ditto.
* platform/graphics/wince/FontCustomPlatformData.h:
- Ditto.
* platform/graphics/wx/FontCustomPlatformData.cpp:
(WebCore::FontCustomPlatformData::fontPlatformData):
- Ditto.
* platform/graphics/wx/FontCustomPlatformData.h:
- Ditto.
* rendering/InlineTextBox.cpp:
(WebCore::InlineTextBox::paint):
- In case of RenderCombineText, we don't rotate text even in vertical writing. Also, we render original text
instead of text returned from text().
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::computeInlinePreferredLogicalWidths):
- Made to call RenderCombinedText's prepareTextCombine() here.
* rendering/RenderBlockLineLayout.cpp:
(WebCore::textWidth):
- Made to always use the render object's width() in case of TextCombine.
(WebCore::RenderBlock::findNextLineBreak):
- Made to call RenderCombinedText's prepareTextCombine() here.
* rendering/RenderCombineText.cpp: Added. A subclass of RenderText.
(WebCore::RenderCombineText::RenderCombineText):
(WebCore::RenderCombineText::styleDidChange):
- Clear the flag that indicated the font has been prepared for combining. The font will be reinitialized in
the next call of RenderBlock::findNextLineBreak().
(WebCore::RenderCombineText::setTextInternal):
- Ditto.
(WebCore::RenderCombineText::width):
- Returns 1-em width in case of font combine.
(WebCore::RenderCombineText::adjustTextOrigin):
- Adjust drawing origin point in case of font combine.
(WebCore::RenderCombineText::charactersToRender):
- Return original text instead of current text in case of font combine.
(WebCore::RenderCombineText::combineText):
- This function tries to pack passed text with; 1) the current font as is, 2) the font created
from the descriptor with half-width variant specified, 3) the font with third-width variant, 4) the font
with quarter-width variant.
- If a suitable font successfully found, replace the current font with the new font. If no appropriate font found,
we give up text-combine as the CSS spec describes.
- If a new font found, we replace the text with 0xFFFC. This is needed for a combined text block to be able to
behave like a single character against text decorations.
* rendering/RenderCombineText.h: Added.
(WebCore::RenderCombineText::isCombined):
(WebCore::RenderCombineText::combinedTextWidth):
- Returns 1-em width in case of font combine.
(WebCore::RenderCombineText::renderName):
(WebCore::toRenderCombineText):
* rendering/RenderText.cpp:
(WebCore::RenderText::widthFromCache):
- Made to call RenderCombineText's combinedTextWidth when the text is combined.
* rendering/RenderingAllInOne.cpp: Added RenderCombineText.cpp
* rendering/style/RenderStyle.h:
(WebCore::InheritedFlags::hasTextCombine):
- Added for a quick test of TextCombine.

LayoutTests:

* fast/text/international/text-combine-image-test.html: Added.
* platform/mac/fast/text/international/text-combine-image-test-expected.checksum: Added.
* platform/mac/fast/text/international/text-combine-image-test-expected.png: Added.
* platform/mac/fast/text/international/text-combine-image-test-expected.txt: Added.

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

54 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/text/international/text-combine-image-test.html [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/international/text-combine-image-test-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/international/text-combine-image-test-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/international/text-combine-image-test-expected.txt [new file with mode: 0644]
Source/WebCore/Android.mk
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.am
Source/WebCore/WebCore.exp.in
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.pro
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSFontFaceSource.cpp
Source/WebCore/css/CSSStyleSelector.cpp
Source/WebCore/dom/Text.cpp
Source/WebCore/loader/cache/CachedFont.cpp
Source/WebCore/loader/cache/CachedFont.h
Source/WebCore/platform/graphics/Font.h
Source/WebCore/platform/graphics/FontCache.cpp
Source/WebCore/platform/graphics/FontDescription.h
Source/WebCore/platform/graphics/FontWidthVariant.h [new file with mode: 0644]
Source/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
Source/WebCore/platform/graphics/cocoa/FontPlatformData.h
Source/WebCore/platform/graphics/cocoa/FontPlatformDataCocoa.mm
Source/WebCore/platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp
Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.cpp
Source/WebCore/platform/graphics/haiku/FontCustomPlatformData.h
Source/WebCore/platform/graphics/mac/FontCacheMac.mm
Source/WebCore/platform/graphics/mac/FontCustomPlatformData.cpp
Source/WebCore/platform/graphics/mac/FontCustomPlatformData.h
Source/WebCore/platform/graphics/mac/GlyphPageTreeNodeMac.cpp
Source/WebCore/platform/graphics/pango/FontCustomPlatformDataPango.cpp
Source/WebCore/platform/graphics/qt/FontCustomPlatformData.h
Source/WebCore/platform/graphics/qt/FontCustomPlatformDataQt.cpp
Source/WebCore/platform/graphics/skia/FontCustomPlatformData.cpp
Source/WebCore/platform/graphics/skia/FontCustomPlatformData.h
Source/WebCore/platform/graphics/win/FontCustomPlatformData.cpp
Source/WebCore/platform/graphics/win/FontCustomPlatformData.h
Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.cpp
Source/WebCore/platform/graphics/win/FontCustomPlatformDataCairo.h
Source/WebCore/platform/graphics/wince/FontCustomPlatformData.cpp
Source/WebCore/platform/graphics/wince/FontCustomPlatformData.h
Source/WebCore/platform/graphics/wx/FontCustomPlatformData.cpp
Source/WebCore/platform/graphics/wx/FontCustomPlatformData.h
Source/WebCore/rendering/InlineTextBox.cpp
Source/WebCore/rendering/RenderBlock.cpp
Source/WebCore/rendering/RenderBlockLineLayout.cpp
Source/WebCore/rendering/RenderCombineText.cpp [new file with mode: 0644]
Source/WebCore/rendering/RenderCombineText.h [new file with mode: 0644]
Source/WebCore/rendering/RenderText.cpp
Source/WebCore/rendering/RenderingAllInOne.cpp
Source/WebCore/rendering/style/RenderStyle.h

index 40aaa9a..f50a6bf 100644 (file)
@@ -1,3 +1,15 @@
+2011-01-31  takano takumi  <takano@apple.com>
+
+        Reviewed by Dave Hyatt.
+
+        Implement text-combine rendering code
+        https://bugs.webkit.org/show_bug.cgi?id=50621
+
+        * fast/text/international/text-combine-image-test.html: Added.
+        * platform/mac/fast/text/international/text-combine-image-test-expected.checksum: Added.
+        * platform/mac/fast/text/international/text-combine-image-test-expected.png: Added.
+        * platform/mac/fast/text/international/text-combine-image-test-expected.txt: Added.
+
 2011-01-31  Jessie Berlin  <jberlin@apple.com>
 
         [Windows 7 Release Tests] fast/forms/select-writing-direction-natural.html failing since r77046
diff --git a/LayoutTests/fast/text/international/text-combine-image-test.html b/LayoutTests/fast/text/international/text-combine-image-test.html
new file mode 100644 (file)
index 0000000..31f32d2
--- /dev/null
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta http-equiv="content-type" content="text/html; charset=utf-8">
+<title>text-combine image test</title>
+<style>
+body {
+    -webkit-writing-mode: vertical-rl;
+}
+
+#Hira24 {
+    font-family: "HiraMinPro-W3";
+    font-size: 24pt;
+}
+
+#Hira24_float {
+    font-family: "HiraMinPro-W3";
+    font-size: 18pt;
+    float: right;
+    border: solid 1px;
+    border-color: red;
+}
+
+#Times24 {
+    font-family: "Times";
+    font-size: 24pt;
+}
+
+#combine {
+    -webkit-text-combine: horizontal;
+}
+
+</style>
+</head>
+<body>
+<hr>
+<span id="Hira24">OFF=西暦2010年1月20日365回</span>
+<hr>
+<span id="Hira24"><span id="combine">ON</span>=西暦<span id="combine">2010</span>年<span id="combine">1</span>月<span id="combine">20</span>日<span id="combine">365</span>回</span>
+<hr>
+<span id="Times24"><span id="combine">Times</span>=西暦<span id="combine">2010</span>年<span id="combine">1</span>月<span id="combine">20</span>日<span id="combine">365</span>回</span>
+<hr>
+<p>
+<span id="Hira24_float">float:right:<span id="combine">2010</span>年<span id="combine">1</span>月<span id="combine">20</span>日</span>
+その女がねかしつけに来てくれるまで、わたしはけっしてねどこにははいらなかった。冬のあらしがだんごのような雪をふきつけて窓ガラスを白くするじぶんになると、この女の人は両手の間にわたしの足をおさえて、歌を歌いながら暖めてくれた。その歌の節も文句も、いまに忘れずにいる。
+</p>
+</body>
+</html>
diff --git a/LayoutTests/platform/mac/fast/text/international/text-combine-image-test-expected.checksum b/LayoutTests/platform/mac/fast/text/international/text-combine-image-test-expected.checksum
new file mode 100644 (file)
index 0000000..ad4e882
--- /dev/null
@@ -0,0 +1 @@
+979b9476b03277b942201e289b7383d6
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/fast/text/international/text-combine-image-test-expected.png b/LayoutTests/platform/mac/fast/text/international/text-combine-image-test-expected.png
new file mode 100644 (file)
index 0000000..5353b94
Binary files /dev/null and b/LayoutTests/platform/mac/fast/text/international/text-combine-image-test-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/text/international/text-combine-image-test-expected.txt b/LayoutTests/platform/mac/fast/text/international/text-combine-image-test-expected.txt
new file mode 100644 (file)
index 0000000..74790d8
--- /dev/null
@@ -0,0 +1,95 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (440,0) size 360x600
+  RenderBlock {HTML} at (0,0) size 360x600
+    RenderBody {BODY} at (8,8) size 336x584
+      RenderBlock {HR} at (0,0) size 2x584 [border: (1px inset #000000)]
+      RenderBlock (anonymous) at (10,0) size 48x584
+        RenderInline {SPAN} at (0,0) size 32x474
+          RenderText {#text} at (8,0) size 32x474
+            text run at (8,0) width 474: "OFF=\x{897F}\x{66A6}2010\x{5E74}1\x{6708}20\x{65E5}365\x{56DE}"
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock {HR} at (66,0) size 2x584 [border: (1px inset #000000)]
+      RenderBlock (anonymous) at (76,0) size 48x584
+        RenderInline {SPAN} at (0,0) size 32x380
+          RenderInline {SPAN} at (0,0) size 32x32
+            RenderCombineText {#text} at (8,0) size 32x32
+              text run at (8,0) width 32: "\x{FFFC}"
+          RenderText {#text} at (8,32) size 32x88
+            text run at (8,32) width 88: "=\x{897F}\x{66A6}"
+          RenderInline {SPAN} at (0,0) size 32x32
+            RenderCombineText {#text} at (8,120) size 32x32
+              text run at (8,120) width 32: "\x{FFFC}"
+          RenderText {#text} at (8,152) size 32x33
+            text run at (8,152) width 33: "\x{5E74}"
+          RenderInline {SPAN} at (0,0) size 32x32
+            RenderCombineText {#text} at (8,185) size 32x32
+              text run at (8,185) width 32: "\x{FFFC}"
+          RenderText {#text} at (8,217) size 32x33
+            text run at (8,217) width 33: "\x{6708}"
+          RenderInline {SPAN} at (0,0) size 32x32
+            RenderCombineText {#text} at (8,250) size 32x32
+              text run at (8,250) width 32: "\x{FFFC}"
+          RenderText {#text} at (8,282) size 32x33
+            text run at (8,282) width 33: "\x{65E5}"
+          RenderInline {SPAN} at (0,0) size 32x32
+            RenderCombineText {#text} at (8,315) size 32x32
+              text run at (8,315) width 32: "\x{FFFC}"
+          RenderText {#text} at (8,347) size 32x33
+            text run at (8,347) width 33: "\x{56DE}"
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock {HR} at (132,0) size 2x584 [border: (1px inset #000000)]
+      RenderBlock (anonymous) at (142,0) size 48x584
+        RenderInline {SPAN} at (0,0) size 37x472
+          RenderInline {SPAN} at (0,0) size 37x80
+            RenderCombineText {#text} at (5,0) size 37x80
+              text run at (5,0) width 80: "Times"
+          RenderText {#text} at (5,80) size 37x84
+            text run at (5,80) width 84: "=\x{897F}\x{66A6}"
+          RenderInline {SPAN} at (0,0) size 37x64
+            RenderCombineText {#text} at (5,164) size 37x64
+              text run at (5,164) width 64: "2010"
+          RenderText {#text} at (5,228) size 37x33
+            text run at (5,228) width 33: "\x{5E74}"
+          RenderInline {SPAN} at (0,0) size 37x32
+            RenderCombineText {#text} at (5,261) size 37x32
+              text run at (5,261) width 32: "\x{FFFC}"
+          RenderText {#text} at (5,293) size 37x33
+            text run at (5,293) width 33: "\x{6708}"
+          RenderInline {SPAN} at (0,0) size 37x32
+            RenderCombineText {#text} at (5,326) size 37x32
+              text run at (5,326) width 32: "\x{FFFC}"
+          RenderText {#text} at (5,358) size 37x33
+            text run at (5,358) width 33: "\x{65E5}"
+          RenderInline {SPAN} at (0,0) size 37x48
+            RenderCombineText {#text} at (5,391) size 37x48
+              text run at (5,391) width 48: "365"
+          RenderText {#text} at (5,439) size 37x33
+            text run at (5,439) width 33: "\x{56DE}"
+        RenderText {#text} at (0,0) size 0x0
+      RenderBlock {HR} at (198,0) size 2x584 [border: (1px inset #000000)]
+      RenderBlock {P} at (216,0) size 120x584
+        RenderBlock (floating) {SPAN} at (0,316) size 38x268 [border: (1px solid #FF0000)]
+          RenderText {#text} at (7,1) size 24x119
+            text run at (7,1) width 119: "float:right:"
+          RenderInline {SPAN} at (0,0) size 24x24
+            RenderCombineText {#text} at (7,120) size 24x24
+              text run at (7,120) width 24: "\x{FFFC}"
+          RenderText {#text} at (7,144) size 24x25
+            text run at (7,144) width 25: "\x{5E74}"
+          RenderInline {SPAN} at (0,0) size 24x24
+            RenderCombineText {#text} at (7,169) size 24x24
+              text run at (7,169) width 24: "\x{FFFC}"
+          RenderText {#text} at (7,193) size 24x25
+            text run at (7,193) width 25: "\x{6708}"
+          RenderInline {SPAN} at (0,0) size 24x24
+            RenderCombineText {#text} at (7,218) size 24x24
+              text run at (7,218) width 24: "\x{FFFC}"
+          RenderText {#text} at (7,242) size 24x25
+            text run at (7,242) width 25: "\x{65E5}"
+        RenderText {#text} at (3,0) size 114x548
+          text run at (3,0) width 291: "\x{305D}\x{306E}\x{5973}\x{304C}\x{306D}\x{304B}\x{3057}\x{3064}\x{3051}\x{306B}\x{6765}\x{3066}\x{304F}\x{308C}\x{308B}\x{307E}\x{3067}\x{3001}"
+          text run at (27,0) width 274: "\x{308F}\x{305F}\x{3057}\x{306F}\x{3051}\x{3063}\x{3057}\x{3066}\x{306D}\x{3069}\x{3053}\x{306B}\x{306F}\x{306F}\x{3044}\x{3089}\x{306A}"
+          text run at (51,0) width 548: "\x{304B}\x{3063}\x{305F}\x{3002}\x{51AC}\x{306E}\x{3042}\x{3089}\x{3057}\x{304C}\x{3060}\x{3093}\x{3054}\x{306E}\x{3088}\x{3046}\x{306A}\x{96EA}\x{3092}\x{3075}\x{304D}\x{3064}\x{3051}\x{3066}\x{7A93}\x{30AC}\x{30E9}\x{30B9}\x{3092}\x{767D}\x{304F}\x{3059}\x{308B}\x{3058}"
+          text run at (75,0) width 548: "\x{3076}\x{3093}\x{306B}\x{306A}\x{308B}\x{3068}\x{3001}\x{3053}\x{306E}\x{5973}\x{306E}\x{4EBA}\x{306F}\x{4E21}\x{624B}\x{306E}\x{9593}\x{306B}\x{308F}\x{305F}\x{3057}\x{306E}\x{8DB3}\x{3092}\x{304A}\x{3055}\x{3048}\x{3066}\x{3001}\x{6B4C}\x{3092}\x{6B4C}\x{3044}\x{306A}"
+          text run at (99,0) width 468: "\x{304C}\x{3089}\x{6696}\x{3081}\x{3066}\x{304F}\x{308C}\x{305F}\x{3002}\x{305D}\x{306E}\x{6B4C}\x{306E}\x{7BC0}\x{3082}\x{6587}\x{53E5}\x{3082}\x{3001}\x{3044}\x{307E}\x{306B}\x{5FD8}\x{308C}\x{305A}\x{306B}\x{3044}\x{308B}\x{3002}"
index b2e37cb..25d7166 100644 (file)
@@ -668,6 +668,7 @@ LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
        rendering/RenderBox.cpp \
        rendering/RenderBoxModelObject.cpp \
        rendering/RenderButton.cpp \
+       rendering/RenderCombineText.cpp \
        rendering/RenderCounter.cpp \
        rendering/RenderEmbeddedObject.cpp \
        rendering/RenderFieldset.cpp \
index bf3afb2..6be3c9d 100644 (file)
@@ -1470,6 +1470,7 @@ SET(WebCore_SOURCES
     rendering/RenderBox.cpp
     rendering/RenderBoxModelObject.cpp
     rendering/RenderButton.cpp
+    rendering/RenderCombineText.cpp
     rendering/RenderCounter.cpp
     rendering/RenderDataGrid.cpp
     rendering/RenderDetails.cpp
index 767543c..4a5031c 100644 (file)
@@ -1,3 +1,166 @@
+2011-01-31  takano takumi  <takano@apple.com>
+
+        Reviewed by Dave Hyatt.
+
+        Implement text-combine rendering code
+        https://bugs.webkit.org/show_bug.cgi?id=50621
+
+        Test: fast/text/international/text-combine-image-test.html
+
+        * Android.mk: Added RenderCombineText.cpp/h
+        * CMakeLists.txt: Added RenderCombineText.cpp/h
+        * GNUmakefile.am: Added RenderCombineText.cpp/h
+        * WebCore.exp.in:
+        * WebCore.gypi: Added RenderCombineText.cpp/h
+        * WebCore.pro: Added RenderCombineText.cpp/h
+        * WebCore.vcproj/WebCore.vcproj: Added RenderCombineText.cpp/h
+        * WebCore.xcodeproj/project.pbxproj: Added RenderCombineText.cpp/h
+        * css/CSSFontFaceSource.cpp:
+        (WebCore::CSSFontFaceSource::getFontData):
+        - Added fontDescription.widthVariant to SimpleFontData creation.
+        * css/CSSStyleSelector.cpp:
+        (WebCore::CSSStyleSelector::applyProperty):
+        - Changed to set "Unique" flag to RenderStyle in case of TextCombine.
+        * dom/Text.cpp:
+        (WebCore::Text::createRenderer):
+        - Changed to create RenderCombineText in case of TextCombine.
+        * loader/cache/CachedFont.cpp:
+        (WebCore::CachedFont::platformDataFromCustomData):
+        - Added FontWidthVariant as an argument for FontPlatformData creation.
+        * loader/cache/CachedFont.h:
+        - Ditto.
+        * platform/graphics/Font.h:
+        (WebCore::Font::widthVariant):
+        - The accessor to FontWidthVariant member variable.
+        * platform/graphics/FontCache.cpp:
+        - Made cache to incorporate FontWidthVariant value.
+        (WebCore::FontPlatformDataCacheKey::FontPlatformDataCacheKey):
+        (WebCore::FontPlatformDataCacheKey::operator==):
+        (WebCore::computeHash):
+        (WebCore::FontCache::getCachedFontPlatformData):
+        * platform/graphics/FontDescription.h:
+        - Add a member variable that holds a width variant - none, half-width, third-width, and quarter-width.
+        (WebCore::FontDescription::FontDescription):
+        (WebCore::FontDescription::widthVariant):
+        (WebCore::FontDescription::setWidthVariant):
+        (WebCore::FontDescription::operator==):
+        * platform/graphics/FontWidthVariant.h: Added.
+        * platform/graphics/cairo/FontCustomPlatformData.h:
+        - Changed to carry FontWidthVariant value.
+        * platform/graphics/cocoa/FontPlatformData.h:
+        - Changed to carry FontWidthVariant value.
+        (WebCore::FontPlatformData::FontPlatformData):
+        (WebCore::FontPlatformData::widthVariant):
+        (WebCore::FontPlatformData::hash):
+        (WebCore::FontPlatformData::operator==):
+        * platform/graphics/cocoa/FontPlatformDataCocoa.mm:
+        (WebCore::FontPlatformData::FontPlatformData):
+        - Changed to carry FontWidthVariant value.
+        (WebCore::FontPlatformData::operator=):
+        - Ditto.
+        (WebCore::mapFontWidthVariantToCTFeatureSelector):
+        - A function to map a FontWidthVariant value to a CoreText's text spacing feature selector.
+        (WebCore::FontPlatformData::ctFont):
+        - Changed to create CTFont with text spacing variant based on FontWidthVariant.
+        * platform/graphics/freetype/FontCustomPlatformDataFreeType.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        - Changed to carry FontWidthVariant value.
+        * platform/graphics/haiku/FontCustomPlatformData.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        - Changed to carry FontWidthVariant value.
+        * platform/graphics/haiku/FontCustomPlatformData.h:
+        * platform/graphics/mac/FontCacheMac.mm:
+        (WebCore::FontCache::createFontPlatformData):
+        - Changed to carry FontWidthVariant value.
+        * platform/graphics/mac/FontCustomPlatformData.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        - Changed to carry FontWidthVariant value.
+        * platform/graphics/mac/FontCustomPlatformData.h:
+        - Ditto.
+        * platform/graphics/mac/GlyphPageTreeNodeMac.cpp:
+        (WebCore::shouldUseCoreText):
+        - Changed to skip CT path when width variant is specified.
+        * platform/graphics/pango/FontCustomPlatformDataPango.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        - Ditto.
+        * platform/graphics/qt/FontCustomPlatformData.h:
+        - Ditto.
+        * platform/graphics/qt/FontCustomPlatformDataQt.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        - Ditto.
+        * platform/graphics/skia/FontCustomPlatformData.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        - Ditto.
+        * platform/graphics/skia/FontCustomPlatformData.h:
+        - Ditto.
+        * platform/graphics/win/FontCustomPlatformData.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        - Ditto.
+        * platform/graphics/win/FontCustomPlatformData.h:
+        - Ditto.
+        * platform/graphics/win/FontCustomPlatformDataCairo.cpp:
+        - Ditto.
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        - Ditto.
+        * platform/graphics/win/FontCustomPlatformDataCairo.h:
+        - Ditto.
+        * platform/graphics/wince/FontCustomPlatformData.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        - Ditto.
+        * platform/graphics/wince/FontCustomPlatformData.h:
+        - Ditto.
+        * platform/graphics/wx/FontCustomPlatformData.cpp:
+        (WebCore::FontCustomPlatformData::fontPlatformData):
+        - Ditto.
+        * platform/graphics/wx/FontCustomPlatformData.h:
+        - Ditto.
+        * rendering/InlineTextBox.cpp:
+        (WebCore::InlineTextBox::paint):
+        - In case of RenderCombineText, we don't rotate text even in vertical writing. Also, we render original text
+        instead of text returned from text().
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::computeInlinePreferredLogicalWidths):
+        - Made to call RenderCombinedText's prepareTextCombine() here.
+        * rendering/RenderBlockLineLayout.cpp:
+        (WebCore::textWidth):
+        - Made to always use the render object's width() in case of TextCombine.
+        (WebCore::RenderBlock::findNextLineBreak):
+        - Made to call RenderCombinedText's prepareTextCombine() here.
+        * rendering/RenderCombineText.cpp: Added. A subclass of RenderText.
+        (WebCore::RenderCombineText::RenderCombineText):
+        (WebCore::RenderCombineText::styleDidChange):
+        - Clear the flag that indicated the font has been prepared for combining. The font will be reinitialized in
+        the next call of RenderBlock::findNextLineBreak().
+        (WebCore::RenderCombineText::setTextInternal):
+        - Ditto.
+        (WebCore::RenderCombineText::width):
+        - Returns 1-em width in case of font combine.
+        (WebCore::RenderCombineText::adjustTextOrigin):
+        - Adjust drawing origin point in case of font combine.
+        (WebCore::RenderCombineText::charactersToRender):
+        - Return original text instead of current text in case of font combine.
+        (WebCore::RenderCombineText::combineText):
+        - This function tries to pack passed text with; 1) the current font as is, 2) the font created
+        from the descriptor with half-width variant specified, 3) the font with third-width variant, 4) the font
+        with quarter-width variant.
+        - If a suitable font successfully found, replace the current font with the new font. If no appropriate font found,
+        we give up text-combine as the CSS spec describes.
+        - If a new font found, we replace the text with 0xFFFC. This is needed for a combined text block to be able to
+        behave like a single character against text decorations.
+        * rendering/RenderCombineText.h: Added.
+        (WebCore::RenderCombineText::isCombined):
+        (WebCore::RenderCombineText::combinedTextWidth):
+        - Returns 1-em width in case of font combine.
+        (WebCore::RenderCombineText::renderName):
+        (WebCore::toRenderCombineText):
+        * rendering/RenderText.cpp:
+        (WebCore::RenderText::widthFromCache):
+        - Made to call RenderCombineText's combinedTextWidth when the text is combined.
+        * rendering/RenderingAllInOne.cpp: Added RenderCombineText.cpp
+        * rendering/style/RenderStyle.h:
+        (WebCore::InheritedFlags::hasTextCombine):
+        - Added for a quick test of TextCombine.
+
 2011-01-31  Oliver Hunt  <oliver@apple.com>
 
         Convert markstack to a slot visitor API
index c173e87..5206581 100644 (file)
@@ -2743,6 +2743,8 @@ webcore_sources += \
        Source/WebCore/rendering/RenderBR.h \
        Source/WebCore/rendering/RenderButton.cpp \
        Source/WebCore/rendering/RenderButton.h \
+       Source/WebCore/rendering/RenderCombineText.cpp \
+       Source/WebCore/rendering/RenderCombineText.h \
        Source/WebCore/rendering/RenderCounter.cpp \
        Source/WebCore/rendering/RenderCounter.h \
        Source/WebCore/rendering/RenderDataGrid.cpp \
index 03544a6..3b12161 100644 (file)
@@ -408,7 +408,7 @@ __ZN7WebCore16DeviceMotionData12Acceleration6createEbdbdbd
 __ZN7WebCore16DeviceMotionData12RotationRate6createEbdbdbd
 __ZN7WebCore16DeviceMotionData6createEN3WTF10PassRefPtrINS0_12AccelerationEEES4_NS2_INS0_12RotationRateEEEbd
 __ZN7WebCore16FontFallbackList15releaseFontDataEv
-__ZN7WebCore16FontPlatformDataC1EP6NSFontfbbNS_15FontOrientationE
+__ZN7WebCore16FontPlatformDataC1EP6NSFontfbbNS_15FontOrientationENS_16FontWidthVariantE
 __ZN7WebCore16FontPlatformDataD1Ev
 __ZN7WebCore16HTMLInputElement13setAutofilledEb
 __ZN7WebCore16LegacyWebArchive19createFromSelectionEPNS_5FrameE
index 20f8c59..1f8efd8 100644 (file)
             'rendering/RenderBoxModelObject.h',
             'rendering/RenderButton.cpp',
             'rendering/RenderButton.h',
+            'rendering/RenderCombineText.cpp',
+            'rendering/RenderCombineText.h',
             'rendering/RenderCounter.cpp',
             'rendering/RenderCounter.h',
             'rendering/RenderDataGrid.cpp',
index ee0efcb..9e458f0 100644 (file)
@@ -1308,6 +1308,7 @@ SOURCES += \
     rendering/RenderBoxModelObject.cpp \
     rendering/RenderBR.cpp \
     rendering/RenderButton.cpp \
+    rendering/RenderCombineText.cpp \
     rendering/RenderCounter.cpp \
     rendering/RenderDataGrid.cpp \
     rendering/RenderDetails.cpp \
@@ -2278,6 +2279,7 @@ HEADERS += \
     rendering/RenderBoxModelObject.h \
     rendering/RenderBR.h \
     rendering/RenderButton.h \
+    rendering/RenderCombineText.h \
     rendering/RenderCounter.h \
     rendering/RenderDataGrid.h \
     rendering/RenderDetails.h \
index 92426e0..bf8f539 100755 (executable)
                                >
                        </File>
                        <File
+                               RelativePath="..\rendering\RenderCombineText.cpp"
+                               >
+                               <FileConfiguration
+                                       Name="Debug|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug_Cairo_CFLite|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release_Cairo_CFLite|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Debug_All|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                               <FileConfiguration
+                                       Name="Release_LTCG|Win32"
+                                       ExcludedFromBuild="true"
+                                       >
+                                       <Tool
+                                               Name="VCCLCompilerTool"
+                                       />
+                               </FileConfiguration>
+                       </File>
+                       <File
+                               RelativePath="..\rendering\RenderCombineText.h"
+                               >
+                       </File>
+                       <File
                                RelativePath="..\rendering\RenderCounter.cpp"
                                >
                                <FileConfiguration
index 98aa4c7..415602e 100644 (file)
                BCE1C4400D9830F4003B02F2 /* JSLocationCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCE1C43F0D9830F4003B02F2 /* JSLocationCustom.cpp */; };
                BCE3BEC20D222B1D007E06E4 /* TagNodeList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCE3BEC00D222B1D007E06E4 /* TagNodeList.cpp */; };
                BCE3BEC30D222B1D007E06E4 /* TagNodeList.h in Headers */ = {isa = PBXBuildFile; fileRef = BCE3BEC10D222B1D007E06E4 /* TagNodeList.h */; };
+               BCE4413312F748E2009B84B8 /* RenderCombineText.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCE4413112F748E2009B84B8 /* RenderCombineText.cpp */; };
+               BCE4413412F748E2009B84B8 /* RenderCombineText.h in Headers */ = {isa = PBXBuildFile; fileRef = BCE4413212F748E2009B84B8 /* RenderCombineText.h */; };
+               BCE4413612F7490B009B84B8 /* FontWidthVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = BCE4413512F7490B009B84B8 /* FontWidthVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BCE658FF0EA9248A007E4533 /* Theme.h in Headers */ = {isa = PBXBuildFile; fileRef = BCE658FE0EA9248A007E4533 /* Theme.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BCE659A90EA927B9007E4533 /* ThemeTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = BCE659A80EA927B9007E4533 /* ThemeTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BCE659E60EA92FB2007E4533 /* ThemeMac.h in Headers */ = {isa = PBXBuildFile; fileRef = BCE659E50EA92FB2007E4533 /* ThemeMac.h */; };
                BCE1C43F0D9830F4003B02F2 /* JSLocationCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSLocationCustom.cpp; sourceTree = "<group>"; };
                BCE3BEC00D222B1D007E06E4 /* TagNodeList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TagNodeList.cpp; sourceTree = "<group>"; };
                BCE3BEC10D222B1D007E06E4 /* TagNodeList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TagNodeList.h; sourceTree = "<group>"; };
+               BCE4413112F748E2009B84B8 /* RenderCombineText.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderCombineText.cpp; sourceTree = "<group>"; };
+               BCE4413212F748E2009B84B8 /* RenderCombineText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderCombineText.h; sourceTree = "<group>"; };
+               BCE4413512F7490B009B84B8 /* FontWidthVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FontWidthVariant.h; sourceTree = "<group>"; };
                BCE658FE0EA9248A007E4533 /* Theme.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Theme.h; sourceTree = "<group>"; };
                BCE659A80EA927B9007E4533 /* ThemeTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThemeTypes.h; sourceTree = "<group>"; };
                BCE659E50EA92FB2007E4533 /* ThemeMac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThemeMac.h; sourceTree = "<group>"; };
                                B2C3DA5A0D006CD600EF6F26 /* FontSelector.h */,
                                37202198106213C600F25C4B /* FontSmoothingMode.h */,
                                3784C34A0E11AA34007D8D48 /* FontTraitsMask.h */,
+                               BCE4413512F7490B009B84B8 /* FontWidthVariant.h */,
                                BCE04C930DAFF902007A0F41 /* GeneratedImage.cpp */,
                                BC23F0DA0DAFF4A4009FDC91 /* GeneratedImage.h */,
                                BCE04C890DAFF7A0007A0F41 /* Generator.h */,
                                BCEA4825097D93020094C9E4 /* RenderBR.h */,
                                BCEA4826097D93020094C9E4 /* RenderButton.cpp */,
                                BCEA4827097D93020094C9E4 /* RenderButton.h */,
+                               BCE4413112F748E2009B84B8 /* RenderCombineText.cpp */,
+                               BCE4413212F748E2009B84B8 /* RenderCombineText.h */,
                                9392F1430AD185FE00691BD4 /* RenderCounter.cpp */,
                                9392F1410AD185F400691BD4 /* RenderCounter.h */,
                                BC77CEC70FF01CBE0070887B /* RenderDataGrid.cpp */,
                                977E2DCE12F0E28300C13379 /* HTMLSourceTracker.h in Headers */,
                                977E2E0F12F0FC9C00C13379 /* XSSFilter.h in Headers */,
                                0F3DD45012F5EA1B000D9190 /* ShadowBlur.h in Headers */,
+                               BCE4413412F748E2009B84B8 /* RenderCombineText.h in Headers */,
+                               BCE4413612F7490B009B84B8 /* FontWidthVariant.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                977E2DCD12F0E28300C13379 /* HTMLSourceTracker.cpp in Sources */,
                                977E2E0E12F0FC9C00C13379 /* XSSFilter.cpp in Sources */,
                                0F3DD44F12F5EA1B000D9190 /* ShadowBlur.cpp in Sources */,
+                               BCE4413312F748E2009B84B8 /* RenderCombineText.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index f965b1d..681a94b 100644 (file)
@@ -115,7 +115,7 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri
     }
 
     // See if we have a mapping in our FontData cache.
-    unsigned hashKey = (fontDescription.computedPixelSize() + 1) << 3 | (fontDescription.orientation() == Vertical ? 4 : 0) | (syntheticBold ? 2 : 0) | (syntheticItalic ? 1 : 0);
+    unsigned hashKey = (fontDescription.computedPixelSize() + 1) << 5 | fontDescription.widthVariant() << 3 | (fontDescription.orientation() == Vertical ? 4 : 0) | (syntheticBold ? 2 : 0) | (syntheticItalic ? 1 : 0);
     if (SimpleFontData* cachedData = m_fontDataTable.get(hashKey))
         return cachedData;
 
@@ -162,7 +162,7 @@ SimpleFontData* CSSFontFaceSource::getFontData(const FontDescription& fontDescri
                 if (!m_font->ensureCustomFontData())
                     return 0;
 
-                fontData.set(new SimpleFontData(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic, fontDescription.orientation(), fontDescription.renderingMode()), true, false));
+                fontData.set(new SimpleFontData(m_font->platformDataFromCustomData(fontDescription.computedPixelSize(), syntheticBold, syntheticItalic, fontDescription.orientation(), fontDescription.widthVariant(), fontDescription.renderingMode()), true, false));
             }
         } else {
 #if ENABLE(SVG_FONTS)
index 0c407a6..526769d 100644 (file)
@@ -5762,6 +5762,8 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value)
 
     case CSSPropertyWebkitTextCombine:
         HANDLE_INHERIT_AND_INITIAL_AND_PRIMITIVE(textCombine, TextCombine)
+        if (m_style->hasTextCombine())
+            m_style->setUnique(); // The style could be modified in RenderCombineText depending on text metrics.
         return;
 
     case CSSPropertyWebkitTextEmphasisPosition:
index 47c532e..34266f1 100644 (file)
@@ -23,6 +23,7 @@
 #include "Text.h"
 
 #include "ExceptionCode.h"
+#include "RenderCombineText.h"
 #include "RenderText.h"
 #include "TextBreakIterator.h"
 #include <wtf/text/CString.h>
@@ -237,7 +238,7 @@ bool Text::rendererIsNeeded(RenderStyle *style)
     return true;
 }
 
-RenderObject* Text::createRenderer(RenderArena* arena, RenderStyle*)
+RenderObject* Text::createRenderer(RenderArena* arena, RenderStyle* style)
 {
 #if ENABLE(SVG)
     Node* parentOrHost = parentOrHostNode();
@@ -248,7 +249,10 @@ RenderObject* Text::createRenderer(RenderArena* arena, RenderStyle*)
     )
         return new (arena) RenderSVGInlineText(this, dataImpl());
 #endif
-    
+
+    if (style->hasTextCombine())
+        return new (arena) RenderCombineText(this, dataImpl());
+
     return new (arena) RenderText(this, dataImpl());
 }
 
index fe3281e..19eb3ba 100644 (file)
@@ -117,7 +117,7 @@ bool CachedFont::ensureCustomFontData()
     return m_fontData;
 }
 
-FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation orientation, FontRenderingMode renderingMode)
+FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant widthVariant, FontRenderingMode renderingMode)
 {
 #if ENABLE(SVG_FONTS)
     if (m_externalSVGDocument)
@@ -125,7 +125,7 @@ FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, b
 #endif
 #ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
     ASSERT(m_fontData);
-    return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic, orientation, renderingMode);
+    return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic, orientation, widthVariant, renderingMode);
 #else
     return FontPlatformData();
 #endif
index 5814087..cdc32ba 100644 (file)
@@ -29,6 +29,7 @@
 #include "CachedResource.h"
 #include "FontOrientation.h"
 #include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
 #include <wtf/Vector.h>
 
 #if ENABLE(SVG_FONTS)
@@ -63,7 +64,7 @@ public:
     void beginLoadIfNeeded(CachedResourceLoader* dl);
 
     bool ensureCustomFontData();
-    FontPlatformData platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+    FontPlatformData platformDataFromCustomData(float size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
 
 #if ENABLE(SVG_FONTS)
     bool isSVGFont() const { return m_isSVGFont; }
index efca6f8..1eac913 100644 (file)
@@ -123,6 +123,7 @@ public:
 
     bool italic() const { return m_fontDescription.italic(); }
     FontWeight weight() const { return m_fontDescription.weight(); }
+    FontWidthVariant widthVariant() const { return m_fontDescription.widthVariant(); }
 
     bool isPlatformFont() const { return m_isPlatformFont; }
 
index cfca980..ca82ebd 100644 (file)
@@ -57,7 +57,7 @@ struct FontPlatformDataCacheKey {
     WTF_MAKE_FAST_ALLOCATED;
 public:
     FontPlatformDataCacheKey(const AtomicString& family = AtomicString(), unsigned size = 0, unsigned weight = 0, bool italic = false,
-                             bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode, FontOrientation orientation = Horizontal)
+                             bool isPrinterFont = false, FontRenderingMode renderingMode = NormalRenderingMode, FontOrientation orientation = Horizontal, FontWidthVariant widthVariant = RegularWidth)
         : m_size(size)
         , m_weight(weight)
         , m_family(family)
@@ -65,6 +65,7 @@ public:
         , m_printerFont(isPrinterFont)
         , m_renderingMode(renderingMode)
         , m_orientation(orientation)
+        , m_widthVariant(widthVariant)
     {
     }
 
@@ -75,7 +76,7 @@ public:
     {
         return equalIgnoringCase(m_family, other.m_family) && m_size == other.m_size && 
                m_weight == other.m_weight && m_italic == other.m_italic && m_printerFont == other.m_printerFont &&
-               m_renderingMode == other.m_renderingMode && m_orientation == other.m_orientation;
+               m_renderingMode == other.m_renderingMode && m_orientation == other.m_orientation && m_widthVariant == other.m_widthVariant;
     }
 
     unsigned m_size;
@@ -85,6 +86,7 @@ public:
     bool m_printerFont;
     FontRenderingMode m_renderingMode;
     FontOrientation m_orientation;
+    FontWidthVariant m_widthVariant;
 
 private:
     static unsigned hashTableDeletedSize() { return 0xFFFFFFFFU; }
@@ -92,10 +94,11 @@ private:
 
 inline unsigned computeHash(const FontPlatformDataCacheKey& fontKey)
 {
-    unsigned hashCodes[4] = {
+    unsigned hashCodes[5] = {
         CaseFoldingHash::hash(fontKey.m_family),
         fontKey.m_size,
         fontKey.m_weight,
+        fontKey.m_widthVariant,
         static_cast<unsigned>(fontKey.m_orientation) << 3 | static_cast<unsigned>(fontKey.m_italic) << 2 | static_cast<unsigned>(fontKey.m_printerFont) << 1 | static_cast<unsigned>(fontKey.m_renderingMode)
     };
     return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes);
@@ -195,7 +198,7 @@ FontPlatformData* FontCache::getCachedFontPlatformData(const FontDescription& fo
     }
 
     FontPlatformDataCacheKey key(familyName, fontDescription.computedPixelSize(), fontDescription.weight(), fontDescription.italic(),
-                                 fontDescription.usePrinterFont(), fontDescription.renderingMode(), fontDescription.orientation());
+                                 fontDescription.usePrinterFont(), fontDescription.renderingMode(), fontDescription.orientation(), fontDescription.widthVariant());
     FontPlatformData* result = 0;
     bool foundResult;
     FontPlatformDataCache::iterator it = gFontPlatformDataCache->find(key);
index 12900bf..283d297 100644 (file)
@@ -30,6 +30,7 @@
 #include "FontRenderingMode.h"
 #include "FontSmoothingMode.h"
 #include "FontTraitsMask.h"
+#include "FontWidthVariant.h"
 #include "TextRenderingMode.h"
 
 namespace WebCore {
@@ -57,6 +58,7 @@ public:
         : m_specifiedSize(0)
         , m_computedSize(0)
         , m_orientation(Horizontal)
+        , m_widthVariant(RegularWidth)
         , m_italic(false)
         , m_smallCaps(false)
         , m_isAbsoluteSize(false)
@@ -97,6 +99,7 @@ public:
     FontTraitsMask traitsMask() const;
     bool isSpecifiedFont() const { return m_isSpecifiedFont; }
     FontOrientation orientation() const { return m_orientation; }
+    FontWidthVariant widthVariant() const { return m_widthVariant; }
 
     void setFamily(const FontFamily& family) { m_familyList = family; }
     void setComputedSize(float s) { m_computedSize = s; }
@@ -117,6 +120,7 @@ public:
     void setTextRenderingMode(TextRenderingMode rendering) { m_textRendering = rendering; }
     void setIsSpecifiedFont(bool isSpecifiedFont) { m_isSpecifiedFont = isSpecifiedFont; }
     void setOrientation(FontOrientation orientation) { m_orientation = orientation; }
+    void setWidthVariant(FontWidthVariant widthVariant) { m_widthVariant = widthVariant; }
 
 private:
     FontFamily m_familyList; // The list of font families to be used.
@@ -126,6 +130,8 @@ private:
     float m_computedSize;    // Computed size adjusted for the minimum font size and the zoom factor.  
 
     FontOrientation m_orientation;
+    
+    FontWidthVariant m_widthVariant;
 
     bool m_italic : 1;
     bool m_smallCaps : 1;
@@ -162,7 +168,8 @@ inline bool FontDescription::operator==(const FontDescription& other) const
         && m_fontSmoothing == other.m_fontSmoothing
         && m_textRendering == other.m_textRendering
         && m_isSpecifiedFont == other.m_isSpecifiedFont
-        && m_orientation == other.m_orientation;
+        && m_orientation == other.m_orientation
+        && m_widthVariant == other.m_widthVariant;
 }
 
 }
diff --git a/Source/WebCore/platform/graphics/FontWidthVariant.h b/Source/WebCore/platform/graphics/FontWidthVariant.h
new file mode 100644 (file)
index 0000000..bbc98ee
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef FontWidthVariant_h
+#define FontWidthVariant_h
+
+namespace WebCore {
+
+enum FontWidthVariant { RegularWidth, HalfWidth, ThirdWidth, QuarterWidth };
+
+} // namespace WebCore
+
+#endif // FontWidthVariant_h
index 50ea00f..5807102 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "FontOrientation.h"
 #include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
 
@@ -40,7 +41,7 @@ struct FontCustomPlatformData {
 public:
     FontCustomPlatformData(FT_Face, SharedBuffer*);
     ~FontCustomPlatformData();
-    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
     static bool supportsFormat(const String&);
 
 private:
index 8cf08fb..ca38029 100644 (file)
@@ -25,6 +25,7 @@
 #define FontPlatformData_h
 
 #include "FontOrientation.h"
+#include "FontWidthVariant.h"
 #include <wtf/text/StringImpl.h>
 
 #ifdef __OBJC__
@@ -59,11 +60,12 @@ inline CTFontRef toCTFontRef(NSFont *nsFont) { return reinterpret_cast<CTFontRef
 
 class FontPlatformData {
   public:
-    FontPlatformData(float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation = Horizontal)
+    FontPlatformData(float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation = Horizontal, FontWidthVariant widthVariant = RegularWidth)
         : m_syntheticBold(syntheticBold)
         , m_syntheticOblique(syntheticOblique)
         , m_orientation(orientation)
         , m_size(size)
+        , m_widthVariant(widthVariant)
         , m_font(0)
 #ifdef BUILDING_ON_TIGER
         , m_cgFont(0)
@@ -72,13 +74,14 @@ class FontPlatformData {
     {
     }
 
-    FontPlatformData(NSFont *nsFont, float size, bool syntheticBold = false, bool syntheticOblique = false, FontOrientation = Horizontal);
+    FontPlatformData(NSFont*, float size, bool syntheticBold = false, bool syntheticOblique = false, FontOrientation = Horizontal, FontWidthVariant = RegularWidth);
     
-    FontPlatformData(CGFontRef cgFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation)
+    FontPlatformData(CGFontRef cgFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, FontWidthVariant widthVariant)
         : m_syntheticBold(syntheticBold)
         , m_syntheticOblique(syntheticOblique)
         , m_orientation(orientation)
         , m_size(size)
+        , m_widthVariant(widthVariant)
         , m_font(0)
         , m_cgFont(cgFont)
         , m_isColorBitmapFont(false)
@@ -96,17 +99,20 @@ class FontPlatformData {
     bool syntheticBold() const { return m_syntheticBold; }
     bool syntheticOblique() const { return m_syntheticOblique; }
     FontOrientation orientation() const { return m_orientation; }
+    FontWidthVariant widthVariant() const { return m_widthVariant; }
 
     bool m_syntheticBold;
     bool m_syntheticOblique;
     FontOrientation m_orientation;
 
     float m_size;
+    
+    FontWidthVariant m_widthVariant;
 
     unsigned hash() const
     {
         ASSERT(m_font != 0 || m_cgFont == 0);
-        uintptr_t hashCodes[2] = { (uintptr_t)m_font, m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique };
+        uintptr_t hashCodes[3] = { (uintptr_t)m_font, m_widthVariant, m_orientation << 2 | m_syntheticBold << 1 | m_syntheticOblique };
         return WTF::StringHasher::createBlobHash<sizeof(hashCodes)>(hashCodes);
     }
 
@@ -115,7 +121,7 @@ class FontPlatformData {
     bool operator==(const FontPlatformData& other) const
     { 
         return m_font == other.m_font && m_syntheticBold == other.m_syntheticBold && m_syntheticOblique == other.m_syntheticOblique && 
-               m_cgFont == other.m_cgFont && m_size == other.m_size && m_orientation == other.m_orientation;
+               m_cgFont == other.m_cgFont && m_size == other.m_size && m_orientation == other.m_orientation && m_widthVariant == other.m_widthVariant;
     }
 
     NSFont *font() const { return m_font; }
index 8dacbe3..b40f698 100644 (file)
@@ -30,6 +30,9 @@
 
 namespace WebCore {
 
+// These CoreText Text Spacing feature selectors are not defined in CoreText.
+enum TextSpacingCTFeatureSelector { TextSpacingProportional, TextSpacingFullWidth, TextSpacingHalfWidth, TextSpacingThirdWidth, TextSpacingQuarterWidth };
+
 #if PLATFORM(MAC)
 void FontPlatformData::loadFont(NSFont* nsFont, float, NSFont*& outNSFont, CGFontRef& cgFont)
 {
@@ -42,10 +45,11 @@ void FontPlatformData::loadFont(NSFont* nsFont, float, NSFont*& outNSFont, CGFon
 }
 #endif  // PLATFORM(MAC)
 
-FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation)
+FontPlatformData::FontPlatformData(NSFont *nsFont, float size, bool syntheticBold, bool syntheticOblique, FontOrientation orientation, FontWidthVariant widthVariant)
     : m_syntheticBold(syntheticBold)
     , m_syntheticOblique(syntheticOblique)
     , m_size(size)
+    , m_widthVariant(widthVariant)
     , m_font(nsFont)
 #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
     // FIXME: Chromium: The following code isn't correct for the Chromium port since the sandbox might
@@ -79,6 +83,7 @@ FontPlatformData::FontPlatformData(const FontPlatformData& f)
     m_syntheticBold = f.m_syntheticBold;
     m_syntheticOblique = f.m_syntheticOblique;
     m_size = f.m_size;
+    m_widthVariant = f.m_widthVariant;
     m_cgFont = f.m_cgFont;
     m_isColorBitmapFont = f.m_isColorBitmapFont;
     m_orientation = f.m_orientation;
@@ -99,6 +104,7 @@ const FontPlatformData& FontPlatformData::operator=(const FontPlatformData& f)
     m_syntheticBold = f.m_syntheticBold;
     m_syntheticOblique = f.m_syntheticOblique;
     m_size = f.m_size;
+    m_widthVariant = f.m_widthVariant;
     m_cgFont = f.m_cgFont;
     if (m_font == f.m_font)
         return *this;
@@ -165,12 +171,48 @@ bool FontPlatformData::allowsLigatures() const
     return ![[m_font coveredCharacterSet] characterIsMember:'a'];
 }
 
+inline int mapFontWidthVariantToCTFeatureSelector(FontWidthVariant variant)
+{
+    switch(variant) {
+    case RegularWidth:
+        return TextSpacingProportional;
+
+    case HalfWidth:
+        return TextSpacingHalfWidth;
+
+    case ThirdWidth:
+        return TextSpacingThirdWidth;
+
+    case QuarterWidth:
+        return TextSpacingQuarterWidth;
+    }
+
+    ASSERT_NOT_REACHED();
+    return TextSpacingProportional;
+}
+
 CTFontRef FontPlatformData::ctFont() const
 {
-    if (m_font)
-        return toCTFontRef(m_font);
-    if (!m_CTFont)
-        m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0));
+    if (m_widthVariant == RegularWidth) {
+        if (m_font)
+            return toCTFontRef(m_font);
+        if (!m_CTFont)
+            m_CTFont.adoptCF(CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0));
+        return m_CTFont.get();
+    }
+    
+    if (!m_CTFont) {
+        int featureTypeValue = kTextSpacingType;
+        int featureSelectorValue = mapFontWidthVariantToCTFeatureSelector(m_widthVariant);
+        RetainPtr<CTFontRef> sourceFont(AdoptCF, CTFontCreateWithGraphicsFont(m_cgFont.get(), m_size, 0, 0));
+        RetainPtr<CTFontDescriptorRef> sourceDescriptor(AdoptCF, CTFontCopyFontDescriptor(sourceFont.get()));
+        RetainPtr<CFNumberRef> featureType(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &featureTypeValue));
+        RetainPtr<CFNumberRef> featureSelector(AdoptCF, CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &featureSelectorValue));
+        RetainPtr<CTFontDescriptorRef> newDescriptor(AdoptCF, CTFontDescriptorCreateCopyWithFeature(sourceDescriptor.get(), featureType.get(), featureSelector.get()));
+        RetainPtr<CTFontRef> newFont(AdoptCF, CTFontCreateWithFontDescriptor(newDescriptor.get(), m_size, 0));
+
+        m_CTFont = newFont.get() ? newFont : sourceFont;
+    }
     return m_CTFont.get();
 }
 
index c547224..841c8a3 100644 (file)
@@ -59,7 +59,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
     cairo_font_face_destroy(m_fontFace);
 }
 
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
 {
     return FontPlatformData(m_fontFace, size, bold, italic);
 }
index ce7ec46..017b1e4 100644 (file)
@@ -31,7 +31,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
 {
 }
 
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
 {
     return FontPlatformData(size, bold, italic);
 }
index 86f99b2..7ffe89a 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "FontOrientation.h"
 #include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
 #include <wtf/Forward.h>
 
 namespace WebCore {
@@ -38,7 +39,7 @@ namespace WebCore {
 
         static bool supportsFormat(const String&);
 
-        FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+        FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
     };
 
     FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer*);
index 068bd8e..c254906 100644 (file)
@@ -211,7 +211,7 @@ FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontD
     bool syntheticBold = isAppKitFontWeightBold(weight) && !isAppKitFontWeightBold(actualWeight);
     bool syntheticOblique = (traits & NSFontItalicTrait) && !(actualTraits & NSFontItalicTrait);
 
-    return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation());
+    return new FontPlatformData(platformFont, size, syntheticBold, syntheticOblique, fontDescription.orientation(), fontDescription.widthVariant());
 }
 
 } // namespace WebCore
index d04d0e4..f2bc33d 100644 (file)
@@ -38,9 +38,9 @@ FontCustomPlatformData::~FontCustomPlatformData()
     CGFontRelease(m_cgFont);
 }
 
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant widthVariant, FontRenderingMode)
 {
-    return FontPlatformData(m_cgFont, size, bold, italic, orientation);
+    return FontPlatformData(m_cgFont, size, bold, italic, orientation, widthVariant);
 }
 
 FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
index 7043d7e..c7ae1ca 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "FontOrientation.h"
 #include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
 #include <CoreFoundation/CFBase.h>
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
@@ -47,7 +48,7 @@ public:
 
     ~FontCustomPlatformData();
 
-    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
 
     static bool supportsFormat(const String&);
 
index 5388c24..8b04ffa 100644 (file)
@@ -39,8 +39,8 @@ namespace WebCore {
 #ifndef BUILDING_ON_TIGER
 static bool shouldUseCoreText(UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
 {
-    if (fontData->orientation() == Vertical && !fontData->isBrokenIdeographFont()) {
-        // Ideographs don't have a vertical variant.
+    if (fontData->platformData().widthVariant() != RegularWidth || (fontData->orientation() == Vertical && !fontData->isBrokenIdeographFont())) {
+        // Ideographs don't have a vertical variant or width variants.
         for (unsigned i = 0; i < bufferLength; ++i) {
             if (!Font::isCJKIdeograph(buffer[i]))
                 return true;
index a158689..f9d36d3 100644 (file)
@@ -30,7 +30,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
 {
 }
 
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
 {
     return FontPlatformData(m_fontFace, size, bold, italic);
 }
index 54fa679..e8441d2 100644 (file)
@@ -24,6 +24,7 @@
 
 #include "FontOrientation.h"
 #include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
 #include <wtf/FastAllocBase.h>
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
@@ -42,7 +43,7 @@ public:
     // for use with QFontDatabase::addApplicationFont/removeApplicationFont
     int m_handle;
 
-    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
 
     static bool supportsFormat(const String&);
 };
index e2f009b..ec8747d 100644 (file)
@@ -34,7 +34,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
     QFontDatabase::removeApplicationFont(m_handle);
 }
 
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
 {
     QFont font;
     font.setFamily(QFontDatabase::applicationFontFamilies(m_handle)[0]);
index b6427b0..0e68c21 100644 (file)
@@ -65,7 +65,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
 #endif
 }
 
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontRenderingMode mode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation orientation, FontWidthVariant, FontRenderingMode mode)
 {
 #if OS(WINDOWS)
     ASSERT(m_fontReference);
index 4228b40..2dee3ab 100644 (file)
@@ -34,6 +34,7 @@
 
 #include "FontOrientation.h"
 #include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
 
@@ -65,7 +66,7 @@ public:
 
     ~FontCustomPlatformData();
 
-    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal,
+    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth,
                                       FontRenderingMode = NormalRenderingMode);
 
     static bool supportsFormat(const String&);
index 1bb2050..4aee6cd 100644 (file)
@@ -59,7 +59,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
     }
 }
 
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontRenderingMode renderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode renderingMode)
 {
     ASSERT(m_fontReference);
     ASSERT(T2embedLibrary());
index de33c63..abdb356 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "FontOrientation.h"
 #include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
 #include "PlatformString.h"
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
@@ -45,7 +46,7 @@ public:
 
     ~FontCustomPlatformData();
 
-    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
 
     static bool supportsFormat(const String&);
 
index c3decbf..fd30a6d 100644 (file)
@@ -32,7 +32,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
    cairo_font_face_destroy(m_fontFace);
 }
 
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant)
 {
     return FontPlatformData(m_fontFace, size, bold, italic);
 }
index 9c67037..ea3ae38 100644 (file)
@@ -42,7 +42,7 @@ public:
     }
     ~FontCustomPlatformData();
 
-    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal);
+    FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth);
 
     static bool supportsFormat(const String&);
 
index 424b64a..fb97fe1 100644 (file)
@@ -45,7 +45,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
         g_customFontCache->unregisterFont(m_name);
 }
 
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontRenderingMode renderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode renderingMode)
 {
     FontDescription fontDesc;
     fontDesc.setComputedSize(size);
index 0508246..fe7ee94 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "FontDescription.h"
 #include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
 #include "PlatformString.h"
 #include <wtf/Noncopyable.h>
 
@@ -47,7 +48,7 @@ namespace WebCore {
 
         ~FontCustomPlatformData();
 
-        FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation fontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+        FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
 
         static bool supportsFormat(const String&);
 
index 6133372..055f0fc 100644 (file)
@@ -31,7 +31,7 @@ FontCustomPlatformData::~FontCustomPlatformData()
 {
 }
 
-FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontRenderingMode)
+FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, bool italic, FontOrientation, FontWidthVariant, FontRenderingMode)
 {
     return FontPlatformData(size, bold, italic);
 }
index 86f99b2..7ffe89a 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "FontOrientation.h"
 #include "FontRenderingMode.h"
+#include "FontWidthVariant.h"
 #include <wtf/Forward.h>
 
 namespace WebCore {
@@ -38,7 +39,7 @@ namespace WebCore {
 
         static bool supportsFormat(const String&);
 
-        FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontRenderingMode = NormalRenderingMode);
+        FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontOrientation = Horizontal, FontWidthVariant = RegularWidth, FontRenderingMode = NormalRenderingMode);
     };
 
     FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer*);
index b574cd1..00d4089 100644 (file)
@@ -36,6 +36,7 @@
 #include "PaintInfo.h"
 #include "RenderArena.h"
 #include "RenderBlock.h"
+#include "RenderCombineText.h"
 #include "RenderRubyRun.h"
 #include "RenderRubyText.h"
 #include "RenderTheme.h"
@@ -486,7 +487,9 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty)
     IntRect boxRect(boxOrigin, IntSize(logicalWidth(), logicalHeight()));
     IntPoint textOrigin = IntPoint(boxOrigin.x(), boxOrigin.y() + styleToUse->fontMetrics().ascent());
 
-    if (!isHorizontal()) {
+    RenderCombineText* combinedText = styleToUse->hasTextCombine() ? toRenderCombineText(textRenderer()) : 0;
+    bool shouldRotate = !isHorizontal() && (!combinedText || !combinedText->isCombined());
+    if (shouldRotate) {
         context->save();
         context->translate(boxRect.x(), boxRect.bottom());
         context->rotate(static_cast<float>(deg2rad(90.)));
@@ -502,6 +505,9 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty)
     int d = styleToUse->textDecorationsInEffect();
     const Font& font = styleToUse->font();
 
+    if (combinedText)
+        combinedText->adjustTextOrigin(textOrigin, boxRect);
+
     // 1. Paint backgrounds behind text if needed. Examples of such backgrounds include selection
     // and composition underlines.
     if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseTextClip && !isPrinting) {
@@ -601,8 +607,13 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty)
         }
     }
 
-    const UChar* characters = textRenderer()->text()->characters() + m_start;
     int length = m_len;
+    const UChar* characters;
+    if (!combinedText)
+        characters = textRenderer()->text()->characters() + m_start;
+    else
+        combinedText->charactersToRender(m_start, characters, length);
+
     BufferForAppendingHyphen charactersWithHyphen;
     if (hasHyphen())
         adjustCharactersAndLengthForHyphen(charactersWithHyphen, styleToUse, characters, length);
@@ -703,7 +714,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, int tx, int ty)
         }
     }
     
-    if (!isHorizontal())
+    if (shouldRotate)
         context->restore();
 }
 
index e992355..3fe51d8 100644 (file)
@@ -36,6 +36,7 @@
 #include "HitTestResult.h"
 #include "InlineTextBox.h"
 #include "PaintInfo.h"
+#include "RenderCombineText.h"
 #include "RenderFlexibleBox.h"
 #include "RenderImage.h"
 #include "RenderInline.h"
@@ -4794,6 +4795,9 @@ void RenderBlock::computeInlinePreferredLogicalWidths()
                     continue;
                 }
 
+                if (t->style()->hasTextCombine())
+                    toRenderCombineText(t)->combineText();
+
                 // Determine if we have a breakable character.  Pass in
                 // whether or not we should ignore any spaces at the front
                 // of the string.  If those are going to be stripped out,
index e57257f..34a1a2c 100644 (file)
@@ -28,6 +28,7 @@
 #include "InlineTextBox.h"
 #include "Logging.h"
 #include "RenderArena.h"
+#include "RenderCombineText.h"
 #include "RenderInline.h"
 #include "RenderLayer.h"
 #include "RenderListMarker.h"
@@ -1383,7 +1384,7 @@ void RenderBlock::fitBelowFloats(int widthToFit, bool firstLine, int& availableW
 
 static inline unsigned textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, int xPos, bool isFixedPitch, bool collapseWhiteSpace)
 {
-    if (isFixedPitch || (!from && len == text->textLength()))
+    if (isFixedPitch || (!from && len == text->textLength()) || text->style()->hasTextCombine())
         return text->width(from, len, font, xPos);
     return font.width(TextRun(text->characters() + from, len, !collapseWhiteSpace, xPos));
 }
@@ -1635,11 +1636,14 @@ InlineIterator RenderBlock::findNextLineBreak(InlineBidiResolver& resolver, bool
             bool isSVGText = t->isSVGInlineText();
 #endif
 
+            RenderStyle* style = t->style(firstLine);
+            if (style->hasTextCombine())
+                toRenderCombineText(o)->combineText();
+
             int strlen = t->textLength();
             int len = strlen - pos;
             const UChar* str = t->characters();
 
-            RenderStyle* style = t->style(firstLine);
             const Font& f = style->font();
             bool isFixedPitch = f.isFixedPitch();
             bool canHyphenate = style->hyphens() == HyphensAuto && WebCore::canHyphenate(style->hyphenationLocale());
diff --git a/Source/WebCore/rendering/RenderCombineText.cpp b/Source/WebCore/rendering/RenderCombineText.cpp
new file mode 100644 (file)
index 0000000..5084e62
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "RenderCombineText.h"
+
+#include "TextRun.h"
+
+namespace WebCore {
+
+const float textCombineMargin = 1.1; // Allow em + 10% margin
+
+RenderCombineText::RenderCombineText(Node* node, PassRefPtr<StringImpl> string)
+     : RenderText(node, string)
+     , m_combinedTextWidth(0)
+     , m_isCombined(false)
+     , m_needsFontUpdate(false)
+{
+}
+
+void RenderCombineText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderText::styleDidChange(diff, oldStyle);
+
+    if (m_isCombined)
+        RenderText::setTextInternal(originalText()); // This RenderCombineText has been combined once. Restore the original text for the next combineText().
+
+    m_needsFontUpdate = true;
+}
+
+void RenderCombineText::setTextInternal(PassRefPtr<StringImpl> text)
+{
+    RenderText::setTextInternal(text);
+
+    m_needsFontUpdate = true;
+}
+
+unsigned RenderCombineText::width(unsigned from, unsigned length, const Font& font, int xPosition, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+{
+    if (!characters())
+        return 0;
+
+    if (m_isCombined)
+        return font.size();
+
+    return RenderText::width(from, length, font, xPosition, fallbackFonts, glyphOverflow);
+}
+
+void RenderCombineText::adjustTextOrigin(IntPoint& textOrigin, const IntRect& boxRect) const
+{
+    if (m_isCombined)
+        textOrigin.move(boxRect.height() / 2 - ceilf(m_combinedTextWidth) / 2, style()->font().pixelSize());
+}
+
+void RenderCombineText::charactersToRender(int start, const UChar*& characters, int& length) const
+{
+    if (m_isCombined) {
+        length = originalText()->length();
+        characters = originalText()->characters();
+        return;
+    }
+    characters = text()->characters() + start;
+}
+
+void RenderCombineText::combineText()
+{
+    if (!m_needsFontUpdate)
+        return;
+
+    m_isCombined = false;
+    m_needsFontUpdate = false;
+
+    // CSS3 spec says text-combine works only in vertical writing mode.
+    if (style()->isHorizontalWritingMode())
+        return;
+
+    TextRun run = TextRun(String(text()));
+    float emWidth = style()->font().fontDescription().computedSize() * textCombineMargin;
+    m_combinedTextWidth = style()->font().floatWidth(run);
+    m_isCombined = m_combinedTextWidth <= emWidth;
+
+    if (!m_isCombined) {
+        // Need to try compressed glyphs.
+        static const FontWidthVariant widthVariants[] = { HalfWidth, ThirdWidth, QuarterWidth };
+        FontDescription compressedFontDescription = style()->font().fontDescription();
+        for (size_t i = 0 ; i < WTF_ARRAY_LENGTH(widthVariants) ; ++i) {
+            compressedFontDescription.setWidthVariant(widthVariants[i]);
+            Font compressedFont = Font(compressedFontDescription, style()->font().letterSpacing(), style()->font().wordSpacing());
+            compressedFont.update(style()->font().fontSelector());
+            float runWidth = compressedFont.floatWidth(run);
+            if (runWidth <= emWidth) {
+                m_combinedTextWidth = runWidth;
+                m_isCombined = true;
+
+                // Replace my font with the new one.
+                if (style()->setFontDescription(compressedFontDescription))
+                    style()->font().update(style()->font().fontSelector());
+
+                break;
+            }
+        }
+    }
+
+    if (m_isCombined) {
+        static const UChar newCharacter = objectReplacementCharacter;
+        DEFINE_STATIC_LOCAL(String, objectReplacementCharacterString, (&newCharacter, 1));
+        RenderText::setTextInternal(objectReplacementCharacterString.impl());
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/rendering/RenderCombineText.h b/Source/WebCore/rendering/RenderCombineText.h
new file mode 100644 (file)
index 0000000..582cbd6
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef RenderCombineText_h
+#define RenderCombineText_h
+
+#include "RenderText.h"
+
+namespace WebCore {
+
+class RenderCombineText : public RenderText {
+public:
+    RenderCombineText(Node*, PassRefPtr<StringImpl>);
+
+    void combineText();
+    void adjustTextOrigin(IntPoint& textOrigin, const IntRect& boxRect) const;
+    void charactersToRender(int start, const UChar*& characters, int& length) const;
+    bool isCombined() const { return m_isCombined; }
+    int combinedTextWidth(const Font& font) const { return font.size(); }
+
+private:
+    virtual unsigned width(unsigned from, unsigned length, const Font&, int xPosition, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
+    virtual const char* renderName() const { return "RenderCombineText"; }
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+    virtual void setTextInternal(PassRefPtr<StringImpl>);
+
+    float m_combinedTextWidth;
+    bool m_isCombined : 1;
+    bool m_needsFontUpdate : 1;
+};
+
+inline RenderCombineText* toRenderCombineText(RenderObject* object)
+{ 
+    ASSERT(!object || object->isText());
+    return static_cast<RenderCombineText*>(object);
+}
+
+inline const RenderCombineText* toRenderCombineText(const RenderObject* object)
+{ 
+    ASSERT(!object || object->isText());
+    return static_cast<const RenderCombineText*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderCombineText(const RenderCombineText*);
+
+} // namespace WebCore
+
+#endif // RenderCombineText_h
index e85c719..98452a4 100644 (file)
@@ -34,6 +34,7 @@
 #include "Range.h"
 #include "RenderArena.h"
 #include "RenderBlock.h"
+#include "RenderCombineText.h"
 #include "RenderLayer.h"
 #include "RenderView.h"
 #include "Text.h"
@@ -561,6 +562,12 @@ IntRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, int* e
 
 ALWAYS_INLINE int RenderText::widthFromCache(const Font& f, int start, int len, int xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
 {
+    if (style()->hasTextCombine()) {
+        const RenderCombineText* combineText = toRenderCombineText(this);
+        if (combineText->isCombined())
+            return combineText->combinedTextWidth(f);
+    }
+
     if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII) {
         int monospaceCharacterWidth = f.spaceWidth();
         int tabWidth = allowTabs() ? monospaceCharacterWidth * 8 : 0;
index faa3566..760f02d 100644 (file)
@@ -45,6 +45,7 @@
 #include "RenderBox.cpp"
 #include "RenderBoxModelObject.cpp"
 #include "RenderButton.cpp"
+#include "RenderCombineText.cpp"
 #include "RenderCounter.cpp"
 #include "RenderDataGrid.cpp"
 #include "RenderDetails.cpp"
index 7a81b35..ae9bda2 100644 (file)
@@ -728,6 +728,7 @@ public:
     bool hasMask() const { return rareNonInheritedData->m_mask.hasImage() || rareNonInheritedData->m_maskBoxImage.hasImage(); }
 
     TextCombine textCombine() const { return static_cast<TextCombine>(rareNonInheritedData->m_textCombine); }
+    bool hasTextCombine() const { return textCombine() != TextCombineNone; }
     // End CSS3 Getters
 
     // Apple-specific property getter methods