cashapp / paparazzi

Render your Android screens without a physical device or emulator
https://cashapp.github.io/paparazzi/
Apache License 2.0
2.28k stars 214 forks source link

Fix text rendering by correctly calling `onPreDraw` before onDraw #1418

Closed geoff-powell closed 4 months ago

geoff-powell commented 4 months ago

This PR added the reflection call to force mFirstFrameExecuted to be true due to some animation issues. This seems to have caused issues with the changes made in Iguana around rendering which calls onPreDraw after render.

A similar PR fixed an issue with onPreDraw calls not getting called on multiple frames. The hope is that this PR fixes the issue in the 2nd PR as well as issue #1403 with text rendering.

Update Confirmed with @gamepro65 that the 2 draw calls is expected when running the same SampleView on a device. First draw call is with the main RecordedCanvas and the second is a supplementary RecordedCanvas provided by RenderedThread image

geoff-powell commented 4 months ago

Unfortunately getting some issues on linux builds with my added test. What is strange is I pulled the generated image from the failed CI run and compared it to the one generated on my Mac ARM machine and the differ is less then 0.1% (Images differ (0.000385% to be exact). But the test report says 3.3xxx%. 🤔 linux-test-report.zip

Mac ARM generated image:

Linux generated image:

Delta image: (most likely due to platform drawing differences in java.awt delta-5e57e882d1350bc9d8be8b83fa9e84699f9affb9

geoff-powell commented 4 months ago

Just noticed that other plugin tests sort files by lastModified so that seems to have fixed things. See in last commit.

geoff-powell commented 4 months ago

This change does feel strange to have 2 draw calls occur but just confirmed in layout lib in jellyfish and iguana that the exact same thing happens there. Also confirmed is that the first draw call is with the NoOp canvas, and second is RecordingCanvas (what actually renders in layoutlib)`

Screenshot 2024-05-10 at 10 20 20 AM

Using this sample view:

class SampleView(context: Context) : TextView(context) {

  init {
    text = "Hello, World!"

    viewTreeObserver.addOnPreDrawListener {
      text = "$text\n+OnPreDraw"
      true
    }
  }

  override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    text = "$text\n+OnDraw($canvas)"
  }
}
geoff-powell commented 4 months ago

Looks good! What ended up happening with the linux diff errors you were getting?

They issue was due to the order of snapshots generated. For some other plugin tests we are sorting by lastModified when asserting multiple snapshots. The rendering diff is platform specific with how layoutlib draws to the canvas. That is why we have the max percent difference of 0.1 as a default value