Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
SDK
/
exoplayer
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
eb7c1470
authored
May 01, 2020
by
ibaker
Committed by
Oliver Woodman
May 01, 2020
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Add AbsoluteSizeSpan to SpannedHtmlConverter
PiperOrigin-RevId: 309390205
parent
fa0178d0
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
90 additions
and
25 deletions
library/ui/src/main/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverter.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitleWebView.java
library/ui/src/test/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverterTest.java
library/ui/src/main/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverter.java
View file @
eb7c1470
...
...
@@ -19,6 +19,7 @@ package com.google.android.exoplayer2.ui;
import
android.graphics.Typeface
;
import
android.text.Html
;
import
android.text.Spanned
;
import
android.text.style.AbsoluteSizeSpan
;
import
android.text.style.BackgroundColorSpan
;
import
android.text.style.ForegroundColorSpan
;
import
android.text.style.StyleSpan
;
...
...
@@ -66,8 +67,12 @@ import java.util.regex.Pattern;
* <li>WebView/Chromium (the intended destination of this HTML) gracefully handles overlapping
* tags and usually renders the same result as spanned text in a TextView.
* </ul>
*
* @param text The (possibly span-styled) text to convert to HTML.
* @param displayDensity The screen density of the device. WebView treats 1 CSS px as one Android
* dp, so to convert size values from Android px to CSS px we need to know the screen density.
*/
public
static
String
convert
(
@Nullable
CharSequence
text
)
{
public
static
String
convert
(
@Nullable
CharSequence
text
,
float
displayDensity
)
{
if
(
text
==
null
)
{
return
""
;
}
...
...
@@ -75,7 +80,7 @@ import java.util.regex.Pattern;
return
escapeHtml
(
text
);
}
Spanned
spanned
=
(
Spanned
)
text
;
SparseArray
<
Transition
>
spanTransitions
=
findSpanTransitions
(
spanned
);
SparseArray
<
Transition
>
spanTransitions
=
findSpanTransitions
(
spanned
,
displayDensity
);
StringBuilder
html
=
new
StringBuilder
(
spanned
.
length
());
int
previousTransition
=
0
;
...
...
@@ -100,11 +105,12 @@ import java.util.regex.Pattern;
return
html
.
toString
();
}
private
static
SparseArray
<
Transition
>
findSpanTransitions
(
Spanned
spanned
)
{
private
static
SparseArray
<
Transition
>
findSpanTransitions
(
Spanned
spanned
,
float
displayDensity
)
{
SparseArray
<
Transition
>
spanTransitions
=
new
SparseArray
<>();
for
(
Object
span
:
spanned
.
getSpans
(
0
,
spanned
.
length
(),
Object
.
class
))
{
@Nullable
String
openingTag
=
getOpeningTag
(
span
);
@Nullable
String
openingTag
=
getOpeningTag
(
span
,
displayDensity
);
@Nullable
String
closingTag
=
getClosingTag
(
span
);
int
spanStart
=
spanned
.
getSpanStart
(
span
);
int
spanEnd
=
spanned
.
getSpanEnd
(
span
);
...
...
@@ -120,7 +126,7 @@ import java.util.regex.Pattern;
}
@Nullable
private
static
String
getOpeningTag
(
Object
span
)
{
private
static
String
getOpeningTag
(
Object
span
,
float
displayDensity
)
{
if
(
span
instanceof
ForegroundColorSpan
)
{
ForegroundColorSpan
colorSpan
=
(
ForegroundColorSpan
)
span
;
return
Util
.
formatInvariant
(
...
...
@@ -132,6 +138,13 @@ import java.util.regex.Pattern;
HtmlUtils
.
toCssRgba
(
colorSpan
.
getBackgroundColor
()));
}
else
if
(
span
instanceof
HorizontalTextInVerticalContextSpan
)
{
return
"<span style='text-combine-upright:all;'>"
;
}
else
if
(
span
instanceof
AbsoluteSizeSpan
)
{
AbsoluteSizeSpan
absoluteSizeSpan
=
(
AbsoluteSizeSpan
)
span
;
float
sizeCssPx
=
absoluteSizeSpan
.
getDip
()
?
absoluteSizeSpan
.
getSize
()
:
absoluteSizeSpan
.
getSize
()
/
displayDensity
;
return
Util
.
formatInvariant
(
"<span style='font-size:%.2fpx;'>"
,
sizeCssPx
);
}
else
if
(
span
instanceof
TypefaceSpan
)
{
@Nullable
String
fontFamily
=
((
TypefaceSpan
)
span
).
getFamily
();
return
fontFamily
!=
null
...
...
@@ -171,7 +184,8 @@ import java.util.regex.Pattern;
private
static
String
getClosingTag
(
Object
span
)
{
if
(
span
instanceof
ForegroundColorSpan
||
span
instanceof
BackgroundColorSpan
||
span
instanceof
HorizontalTextInVerticalContextSpan
)
{
||
span
instanceof
HorizontalTextInVerticalContextSpan
||
span
instanceof
AbsoluteSizeSpan
)
{
return
"</span>"
;
}
else
if
(
span
instanceof
TypefaceSpan
)
{
@Nullable
String
fontFamily
=
((
TypefaceSpan
)
span
).
getFamily
();
...
...
library/ui/src/main/java/com/google/android/exoplayer2/ui/SubtitleWebView.java
View file @
eb7c1470
...
...
@@ -309,7 +309,9 @@ import java.util.List;
horizontalTranslatePercent
,
verticalTranslatePercent
))
.
append
(
Util
.
formatInvariant
(
"<span style=\"background-color:%s;\">"
,
backgroundColorCss
))
.
append
(
SpannedToHtmlConverter
.
convert
(
cue
.
text
))
.
append
(
SpannedToHtmlConverter
.
convert
(
cue
.
text
,
getContext
().
getResources
().
getDisplayMetrics
().
density
))
.
append
(
"</span>"
)
.
append
(
"</div>"
);
}
...
...
library/ui/src/test/java/com/google/android/exoplayer2/ui/SpannedToHtmlConverterTest.java
View file @
eb7c1470
...
...
@@ -22,21 +22,31 @@ import android.graphics.Color;
import
android.graphics.Typeface
;
import
android.text.SpannableString
;
import
android.text.Spanned
;
import
android.text.style.AbsoluteSizeSpan
;
import
android.text.style.BackgroundColorSpan
;
import
android.text.style.ForegroundColorSpan
;
import
android.text.style.StyleSpan
;
import
android.text.style.TypefaceSpan
;
import
android.text.style.UnderlineSpan
;
import
androidx.test.core.app.ApplicationProvider
;
import
androidx.test.ext.junit.runners.AndroidJUnit4
;
import
com.google.android.exoplayer2.text.span.HorizontalTextInVerticalContextSpan
;
import
com.google.android.exoplayer2.text.span.RubySpan
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.robolectric.annotation.Config
;
/** Tests for {@link SpannedToHtmlConverter}. */
@RunWith
(
AndroidJUnit4
.
class
)
public
class
SpannedToHtmlConverterTest
{
private
final
float
displayDensity
;
public
SpannedToHtmlConverterTest
()
{
displayDensity
=
ApplicationProvider
.
getApplicationContext
().
getResources
().
getDisplayMetrics
().
density
;
}
@Test
public
void
convert_supportsForegroundColorSpan
()
{
SpannableString
spanned
=
new
SpannableString
(
"String with colored section"
);
...
...
@@ -46,7 +56,7 @@ public class SpannedToHtmlConverterTest {
"String with colored"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
)
.
isEqualTo
(
"String with <span style='color:rgba(64,32,16,0.200);'>colored</span> section"
);
...
...
@@ -61,7 +71,7 @@ public class SpannedToHtmlConverterTest {
"String with highlighted"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
)
.
isEqualTo
(
...
...
@@ -78,7 +88,7 @@ public class SpannedToHtmlConverterTest {
"Vertical text with 123"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
)
.
isEqualTo
(
...
...
@@ -86,6 +96,40 @@ public class SpannedToHtmlConverterTest {
+
"horizontal numbers"
);
}
// Set the screen density so we see that px are handled differently to dp.
@Config
(
qualifiers
=
"xhdpi"
)
@Test
public
void
convert_supportsAbsoluteSizeSpan_px
()
{
SpannableString
spanned
=
new
SpannableString
(
"String with 10px section"
);
spanned
.
setSpan
(
new
AbsoluteSizeSpan
(
/* size= */
10
,
/* dip= */
false
),
"String with "
.
length
(),
"String with 10px"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
// 10 Android px are converted to 5 CSS px because WebView treats 1 CSS px as 1 Android dp
// and we're using screen density xhdpi i.e. density=2.
assertThat
(
html
).
isEqualTo
(
"String with <span style='font-size:5.00px;'>10px</span> section"
);
}
// Set the screen density so we see that px are handled differently to dp.
@Config
(
qualifiers
=
"xhdpi"
)
@Test
public
void
convert_supportsAbsoluteSizeSpan_dp
()
{
SpannableString
spanned
=
new
SpannableString
(
"String with 10dp section"
);
spanned
.
setSpan
(
new
AbsoluteSizeSpan
(
/* size= */
10
,
/* dip= */
true
),
"String with "
.
length
(),
"String with 10dp"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"String with <span style='font-size:10.00px;'>10dp</span> section"
);
}
@Test
public
void
convert_supportsTypefaceSpan
()
{
SpannableString
spanned
=
new
SpannableString
(
"String with Times New Roman section"
);
...
...
@@ -95,7 +139,7 @@ public class SpannedToHtmlConverterTest {
"String with Times New Roman"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
)
.
isEqualTo
(
...
...
@@ -112,7 +156,7 @@ public class SpannedToHtmlConverterTest {
"String with unstyled"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"String with unstyled section"
);
}
...
...
@@ -137,7 +181,7 @@ public class SpannedToHtmlConverterTest {
"String with bold, italic and bold-italic"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
)
.
isEqualTo
(
...
...
@@ -159,7 +203,7 @@ public class SpannedToHtmlConverterTest {
"String with over-annotated and under-annotated"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
)
.
isEqualTo
(
...
...
@@ -185,28 +229,31 @@ public class SpannedToHtmlConverterTest {
"String with underlined"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"String with <u>underlined</u> section."
);
}
@Test
public
void
convert_escapesHtmlInUnspannedString
()
{
String
html
=
SpannedToHtmlConverter
.
convert
(
"String with <b>bold</b> tags"
);
String
html
=
SpannedToHtmlConverter
.
convert
(
"String with <b>bold</b> tags"
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"String with <b>bold</b> tags"
);
}
@Test
public
void
convert_handlesLinebreakInUnspannedString
()
{
String
html
=
SpannedToHtmlConverter
.
convert
(
"String with\nnew line and\r\ncrlf style too"
);
String
html
=
SpannedToHtmlConverter
.
convert
(
"String with\nnew line and\r\ncrlf style too"
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"String with<br>new line and<br>crlf style too"
);
}
@Test
public
void
convert_doesntConvertAmpersandLineFeedToBrTag
()
{
String
html
=
SpannedToHtmlConverter
.
convert
(
"String with new line ampersand code"
);
String
html
=
SpannedToHtmlConverter
.
convert
(
"String with new line ampersand code"
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"String with&#10;new line ampersand code"
);
}
...
...
@@ -220,14 +267,16 @@ public class SpannedToHtmlConverterTest {
"String with <foo>unrecognised</foo>"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"String with <i><foo>unrecognised</foo></i> tags"
);
}
@Test
public
void
convert_handlesLinebreakInSpannedString
()
{
String
html
=
SpannedToHtmlConverter
.
convert
(
"String with\nnew line and\r\ncrlf style too"
);
String
html
=
SpannedToHtmlConverter
.
convert
(
"String with\nnew line and\r\ncrlf style too"
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"String with<br>new line and<br>crlf style too"
);
}
...
...
@@ -236,7 +285,7 @@ public class SpannedToHtmlConverterTest {
public
void
convert_convertsNonAsciiCharactersToAmpersandCodes
()
{
String
html
=
SpannedToHtmlConverter
.
convert
(
new
SpannableString
(
"Strìng with 優しいの non-ASCII characters"
));
new
SpannableString
(
"Strìng with 優しいの non-ASCII characters"
)
,
displayDensity
);
assertThat
(
html
)
.
isEqualTo
(
"Strìng with 優しいの non-ASCII characters"
);
...
...
@@ -256,7 +305,7 @@ public class SpannedToHtmlConverterTest {
"String with unrecognised"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"String with unrecognised span"
);
}
...
...
@@ -270,7 +319,7 @@ public class SpannedToHtmlConverterTest {
spanned
.
setSpan
(
new
StyleSpan
(
Typeface
.
ITALIC
),
start
,
end
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
spanned
.
setSpan
(
new
UnderlineSpan
(),
start
,
end
,
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"String with <b><i><u>italic-bold-underlined</u></i></b> section"
);
}
...
...
@@ -287,7 +336,7 @@ public class SpannedToHtmlConverterTest {
"String with italic and bold"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"String with <i>italic and <b>bold</b></i> section"
);
}
...
...
@@ -306,7 +355,7 @@ public class SpannedToHtmlConverterTest {
"String with italic and bold section"
.
length
(),
Spanned
.
SPAN_EXCLUSIVE_EXCLUSIVE
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
);
String
html
=
SpannedToHtmlConverter
.
convert
(
spanned
,
displayDensity
);
assertThat
(
html
).
isEqualTo
(
"<i>String with italic <b>and bold</i> section</b>"
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment