[AI] Stroke redraw allocates and destroys a native Onyx pen for every stroke
Los mantenedores suelen responder en 2 días
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 4/5
- Tiempo estimado
- 3-5 días
- Aptitud para principiantes
- 48/100
- Tipo de issue
- Refactorización
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Área
- mobile-dev, performance
Línea de trabajo
Start by tracing PageView.drawAreaScreenCoordinates or drawOnCanvasFromPage and measure a full-page redraw on a real device, separating native pen creation and destruction from rendering. If that cost is significant, prototype reuse for the fountain V2 and square wrappers in editor/drawing/onyx/ and compare output against fresh pens. Done means the measurements justify the change and visual checks show no stroke differences.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Summary
When a page is (re)drawn, every stroke drawn with a Neo pen allocates a new native Onyx pen, renders one stroke with it, and destroys it. On a page with thousands of strokes that is thousands of JNI allocate/free round-trips per redraw (page open, scroll, zoom, undo, erase repaint). This may be a significant part of redraw time and needs to be measured.
Where it happens
Notable's own wrappers (editor/drawing/onyx/):
NeoFountainPenV2Wrapper.drawStroke:FountainShapes.createNeoPenV2(...)→NeoPenRender(neoPen)→render(...)→destroyPen(), once per stroke.NeoSquarePenWrapper.drawStroke:NeoSquarePen.create(config)→NeoPenRender→destroyPen(), once per stroke.
Onyx SDK wrappers that OnyxStrokeRenderer calls (confirmed in the onyxsdk-pen 1.5.8 sources, which Onyx now publishes as -sources.jar):
NeoBrushPenWrapper,NeoMarkerPenWrapperandNeoFountainPenWrappergo throughNeoPenUtils.computeStrokePoints, which doesnew NeoPenConfig()→NeoBrushPen/NeoFountainPen/NeoMarkerPen.create(config)→ … →pen.destroy()per call.NeoCharcoalPenWrapper/NeoCharcoalPenV2WrapperdoNeoCharcoalPen(V2).create(config)…pen.destroy()per call.NeoMarkerPenWrapper.drawStrokealso creates anew Canvas(...)over the shared screen-sized pen bitmap per stroke (see #309 for the related offscreen-buffer issue).
Only the ballpoint pen is rendered without a native pen.
Why reuse might be possible
From the onyxsdk-penbrush 1.1.2 sources:
NeoPenhas no API to change its config after creation. Width and other parameters are fixed increate(config)/createNeoPenV2(width, …).- Each stroke is driven through
onPenDown→onPenMove→onPenUpon the native handle (NeoPenNative.onPenDown(penHandle, …)), which looks like a per-stroke state machine. So one native pen per (pen type, width, other config) could probably be reused for many strokes within one redraw pass and destroyed once at the end.
Not verified: that onPenDown fully resets the native state (no carry-over of smoothing or prediction from the previous stroke), and that NeoPenRender can be reused or recreated cheaply around a reused NeoPen.
What to investigate
- Measure first. Time a full-page redraw on a stroke-heavy page (e.g.
PageView.drawAreaScreenCoordinates/drawOnCanvasFromPage) on a real device (Note Air 4C / Note 4C). Split the time into pen create/destroy and the actual render (method tracing or manual timers aroundcreateNeoPenV2/create/destroy). - If create/destroy is significant, prototype a per-redraw pen cache for the pens we construct ourselves (fountain V2, square): key by pen type + config (width, …), reuse across strokes, destroy all at the end of the pass.
- Verify visually that reused pens produce identical output to fresh ones (overlay or pixel diff of a test page), especially for the fountain V2 smoothing and the first/last segments of each stroke.
- For the SDK-wrapped pens (brush, marker, charcoal) reuse would mean replacing
NeoPenUtils.computeStrokePoints/ the charcoal wrappers with our own calls against the publicNeoPenAPI. Worth doing only if step 1 shows a real gain.
Context
Found while reviewing the Onyx SDK 1.5.8 / penbrush 1.1.2 sources during the SDK bump (notes in docs/onyx-sdk/sdk-release-changelog.md, untracked working docs).
- Lenguaje dominante
- Kotlin
- Estrellas
- 269
- Forks
- 44
- Merge medio
- 3 d 21 h
- PR fusionados (30 d)
- 22
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de Ethran/notable
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 90/100
Los mantenedores suelen responder en 2 días
-
bug
Dificultad 5/5 Más de una semana Aptitud para principiantes 35/100
Los mantenedores suelen responder en 2 días
-
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
Ethran/notable#351 · 1 comentario ·
Los mantenedores suelen responder en 2 días
-
Repeat background does not workAbiertobug
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
Ethran/notable#348 · 1 comentario ·
Los mantenedores suelen responder en 2 días
-
Dificultad 4/5 3-5 días Aptitud para principiantes 25/100
Los mantenedores suelen responder en 2 días
Todos los issues de Ethran/notable
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
openai/openai-java#1337 ·
Los mantenedores suelen responder en 1 día
-
enhancement impact:U1 P3 reach:R2 size:S
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
-
sentry-loop
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
paritytech/trinity-user-agents#1890 ·
Los mantenedores suelen responder en 1 día
-
android:core
Dificultad 2/5 1-3 horas Aptitud para principiantes 82/100
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Kotlin/kotlinx-io#543 ·