Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
name: CI

on:
push:
pull_request:
workflow_dispatch:

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

env:
FLUTTER_VERSION: 3.47.2

jobs:
quality:
name: Analyze and test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: stable
cache: true
- run: flutter pub get
- run: flutter analyze
- run: flutter test
- run: flutter test
working-directory: example

android:
name: Android debug build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: stable
cache: true
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
- run: flutter pub get
working-directory: example
- run: flutter build apk --debug --target-platform android-arm64
working-directory: example
- name: Verify API and ABI contract in APK
working-directory: example
run: |
apk=build/app/outputs/flutter-apk/app-debug.apk
apkanalyzer="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/apkanalyzer"
test -x "$apkanalyzer"
test "$("$apkanalyzer" manifest min-sdk "$apk")" = "29"
test "$(unzip -Z1 "$apk" | awk -F/ '/^lib\// {print $2}' | sort -u)" = "arm64-v8a"

macos:
name: macOS release build
runs-on: macos-15
steps:
- uses: actions/checkout@v4
- uses: subosito/flutter-action@v2
with:
flutter-version: ${{ env.FLUTTER_VERSION }}
channel: stable
cache: true
- run: flutter precache --macos
- run: flutter pub get
working-directory: example
- run: python3 tool/macos_run.py --mode release --build-only
working-directory: example

platform-contract:
name: Platform contract
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Verify declared platform hosts
run: |
test -d example/android
test -d example/macos
test ! -d example/web
test ! -d example/ios
test ! -d example/linux
test ! -d example/windows
grep -F 'minSdk = 29' example/android/app/build.gradle.kts
grep -F 'abiFilters += "arm64-v8a"' example/android/app/build.gradle.kts
10 changes: 10 additions & 0 deletions .pubignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.github/
.agents/
.codex/
build/
docs/
AGENTS.md
AI_ANALYSIS.md
CONTEXT.md
OWNERS.md
PHASE_SUMMARY.md
76 changes: 76 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# Agent guide

## Repository purpose

`gcode_core` parses a deliberately small G-code subset, builds two-dimensional
toolpaths, and renders them through Flutter GPU. The package is GPU-only; do not
silently introduce a second renderer or claim a platform is supported from a
successful cross-compile alone.

## Layout and ownership

- `lib/src/parser`, `models`, `services`: platform-neutral parsing and geometry.
- `lib/src/data/readers`: native file-system readers; currently uses `dart:io`.
- `lib/src/rendering`: Flutter GPU resources, geometry, surfaces, and shaders.
- `lib/src/widgets`: reusable package UI.
- `shaders`: source shaders plus the checked-in generated shader bundle.
- `example/lib/src/gcode_session_controller.dart`: example state and playback.
- `example/lib/src/gcode_example_page.dart`: page composition only.
- `example/lib/src/widgets`: independently testable example UI.
- `example/lib/gpu_validation.dart`: native GPU lifecycle/performance harness.
- `docs/evidence`: durable runtime evidence; do not rewrite historical evidence.

## Current platform contract

- macOS: primary validated GPU platform.
- Android: API 29+ and ARM64-only. The host and APK build are present; runtime
GPU/device evidence is pending. Do not add ARM32 or x86 compatibility without
an explicit product decision.
- iOS, Linux, Windows: not supported until hosts, builds, and native evidence land.
- Web: unsupported while `dart:io` and the GPU-only renderer remain unconditional.

Update the platform-contract CI job and this section together when adding a
host. A build is only build evidence. Runtime support requires a platform report
with device/OS, Flutter revision, artifact revision, file-picker behavior, GPU
initialization, screenshots, and frame/memory measurements.

## Change boundaries

- Keep parsing behavior out of widgets.
- Keep file-picker calls in the example controller or a platform service.
- Treat segment lists as immutable; replace the list when geometry changes.
- Reuse GPU buffers and surfaces across frames. Dispose `ui.Image` handles.
- Do not rebuild geometry for playback-only progress changes.
- Preserve unrelated evidence and generated platform files.

## Test growth order

1. Pure unit tests for parser, bounds, builders, and viewport math.
2. Controller tests for loading, playback, replay, seeking, and disposal.
3. Widget tests at 320, 600, 720, and desktop widths.
4. Android ARM64 API 29 and API 35 integration tests for picker cancellation
and sample load. Do not use x86/x86_64 emulator evidence.
5. Native GPU profile runs using `gpu_validation.dart`.
6. Add iOS/Windows/Linux build jobs only with their corresponding host changes.

Minimum local gate from the repository root:

```sh
flutter analyze
flutter test
(cd example && flutter test)
```

Run Android builds from `example`, not the package root:

```sh
cd example
flutter build apk --debug --target-platform android-arm64
```

macOS uses its checked compatibility entrypoint:

```sh
cd example
python3 tool/macos_run.py --mode release --build-only
```
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
# Changelog

## 0.2.0 — 2026-09-23

First stable package release. It promotes the Flutter GPU renderer from the
macOS prerelease and adds the Android API 29+ ARM64 host contract, adaptive
example UI, session-controller extraction, and CI coverage for package tests,
Android builds, macOS builds, and declared platform support.

### Platform support

- macOS: Flutter GPU runtime baseline validated.
- Android: API 29+ ARM64 host, build, and physical-device runtime validated.
- Web, Windows, Linux, and iOS: not supported by the GPU renderer in this
release.

## 0.2.0-dev.1 — 2026-09-06

First macOS prerelease, distributed by Git tag / GitHub Release.
Expand Down
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 lizy-coding

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
62 changes: 45 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,37 @@

![example](https://github.com/lizy-coding/gcode_core/blob/master/gcode_print.gif)

G-code parsing and visualization package extracted for Flutter Forge.
G-code parsing, streaming toolpath construction, playback UI, and Flutter GPU
visualization for Flutter applications.

## First macOS prerelease: 0.2.0-dev.1
## Install

This release is distributed through GitHub/Git, not pub.dev. Pin the release tag
instead of following `dev`:
Version 0.2.0 is published on pub.dev:

```yaml
dependencies:
gcode_core:
git:
url: https://github.com/lizy-coding/gcode_core.git
ref: v0.2.0-dev.1
gcode_core: ^0.2.0
```

See [release notes](docs/releases/0.2.0-dev.1.md) and
[CHANGELOG](CHANGELOG.md) for breaking changes and validation limits.
Flutter 3.47.2 or newer is required. The package bundles its compiled shader
asset; consumers do not need to copy shader files manually.

## Platform support

| Platform | Status | Requirements |
| --- | --- | --- |
| macOS | Supported | macOS 12+, Impeller and Flutter GPU enabled |
| Android | Supported | API 29+, ARM64, Impeller and Flutter GPU enabled |
| iOS | Not supported | No validated host contract in 0.2.0 |
| Windows | Not supported | Flutter GPU renderer is not admitted in 0.2.0 |
| Linux | Not supported | No validated host contract in 0.2.0 |
| Web | Not supported | The renderer and file reader use native-only APIs |

Unsupported platforms do not imply that parsing concepts are platform-specific;
the published package as a whole includes a GPU-only Flutter renderer and is
released only against the hosts listed as supported.

### Host configuration

For a macOS host, use Flutter 3.47.2 and add these keys to the top-level dict in
`macos/Runner/Info.plist`:
Expand All @@ -30,11 +44,11 @@ For a macOS host, use Flutter 3.47.2 and add these keys to the top-level dict in
<true/>
```

The host needs a macOS deployment target of at least 12.0; runtime evidence is
currently limited to macOS 26.5 on Apple Silicon. The package bundles its shader
asset automatically. Example Xcode/CocoaPods workarounds do not propagate into
consumer apps and should only be adopted if the same build issue occurs.
This is a Flutter package; its public entry point is not a pure Dart CLI API.
The macOS deployment target must be at least 12.0. On Android, use a minimum SDK
of 29, build for `arm64-v8a`, and keep Impeller enabled. The example project is
the reference host configuration for both platforms. Example Xcode/CocoaPods
workarounds do not propagate into consumer apps and should only be adopted if
the same build issue occurs.

## Scope

Expand All @@ -53,7 +67,8 @@ Flutter 3.47.2 or newer is required. `GcodeCanvas` is GPU-only: G0 dashes,
G1 lines, background paths, playback, grid, origin, tool head and glow are all
rendered by GPU shaders. There is no Canvas backend or automatic fallback.
Flutter only composites the resulting image and displays ordinary UI widgets.
Only macOS has been exercised in this implementation phase.
The renderer has no Canvas fallback. Unsupported GPU initialization is surfaced
as an error so applications can provide an explicit unavailable state.

```dart
GcodeCanvas(
Expand Down Expand Up @@ -88,19 +103,28 @@ fields (`toolHeadColor`, `toolHeadGlowColor`, `originDotColor`), replacing Paint
objects. Unsupported GPU initialization is reported as an error, never a
fallback renderer.

## Test
## Validation

```bash
flutter test
(cd example && flutter test)
```

CI keeps separate quality, Android build, macOS build, and platform-contract
jobs. Android is deliberately constrained to API 29+ and `arm64-v8a`. Native
acceptance evidence remains platform-specific; adding a new host requires its
own build, runtime, rendering, lifecycle, and performance evidence. See
`AGENTS.md` for the admission contract.

## Example

Run the Flutter example app:

```bash
cd example
flutter run -d macos
# or an API 29+ ARM64 Android device
flutter run -d <android-device-id>
```

IDE runs use `example/lib/main.dart` with the macOS device. The example's
Expand Down Expand Up @@ -136,3 +160,7 @@ G1 X10 Y10
}
}
```

## License

MIT. See [LICENSE](LICENSE).
5 changes: 4 additions & 1 deletion example/.metadata
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.

version:
revision: "00b0c91f06209d9e4a41f71b7a512d6eb3b9c694"
revision: "d3b14c876900e553bc736ca19295fc09e3853e8e"
channel: "stable"

project_type: app
Expand All @@ -18,6 +18,9 @@ migration:
- platform: macos
create_revision: 00b0c91f06209d9e4a41f71b7a512d6eb3b9c694
base_revision: 00b0c91f06209d9e4a41f71b7a512d6eb3b9c694
- platform: android
create_revision: d3b14c876900e553bc736ca19295fc09e3853e8e
base_revision: d3b14c876900e553bc736ca19295fc09e3853e8e

# User provided section

Expand Down
Loading
Loading