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