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
37908dd4
authored
Jan 20, 2020
by
ibaker
Committed by
Ian Baker
Jan 24, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Remove TTML package from null-checking blacklist
PiperOrigin-RevId: 290629644
parent
8a2a5271
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
107 additions
and
68 deletions
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/TtmlRenderUtil.java
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlDecoder.java
View file @
37908dd4
...
@@ -16,11 +16,13 @@
...
@@ -16,11 +16,13 @@
package
com
.
google
.
android
.
exoplayer2
.
text
.
ttml
;
package
com
.
google
.
android
.
exoplayer2
.
text
.
ttml
;
import
android.text.Layout
;
import
android.text.Layout
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.C
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.Cue
;
import
com.google.android.exoplayer2.text.SimpleSubtitleDecoder
;
import
com.google.android.exoplayer2.text.SimpleSubtitleDecoder
;
import
com.google.android.exoplayer2.text.Subtitle
;
import
com.google.android.exoplayer2.text.Subtitle
;
import
com.google.android.exoplayer2.text.SubtitleDecoderException
;
import
com.google.android.exoplayer2.text.SubtitleDecoderException
;
import
com.google.android.exoplayer2.util.Assertions
;
import
com.google.android.exoplayer2.util.ColorParser
;
import
com.google.android.exoplayer2.util.ColorParser
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Log
;
import
com.google.android.exoplayer2.util.Util
;
import
com.google.android.exoplayer2.util.Util
;
...
@@ -32,6 +34,7 @@ import java.util.HashMap;
...
@@ -32,6 +34,7 @@ import java.util.HashMap;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.regex.Matcher
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
java.util.regex.Pattern
;
import
org.checkerframework.checker.nullness.qual.PolyNull
;
import
org.xmlpull.v1.XmlPullParser
;
import
org.xmlpull.v1.XmlPullParser
;
import
org.xmlpull.v1.XmlPullParserException
;
import
org.xmlpull.v1.XmlPullParserException
;
import
org.xmlpull.v1.XmlPullParserFactory
;
import
org.xmlpull.v1.XmlPullParserFactory
;
...
@@ -110,18 +113,18 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -110,18 +113,18 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
Map
<
String
,
TtmlStyle
>
globalStyles
=
new
HashMap
<>();
Map
<
String
,
TtmlStyle
>
globalStyles
=
new
HashMap
<>();
Map
<
String
,
TtmlRegion
>
regionMap
=
new
HashMap
<>();
Map
<
String
,
TtmlRegion
>
regionMap
=
new
HashMap
<>();
Map
<
String
,
String
>
imageMap
=
new
HashMap
<>();
Map
<
String
,
String
>
imageMap
=
new
HashMap
<>();
regionMap
.
put
(
TtmlNode
.
ANONYMOUS_REGION_ID
,
new
TtmlRegion
(
null
));
regionMap
.
put
(
TtmlNode
.
ANONYMOUS_REGION_ID
,
new
TtmlRegion
(
TtmlNode
.
ANONYMOUS_REGION_ID
));
ByteArrayInputStream
inputStream
=
new
ByteArrayInputStream
(
bytes
,
0
,
length
);
ByteArrayInputStream
inputStream
=
new
ByteArrayInputStream
(
bytes
,
0
,
length
);
xmlParser
.
setInput
(
inputStream
,
null
);
xmlParser
.
setInput
(
inputStream
,
null
);
TtmlSubtitle
ttmlSubtitle
=
null
;
@Nullable
TtmlSubtitle
ttmlSubtitle
=
null
;
ArrayDeque
<
TtmlNode
>
nodeStack
=
new
ArrayDeque
<>();
ArrayDeque
<
TtmlNode
>
nodeStack
=
new
ArrayDeque
<>();
int
unsupportedNodeDepth
=
0
;
int
unsupportedNodeDepth
=
0
;
int
eventType
=
xmlParser
.
getEventType
();
int
eventType
=
xmlParser
.
getEventType
();
FrameAndTickRate
frameAndTickRate
=
DEFAULT_FRAME_AND_TICK_RATE
;
FrameAndTickRate
frameAndTickRate
=
DEFAULT_FRAME_AND_TICK_RATE
;
CellResolution
cellResolution
=
DEFAULT_CELL_RESOLUTION
;
CellResolution
cellResolution
=
DEFAULT_CELL_RESOLUTION
;
TtsExtent
ttsExtent
=
null
;
@Nullable
TtsExtent
ttsExtent
=
null
;
while
(
eventType
!=
XmlPullParser
.
END_DOCUMENT
)
{
while
(
eventType
!=
XmlPullParser
.
END_DOCUMENT
)
{
TtmlNode
parent
=
nodeStack
.
peek
();
@Nullable
TtmlNode
parent
=
nodeStack
.
peek
();
if
(
unsupportedNodeDepth
==
0
)
{
if
(
unsupportedNodeDepth
==
0
)
{
String
name
=
xmlParser
.
getName
();
String
name
=
xmlParser
.
getName
();
if
(
eventType
==
XmlPullParser
.
START_TAG
)
{
if
(
eventType
==
XmlPullParser
.
START_TAG
)
{
...
@@ -149,10 +152,12 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -149,10 +152,12 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
}
}
}
}
}
else
if
(
eventType
==
XmlPullParser
.
TEXT
)
{
}
else
if
(
eventType
==
XmlPullParser
.
TEXT
)
{
parent
.
addChild
(
TtmlNode
.
buildTextNode
(
xmlParser
.
getText
()));
Assertions
.
checkNotNull
(
parent
)
.
addChild
(
TtmlNode
.
buildTextNode
(
xmlParser
.
getText
()));
}
else
if
(
eventType
==
XmlPullParser
.
END_TAG
)
{
}
else
if
(
eventType
==
XmlPullParser
.
END_TAG
)
{
if
(
xmlParser
.
getName
().
equals
(
TtmlNode
.
TAG_TT
))
{
if
(
xmlParser
.
getName
().
equals
(
TtmlNode
.
TAG_TT
))
{
ttmlSubtitle
=
new
TtmlSubtitle
(
nodeStack
.
peek
(),
globalStyles
,
regionMap
,
imageMap
);
ttmlSubtitle
=
new
TtmlSubtitle
(
Assertions
.
checkNotNull
(
nodeStack
.
peek
()),
globalStyles
,
regionMap
,
imageMap
);
}
}
nodeStack
.
pop
();
nodeStack
.
pop
();
}
}
...
@@ -166,7 +171,11 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -166,7 +171,11 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
xmlParser
.
next
();
xmlParser
.
next
();
eventType
=
xmlParser
.
getEventType
();
eventType
=
xmlParser
.
getEventType
();
}
}
if
(
ttmlSubtitle
!=
null
)
{
return
ttmlSubtitle
;
return
ttmlSubtitle
;
}
else
{
throw
new
SubtitleDecoderException
(
"No TTML subtitles found"
);
}
}
catch
(
XmlPullParserException
xppe
)
{
}
catch
(
XmlPullParserException
xppe
)
{
throw
new
SubtitleDecoderException
(
"Unable to decode source"
,
xppe
);
throw
new
SubtitleDecoderException
(
"Unable to decode source"
,
xppe
);
}
catch
(
IOException
e
)
{
}
catch
(
IOException
e
)
{
...
@@ -221,8 +230,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -221,8 +230,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
return
defaultValue
;
return
defaultValue
;
}
}
try
{
try
{
int
columns
=
Integer
.
parseInt
(
cellResolutionMatcher
.
group
(
1
));
int
columns
=
Integer
.
parseInt
(
Assertions
.
checkNotNull
(
cellResolutionMatcher
.
group
(
1
)
));
int
rows
=
Integer
.
parseInt
(
cellResolutionMatcher
.
group
(
2
));
int
rows
=
Integer
.
parseInt
(
Assertions
.
checkNotNull
(
cellResolutionMatcher
.
group
(
2
)
));
if
(
columns
==
0
||
rows
==
0
)
{
if
(
columns
==
0
||
rows
==
0
)
{
throw
new
SubtitleDecoderException
(
"Invalid cell resolution "
+
columns
+
" "
+
rows
);
throw
new
SubtitleDecoderException
(
"Invalid cell resolution "
+
columns
+
" "
+
rows
);
}
}
...
@@ -233,7 +242,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -233,7 +242,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
}
}
}
}
@Nullable
private
TtsExtent
parseTtsExtent
(
XmlPullParser
xmlParser
)
{
private
TtsExtent
parseTtsExtent
(
XmlPullParser
xmlParser
)
{
@Nullable
String
ttsExtent
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_EXTENT
);
String
ttsExtent
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_EXTENT
);
if
(
ttsExtent
==
null
)
{
if
(
ttsExtent
==
null
)
{
return
null
;
return
null
;
...
@@ -245,8 +256,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -245,8 +256,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
return
null
;
return
null
;
}
}
try
{
try
{
int
width
=
Integer
.
parseInt
(
extentMatcher
.
group
(
1
));
int
width
=
Integer
.
parseInt
(
Assertions
.
checkNotNull
(
extentMatcher
.
group
(
1
)
));
int
height
=
Integer
.
parseInt
(
extentMatcher
.
group
(
2
));
int
height
=
Integer
.
parseInt
(
Assertions
.
checkNotNull
(
extentMatcher
.
group
(
2
)
));
return
new
TtsExtent
(
width
,
height
);
return
new
TtsExtent
(
width
,
height
);
}
catch
(
NumberFormatException
e
)
{
}
catch
(
NumberFormatException
e
)
{
Log
.
w
(
TAG
,
"Ignoring malformed tts extent: "
+
ttsExtent
);
Log
.
w
(
TAG
,
"Ignoring malformed tts extent: "
+
ttsExtent
);
...
@@ -258,24 +269,26 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -258,24 +269,26 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
XmlPullParser
xmlParser
,
XmlPullParser
xmlParser
,
Map
<
String
,
TtmlStyle
>
globalStyles
,
Map
<
String
,
TtmlStyle
>
globalStyles
,
CellResolution
cellResolution
,
CellResolution
cellResolution
,
TtsExtent
ttsExtent
,
@Nullable
TtsExtent
ttsExtent
,
Map
<
String
,
TtmlRegion
>
globalRegions
,
Map
<
String
,
TtmlRegion
>
globalRegions
,
Map
<
String
,
String
>
imageMap
)
Map
<
String
,
String
>
imageMap
)
throws
IOException
,
XmlPullParserException
{
throws
IOException
,
XmlPullParserException
{
do
{
do
{
xmlParser
.
next
();
xmlParser
.
next
();
if
(
XmlPullParserUtil
.
isStartTag
(
xmlParser
,
TtmlNode
.
TAG_STYLE
))
{
if
(
XmlPullParserUtil
.
isStartTag
(
xmlParser
,
TtmlNode
.
TAG_STYLE
))
{
String
parentStyleId
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
ATTR_STYLE
);
@Nullable
String
parentStyleId
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
ATTR_STYLE
);
TtmlStyle
style
=
parseStyleAttributes
(
xmlParser
,
new
TtmlStyle
());
TtmlStyle
style
=
parseStyleAttributes
(
xmlParser
,
new
TtmlStyle
());
if
(
parentStyleId
!=
null
)
{
if
(
parentStyleId
!=
null
)
{
for
(
String
id
:
parseStyleIds
(
parentStyleId
))
{
for
(
String
id
:
parseStyleIds
(
parentStyleId
))
{
style
.
chain
(
globalStyles
.
get
(
id
));
style
.
chain
(
globalStyles
.
get
(
id
));
}
}
}
}
if
(
style
.
getId
()
!=
null
)
{
String
styleId
=
style
.
getId
();
globalStyles
.
put
(
style
.
getId
(),
style
);
if
(
styleId
!=
null
)
{
globalStyles
.
put
(
styleId
,
style
);
}
}
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xmlParser
,
TtmlNode
.
TAG_REGION
))
{
}
else
if
(
XmlPullParserUtil
.
isStartTag
(
xmlParser
,
TtmlNode
.
TAG_REGION
))
{
@Nullable
TtmlRegion
ttmlRegion
=
parseRegionAttributes
(
xmlParser
,
cellResolution
,
ttsExtent
);
TtmlRegion
ttmlRegion
=
parseRegionAttributes
(
xmlParser
,
cellResolution
,
ttsExtent
);
if
(
ttmlRegion
!=
null
)
{
if
(
ttmlRegion
!=
null
)
{
globalRegions
.
put
(
ttmlRegion
.
id
,
ttmlRegion
);
globalRegions
.
put
(
ttmlRegion
.
id
,
ttmlRegion
);
...
@@ -292,7 +305,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -292,7 +305,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
do
{
do
{
xmlParser
.
next
();
xmlParser
.
next
();
if
(
XmlPullParserUtil
.
isStartTag
(
xmlParser
,
TtmlNode
.
TAG_IMAGE
))
{
if
(
XmlPullParserUtil
.
isStartTag
(
xmlParser
,
TtmlNode
.
TAG_IMAGE
))
{
String
id
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
"id"
);
@Nullable
String
id
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
"id"
);
if
(
id
!=
null
)
{
if
(
id
!=
null
)
{
String
encodedBitmapData
=
xmlParser
.
nextText
();
String
encodedBitmapData
=
xmlParser
.
nextText
();
imageMap
.
put
(
id
,
encodedBitmapData
);
imageMap
.
put
(
id
,
encodedBitmapData
);
...
@@ -309,9 +322,10 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -309,9 +322,10 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
* fractions. In case of missing tts:extent the pixel defined regions can't be parsed, and null is
* fractions. In case of missing tts:extent the pixel defined regions can't be parsed, and null is
* returned.
* returned.
*/
*/
@Nullable
private
TtmlRegion
parseRegionAttributes
(
private
TtmlRegion
parseRegionAttributes
(
XmlPullParser
xmlParser
,
CellResolution
cellResolution
,
TtsExtent
ttsExtent
)
{
XmlPullParser
xmlParser
,
CellResolution
cellResolution
,
@Nullable
TtsExtent
ttsExtent
)
{
String
regionId
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_ID
);
@Nullable
String
regionId
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_ID
);
if
(
regionId
==
null
)
{
if
(
regionId
==
null
)
{
return
null
;
return
null
;
}
}
...
@@ -319,14 +333,16 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -319,14 +333,16 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
float
position
;
float
position
;
float
line
;
float
line
;
@Nullable
String
regionOrigin
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_ORIGIN
);
String
regionOrigin
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_ORIGIN
);
if
(
regionOrigin
!=
null
)
{
if
(
regionOrigin
!=
null
)
{
Matcher
originPercentageMatcher
=
PERCENTAGE_COORDINATES
.
matcher
(
regionOrigin
);
Matcher
originPercentageMatcher
=
PERCENTAGE_COORDINATES
.
matcher
(
regionOrigin
);
Matcher
originPixelMatcher
=
PIXEL_COORDINATES
.
matcher
(
regionOrigin
);
Matcher
originPixelMatcher
=
PIXEL_COORDINATES
.
matcher
(
regionOrigin
);
if
(
originPercentageMatcher
.
matches
())
{
if
(
originPercentageMatcher
.
matches
())
{
try
{
try
{
position
=
Float
.
parseFloat
(
originPercentageMatcher
.
group
(
1
))
/
100
f
;
position
=
line
=
Float
.
parseFloat
(
originPercentageMatcher
.
group
(
2
))
/
100
f
;
Float
.
parseFloat
(
Assertions
.
checkNotNull
(
originPercentageMatcher
.
group
(
1
)))
/
100
f
;
line
=
Float
.
parseFloat
(
Assertions
.
checkNotNull
(
originPercentageMatcher
.
group
(
2
)))
/
100
f
;
}
catch
(
NumberFormatException
e
)
{
}
catch
(
NumberFormatException
e
)
{
Log
.
w
(
TAG
,
"Ignoring region with malformed origin: "
+
regionOrigin
);
Log
.
w
(
TAG
,
"Ignoring region with malformed origin: "
+
regionOrigin
);
return
null
;
return
null
;
...
@@ -337,8 +353,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -337,8 +353,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
return
null
;
return
null
;
}
}
try
{
try
{
int
width
=
Integer
.
parseInt
(
originPixelMatcher
.
group
(
1
));
int
width
=
Integer
.
parseInt
(
Assertions
.
checkNotNull
(
originPixelMatcher
.
group
(
1
)
));
int
height
=
Integer
.
parseInt
(
originPixelMatcher
.
group
(
2
));
int
height
=
Integer
.
parseInt
(
Assertions
.
checkNotNull
(
originPixelMatcher
.
group
(
2
)
));
// Convert pixel values to fractions.
// Convert pixel values to fractions.
position
=
width
/
(
float
)
ttsExtent
.
width
;
position
=
width
/
(
float
)
ttsExtent
.
width
;
line
=
height
/
(
float
)
ttsExtent
.
height
;
line
=
height
/
(
float
)
ttsExtent
.
height
;
...
@@ -362,14 +378,17 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -362,14 +378,17 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
float
width
;
float
width
;
float
height
;
float
height
;
@Nullable
String
regionExtent
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_EXTENT
);
String
regionExtent
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_EXTENT
);
if
(
regionExtent
!=
null
)
{
if
(
regionExtent
!=
null
)
{
Matcher
extentPercentageMatcher
=
PERCENTAGE_COORDINATES
.
matcher
(
regionExtent
);
Matcher
extentPercentageMatcher
=
PERCENTAGE_COORDINATES
.
matcher
(
regionExtent
);
Matcher
extentPixelMatcher
=
PIXEL_COORDINATES
.
matcher
(
regionExtent
);
Matcher
extentPixelMatcher
=
PIXEL_COORDINATES
.
matcher
(
regionExtent
);
if
(
extentPercentageMatcher
.
matches
())
{
if
(
extentPercentageMatcher
.
matches
())
{
try
{
try
{
width
=
Float
.
parseFloat
(
extentPercentageMatcher
.
group
(
1
))
/
100
f
;
width
=
height
=
Float
.
parseFloat
(
extentPercentageMatcher
.
group
(
2
))
/
100
f
;
Float
.
parseFloat
(
Assertions
.
checkNotNull
(
extentPercentageMatcher
.
group
(
1
)))
/
100
f
;
height
=
Float
.
parseFloat
(
Assertions
.
checkNotNull
(
extentPercentageMatcher
.
group
(
2
)))
/
100
f
;
}
catch
(
NumberFormatException
e
)
{
}
catch
(
NumberFormatException
e
)
{
Log
.
w
(
TAG
,
"Ignoring region with malformed extent: "
+
regionOrigin
);
Log
.
w
(
TAG
,
"Ignoring region with malformed extent: "
+
regionOrigin
);
return
null
;
return
null
;
...
@@ -380,8 +399,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -380,8 +399,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
return
null
;
return
null
;
}
}
try
{
try
{
int
extentWidth
=
Integer
.
parseInt
(
extentPixelMatcher
.
group
(
1
));
int
extentWidth
=
Integer
.
parseInt
(
Assertions
.
checkNotNull
(
extentPixelMatcher
.
group
(
1
)
));
int
extentHeight
=
Integer
.
parseInt
(
extentPixelMatcher
.
group
(
2
));
int
extentHeight
=
Integer
.
parseInt
(
Assertions
.
checkNotNull
(
extentPixelMatcher
.
group
(
2
)
));
// Convert pixel values to fractions.
// Convert pixel values to fractions.
width
=
extentWidth
/
(
float
)
ttsExtent
.
width
;
width
=
extentWidth
/
(
float
)
ttsExtent
.
width
;
height
=
extentHeight
/
(
float
)
ttsExtent
.
height
;
height
=
extentHeight
/
(
float
)
ttsExtent
.
height
;
...
@@ -404,8 +423,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -404,8 +423,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
}
}
@Cue
.
AnchorType
int
lineAnchor
=
Cue
.
ANCHOR_TYPE_START
;
@Cue
.
AnchorType
int
lineAnchor
=
Cue
.
ANCHOR_TYPE_START
;
String
displayAlign
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
@Nullable
TtmlNode
.
ATTR_TTS_DISPLAY_ALIGN
);
String
displayAlign
=
XmlPullParserUtil
.
getAttributeValue
(
xmlParser
,
TtmlNode
.
ATTR_TTS_DISPLAY_ALIGN
);
if
(
displayAlign
!=
null
)
{
if
(
displayAlign
!=
null
)
{
switch
(
Util
.
toLowerInvariant
(
displayAlign
))
{
switch
(
Util
.
toLowerInvariant
(
displayAlign
))
{
case
"center"
:
case
"center"
:
...
@@ -440,7 +460,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -440,7 +460,8 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
return
parentStyleIds
.
isEmpty
()
?
new
String
[
0
]
:
Util
.
split
(
parentStyleIds
,
"\\s+"
);
return
parentStyleIds
.
isEmpty
()
?
new
String
[
0
]
:
Util
.
split
(
parentStyleIds
,
"\\s+"
);
}
}
private
TtmlStyle
parseStyleAttributes
(
XmlPullParser
parser
,
TtmlStyle
style
)
{
@PolyNull
private
TtmlStyle
parseStyleAttributes
(
XmlPullParser
parser
,
@PolyNull
TtmlStyle
style
)
{
int
attributeCount
=
parser
.
getAttributeCount
();
int
attributeCount
=
parser
.
getAttributeCount
();
for
(
int
i
=
0
;
i
<
attributeCount
;
i
++)
{
for
(
int
i
=
0
;
i
<
attributeCount
;
i
++)
{
String
attributeValue
=
parser
.
getAttributeValue
(
i
);
String
attributeValue
=
parser
.
getAttributeValue
(
i
);
...
@@ -527,21 +548,24 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -527,21 +548,24 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
return
style
;
return
style
;
}
}
private
TtmlStyle
createIfNull
(
TtmlStyle
style
)
{
private
TtmlStyle
createIfNull
(
@Nullable
TtmlStyle
style
)
{
return
style
==
null
?
new
TtmlStyle
()
:
style
;
return
style
==
null
?
new
TtmlStyle
()
:
style
;
}
}
private
TtmlNode
parseNode
(
XmlPullParser
parser
,
TtmlNode
parent
,
private
TtmlNode
parseNode
(
Map
<
String
,
TtmlRegion
>
regionMap
,
FrameAndTickRate
frameAndTickRate
)
XmlPullParser
parser
,
@Nullable
TtmlNode
parent
,
Map
<
String
,
TtmlRegion
>
regionMap
,
FrameAndTickRate
frameAndTickRate
)
throws
SubtitleDecoderException
{
throws
SubtitleDecoderException
{
long
duration
=
C
.
TIME_UNSET
;
long
duration
=
C
.
TIME_UNSET
;
long
startTime
=
C
.
TIME_UNSET
;
long
startTime
=
C
.
TIME_UNSET
;
long
endTime
=
C
.
TIME_UNSET
;
long
endTime
=
C
.
TIME_UNSET
;
String
regionId
=
TtmlNode
.
ANONYMOUS_REGION_ID
;
String
regionId
=
TtmlNode
.
ANONYMOUS_REGION_ID
;
String
imageId
=
null
;
@Nullable
String
imageId
=
null
;
String
[]
styleIds
=
null
;
@Nullable
String
[]
styleIds
=
null
;
int
attributeCount
=
parser
.
getAttributeCount
();
int
attributeCount
=
parser
.
getAttributeCount
();
TtmlStyle
style
=
parseStyleAttributes
(
parser
,
null
);
@Nullable
TtmlStyle
style
=
parseStyleAttributes
(
parser
,
null
);
for
(
int
i
=
0
;
i
<
attributeCount
;
i
++)
{
for
(
int
i
=
0
;
i
<
attributeCount
;
i
++)
{
String
attr
=
parser
.
getAttributeName
(
i
);
String
attr
=
parser
.
getAttributeName
(
i
);
String
value
=
parser
.
getAttributeValue
(
i
);
String
value
=
parser
.
getAttributeValue
(
i
);
...
@@ -636,7 +660,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -636,7 +660,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
}
}
if
(
matcher
.
matches
())
{
if
(
matcher
.
matches
())
{
String
unit
=
matcher
.
group
(
3
);
String
unit
=
Assertions
.
checkNotNull
(
matcher
.
group
(
3
)
);
switch
(
unit
)
{
switch
(
unit
)
{
case
"px"
:
case
"px"
:
out
.
setFontSizeUnit
(
TtmlStyle
.
FONT_SIZE_UNIT_PIXEL
);
out
.
setFontSizeUnit
(
TtmlStyle
.
FONT_SIZE_UNIT_PIXEL
);
...
@@ -650,7 +674,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -650,7 +674,7 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
default
:
default
:
throw
new
SubtitleDecoderException
(
"Invalid unit for fontSize: '"
+
unit
+
"'."
);
throw
new
SubtitleDecoderException
(
"Invalid unit for fontSize: '"
+
unit
+
"'."
);
}
}
out
.
setFontSize
(
Float
.
valueOf
(
matcher
.
group
(
1
)));
out
.
setFontSize
(
Float
.
parseFloat
(
Assertions
.
checkNotNull
(
matcher
.
group
(
1
)
)));
}
else
{
}
else
{
throw
new
SubtitleDecoderException
(
"Invalid expression for fontSize: '"
+
expression
+
"'."
);
throw
new
SubtitleDecoderException
(
"Invalid expression for fontSize: '"
+
expression
+
"'."
);
}
}
...
@@ -671,18 +695,18 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -671,18 +695,18 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
throws
SubtitleDecoderException
{
throws
SubtitleDecoderException
{
Matcher
matcher
=
CLOCK_TIME
.
matcher
(
time
);
Matcher
matcher
=
CLOCK_TIME
.
matcher
(
time
);
if
(
matcher
.
matches
())
{
if
(
matcher
.
matches
())
{
String
hours
=
matcher
.
group
(
1
);
String
hours
=
Assertions
.
checkNotNull
(
matcher
.
group
(
1
)
);
double
durationSeconds
=
Long
.
parseLong
(
hours
)
*
3600
;
double
durationSeconds
=
Long
.
parseLong
(
hours
)
*
3600
;
String
minutes
=
matcher
.
group
(
2
);
String
minutes
=
Assertions
.
checkNotNull
(
matcher
.
group
(
2
)
);
durationSeconds
+=
Long
.
parseLong
(
minutes
)
*
60
;
durationSeconds
+=
Long
.
parseLong
(
minutes
)
*
60
;
String
seconds
=
matcher
.
group
(
3
);
String
seconds
=
Assertions
.
checkNotNull
(
matcher
.
group
(
3
)
);
durationSeconds
+=
Long
.
parseLong
(
seconds
);
durationSeconds
+=
Long
.
parseLong
(
seconds
);
String
fraction
=
matcher
.
group
(
4
);
@Nullable
String
fraction
=
matcher
.
group
(
4
);
durationSeconds
+=
(
fraction
!=
null
)
?
Double
.
parseDouble
(
fraction
)
:
0
;
durationSeconds
+=
(
fraction
!=
null
)
?
Double
.
parseDouble
(
fraction
)
:
0
;
String
frames
=
matcher
.
group
(
5
);
@Nullable
String
frames
=
matcher
.
group
(
5
);
durationSeconds
+=
(
frames
!=
null
)
durationSeconds
+=
(
frames
!=
null
)
?
Long
.
parseLong
(
frames
)
/
frameAndTickRate
.
effectiveFrameRate
:
0
;
?
Long
.
parseLong
(
frames
)
/
frameAndTickRate
.
effectiveFrameRate
:
0
;
String
subframes
=
matcher
.
group
(
6
);
@Nullable
String
subframes
=
matcher
.
group
(
6
);
durationSeconds
+=
(
subframes
!=
null
)
durationSeconds
+=
(
subframes
!=
null
)
?
((
double
)
Long
.
parseLong
(
subframes
))
/
frameAndTickRate
.
subFrameRate
?
((
double
)
Long
.
parseLong
(
subframes
))
/
frameAndTickRate
.
subFrameRate
/
frameAndTickRate
.
effectiveFrameRate
/
frameAndTickRate
.
effectiveFrameRate
...
@@ -691,9 +715,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
...
@@ -691,9 +715,9 @@ public final class TtmlDecoder extends SimpleSubtitleDecoder {
}
}
matcher
=
OFFSET_TIME
.
matcher
(
time
);
matcher
=
OFFSET_TIME
.
matcher
(
time
);
if
(
matcher
.
matches
())
{
if
(
matcher
.
matches
())
{
String
timeValue
=
matcher
.
group
(
1
);
String
timeValue
=
Assertions
.
checkNotNull
(
matcher
.
group
(
1
)
);
double
offsetSeconds
=
Double
.
parseDouble
(
timeValue
);
double
offsetSeconds
=
Double
.
parseDouble
(
timeValue
);
String
unit
=
matcher
.
group
(
2
);
String
unit
=
Assertions
.
checkNotNull
(
matcher
.
group
(
2
)
);
switch
(
unit
)
{
switch
(
unit
)
{
case
"h"
:
case
"h"
:
offsetSeconds
*=
3600
;
offsetSeconds
*=
3600
;
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlNode.java
View file @
37908dd4
...
@@ -31,6 +31,7 @@ import java.util.Map;
...
@@ -31,6 +31,7 @@ import java.util.Map;
import
java.util.Map.Entry
;
import
java.util.Map.Entry
;
import
java.util.TreeMap
;
import
java.util.TreeMap
;
import
java.util.TreeSet
;
import
java.util.TreeSet
;
import
org.checkerframework.checker.nullness.qual.MonotonicNonNull
;
/**
/**
* A package internal representation of TTML node.
* A package internal representation of TTML node.
...
@@ -93,7 +94,7 @@ import java.util.TreeSet;
...
@@ -93,7 +94,7 @@ import java.util.TreeSet;
private
final
HashMap
<
String
,
Integer
>
nodeStartsByRegion
;
private
final
HashMap
<
String
,
Integer
>
nodeStartsByRegion
;
private
final
HashMap
<
String
,
Integer
>
nodeEndsByRegion
;
private
final
HashMap
<
String
,
Integer
>
nodeEndsByRegion
;
private
List
<
TtmlNode
>
children
;
@MonotonicNonNull
private
List
<
TtmlNode
>
children
;
public
static
TtmlNode
buildTextNode
(
String
text
)
{
public
static
TtmlNode
buildTextNode
(
String
text
)
{
return
new
TtmlNode
(
return
new
TtmlNode
(
...
@@ -196,6 +197,7 @@ import java.util.TreeSet;
...
@@ -196,6 +197,7 @@ import java.util.TreeSet;
}
}
}
}
@Nullable
public
String
[]
getStyleIds
()
{
public
String
[]
getStyleIds
()
{
return
styleIds
;
return
styleIds
;
}
}
...
@@ -217,7 +219,7 @@ import java.util.TreeSet;
...
@@ -217,7 +219,7 @@ import java.util.TreeSet;
// Create image based cues.
// Create image based cues.
for
(
Pair
<
String
,
String
>
regionImagePair
:
regionImageOutputs
)
{
for
(
Pair
<
String
,
String
>
regionImagePair
:
regionImageOutputs
)
{
String
encodedBitmapData
=
imageMap
.
get
(
regionImagePair
.
second
);
@Nullable
String
encodedBitmapData
=
imageMap
.
get
(
regionImagePair
.
second
);
if
(
encodedBitmapData
==
null
)
{
if
(
encodedBitmapData
==
null
)
{
// Image reference points to an invalid image. Do nothing.
// Image reference points to an invalid image. Do nothing.
continue
;
continue
;
...
@@ -225,7 +227,7 @@ import java.util.TreeSet;
...
@@ -225,7 +227,7 @@ import java.util.TreeSet;
byte
[]
bitmapData
=
Base64
.
decode
(
encodedBitmapData
,
Base64
.
DEFAULT
);
byte
[]
bitmapData
=
Base64
.
decode
(
encodedBitmapData
,
Base64
.
DEFAULT
);
Bitmap
bitmap
=
BitmapFactory
.
decodeByteArray
(
bitmapData
,
/* offset= */
0
,
bitmapData
.
length
);
Bitmap
bitmap
=
BitmapFactory
.
decodeByteArray
(
bitmapData
,
/* offset= */
0
,
bitmapData
.
length
);
TtmlRegion
region
=
regionMap
.
get
(
regionImagePair
.
first
);
TtmlRegion
region
=
Assertions
.
checkNotNull
(
regionMap
.
get
(
regionImagePair
.
first
)
);
cues
.
add
(
cues
.
add
(
new
Cue
.
Builder
()
new
Cue
.
Builder
()
...
@@ -241,7 +243,7 @@ import java.util.TreeSet;
...
@@ -241,7 +243,7 @@ import java.util.TreeSet;
// Create text based cues.
// Create text based cues.
for
(
Entry
<
String
,
SpannableStringBuilder
>
entry
:
regionTextOutputs
.
entrySet
())
{
for
(
Entry
<
String
,
SpannableStringBuilder
>
entry
:
regionTextOutputs
.
entrySet
())
{
TtmlRegion
region
=
regionMap
.
get
(
entry
.
getKey
(
));
TtmlRegion
region
=
Assertions
.
checkNotNull
(
regionMap
.
get
(
entry
.
getKey
()
));
cues
.
add
(
cues
.
add
(
new
Cue
(
new
Cue
(
cleanUpText
(
entry
.
getValue
()),
cleanUpText
(
entry
.
getValue
()),
...
@@ -286,7 +288,7 @@ import java.util.TreeSet;
...
@@ -286,7 +288,7 @@ import java.util.TreeSet;
String
resolvedRegionId
=
ANONYMOUS_REGION_ID
.
equals
(
regionId
)
?
inheritedRegion
:
regionId
;
String
resolvedRegionId
=
ANONYMOUS_REGION_ID
.
equals
(
regionId
)
?
inheritedRegion
:
regionId
;
if
(
isTextNode
&&
descendsPNode
)
{
if
(
isTextNode
&&
descendsPNode
)
{
getRegionOutput
(
resolvedRegionId
,
regionOutputs
).
append
(
text
);
getRegionOutput
(
resolvedRegionId
,
regionOutputs
).
append
(
Assertions
.
checkNotNull
(
text
)
);
}
else
if
(
TAG_BR
.
equals
(
tag
)
&&
descendsPNode
)
{
}
else
if
(
TAG_BR
.
equals
(
tag
)
&&
descendsPNode
)
{
getRegionOutput
(
resolvedRegionId
,
regionOutputs
).
append
(
'\n'
);
getRegionOutput
(
resolvedRegionId
,
regionOutputs
).
append
(
'\n'
);
}
else
if
(
isActive
(
timeUs
))
{
}
else
if
(
isActive
(
timeUs
))
{
...
@@ -330,7 +332,7 @@ import java.util.TreeSet;
...
@@ -330,7 +332,7 @@ import java.util.TreeSet;
int
start
=
nodeStartsByRegion
.
containsKey
(
regionId
)
?
nodeStartsByRegion
.
get
(
regionId
)
:
0
;
int
start
=
nodeStartsByRegion
.
containsKey
(
regionId
)
?
nodeStartsByRegion
.
get
(
regionId
)
:
0
;
int
end
=
entry
.
getValue
();
int
end
=
entry
.
getValue
();
if
(
start
!=
end
)
{
if
(
start
!=
end
)
{
SpannableStringBuilder
regionOutput
=
regionOutputs
.
get
(
regionId
);
SpannableStringBuilder
regionOutput
=
Assertions
.
checkNotNull
(
regionOutputs
.
get
(
regionId
)
);
applyStyleToOutput
(
globalStyles
,
regionOutput
,
start
,
end
);
applyStyleToOutput
(
globalStyles
,
regionOutput
,
start
,
end
);
}
}
}
}
...
@@ -344,7 +346,7 @@ import java.util.TreeSet;
...
@@ -344,7 +346,7 @@ import java.util.TreeSet;
SpannableStringBuilder
regionOutput
,
SpannableStringBuilder
regionOutput
,
int
start
,
int
start
,
int
end
)
{
int
end
)
{
TtmlStyle
resolvedStyle
=
TtmlRenderUtil
.
resolveStyle
(
style
,
styleIds
,
globalStyles
);
@Nullable
TtmlStyle
resolvedStyle
=
TtmlRenderUtil
.
resolveStyle
(
style
,
styleIds
,
globalStyles
);
if
(
resolvedStyle
!=
null
)
{
if
(
resolvedStyle
!=
null
)
{
TtmlRenderUtil
.
applyStylesToSpan
(
regionOutput
,
start
,
end
,
resolvedStyle
);
TtmlRenderUtil
.
applyStylesToSpan
(
regionOutput
,
start
,
end
,
resolvedStyle
);
}
}
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlRenderUtil.java
View file @
37908dd4
...
@@ -15,6 +15,7 @@
...
@@ -15,6 +15,7 @@
*/
*/
package
com
.
google
.
android
.
exoplayer2
.
text
.
ttml
;
package
com
.
google
.
android
.
exoplayer2
.
text
.
ttml
;
import
android.text.Layout.Alignment
;
import
android.text.SpannableStringBuilder
;
import
android.text.SpannableStringBuilder
;
import
android.text.Spanned
;
import
android.text.Spanned
;
import
android.text.style.AbsoluteSizeSpan
;
import
android.text.style.AbsoluteSizeSpan
;
...
@@ -26,6 +27,7 @@ import android.text.style.StrikethroughSpan;
...
@@ -26,6 +27,7 @@ import android.text.style.StrikethroughSpan;
import
android.text.style.StyleSpan
;
import
android.text.style.StyleSpan
;
import
android.text.style.TypefaceSpan
;
import
android.text.style.TypefaceSpan
;
import
android.text.style.UnderlineSpan
;
import
android.text.style.UnderlineSpan
;
import
androidx.annotation.Nullable
;
import
com.google.android.exoplayer2.text.SpanUtil
;
import
com.google.android.exoplayer2.text.SpanUtil
;
import
java.util.Map
;
import
java.util.Map
;
...
@@ -34,31 +36,36 @@ import java.util.Map;
...
@@ -34,31 +36,36 @@ import java.util.Map;
*/
*/
/* package */
final
class
TtmlRenderUtil
{
/* package */
final
class
TtmlRenderUtil
{
public
static
TtmlStyle
resolveStyle
(
TtmlStyle
style
,
String
[]
styleIds
,
@Nullable
Map
<
String
,
TtmlStyle
>
globalStyles
)
{
public
static
TtmlStyle
resolveStyle
(
if
(
style
==
null
&&
styleIds
==
null
)
{
@Nullable
TtmlStyle
style
,
@Nullable
String
[]
styleIds
,
Map
<
String
,
TtmlStyle
>
globalStyles
)
{
if
(
style
==
null
)
{
if
(
styleIds
==
null
)
{
// No styles at all.
// No styles at all.
return
null
;
return
null
;
}
else
if
(
style
==
null
&&
styleIds
.
length
==
1
)
{
}
else
if
(
styleIds
.
length
==
1
)
{
// Only one single referential style present.
// Only one single referential style present.
return
globalStyles
.
get
(
styleIds
[
0
]);
return
globalStyles
.
get
(
styleIds
[
0
]);
}
else
if
(
style
==
null
&&
styleIds
.
length
>
1
)
{
}
else
if
(
styleIds
.
length
>
1
)
{
// Only multiple referential styles present.
// Only multiple referential styles present.
TtmlStyle
chainedStyle
=
new
TtmlStyle
();
TtmlStyle
chainedStyle
=
new
TtmlStyle
();
for
(
String
id
:
styleIds
)
{
for
(
String
id
:
styleIds
)
{
chainedStyle
.
chain
(
globalStyles
.
get
(
id
));
chainedStyle
.
chain
(
globalStyles
.
get
(
id
));
}
}
return
chainedStyle
;
return
chainedStyle
;
}
else
if
(
style
!=
null
&&
styleIds
!=
null
&&
styleIds
.
length
==
1
)
{
}
}
else
/* style != null */
{
if
(
styleIds
!=
null
&&
styleIds
.
length
==
1
)
{
// Merge a single referential style into inline style.
// Merge a single referential style into inline style.
return
style
.
chain
(
globalStyles
.
get
(
styleIds
[
0
]));
return
style
.
chain
(
globalStyles
.
get
(
styleIds
[
0
]));
}
else
if
(
style
!=
null
&&
styleIds
!=
null
&&
styleIds
.
length
>
1
)
{
}
else
if
(
styleIds
!=
null
&&
styleIds
.
length
>
1
)
{
// Merge multiple referential styles into inline style.
// Merge multiple referential styles into inline style.
for
(
String
id
:
styleIds
)
{
for
(
String
id
:
styleIds
)
{
style
.
chain
(
globalStyles
.
get
(
id
));
style
.
chain
(
globalStyles
.
get
(
id
));
}
}
return
style
;
return
style
;
}
}
}
// Only inline styles available.
// Only inline styles available.
return
style
;
return
style
;
}
}
...
@@ -100,10 +107,11 @@ import java.util.Map;
...
@@ -100,10 +107,11 @@ import java.util.Map;
end
,
end
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
}
}
if
(
style
.
getTextAlign
()
!=
null
)
{
@Nullable
Alignment
textAlign
=
style
.
getTextAlign
();
if
(
textAlign
!=
null
)
{
SpanUtil
.
addOrReplaceSpan
(
SpanUtil
.
addOrReplaceSpan
(
builder
,
builder
,
new
AlignmentSpan
.
Standard
(
style
.
getTextAlign
()
),
new
AlignmentSpan
.
Standard
(
textAlign
),
start
,
start
,
end
,
end
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
...
...
library/core/src/main/java/com/google/android/exoplayer2/text/ttml/TtmlStyle.java
View file @
37908dd4
...
@@ -18,9 +18,11 @@ package com.google.android.exoplayer2.text.ttml;
...
@@ -18,9 +18,11 @@ package com.google.android.exoplayer2.text.ttml;
import
android.graphics.Typeface
;
import
android.graphics.Typeface
;
import
android.text.Layout
;
import
android.text.Layout
;
import
androidx.annotation.IntDef
;
import
androidx.annotation.IntDef
;
import
androidx.annotation.Nullable
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.Documented
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.RetentionPolicy
;
import
org.checkerframework.checker.nullness.qual.MonotonicNonNull
;
/**
/**
* Style object of a <code>TtmlNode</code>
* Style object of a <code>TtmlNode</code>
...
@@ -58,7 +60,7 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -58,7 +60,7 @@ import java.lang.annotation.RetentionPolicy;
private
static
final
int
OFF
=
0
;
private
static
final
int
OFF
=
0
;
private
static
final
int
ON
=
1
;
private
static
final
int
ON
=
1
;
private
String
fontFamily
;
private
@MonotonicNonNull
String
fontFamily
;
private
int
fontColor
;
private
int
fontColor
;
private
boolean
hasFontColor
;
private
boolean
hasFontColor
;
private
int
backgroundColor
;
private
int
backgroundColor
;
...
@@ -69,8 +71,8 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -69,8 +71,8 @@ import java.lang.annotation.RetentionPolicy;
@OptionalBoolean
private
int
italic
;
@OptionalBoolean
private
int
italic
;
@FontSizeUnit
private
int
fontSizeUnit
;
@FontSizeUnit
private
int
fontSizeUnit
;
private
float
fontSize
;
private
float
fontSize
;
private
String
id
;
private
@MonotonicNonNull
String
id
;
private
Layout
.
Alignment
textAlign
;
private
Layout
.
@MonotonicNonNull
Alignment
textAlign
;
public
TtmlStyle
()
{
public
TtmlStyle
()
{
linethrough
=
UNSPECIFIED
;
linethrough
=
UNSPECIFIED
;
...
@@ -122,6 +124,7 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -122,6 +124,7 @@ import java.lang.annotation.RetentionPolicy;
return
this
;
return
this
;
}
}
@Nullable
public
String
getFontFamily
()
{
public
String
getFontFamily
()
{
return
fontFamily
;
return
fontFamily
;
}
}
...
@@ -171,7 +174,7 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -171,7 +174,7 @@ import java.lang.annotation.RetentionPolicy;
*
*
* @param ancestor the referential style to inherit from
* @param ancestor the referential style to inherit from
*/
*/
public
TtmlStyle
chain
(
TtmlStyle
ancestor
)
{
public
TtmlStyle
chain
(
@Nullable
TtmlStyle
ancestor
)
{
return
inherit
(
ancestor
,
true
);
return
inherit
(
ancestor
,
true
);
}
}
...
@@ -182,11 +185,11 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -182,11 +185,11 @@ import java.lang.annotation.RetentionPolicy;
*
*
* @param ancestor the ancestor style to inherit from
* @param ancestor the ancestor style to inherit from
*/
*/
public
TtmlStyle
inherit
(
TtmlStyle
ancestor
)
{
public
TtmlStyle
inherit
(
@Nullable
TtmlStyle
ancestor
)
{
return
inherit
(
ancestor
,
false
);
return
inherit
(
ancestor
,
false
);
}
}
private
TtmlStyle
inherit
(
TtmlStyle
ancestor
,
boolean
chaining
)
{
private
TtmlStyle
inherit
(
@Nullable
TtmlStyle
ancestor
,
boolean
chaining
)
{
if
(
ancestor
!=
null
)
{
if
(
ancestor
!=
null
)
{
if
(!
hasFontColor
&&
ancestor
.
hasFontColor
)
{
if
(!
hasFontColor
&&
ancestor
.
hasFontColor
)
{
setFontColor
(
ancestor
.
fontColor
);
setFontColor
(
ancestor
.
fontColor
);
...
@@ -197,7 +200,7 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -197,7 +200,7 @@ import java.lang.annotation.RetentionPolicy;
if
(
italic
==
UNSPECIFIED
)
{
if
(
italic
==
UNSPECIFIED
)
{
italic
=
ancestor
.
italic
;
italic
=
ancestor
.
italic
;
}
}
if
(
fontFamily
==
null
)
{
if
(
fontFamily
==
null
&&
ancestor
.
fontFamily
!=
null
)
{
fontFamily
=
ancestor
.
fontFamily
;
fontFamily
=
ancestor
.
fontFamily
;
}
}
if
(
linethrough
==
UNSPECIFIED
)
{
if
(
linethrough
==
UNSPECIFIED
)
{
...
@@ -206,7 +209,7 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -206,7 +209,7 @@ import java.lang.annotation.RetentionPolicy;
if
(
underline
==
UNSPECIFIED
)
{
if
(
underline
==
UNSPECIFIED
)
{
underline
=
ancestor
.
underline
;
underline
=
ancestor
.
underline
;
}
}
if
(
textAlign
==
null
)
{
if
(
textAlign
==
null
&&
ancestor
.
textAlign
!=
null
)
{
textAlign
=
ancestor
.
textAlign
;
textAlign
=
ancestor
.
textAlign
;
}
}
if
(
fontSizeUnit
==
UNSPECIFIED
)
{
if
(
fontSizeUnit
==
UNSPECIFIED
)
{
...
@@ -226,10 +229,12 @@ import java.lang.annotation.RetentionPolicy;
...
@@ -226,10 +229,12 @@ import java.lang.annotation.RetentionPolicy;
return
this
;
return
this
;
}
}
@Nullable
public
String
getId
()
{
public
String
getId
()
{
return
id
;
return
id
;
}
}
@Nullable
public
Layout
.
Alignment
getTextAlign
()
{
public
Layout
.
Alignment
getTextAlign
()
{
return
textAlign
;
return
textAlign
;
}
}
...
...
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