Fix a bug with TTML font styling.

Due to a bug, for each TTML node, when applying its style to the encompassed
regions, it applies child nodes's styling several time for each region (the
number of time is equal to the number of region). This leads to a styling issue
if there are multiple regions in a node displayed at the same time in TTML file.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=196810046
This commit is contained in:
hoangtc 2018-05-16 04:33:57 -07:00 committed by Andrew Lewis
parent 9a45d504d3
commit 17abab455e
2 changed files with 42 additions and 22 deletions

View file

@ -16,6 +16,9 @@
* HLS:
* Fix playback of livestreams with EXT-X-PROGRAM-DATE-TIME tags
([#4239](https://github.com/google/ExoPlayer/issues/4239)).
* Caption:
* Fix a TTML styling issue when there are multiple regions displayed at the
same time that can make text size of each region much smaller than defined.
### 2.8.0 ###

View file

@ -175,7 +175,7 @@ import java.util.TreeSet;
Map<String, TtmlRegion> regionMap) {
TreeMap<String, SpannableStringBuilder> regionOutputs = new TreeMap<>();
traverseForText(timeUs, false, regionId, regionOutputs);
traverseForStyle(globalStyles, regionOutputs);
traverseForStyle(timeUs, globalStyles, regionOutputs);
List<Cue> cues = new ArrayList<>();
for (Entry<String, SpannableStringBuilder> entry : regionOutputs.entrySet()) {
TtmlRegion region = regionMap.get(entry.getKey());
@ -185,25 +185,31 @@ import java.util.TreeSet;
return cues;
}
private void traverseForText(long timeUs, boolean descendsPNode,
String inheritedRegion, Map<String, SpannableStringBuilder> regionOutputs) {
private void traverseForText(
long timeUs,
boolean descendsPNode,
String inheritedRegion,
Map<String, SpannableStringBuilder> regionOutputs) {
nodeStartsByRegion.clear();
nodeEndsByRegion.clear();
String resolvedRegionId = regionId;
if (ANONYMOUS_REGION_ID.equals(resolvedRegionId)) {
resolvedRegionId = inheritedRegion;
if (TAG_METADATA.equals(tag)) {
// Ignore metadata tag.
return;
}
String resolvedRegionId = ANONYMOUS_REGION_ID.equals(regionId) ? inheritedRegion : regionId;
if (isTextNode && descendsPNode) {
getRegionOutput(resolvedRegionId, regionOutputs).append(text);
} else if (TAG_BR.equals(tag) && descendsPNode) {
getRegionOutput(resolvedRegionId, regionOutputs).append('\n');
} else if (TAG_METADATA.equals(tag)) {
// Do nothing.
} else if (isActive(timeUs)) {
boolean isPNode = TAG_P.equals(tag);
// This is a container node, which can contain zero or more children.
for (Entry<String, SpannableStringBuilder> entry : regionOutputs.entrySet()) {
nodeStartsByRegion.put(entry.getKey(), entry.getValue().length());
}
boolean isPNode = TAG_P.equals(tag);
for (int i = 0; i < getChildCount(); i++) {
getChild(i).traverseForText(timeUs, descendsPNode || isPNode, resolvedRegionId,
regionOutputs);
@ -211,39 +217,50 @@ import java.util.TreeSet;
if (isPNode) {
TtmlRenderUtil.endParagraph(getRegionOutput(resolvedRegionId, regionOutputs));
}
for (Entry<String, SpannableStringBuilder> entry : regionOutputs.entrySet()) {
nodeEndsByRegion.put(entry.getKey(), entry.getValue().length());
}
}
}
private static SpannableStringBuilder getRegionOutput(String resolvedRegionId,
Map<String, SpannableStringBuilder> regionOutputs) {
private static SpannableStringBuilder getRegionOutput(
String resolvedRegionId, Map<String, SpannableStringBuilder> regionOutputs) {
if (!regionOutputs.containsKey(resolvedRegionId)) {
regionOutputs.put(resolvedRegionId, new SpannableStringBuilder());
}
return regionOutputs.get(resolvedRegionId);
}
private void traverseForStyle(Map<String, TtmlStyle> globalStyles,
private void traverseForStyle(
long timeUs,
Map<String, TtmlStyle> globalStyles,
Map<String, SpannableStringBuilder> regionOutputs) {
if (!isActive(timeUs)) {
return;
}
for (Entry<String, Integer> entry : nodeEndsByRegion.entrySet()) {
String regionId = entry.getKey();
int start = nodeStartsByRegion.containsKey(regionId) ? nodeStartsByRegion.get(regionId) : 0;
applyStyleToOutput(globalStyles, regionOutputs.get(regionId), start, entry.getValue());
for (int i = 0; i < getChildCount(); ++i) {
getChild(i).traverseForStyle(globalStyles, regionOutputs);
int end = entry.getValue();
if (start != end) {
SpannableStringBuilder regionOutput = regionOutputs.get(regionId);
applyStyleToOutput(globalStyles, regionOutput, start, end);
}
}
for (int i = 0; i < getChildCount(); ++i) {
getChild(i).traverseForStyle(timeUs, globalStyles, regionOutputs);
}
}
private void applyStyleToOutput(Map<String, TtmlStyle> globalStyles,
SpannableStringBuilder regionOutput, int start, int end) {
if (start != end) {
TtmlStyle resolvedStyle = TtmlRenderUtil.resolveStyle(style, styleIds, globalStyles);
if (resolvedStyle != null) {
TtmlRenderUtil.applyStylesToSpan(regionOutput, start, end, resolvedStyle);
}
private void applyStyleToOutput(
Map<String, TtmlStyle> globalStyles,
SpannableStringBuilder regionOutput,
int start,
int end) {
TtmlStyle resolvedStyle = TtmlRenderUtil.resolveStyle(style, styleIds, globalStyles);
if (resolvedStyle != null) {
TtmlRenderUtil.applyStylesToSpan(regionOutput, start, end, resolvedStyle);
}
}