Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
AloqaIM-Android
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
AloqaIM-Android
Commits
cf8b2b50
Unverified
Commit
cf8b2b50
authored
Dec 13, 2017
by
Lucio Maciel
Committed by
GitHub
Dec 13, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #621 from filipedelimabrito/improvement/svg-support
[IMPROVEMENT] SVG support
parents
046b60b9
d176a339
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
293 additions
and
4 deletions
+293
-4
build.gradle
app/build.gradle
+2
-0
LayoutHelper.kt
app/src/main/java/chat/rocket/android/app/LayoutHelper.kt
+1
-1
RocketChatApplication.kt
...ain/java/chat/rocket/android/app/RocketChatApplication.kt
+17
-2
ChatListFragment.kt
...java/chat/rocket/android/app/chatlist/ChatListFragment.kt
+1
-1
ColorImage.kt
...src/main/java/chat/rocket/android/app/utils/ColorImage.kt
+134
-0
CustomImageFormatConfigurator.kt
...rocket/android/app/utils/CustomImageFormatConfigurator.kt
+24
-0
SvgDecoder.kt
...src/main/java/chat/rocket/android/app/utils/SvgDecoder.kt
+111
-0
dependencies.gradle
dependencies.gradle
+3
-0
No files found.
app/build.gradle
View file @
cf8b2b50
...
...
@@ -71,6 +71,8 @@ dependencies {
implementation
libraries
.
floatingSearchView
implementation
libraries
.
androidSvg
testImplementation
libraries
.
junit
androidTestImplementation
(
libraries
.
expressoCore
,
{
exclude
group:
'com.android.support'
,
module:
'support-annotations'
...
...
app/src/main/java/chat/rocket/android/app/LayoutHelper.kt
View file @
cf8b2b50
...
...
@@ -30,7 +30,7 @@ class LayoutHelper {
childOfContent
?.
viewTreeObserver
?.
addOnGlobalLayoutListener
(
listener
)
frameLayoutParams
=
childOfContent
?.
layoutParams
as
FrameLayout
.
LayoutParams
}
catch
(
exception
:
ClassCastException
)
{
// TODO: are we using the android.util.Log for logging that type of errors?
// TODO: are we using the android.util.Log for logging that type of errors?
or should we use the SDK logger?
Log
.
e
(
"ERROR"
,
exception
.
message
)
}
}
...
...
app/src/main/java/chat/rocket/android/app/RocketChatApplication.kt
View file @
cf8b2b50
...
...
@@ -3,8 +3,11 @@ package chat.rocket.android.app
import
android.app.Activity
import
android.app.Application
import
chat.rocket.android.BuildConfig
import
chat.rocket.android.app.utils.CustomImageFormatConfigurator
import
com.facebook.drawee.backends.pipeline.DraweeConfig
import
chat.rocket.android.dagger.DaggerAppComponent
import
com.facebook.drawee.backends.pipeline.Fresco
import
com.facebook.imagepipeline.core.ImagePipelineConfig
import
com.jakewharton.threetenabp.AndroidThreeTen
import
dagger.android.AndroidInjector
import
dagger.android.DispatchingAndroidInjector
...
...
@@ -22,12 +25,24 @@ class RocketChatApplication : Application(), HasActivityInjector {
DaggerAppComponent
.
builder
().
application
(
this
).
build
().
inject
(
this
)
Fresco
.
initialize
(
this
)
AndroidThreeTen
.
init
(
this
)
setupFresco
()
setupTimber
()
}
private
fun
setupFresco
()
{
val
imagePipelineConfig
=
ImagePipelineConfig
.
newBuilder
(
this
)
.
setImageDecoderConfig
(
CustomImageFormatConfigurator
.
createImageDecoderConfig
())
.
build
()
val
draweeConfigBuilder
=
DraweeConfig
.
newBuilder
()
CustomImageFormatConfigurator
.
addCustomDrawableFactories
(
draweeConfigBuilder
)
Fresco
.
initialize
(
this
,
imagePipelineConfig
,
draweeConfigBuilder
.
build
())
}
private
fun
setupTimber
()
{
if
(
BuildConfig
.
DEBUG
)
{
Timber
.
plant
(
Timber
.
DebugTree
())
...
...
app/src/main/java/chat/rocket/android/app/chatlist/ChatListFragment.kt
View file @
cf8b2b50
...
...
@@ -91,4 +91,4 @@ class ChatListFragment : Fragment() {
recycler_view
.
addItemDecoration
(
DividerItemDecoration
(
this
,
DividerItemDecoration
.
VERTICAL
))
}
}
}
\ No newline at end of file
}
app/src/main/java/chat/rocket/android/app/utils/ColorImage.kt
0 → 100644
View file @
cf8b2b50
package
chat.rocket.android.app.utils
import
android.graphics.drawable.ColorDrawable
import
android.graphics.drawable.Drawable
import
android.support.annotation.ColorInt
import
android.support.annotation.Nullable
import
android.support.v4.graphics.ColorUtils
import
com.facebook.common.internal.ByteStreams
import
com.facebook.imageformat.ImageFormat
import
com.facebook.imageformat.ImageFormatCheckerUtils
import
com.facebook.imagepipeline.common.ImageDecodeOptions
import
com.facebook.imagepipeline.decoder.ImageDecoder
import
com.facebook.imagepipeline.drawable.DrawableFactory
import
com.facebook.imagepipeline.image.CloseableImage
import
com.facebook.imagepipeline.image.EncodedImage
import
com.facebook.imagepipeline.image.QualityInfo
import
java.io.IOException
/**
* Simple decoder that can decode color images that have the following format: <color>#FF5722</color>.
*
* @see {https://github.com/facebook/fresco/blob/master/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/imageformat/color/ColorImageExample.java}
*/
object
ColorImage
{
// Custom ImageFormat for color images.
private
val
imageFormatColor
=
ImageFormat
(
"IMAGE_FORMAT_COLOR"
,
"color"
)
// XML color tag that our colors must start with.
val
colorTag
=
"<color>"
/**
* Creates a new image format checker for [ColorImage.imageFormatColor].
*
* @return the image format checker.
*/
fun
createFormatChecker
():
ImageFormat
.
FormatChecker
=
ColorFormatChecker
()
/**
* Creates a new decoder that can decode [ColorImage.imageFormatColor] images.
*
* @return the decoder.
*/
fun
createDecoder
():
ImageDecoder
=
ColorDecoder
()
fun
createDrawableFactory
():
ColorDrawableFactory
=
ColorDrawableFactory
()
/**
* Custom color format checker that verifies that the header of the file corresponds to our [ColorImage.colorTag].
*/
class
ColorFormatChecker
:
ImageFormat
.
FormatChecker
{
private
val
header
=
ImageFormatCheckerUtils
.
asciiBytes
(
colorTag
)
override
fun
getHeaderSize
():
Int
{
return
header
.
size
}
@Nullable
override
fun
determineFormat
(
headerBytes
:
ByteArray
,
headerSize
:
Int
):
ImageFormat
?
{
if
(
headerSize
>
getHeaderSize
())
{
if
(
ImageFormatCheckerUtils
.
startsWithPattern
(
headerBytes
,
header
))
{
return
imageFormatColor
}
}
return
null
}
}
/**
* Custom closeable color image that holds a single color int value.
*/
class
CloseableColorImage
(
@field
:
ColorInt
@get
:
ColorInt
val
color
:
Int
)
:
CloseableImage
()
{
private
var
isClosed
=
false
override
fun
close
()
{
isClosed
=
true
}
override
fun
getSizeInBytes
():
Int
=
0
override
fun
isClosed
():
Boolean
=
isClosed
override
fun
getWidth
():
Int
=
0
override
fun
getHeight
():
Int
=
0
}
/**
* Decodes a color XML tag: <color>#rrggbb</color>.
*/
class
ColorDecoder
:
ImageDecoder
{
@Nullable
override
fun
decode
(
encodedImage
:
EncodedImage
,
length
:
Int
,
qualityInfo
:
QualityInfo
,
options
:
ImageDecodeOptions
):
CloseableImage
?
{
try
{
// Read the file as a string
val
text
=
String
(
ByteStreams
.
toByteArray
(
encodedImage
.
inputStream
))
// Check if the string matches "<color>#"
if
(!
text
.
startsWith
(
colorTag
+
"#"
))
{
return
null
}
// Parse the int value between # and <
val
startIndex
=
colorTag
.
length
+
1
val
endIndex
=
text
.
lastIndexOf
(
'<'
)
var
color
=
Integer
.
parseInt
(
text
.
substring
(
startIndex
,
endIndex
),
16
)
// Add the alpha component so that we actually see the color
color
=
ColorUtils
.
setAlphaComponent
(
color
,
255
)
// Return the CloseableImage
return
CloseableColorImage
(
color
)
}
catch
(
e
:
IOException
)
{
// TODO: are we using the android.util.Log for logging that type of errors? or should we use the SDK logger?
e
.
printStackTrace
()
}
// Return nothing if an error occurred
return
null
}
}
/**
* Color drawable factory that is able to render a [CloseableColorImage] by creating a new [ColorDrawable] for the given color.
*/
class
ColorDrawableFactory
:
DrawableFactory
{
override
fun
supportsImageType
(
image
:
CloseableImage
):
Boolean
{
// We can only handle CloseableColorImages.
return
image
is
CloseableColorImage
}
@Nullable
override
fun
createDrawable
(
image
:
CloseableImage
):
Drawable
?
{
// Just return a simple ColorDrawable with the given color value.
return
ColorDrawable
((
image
as
CloseableColorImage
).
color
)
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/app/utils/CustomImageFormatConfigurator.kt
0 → 100644
View file @
cf8b2b50
package
chat.rocket.android.app.utils
import
com.facebook.drawee.backends.pipeline.DraweeConfig
import
com.facebook.imagepipeline.decoder.ImageDecoderConfig
/**
* Utility class to add custom decoders and drawable factories.
*
* @see {https://github.com/facebook/fresco/blob/master/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/CustomImageFormatConfigurator.java}
*/
object
CustomImageFormatConfigurator
{
fun
createImageDecoderConfig
()
:
ImageDecoderConfig
{
return
ImageDecoderConfig
.
newBuilder
()
.
addDecodingCapability
(
SvgDecoder
.
svgFormat
,
SvgDecoder
.
SvgFormatChecker
(),
SvgDecoder
.
Decoder
())
.
build
()
}
fun
addCustomDrawableFactories
(
draweeConfigBuilder
:
DraweeConfig
.
Builder
)
{
// We always add the color drawable factory so that it can be used for image decoder overrides.
draweeConfigBuilder
.
addCustomDrawableFactory
(
ColorImage
.
createDrawableFactory
())
draweeConfigBuilder
.
addCustomDrawableFactory
(
SvgDecoder
.
SvgDrawableFactory
())
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/app/utils/SvgDecoder.kt
0 → 100644
View file @
cf8b2b50
package
chat.rocket.android.app.utils
import
android.graphics.Rect
import
android.graphics.drawable.Drawable
import
android.graphics.drawable.PictureDrawable
import
android.support.annotation.Nullable
import
com.caverock.androidsvg.SVG
import
com.caverock.androidsvg.SVGParseException
import
com.facebook.imageformat.ImageFormat
import
com.facebook.imageformat.ImageFormatCheckerUtils
import
com.facebook.imagepipeline.common.ImageDecodeOptions
import
com.facebook.imagepipeline.decoder.ImageDecoder
import
com.facebook.imagepipeline.drawable.DrawableFactory
import
com.facebook.imagepipeline.image.CloseableImage
import
com.facebook.imagepipeline.image.EncodedImage
import
com.facebook.imagepipeline.image.QualityInfo
/**
* SVG example that defines all classes required to decode and render SVG images.
*
* @see {https://github.com/facebook/fresco/blob/master/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/imageformat/svg/SvgDecoderExample.java}
*/
object
SvgDecoder
{
val
svgFormat
=
ImageFormat
(
"SVG_FORMAT"
,
"svg"
)
// We do not include the closing ">" since there can be additional information.
private
val
headerTag
=
"<?xml"
private
val
possibleHeaderTags
=
arrayOf
(
ImageFormatCheckerUtils
.
asciiBytes
(
"<svg"
))
/**
* Custom SVG format checker that verifies that the header of the file corresponds to our [SvgDecoder.headerTag] or [SvgDecoder.possibleHeaderTags].
*/
class
SvgFormatChecker
:
ImageFormat
.
FormatChecker
{
private
val
header
=
ImageFormatCheckerUtils
.
asciiBytes
(
headerTag
)
override
fun
getHeaderSize
():
Int
{
return
header
.
size
}
@Nullable
override
fun
determineFormat
(
headerBytes
:
ByteArray
,
headerSize
:
Int
):
ImageFormat
?
{
if
(
headerSize
>
getHeaderSize
())
{
if
(
ImageFormatCheckerUtils
.
startsWithPattern
(
headerBytes
,
header
))
{
return
svgFormat
}
if
(
possibleHeaderTags
.
any
{
ImageFormatCheckerUtils
.
startsWithPattern
(
headerBytes
,
it
)
&&
ImageFormatCheckerUtils
.
indexOfPattern
(
headerBytes
,
headerBytes
.
size
,
header
,
header
.
size
)
>
-
1
})
{
return
svgFormat
}
}
return
null
}
}
/**
* Custom closeable SVG image that holds a single SVG.
*/
class
CloseableSvgImage
(
val
svg
:
SVG
)
:
CloseableImage
()
{
private
var
isClose
=
false
override
fun
close
()
{
isClose
=
true
}
override
fun
getSizeInBytes
():
Int
=
0
override
fun
isClosed
():
Boolean
=
isClose
override
fun
getWidth
():
Int
=
0
override
fun
getHeight
():
Int
=
0
}
/**
* Decodes a [SvgDecoder.svgFormat] image.
*/
class
Decoder
:
ImageDecoder
{
@Nullable
override
fun
decode
(
encodedImage
:
EncodedImage
,
length
:
Int
,
qualityInfo
:
QualityInfo
,
options
:
ImageDecodeOptions
):
CloseableImage
?
{
try
{
val
svg
=
SVG
.
getFromInputStream
(
encodedImage
.
inputStream
)
return
CloseableSvgImage
(
svg
)
}
catch
(
e
:
SVGParseException
)
{
// TODO: are we using the android.util.Log for logging that type of errors? or should we use the SDK logger?
e
.
printStackTrace
()
}
// Return nothing if an error occurred
return
null
}
}
/**
* SVG drawable factory that creates [PictureDrawable]s for SVG images.
*/
class
SvgDrawableFactory
:
DrawableFactory
{
override
fun
supportsImageType
(
image
:
CloseableImage
):
Boolean
{
return
image
is
CloseableSvgImage
}
@Nullable
override
fun
createDrawable
(
image
:
CloseableImage
):
Drawable
?
{
return
SvgPictureDrawable
((
image
as
CloseableSvgImage
).
svg
)
}
}
class
SvgPictureDrawable
(
private
val
svg
:
SVG
)
:
PictureDrawable
(
null
)
{
override
fun
onBoundsChange
(
bounds
:
Rect
)
{
super
.
onBoundsChange
(
bounds
)
picture
=
svg
.
renderToPicture
(
bounds
.
width
(),
bounds
.
height
())
}
}
}
\ No newline at end of file
dependencies.gradle
View file @
cf8b2b50
...
...
@@ -23,6 +23,7 @@ ext {
timber
:
'4.5.1'
,
threeTenABP
:
'1.0.5'
,
floatingSearchView:
'2.1.1'
,
androidSvg
:
'1.2.1'
,
// For testing
junit
:
'4.12'
,
...
...
@@ -70,6 +71,8 @@ ext {
floatingSearchView
:
"com.github.arimorty:floatingsearchview:${versions.floatingSearchView}"
,
androidSvg
:
"com.caverock:androidsvg:${versions.androidSvg}"
,
// For testing
toolsJar
:
files
(
Jvm
.
current
().
getToolsJar
()),
junit
:
"junit:junit:$versions.junit"
,
...
...
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