Skip to content

Canvas feature#2290

Open
desireddymohithreddy0925 wants to merge 5 commits into
Karanjot786:mainfrom
desireddymohithreddy0925:canvas-feature
Open

Canvas feature#2290
desireddymohithreddy0925 wants to merge 5 commits into
Karanjot786:mainfrom
desireddymohithreddy0925:canvas-feature

Conversation

@desireddymohithreddy0925

@desireddymohithreddy0925 desireddymohithreddy0925 commented Jul 10, 2026

Copy link
Copy Markdown

Description

This PR adds a Canvas and BrailleCanvas widget to @termuijs/widgets. It provides an HTML5 Canvas-like API for drawing lines, rectangles, and primitive graphics in the terminal, utilizing braille and block characters for sub-cell rendering resolution.

Related Issue

Closes #2250

Which package(s)?

@termuijs/widgets

Type of Change

  • 🐛 Bug fix (type:bug)
  • ✨ Feature (type:feature)
  • 📝 Docs (type:docs)
  • 🧪 Tests (type:testing)
  • ♻️ Refactor (type:refactor)
  • 🎨 Design / UX (type:design)
  • ♿ Accessibility (type:accessibility)
  • ⚡ Performance (type:performance)
  • 🔧 DevOps / CI (type:devops)
  • 🔒 Security (type:security)

Checklist

  • ⭐ You starred the repo. The needs-star check blocks your merge otherwise.
  • Tests pass locally: bun vitest run
  • Build passes: bun run build
  • Typecheck passes: bun run typecheck
  • You read CONTRIBUTING.md.
  • Your PR title follows type: short description.
  • Widget state mutators call markDirty() (if your change affects rendering).
  • No new any types without an inline comment explaining why.
  • No unrelated refactors bundled into this PR.

GSSoC 2026 Participation

  • You are a GSSoC 2026 contributor.
  • Your GSSoC profile: https://gssoc.girlscript.org/profile/YOUR_PROFILE_ID_HERE

Screenshots / Recordings (UI changes)

Notes for the Reviewer

The implementation uses Bresenham's line algorithm combined with UTF-8 braille character mapping (\u2800 to \u28FF) to achieve 2x4 sub-pixel drawing accuracy in standard terminal cells.

Summary by CodeRabbit

  • New Features
    • Added support for drawing filled circles on the canvas.
    • Added support for drawing outlined rectangles with configurable position and dimensions.

@github-actions github-actions Bot added the area:widgets @termuijs/widgets label Jul 10, 2026
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Canvas adds public methods for filled-circle rasterization and axis-aligned rectangle outlines. Circles scan their bounding box, while rectangles validate dimensions and draw four edges through lineTo.

Changes

Canvas primitive drawing

Layer / File(s) Summary
Primitive drawing methods
packages/widgets/src/display/Canvas.ts
Adds fillCircle for setting pixels inside a circle and strokeRect for drawing validated rectangle borders with lineTo.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested labels: type:feature, level:intermediate

Suggested reviewers: Karanjot786

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is too vague to describe the actual change and does not follow the required type: short description format. Rename it to something specific like feat: add canvas primitive drawing APIs.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The PR description fills the required sections and includes the linked issue, package, type, checklist, and reviewer notes.
Linked Issues check ✅ Passed The changes add canvas primitive drawing support with rectangle and circle APIs, matching the goal of issue #2250.
Out of Scope Changes check ✅ Passed The shown changes stay within the canvas drawing feature and do not introduce unrelated refactors.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/widgets/src/display/Canvas.ts (1)

123-135: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Consider batching markDirty() in fillCircle for consistency with fillRect.

fillCircle calls setPixel per pixel, each invoking bounds-checking and potentially markDirty() individually. The existing fillRect (lines 62–81) instead manipulates _pixels directly and calls markDirty() once. For large circles this means up to (2r+1)² setPixel calls with per-call overhead. Aligning fillCircle with the fillRect pattern would reduce redundant work.

♻️ Proposed optimization: direct pixel manipulation with batched dirty flag
 public fillCircle(cx: number, cy: number, r: number): void {
     cx = Math.floor(cx);
     cy = Math.floor(cy);
     r = Math.floor(r);
 
-    for (let y = -r; y <= r; y++) {
-        for (let x = -r; x <= r; x++) {
-            if (x * x + y * y <= r * r) {
-                this.setPixel(cx + x, cy + y);
-            }
+    let dirty = false;
+    const r2 = r * r;
+    for (let y = -r; y <= r; y++) {
+        const py = cy + y;
+        if (py < 0 || py >= this._canvasHeight) continue;
+        for (let x = -r; x <= r; x++) {
+            if (x * x + y * y > r2) continue;
+            const px = cx + x;
+            if (px < 0 || px >= this._canvasWidth) continue;
+            const idx = py * this._canvasWidth + px;
+            if (this._pixels[idx] !== 1) {
+                this._pixels[idx] = 1;
+                dirty = true;
+            }
         }
     }
+    if (dirty) {
+        this.markDirty();
+    }
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/widgets/src/display/Canvas.ts` around lines 123 - 135, Optimize
fillCircle by matching fillRect’s direct _pixels manipulation pattern: perform
bounds checks while writing circle pixels directly, avoid calling setPixel for
each pixel, and invoke markDirty() once only if at least one pixel was changed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/widgets/src/display/Canvas.ts`:
- Around line 123-135: Optimize fillCircle by matching fillRect’s direct _pixels
manipulation pattern: perform bounds checks while writing circle pixels
directly, avoid calling setPixel for each pixel, and invoke markDirty() once
only if at least one pixel was changed.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3966d62b-083e-4663-9bab-472a8e766a98

📥 Commits

Reviewing files that changed from the base of the PR and between 65d1f7e and ddadbe6.

📒 Files selected for processing (1)
  • packages/widgets/src/display/Canvas.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:widgets @termuijs/widgets

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] Canvas Widget for Primitive Drawing

1 participant