Add CSS Specificity score system to WebvttCssStyle
This CL provides the necessary infrastructure to add styling by class. This was separated into two different CLs to ease reviewing. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=120336976
This commit is contained in:
parent
0fc53f6e37
commit
c11fda04e5
@ -178,6 +178,36 @@ public final class CssParserTest extends InstrumentationTestCase {
|
||||
assertEquals(CssParser.parseNextToken(input, builder), null);
|
||||
}
|
||||
|
||||
public void testStyleScoreSystem() {
|
||||
WebvttCssStyle style = new WebvttCssStyle();
|
||||
// Universal selector.
|
||||
assertEquals(1, style.getSpecificityScore(null, null, new String[0], null));
|
||||
// Class match without tag match.
|
||||
style.setTargetClasses(new String[] { "class1", "class2"});
|
||||
assertEquals(8, style.getSpecificityScore(null, null,
|
||||
new String[] { "class1", "class2", "class3" }, null));
|
||||
// Class and tag match
|
||||
style.setTargetTagName("b");
|
||||
assertEquals(10, style.getSpecificityScore(null, "b",
|
||||
new String[] { "class1", "class2", "class3" }, null));
|
||||
// Class insufficiency.
|
||||
assertEquals(0, style.getSpecificityScore(null, "b", new String[] { "class1", "class" }, null));
|
||||
// Voice, classes and tag match.
|
||||
style.setTargetVoice("Manuel Cráneo");
|
||||
assertEquals(14, style.getSpecificityScore(null, "b",
|
||||
new String[] { "class1", "class2", "class3" }, "Manuel Cráneo"));
|
||||
// Voice mismatch.
|
||||
assertEquals(0, style.getSpecificityScore(null, "b",
|
||||
new String[] { "class1", "class2", "class3" }, "Manuel Craneo"));
|
||||
// Id, voice, classes and tag match.
|
||||
style.setTargetId("id");
|
||||
assertEquals(0x40000000 + 14, style.getSpecificityScore("id", "b",
|
||||
new String[] { "class1", "class2", "class3" }, "Manuel Cráneo"));
|
||||
// Id mismatch.
|
||||
assertEquals(0, style.getSpecificityScore("id1", "b",
|
||||
new String[] { "class1", "class2", "class3" }, null));
|
||||
}
|
||||
|
||||
// Utility methods.
|
||||
|
||||
private void assertSkipsToEndOfSkip(String expectedLine, String s) {
|
||||
|
@ -20,6 +20,10 @@ import com.google.android.exoplayer.util.Util;
|
||||
import android.graphics.Typeface;
|
||||
import android.text.Layout;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Style object of a Css style block in a Webvtt file.
|
||||
*
|
||||
@ -42,6 +46,13 @@ import android.text.Layout;
|
||||
private static final int OFF = 0;
|
||||
private static final int ON = 1;
|
||||
|
||||
// Selector properties.
|
||||
private String targetId;
|
||||
private String targetTag;
|
||||
private List<String> targetClasses;
|
||||
private String targetVoice;
|
||||
|
||||
// Style properties.
|
||||
private String fontFamily;
|
||||
private int fontColor;
|
||||
private boolean hasFontColor;
|
||||
@ -60,6 +71,10 @@ import android.text.Layout;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
targetId = "";
|
||||
targetTag = "";
|
||||
targetClasses = Collections.emptyList();
|
||||
targetVoice = "";
|
||||
fontFamily = null;
|
||||
hasFontColor = false;
|
||||
hasBackgroundColor = false;
|
||||
@ -71,6 +86,59 @@ import android.text.Layout;
|
||||
textAlign = null;
|
||||
}
|
||||
|
||||
public void setTargetId(String targetId) {
|
||||
this.targetId = targetId;
|
||||
}
|
||||
|
||||
public void setTargetTagName(String targetTag) {
|
||||
this.targetTag = targetTag;
|
||||
}
|
||||
|
||||
public void setTargetClasses(String[] targetClasses) {
|
||||
this.targetClasses = Arrays.asList(targetClasses);
|
||||
}
|
||||
|
||||
public void setTargetVoice(String targetVoice) {
|
||||
this.targetVoice = targetVoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a value in a score system compliant with the CSS Specificity rules.
|
||||
*
|
||||
* @see <a href="https://www.w3.org/TR/CSS2/cascade.html">CSS Cascading</a>
|
||||
*
|
||||
* The score works as follows:
|
||||
* <ul>
|
||||
* <li> Id match adds 0x40000000 to the score.
|
||||
* <li> Each class and voice match adds 4 to the score.
|
||||
* <li> Tag matching adds 2 to the score.
|
||||
* <li> Universal selector matching scores 1.
|
||||
* </ul>
|
||||
*
|
||||
* @param id The id of the cue if present, {@code null} otherwise.
|
||||
* @param tag Name of the tag, {@code null} if it refers to the entire cue.
|
||||
* @param classes An array containing the classes the tag belongs to. Must not be null.
|
||||
* @param voice Annotated voice if present, {@code null} otherwise.
|
||||
* @return The score of the match, zero if there is no match.
|
||||
*/
|
||||
public int getSpecificityScore(String id, String tag, String[] classes, String voice) {
|
||||
if (targetId.isEmpty() && targetTag.isEmpty() && targetClasses.isEmpty()
|
||||
&& targetVoice.isEmpty()) {
|
||||
// The selector is universal. It matches with the minimum score.
|
||||
return 1;
|
||||
}
|
||||
int score = 0;
|
||||
score = updateScoreForMatch(score, targetId, id, 0x40000000);
|
||||
score = updateScoreForMatch(score, targetTag, tag, 2);
|
||||
score = updateScoreForMatch(score, targetVoice, voice, 4);
|
||||
if (score == -1 || !Arrays.asList(classes).containsAll(targetClasses)) {
|
||||
return 0;
|
||||
} else {
|
||||
score += targetClasses.size() * 4;
|
||||
}
|
||||
return score;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the style or {@link #UNSPECIFIED} when no style information is given.
|
||||
*
|
||||
@ -214,5 +282,12 @@ import android.text.Layout;
|
||||
}
|
||||
}
|
||||
|
||||
private static int updateScoreForMatch(int currentScore, String target, String actual,
|
||||
int score) {
|
||||
if (target.isEmpty() || currentScore == -1) {
|
||||
return currentScore;
|
||||
}
|
||||
return target.equals(actual) ? currentScore + score : -1;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -211,10 +211,10 @@ import java.util.regex.Pattern;
|
||||
}
|
||||
}
|
||||
// apply unclosed tags
|
||||
applyStyleToText(spannedText, styleMap.get(UNIVERSAL_CUE_ID), 0, spannedText.length());
|
||||
while (!startTagStack.isEmpty()) {
|
||||
applySpansForTag(startTagStack.pop(), spannedText, styleMap);
|
||||
}
|
||||
applyStyleToText(spannedText, styleMap.get(UNIVERSAL_CUE_ID), 0, spannedText.length());
|
||||
applyStyleToText(spannedText, styleMap.get(CUE_ID_PREFIX + id), 0, spannedText.length());
|
||||
builder.setText(spannedText);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user