Source/WebCore/ChangeLog

 12013-01-23 Victor Carbune <vcarbune@chromium.org>
 2
 3 Determine text direction for rendering a TextTrackCue
 4 https://bugs.webkit.org/show_bug.cgi?id=79749
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Test: media/track/track-cue-rendering-rtl.html
 9
 10 * html/track/TextTrackCue.cpp:
 11 (WebCore::TextTrackCueBox::applyCSSProperties): Updated to
 12 retrieve apply the direction determined.
 13 (WebCore::TextTrackCue::TextTrackCue): Set default value
 14 for the display direction.
 15 (WebCore::TextTrackCue::determineTextDirection): Determined
 16 direction using the Unicode Bidirectional Algorithm.
 17 (WebCore):
 18 (WebCore::TextTrackCue::calculateDisplayParameters): Updated.
 19 (WebCore::TextTrackCue::getCSSWritingDirection): Added to
 20 return the writing direction of the cue.
 21 * html/track/TextTrackCue.h:
 22 (TextTrackCue):
 23 * platform/graphics/GraphicsContext.cpp: Extracted TextRunIterator.
 24 * platform/graphics/TextRun.h: Added TextRunIterator.
 25 (TextRunIterator): Moved the TextRunIterator class to TextRun,
 26 so it can be used anywhere the unicode bidirectional algorithm
 27 needs to be run.
 28 (WebCore::TextRunIterator::TextRunIterator):
 29 (WebCore::TextRunIterator::offset):
 30 (WebCore::TextRunIterator::increment):
 31 (WebCore::TextRunIterator::atEnd):
 32 (WebCore::TextRunIterator::current):
 33 (WebCore::TextRunIterator::direction):
 34 (WebCore::TextRunIterator::operator==):
 35 (WebCore::TextRunIterator::operator!=):
 36 (WebCore):
 37
1382013-01-23 Tony Chang <tony@chromium.org>
239
340 Incorrect scrollable height during simplified layout

Source/WebCore/html/track/TextTrackCue.cpp

3535
3636#include "TextTrackCue.h"
3737
 38#include "BidiResolver.h"
3839#include "CSSPropertyNames.h"
3940#include "CSSValueKeywords.h"
4041#include "DocumentFragment.h"

4546#include "NodeTraversal.h"
4647#include "RenderTextTrackCue.h"
4748#include "Text.h"
 49#include "TextRun.h"
4850#include "TextTrack.h"
4951#include "TextTrackCueList.h"
5052#include "WebVTTElement.h"

@@void TextTrackCueBox::applyCSSProperties(const IntSize&)
119121 // the 'unicode-bidi' property must be set to 'plaintext'
120122 setInlineStyleProperty(CSSPropertyUnicodeBidi, CSSValueWebkitPlaintext);
121123
122  // FIXME: Determine the text direction using the BIDI algorithm. http://wkb.ug/79749
123124 // the 'direction' property must be set to direction
124  setInlineStyleProperty(CSSPropertyDirection, CSSValueLtr);
 125 setInlineStyleProperty(CSSPropertyDirection, m_cue->getCSSWritingDirection());
125126
126127 // the 'writing-mode' property must be set to writing-mode
127128 setInlineStyleProperty(CSSPropertyWebkitWritingMode, m_cue->getCSSWritingMode(), false);

@@TextTrackCue::TextTrackCue(ScriptExecutionContext* context, double start, double
210211 , m_snapToLines(true)
211212 , m_allDocumentNodes(HTMLDivElement::create(static_cast<Document*>(context)))
212213 , m_displayTreeShouldChange(true)
 214 , m_displayDirection(CSSValueLtr)
213215{
214216 ASSERT(m_scriptExecutionContext->isDocument());
215217

@@int TextTrackCue::calculateComputedLinePosition()
595597 return n;
596598}
597599
 600void TextTrackCue::determineTextDirection()
 601{
 602 DEFINE_STATIC_LOCAL(const String, rtTag, (ASCIILiteral("rt")));
 603 createWebVTTNodeTree();
 604
 605 // Apply the Unicode Bidirectional Algorithm's Paragraph Level steps to the
 606 // concatenation of the values of each WebVTT Text Object in nodes, in a
 607 // pre-order, depth-first traversal, excluding WebVTT Ruby Text Objects and
 608 // their descendants...
 609 StringBuilder paragraphBuilder;
 610 for (Node* node = m_webVTTNodeTree->firstChild(); node; node = NodeTraversal::next(node, m_webVTTNodeTree.get())) {
 611 if (!node->isTextNode() || node->localName() == rtTag)
 612 continue;
 613
 614 paragraphBuilder.append(node->nodeValue());
 615 }
 616
 617 String paragraph = paragraphBuilder.toString();
 618 if (!paragraph.length())
 619 return;
 620
 621 TextRun textRun(paragraph, paragraph.length());
 622
 623 BidiResolver<TextRunIterator, BidiCharacterRun> bidiResolver;
 624 bidiResolver.setStatus(BidiStatus(textRun.direction(), textRun.directionalOverride()));
 625 bidiResolver.setPositionIgnoringNestedIsolates(TextRunIterator(&textRun, 0));
 626
 627 BidiRunList<BidiCharacterRun>& bidiRuns = bidiResolver.runs();
 628 bidiResolver.createBidiRunsForLine(TextRunIterator(&textRun, textRun.length()));
 629
 630 ASSERT(bidiRuns.runCount());
 631
 632 // ... to determine the paragraph embedding level of the first Unicode paragraph of the cue.
 633
 634 // If the paragraph embedding level determined in the previous step is even
 635 // (the paragraph direction is left-to-right), let direction be 'ltr', otherwise, let it be 'rtl'.
 636 m_displayDirection = bidiRuns.firstRun()->level() % 2 ? CSSValueRtl : CSSValueLtr;
 637}
 638
598639void TextTrackCue::calculateDisplayParameters()
599640{
600  // FIXME(BUG 79749): Determine the text direction using the BIDI algorithm.
601641 // Steps 10.2, 10.3
602  m_displayDirection = CSSValueLtr;
 642 determineTextDirection();
603643
604644 // 10.4 If the text track cue writing direction is horizontal, then let
605645 // block-flow be 'tb'. Otherwise, if the text track cue writing direction is

@@NextSetting:
10391079 }
10401080}
10411081
 1082int TextTrackCue::getCSSWritingDirection() const
 1083{
 1084 return m_displayDirection;
 1085}
 1086
10421087int TextTrackCue::getCSSWritingMode() const
10431088{
10441089 return m_displayWritingMode;

Source/WebCore/html/track/TextTrackCue.h

@@public:
169169 virtual ScriptExecutionContext* scriptExecutionContext() const;
170170
171171 std::pair<double, double> getCSSPosition() const;
 172
172173 int getCSSSize() const;
 174 int getCSSWritingDirection() const;
173175 int getCSSWritingMode() const;
174176
175177 enum WritingDirection {

@@private:
220222 std::pair<double, double> getPositionCoordinates() const;
221223 void parseSettings(const String&);
222224
 225 void determineTextDirection();
223226 void calculateDisplayParameters();
224227
225228 void cueWillChange();

Source/WebCore/platform/graphics/GraphicsContext.cpp

@@using namespace std;
4040
4141namespace WebCore {
4242
43 class TextRunIterator {
44 public:
45  TextRunIterator()
46  : m_textRun(0)
47  , m_offset(0)
48  {
49  }
50 
51  TextRunIterator(const TextRun* textRun, unsigned offset)
52  : m_textRun(textRun)
53  , m_offset(offset)
54  {
55  }
56 
57  TextRunIterator(const TextRunIterator& other)
58  : m_textRun(other.m_textRun)
59  , m_offset(other.m_offset)
60  {
61  }
62 
63  unsigned offset() const { return m_offset; }
64  void increment() { m_offset++; }
65  bool atEnd() const { return !m_textRun || m_offset >= m_textRun->length(); }
66  UChar current() const { return (*m_textRun)[m_offset]; }
67  WTF::Unicode::Direction direction() const { return atEnd() ? WTF::Unicode::OtherNeutral : WTF::Unicode::direction(current()); }
68 
69  bool operator==(const TextRunIterator& other)
70  {
71  return m_offset == other.m_offset && m_textRun == other.m_textRun;
72  }
73 
74  bool operator!=(const TextRunIterator& other) { return !operator==(other); }
75 
76 private:
77  const TextRun* m_textRun;
78  int m_offset;
79 };
80 
8143GraphicsContext::GraphicsContext(PlatformGraphicsContext* platformGraphicsContext)
8244 : m_updatingControlTints(false)
8345 , m_transparencyCount(0)

Source/WebCore/platform/graphics/TextRun.h

@@inline void TextRun::setTabSize(bool allow, unsigned size)
256256 m_tabSize = size;
257257}
258258
 259class TextRunIterator {
 260public:
 261 TextRunIterator()
 262 : m_textRun(0)
 263 , m_offset(0)
 264 {
 265 }
 266
 267 TextRunIterator(const TextRun* textRun, unsigned offset)
 268 : m_textRun(textRun)
 269 , m_offset(offset)
 270 {
 271 }
 272
 273 TextRunIterator(const TextRunIterator& other)
 274 : m_textRun(other.m_textRun)
 275 , m_offset(other.m_offset)
 276 {
 277 }
 278
 279 unsigned offset() const { return m_offset; }
 280 void increment() { m_offset++; }
 281 bool atEnd() const { return !m_textRun || m_offset >= m_textRun->length(); }
 282 UChar current() const { return (*m_textRun)[m_offset]; }
 283 WTF::Unicode::Direction direction() const { return atEnd() ? WTF::Unicode::OtherNeutral : WTF::Unicode::direction(current()); }
 284
 285 bool operator==(const TextRunIterator& other)
 286 {
 287 return m_offset == other.m_offset && m_textRun == other.m_textRun;
 288 }
 289
 290 bool operator!=(const TextRunIterator& other) { return !operator==(other); }
 291
 292private:
 293 const TextRun* m_textRun;
 294 int m_offset;
 295};
 296
259297}
260298
261299#endif

LayoutTests/ChangeLog

 12013-01-23 Victor Carbune <vcarbune@chromium.org>
 2
 3 Determine text direction for rendering a TextTrackCue
 4 https://bugs.webkit.org/show_bug.cgi?id=79749
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 * media/track/captions-webvtt/captions-rtl.vtt: Added.
 9 * media/track/track-cue-rendering-rtl-expected.txt: Added.
 10 * media/track/track-cue-rendering-rtl.html: Added.
 11
1122013-01-23 Tony Chang <tony@chromium.org>
213
314 Incorrect scrollable height during simplified layout

LayoutTests/media/track/captions-webvtt/captions-rtl.vtt

 1WEBVTT
 2
 31
 400:00:00.000 --> 00:00:01.000
 5تجربة

LayoutTests/media/track/track-cue-rendering-rtl-expected.txt

 1Test that TextTrack RTL cues are rendered correctly.
 2
 3EVENT(canplaythrough)
 4EVENT(seeked)
 5
 6** The cue should contain arabic text **
 7EXPECTED (video.currentTime == '0.5') OK
 8EXPECTED (testTrack.track.activeCues.length == '1') OK
 9EXPECTED (testTrack.track.activeCues[0].text == 'تجربة') OK
 10EXPECTED (testCueDisplayBox.innerText == 'تجربة') OK
 11
 12** The position should be default and CSS direction set to RTL **
 13EXPECTED (2 * testCueDisplayBox.offsetLeft == video.videoWidth - testCueDisplayBox.offsetWidth == 'true') OK
 14EXPECTED (getComputedStyle(testCueDisplayBox).direction == 'rtl') OK
 15END OF TEST
 16

LayoutTests/media/track/track-cue-rendering-rtl.html

 1<!DOCTYPE html>
 2<html>
 3 <head>
 4 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 5
 6 <script src=../media-file.js></script>
 7 <script src=../video-test.js></script>
 8 <script src=../media-controls.js></script>
 9
 10 <script>
 11
 12 var testTrack;
 13 var testCueDisplayBox;
 14 var seekedCount = 0;
 15 var info = [ "تجربة" ];
 16
 17 function testCueStyle()
 18 {
 19 endTest();
 20 }
 21
 22 function seeked()
 23 {
 24 testCueDisplayBox = textTrackDisplayElement(video, 'display');
 25
 26 consoleWrite("");
 27 consoleWrite("** The cue should contain arabic text **");
 28 testExpected("video.currentTime", seekedCount + .5);
 29 testExpected("testTrack.track.activeCues.length", 1);
 30 testExpected("testTrack.track.activeCues[0].text", info[seekedCount]);
 31 testExpected("testCueDisplayBox.innerText", info[seekedCount]);
 32
 33 consoleWrite("");
 34 consoleWrite("** The position should be default and CSS direction set to RTL **");
 35 testExpected("2 * testCueDisplayBox.offsetLeft == video.videoWidth - testCueDisplayBox.offsetWidth", true)
 36 testExpected("getComputedStyle(testCueDisplayBox).direction", "rtl");
 37
 38 if (++seekedCount == info.length)
 39 endTest();
 40 else {
 41 consoleWrite("");
 42 run("video.currentTime = " + (video.currentTime + 1));
 43 return;
 44 }
 45 }
 46
 47 function loaded()
 48 {
 49 consoleWrite("Test that TextTrack RTL cues are rendered correctly.");
 50 testTrack = document.querySelector('track');
 51
 52 findMediaElement();
 53 video.src = findMediaFile('video', '../content/test');
 54
 55 consoleWrite("");
 56 waitForEvent('seeked', seeked);
 57 waitForEvent('canplaythrough', function() { video.currentTime = .5; });
 58 }
 59 </script>
 60 </head>
 61 <body onload="loaded()">
 62 <video controls >
 63 <track src="captions-webvtt/captions-rtl.vtt" kind="captions" default>
 64 </video>
 65 </body>
 66</html>