• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.google.android.exoplayer2.text.ttml;
17 
18 import android.graphics.Typeface;
19 import android.text.Layout;
20 import androidx.annotation.IntDef;
21 import androidx.annotation.Nullable;
22 import com.google.android.exoplayer2.text.Cue;
23 import com.google.android.exoplayer2.text.Cue.VerticalType;
24 import com.google.android.exoplayer2.text.span.RubySpan;
25 import java.lang.annotation.Documented;
26 import java.lang.annotation.Retention;
27 import java.lang.annotation.RetentionPolicy;
28 
29 /**
30  * Style object of a <code>TtmlNode</code>
31  */
32 /* package */ final class TtmlStyle {
33 
34   public static final int UNSPECIFIED = -1;
35 
36   @Documented
37   @Retention(RetentionPolicy.SOURCE)
38   @IntDef(
39       flag = true,
40       value = {UNSPECIFIED, STYLE_NORMAL, STYLE_BOLD, STYLE_ITALIC, STYLE_BOLD_ITALIC})
41   public @interface StyleFlags {}
42 
43   public static final int STYLE_NORMAL = Typeface.NORMAL;
44   public static final int STYLE_BOLD = Typeface.BOLD;
45   public static final int STYLE_ITALIC = Typeface.ITALIC;
46   public static final int STYLE_BOLD_ITALIC = Typeface.BOLD_ITALIC;
47 
48   @Documented
49   @Retention(RetentionPolicy.SOURCE)
50   @IntDef({UNSPECIFIED, FONT_SIZE_UNIT_PIXEL, FONT_SIZE_UNIT_EM, FONT_SIZE_UNIT_PERCENT})
51   public @interface FontSizeUnit {}
52 
53   public static final int FONT_SIZE_UNIT_PIXEL = 1;
54   public static final int FONT_SIZE_UNIT_EM = 2;
55   public static final int FONT_SIZE_UNIT_PERCENT = 3;
56 
57   @Documented
58   @Retention(RetentionPolicy.SOURCE)
59   @IntDef({UNSPECIFIED, OFF, ON})
60   private @interface OptionalBoolean {}
61 
62   private static final int OFF = 0;
63   private static final int ON = 1;
64 
65   @Documented
66   @Retention(RetentionPolicy.SOURCE)
67   @IntDef({UNSPECIFIED, RUBY_TYPE_CONTAINER, RUBY_TYPE_BASE, RUBY_TYPE_TEXT, RUBY_TYPE_DELIMITER})
68   public @interface RubyType {}
69 
70   public static final int RUBY_TYPE_CONTAINER = 1;
71   public static final int RUBY_TYPE_BASE = 2;
72   public static final int RUBY_TYPE_TEXT = 3;
73   public static final int RUBY_TYPE_DELIMITER = 4;
74 
75   @Nullable private String fontFamily;
76   private int fontColor;
77   private boolean hasFontColor;
78   private int backgroundColor;
79   private boolean hasBackgroundColor;
80   @OptionalBoolean private int linethrough;
81   @OptionalBoolean private int underline;
82   @OptionalBoolean private int bold;
83   @OptionalBoolean private int italic;
84   @FontSizeUnit private int fontSizeUnit;
85   private float fontSize;
86   @Nullable private String id;
87   @RubyType private int rubyType;
88   @RubySpan.Position private int rubyPosition;
89   @Nullable private Layout.Alignment textAlign;
90   @OptionalBoolean private int textCombine;
91   @Cue.VerticalType private int verticalType;
92 
TtmlStyle()93   public TtmlStyle() {
94     linethrough = UNSPECIFIED;
95     underline = UNSPECIFIED;
96     bold = UNSPECIFIED;
97     italic = UNSPECIFIED;
98     fontSizeUnit = UNSPECIFIED;
99     rubyType = UNSPECIFIED;
100     rubyPosition = RubySpan.POSITION_UNKNOWN;
101     textCombine = UNSPECIFIED;
102     verticalType = Cue.TYPE_UNSET;
103   }
104 
105   /**
106    * Returns the style or {@link #UNSPECIFIED} when no style information is given.
107    *
108    * @return {@link #UNSPECIFIED}, {@link #STYLE_NORMAL}, {@link #STYLE_BOLD}, {@link #STYLE_BOLD}
109    *     or {@link #STYLE_BOLD_ITALIC}.
110    */
getStyle()111   @StyleFlags public int getStyle() {
112     if (bold == UNSPECIFIED && italic == UNSPECIFIED) {
113       return UNSPECIFIED;
114     }
115     return (bold == ON ? STYLE_BOLD : STYLE_NORMAL)
116         | (italic == ON ? STYLE_ITALIC : STYLE_NORMAL);
117   }
118 
isLinethrough()119   public boolean isLinethrough() {
120     return linethrough == ON;
121   }
122 
setLinethrough(boolean linethrough)123   public TtmlStyle setLinethrough(boolean linethrough) {
124     this.linethrough = linethrough ? ON : OFF;
125     return this;
126   }
127 
isUnderline()128   public boolean isUnderline() {
129     return underline == ON;
130   }
131 
setUnderline(boolean underline)132   public TtmlStyle setUnderline(boolean underline) {
133     this.underline = underline ? ON : OFF;
134     return this;
135   }
136 
setBold(boolean bold)137   public TtmlStyle setBold(boolean bold) {
138     this.bold = bold ? ON : OFF;
139     return this;
140   }
141 
setItalic(boolean italic)142   public TtmlStyle setItalic(boolean italic) {
143     this.italic = italic ? ON : OFF;
144     return this;
145   }
146 
147   @Nullable
getFontFamily()148   public String getFontFamily() {
149     return fontFamily;
150   }
151 
setFontFamily(@ullable String fontFamily)152   public TtmlStyle setFontFamily(@Nullable String fontFamily) {
153     this.fontFamily = fontFamily;
154     return this;
155   }
156 
getFontColor()157   public int getFontColor() {
158     if (!hasFontColor) {
159       throw new IllegalStateException("Font color has not been defined.");
160     }
161     return fontColor;
162   }
163 
setFontColor(int fontColor)164   public TtmlStyle setFontColor(int fontColor) {
165     this.fontColor = fontColor;
166     hasFontColor = true;
167     return this;
168   }
169 
hasFontColor()170   public boolean hasFontColor() {
171     return hasFontColor;
172   }
173 
getBackgroundColor()174   public int getBackgroundColor() {
175     if (!hasBackgroundColor) {
176       throw new IllegalStateException("Background color has not been defined.");
177     }
178     return backgroundColor;
179   }
180 
setBackgroundColor(int backgroundColor)181   public TtmlStyle setBackgroundColor(int backgroundColor) {
182     this.backgroundColor = backgroundColor;
183     hasBackgroundColor = true;
184     return this;
185   }
186 
hasBackgroundColor()187   public boolean hasBackgroundColor() {
188     return hasBackgroundColor;
189   }
190 
191   /**
192    * Chains this style to referential style. Local properties which are already set are never
193    * overridden.
194    *
195    * @param ancestor the referential style to inherit from
196    */
chain(@ullable TtmlStyle ancestor)197   public TtmlStyle chain(@Nullable TtmlStyle ancestor) {
198     return inherit(ancestor, true);
199   }
200 
201   /**
202    * Inherits from an ancestor style. Properties like <i>tts:backgroundColor</i> which are not
203    * inheritable are not inherited as well as properties which are already set locally are never
204    * overridden.
205    *
206    * @param ancestor the ancestor style to inherit from
207    */
inherit(@ullable TtmlStyle ancestor)208   public TtmlStyle inherit(@Nullable TtmlStyle ancestor) {
209     return inherit(ancestor, false);
210   }
211 
inherit(@ullable TtmlStyle ancestor, boolean chaining)212   private TtmlStyle inherit(@Nullable TtmlStyle ancestor, boolean chaining) {
213     if (ancestor != null) {
214       if (!hasFontColor && ancestor.hasFontColor) {
215         setFontColor(ancestor.fontColor);
216       }
217       if (bold == UNSPECIFIED) {
218         bold = ancestor.bold;
219       }
220       if (italic == UNSPECIFIED) {
221         italic = ancestor.italic;
222       }
223       if (fontFamily == null && ancestor.fontFamily != null) {
224         fontFamily = ancestor.fontFamily;
225       }
226       if (linethrough == UNSPECIFIED) {
227         linethrough = ancestor.linethrough;
228       }
229       if (underline == UNSPECIFIED) {
230         underline = ancestor.underline;
231       }
232       if (rubyPosition == RubySpan.POSITION_UNKNOWN) {
233         rubyPosition = ancestor.rubyPosition;
234       }
235       if (textAlign == null && ancestor.textAlign != null) {
236         textAlign = ancestor.textAlign;
237       }
238       if (textCombine == UNSPECIFIED) {
239         textCombine = ancestor.textCombine;
240       }
241       if (fontSizeUnit == UNSPECIFIED) {
242         fontSizeUnit = ancestor.fontSizeUnit;
243         fontSize = ancestor.fontSize;
244       }
245       // attributes not inherited as of http://www.w3.org/TR/ttml1/
246       if (chaining && !hasBackgroundColor && ancestor.hasBackgroundColor) {
247         setBackgroundColor(ancestor.backgroundColor);
248       }
249       if (chaining && rubyType == UNSPECIFIED && ancestor.rubyType != UNSPECIFIED) {
250         rubyType = ancestor.rubyType;
251       }
252       if (chaining && verticalType == Cue.TYPE_UNSET && ancestor.verticalType != Cue.TYPE_UNSET) {
253         setVerticalType(ancestor.verticalType);
254       }
255     }
256     return this;
257   }
258 
setId(@ullable String id)259   public TtmlStyle setId(@Nullable String id) {
260     this.id = id;
261     return this;
262   }
263 
264   @Nullable
getId()265   public String getId() {
266     return id;
267   }
268 
setRubyType(@ubyType int rubyType)269   public TtmlStyle setRubyType(@RubyType int rubyType) {
270     this.rubyType = rubyType;
271     return this;
272   }
273 
274   @RubyType
getRubyType()275   public int getRubyType() {
276     return rubyType;
277   }
278 
setRubyPosition(@ubySpan.Position int position)279   public TtmlStyle setRubyPosition(@RubySpan.Position int position) {
280     this.rubyPosition = position;
281     return this;
282   }
283 
284   @RubySpan.Position
getRubyPosition()285   public int getRubyPosition() {
286     return rubyPosition;
287   }
288 
289   @Nullable
getTextAlign()290   public Layout.Alignment getTextAlign() {
291     return textAlign;
292   }
293 
setTextAlign(@ullable Layout.Alignment textAlign)294   public TtmlStyle setTextAlign(@Nullable Layout.Alignment textAlign) {
295     this.textAlign = textAlign;
296     return this;
297   }
298 
299   /** Returns true if the source entity has {@code tts:textCombine=all}. */
getTextCombine()300   public boolean getTextCombine() {
301     return textCombine == ON;
302   }
303 
setTextCombine(boolean combine)304   public TtmlStyle setTextCombine(boolean combine) {
305     this.textCombine = combine ? ON : OFF;
306     return this;
307   }
308 
setFontSize(float fontSize)309   public TtmlStyle setFontSize(float fontSize) {
310     this.fontSize = fontSize;
311     return this;
312   }
313 
setFontSizeUnit(int fontSizeUnit)314   public TtmlStyle setFontSizeUnit(int fontSizeUnit) {
315     this.fontSizeUnit = fontSizeUnit;
316     return this;
317   }
318 
getFontSizeUnit()319   @FontSizeUnit public int getFontSizeUnit() {
320     return fontSizeUnit;
321   }
322 
getFontSize()323   public float getFontSize() {
324     return fontSize;
325   }
326 
setVerticalType(@erticalType int verticalType)327   public TtmlStyle setVerticalType(@VerticalType int verticalType) {
328     this.verticalType = verticalType;
329     return this;
330   }
331 
332   @VerticalType
getVerticalType()333   public int getVerticalType() {
334     return verticalType;
335   }
336 }
337