Add support for TTML origin and extent attributes defined in style instead of region

This commit is contained in:
Olivier Jouvenaux 2024-12-18 11:36:54 +01:00 committed by Ian Baker
parent d8333b37cf
commit fbd6dfa439
3 changed files with 58 additions and 2 deletions

View File

@ -53,6 +53,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
public static final String ANONYMOUS_REGION_ID = ""; public static final String ANONYMOUS_REGION_ID = "";
public static final String ATTR_ID = "id"; public static final String ATTR_ID = "id";
public static final String ATTR_STYLE = "style";
public static final String ATTR_TTS_ORIGIN = "origin"; public static final String ATTR_TTS_ORIGIN = "origin";
public static final String ATTR_TTS_EXTENT = "extent"; public static final String ATTR_TTS_EXTENT = "extent";
public static final String ATTR_TTS_DISPLAY_ALIGN = "displayAlign"; public static final String ATTR_TTS_DISPLAY_ALIGN = "displayAlign";

View File

@ -315,7 +315,7 @@ public final class TtmlParser implements SubtitleParser {
globalStyles.put(styleId, style); 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, cellRows, ttsExtent); @Nullable TtmlRegion ttmlRegion = parseRegionAttributes(xmlParser, cellRows, ttsExtent, globalStyles);
if (ttmlRegion != null) { if (ttmlRegion != null) {
globalRegions.put(ttmlRegion.id, ttmlRegion); globalRegions.put(ttmlRegion.id, ttmlRegion);
} }
@ -350,7 +350,8 @@ public final class TtmlParser implements SubtitleParser {
*/ */
@Nullable @Nullable
private static TtmlRegion parseRegionAttributes( private static TtmlRegion parseRegionAttributes(
XmlPullParser xmlParser, int cellRows, @Nullable TtsExtent ttsExtent) { XmlPullParser xmlParser, int cellRows, @Nullable TtsExtent ttsExtent,
Map<String, TtmlStyle> globalStyles) {
@Nullable 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;
@ -361,6 +362,15 @@ public final class TtmlParser implements SubtitleParser {
@Nullable @Nullable
String regionOrigin = XmlPullParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_TTS_ORIGIN); String regionOrigin = XmlPullParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_TTS_ORIGIN);
if (regionOrigin == null) {
String styleId = XmlPullParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_STYLE);
if (styleId != null) {
TtmlStyle style = globalStyles.get(styleId);
if (style != null) {
regionOrigin = style.getOrigin();
}
}
}
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);
@ -406,6 +416,15 @@ public final class TtmlParser implements SubtitleParser {
float height; float height;
@Nullable @Nullable
String regionExtent = XmlPullParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_TTS_EXTENT); String regionExtent = XmlPullParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_TTS_EXTENT);
if (regionExtent == null) {
String styleId = XmlPullParserUtil.getAttributeValue(xmlParser, TtmlNode.ATTR_STYLE);
if (styleId != null) {
TtmlStyle style = globalStyles.get(styleId);
if (style != null) {
regionExtent = style.getExtent();
}
}
}
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);
@ -626,6 +645,12 @@ public final class TtmlParser implements SubtitleParser {
case TtmlNode.ATTR_TTS_SHEAR: case TtmlNode.ATTR_TTS_SHEAR:
style = createIfNull(style).setShearPercentage(parseShear(attributeValue)); style = createIfNull(style).setShearPercentage(parseShear(attributeValue));
break; break;
case TtmlNode.ATTR_TTS_ORIGIN:
style = createIfNull(style).setOrigin(attributeValue);
break;
case TtmlNode.ATTR_TTS_EXTENT:
style = createIfNull(style).setExtent(attributeValue);
break;
default: default:
// ignore // ignore
break; break;

View File

@ -96,6 +96,8 @@ import java.lang.annotation.Target;
private @OptionalBoolean int textCombine; private @OptionalBoolean int textCombine;
@Nullable private TextEmphasis textEmphasis; @Nullable private TextEmphasis textEmphasis;
private float shearPercentage; private float shearPercentage;
@Nullable private String origin;
@Nullable private String extent;
public TtmlStyle() { public TtmlStyle() {
linethrough = UNSPECIFIED; linethrough = UNSPECIFIED;
@ -277,6 +279,12 @@ import java.lang.annotation.Target;
if (shearPercentage == UNSPECIFIED_SHEAR) { if (shearPercentage == UNSPECIFIED_SHEAR) {
shearPercentage = ancestor.shearPercentage; shearPercentage = ancestor.shearPercentage;
} }
if (origin == null) {
origin = ancestor.origin;
}
if (extent == null) {
extent = ancestor.extent;
}
// 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);
@ -382,4 +390,26 @@ import java.lang.annotation.Target;
public float getFontSize() { public float getFontSize() {
return fontSize; return fontSize;
} }
@CanIgnoreReturnValue
public TtmlStyle setOrigin(@Nullable String origin) {
this.origin = origin;
return this;
}
@Nullable
public String getOrigin() {
return origin;
}
@CanIgnoreReturnValue
public TtmlStyle setExtent(@Nullable String extent) {
this.extent = extent;
return this;
}
@Nullable
public String getExtent() {
return extent;
}
} }