jzbrooks / vgo

vector graphic optimization
MIT License
43 stars 2 forks source link

Merge paths can cause extremely large command sequences for a single path #82

Open jzbrooks opened 2 months ago

jzbrooks commented 2 months ago

It does not break the image, but in the build processes somewhere (AAPT?) the path data string gets replaced with STRING_TOO_LARGE. In this case the path data was 159849 chars long.

FATAL EXCEPTION: main
Process: com.chickfila.cfaflagship.debug, PID: 17895
android.content.res.Resources$NotFoundException: Drawable com.chickfila.cfaflagship.debug:drawable/ic_rewards_background_member with resource ID #0x7f080286
Caused by: android.content.res.Resources$NotFoundException: File res/drawable/ic_rewards_background_member.xml from drawable resource ID #0x7f080286
    at android.content.res.ResourcesImpl.loadDrawableForCookie(ResourcesImpl.java:913)
    at android.content.res.ResourcesImpl.loadDrawable(ResourcesImpl.java:681)
    at android.content.res.Resources.loadDrawable(Resources.java:1004)
    at android.content.res.Resources.getDrawableForDensity(Resources.java:994)
    at android.content.res.Resources.getDrawable(Resources.java:933)
    at android.content.Context.getDrawable(Context.java:948)
    at androidx.core.content.ContextCompat$Api21Impl.getDrawable(ContextCompat.java:1049)
    at androidx.core.content.ContextCompat.getDrawable(ContextCompat.java:485)
    at androidx.appcompat.widget.ResourceManagerInternal.getDrawable(ResourceManagerInternal.java:147)
    at androidx.appcompat.widget.ResourceManagerInternal.getDrawable(ResourceManagerInternal.java:135)
    at androidx.appcompat.content.res.AppCompatResources.getDrawable(AppCompatResources.java:64)
    at androidx.appcompat.widget.AppCompatImageHelper.setImageResource(AppCompatImageHelper.java:90)
    at androidx.appcompat.widget.AppCompatImageView.setImageResource(AppCompatImageView.java:102)
    at com.chickfila.cfaflagship.debug.activities.IconTesterActivity$IconsAdapter.bindView(IconTesterActivity.kt:85)
    at com.chickfila.cfaflagship.debug.activities.IconTesterActivity$IconsAdapter.getView(IconTesterActivity.kt:77)
    at android.widget.AbsListView.obtainView(AbsListView.java:2466)
    at android.widget.ListView.makeAndAddView(ListView.java:2065)
    at android.widget.ListView.fillDown(ListView.java:791)
    at android.widget.ListView.fillGap(ListView.java:754)
    at android.widget.AbsListView.trackMotionScroll(AbsListView.java:5557)
    at android.widget.ListView.trackMotionScroll(ListView.java:1982)
    at android.widget.AbsListView$FlingRunnable.run(AbsListView.java:5099)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1339)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1348)
    at android.view.Choreographer.doCallbacks(Choreographer.java:952)
    at android.view.Choreographer.doFrame(Choreographer.java:878)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1322)
    at android.os.Handler.handleCallback(Handler.java:958)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loopOnce(Looper.java:205)
    at android.os.Looper.loop(Looper.java:294)
    at android.app.ActivityThread.main(ActivityThread.java:8177)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:552)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:971)
Caused by: java.lang.IllegalArgumentException: R is not a valid verb. Failure occurred at position 2 of path: STRING_TOO_LARGE
    at android.util.PathParser.nCreatePathDataFromString(Native Method)
    at android.util.PathParser.-$$Nest$smnCreatePathDataFromString(Unknown Source:0)
    at android.util.PathParser$PathData.<init>(PathParser.java:79)
    at android.graphics.drawable.VectorDrawable$VFullPath.updateStateFromTypedArray(VectorDrawable.java:2028)
    at android.graphics.drawable.VectorDrawable$VFullPath.inflate(VectorDrawable.java:1979)
    at android.graphics.drawable.VectorDrawable.inflateChildElements(VectorDrawable.java:840)
    at android.graphics.drawable.VectorDrawable.inflate(VectorDrawable.java:738)
    at android.graphics.drawable.DrawableInflater.inflateFromXmlForDensity(DrawableInflater.java:141)
    at android.graphics.drawable.Drawable.createFromXmlInnerForDensity(Drawable.java:1394)
    at android.graphics.drawable.Drawable.createFromXmlForDensity(Drawable.java:1355)
jzbrooks commented 1 month ago

For now, filtering out these images is the best workaround. It's easily done with an exclude in a gradle file tree if using the plugin, but could be done with the cli tool also.

jzbrooks commented 1 month ago

Seems like the max value is 1 << 15 or 32767. We should probably break strings along that boundary (at least for VD). Some shorter boundary could make sense considering "long path" lint warnings. Rendering engines probably parallelize drawing individual paths. I haven't seen long paths noticeably impact rendering.

https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/libs/androidfw/StringPool.cpp;l=376;bpv=1;bpt=0 https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/libs/androidfw/StringPool.cpp;l=339;drc=d262a68a1e0c3b640274b094a7f1e3a5b75563e9;bpv=1;bpt=0

jzbrooks commented 1 month ago

Addressing #25 would address this also

jzbrooks commented 1 week ago

https://issuetracker.google.com/issues/222821851