Skip to content

Commit

Permalink
Add support for TTML Regions extent
Browse files Browse the repository at this point in the history
This allows limiting the horizontal extension of the cues.
NOTE: So far, we only support percentages for size magnitudes.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=121667873
  • Loading branch information
AquilesCanta authored and ojw28 committed May 6, 2016
1 parent 2036fed commit f057916
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 31 deletions.
2 changes: 1 addition & 1 deletion library/src/androidTest/assets/ttml/multiple_regions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<layout>
<region xml:id="region1" ttm:origin="10% 10%" extent="20% 20%"/>
<region xml:id="region2" ttm:origin="40% 40%" extent="20% 20%"/>
<region xml:id="region3" ttm:origin="10% 80%" extent="10% 10%"/>
<region xml:id="region3" ttm:origin="10% 80%"/>
<region xml:id="region4" ttm:origin="60% 10%" extent="20% 20%"/>
<region xml:id="ultimate" ttm:origin="45% 45%" extent="35% 35%"/>
</layout>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,31 +157,37 @@ public void testMultipleRegions() throws IOException {
assertEquals("lorem", ttmlCue.text.toString());
assertEquals(10.f / 100.f, ttmlCue.position);
assertEquals(10.f / 100.f, ttmlCue.line);
assertEquals(20.f / 100.f, ttmlCue.size);

ttmlCue = output.get(1);
assertEquals("amet", ttmlCue.text.toString());
assertEquals(60.f / 100.f, ttmlCue.position);
assertEquals(10.f / 100.f, ttmlCue.line);
assertEquals(20.f / 100.f, ttmlCue.size);

output = subtitle.getCues(5000000);
assertEquals(1, output.size());
ttmlCue = output.get(0);
assertEquals("ipsum", ttmlCue.text.toString());
assertEquals(40.f / 100.f, ttmlCue.position);
assertEquals(40.f / 100.f, ttmlCue.line);
assertEquals(20.f / 100.f, ttmlCue.size);

output = subtitle.getCues(9000000);
assertEquals(1, output.size());
ttmlCue = output.get(0);
assertEquals("dolor", ttmlCue.text.toString());
assertEquals(10.f / 100.f, ttmlCue.position);
assertEquals(80.f / 100.f, ttmlCue.line);
assertEquals(Cue.DIMEN_UNSET, ttmlCue.size);

output = subtitle.getCues(21000000);
assertEquals(1, output.size());
ttmlCue = output.get(0);
assertEquals("She first said this", ttmlCue.text.toString());
assertEquals(45.f / 100.f, ttmlCue.position);
assertEquals(45.f / 100.f, ttmlCue.line);
assertEquals(35.f / 100.f, ttmlCue.size);
output = subtitle.getCues(25000000);
ttmlCue = output.get(0);
assertEquals("She first said this\nThen this", ttmlCue.text.toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
public static final String ANONYMOUS_REGION_ID = "";
public static final String ATTR_ID = "id";
public static final String ATTR_TTS_BACKGROUND_COLOR = "backgroundColor";
public static final String ATTR_TTS_EXTENT = "extent";
public static final String ATTR_TTS_FONT_STYLE = "fontStyle";
public static final String ATTR_TTS_FONT_SIZE = "fontSize";
public static final String ATTR_TTS_FONT_FAMILY = "fontFamily";
Expand Down Expand Up @@ -82,12 +83,12 @@
public final long endTimeUs;
public final TtmlStyle style;
public final String regionId;
private String[] styleIds;

private List<TtmlNode> children;
private final String[] styleIds;
private final HashMap<String, Integer> nodeStartsByRegion;
private final HashMap<String, Integer> nodeEndsByRegion;

private HashMap<String, Integer> nodeStartsByRegion;
private HashMap<String, Integer> nodeEndsByRegion;
private List<TtmlNode> children;

public static TtmlNode buildTextNode(String text) {
return new TtmlNode(null, TtmlRenderUtil.applyTextElementSpacePolicy(text), UNDEFINED_TIME,
Expand Down Expand Up @@ -180,7 +181,7 @@ public List<Cue> getCues(long timeUs, Map<String, TtmlStyle> globalStyles,
for (Entry<String, SpannableStringBuilder> entry : regionOutputs.entrySet()) {
TtmlRegion region = regionMap.get(entry.getKey());
cues.add(new Cue(cleanUpText(entry.getValue()), null, region.line, Cue.TYPE_UNSET,
Cue.TYPE_UNSET, region.position, Cue.TYPE_UNSET, Cue.DIMEN_UNSET));
Cue.TYPE_UNSET, region.position, Cue.TYPE_UNSET, region.width));
}
return cues;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import com.google.android.exoplayer.C;
import com.google.android.exoplayer.ParserException;
import com.google.android.exoplayer.text.Cue;
import com.google.android.exoplayer.text.SubtitleParser;
import com.google.android.exoplayer.util.MimeTypes;
import com.google.android.exoplayer.util.ParserUtil;
Expand Down Expand Up @@ -74,9 +75,8 @@ public final class TtmlParser implements SubtitleParser {
+ "(?:(\\.[0-9]+)|:([0-9][0-9])(?:\\.([0-9]+))?)?$");
private static final Pattern OFFSET_TIME =
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 ORIGIN_COORDINATES =
private static final Pattern FONT_SIZE = Pattern.compile("^(([0-9]*.)?[0-9]+)(px|em|%)$");
private static final Pattern PERCENTAGE_COORDINATES =
Pattern.compile("^(\\d+\\.?\\d*?)% (\\d+\\.?\\d*?)%$");

// TODO: read and apply the following attributes if specified.
Expand Down Expand Up @@ -189,23 +189,42 @@ private Map<String, TtmlStyle> parseHeader(XmlPullParser xmlParser,
return globalStyles;
}

/**
* Parses a region declaration. Supports origin and extent definition but only when defined in
* terms of percentage of the viewport. Regions that do not correctly declare origin are ignored.
*/
private Pair<String, TtmlRegion> parseRegionAttributes(XmlPullParser xmlParser) {
String regionId = ParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_ID);
String regionOrigin = ParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_TTS_ORIGIN);
String regionExtent = ParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_TTS_EXTENT);
if (regionOrigin == null || regionId == null) {
return null;
}
Matcher originMatcher = ORIGIN_COORDINATES.matcher(regionOrigin);
float position = Cue.DIMEN_UNSET;
float line = Cue.DIMEN_UNSET;
Matcher originMatcher = PERCENTAGE_COORDINATES.matcher(regionOrigin);
if (originMatcher.matches()) {
try {
float position = Float.parseFloat(originMatcher.group(1)) / 100.f;
float line = Float.parseFloat(originMatcher.group(2)) / 100.f;
return new Pair<>(regionId, new TtmlRegion(position, line));
position = Float.parseFloat(originMatcher.group(1)) / 100.f;
line = Float.parseFloat(originMatcher.group(2)) / 100.f;
} catch (NumberFormatException e) {
Log.w(TAG, "Ignoring malformed region declaration: '" + regionOrigin + "'", e);
Log.w(TAG, "Ignoring region with malformed origin: '" + regionOrigin + "'", e);
position = Cue.DIMEN_UNSET;
}
}
float width = Cue.DIMEN_UNSET;
if (regionExtent != null) {
Matcher extentMatcher = PERCENTAGE_COORDINATES.matcher(regionExtent);
if (extentMatcher.matches()) {
try {
width = Float.parseFloat(extentMatcher.group(1)) / 100.f;
} catch (NumberFormatException e) {
Log.w(TAG, "Ignoring malformed region extent: '" + regionExtent + "'", e);
}
}
}
return null;
return position != Cue.DIMEN_UNSET ? new Pair<>(regionId, new TtmlRegion(position, line, width))
: null;
}

private String[] parseStyleIds(String parentStyleIds) {
Expand Down Expand Up @@ -387,10 +406,11 @@ private static void parseFontSize(String expression, TtmlStyle out) throws Parse
matcher = FONT_SIZE.matcher(expression);
} else if (expressions.length == 2){
matcher = FONT_SIZE.matcher(expressions[1]);
Log.w(TAG, "multiple values in fontSize attribute. Picking the second "
+ "value for vertical font size and ignoring the first.");
Log.w(TAG, "Multiple values in fontSize attribute. Picking the second value for vertical font"
+ " size and ignoring the first.");
} else {
throw new ParserException();
throw new ParserException("Invalid number of entries for fontSize: " + expressions.length
+ ".");
}

if (matcher.matches()) {
Expand All @@ -406,11 +426,11 @@ private static void parseFontSize(String expression, TtmlStyle out) throws Parse
out.setFontSizeUnit(TtmlStyle.FONT_SIZE_UNIT_PERCENT);
break;
default:
throw new ParserException();
throw new ParserException("Invalid unit for fontSize: '" + unit + "'.");
}
out.setFontSize(Float.valueOf(matcher.group(1)));
} else {
throw new ParserException();
throw new ParserException("Invalid expression for fontSize: '" + expression + "'.");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,16 @@

public final float position;
public final float line;
public final float width;

public TtmlRegion() {
this(Cue.DIMEN_UNSET, Cue.DIMEN_UNSET);
this(Cue.DIMEN_UNSET, Cue.DIMEN_UNSET, Cue.DIMEN_UNSET);
}

public TtmlRegion(float position, float line) {
public TtmlRegion(float position, float line, float width) {
this.position = position;
this.line = line;
this.width = width;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,17 @@ public static TtmlStyle resolveStyle(TtmlStyle style, String[] styleIds,
} else if (style == null && styleIds.length > 1) {
// Only multiple referential styles present.
TtmlStyle chainedStyle = new TtmlStyle();
for (int i = 0; i < styleIds.length; i++) {
chainedStyle.chain(globalStyles.get(styleIds[i]));
for (String id : styleIds) {
chainedStyle.chain(globalStyles.get(id));
}
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 (int i = 0; i < styleIds.length; i++) {
style.chain(globalStyles.get(styleIds[i]));
for (String id : styleIds) {
style.chain(globalStyles.get(id));
}
return style;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
public static final int FONT_SIZE_UNIT_PERCENT = 3;

private static final int OFF = 0;
private static final int ON = 1;
private static final int ON = 1;

private String fontFamily;
private int fontColor;
Expand Down Expand Up @@ -113,9 +113,9 @@ public int getFontColor() {
return fontColor;
}

public TtmlStyle setFontColor(int color) {
public TtmlStyle setFontColor(int fontColor) {
Assertions.checkState(inheritableStyle == null);
this.fontColor = color;
this.fontColor = fontColor;
hasFontColor = true;
return this;
}
Expand Down Expand Up @@ -232,8 +232,8 @@ public TtmlStyle setFontSize(float fontSize) {
return this;
}

public TtmlStyle setFontSizeUnit(int unit) {
this.fontSizeUnit = unit;
public TtmlStyle setFontSizeUnit(int fontSizeUnit) {
this.fontSizeUnit = fontSizeUnit;
return this;
}

Expand Down

0 comments on commit f057916

Please sign in to comment.