diff --git a/AXrLottie/build.gradle b/AXrLottie/build.gradle index b4782fa..52970e7 100644 --- a/AXrLottie/build.gradle +++ b/AXrLottie/build.gradle @@ -1,4 +1,6 @@ -apply plugin: 'com.android.library' +plugins { + id 'com.android.library' +} android { compileSdkVersion 30 @@ -13,6 +15,7 @@ android { consumerProguardFiles "consumer-rules.pro" externalNativeBuild { cmake { + arguments "-DANDROID_ARM_NEON=OFF" cppFlags "-std=c++14" } } @@ -36,70 +39,18 @@ android { dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.annotation:annotation:1.1.0' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test.ext:junit:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'androidx.annotation:annotation:1.2.0' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' } +// PUBLISH -//JCenter -apply plugin: 'com.github.dcendents.android-maven' -apply plugin: 'com.jfrog.bintray' - -def artifact = new Properties() -artifact.load(new FileInputStream("deploy.settings")) - -version=artifact.version -group=artifact.groupId - -install { - repositories.mavenInstaller { - pom.project { - packaging 'aar' - groupId artifact.groupId - artifactId artifact.id - version artifact.version - name artifact.id // pom.project.name must be same as bintray.pkg.name - url artifact.siteUrl - inceptionYear '2020' // HARDCODED - licenses { - license { // HARDCODED - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - distribution 'repo' - } - } - scm { - connection artifact.gitUrl - developerConnection artifact.gitUrl - url artifact.siteUrl - } - } - } -} - -def properties = new Properties() -properties.load(new FileInputStream("local.properties")) - -bintray { - user = properties.getProperty("bintray.user") - key = properties.getProperty("bintray.apikey") - - configurations = ['archives'] - pkg { - repo = "Aghajari" - name = artifact.id - websiteUrl = artifact.siteUrl - vcsUrl = artifact.gitUrl - licenses = artifact.licenses - publish = true - version { - name = artifact.version - } - } -} +apply plugin: 'maven' +apply plugin: 'maven-publish' +apply plugin: 'signing' task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs @@ -111,6 +62,12 @@ task javadoc(type: Javadoc) { classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) } +afterEvaluate { + javadoc.classpath += files(android.libraryVariants.collect { variant -> + variant.javaCompileProvider.get().classpath.files + }) +} + task javadocJar(type: Jar, dependsOn: javadoc) { classifier = 'javadoc' from javadoc.destinationDir @@ -121,13 +78,65 @@ artifacts { archives sourcesJar } -repositories { - maven { url 'https://maven.google.com' } - mavenCentral() +signing { + useInMemoryPgpKeys( + rootProject.ext["signing.keyId"], + rootProject.ext["signing.key"], + rootProject.ext["signing.password"], + ) + sign publishing.publications } tasks.withType(Javadoc) { options.addStringOption('Xdoclint:none', '-quiet') options.addStringOption('encoding', 'UTF-8') options.addStringOption('charSet', 'UTF-8') -} \ No newline at end of file +} + +def artifact = new Properties() +artifact.load(new FileInputStream("deploy.settings")) + +version = artifact.version +group = artifact.groupId +archivesBaseName = artifact.id + +afterEvaluate { + publishing { + publications { + release(MavenPublication) { + groupId artifact.groupId + artifactId artifact.id + version artifact.version + from components.release + + pom { + name = artifact.id + packaging = 'aar' + description = 'AXrLottie (Android) Renders animations and vectors exported in the bodymovin JSON format. (Using rLottie)' + url = artifact.siteUrl + + scm { + connection = artifact.gitUrl + developerConnection = artifact.gitUrl + url = artifact.siteUrl + } + + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + + developers { + developer { + id = 'Aghajari' + name = 'AmirHossein Aghajari' + email = 'amirhossein.aghajari.82@gmail.com' + } + } + } + } + } + } +} diff --git a/AXrLottie/output/aar/AXrLottie-release.aar b/AXrLottie/output/aar/AXrLottie-release.aar deleted file mode 100644 index 2b4275c..0000000 Binary files a/AXrLottie/output/aar/AXrLottie-release.aar and /dev/null differ diff --git a/AXrLottie/src/main/cpp/src/lottie/lottieitem.cpp b/AXrLottie/src/main/cpp/src/lottie/lottieitem.cpp index 7a746b8..690e2c7 100644 --- a/AXrLottie/src/main/cpp/src/lottie/lottieitem.cpp +++ b/AXrLottie/src/main/cpp/src/lottie/lottieitem.cpp @@ -597,11 +597,21 @@ void renderer::CompLayer::renderMatteLayer(VPainter *painter, const VRle &mask, srcBitmap.updateLuma(); } + auto clip = layerPainter.clipBoundingRect(); + + // if the layer has only one renderer then use it as the clip rect + // when blending 2 buffer and copy back to final buffer to avoid + // unnecessary pixel processing. + if (layer->renderList().size() == 1) + { + clip = layer->renderList()[0]->rle().boundingRect(); + } + // 2.3 draw src buffer as mask - layerPainter.drawBitmap(VPoint(), srcBitmap); + layerPainter.drawBitmap(clip, srcBitmap, clip); layerPainter.end(); // 3. draw the result buffer into painter - painter->drawBitmap(VPoint(), layerBitmap); + painter->drawBitmap(clip, layerBitmap, clip); cache.release_surface(srcBitmap); cache.release_surface(layerBitmap); diff --git a/AXrLottie/src/main/cpp/src/lottie/lottieitem_capi.cpp b/AXrLottie/src/main/cpp/src/lottie/lottieitem_capi.cpp index a4d8546..6f6fb95 100644 --- a/AXrLottie/src/main/cpp/src/lottie/lottieitem_capi.cpp +++ b/AXrLottie/src/main/cpp/src/lottie/lottieitem_capi.cpp @@ -121,7 +121,7 @@ void renderer::Layer::buildLayerNode() auto ptPtr = reinterpret_cast(pts.data()); auto elmPtr = reinterpret_cast(elm.data()); cNode.mPath.ptPtr = ptPtr; - cNode.mPath.ptCount = pts.size(); + cNode.mPath.ptCount = 2 * pts.size(); cNode.mPath.elmPtr = elmPtr; cNode.mPath.elmCount = elm.size(); cNode.mAlpha = uchar(mask.mCombinedAlpha * 255.0f); diff --git a/AXrLottie/src/main/cpp/src/lottie/lottiemodel.cpp b/AXrLottie/src/main/cpp/src/lottie/lottiemodel.cpp index daa8780..b3b4609 100644 --- a/AXrLottie/src/main/cpp/src/lottie/lottiemodel.cpp +++ b/AXrLottie/src/main/cpp/src/lottie/lottiemodel.cpp @@ -205,7 +205,7 @@ void model::Dash::getDashInfo(int frameNo, std::vector &result) const { result.clear(); - if (mData.empty()) return; + if (mData.size() <= 1) return; if (result.capacity() < mData.size()) result.reserve(mData.size() + 1); diff --git a/AXrLottie/src/main/cpp/src/lottie/lottiemodel.h b/AXrLottie/src/main/cpp/src/lottie/lottiemodel.h index 56b532c..6ad1d83 100644 --- a/AXrLottie/src/main/cpp/src/lottie/lottiemodel.h +++ b/AXrLottie/src/main/cpp/src/lottie/lottiemodel.h @@ -688,7 +688,9 @@ class Layer : public Group { int inFrame() const noexcept { return mInFrame; } int outFrame() const noexcept { return mOutFrame; } int startFrame() const noexcept { return mStartFrame; } - Color solidColor() const noexcept { return mExtra->mSolidColor; } + Color solidColor() const noexcept { + return mExtra ? mExtra->mSolidColor : Color(); + } bool autoOrient() const noexcept { return mAutoOrient; } int timeRemap(int frameNo) const; VSize layerSize() const { return mLayerSize; } @@ -705,10 +707,7 @@ class Layer : public Group { { return mTransform ? mTransform->opacity(frameNo) : 1.0f; } - Asset *asset() const - { - return (mExtra && mExtra->mAsset) ? mExtra->mAsset : nullptr; - } + Asset *asset() const { return mExtra ? mExtra->mAsset : nullptr; } struct Extra { Color mSolidColor; std::string mPreCompRefId; diff --git a/AXrLottie/src/main/cpp/src/lottie/lottieparser.cpp b/AXrLottie/src/main/cpp/src/lottie/lottieparser.cpp index 914507d..a2e86fd 100644 --- a/AXrLottie/src/main/cpp/src/lottie/lottieparser.cpp +++ b/AXrLottie/src/main/cpp/src/lottie/lottieparser.cpp @@ -145,6 +145,10 @@ class LookaheadParserHandler { return true; } + void Error() + { + st_ = kError; + } protected: explicit LookaheadParserHandler(char *str); @@ -191,6 +195,7 @@ class LottieParserImpl : public LookaheadParserHandler { int GetInt(); double GetDouble(); const char * GetString(); + std::string GetStringObject(); bool GetBool(); void GetNull(); @@ -399,7 +404,6 @@ bool LottieParserImpl::EnterObject() { if (st_ != kEnteringObject) { st_ = kError; - RAPIDJSON_ASSERT(false); return false; } @@ -411,7 +415,6 @@ bool LottieParserImpl::EnterArray() { if (st_ != kEnteringArray) { st_ = kError; - RAPIDJSON_ASSERT(false); return false; } @@ -441,7 +444,6 @@ const char *LottieParserImpl::NextObjectKey() } if (st_ != kExitingObject) { - RAPIDJSON_ASSERT(false); st_ = kError; return nullptr; } @@ -465,7 +467,6 @@ bool LottieParserImpl::NextArrayValue() } if (st_ == kError || st_ == kHasKey) { - RAPIDJSON_ASSERT(false); st_ = kError; return false; } @@ -477,7 +478,6 @@ int LottieParserImpl::GetInt() { if (st_ != kHasNumber || !v_.IsInt()) { st_ = kError; - RAPIDJSON_ASSERT(false); return 0; } @@ -490,7 +490,6 @@ double LottieParserImpl::GetDouble() { if (st_ != kHasNumber) { st_ = kError; - RAPIDJSON_ASSERT(false); return 0.; } @@ -503,7 +502,6 @@ bool LottieParserImpl::GetBool() { if (st_ != kHasBool) { st_ = kError; - RAPIDJSON_ASSERT(false); return false; } @@ -526,7 +524,6 @@ const char *LottieParserImpl::GetString() { if (st_ != kHasString) { st_ = kError; - RAPIDJSON_ASSERT(false); return nullptr; } @@ -535,6 +532,17 @@ const char *LottieParserImpl::GetString() return result; } +std::string LottieParserImpl::GetStringObject() +{ + auto str = GetString(); + + if (str) { + return std::string(str); + } + + return {}; +} + void LottieParserImpl::SkipOut(int depth) { do { @@ -543,7 +551,6 @@ void LottieParserImpl::SkipOut(int depth) } else if (st_ == kExitingArray || st_ == kExitingObject) { --depth; } else if (st_ == kError) { - RAPIDJSON_ASSERT(false); return; } @@ -609,7 +616,6 @@ void LottieParserImpl::Skip(const char * /*key*/) model::BlendMode LottieParserImpl::getBlendMode() { - RAPIDJSON_ASSERT(PeekType() == kNumberType); auto mode = model::BlendMode::Normal; switch (GetInt()) { @@ -646,7 +652,6 @@ void LottieParserImpl::resolveLayerRefs() void LottieParserImpl::parseComposition() { - RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); std::shared_ptr sharedComposition = std::make_shared(); @@ -654,22 +659,16 @@ void LottieParserImpl::parseComposition() compRef = comp; while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "v")) { - RAPIDJSON_ASSERT(PeekType() == kStringType); - comp->mVersion = std::string(GetString()); + comp->mVersion = GetStringObject(); } else if (0 == strcmp(key, "w")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); comp->mSize.setWidth(GetInt()); } else if (0 == strcmp(key, "h")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); comp->mSize.setHeight(GetInt()); } else if (0 == strcmp(key, "ip")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); comp->mStartFrame = GetDouble(); } else if (0 == strcmp(key, "op")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); comp->mEndFrame = GetDouble(); } else if (0 == strcmp(key, "fr")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); comp->mFrameRate = GetDouble(); } else if (0 == strcmp(key, "assets")) { parseAssets(comp); @@ -689,6 +688,11 @@ void LottieParserImpl::parseComposition() // don't have a valid bodymovin header return; } + if (comp->mStartFrame > comp->mEndFrame) { + // reversed animation? missing data? + return; + } + if (!IsValid()) { return; } @@ -703,20 +707,16 @@ void LottieParserImpl::parseComposition() void LottieParserImpl::parseMarker() { - RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); std::string comment; int timeframe{0}; int duration{0}; while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "cm")) { - RAPIDJSON_ASSERT(PeekType() == kStringType); - comment = std::string(GetString()); + comment = GetStringObject(); } else if (0 == strcmp(key, "tm")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); timeframe = GetDouble(); } else if (0 == strcmp(key, "dr")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); duration = GetDouble(); } else { @@ -732,7 +732,6 @@ void LottieParserImpl::parseMarker() void LottieParserImpl::parseMarkers() { - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { parseMarker(); @@ -742,7 +741,6 @@ void LottieParserImpl::parseMarkers() void LottieParserImpl::parseAssets(model::Composition *composition) { - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { auto asset = parseAsset(); @@ -818,7 +816,6 @@ static std::string toString(const T &value) */ model::Asset *LottieParserImpl::parseAsset() { - RAPIDJSON_ASSERT(PeekType() == kObjectType); auto asset = allocator().make(); std::string filename; @@ -827,30 +824,24 @@ model::Asset *LottieParserImpl::parseAsset() EnterObject(); while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "w")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); asset->mWidth = GetInt(); } else if (0 == strcmp(key, "h")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); asset->mHeight = GetInt(); } else if (0 == strcmp(key, "p")) { /* image name */ asset->mAssetType = model::Asset::Type::Image; - RAPIDJSON_ASSERT(PeekType() == kStringType); filename = std::string(GetString()); } else if (0 == strcmp(key, "u")) { /* relative image path */ - RAPIDJSON_ASSERT(PeekType() == kStringType); - relativePath = std::string(GetString()); + relativePath = GetStringObject(); } else if (0 == strcmp(key, "e")) { /* relative image path */ embededResource = GetInt(); } else if (0 == strcmp(key, "id")) { /* reference id*/ if (PeekType() == kStringType) { - asset->mRefId = std::string(GetString()); + asset->mRefId = GetStringObject(); } else { - RAPIDJSON_ASSERT(PeekType() == kNumberType); asset->mRefId = toString(GetInt()); } } else if (0 == strcmp(key, "layers")) { asset->mAssetType = model::Asset::Type::Precomp; - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); bool staticFlag = true; while (NextArrayValue()) { @@ -889,7 +880,6 @@ void LottieParserImpl::parseLayers(model::Composition *comp) comp->mRootLayer->mLayerType = model::Layer::Type::Precomp; comp->mRootLayer->setName("__"); bool staticFlag = true; - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { auto layer = parseLayer(); @@ -903,6 +893,8 @@ void LottieParserImpl::parseLayers(model::Composition *comp) model::Color LottieParserImpl::toColor(const char *str) { + if (!str) return {}; + model::Color color; auto len = strlen(str); @@ -928,7 +920,6 @@ model::Color LottieParserImpl::toColor(const char *str) model::MatteType LottieParserImpl::getMatteType() { - RAPIDJSON_ASSERT(PeekType() == kNumberType); switch (GetInt()) { case 1: return model::MatteType::Alpha; @@ -950,7 +941,6 @@ model::MatteType LottieParserImpl::getMatteType() model::Layer::Type LottieParserImpl::getLayerType() { - RAPIDJSON_ASSERT(PeekType() == kNumberType); switch (GetInt()) { case 0: return model::Layer::Type::Precomp; @@ -982,7 +972,6 @@ model::Layer::Type LottieParserImpl::getLayerType() */ model::Layer *LottieParserImpl::parseLayer() { - RAPIDJSON_ASSERT(PeekType() == kObjectType); model::Layer *layer = allocator().make(); curLayerRef = layer; bool ddd = true; @@ -991,43 +980,33 @@ model::Layer *LottieParserImpl::parseLayer() if (0 == strcmp(key, "ty")) { /* Type of layer*/ layer->mLayerType = getLayerType(); } else if (0 == strcmp(key, "nm")) { /*Layer name*/ - RAPIDJSON_ASSERT(PeekType() == kStringType); layer->setName(GetString()); } else if (0 == strcmp(key, "ind")) { /*Layer index in AE. Used for parenting and expressions.*/ - RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mId = GetInt(); } else if (0 == strcmp(key, "ddd")) { /*3d layer */ - RAPIDJSON_ASSERT(PeekType() == kNumberType); ddd = GetInt(); } else if (0 == strcmp(key, "parent")) { /*Layer Parent. Uses "ind" of parent.*/ - RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mParentId = GetInt(); } else if (0 == strcmp(key, "refId")) { /*preComp Layer reference id*/ - RAPIDJSON_ASSERT(PeekType() == kStringType); - layer->extra()->mPreCompRefId = std::string(GetString()); + layer->extra()->mPreCompRefId = GetStringObject(); layer->mHasGradient = true; mLayersToUpdate.push_back(layer); } else if (0 == strcmp(key, "sr")) { // "Layer Time Stretching" - RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mTimeStreatch = GetDouble(); } else if (0 == strcmp(key, "tm")) { // time remapping parseProperty(layer->extra()->mTimeRemap); } else if (0 == strcmp(key, "ip")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mInFrame = std::lround(GetDouble()); } else if (0 == strcmp(key, "op")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mOutFrame = std::lround(GetDouble()); } else if (0 == strcmp(key, "st")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); layer->mStartFrame = GetDouble(); } else if (0 == strcmp(key, "bm")) { layer->mBlendMode = getBlendMode(); } else if (0 == strcmp(key, "ks")) { - RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); layer->mTransform = parseTransformObject(ddd); } else if (0 == strcmp(key, "shapes")) { @@ -1087,7 +1066,7 @@ model::Layer *LottieParserImpl::parseLayer() staticFlag &= child->isStatic(); } - if (layer->hasMask()) { + if (layer->hasMask() && layer->mExtra) { for (const auto &mask : layer->mExtra->mMasks) { staticFlag &= mask->isStatic(); } @@ -1100,7 +1079,6 @@ model::Layer *LottieParserImpl::parseLayer() void LottieParserImpl::parseMaskProperty(model::Layer *layer) { - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { layer->extra()->mMasks.push_back(parseMaskObject()); @@ -1111,7 +1089,6 @@ model::Mask *LottieParserImpl::parseMaskObject() { auto obj = allocator().make(); - RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "inv")) { @@ -1156,7 +1133,6 @@ model::Mask *LottieParserImpl::parseMaskObject() void LottieParserImpl::parseShapesAttr(model::Layer *layer) { - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { parseObject(layer); @@ -1165,7 +1141,6 @@ void LottieParserImpl::parseShapesAttr(model::Layer *layer) model::Object *LottieParserImpl::parseObjectTypeAttr() { - RAPIDJSON_ASSERT(PeekType() == kStringType); const char *type = GetString(); if (0 == strcmp(type, "gr")) { return parseGroupObject(); @@ -1211,7 +1186,6 @@ model::Object *LottieParserImpl::parseObjectTypeAttr() void LottieParserImpl::parseObject(model::Group *parent) { - RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "ty")) { @@ -1253,14 +1227,13 @@ model::Object *LottieParserImpl::parseGroupObject() if (0 == strcmp(key, "nm")) { group->setName(GetString()); } else if (0 == strcmp(key, "it")) { - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { - RAPIDJSON_ASSERT(PeekType() == kObjectType); parseObject(group); } - if (group->mChildren.back()->type() == - model::Object::Type::Transform) { + if (!group->mChildren.empty() + && group->mChildren.back()->type() + == model::Object::Type::Transform) { group->mTransform = static_cast(group->mChildren.back()); group->mChildren.pop_back(); @@ -1437,7 +1410,6 @@ model::Polystar *LottieParserImpl::parsePolystarObject() model::Trim::TrimType LottieParserImpl::getTrimType() { - RAPIDJSON_ASSERT(PeekType() == kNumberType); switch (GetInt()) { case 1: return model::Trim::TrimType::Simultaneously; @@ -1446,7 +1418,7 @@ model::Trim::TrimType LottieParserImpl::getTrimType() return model::Trim::TrimType::Individually; break; default: - RAPIDJSON_ASSERT(0); + Error(); return model::Trim::TrimType::Simultaneously; break; } @@ -1594,10 +1566,13 @@ model::Transform *LottieParserImpl::parseTransformObject(bool ddd) } else if (0 == strcmp(key, "hd")) { objT->setHidden(GetBool()); } else if (0 == strcmp(key, "rx")) { + if (!obj->mExtra) return nullptr; parseProperty(obj->mExtra->m3DRx); } else if (0 == strcmp(key, "ry")) { + if (!obj->mExtra) return nullptr; parseProperty(obj->mExtra->m3DRy); } else if (0 == strcmp(key, "rz")) { + if (!obj->mExtra) return nullptr; parseProperty(obj->mExtra->m3DRz); } else { Skip(key); @@ -1656,7 +1631,6 @@ model::Fill *LottieParserImpl::parseFillObject() */ CapStyle LottieParserImpl::getLineCap() { - RAPIDJSON_ASSERT(PeekType() == kNumberType); switch (GetInt()) { case 1: return CapStyle::Flat; @@ -1672,7 +1646,6 @@ CapStyle LottieParserImpl::getLineCap() FillRule LottieParserImpl::getFillRule() { - RAPIDJSON_ASSERT(PeekType() == kNumberType); switch (GetInt()) { case 1: return FillRule::Winding; @@ -1691,7 +1664,6 @@ FillRule LottieParserImpl::getFillRule() */ JoinStyle LottieParserImpl::getLineJoin() { - RAPIDJSON_ASSERT(PeekType() == kNumberType); switch (GetInt()) { case 1: return JoinStyle::Miter; @@ -1728,7 +1700,6 @@ model::Stroke *LottieParserImpl::parseStrokeObject() } else if (0 == strcmp(key, "lj")) { obj->mJoinStyle = getLineJoin(); } else if (0 == strcmp(key, "ml")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); obj->mMiterLimit = GetDouble(); } else if (0 == strcmp(key, "d")) { parseDashProperty(obj->mDash); @@ -1750,7 +1721,6 @@ void LottieParserImpl::parseGradientProperty(model::Gradient *obj, const char * key) { if (0 == strcmp(key, "t")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); obj->mGradientType = GetInt(); } else if (0 == strcmp(key, "o")) { parseProperty(obj->mOpacity); @@ -1808,10 +1778,8 @@ model::GradientFill *LottieParserImpl::parseGFillObject() void LottieParserImpl::parseDashProperty(model::Dash &dash) { - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { - RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "v")) { @@ -1841,7 +1809,6 @@ model::GradientStroke *LottieParserImpl::parseGStrokeObject() } else if (0 == strcmp(key, "lj")) { obj->mJoinStyle = getLineJoin(); } else if (0 == strcmp(key, "ml")) { - RAPIDJSON_ASSERT(PeekType() == kNumberType); obj->mMiterLimit = GetDouble(); } else if (0 == strcmp(key, "d")) { parseDashProperty(obj->mDash); @@ -1857,10 +1824,8 @@ model::GradientStroke *LottieParserImpl::parseGStrokeObject() void LottieParserImpl::getValue(std::vector &v) { - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); VPointF pt; getValue(pt); @@ -1897,7 +1862,7 @@ void LottieParserImpl::getValue(float &val) } else if (PeekType() == kNumberType) { val = GetDouble(); } else { - RAPIDJSON_ASSERT(0); + Error(); } } @@ -1940,7 +1905,7 @@ void LottieParserImpl::getValue(int &val) } else if (PeekType() == kNumberType) { val = GetInt(); } else { - RAPIDJSON_ASSERT(0); + Error(); } } @@ -1955,7 +1920,6 @@ void LottieParserImpl::parsePathInfo() bool arrayWrapper = (PeekType() == kArrayType); if (arrayWrapper) EnterArray(); - RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "i")) { @@ -1967,7 +1931,7 @@ void LottieParserImpl::parsePathInfo() } else if (0 == strcmp(key, "c")) { mPathInfo.mClosed = GetBool(); } else { - RAPIDJSON_ASSERT(0); + Error(); Skip(nullptr); } } @@ -1987,7 +1951,6 @@ void LottieParserImpl::getValue(model::PathData &obj) VPointF LottieParserImpl::parseInperpolatorPoint() { VPointF cp; - RAPIDJSON_ASSERT(PeekType() == kObjectType); EnterObject(); while (const char *key = NextObjectKey()) { if (0 == strcmp(key, "x")) { @@ -2076,17 +2039,15 @@ void LottieParserImpl::parseKeyFrame(model::KeyFrames &obj) continue; } else if (0 == strcmp(key, "n")) { if (PeekType() == kStringType) { - parsed.interpolatorKey = GetString(); + parsed.interpolatorKey = GetStringObject(); } else { - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { - RAPIDJSON_ASSERT(PeekType() == kStringType); if (parsed.interpolatorKey.empty()) { - parsed.interpolatorKey = GetString(); + parsed.interpolatorKey = GetStringObject(); } else { // skip rest of the string - GetString(); + Skip(nullptr); } } } @@ -2142,12 +2103,10 @@ void LottieParserImpl::parseShapeProperty(model::Property &obj) if (PeekType() == kArrayType) { EnterArray(); while (NextArrayValue()) { - RAPIDJSON_ASSERT(PeekType() == kObjectType); parseKeyFrame(obj.animation()); } } else { if (!obj.isStatic()) { - RAPIDJSON_ASSERT(false); st_ = kError; return; } @@ -2168,14 +2127,12 @@ void LottieParserImpl::parsePropertyHelper(model::Property &obj) { if (PeekType() == kNumberType) { if (!obj.isStatic()) { - RAPIDJSON_ASSERT(false); st_ = kError; return; } /*single value property with no animation*/ getValue(obj.value()); } else { - RAPIDJSON_ASSERT(PeekType() == kArrayType); EnterArray(); while (NextArrayValue()) { /* property with keyframe info*/ @@ -2188,9 +2145,7 @@ void LottieParserImpl::parsePropertyHelper(model::Property &obj) * or array of object without entering the array * thats why this hack is there */ - RAPIDJSON_ASSERT(PeekType() == kNumberType); if (!obj.isStatic()) { - RAPIDJSON_ASSERT(false); st_ = kError; return; } diff --git a/AXrLottie/src/main/cpp/src/vector/vbezier.cpp b/AXrLottie/src/main/cpp/src/vector/vbezier.cpp index 797d564..1588929 100644 --- a/AXrLottie/src/main/cpp/src/vector/vbezier.cpp +++ b/AXrLottie/src/main/cpp/src/vector/vbezier.cpp @@ -81,12 +81,12 @@ float VBezier::tAtLength(float l, float totalLength) const t *= 0.5; float lastBigger = 1.0; - while (1) { + for (int num = 0; num < 100500; num++) { VBezier right = *this; VBezier left; right.parameterSplitLeft(t, &left); float lLen = left.length(); - if (fabs(lLen - l) < error) break; + if (fabs(lLen - l) < error) return t; if (lLen < l) { t += (lastBigger - t) * 0.5f; @@ -95,6 +95,7 @@ float VBezier::tAtLength(float l, float totalLength) const t -= t * 0.5f; } } + vWarning << "no convergence"; return t; } diff --git a/AXrLottie/src/main/cpp/src/vector/vpainter.cpp b/AXrLottie/src/main/cpp/src/vector/vpainter.cpp index 4ebbc5c..38a58e0 100644 --- a/AXrLottie/src/main/cpp/src/vector/vpainter.cpp +++ b/AXrLottie/src/main/cpp/src/vector/vpainter.cpp @@ -84,12 +84,12 @@ void VPainter::drawBitmapUntransform(const VRect & target, { mSpanData.initTexture(&bitmap, const_alpha, source); if (!mSpanData.mUnclippedBlendFunc) return; - mSpanData.dx = float(-target.x()); - mSpanData.dy = float(-target.y()); - VRect rr = source.translated(target.x(), target.y()); + // update translation matrix for source texture. + mSpanData.dx = float(target.x() - source.x()); + mSpanData.dy = float(target.y() - source.y()); - fillRect(rr, &mSpanData); + fillRect(target, &mSpanData); } VPainter::VPainter(VBitmap *buffer) diff --git a/AXrLottie/src/main/java/com/aghajari/rlottie/AXrLottie.java b/AXrLottie/src/main/java/com/aghajari/rlottie/AXrLottie.java index 2524e75..ab2bac9 100644 --- a/AXrLottie/src/main/java/com/aghajari/rlottie/AXrLottie.java +++ b/AXrLottie/src/main/java/com/aghajari/rlottie/AXrLottie.java @@ -41,7 +41,7 @@ /** * @author Amir Hossein Aghajari - * @version 1.1.0 + * @version 1.2.0 */ public class AXrLottie { static { diff --git a/AXrLottie/src/main/java/com/aghajari/rlottie/AXrLottieDrawable.java b/AXrLottie/src/main/java/com/aghajari/rlottie/AXrLottieDrawable.java index 3e46a80..513ad81 100755 --- a/AXrLottie/src/main/java/com/aghajari/rlottie/AXrLottieDrawable.java +++ b/AXrLottie/src/main/java/com/aghajari/rlottie/AXrLottieDrawable.java @@ -142,7 +142,10 @@ public void onResult(File file) { @Override public void onResult(Throwable result) { // Failure Listener - Log.e(TAG, result.toString()); + + if (result != null) + Log.e(TAG, result.toString()); + if (loaderListener != null) loaderListener.onError(AXrLottieDrawable.this, result); } diff --git a/AXrLottieGlideDecoder/build.gradle b/AXrLottieGlideDecoder/build.gradle index efb5714..d18490b 100644 --- a/AXrLottieGlideDecoder/build.gradle +++ b/AXrLottieGlideDecoder/build.gradle @@ -24,12 +24,9 @@ android { } dependencies { - - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'com.google.android.material:material:1.1.0' - testImplementation 'junit:junit:4.+' - androidTestImplementation 'androidx.test.ext:junit:1.1.2' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' implementation project(':AXrLottie') @@ -37,62 +34,11 @@ dependencies { annotationProcessor "com.github.bumptech.glide:compiler:4.12.0" } -//JCenter -apply plugin: 'com.github.dcendents.android-maven' -apply plugin: 'com.jfrog.bintray' +// PUBLISH -def artifact = new Properties() -artifact.load(new FileInputStream("deploy.settings")) - -version=artifact.version -group=artifact.groupId - -install { - repositories.mavenInstaller { - pom.project { - packaging 'aar' - groupId artifact.groupId - artifactId 'AXrLottieGlideDecoder' - version artifact.version - name 'AXrLottieGlideDecoder' // pom.project.name must be same as bintray.pkg.name - url artifact.siteUrl - inceptionYear '2020' // HARDCODED - licenses { - license { // HARDCODED - name 'The Apache Software License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - distribution 'repo' - } - } - scm { - connection artifact.gitUrl - developerConnection artifact.gitUrl - url artifact.siteUrl - } - } - } -} - -def properties = new Properties() -properties.load(new FileInputStream("local.properties")) - -bintray { - user = properties.getProperty("bintray.user") - key = properties.getProperty("bintray.apikey") - - configurations = ['archives'] - pkg { - repo = "Aghajari" - name = artifact.id - websiteUrl = artifact.siteUrl - vcsUrl = artifact.gitUrl - licenses = artifact.licenses - publish = true - version { - name = artifact.version - } - } -} +apply plugin: 'maven' +apply plugin: 'maven-publish' +apply plugin: 'signing' task sourcesJar(type: Jar) { from android.sourceSets.main.java.srcDirs @@ -104,6 +50,12 @@ task javadoc(type: Javadoc) { classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) } +afterEvaluate { + javadoc.classpath += files(android.libraryVariants.collect { variant -> + variant.javaCompileProvider.get().classpath.files + }) +} + task javadocJar(type: Jar, dependsOn: javadoc) { classifier = 'javadoc' from javadoc.destinationDir @@ -114,13 +66,65 @@ artifacts { archives sourcesJar } -repositories { - maven { url 'https://maven.google.com' } - mavenCentral() +signing { + useInMemoryPgpKeys( + rootProject.ext["signing.keyId"], + rootProject.ext["signing.key"], + rootProject.ext["signing.password"], + ) + sign publishing.publications } tasks.withType(Javadoc) { options.addStringOption('Xdoclint:none', '-quiet') options.addStringOption('encoding', 'UTF-8') options.addStringOption('charSet', 'UTF-8') +} + +def artifact = new Properties() +artifact.load(new FileInputStream("deploy.settings")) + +version = artifact.version +group = artifact.groupId +archivesBaseName = 'AXrLottieGlideDecoder' + +afterEvaluate { + publishing { + publications { + release(MavenPublication) { + groupId artifact.groupId + artifactId 'AXrLottieGlideDecoder' + version artifact.version + from components.release + + pom { + name = 'AXrLottieGlideDecoder' + packaging = 'aar' + description = 'AXrLottieGlideDecoder is a Glide integration library for displaying AXrLottieDrawable (AXrLottie).' + url = artifact.siteUrl + + scm { + connection = artifact.gitUrl + developerConnection = artifact.gitUrl + url = artifact.siteUrl + } + + licenses { + license { + name = 'The Apache License, Version 2.0' + url = 'http://www.apache.org/licenses/LICENSE-2.0.txt' + } + } + + developers { + developer { + id = 'Aghajari' + name = 'AmirHossein Aghajari' + email = 'amirhossein.aghajari.82@gmail.com' + } + } + } + } + } + } } \ No newline at end of file diff --git a/AXrLottieGlideDecoder/outputs/AXrLottieGlideDecoder-release.aar b/AXrLottieGlideDecoder/outputs/AXrLottieGlideDecoder-release.aar deleted file mode 100644 index 14b03ba..0000000 Binary files a/AXrLottieGlideDecoder/outputs/AXrLottieGlideDecoder-release.aar and /dev/null differ diff --git a/AXrLottieGlideDecoder/src/main/java/com/aghajari/rlottie/glide/AXrLottieGlideOptions.java b/AXrLottieGlideDecoder/src/main/java/com/aghajari/rlottie/glide/AXrLottieGlideOptions.java index d5f5386..7a2ce23 100644 --- a/AXrLottieGlideDecoder/src/main/java/com/aghajari/rlottie/glide/AXrLottieGlideOptions.java +++ b/AXrLottieGlideDecoder/src/main/java/com/aghajari/rlottie/glide/AXrLottieGlideOptions.java @@ -23,7 +23,7 @@ /** * @author Amir Hossein Aghajari - * @version 1.1.0 + * @version 1.2.0 */ public final class AXrLottieGlideOptions { @@ -62,7 +62,7 @@ public final class AXrLottieGlideOptions { "com.aghajari.rlottie.glide#AutoStart", true); /** - * Customizes the size of the animation + * Customizes the size of the lottie drawable */ public static final Option SIZE = Option.memory( "com.aghajari.rlottie.glide#Size", -1); diff --git a/app/build.gradle b/app/build.gradle index 8f5ae90..35eab9b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,18 +23,19 @@ android { dependencies { implementation fileTree(dir: "libs", include: ["*.jar"]) - implementation 'androidx.appcompat:appcompat:1.2.0' - implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'androidx.recyclerview:recyclerview:1.2.1' implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test.ext:junit:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.0' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - implementation 'com.aghajari.emojiview:AXEmojiView:1.3.0' + implementation 'io.github.aghajari:AXEmojiView:1.4.0' + implementation 'io.github.aghajari:AXEmojiView-iOSProvider:1.4.0' implementation project(':AXrLottie') - implementation 'com.squareup.okhttp3:okhttp:4.9.0' + implementation 'com.squareup.okhttp3:okhttp:4.9.1' implementation project(':AXrLottieGlideDecoder') implementation "com.github.bumptech.glide:glide:4.12.0" diff --git a/app/src/main/java/com/aghajari/sample/axrlottie/AXrLottieApplication.java b/app/src/main/java/com/aghajari/sample/axrlottie/AXrLottieApplication.java index 484cc05..dfc535e 100644 --- a/app/src/main/java/com/aghajari/sample/axrlottie/AXrLottieApplication.java +++ b/app/src/main/java/com/aghajari/sample/axrlottie/AXrLottieApplication.java @@ -10,7 +10,7 @@ import androidx.annotation.Nullable; import com.aghajari.emojiview.AXEmojiManager; -import com.aghajari.emojiview.emoji.iosprovider.AXIOSEmojiProvider; +import com.aghajari.emojiview.iosprovider.AXIOSEmojiProvider; import com.aghajari.emojiview.listener.StickerViewCreatorListener; import com.aghajari.emojiview.sticker.StickerCategory; import com.aghajari.rlottie.AXrLottie; @@ -19,10 +19,6 @@ import com.aghajari.rlottie.AXrLottieOptions; import com.aghajari.rlottie.extension.GZipFileExtension; -/** - * @author kienht - * @since 03/02/2021 - */ public class AXrLottieApplication extends Application { @Override diff --git a/app/src/main/java/com/aghajari/sample/axrlottie/MainActivity.java b/app/src/main/java/com/aghajari/sample/axrlottie/MainActivity.java index 9453cf9..e459cc7 100644 --- a/app/src/main/java/com/aghajari/sample/axrlottie/MainActivity.java +++ b/app/src/main/java/com/aghajari/sample/axrlottie/MainActivity.java @@ -1,22 +1,11 @@ package com.aghajari.sample.axrlottie; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; -import android.content.Context; import android.content.Intent; -import android.graphics.Color; import android.os.Bundle; import android.view.View; -import com.aghajari.emojiview.AXEmojiManager; -import com.aghajari.emojiview.emoji.iosprovider.AXIOSEmojiProvider; -import com.aghajari.emojiview.listener.StickerViewCreatorListener; -import com.aghajari.emojiview.sticker.StickerCategory; -import com.aghajari.rlottie.AXrLottie; -import com.aghajari.rlottie.AXrLottieImageView; -import com.aghajari.rlottie.extension.GZipFileExtension; import com.aghajari.sample.axrlottie.activity.AXEmojiViewActivity; import com.aghajari.sample.axrlottie.activity.ColorLayerActivity; diff --git a/app/src/main/java/com/aghajari/sample/axrlottie/OkHttpNetworkFetcher.java b/app/src/main/java/com/aghajari/sample/axrlottie/OkHttpNetworkFetcher.java index ddd7950..6474121 100644 --- a/app/src/main/java/com/aghajari/sample/axrlottie/OkHttpNetworkFetcher.java +++ b/app/src/main/java/com/aghajari/sample/axrlottie/OkHttpNetworkFetcher.java @@ -24,7 +24,6 @@ import java.io.IOException; import java.io.InputStream; -import java.net.HttpURLConnection; import java.util.concurrent.TimeUnit; import okhttp3.OkHttpClient; diff --git a/app/src/main/java/com/aghajari/sample/axrlottie/activity/SimpleNetworkActivity.java b/app/src/main/java/com/aghajari/sample/axrlottie/activity/SimpleNetworkActivity.java index aa67e87..6cc28ba 100644 --- a/app/src/main/java/com/aghajari/sample/axrlottie/activity/SimpleNetworkActivity.java +++ b/app/src/main/java/com/aghajari/sample/axrlottie/activity/SimpleNetworkActivity.java @@ -5,7 +5,10 @@ import androidx.appcompat.app.AppCompatActivity; +import com.aghajari.rlottie.AXrLottie; +import com.aghajari.rlottie.AXrLottieDrawable; import com.aghajari.rlottie.AXrLottieImageView; +import com.aghajari.rlottie.AXrLottieOptions; import com.aghajari.rlottie.glide.AXrLottieGlideOptions; import com.aghajari.sample.axrlottie.R; import com.bumptech.glide.Glide; diff --git a/build.gradle b/build.gradle index 0cc717f..46e1920 100644 --- a/build.gradle +++ b/build.gradle @@ -2,33 +2,52 @@ buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { - classpath "com.android.tools.build:gradle:4.0.1" + classpath "com.android.tools.build:gradle:4.2.0" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files - classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.3' - classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' } } +plugins { + id("io.github.gradle-nexus.publish-plugin") version "1.1.0" +} + allprojects { repositories { maven { url 'https://maven.google.com' } - jcenter() mavenCentral() } - - tasks.withType(Javadoc).all { - enabled = false - } } task clean(type: Delete) { delete rootProject.buildDir } -apply plugin: 'com.jfrog.bintray' +ext["signing.keyId"] = '' +ext["signing.password"] = '' +ext["signing.key"] = '' +ext["sonatypeStagingProfileId"] = '' +ext["ossrhUsername"] = '' +ext["ossrhPassword"] = '' + +File secretPropsFile = project.rootProject.file('local.properties') +Properties p = new Properties() +new FileInputStream(secretPropsFile).withCloseable { is -> p.load(is) } +p.each { name, value -> ext[name] = value } + +nexusPublishing { + repositories { + sonatype { + stagingProfileId = rootProject.ext["sonatypeStagingProfileId"] + username = rootProject.ext["ossrhUsername"] + password = rootProject.ext["ossrhPassword"] + nexusUrl.set(uri("https://s01.oss.sonatype.org/service/local/")) + snapshotRepositoryUrl.set(uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")) + } + } +} diff --git a/deploy.settings b/deploy.settings index fd765f9..25aa425 100644 --- a/deploy.settings +++ b/deploy.settings @@ -1,7 +1,7 @@ siteUrl = https://github.com/Aghajari/AXrLottie gitUrl = https://github.com/Aghajari/AXrLottie.git -version = 1.1.0 -groupId = com.aghajari.rlottie +version = 1.2.0 +groupId = io.github.aghajari licenses = ['Apache-2.0'] id = AXrLottie name = AXrLottie \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index b87d174..ab16d1e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,5 +3,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip