Bug 28420 - Implement HTML5 <ruby> rendering
authorrolandsteiner@chromium.org <rolandsteiner@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Nov 2009 01:52:25 +0000 (01:52 +0000)
committerrolandsteiner@chromium.org <rolandsteiner@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 2 Nov 2009 01:52:25 +0000 (01:52 +0000)
(https://bugs.webkit.org/show_bug.cgi?id=28420)

Reviewed by Dave Hyatt.

First rudimentary implementation of HTML5 ruby rendering support.

WebCore:

Following the HTML 5 spec, the box object model for a <ruby> element allows several runs of ruby
bases with their respective ruby texts looks as follows:

1 RenderRuby object, corresponding to the whole <ruby> HTML element
     1+ RenderRubyRun (anonymous)
         0 or 1 RenderRubyText - shuffled to the front in order to re-use existing block layouting
             0-n inline object(s)
         0 or 1 RenderRubyBase - contains the inline objects that make up the ruby base
             1-n inline object(s)

Note: <rp> elements are defined as having 'display:none' and thus normally are not assigned a renderer.

New layout tests will be committed in a follow-up patch under fast/ruby.

Makefiles, etc.
* GNUmakefile.am:
* WebCore.gypi:
* WebCore.pro:
* WebCore.xcodeproj/project.pbxproj:

CSS
* css/html.css: Added <ruby> and <rt>

Existing render files:
* rendering/RenderBlock.cpp: make moveChild a member function moveChildTo
(WebCore::RenderBlock::moveChildTo):
(WebCore::RenderBlock::makeChildrenNonInline):
(WebCore::RenderBlock::removeChild):
* rendering/RenderBlock.h:
* rendering/RenderObject.cpp:
(WebCore::RenderObject::createObject): instantiate ruby renderers based on element name
* rendering/RenderObject.h: add query methods for ruby renderers
(WebCore::RenderObject::isRuby):
(WebCore::RenderObject::isRubyBase):
(WebCore::RenderObject::isRubyRun):
(WebCore::RenderObject::isRubyText):

New ruby renderers:
* rendering/RenderRuby.cpp: Added.
(WebCore::lastRubyRun):
(WebCore::findRubyRunParent):
(WebCore::RenderRubyAsInline::RenderRubyAsInline):
(WebCore::RenderRubyAsInline::~RenderRubyAsInline):
(WebCore::RenderRubyAsInline::isChildAllowed):
(WebCore::RenderRubyAsInline::addChild):
(WebCore::RenderRubyAsInline::removeChild):
(WebCore::RenderRubyAsBlock::RenderRubyAsBlock):
(WebCore::RenderRubyAsBlock::~RenderRubyAsBlock):
(WebCore::RenderRubyAsBlock::isChildAllowed):
(WebCore::RenderRubyAsBlock::addChild):
(WebCore::RenderRubyAsBlock::removeChild):
* rendering/RenderRuby.h: Added.
(WebCore::RenderRubyAsInline::renderName):
(WebCore::RenderRubyAsInline::isRuby):
(WebCore::RenderRubyAsBlock::renderName):
(WebCore::RenderRubyAsBlock::isRuby):
* rendering/RenderRubyBase.cpp: Added.
(WebCore::RenderRubyBase::RenderRubyBase):
(WebCore::RenderRubyBase::~RenderRubyBase):
(WebCore::RenderRubyBase::isChildAllowed):
(WebCore::RenderRubyBase::splitToLeft):
(WebCore::RenderRubyBase::mergeWithRight):
* rendering/RenderRubyBase.h: Added.
(WebCore::RenderRubyBase::renderName):
(WebCore::RenderRubyBase::isRubyBase):
* rendering/RenderRubyRun.cpp: Added.
(WebCore::RenderRubyRun::RenderRubyRun):
(WebCore::RenderRubyRun::~RenderRubyRun):
(WebCore::RenderRubyRun::hasRubyText):
(WebCore::RenderRubyRun::hasRubyBase):
(WebCore::RenderRubyRun::isEmpty):
(WebCore::RenderRubyRun::rubyText):
(WebCore::RenderRubyRun::rubyBase):
(WebCore::RenderRubyRun::rubyBaseSafe):
(WebCore::RenderRubyRun::firstLineBlock):
(WebCore::RenderRubyRun::updateFirstLetter):
(WebCore::RenderRubyRun::isChildAllowed):
(WebCore::RenderRubyRun::addChild):
(WebCore::RenderRubyRun::removeChild):
(WebCore::RenderRubyRun::createRubyBase):
(WebCore::RenderRubyRun::staticCreateRubyRun):
* rendering/RenderRubyRun.h: Added.
(WebCore::RenderRubyRun::renderName):
(WebCore::RenderRubyRun::isRubyRun):
* rendering/RenderRubyText.cpp: Added.
(WebCore::RenderRubyText::RenderRubyText):
(WebCore::RenderRubyText::~RenderRubyText):
(WebCore::RenderRubyText::isChildAllowed):
* rendering/RenderRubyText.h: Added.
(WebCore::RenderRubyText::renderName):
(WebCore::RenderRubyText::isRubyText):

LayoutTests:

Further layout tests will be committed in a follow-up patch under fast/ruby.

* fast/ruby/parse-rp-expected.txt: result changed due to <rt> being rendered as block within <ruby>

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

20 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/ruby/parse-rp-expected.txt
WebCore/ChangeLog
WebCore/GNUmakefile.am
WebCore/WebCore.gypi
WebCore/WebCore.pro
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/css/html.css
WebCore/rendering/RenderBlock.cpp
WebCore/rendering/RenderBlock.h
WebCore/rendering/RenderObject.cpp
WebCore/rendering/RenderObject.h
WebCore/rendering/RenderRuby.cpp [new file with mode: 0644]
WebCore/rendering/RenderRuby.h [new file with mode: 0644]
WebCore/rendering/RenderRubyBase.cpp [new file with mode: 0644]
WebCore/rendering/RenderRubyBase.h [new file with mode: 0644]
WebCore/rendering/RenderRubyRun.cpp [new file with mode: 0644]
WebCore/rendering/RenderRubyRun.h [new file with mode: 0644]
WebCore/rendering/RenderRubyText.cpp [new file with mode: 0644]
WebCore/rendering/RenderRubyText.h [new file with mode: 0644]

index 3a18d1c..f80dff8 100644 (file)
@@ -1,3 +1,16 @@
+2009-11-02  Roland Steiner  <rolandsteiner@chromium.org>
+
+        Reviewed by Dave Hyatt.
+
+        Bug 28420 -  Implement HTML5 <ruby> rendering
+        (https://bugs.webkit.org/show_bug.cgi?id=28420)
+
+        First rudimentary implementation of HTML5 ruby rendering support.
+
+        Further layout tests will be committed in a follow-up patch under fast/ruby.
+
+        * fast/ruby/parse-rp-expected.txt: result changed due to <rt> being rendered as block within <ruby>
+
 2009-11-01  Alexey Proskuryakov  <ap@apple.com>
 
         Reviewed by Dan Bernstein.
index be982de..5641a35 100644 (file)
@@ -2,4 +2,6 @@ The following is a test for parsing ruby <rp> and <rt> elements. According to HT
 
 TEST PASSED: Markup was correct
 
-Before base/left rp/text/right rp After
+Before base/
+text/
+ After
index 6626d75..d291da2 100644 (file)
@@ -1,3 +1,104 @@
+2009-11-02  Roland Steiner  <rolandsteiner@chromium.org>
+
+        Reviewed by Dave Hyatt.
+
+        Bug 28420 -  Implement HTML5 <ruby> rendering
+        (https://bugs.webkit.org/show_bug.cgi?id=28420)
+
+        First rudimentary implementation of HTML5 ruby rendering support.
+
+        Following the HTML 5 spec, the box object model for a <ruby> element allows several runs of ruby
+        bases with their respective ruby texts looks as follows:
+
+        1 RenderRuby object, corresponding to the whole <ruby> HTML element
+             1+ RenderRubyRun (anonymous)
+                 0 or 1 RenderRubyText - shuffled to the front in order to re-use existing block layouting
+                     0-n inline object(s)
+                 0 or 1 RenderRubyBase - contains the inline objects that make up the ruby base
+                     1-n inline object(s)
+
+        Note: <rp> elements are defined as having 'display:none' and thus normally are not assigned a renderer.
+        
+        New layout tests will be committed in a follow-up patch under fast/ruby.
+
+        Makefiles, etc.
+        * GNUmakefile.am:
+        * WebCore.gypi:
+        * WebCore.pro:
+        * WebCore.xcodeproj/project.pbxproj:
+
+        CSS
+        * css/html.css: Added <ruby> and <rt>
+
+        Existing render files:
+        * rendering/RenderBlock.cpp: make moveChild a member function moveChildTo
+        (WebCore::RenderBlock::moveChildTo):
+        (WebCore::RenderBlock::makeChildrenNonInline):
+        (WebCore::RenderBlock::removeChild):
+        * rendering/RenderBlock.h:
+        * rendering/RenderObject.cpp:
+        (WebCore::RenderObject::createObject): instantiate ruby renderers based on element name
+        * rendering/RenderObject.h: add query methods for ruby renderers
+        (WebCore::RenderObject::isRuby):
+        (WebCore::RenderObject::isRubyBase):
+        (WebCore::RenderObject::isRubyRun):
+        (WebCore::RenderObject::isRubyText):
+
+        New ruby renderers:
+        * rendering/RenderRuby.cpp: Added.
+        (WebCore::lastRubyRun):
+        (WebCore::findRubyRunParent):
+        (WebCore::RenderRubyAsInline::RenderRubyAsInline):
+        (WebCore::RenderRubyAsInline::~RenderRubyAsInline):
+        (WebCore::RenderRubyAsInline::isChildAllowed):
+        (WebCore::RenderRubyAsInline::addChild):
+        (WebCore::RenderRubyAsInline::removeChild):
+        (WebCore::RenderRubyAsBlock::RenderRubyAsBlock):
+        (WebCore::RenderRubyAsBlock::~RenderRubyAsBlock):
+        (WebCore::RenderRubyAsBlock::isChildAllowed):
+        (WebCore::RenderRubyAsBlock::addChild):
+        (WebCore::RenderRubyAsBlock::removeChild):
+        * rendering/RenderRuby.h: Added.
+        (WebCore::RenderRubyAsInline::renderName):
+        (WebCore::RenderRubyAsInline::isRuby):
+        (WebCore::RenderRubyAsBlock::renderName):
+        (WebCore::RenderRubyAsBlock::isRuby):
+        * rendering/RenderRubyBase.cpp: Added.
+        (WebCore::RenderRubyBase::RenderRubyBase):
+        (WebCore::RenderRubyBase::~RenderRubyBase):
+        (WebCore::RenderRubyBase::isChildAllowed):
+        (WebCore::RenderRubyBase::splitToLeft):
+        (WebCore::RenderRubyBase::mergeWithRight):
+        * rendering/RenderRubyBase.h: Added.
+        (WebCore::RenderRubyBase::renderName):
+        (WebCore::RenderRubyBase::isRubyBase):
+        * rendering/RenderRubyRun.cpp: Added.
+        (WebCore::RenderRubyRun::RenderRubyRun):
+        (WebCore::RenderRubyRun::~RenderRubyRun):
+        (WebCore::RenderRubyRun::hasRubyText):
+        (WebCore::RenderRubyRun::hasRubyBase):
+        (WebCore::RenderRubyRun::isEmpty):
+        (WebCore::RenderRubyRun::rubyText):
+        (WebCore::RenderRubyRun::rubyBase):
+        (WebCore::RenderRubyRun::rubyBaseSafe):
+        (WebCore::RenderRubyRun::firstLineBlock):
+        (WebCore::RenderRubyRun::updateFirstLetter):
+        (WebCore::RenderRubyRun::isChildAllowed):
+        (WebCore::RenderRubyRun::addChild):
+        (WebCore::RenderRubyRun::removeChild):
+        (WebCore::RenderRubyRun::createRubyBase):
+        (WebCore::RenderRubyRun::staticCreateRubyRun):
+        * rendering/RenderRubyRun.h: Added.
+        (WebCore::RenderRubyRun::renderName):
+        (WebCore::RenderRubyRun::isRubyRun):
+        * rendering/RenderRubyText.cpp: Added.
+        (WebCore::RenderRubyText::RenderRubyText):
+        (WebCore::RenderRubyText::~RenderRubyText):
+        (WebCore::RenderRubyText::isChildAllowed):
+        * rendering/RenderRubyText.h: Added.
+        (WebCore::RenderRubyText::renderName):
+        (WebCore::RenderRubyText::isRubyText):
+
 2009-11-01  Alexey Proskuryakov  <ap@apple.com>
 
         Reviewed by Dan Bernstein.
index 87b105f..aabbc0f 100644 (file)
@@ -1775,6 +1775,14 @@ webcore_sources += \
        WebCore/rendering/RenderReplaced.h \
        WebCore/rendering/RenderReplica.cpp \
        WebCore/rendering/RenderReplica.h \
+       WebCore/rendering/RenderRuby.cpp \
+       WebCore/rendering/RenderRuby.h \
+       WebCore/rendering/RenderRubyBase.cpp \
+       WebCore/rendering/RenderRubyBase.h \
+       WebCore/rendering/RenderRubyRun.cpp \
+       WebCore/rendering/RenderRubyRun.h \
+       WebCore/rendering/RenderRubyText.cpp \
+       WebCore/rendering/RenderRubyText.h \
        WebCore/rendering/RenderScrollbar.cpp \
        WebCore/rendering/RenderScrollbar.h \
        WebCore/rendering/RenderScrollbarPart.cpp \
index 97ca80a..ff578ef 100644 (file)
             'rendering/RenderReplaced.h',
             'rendering/RenderReplica.cpp',
             'rendering/RenderReplica.h',
+            'rendering/RenderRuby.cpp',
+            'rendering/RenderRuby.h',
+            'rendering/RenderRubyBase.cpp',
+            'rendering/RenderRubyBase.h',
+            'rendering/RenderRubyRun.cpp',
+            'rendering/RenderRubyRun.h',
+            'rendering/RenderRubyText.cpp',
+            'rendering/RenderRubyText.h',
             'rendering/RenderSVGBlock.cpp',
             'rendering/RenderSVGBlock.h',
             'rendering/RenderSVGContainer.cpp',
index c1d0f9a..c8833e9 100644 (file)
@@ -1308,6 +1308,10 @@ SOURCES += \
     rendering/RenderPartObject.cpp \
     rendering/RenderReplaced.cpp \
     rendering/RenderReplica.cpp \
+    rendering/RenderRuby.cpp \
+    rendering/RenderRubyBase.cpp \
+    rendering/RenderRubyRun.cpp \
+    rendering/RenderRubyText.cpp \
     rendering/RenderScrollbar.cpp \
     rendering/RenderScrollbarPart.cpp \
     rendering/RenderScrollbarTheme.cpp \
@@ -2022,6 +2026,10 @@ HEADERS += \
     rendering/RenderPath.h \
     rendering/RenderReplaced.h \
     rendering/RenderReplica.h \
+    rendering/RenderRuby.h \
+    rendering/RenderRubyBase.h \
+    rendering/RenderRubyRun.h \
+    rendering/RenderRubyText.h \
     rendering/RenderScrollbar.h \
     rendering/RenderScrollbarPart.h \
     rendering/RenderScrollbarTheme.h \
index 4ea17c3..67bd8d9 100644 (file)
                1449E287107D4DB400B5793F /* JSCallbackData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1449E286107D4DB400B5793F /* JSCallbackData.cpp */; };
                1477E7760BF4134A00152872 /* PageCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1477E7740BF4134A00152872 /* PageCache.cpp */; };
                1477E7770BF4134A00152872 /* PageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 1477E7750BF4134A00152872 /* PageCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               1479FAED109AE37500DED655 /* RenderRuby.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1479FAE5109AE37500DED655 /* RenderRuby.cpp */; };
+               1479FAEE109AE37500DED655 /* RenderRuby.h in Headers */ = {isa = PBXBuildFile; fileRef = 1479FAE6109AE37500DED655 /* RenderRuby.h */; };
+               1479FAEF109AE37500DED655 /* RenderRubyBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1479FAE7109AE37500DED655 /* RenderRubyBase.cpp */; };
+               1479FAF0109AE37500DED655 /* RenderRubyBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 1479FAE8109AE37500DED655 /* RenderRubyBase.h */; };
+               1479FAF1109AE37500DED655 /* RenderRubyRun.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1479FAE9109AE37500DED655 /* RenderRubyRun.cpp */; };
+               1479FAF2109AE37500DED655 /* RenderRubyRun.h in Headers */ = {isa = PBXBuildFile; fileRef = 1479FAEA109AE37500DED655 /* RenderRubyRun.h */; };
+               1479FAF3109AE37500DED655 /* RenderRubyText.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1479FAEB109AE37500DED655 /* RenderRubyText.cpp */; };
+               1479FAF4109AE37500DED655 /* RenderRubyText.h in Headers */ = {isa = PBXBuildFile; fileRef = 1479FAEC109AE37500DED655 /* RenderRubyText.h */; };
                148AFDA50AF58360008CC700 /* ExceptionHandlers.h in Headers */ = {isa = PBXBuildFile; fileRef = 148AFDA30AF58360008CC700 /* ExceptionHandlers.h */; settings = {ATTRIBUTES = (Private, ); }; };
                148AFDA60AF58360008CC700 /* ExceptionHandlers.mm in Sources */ = {isa = PBXBuildFile; fileRef = 148AFDA40AF58360008CC700 /* ExceptionHandlers.mm */; };
                14993BE50B2F2B1C0050497F /* FocusController.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14993BE30B2F2B1C0050497F /* FocusController.cpp */; };
                1449E286107D4DB400B5793F /* JSCallbackData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCallbackData.cpp; sourceTree = "<group>"; };
                1477E7740BF4134A00152872 /* PageCache.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PageCache.cpp; sourceTree = "<group>"; };
                1477E7750BF4134A00152872 /* PageCache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PageCache.h; sourceTree = "<group>"; };
+               1479FAE5109AE37500DED655 /* RenderRuby.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderRuby.cpp; sourceTree = "<group>"; };
+               1479FAE6109AE37500DED655 /* RenderRuby.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderRuby.h; sourceTree = "<group>"; };
+               1479FAE7109AE37500DED655 /* RenderRubyBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderRubyBase.cpp; sourceTree = "<group>"; };
+               1479FAE8109AE37500DED655 /* RenderRubyBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderRubyBase.h; sourceTree = "<group>"; };
+               1479FAE9109AE37500DED655 /* RenderRubyRun.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderRubyRun.cpp; sourceTree = "<group>"; };
+               1479FAEA109AE37500DED655 /* RenderRubyRun.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderRubyRun.h; sourceTree = "<group>"; };
+               1479FAEB109AE37500DED655 /* RenderRubyText.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderRubyText.cpp; sourceTree = "<group>"; };
+               1479FAEC109AE37500DED655 /* RenderRubyText.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderRubyText.h; sourceTree = "<group>"; };
                14813BF309EDF88E00F757E1 /* IDLParser.pm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text.script.perl; name = IDLParser.pm; path = scripts/IDLParser.pm; sourceTree = "<group>"; };
                148AFDA30AF58360008CC700 /* ExceptionHandlers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ExceptionHandlers.h; sourceTree = "<group>"; };
                148AFDA40AF58360008CC700 /* ExceptionHandlers.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = ExceptionHandlers.mm; sourceTree = "<group>"; };
                                A871DFDF0A15376B00B12A68 /* RenderReplaced.h */,
                                BCA846D40DC67A350026C309 /* RenderReplica.cpp */,
                                BCA846D50DC67A350026C309 /* RenderReplica.h */,
+                               1479FAE5109AE37500DED655 /* RenderRuby.cpp */,
+                               1479FAE6109AE37500DED655 /* RenderRuby.h */,
+                               1479FAE7109AE37500DED655 /* RenderRubyBase.cpp */,
+                               1479FAE8109AE37500DED655 /* RenderRubyBase.h */,
+                               1479FAE9109AE37500DED655 /* RenderRubyRun.cpp */,
+                               1479FAEA109AE37500DED655 /* RenderRubyRun.h */,
+                               1479FAEB109AE37500DED655 /* RenderRubyText.cpp */,
+                               1479FAEC109AE37500DED655 /* RenderRubyText.h */,
                                BC3BE9900E9C1C7C00835588 /* RenderScrollbar.cpp */,
                                BC3BE9910E9C1C7C00835588 /* RenderScrollbar.h */,
                                BC3BE9AA0E9C242000835588 /* RenderScrollbarPart.cpp */,
                                BC97E23A109144950010D361 /* HTMLAllCollection.h in Headers */,
                                BC97E413109154FA0010D361 /* JSHTMLAllCollection.h in Headers */,
                                37C236111097EE7700EF9F72 /* ComplexTextController.h in Headers */,
+                               1479FAEE109AE37500DED655 /* RenderRuby.h in Headers */,
+                               1479FAF0109AE37500DED655 /* RenderRubyBase.h in Headers */,
+                               1479FAF2109AE37500DED655 /* RenderRubyRun.h in Headers */,
+                               1479FAF4109AE37500DED655 /* RenderRubyText.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                BC97E23B109144950010D361 /* HTMLAllCollection.cpp in Sources */,
                                BC97E412109154FA0010D361 /* JSHTMLAllCollection.cpp in Sources */,
                                BC97E42C10915B060010D361 /* JSHTMLAllCollectionCustom.cpp in Sources */,
+                               1479FAED109AE37500DED655 /* RenderRuby.cpp in Sources */,
+                               1479FAEF109AE37500DED655 /* RenderRubyBase.cpp in Sources */,
+                               1479FAF1109AE37500DED655 /* RenderRubyRun.cpp in Sources */,
+                               1479FAF3109AE37500DED655 /* RenderRubyText.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 095fab3..c89a000 100644 (file)
@@ -607,6 +607,18 @@ a:-webkit-any-link:active {
     color: -webkit-activelink
 }
 
+/* HTML5 ruby elements */
+
+ruby > rt {
+    display: block;
+    font-size: 60%;         /* make slightly larger than 50% for better readability */
+    text-align: center;
+}
+
+ruby > rp {
+    display: none;
+}
+
 /* other elements */
 
 noframes {
index 237478d..c9bd922 100644 (file)
@@ -58,12 +58,6 @@ static const int verticalLineClickFudgeFactor = 3;
 
 using namespace HTMLNames;
 
-static void moveChild(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* from, RenderObjectChildList* fromChildList, RenderObject* child)
-{
-    ASSERT(from == child->parent());
-    toChildList->appendChildNode(to, fromChildList->removeChildNode(from, child, false), false);
-}
-
 struct ColumnInfo {
     ColumnInfo()
         : m_desiredColumnWidth(0)
@@ -399,6 +393,19 @@ RootInlineBox* RenderBlock::createAndAppendRootInlineBox()
     m_lineBoxes.appendLineBox(rootBox);
     return rootBox;
 }
+    
+void RenderBlock::moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* child)
+{
+    ASSERT(this == child->parent());
+    toChildList->appendChildNode(to, children()->removeChildNode(this, child, false), false);
+}
+
+void RenderBlock::moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* beforeChild, RenderObject* child)
+{
+    ASSERT(this == child->parent());
+    ASSERT(!beforeChild || to == beforeChild->parent());
+    toChildList->insertChildNode(to, children()->removeChildNode(this, child, false), beforeChild, false);
+}
 
 void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
 {    
@@ -436,9 +443,9 @@ void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
             RenderObject* no = o;
             o = no->nextSibling();
             
-            moveChild(block, block->children(), this, children(), no);
+            moveChildTo(block, block->children(), no);
         }
-        moveChild(block, block->children(), this, children(), inlineRunEnd);
+        moveChildTo(block, block->children(), inlineRunEnd);
     }
 
 #ifndef NDEBUG
@@ -513,7 +520,7 @@ void RenderBlock::removeChild(RenderObject* oldChild)
         while (o) {
             RenderObject* no = o;
             o = no->nextSibling();
-            moveChild(prevBlock, prevBlock->children(), nextBlock, nextBlock->children(), no);
+            nextBlock->moveChildTo(prevBlock, prevBlock->children(), no);
         }
  
         nextBlock->deleteLineBoxTree();
@@ -536,7 +543,7 @@ void RenderBlock::removeChild(RenderObject* oldChild)
         while (o) {
             RenderObject* no = o;
             o = no->nextSibling();
-            moveChild(this, children(), anonBlock, anonBlock->children(), no);
+            anonBlock->moveChildTo(this, children(), no);
         }
 
         // Delete the now-empty block's lines and nuke it.
index 7ba5fce..050ab38 100644 (file)
@@ -140,6 +140,9 @@ public:
     RenderBlock* createAnonymousBlock(bool isFlexibleBox = false) const;
 
 protected:
+    void moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* child);
+    void moveChildTo(RenderObject* to, RenderObjectChildList* toChildList, RenderObject* beforeChild, RenderObject* child);
+
     int maxTopPosMargin() const { return m_maxMargin ? m_maxMargin->m_topPos : MaxMargin::topPosDefault(this); }
     int maxTopNegMargin() const { return m_maxMargin ? m_maxMargin->m_topNeg : MaxMargin::topNegDefault(this); }
     int maxBottomPosMargin() const { return m_maxMargin ? m_maxMargin->m_bottomPos : MaxMargin::bottomPosDefault(this); }
index a10ffd9..e451c30 100644 (file)
@@ -4,6 +4,7 @@
  *           (C) 2000 Dirk Mueller (mueller@kde.org)
  *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
  * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
  *
  * This library is free software; you can redistribute it and/or
@@ -41,6 +42,8 @@
 #include "RenderImageGeneratedContent.h"
 #include "RenderInline.h"
 #include "RenderListItem.h"
+#include "RenderRuby.h"
+#include "RenderRubyText.h"
 #include "RenderTableCell.h"
 #include "RenderTableCol.h"
 #include "RenderTableRow.h"
@@ -103,46 +106,42 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
         return image;
     }
 
-    RenderObject* o = 0;
+    if (node->hasTagName(rubyTag)) {
+        if (style->display() == INLINE)
+            return new (arena) RenderRubyAsInline(node);
+        else
+            return new (arena) RenderRubyAsBlock(node);
+    }
+    // treat <rt> as ruby text ONLY if it still has its default treatment of block
+    if (node->hasTagName(rtTag) && style->display() == BLOCK)
+        return new (arena) RenderRubyText(node); 
 
     switch (style->display()) {
         case NONE:
-            break;
+            return 0;
         case INLINE:
-            o = new (arena) RenderInline(node);
-            break;
+            return new (arena) RenderInline(node);
         case BLOCK:
-            o = new (arena) RenderBlock(node);
-            break;
         case INLINE_BLOCK:
-            o = new (arena) RenderBlock(node);
-            break;
-        case LIST_ITEM:
-            o = new (arena) RenderListItem(node);
-            break;
         case RUN_IN:
         case COMPACT:
-            o = new (arena) RenderBlock(node);
-            break;
+            return new (arena) RenderBlock(node);
+        case LIST_ITEM:
+            return new (arena) RenderListItem(node);
         case TABLE:
         case INLINE_TABLE:
-            o = new (arena) RenderTable(node);
-            break;
+            return new (arena) RenderTable(node);
         case TABLE_ROW_GROUP:
         case TABLE_HEADER_GROUP:
         case TABLE_FOOTER_GROUP:
-            o = new (arena) RenderTableSection(node);
-            break;
+            return new (arena) RenderTableSection(node);
         case TABLE_ROW:
-            o = new (arena) RenderTableRow(node);
-            break;
+            return new (arena) RenderTableRow(node);
         case TABLE_COLUMN_GROUP:
         case TABLE_COLUMN:
-            o = new (arena) RenderTableCol(node);
-            break;
+            return new (arena) RenderTableCol(node);
         case TABLE_CELL:
-            o = new (arena) RenderTableCell(node);
-            break;
+            return new (arena) RenderTableCell(node);
         case TABLE_CAPTION:
 #if ENABLE(WCSS)
         // As per the section 17.1 of the spec WAP-239-WCSS-20011026-a.pdf, 
@@ -150,15 +149,13 @@ RenderObject* RenderObject::createObject(Node* node, RenderStyle* style)
         // principal block box ([CSS2] section 9.2.1).
         case WAP_MARQUEE:
 #endif
-            o = new (arena) RenderBlock(node);
-            break;
+            return new (arena) RenderBlock(node);
         case BOX:
         case INLINE_BOX:
-            o = new (arena) RenderFlexibleBox(node);
-            break;
+            return new (arena) RenderFlexibleBox(node);
     }
 
-    return o;
+    return 0;
 }
 
 #ifndef NDEBUG 
index e358c98..acfdd49 100644 (file)
@@ -4,6 +4,7 @@
  *           (C) 2000 Dirk Mueller (mueller@kde.org)
  *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google 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
@@ -267,6 +268,10 @@ public:
     virtual bool isRenderInline() const { return false; }
     virtual bool isRenderPart() const { return false; }
     virtual bool isRenderView() const { return false; }
+    virtual bool isRuby() const { return false; }
+    virtual bool isRubyBase() const { return false; }
+    virtual bool isRubyRun() const { return false; }
+    virtual bool isRubyText() const { return false; }
     virtual bool isSlider() const { return false; }
     virtual bool isTable() const { return false; }
     virtual bool isTableCell() const { return false; }
diff --git a/WebCore/rendering/RenderRuby.cpp b/WebCore/rendering/RenderRuby.cpp
new file mode 100644 (file)
index 0000000..8d113f9
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderRuby.h"
+
+#include "RenderRubyRun.h"
+
+namespace WebCore {
+
+//=== generic helper functions to avoid excessive code duplication ===
+
+static RenderRubyRun* lastRubyRun(const RenderObject* ruby)
+{
+    RenderObject* child = ruby->lastChild();
+    if (child && ruby->isAfterContent(child))
+        child = child->previousSibling();
+    ASSERT(!child || child->isRubyRun());
+    return static_cast<RenderRubyRun*>(child);
+}
+
+static inline RenderRubyRun* findRubyRunParent(RenderObject* child)
+{
+    while (child && !child->isRubyRun())
+        child = child->parent();
+    return static_cast<RenderRubyRun*>(child);
+}
+
+//=== ruby as inline object ===
+
+RenderRubyAsInline::RenderRubyAsInline(Node* node)
+    : RenderInline(node)
+{
+}
+
+RenderRubyAsInline::~RenderRubyAsInline()
+{
+}
+
+bool RenderRubyAsInline::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+    return child->isRubyText()
+        || child->isRubyRun()
+        || child->isInline();
+}
+
+void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    // Note: ':after' content is handled implicitely below
+
+    // if child is a ruby run, just add it normally
+    if (child->isRubyRun()) {
+        RenderInline::addChild(child, beforeChild);
+        return;
+    }
+
+    if (beforeChild && !isAfterContent(beforeChild)) {
+        // insert child into run
+        ASSERT(!beforeChild->isRubyRun());
+        RenderRubyRun* run = findRubyRunParent(beforeChild);
+        ASSERT(run); // beforeChild should always have a run as parent
+        if (run) {
+            run->addChild(child, beforeChild);
+            return;
+        }
+        ASSERT(false); // beforeChild should always have a run as parent!
+        // Emergency fallback: fall through and just append.
+    }
+
+    // If the new child would be appended, try to add the child to the previous run
+    // if possible, or create a new run otherwise.
+    // (The RenderRubyRun object will handle the details)
+    RenderRubyRun* lastRun = lastRubyRun(this);
+    if (!lastRun || lastRun->hasRubyText()) {
+        lastRun = RenderRubyRun::staticCreateRubyRun(this);
+        RenderInline::addChild(lastRun);
+    }
+    lastRun->addChild(child);
+}
+
+void RenderRubyAsInline::removeChild(RenderObject* child)
+{
+    // If the child's parent is *this, i.e. a ruby run or ':after' content,
+    // just use the normal remove method.
+    if (child->parent() == this) {
+        ASSERT(child->isRubyRun() || child->isAfterContent());
+        RenderInline::removeChild(child);
+        return;
+    }
+
+    // Find the containing run
+    RenderRubyRun* run = findRubyRunParent(child);
+    ASSERT(run);
+    run->removeChild(child);
+}
+
+
+//=== ruby as block object ===
+
+RenderRubyAsBlock::RenderRubyAsBlock(Node* node)
+    : RenderBlock(node)
+{
+}
+
+RenderRubyAsBlock::~RenderRubyAsBlock()
+{
+}
+
+bool RenderRubyAsBlock::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+    return child->isRubyText()
+        || child->isRubyRun()
+        || child->isInline();
+}
+
+void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    // Note: ':after' content is handled implicitely below
+
+    // if child is a ruby run, just add it normally
+    if (child->isRubyRun()) {
+        RenderBlock::addChild(child, beforeChild);
+        return;
+    }
+
+    if (beforeChild && !isAfterContent(beforeChild)) {
+        // insert child into run
+        ASSERT(!beforeChild->isRubyRun());
+        RenderObject* run = beforeChild;
+        while (run && !run->isRubyRun())
+            run = run->parent();
+        if (run) {
+            run->addChild(child, beforeChild);
+            return;
+        }
+        ASSERT(false); // beforeChild should always have a run as parent!
+        // Emergency fallback: fall through and just append.
+    }
+
+    // If the new child would be appended, try to add the child to the previous run
+    // if possible, or create a new run otherwise.
+    // (The RenderRubyRun object will handle the details)
+    RenderRubyRun* lastRun = lastRubyRun(this);
+    if (!lastRun || lastRun->hasRubyText()) {
+        lastRun = RenderRubyRun::staticCreateRubyRun(this);
+        RenderBlock::addChild(lastRun);
+    }
+    lastRun->addChild(child);
+}
+
+void RenderRubyAsBlock::removeChild(RenderObject* child)
+{
+    // If the child's parent is *this, just use the normal remove method.
+    if (child->parent() == this) {
+        // This should happen only during destruction of the whole ruby element, though.
+        RenderBlock::removeChild(child);
+        return;
+    }
+
+    // Find the containing run
+    RenderRubyRun* run = findRubyRunParent(child);
+    ASSERT(run);
+    run->removeChild(child);
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/rendering/RenderRuby.h b/WebCore/rendering/RenderRuby.h
new file mode 100644 (file)
index 0000000..a74150c
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER 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 RenderRuby_h
+#define RenderRuby_h
+
+#include "RenderBlock.h"
+#include "RenderInline.h"
+
+namespace WebCore {
+
+// Following the HTML 5 spec, the box object model for a <ruby> element allows several runs of ruby
+// bases with their respective ruby texts looks as follows:
+//
+// 1 RenderRuby object, corresponding to the whole <ruby> HTML element
+//      1+ RenderRubyRun (anonymous)
+//          0 or 1 RenderRubyText - shuffled to the front in order to re-use existing block layouting
+//              0-n inline object(s)
+//          0 or 1 RenderRubyBase - contains the inline objects that make up the ruby base
+//              1-n inline object(s)
+//
+// Note: <rp> elements are defined as having 'display:none' and thus normally are not assigned a renderer.
+
+// <ruby> when used as 'display:inline'
+class RenderRubyAsInline : public RenderInline {
+public:
+    RenderRubyAsInline(Node*);
+    virtual ~RenderRubyAsInline();
+
+    virtual const char* renderName() const { return "RenderRuby (inline)"; }
+
+    virtual bool isRuby() const { return true; }
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject* child);
+};
+
+// <ruby> when used as 'display:block' or 'display:inline-block'
+class RenderRubyAsBlock : public RenderBlock {
+public:
+    RenderRubyAsBlock(Node*);
+    virtual ~RenderRubyAsBlock();
+
+    virtual const char* renderName() const { return "RenderRuby (block)"; }
+
+    virtual bool isRuby() const { return true; }
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject* child);
+};
+
+} // namespace WebCore
+
+#endif // RenderRuby_h
diff --git a/WebCore/rendering/RenderRubyBase.cpp b/WebCore/rendering/RenderRubyBase.cpp
new file mode 100644 (file)
index 0000000..5cb25f4
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderRubyBase.h"
+
+namespace WebCore {
+
+RenderRubyBase::RenderRubyBase(Node* node)
+    : RenderBlock(node)
+{
+    setInline(false);
+}
+
+RenderRubyBase::~RenderRubyBase()
+{
+}
+
+bool RenderRubyBase::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+    return child->isInline();
+}
+
+void RenderRubyBase::splitToLeft(RenderBlock* leftBase, RenderObject* beforeChild)
+{
+    // This function removes all children that are before (!) beforeChild
+    // and appends them to leftBase.
+    ASSERT(leftBase);
+
+    // First make sure that beforeChild (if set) is indeed a direct child of this.
+    // Fallback: climb up the tree to make sure. This may result in somewhat incorrect rendering.
+    // FIXME: Can this happen? Is there a better/more correct way to solve this?
+    ASSERT(!beforeChild || beforeChild->parent() == this);
+    while (beforeChild && beforeChild->parent() != this)
+        beforeChild = beforeChild->parent();
+
+    RenderObject* child = firstChild();
+    while (child != beforeChild) {
+        RenderObject* nextChild = child->nextSibling();
+        moveChildTo(leftBase, leftBase->children(), child);
+        child = nextChild;
+    }
+}
+
+void RenderRubyBase::mergeWithRight(RenderBlock* rightBase)
+{
+    // This function removes all children and prepends (!) them to rightBase.
+    ASSERT(rightBase);
+
+    RenderObject* firstPos = rightBase->firstChild();
+    RenderObject* child = lastChild();
+    while (child) {
+        moveChildTo(rightBase, rightBase->children(), firstPos, child);
+        firstPos = child;
+        child = lastChild();
+    }
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderRubyBase.h b/WebCore/rendering/RenderRubyBase.h
new file mode 100644 (file)
index 0000000..57baf99
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER 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 RenderRubyBase_h
+#define RenderRubyBase_h
+
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+class RenderRubyBase : public RenderBlock {
+public:
+    RenderRubyBase(Node*);
+    virtual ~RenderRubyBase();
+
+    virtual const char* renderName() const { return "RenderRubyBase (anonymous)"; }
+
+    virtual bool isRubyBase() const { return true; }
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+
+    void splitToLeft(RenderBlock* leftBase, RenderObject* beforeChild);
+    void mergeWithRight(RenderBlock* rightBase);
+};
+
+} // namespace WebCore
+
+#endif // RenderRubyBase_h
diff --git a/WebCore/rendering/RenderRubyRun.cpp b/WebCore/rendering/RenderRubyRun.cpp
new file mode 100644 (file)
index 0000000..561178b
--- /dev/null
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderRubyRun.h"
+
+#include "RenderRubyBase.h"
+#include "RenderRubyText.h"
+#include "RenderView.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderRubyRun::RenderRubyRun(Node* node)
+    : RenderBlock(node)
+{
+    setReplaced(true);
+    setInline(true);
+}
+
+RenderRubyRun::~RenderRubyRun()
+{
+}
+
+bool RenderRubyRun::hasRubyText() const
+{
+    // The only place where a ruby text can be is in the first position
+    // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' content themselves.
+    return firstChild() && firstChild()->isRubyText();
+}
+
+bool RenderRubyRun::hasRubyBase() const
+{
+    // The only place where a ruby base can be is in the last position
+    // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' content themselves.
+    return lastChild() && lastChild()->isRubyBase();
+}
+
+bool RenderRubyRun::isEmpty() const
+{
+    return !hasRubyText() && !hasRubyBase();
+}
+
+RenderRubyText* RenderRubyRun::rubyText() const
+{
+    RenderObject* child = firstChild();
+    return child && child->isRubyText() ? static_cast<RenderRubyText*>(child) : 0;
+}
+
+RenderRubyBase* RenderRubyRun::rubyBase() const
+{
+    RenderObject* child = lastChild();
+    return child && child->isRubyBase() ? static_cast<RenderRubyBase*>(child) : 0;
+}
+
+RenderRubyBase* RenderRubyRun::rubyBaseSafe()
+{
+    RenderRubyBase* base = rubyBase();
+    if (!base) {
+        base = createRubyBase();
+        RenderBlock::addChild(base);
+    }
+    return base;
+}
+
+RenderBlock* RenderRubyRun::firstLineBlock() const
+{
+    return 0;
+}
+
+void RenderRubyRun::updateFirstLetter()
+{
+}
+
+bool RenderRubyRun::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+    return child->isRubyText() || child->isInline();
+}
+
+void RenderRubyRun::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    ASSERT(child);
+
+    // If child is a ruby text
+    if (child->isRubyText()) {
+        if (!beforeChild) {
+            // RenderRuby has already ascertained that we can add the child here.
+            ASSERT(!hasRubyText());
+            // prepend ruby texts as first child
+            RenderBlock::addChild(child, firstChild());
+        }  else if (beforeChild->isRubyText()) {
+            // New text is inserted just before another.
+            // In this case the new text takes the place of the old one, and
+            // the old text goes into a new run that is inserted as next sibling.
+            ASSERT(beforeChild->parent() == this);
+            RenderObject* ruby = parent();
+            ASSERT(ruby->isRuby());
+            RenderBlock* newRun = staticCreateRubyRun(ruby);
+            ruby->addChild(newRun, nextSibling());
+            // Add the new ruby text and move the old one to the new run
+            // Note: Doing it in this order and not using RenderRubyRun's methods,
+            // in order to avoid automatic removal of the ruby run in case there is no
+            // other child besides the old ruby text.
+            RenderBlock::addChild(child, beforeChild);
+            RenderBlock::removeChild(beforeChild);
+            newRun->addChild(beforeChild);
+        } else {
+            ASSERT(hasRubyBase()); // Otherwise beforeChild would be borked.
+            // Insertion before a ruby base object.
+            // In this case we need insert a new run before the current one and split the base.
+            RenderObject* ruby = parent();
+            RenderRubyRun* newRun = staticCreateRubyRun(ruby);
+            ruby->addChild(newRun, this);
+            newRun->addChild(child);
+            rubyBaseSafe()->splitToLeft(newRun->rubyBaseSafe(), beforeChild);
+        }
+    } else {
+        // child is not a text -> insert it into the base
+        // (append it instead if beforeChild is the ruby text)
+        if (beforeChild && beforeChild->isRubyText())
+            beforeChild = 0;
+        rubyBaseSafe()->addChild(child, beforeChild);
+    }
+}
+
+void RenderRubyRun::removeChild(RenderObject* child)
+{
+    // If the child is a ruby text, then merge the ruby base with the base of
+    // the right sibling run, if possible.
+    if (!documentBeingDestroyed() && child->isRubyText()) {
+        RenderRubyBase* base = rubyBase();
+        RenderObject* rightNeighbour = nextSibling();
+        if (base && rightNeighbour && rightNeighbour->isRubyRun()) {
+            // Ruby run without a base can happen only at the first run.
+            RenderRubyRun* rightRun = static_cast<RenderRubyRun*>(rightNeighbour);
+            ASSERT(rightRun->hasRubyBase());
+            base->mergeWithRight(rightRun->rubyBaseSafe());
+            // The now empty ruby base will be removed below.
+        }
+    }
+
+    RenderBlock::removeChild(child);
+
+    if (!documentBeingDestroyed()) {
+        // Check if our base (if any) is now empty. If so, destroy it.
+        RenderBlock* base = rubyBase();
+        if (base && !base->firstChild()) {
+            RenderBlock::removeChild(base);
+            base->deleteLineBoxTree();
+            base->destroy();
+        }
+
+        // If any of the above leaves the run empty, destroy it as well
+        if (isEmpty()) {
+            parent()->removeChild(this);
+            deleteLineBoxTree();
+            destroy();
+        }
+    }
+}
+
+RenderRubyBase* RenderRubyRun::createRubyBase() const
+{
+    RenderRubyBase* rb = new (renderArena()) RenderRubyBase(document() /* anonymous */);
+    RefPtr<RenderStyle> newStyle = RenderStyle::create();
+    newStyle->inheritFrom(style());
+    newStyle->setDisplay(BLOCK);
+    newStyle->setTextAlign(CENTER); // FIXME: use WEBKIT_CENTER?
+    rb->setStyle(newStyle.release());
+    return rb;
+}
+
+RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby)
+{
+    ASSERT(parentRuby && parentRuby->isRuby());
+    RenderRubyRun* rr = new (parentRuby->renderArena()) RenderRubyRun(parentRuby->document() /* anonymous */);
+    RefPtr<RenderStyle> newStyle = RenderStyle::create();
+    newStyle->inheritFrom(parentRuby->style());
+    newStyle->setDisplay(INLINE_BLOCK);
+    rr->setStyle(newStyle.release());
+    return rr;
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderRubyRun.h b/WebCore/rendering/RenderRubyRun.h
new file mode 100644 (file)
index 0000000..52ee72c
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER 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 RenderRubyRun_h
+#define RenderRubyRun_h
+
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+class RenderRubyBase;
+class RenderRubyText;
+
+// RenderRubyRun are 'inline-block/table' like objects,and wrap a single pairing of a ruby base with its ruby text(s).
+// See RenderRuby.h for further comments on the structure
+
+class RenderRubyRun : public RenderBlock {
+public:
+    RenderRubyRun(Node*);
+    virtual ~RenderRubyRun();
+
+    virtual const char* renderName() const { return "RenderRubyRun (anonymous)"; }
+
+    virtual bool isRubyRun() const { return true; }
+
+    bool hasRubyText() const;
+    bool hasRubyBase() const;
+    bool isEmpty() const;
+    RenderRubyText* rubyText() const;
+    RenderRubyBase* rubyBase() const;
+    RenderRubyBase* rubyBaseSafe(); // creates the base if it doesn't already exist
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject* child);
+
+    virtual RenderBlock* firstLineBlock() const;
+    virtual void updateFirstLetter();
+
+    static RenderRubyRun* staticCreateRubyRun(const RenderObject* parentRuby);
+
+protected:
+    RenderRubyBase* createRubyBase() const;
+};
+
+} // namespace WebCore
+
+#endif // RenderRubyRun_h
diff --git a/WebCore/rendering/RenderRubyText.cpp b/WebCore/rendering/RenderRubyText.cpp
new file mode 100644 (file)
index 0000000..cfe3b5c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RenderRubyText.h"
+
+namespace WebCore {
+
+RenderRubyText::RenderRubyText(Node* node)
+    : RenderBlock(node)
+{
+}
+
+RenderRubyText::~RenderRubyText()
+{
+}
+
+bool RenderRubyText::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+    return child->isInline();
+}
+
+} // namespace WebCore
diff --git a/WebCore/rendering/RenderRubyText.h b/WebCore/rendering/RenderRubyText.h
new file mode 100644 (file)
index 0000000..e475914
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER 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 RenderRubyText_h
+#define RenderRubyText_h
+
+#include "RenderBlock.h"
+
+namespace WebCore {
+
+class RenderRubyText : public RenderBlock {
+public:
+    RenderRubyText(Node*);
+    virtual ~RenderRubyText();
+
+    virtual const char* renderName() const { return "RenderRubyText"; }
+
+    virtual bool isRubyText() const { return true; }
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+};
+
+} // namespace WebCore
+
+#endif // RenderRubyText_h