Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
377bf27f
authored
May 18, 2020
by
ibaker
Committed by
Oliver Woodman
May 18, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Extend WebVTT ruby-position support to include <rt> tags
PiperOrigin-RevId: 312096467
parent
38fc7d8c
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
53 additions
and
19 deletions
RELEASENOTES.md
library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java
library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttDecoderTest.java
testdata/src/test/assets/webvtt/with_rubies
RELEASENOTES.md
View file @
377bf27f
...
...
@@ -128,6 +128,7 @@
of which are supported.
*
Ignore excess characters in CEA-608 lines (max length is 32)
(
[
#7341
](
https://github.com/google/ExoPlayer/issues/7341
)
).
*
Add support for WebVTT's
`ruby-position`
CSS property.
*
DRM:
*
Add support for attaching DRM sessions to clear content in the demo app.
*
Remove
`DrmSessionManager`
references from all renderers.
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/webvtt/WebvttCueParser.java
View file @
377bf27f
...
...
@@ -538,8 +538,6 @@ public final class WebvttCueParser {
List
<
StyleMatch
>
scratchStyleMatches
)
{
int
start
=
startTag
.
position
;
int
end
=
text
.
length
();
scratchStyleMatches
.
clear
();
getApplicableStyles
(
styles
,
cueId
,
startTag
,
scratchStyleMatches
);
switch
(
startTag
.
name
)
{
case
TAG_BOLD:
...
...
@@ -551,7 +549,7 @@ public final class WebvttCueParser {
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
break
;
case
TAG_RUBY:
applyRubySpans
(
text
,
start
,
nestedElements
,
scratchStyleMatch
es
);
applyRubySpans
(
text
,
cueId
,
startTag
,
nestedElements
,
styl
es
);
break
;
case
TAG_UNDERLINE:
text
.
setSpan
(
new
UnderlineSpan
(),
start
,
end
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
...
...
@@ -567,6 +565,8 @@ public final class WebvttCueParser {
return
;
}
scratchStyleMatches
.
clear
();
getApplicableStyles
(
styles
,
cueId
,
startTag
,
scratchStyleMatches
);
for
(
int
i
=
0
;
i
<
scratchStyleMatches
.
size
();
i
++)
{
applyStyleToText
(
text
,
scratchStyleMatches
.
get
(
i
).
style
,
start
,
end
);
}
...
...
@@ -574,27 +574,29 @@ public final class WebvttCueParser {
private
static
void
applyRubySpans
(
SpannableStringBuilder
text
,
int
startTagPosition
,
@Nullable
String
cueId
,
StartTag
startTag
,
List
<
Element
>
nestedElements
,
List
<
StyleMatch
>
styleMatches
)
{
@RubySpan
.
Position
int
rubyPosition
=
RubySpan
.
POSITION_OVER
;
for
(
int
i
=
0
;
i
<
styleMatches
.
size
();
i
++)
{
WebvttCssStyle
style
=
styleMatches
.
get
(
i
).
style
;
if
(
style
.
getRubyPosition
()
!=
RubySpan
.
POSITION_UNKNOWN
)
{
rubyPosition
=
style
.
getRubyPosition
();
break
;
}
}
List
<
WebvttCssStyle
>
styles
)
{
@RubySpan
.
Position
int
rubyTagPosition
=
getRubyPosition
(
styles
,
cueId
,
startTag
);
List
<
Element
>
sortedNestedElements
=
new
ArrayList
<>(
nestedElements
.
size
());
sortedNestedElements
.
addAll
(
nestedElements
);
Collections
.
sort
(
sortedNestedElements
,
Element
.
BY_START_POSITION_ASC
);
int
deletedCharCount
=
0
;
int
lastRubyTextEnd
=
startTag
P
osition
;
int
lastRubyTextEnd
=
startTag
.
p
osition
;
for
(
int
i
=
0
;
i
<
sortedNestedElements
.
size
();
i
++)
{
if
(!
TAG_RUBY_TEXT
.
equals
(
sortedNestedElements
.
get
(
i
).
startTag
.
name
))
{
continue
;
}
Element
rubyTextElement
=
sortedNestedElements
.
get
(
i
);
// Use the <rt> element's ruby-position if set, otherwise the <ruby> element's and otherwise
// default to OVER.
@RubySpan
.
Position
int
rubyPosition
=
firstKnownRubyPosition
(
getRubyPosition
(
styles
,
cueId
,
rubyTextElement
.
startTag
),
rubyTagPosition
,
RubySpan
.
POSITION_OVER
);
// Move the rubyText from spannedText into the RubySpan.
int
adjustedRubyTextStart
=
rubyTextElement
.
startTag
.
position
-
deletedCharCount
;
int
adjustedRubyTextEnd
=
rubyTextElement
.
endPosition
-
deletedCharCount
;
...
...
@@ -611,6 +613,37 @@ public final class WebvttCueParser {
}
}
@RubySpan
.
Position
private
static
int
getRubyPosition
(
List
<
WebvttCssStyle
>
styles
,
@Nullable
String
cueId
,
StartTag
startTag
)
{
List
<
StyleMatch
>
styleMatches
=
new
ArrayList
<>();
getApplicableStyles
(
styles
,
cueId
,
startTag
,
styleMatches
);
for
(
int
i
=
0
;
i
<
styleMatches
.
size
();
i
++)
{
WebvttCssStyle
style
=
styleMatches
.
get
(
i
).
style
;
if
(
style
.
getRubyPosition
()
!=
RubySpan
.
POSITION_UNKNOWN
)
{
return
style
.
getRubyPosition
();
}
}
return
RubySpan
.
POSITION_UNKNOWN
;
}
@RubySpan
.
Position
private
static
int
firstKnownRubyPosition
(
@RubySpan
.
Position
int
position1
,
@RubySpan
.
Position
int
position2
,
@RubySpan
.
Position
int
position3
)
{
if
(
position1
!=
RubySpan
.
POSITION_UNKNOWN
)
{
return
position1
;
}
if
(
position2
!=
RubySpan
.
POSITION_UNKNOWN
)
{
return
position2
;
}
if
(
position3
!=
RubySpan
.
POSITION_UNKNOWN
)
{
return
position3
;
}
throw
new
IllegalArgumentException
();
}
/**
* Adds {@link ForegroundColorSpan}s and {@link BackgroundColorSpan}s to {@code text} for entries
* in {@code classes} that match WebVTT's <a
...
...
library/core/src/test/java/com/google/android/exoplayer2/text/webvtt/WebvttDecoderTest.java
View file @
377bf27f
...
...
@@ -373,18 +373,18 @@ public class WebvttDecoderTest {
"Some text with under-ruby and over-ruby (default)"
.
length
())
.
withTextAndPosition
(
"over"
,
RubySpan
.
POSITION_OVER
);
// Check many <rt> tags nested in a single <ruby> span.
// Check many <rt> tags
with different positions
nested in a single <ruby> span.
Cue
thirdCue
=
Iterables
.
getOnlyElement
(
subtitle
.
getCues
(
subtitle
.
getEventTime
(
4
)));
assertThat
(
thirdCue
.
text
.
toString
()).
isEqualTo
(
"base1base2base3."
);
assertThat
((
Spanned
)
thirdCue
.
text
)
.
hasRubySpanBetween
(
/* start= */
0
,
"base1"
.
length
())
.
withTextAndPosition
(
"
text
1"
,
RubySpan
.
POSITION_OVER
);
.
withTextAndPosition
(
"
over
1"
,
RubySpan
.
POSITION_OVER
);
assertThat
((
Spanned
)
thirdCue
.
text
)
.
hasRubySpanBetween
(
"base1"
.
length
(),
"base1base2"
.
length
())
.
withTextAndPosition
(
"
text2"
,
RubySpan
.
POSITION_OV
ER
);
.
withTextAndPosition
(
"
under2"
,
RubySpan
.
POSITION_UND
ER
);
assertThat
((
Spanned
)
thirdCue
.
text
)
.
hasRubySpanBetween
(
"base1base2"
.
length
(),
"base1base2base3"
.
length
())
.
withTextAndPosition
(
"
text3"
,
RubySpan
.
POSITION_OV
ER
);
.
withTextAndPosition
(
"
under3"
,
RubySpan
.
POSITION_UND
ER
);
// Check a <ruby> span with no <rt> tags.
Cue
fourthCue
=
Iterables
.
getOnlyElement
(
subtitle
.
getCues
(
subtitle
.
getEventTime
(
6
)));
...
...
testdata/src/test/assets/webvtt/with_rubies
View file @
377bf27f
...
...
@@ -19,7 +19,7 @@ Some <ruby.under>text with under-ruby<rt>under</rt></ruby> and <ruby>over-ruby (
NOTE Many individual rubies in a single <ruby> tag
00:00:05.000 --> 00:00:06.000
<ruby
>base1<rt>text1</rt>base2<rt>text2</rt>base3<rt>text
3</rt></ruby>.
<ruby
.under>base1<rt.over>over1</rt>base2<rt>under2</rt>base3<rt.under>under
3</rt></ruby>.
00:00:07.000 --> 00:00:08.000
Some <ruby>text with no ruby text</ruby>.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment