Skip to content

Commit

Permalink
Maintenance (#802)
Browse files Browse the repository at this point in the history
* Dependency versions bump
* Stop further decoding on error. Fixes incorrect error code in #801
* Sample dependency versions bump
* Stronger suppress warning for workaround in LibraryLoader
* Fix java to kotlin conversion of TexturePlaceholderFragment.kt
* Clear GifTextureView when removing source. Fixes #745
* Fix current position calculation on the subsequent loops on first frame. Fixes #657
* Update NDK to 25.0.8775105
* Release 1.2.25
  • Loading branch information
koral-- authored Aug 18, 2022
1 parent 8610823 commit 7a700e9
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 148 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
#### 1.2.25
- 2022-08-18 - [commits](https://github.com/koral--/android-gif-drawable/compare/v1.2.24...v1.2.25)
- Fix sample size not taken into account [(#797)](https://github.com/koral--/android-gif-drawable/pull/797) [(#798)](https://github.com/koral--/android-gif-drawable/pull/798)
- Stop further decoding on error [(#801)](https://github.com/koral--/android-gif-drawable/pull/801)
- Clear GifTextureView when removing source [(#745)](https://github.com/koral--/android-gif-drawable/pull/745)
- Fix negative current position [(#657)](https://github.com/koral--/android-gif-drawable/pull/657)

#### 1.2.24
- 2022-01-17 - [commits](https://github.com/koral--/android-gif-drawable/compare/v1.2.23...v1.2.24)
- Limit comment maximum length [(#766)](https://github.com/koral--/android-gif-drawable/pull/766)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Bundled GIFLib via JNI is used to render frames. This way should be more efficie
Insert the following dependency to `build.gradle` file of your project.
```groovy
dependencies {
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.24'
implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.25'
}
```
Note that Maven central repository should be defined eg. in top-level `build.gradle` like this:
Expand Down
176 changes: 82 additions & 94 deletions android-gif-drawable/src/main/c/decoding.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,113 +27,103 @@ void DDGifSlurp(GifInfo *info, bool decode, bool exitAfterFrame) {
break;
}
bool isInitialPass = !decode && !exitAfterFrame;
switch (RecordType) {
case IMAGE_DESC_RECORD_TYPE:
if (RecordType == IMAGE_DESC_RECORD_TYPE) {
if (DGifGetImageDesc(gifFilePtr, isInitialPass, info->originalWidth,
info->originalHeight) == GIF_ERROR) {
break;
}

if (DGifGetImageDesc(gifFilePtr, isInitialPass, info->originalWidth, info->originalHeight) == GIF_ERROR) {
if (isInitialPass) {
if (!updateGCB(info, &lastAllocatedGCBIndex)) {
break;
}
}

if (isInitialPass) {
if (!updateGCB(info, &lastAllocatedGCBIndex)) {
break;
}
if (decode) {
const uint_fast32_t newRasterSize = gifFilePtr->Image.Width * gifFilePtr->Image.Height;
if (newRasterSize == 0) {
free(info->rasterBits);
info->rasterBits = NULL;
info->rasterSize = newRasterSize;
break;
}

if (decode) {
const uint_fast32_t newRasterSize = gifFilePtr->Image.Width * gifFilePtr->Image.Height;
if (newRasterSize == 0) {
free(info->rasterBits);
info->rasterBits = NULL;
info->rasterSize = newRasterSize;
return;
}
const int_fast32_t widthOverflow = gifFilePtr->Image.Width - info->originalWidth;
const int_fast32_t heightOverflow = gifFilePtr->Image.Height - info->originalHeight;
if (newRasterSize > info->rasterSize || widthOverflow > 0 || heightOverflow > 0) {
const int_fast32_t widthOverflow = gifFilePtr->Image.Width - info->originalWidth;
const int_fast32_t heightOverflow = gifFilePtr->Image.Height - info->originalHeight;
if (newRasterSize > info->rasterSize || widthOverflow > 0 || heightOverflow > 0) {
void *tmpRasterBits = reallocarray(info->rasterBits, newRasterSize, sizeof(GifPixelType));
if (tmpRasterBits == NULL) {
gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
break;
}
info->rasterBits = tmpRasterBits;
info->rasterSize = newRasterSize;
if (tmpRasterBits == NULL) {
gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
break;
}
if (gifFilePtr->Image.Interlace) {
uint_fast16_t i, j;
/*
* The way an interlaced image should be read -
* offsets and jumps...
*/
uint_fast8_t InterlacedOffset[] = {0, 4, 2, 1};
uint_fast8_t InterlacedJumps[] = {8, 8, 4, 2};
/* Need to perform 4 passes on the image */
for (i = 0; i < 4; i++)
info->rasterBits = tmpRasterBits;
info->rasterSize = newRasterSize;
}
if (gifFilePtr->Image.Interlace) {
uint_fast16_t i, j;
/*
* The way an interlaced image should be read -
* offsets and jumps...
*/
uint_fast8_t InterlacedOffset[] = {0, 4, 2, 1};
uint_fast8_t InterlacedJumps[] = {8, 8, 4, 2};
/* Need to perform 4 passes on the image */
for (i = 0; i < 4; i++)
for (j = InterlacedOffset[i]; j < gifFilePtr->Image.Height; j += InterlacedJumps[i]) {
if (DGifGetLine(gifFilePtr, info->rasterBits + j * gifFilePtr->Image.Width, gifFilePtr->Image.Width) == GIF_ERROR)
break;
}
} else {
if (DGifGetLine(gifFilePtr, info->rasterBits, gifFilePtr->Image.Width * gifFilePtr->Image.Height) == GIF_ERROR) {
break;
break;
}
} else {
if (DGifGetLine(gifFilePtr, info->rasterBits, gifFilePtr->Image.Width * gifFilePtr->Image.Height) == GIF_ERROR) {
break;
}
}

if (info->sampleSize > 1) {
unsigned char *dst = info->rasterBits;
unsigned char *src = info->rasterBits;
unsigned char *const srcEndImage = info->rasterBits + gifFilePtr->Image.Width * gifFilePtr->Image.Height;
if (info->sampleSize > 1) {
unsigned char *dst = info->rasterBits;
unsigned char *src = info->rasterBits;
unsigned char *const srcEndImage = info->rasterBits + gifFilePtr->Image.Width * gifFilePtr->Image.Height;
do {
unsigned char *srcNextLineStart = src + gifFilePtr->Image.Width * info->sampleSize;
unsigned char *const srcEndLine = src + gifFilePtr->Image.Width;
unsigned char *dstEndLine = dst + gifFilePtr->Image.Width / info->sampleSize;
do {
unsigned char *srcNextLineStart = src + gifFilePtr->Image.Width * info->sampleSize;
unsigned char *const srcEndLine = src + gifFilePtr->Image.Width;
unsigned char *dstEndLine = dst + gifFilePtr->Image.Width / info->sampleSize;
do {
*dst = *src;
dst++;
src += info->sampleSize;
} while (src < srcEndLine);
dst = dstEndLine;
src = srcNextLineStart;
} while (src < srcEndImage);
*dst = *src;
dst++;
src += info->sampleSize;
} while (src < srcEndLine);
dst = dstEndLine;
src = srcNextLineStart;
} while (src < srcEndImage);
}
return;
} else {
do {
if (DGifGetCodeNext(gifFilePtr, &ExtData) == GIF_ERROR) {
break;
}
} while (ExtData != NULL);
if (exitAfterFrame) {
return;
} else {
do {
if (DGifGetCodeNext(gifFilePtr, &ExtData) == GIF_ERROR) {
break;
}
} while (ExtData != NULL);
if (exitAfterFrame) {
return;
}
}
}
} else if (RecordType == EXTENSION_RECORD_TYPE) {
if (DGifGetExtension(gifFilePtr, &ExtFunction, &ExtData) == GIF_ERROR) {
break;

case EXTENSION_RECORD_TYPE:
if (DGifGetExtension(gifFilePtr, &ExtFunction, &ExtData) == GIF_ERROR) {
}
if (isInitialPass) {
updateGCB(info, &lastAllocatedGCBIndex);
if (readExtensions(ExtFunction, ExtData, info) == GIF_ERROR) {
break;
}
if (isInitialPass) {
updateGCB(info, &lastAllocatedGCBIndex);
if (readExtensions(ExtFunction, ExtData, info) == GIF_ERROR) {
break;
}
}
while (ExtData != NULL) {
if (DGifGetExtensionNext(gifFilePtr, &ExtData) == GIF_ERROR) {
break;
}
while (ExtData != NULL) {
if (DGifGetExtensionNext(gifFilePtr, &ExtData) == GIF_ERROR) {
break;
}
if (isInitialPass && readExtensions(ExtFunction, ExtData, info) == GIF_ERROR) {
break;
}
if (isInitialPass && readExtensions(ExtFunction, ExtData, info) == GIF_ERROR) {
break;
}
break;

case TERMINATE_RECORD_TYPE:
break;

default:
break;
}
}
} while (RecordType != TERMINATE_RECORD_TYPE);

Expand All @@ -151,17 +141,15 @@ static int readExtensions(int ExtFunction, GifByteType *ExtData, GifInfo *info)
}

GCB->DelayTime = GCB->DelayTime > 1 ? GCB->DelayTime * 10 : DEFAULT_FRAME_DURATION_MS;
}
else if (ExtFunction == COMMENT_EXT_FUNC_CODE) {
} else if (ExtFunction == COMMENT_EXT_FUNC_CODE) {
if (getComment(ExtData, info) == GIF_ERROR) {
info->gifFilePtr->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
return GIF_ERROR;
}
}
else if (ExtFunction == APPLICATION_EXT_FUNC_CODE) {
} else if (ExtFunction == APPLICATION_EXT_FUNC_CODE) {
char const *string = (char const *) (ExtData + 1);
if (strncmp("NETSCAPE2.0", string, ExtData[0]) == 0
|| strncmp("ANIMEXTS1.0", string, ExtData[0]) == 0) {
|| strncmp("ANIMEXTS1.0", string, ExtData[0]) == 0) {
if (DGifGetExtensionNext(info->gifFilePtr, &ExtData) == GIF_ERROR) {
return GIF_ERROR;
}
Expand All @@ -180,11 +168,11 @@ static int readExtensions(int ExtFunction, GifByteType *ExtData, GifInfo *info)
static int getComment(GifByteType *Bytes, GifInfo *info) {
unsigned int length = (unsigned int) Bytes[0];
size_t offset = info->comment != NULL ? strlen(info->comment) : 0;
unsigned int newLength = length + offset + 1;
if (newLength > COMMENT_LENGTH_MAX) {
unsigned int newLength = length + offset + 1;
if (newLength > COMMENT_LENGTH_MAX) {
return GIF_OK;
}
char *ret = reallocarray(info->comment, newLength, sizeof(char));
char *ret = reallocarray(info->comment, newLength, sizeof(char));
if (ret != NULL) {
memcpy(ret + offset, &Bytes[1], length);
ret[length + offset] = 0;
Expand Down
6 changes: 3 additions & 3 deletions android-gif-drawable/src/main/c/metadata.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,13 @@ Java_pl_droidsonroids_gif_GifInfoHandle_getCurrentPosition(JNIEnv *__unused env,
if (info == NULL) {
return 0;
}
const uint_fast32_t idx = info->currentIndex;
if (info->gifFilePtr->ImageCount == 1) {
return 0;
}
uint_fast32_t i;
uint32_t sum = 0;
for (i = 0; i < idx; i++) {
const uint_fast32_t maxFrameIndex = info->currentIndex == 0 ? info->gifFilePtr->ImageCount : info->currentIndex;
for (i = 0; i < maxFrameIndex; i++) {
sum += info->controlBlock[i].DelayTime;
}

Expand Down Expand Up @@ -229,7 +229,7 @@ jint restoreSavedState(GifInfo *info, JNIEnv *env, jlongArray state, void *pixel

__unused JNIEXPORT jint JNICALL
Java_pl_droidsonroids_gif_GifInfoHandle_restoreSavedState(JNIEnv *env, jclass __unused handleClass,
jlong gifInfo, jlongArray state, jobject jbitmap) {
jlong gifInfo, jlongArray state, jobject jbitmap) {
GifInfo *const info = ((GifInfo *) (intptr_t) gifInfo);
void *pixels;
if (info == NULL || lockPixels(env, jbitmap, info, &pixels) != 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.opengl.GLES20;
import android.os.Build;
import android.os.Parcelable;
import android.util.AttributeSet;
Expand All @@ -22,6 +24,12 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;

/**
* <p>{@link TextureView} which can display animated GIFs. GifTextureView can only be used in a
* hardware accelerated window. When rendered in software, GifTextureView will draw nothing.</p>
Expand Down Expand Up @@ -329,6 +337,20 @@ public synchronized void setInputSource(@Nullable InputSource inputSource,
mRenderThread = new RenderThread(this);
if (inputSource != null) {
mRenderThread.start();
} else {
clearSurface();
}
}

private void clearSurface() {
final SurfaceTexture surfaceTexture = getSurfaceTexture();
if (surfaceTexture != null) {
final Surface surface = new Surface(surfaceTexture);
try {
surface.unlockCanvasAndPost(surface.lockCanvas(null));
} finally {
surface.release();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ private static Context getContext() {
try {
@SuppressLint("PrivateApi")
final Class<?> activityThread = Class.forName("android.app.ActivityThread");
@SuppressLint("DiscouragedPrivateApi")
final Method currentApplicationMethod = activityThread.getDeclaredMethod("currentApplication");
sAppContext = (Context) currentApplicationMethod.invoke(null);
} catch (Exception e) {
Expand Down
24 changes: 12 additions & 12 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
buildscript {
ext {
versions = [
compileSdk : 31,
targetSdk : 31,
compileSdk : 32,
targetSdk : 32,
minSdk : 17,
ndk : '23.1.7779620',
androidxAppcompat : '1.2.0',
androidxAnnotations: '1.3.0',
ndk : '25.0.8775105',
androidxAppcompat : '1.5.0',
androidxAnnotations: '1.4.0',
androidxTest : '1.4.0',
coroutines : '1.3.9',
leakCanary : '2.7',
kotlin : '1.6.10',
coroutines : '1.6.4',
leakCanary : '2.9.1',
kotlin : '1.7.10',
intellijAnnotations: '13.0',
material : '1.5.0',
material : '1.6.1',
androidXextJunit : '1.1.3',
androidGradlePlugin: '7.0.3',
androidGradlePlugin: '7.2.0',
junit : '4.13.2',
mockito : '3.5.13',
mockito : '4.6.1',
robolectric : '4.4',
assertj3 : '3.14.0',
assertj1 : '1.7.1',
concurrentunit : '0.4.6',
openglApi : 'gl1.1-android-2.1_r1',
mockwebserver : '4.9.0',
relinker : '1.4.1',
mavenPublishPlugin : '0.18.0',
mavenPublishPlugin : '0.21.0',
]
}
repositories {
Expand Down
7 changes: 5 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true

SONATYPE_HOST=DEFAULT
RELEASE_SIGNING_ENABLED=true

GROUP=pl.droidsonroids.gif
POM_ARTIFACT_ID=android-gif-drawable
VERSION_NAME=1.2.24
VERSION_NAME=1.2.25

POM_NAME=android-gif-drawable
POM_DESCRIPTION=Views and Drawable for displaying animated GIFs for Android
Expand All @@ -19,5 +22,5 @@ POM_SCM_CONNECTION=scm:git:git://github.com/koral--/android-gif-drawable.git
POM_SCM_DEV_CONNECTION=scm:git:ssh://[email protected]/koral--/android-gif-drawable.git

POM_DEVELOPER_ID=koral
POM_DEVELOPER_NAME=Karol Wrótniak
POM_DEVELOPER_NAME=Karol Wrótniak
POM_DEVELOPER_URL=https://github.com/koral--
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading

0 comments on commit 7a700e9

Please sign in to comment.