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
6603c6bb
authored
Apr 01, 2021
by
Oliver Woodman
Browse files
Options
_('Browse Files')
Download
Plain Diff
Merge pull request #8720 from dlafayet:tts-shear-block
PiperOrigin-RevId: 365998615
parents
dc0ee758
475b1fe3
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
185 additions
and
13 deletions
RELEASENOTES.md
library/common/src/main/java/com/google/android/exoplayer2/text/Cue.java
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java
library/core/src/test/java/com/google/android/exoplayer2/text/CueTest.java
library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java
library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlStyleTest.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/WebViewSubtitleOutput.java
testdata/src/test/assets/media/ttml/shear.xml
RELEASENOTES.md
View file @
6603c6bb
...
@@ -20,8 +20,8 @@
...
@@ -20,8 +20,8 @@
*
Add group setting to
`PlayerNotificationManager`
.
*
Add group setting to
`PlayerNotificationManager`
.
*
Fix
`StyledPlayerView`
scrubber not reappearing correctly in some cases
*
Fix
`StyledPlayerView`
scrubber not reappearing correctly in some cases
(
[
#8646
](
https://github.com/google/ExoPlayer/issues/8646
)
).
(
[
#8646
](
https://github.com/google/ExoPlayer/issues/8646
)
).
*
Fix measurement of
`StyledPlayerView`
and
`StyledPlayerControlView`
*
Fix measurement of
`StyledPlayerView`
and
`StyledPlayerControlView`
when
when
`wrap_content`
is used
`wrap_content`
is used
(
[
#8726
](
https://github.com/google/ExoPlayer/issues/8726
)
).
(
[
#8726
](
https://github.com/google/ExoPlayer/issues/8726
)
).
*
Audio:
*
Audio:
*
Report unexpected discontinuities in
*
Report unexpected discontinuities in
...
@@ -101,6 +101,7 @@
...
@@ -101,6 +101,7 @@
*
Fix CEA-708 priority handling to sort cues in the order defined by the
*
Fix CEA-708 priority handling to sort cues in the order defined by the
spec (
[
#8704
](
https://github.com/google/ExoPlayer/issues/8704
)
).
spec (
[
#8704
](
https://github.com/google/ExoPlayer/issues/8704
)
).
*
Support TTML
`textEmphasis`
attributes, used for Japanese boutens.
*
Support TTML
`textEmphasis`
attributes, used for Japanese boutens.
*
Support TTML
`shear`
attributes.
*
MediaSession extension: Remove dependency to core module and rely on common
*
MediaSession extension: Remove dependency to core module and rely on common
only. The
`TimelineQueueEditor`
uses a new
`MediaDescriptionConverter`
for
only. The
`TimelineQueueEditor`
uses a new
`MediaDescriptionConverter`
for
this purpose and does not rely on the
`ConcatenatingMediaSource`
anymore.
this purpose and does not rely on the
`ConcatenatingMediaSource`
anymore.
...
...
library/common/src/main/java/com/google/android/exoplayer2/text/Cue.java
View file @
6603c6bb
...
@@ -270,6 +270,12 @@ public final class Cue {
...
@@ -270,6 +270,12 @@ public final class Cue {
public
final
@VerticalType
int
verticalType
;
public
final
@VerticalType
int
verticalType
;
/**
/**
* The shear angle in degrees to be applied to this Cue, expressed in graphics coordinates. This
* results in a skew transform for the block along the inline progression axis.
*/
public
final
float
shearDegrees
;
/**
* Creates a text cue whose {@link #textAlignment} is null, whose type parameters are set to
* Creates a text cue whose {@link #textAlignment} is null, whose type parameters are set to
* {@link #TYPE_UNSET} and whose dimension parameters are set to {@link #DIMEN_UNSET}.
* {@link #TYPE_UNSET} and whose dimension parameters are set to {@link #DIMEN_UNSET}.
*
*
...
@@ -370,7 +376,8 @@ public final class Cue {
...
@@ -370,7 +376,8 @@ public final class Cue {
/* bitmapHeight= */
DIMEN_UNSET
,
/* bitmapHeight= */
DIMEN_UNSET
,
/* windowColorSet= */
false
,
/* windowColorSet= */
false
,
/* windowColor= */
Color
.
BLACK
,
/* windowColor= */
Color
.
BLACK
,
/* verticalType= */
TYPE_UNSET
);
/* verticalType= */
TYPE_UNSET
,
/* shearDegrees= */
0
f
);
}
}
/**
/**
...
@@ -415,7 +422,8 @@ public final class Cue {
...
@@ -415,7 +422,8 @@ public final class Cue {
/* bitmapHeight= */
DIMEN_UNSET
,
/* bitmapHeight= */
DIMEN_UNSET
,
windowColorSet
,
windowColorSet
,
windowColor
,
windowColor
,
/* verticalType= */
TYPE_UNSET
);
/* verticalType= */
TYPE_UNSET
,
/* shearDegrees= */
0
f
);
}
}
private
Cue
(
private
Cue
(
...
@@ -433,7 +441,8 @@ public final class Cue {
...
@@ -433,7 +441,8 @@ public final class Cue {
float
bitmapHeight
,
float
bitmapHeight
,
boolean
windowColorSet
,
boolean
windowColorSet
,
int
windowColor
,
int
windowColor
,
@VerticalType
int
verticalType
)
{
@VerticalType
int
verticalType
,
float
shearDegrees
)
{
// Exactly one of text or bitmap should be set.
// Exactly one of text or bitmap should be set.
if
(
text
==
null
)
{
if
(
text
==
null
)
{
Assertions
.
checkNotNull
(
bitmap
);
Assertions
.
checkNotNull
(
bitmap
);
...
@@ -455,6 +464,7 @@ public final class Cue {
...
@@ -455,6 +464,7 @@ public final class Cue {
this
.
textSizeType
=
textSizeType
;
this
.
textSizeType
=
textSizeType
;
this
.
textSize
=
textSize
;
this
.
textSize
=
textSize
;
this
.
verticalType
=
verticalType
;
this
.
verticalType
=
verticalType
;
this
.
shearDegrees
=
shearDegrees
;
}
}
/** Returns a new {@link Cue.Builder} initialized with the same values as this Cue. */
/** Returns a new {@link Cue.Builder} initialized with the same values as this Cue. */
...
@@ -479,6 +489,7 @@ public final class Cue {
...
@@ -479,6 +489,7 @@ public final class Cue {
private
boolean
windowColorSet
;
private
boolean
windowColorSet
;
@ColorInt
private
int
windowColor
;
@ColorInt
private
int
windowColor
;
@VerticalType
private
int
verticalType
;
@VerticalType
private
int
verticalType
;
private
float
shearDegrees
;
public
Builder
()
{
public
Builder
()
{
text
=
null
;
text
=
null
;
...
@@ -514,6 +525,7 @@ public final class Cue {
...
@@ -514,6 +525,7 @@ public final class Cue {
windowColorSet
=
cue
.
windowColorSet
;
windowColorSet
=
cue
.
windowColorSet
;
windowColor
=
cue
.
windowColor
;
windowColor
=
cue
.
windowColor
;
verticalType
=
cue
.
verticalType
;
verticalType
=
cue
.
verticalType
;
shearDegrees
=
cue
.
shearDegrees
;
}
}
/**
/**
...
@@ -794,6 +806,12 @@ public final class Cue {
...
@@ -794,6 +806,12 @@ public final class Cue {
return
this
;
return
this
;
}
}
/** Sets the shear angle for this Cue. */
public
Builder
setShearDegrees
(
float
shearDegrees
)
{
this
.
shearDegrees
=
shearDegrees
;
return
this
;
}
/**
/**
* Gets the vertical formatting for this Cue.
* Gets the vertical formatting for this Cue.
*
*
...
@@ -821,7 +839,8 @@ public final class Cue {
...
@@ -821,7 +839,8 @@ public final class Cue {
bitmapHeight
,
bitmapHeight
,
windowColorSet
,
windowColorSet
,
windowColor
,
windowColor
,
verticalType
);
verticalType
,
shearDegrees
);
}
}
}
}
}
}
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java
View file @
6603c6bb
...
@@ -15,6 +15,9 @@
...
@@ -15,6 +15,9 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
.
text
.
ttml
;
package
com
.
google
.
android
.
exoplayer2
.
text
.
ttml
;
import
static
java
.
lang
.
Math
.
max
;
import
static
java
.
lang
.
Math
.
min
;
import
android.text.Layout
;
import
android.text.Layout
;
import
androidx.annotation.Nullable
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
...
@@ -81,7 +84,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -81,7 +84,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
private
static
final
Pattern
OFFSET_TIME
=
private
static
final
Pattern
OFFSET_TIME
=
Pattern
.
compile
(
"^([0-9]+(?:\\.[0-9]+)?)(h|m|s|ms|f|t)$"
);
Pattern
.
compile
(
"^([0-9]+(?:\\.[0-9]+)?)(h|m|s|ms|f|t)$"
);
private
static
final
Pattern
FONT_SIZE
=
Pattern
.
compile
(
"^(([0-9]*.)?[0-9]+)(px|em|%)$"
);
private
static
final
Pattern
FONT_SIZE
=
Pattern
.
compile
(
"^(([0-9]*.)?[0-9]+)(px|em|%)$"
);
private
static
final
Pattern
PERCENTAGE_COORDINATES
=
static
final
Pattern
SIGNED_PERCENTAGE
=
Pattern
.
compile
(
"^([-+]?\\d+\\.?\\d*?)%$"
);
static
final
Pattern
PERCENTAGE_COORDINATES
=
Pattern
.
compile
(
"^(\\d+\\.?\\d*?)% (\\d+\\.?\\d*?)%$"
);
Pattern
.
compile
(
"^(\\d+\\.?\\d*?)% (\\d+\\.?\\d*?)%$"
);
private
static
final
Pattern
PIXEL_COORDINATES
=
private
static
final
Pattern
PIXEL_COORDINATES
=
Pattern
.
compile
(
"^(\\d+\\.?\\d*?)px (\\d+\\.?\\d*?)px$"
);
Pattern
.
compile
(
"^(\\d+\\.?\\d*?)px (\\d+\\.?\\d*?)px$"
);
...
@@ -614,6 +618,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -614,6 +618,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
createIfNull
(
style
)
createIfNull
(
style
)
.
setTextEmphasis
(
TextEmphasis
.
parse
(
Util
.
toLowerInvariant
(
attributeValue
)));
.
setTextEmphasis
(
TextEmphasis
.
parse
(
Util
.
toLowerInvariant
(
attributeValue
)));
break
;
break
;
case
TtmlNode
.
ATTR_TTS_SHEAR
:
style
=
createIfNull
(
style
).
setShearPercentage
(
parseShear
(
attributeValue
));
break
;
default
:
default
:
// ignore
// ignore
break
;
break
;
...
@@ -756,10 +763,35 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -756,10 +763,35 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
}
}
/**
/**
* Returns the parsed shear percentage (between -100.0 and +100.0 inclusive), or {@link
* TtmlStyle#UNSPECIFIED_SHEAR} if parsing failed.
*/
private
static
float
parseShear
(
String
expression
)
{
Matcher
matcher
=
SIGNED_PERCENTAGE
.
matcher
(
expression
);
if
(!
matcher
.
matches
())
{
Log
.
w
(
TAG
,
"Invalid value for shear: "
+
expression
);
return
TtmlStyle
.
UNSPECIFIED_SHEAR
;
}
try
{
String
percentage
=
Assertions
.
checkNotNull
(
matcher
.
group
(
1
));
float
value
=
Float
.
parseFloat
(
percentage
);
// https://www.w3.org/TR/2018/REC-ttml2-20181108/#semantics-style-procedures-shear
// If the absolute value of the specified percentage is greater than 100%, then it must be
// interpreted as if 100% were specified with the appropriate sign.
value
=
max
(-
100
f
,
value
);
value
=
min
(
100
f
,
value
);
return
value
;
}
catch
(
NumberFormatException
e
)
{
Log
.
w
(
TAG
,
"Failed to parse shear: "
+
expression
,
e
);
return
TtmlStyle
.
UNSPECIFIED_SHEAR
;
}
}
/**
* Parses a time expression, returning the parsed timestamp.
* Parses a time expression, returning the parsed timestamp.
*
<p>
*
*
For the format of a time expression, see:
*
<p>For the format of a time expression, see: <a
*
<a
href="http://www.w3.org/TR/ttaf1-dfxp/#timing-value-timeExpression">timeExpression</a>
* href="http://www.w3.org/TR/ttaf1-dfxp/#timing-value-timeExpression">timeExpression</a>
*
*
* @param time A string that includes the time expression.
* @param time A string that includes the time expression.
* @param frameAndTickRate The effective frame and tick rates of the stream.
* @param frameAndTickRate The effective frame and tick rates of the stream.
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java
View file @
6603c6bb
...
@@ -71,6 +71,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
...
@@ -71,6 +71,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public
static
final
String
ATTR_TTS_TEXT_COMBINE
=
"textCombine"
;
public
static
final
String
ATTR_TTS_TEXT_COMBINE
=
"textCombine"
;
public
static
final
String
ATTR_TTS_TEXT_EMPHASIS
=
"textEmphasis"
;
public
static
final
String
ATTR_TTS_TEXT_EMPHASIS
=
"textEmphasis"
;
public
static
final
String
ATTR_TTS_WRITING_MODE
=
"writingMode"
;
public
static
final
String
ATTR_TTS_WRITING_MODE
=
"writingMode"
;
public
static
final
String
ATTR_TTS_SHEAR
=
"shear"
;
// Values for ruby
// Values for ruby
public
static
final
String
RUBY_CONTAINER
=
"container"
;
public
static
final
String
RUBY_CONTAINER
=
"container"
;
...
@@ -408,6 +409,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
...
@@ -408,6 +409,16 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
if
(
resolvedStyle
!=
null
)
{
if
(
resolvedStyle
!=
null
)
{
TtmlRenderUtil
.
applyStylesToSpan
(
TtmlRenderUtil
.
applyStylesToSpan
(
text
,
start
,
end
,
resolvedStyle
,
parent
,
globalStyles
,
verticalType
);
text
,
start
,
end
,
resolvedStyle
,
parent
,
globalStyles
,
verticalType
);
if
(
resolvedStyle
.
getShearPercentage
()
!=
TtmlStyle
.
UNSPECIFIED_SHEAR
&&
TAG_P
.
equals
(
tag
))
{
// Shear style should only be applied to P nodes
// https://www.w3.org/TR/2018/REC-ttml2-20181108/#style-attribute-shear
// The spec doesn't specify the coordinate system to use for block shear
// however the spec shows examples of how different values are expected to be rendered.
// See: https://www.w3.org/TR/2018/REC-ttml2-20181108/#style-attribute-shear
// https://www.w3.org/TR/2018/REC-ttml2-20181108/#style-attribute-fontShear
// This maps the shear percentage to shear angle in graphics coordinates
regionOutput
.
setShearDegrees
((
resolvedStyle
.
getShearPercentage
()
*
-
90
)
/
100
);
}
regionOutput
.
setTextAlignment
(
resolvedStyle
.
getTextAlign
());
regionOutput
.
setTextAlignment
(
resolvedStyle
.
getTextAlign
());
}
}
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java
View file @
6603c6bb
...
@@ -30,6 +30,7 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -30,6 +30,7 @@ import java.lang.annotation.RetentionPolicy;
/* package */
final
class
TtmlStyle
{
/* package */
final
class
TtmlStyle
{
public
static
final
int
UNSPECIFIED
=
-
1
;
public
static
final
int
UNSPECIFIED
=
-
1
;
public
static
final
float
UNSPECIFIED_SHEAR
=
Float
.
MAX_VALUE
;
@Documented
@Documented
@Retention
(
RetentionPolicy
.
SOURCE
)
@Retention
(
RetentionPolicy
.
SOURCE
)
...
@@ -87,6 +88,7 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -87,6 +88,7 @@ import java.lang.annotation.RetentionPolicy;
@Nullable
private
Layout
.
Alignment
textAlign
;
@Nullable
private
Layout
.
Alignment
textAlign
;
@OptionalBoolean
private
int
textCombine
;
@OptionalBoolean
private
int
textCombine
;
@Nullable
private
TextEmphasis
textEmphasis
;
@Nullable
private
TextEmphasis
textEmphasis
;
private
float
shearPercentage
;
public
TtmlStyle
()
{
public
TtmlStyle
()
{
linethrough
=
UNSPECIFIED
;
linethrough
=
UNSPECIFIED
;
...
@@ -97,6 +99,7 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -97,6 +99,7 @@ import java.lang.annotation.RetentionPolicy;
rubyType
=
UNSPECIFIED
;
rubyType
=
UNSPECIFIED
;
rubyPosition
=
TextAnnotation
.
POSITION_UNKNOWN
;
rubyPosition
=
TextAnnotation
.
POSITION_UNKNOWN
;
textCombine
=
UNSPECIFIED
;
textCombine
=
UNSPECIFIED
;
shearPercentage
=
UNSPECIFIED_SHEAR
;
}
}
/**
/**
...
@@ -185,6 +188,15 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -185,6 +188,15 @@ import java.lang.annotation.RetentionPolicy;
return
hasBackgroundColor
;
return
hasBackgroundColor
;
}
}
public
TtmlStyle
setShearPercentage
(
float
shearPercentage
)
{
this
.
shearPercentage
=
shearPercentage
;
return
this
;
}
public
float
getShearPercentage
()
{
return
shearPercentage
;
}
/**
/**
* Chains this style to referential style. Local properties which are already set are never
* Chains this style to referential style. Local properties which are already set are never
* overridden.
* overridden.
...
@@ -242,6 +254,9 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -242,6 +254,9 @@ import java.lang.annotation.RetentionPolicy;
if
(
textEmphasis
==
null
)
{
if
(
textEmphasis
==
null
)
{
textEmphasis
=
ancestor
.
textEmphasis
;
textEmphasis
=
ancestor
.
textEmphasis
;
}
}
if
(
shearPercentage
==
UNSPECIFIED_SHEAR
)
{
shearPercentage
=
ancestor
.
shearPercentage
;
}
// attributes not inherited as of http://www.w3.org/TR/ttml1/
// attributes not inherited as of http://www.w3.org/TR/ttml1/
if
(
chaining
&&
!
hasBackgroundColor
&&
ancestor
.
hasBackgroundColor
)
{
if
(
chaining
&&
!
hasBackgroundColor
&&
ancestor
.
hasBackgroundColor
)
{
setBackgroundColor
(
ancestor
.
backgroundColor
);
setBackgroundColor
(
ancestor
.
backgroundColor
);
...
...
library/core/src/test/java/com/google/android/exoplayer2/text/CueTest.java
View file @
6603c6bb
...
@@ -45,6 +45,7 @@ public class CueTest {
...
@@ -45,6 +45,7 @@ public class CueTest {
.
setSize
(
0.8f
)
.
setSize
(
0.8f
)
.
setWindowColor
(
Color
.
CYAN
)
.
setWindowColor
(
Color
.
CYAN
)
.
setVerticalType
(
Cue
.
VERTICAL_TYPE_RL
)
.
setVerticalType
(
Cue
.
VERTICAL_TYPE_RL
)
.
setShearDegrees
(-
15
f
)
.
build
();
.
build
();
Cue
modifiedCue
=
cue
.
buildUpon
().
build
();
Cue
modifiedCue
=
cue
.
buildUpon
().
build
();
...
@@ -61,6 +62,7 @@ public class CueTest {
...
@@ -61,6 +62,7 @@ public class CueTest {
assertThat
(
cue
.
windowColor
).
isEqualTo
(
Color
.
CYAN
);
assertThat
(
cue
.
windowColor
).
isEqualTo
(
Color
.
CYAN
);
assertThat
(
cue
.
windowColorSet
).
isTrue
();
assertThat
(
cue
.
windowColorSet
).
isTrue
();
assertThat
(
cue
.
verticalType
).
isEqualTo
(
Cue
.
VERTICAL_TYPE_RL
);
assertThat
(
cue
.
verticalType
).
isEqualTo
(
Cue
.
VERTICAL_TYPE_RL
);
assertThat
(
cue
.
shearDegrees
).
isEqualTo
(-
15
f
);
assertThat
(
modifiedCue
.
text
).
isSameInstanceAs
(
cue
.
text
);
assertThat
(
modifiedCue
.
text
).
isSameInstanceAs
(
cue
.
text
);
assertThat
(
modifiedCue
.
textAlignment
).
isEqualTo
(
cue
.
textAlignment
);
assertThat
(
modifiedCue
.
textAlignment
).
isEqualTo
(
cue
.
textAlignment
);
...
@@ -74,6 +76,7 @@ public class CueTest {
...
@@ -74,6 +76,7 @@ public class CueTest {
assertThat
(
modifiedCue
.
windowColor
).
isEqualTo
(
cue
.
windowColor
);
assertThat
(
modifiedCue
.
windowColor
).
isEqualTo
(
cue
.
windowColor
);
assertThat
(
modifiedCue
.
windowColorSet
).
isEqualTo
(
cue
.
windowColorSet
);
assertThat
(
modifiedCue
.
windowColorSet
).
isEqualTo
(
cue
.
windowColorSet
);
assertThat
(
modifiedCue
.
verticalType
).
isEqualTo
(
cue
.
verticalType
);
assertThat
(
modifiedCue
.
verticalType
).
isEqualTo
(
cue
.
verticalType
);
assertThat
(
modifiedCue
.
shearDegrees
).
isEqualTo
(
cue
.
shearDegrees
);
}
}
@Test
@Test
...
...
library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlDecoderTest.java
View file @
6603c6bb
...
@@ -69,6 +69,7 @@ public final class TtmlDecoderTest {
...
@@ -69,6 +69,7 @@ public final class TtmlDecoderTest {
private
static
final
String
TEXT_COMBINE_FILE
=
"media/ttml/text_combine.xml"
;
private
static
final
String
TEXT_COMBINE_FILE
=
"media/ttml/text_combine.xml"
;
private
static
final
String
RUBIES_FILE
=
"media/ttml/rubies.xml"
;
private
static
final
String
RUBIES_FILE
=
"media/ttml/rubies.xml"
;
private
static
final
String
TEXT_EMPHASIS_FILE
=
"media/ttml/text_emphasis.xml"
;
private
static
final
String
TEXT_EMPHASIS_FILE
=
"media/ttml/text_emphasis.xml"
;
private
static
final
String
SHEAR_FILE
=
"media/ttml/shear.xml"
;
@Test
@Test
public
void
inlineAttributes
()
throws
IOException
,
SubtitleDecoderException
{
public
void
inlineAttributes
()
throws
IOException
,
SubtitleDecoderException
{
...
@@ -816,6 +817,35 @@ public final class TtmlDecoderTest {
...
@@ -816,6 +817,35 @@ public final class TtmlDecoderTest {
TextAnnotation
.
POSITION_BEFORE
);
TextAnnotation
.
POSITION_BEFORE
);
}
}
@Test
public
void
shear
()
throws
IOException
,
SubtitleDecoderException
{
TtmlSubtitle
subtitle
=
getSubtitle
(
SHEAR_FILE
);
Cue
firstCue
=
getOnlyCueAtTimeUs
(
subtitle
,
10_000_000
);
assertThat
(
firstCue
.
shearDegrees
).
isZero
();
Cue
secondCue
=
getOnlyCueAtTimeUs
(
subtitle
,
20_000_000
);
assertThat
(
secondCue
.
shearDegrees
).
isWithin
(
0.01f
).
of
(-
15
f
);
Cue
thirdCue
=
getOnlyCueAtTimeUs
(
subtitle
,
30_000_000
);
assertThat
(
thirdCue
.
shearDegrees
).
isWithin
(
0.01f
).
of
(
15
f
);
Cue
fourthCue
=
getOnlyCueAtTimeUs
(
subtitle
,
40_000_000
);
assertThat
(
fourthCue
.
shearDegrees
).
isWithin
(
0.01f
).
of
(-
15
f
);
Cue
fifthCue
=
getOnlyCueAtTimeUs
(
subtitle
,
50_000_000
);
assertThat
(
fifthCue
.
shearDegrees
).
isWithin
(
0.01f
).
of
(-
22.5f
);
Cue
sixthCue
=
getOnlyCueAtTimeUs
(
subtitle
,
60_000_000
);
assertThat
(
sixthCue
.
shearDegrees
).
isWithin
(
0.01f
).
of
(
0
f
);
Cue
seventhCue
=
getOnlyCueAtTimeUs
(
subtitle
,
70_000_000
);
assertThat
(
seventhCue
.
shearDegrees
).
isWithin
(
0.01f
).
of
(-
90
f
);
Cue
eighthCue
=
getOnlyCueAtTimeUs
(
subtitle
,
80_000_000
);
assertThat
(
eighthCue
.
shearDegrees
).
isWithin
(
0.01f
).
of
(
90
f
);
}
private
static
Spanned
getOnlyCueTextAtTimeUs
(
Subtitle
subtitle
,
long
timeUs
)
{
private
static
Spanned
getOnlyCueTextAtTimeUs
(
Subtitle
subtitle
,
long
timeUs
)
{
Cue
cue
=
getOnlyCueAtTimeUs
(
subtitle
,
timeUs
);
Cue
cue
=
getOnlyCueAtTimeUs
(
subtitle
,
timeUs
);
assertThat
(
cue
.
text
).
isInstanceOf
(
Spanned
.
class
);
assertThat
(
cue
.
text
).
isInstanceOf
(
Spanned
.
class
);
...
...
library/core/src/test/java/com/google/android/exoplayer2/text/ttml/TtmlStyleTest.java
View file @
6603c6bb
...
@@ -49,6 +49,7 @@ public final class TtmlStyleTest {
...
@@ -49,6 +49,7 @@ public final class TtmlStyleTest {
private
static
final
Layout
.
Alignment
TEXT_ALIGN
=
Layout
.
Alignment
.
ALIGN_CENTER
;
private
static
final
Layout
.
Alignment
TEXT_ALIGN
=
Layout
.
Alignment
.
ALIGN_CENTER
;
private
static
final
boolean
TEXT_COMBINE
=
true
;
private
static
final
boolean
TEXT_COMBINE
=
true
;
public
static
final
String
TEXT_EMPHASIS_STYLE
=
"dot before"
;
public
static
final
String
TEXT_EMPHASIS_STYLE
=
"dot before"
;
public
static
final
float
SHEAR_PERCENTAGE
=
16
f
;
private
final
TtmlStyle
populatedStyle
=
private
final
TtmlStyle
populatedStyle
=
new
TtmlStyle
()
new
TtmlStyle
()
...
@@ -66,7 +67,8 @@ public final class TtmlStyleTest {
...
@@ -66,7 +67,8 @@ public final class TtmlStyleTest {
.
setRubyPosition
(
RUBY_POSITION
)
.
setRubyPosition
(
RUBY_POSITION
)
.
setTextAlign
(
TEXT_ALIGN
)
.
setTextAlign
(
TEXT_ALIGN
)
.
setTextCombine
(
TEXT_COMBINE
)
.
setTextCombine
(
TEXT_COMBINE
)
.
setTextEmphasis
(
TextEmphasis
.
parse
(
TEXT_EMPHASIS_STYLE
));
.
setTextEmphasis
(
TextEmphasis
.
parse
(
TEXT_EMPHASIS_STYLE
))
.
setShearPercentage
(
SHEAR_PERCENTAGE
);
@Test
@Test
public
void
inheritStyle
()
{
public
void
inheritStyle
()
{
...
@@ -94,6 +96,7 @@ public final class TtmlStyleTest {
...
@@ -94,6 +96,7 @@ public final class TtmlStyleTest {
assertThat
(
style
.
getTextEmphasis
().
markShape
).
isEqualTo
(
TextEmphasisSpan
.
MARK_SHAPE_DOT
);
assertThat
(
style
.
getTextEmphasis
().
markShape
).
isEqualTo
(
TextEmphasisSpan
.
MARK_SHAPE_DOT
);
assertThat
(
style
.
getTextEmphasis
().
markFill
).
isEqualTo
(
TextEmphasisSpan
.
MARK_FILL_FILLED
);
assertThat
(
style
.
getTextEmphasis
().
markFill
).
isEqualTo
(
TextEmphasisSpan
.
MARK_FILL_FILLED
);
assertThat
(
style
.
getTextEmphasis
().
position
).
isEqualTo
(
POSITION_BEFORE
);
assertThat
(
style
.
getTextEmphasis
().
position
).
isEqualTo
(
POSITION_BEFORE
);
assertThat
(
style
.
getShearPercentage
()).
isEqualTo
(
SHEAR_PERCENTAGE
);
}
}
@Test
@Test
...
@@ -121,6 +124,7 @@ public final class TtmlStyleTest {
...
@@ -121,6 +124,7 @@ public final class TtmlStyleTest {
assertThat
(
style
.
getTextEmphasis
().
markShape
).
isEqualTo
(
TextEmphasisSpan
.
MARK_SHAPE_DOT
);
assertThat
(
style
.
getTextEmphasis
().
markShape
).
isEqualTo
(
TextEmphasisSpan
.
MARK_SHAPE_DOT
);
assertThat
(
style
.
getTextEmphasis
().
markFill
).
isEqualTo
(
TextEmphasisSpan
.
MARK_FILL_FILLED
);
assertThat
(
style
.
getTextEmphasis
().
markFill
).
isEqualTo
(
TextEmphasisSpan
.
MARK_FILL_FILLED
);
assertThat
(
style
.
getTextEmphasis
().
position
).
isEqualTo
(
POSITION_BEFORE
);
assertThat
(
style
.
getTextEmphasis
().
position
).
isEqualTo
(
POSITION_BEFORE
);
assertThat
(
style
.
getShearPercentage
()).
isEqualTo
(
SHEAR_PERCENTAGE
);
}
}
@Test
@Test
...
@@ -267,4 +271,16 @@ public final class TtmlStyleTest {
...
@@ -267,4 +271,16 @@ public final class TtmlStyleTest {
assertThat
(
style
.
getTextEmphasis
().
markFill
).
isEqualTo
(
TextEmphasisSpan
.
MARK_FILL_OPEN
);
assertThat
(
style
.
getTextEmphasis
().
markFill
).
isEqualTo
(
TextEmphasisSpan
.
MARK_FILL_OPEN
);
assertThat
(
style
.
getTextEmphasis
().
position
).
isEqualTo
(
TextAnnotation
.
POSITION_AFTER
);
assertThat
(
style
.
getTextEmphasis
().
position
).
isEqualTo
(
TextAnnotation
.
POSITION_AFTER
);
}
}
@Test
public
void
shear
()
{
TtmlStyle
style
=
new
TtmlStyle
();
assertThat
(
style
.
getShearPercentage
()).
isEqualTo
(
TtmlStyle
.
UNSPECIFIED_SHEAR
);
style
.
setShearPercentage
(
101
f
);
assertThat
(
style
.
getShearPercentage
()).
isEqualTo
(
101
f
);
style
.
setShearPercentage
(-
200
f
);
assertThat
(
style
.
getShearPercentage
()).
isEqualTo
(-
200
f
);
style
.
setShearPercentage
(
0.1f
);
assertThat
(
style
.
getShearPercentage
()).
isEqualTo
(
0.1f
);
}
}
}
library/ui/src/main/java/com/google/android/exoplayer2/ui/WebViewSubtitleOutput.java
View file @
6603c6bb
...
@@ -286,7 +286,8 @@ import java.util.Map;
...
@@ -286,7 +286,8 @@ import java.util.Map;
+
"writing-mode:%s;"
+
"writing-mode:%s;"
+
"font-size:%s;"
+
"font-size:%s;"
+
"background-color:%s;"
+
"background-color:%s;"
+
"transform:translate(%s%%,%s%%);"
+
"transform:translate(%s%%,%s%%)"
+
"%s;"
+
"'>"
,
+
"'>"
,
/* z-index */
i
,
/* z-index */
i
,
positionProperty
,
positionProperty
,
...
@@ -300,7 +301,8 @@ import java.util.Map;
...
@@ -300,7 +301,8 @@ import java.util.Map;
cueTextSizeCssPx
,
cueTextSizeCssPx
,
windowCssColor
,
windowCssColor
,
horizontalTranslatePercent
,
horizontalTranslatePercent
,
verticalTranslatePercent
))
verticalTranslatePercent
,
getBlockShearTransformFunction
(
cue
)))
.
append
(
Util
.
formatInvariant
(
"<span class='%s'>"
,
DEFAULT_BACKGROUND_CSS_CLASS
))
.
append
(
Util
.
formatInvariant
(
"<span class='%s'>"
,
DEFAULT_BACKGROUND_CSS_CLASS
))
.
append
(
htmlAndCss
.
html
)
.
append
(
htmlAndCss
.
html
)
.
append
(
"</span>"
)
.
append
(
"</span>"
)
...
@@ -322,6 +324,17 @@ import java.util.Map;
...
@@ -322,6 +324,17 @@ import java.util.Map;
"base64"
);
"base64"
);
}
}
private
static
String
getBlockShearTransformFunction
(
Cue
cue
)
{
if
(
cue
.
shearDegrees
!=
0.0f
)
{
String
direction
=
(
cue
.
verticalType
==
Cue
.
VERTICAL_TYPE_LR
||
cue
.
verticalType
==
Cue
.
VERTICAL_TYPE_RL
)
?
"skewY"
:
"skewX"
;
return
Util
.
formatInvariant
(
"%s(%.2fdeg)"
,
direction
,
cue
.
shearDegrees
);
}
return
""
;
}
/**
/**
* Converts a text size to a CSS px value.
* Converts a text size to a CSS px value.
*
*
...
...
testdata/src/test/assets/media/ttml/shear.xml
0 → 100644
View file @
6603c6bb
<tt
xmlns:ttm=
"http://www.w3.org/2006/10/ttaf1#metadata"
xmlns:ttp=
"http://www.w3.org/2006/10/ttaf1#parameter"
xmlns:tts=
"http://www.w3.org/2006/10/ttaf1#style"
xmlns=
"http://www.w3.org/ns/ttml"
xmlns=
"http://www.w3.org/2006/10/ttaf1"
>
<body>
<div>
<p
begin=
"10s"
end=
"18s"
tts:shear=
"0%"
>
0%
</p>
</div>
<div>
<p
begin=
"20s"
end=
"28s"
tts:shear=
"16.67%"
>
16.67%
</p>
</div>
<div>
<p
begin=
"30s"
end=
"38s"
tts:shear=
"-16.67%"
>
-16.67%
</p>
</div>
<div>
<p
begin=
"40s"
end=
"48s"
tts:shear=
"+16.67%"
>
+16.67%
</p>
</div>
<div>
<p
begin=
"50s"
end=
"58s"
tts:shear=
"+25%"
>
+25%
</p>
</div>
<div>
<p
begin=
"60s"
end=
"68s"
tts:shear=
"Invalid"
>
Invalid
</p>
</div>
<div>
<p
begin=
"70s"
end=
"78s"
tts:shear=
"101.01%"
>
100.01%
</p>
</div>
<div>
<p
begin=
"80s"
end=
"88s"
tts:shear=
"-101.1%"
>
-101.1%
</p>
</div>
</body>
</tt>
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