GCanvas Rendering Pipeline

A comprehensive guide to understanding the shape rendering architecture

Overview

GCanvas is a modular 2D rendering and game framework built on top of the HTML5 Canvas API. At its core, it uses a layered approach to rendering that provides a clean, declarative way to draw and manipulate shapes on the canvas.

The rendering pipeline in GCanvas follows a hierarchical structure that builds from basic positioning to complex visual elements. This hierarchy provides a consistent interface and allows for sophisticated compositions and transformations.

Euclidian
Geometry2d
Renderable
Transformable
Shape

The Rendering Pipeline

The rendering pipeline consists of a chain of classes that inherit from each other, with each layer adding more functionality. Let's explore each layer in detail:

1. Euclidian

The Euclidian class is the foundation of all visual elements in GCanvas. It provides the most basic properties needed for positioning and sizing objects.

Key Features:

Example: Creating a basic Euclidian object
// Create a basic Euclidian object
const basicShape = new Euclidian({
  x: 100,
  y: 100,
  width: 50,
  height: 30
});

// Position and size can be accessed and modified
console.log(basicShape.x, basicShape.y); // 100, 100
console.log(basicShape.width, basicShape.height); // 50, 30

// The object validates properties to prevent errors
basicShape.width = 80; // Valid
// basicShape.width = "invalid"; // Error: Invalid property value: width invalid
Euclidian visualization

2. Geometry2d

The Geometry2d class extends Euclidian by adding spatial constraints and bounding box calculations. This allows for controlled positioning and more advanced spatial operations.

Key Features:

Example: Using Geometry2d with constraints
// Create a Geometry2d object with constraints
const constrainedShape = new Geometry2d({
  x: 100,
  y: 100,
  width: 50,
  height: 30,
  minX: 50,
  maxX: 150,
  minY: 50,
  maxY: 150,
  crisp: true // Ensures positions and dimensions are whole numbers
});

// Constraints are applied when updating
constrainedShape.x = 40; // Will be constrained to minX (50)
constrainedShape.update();
console.log(constrainedShape.x); // 50

// Get bounding box information
const bounds = constrainedShape.getBounds();
console.log(bounds); // { x: 50, y: 100, width: 50, height: 30 }

// Get local (top-left) position relative to center
const local = constrainedShape.getLocalPosition();
console.log(local); // { x: 25, y: 85 }
Geometry2d constraints

3. Renderable

The Renderable class extends Geometry2d by adding visual properties and rendering capabilities. It handles the visibility, opacity, and shadows of visual elements.

Key Features:

Example: Creating a Renderable object with visual properties
// Create a Renderable object
const renderableShape = new Renderable({
  x: 100,
  y: 100,
  width: 50,
  height: 30,
  visible: true,
  opacity: 0.7,
  shadowColor: "rgba(0,0,0,0.5)",
  shadowBlur: 5,
  shadowOffsetX: 3,
  shadowOffsetY: 3
});

// Control visibility
renderableShape.visible = false; // Hide the object
renderableShape.visible = true;  // Show the object

// Control opacity (0-1)
renderableShape.opacity = 0.5;   // 50% opacity

// The render() method will apply these properties
// and then call draw() to render the actual shape
Renderable with opacity and shadows

4. Transformable

The Transformable class extends Renderable by adding transformation capabilities. It handles rotation and scaling of visual elements.

Key Features:

Example: Applying transformations to an object
// Create a Transformable object
const transformableShape = new Transformable({
  x: 100,
  y: 100,
  width: 50,
  height: 30,
  rotation: Math.PI / 4, // 45 degrees
  scaleX: 1.5,
  scaleY: 0.8
});

// Rotation and scaling can be adjusted
transformableShape.rotation = Math.PI / 6; // 30 degrees
transformableShape.scaleX = 2.0;
transformableShape.scaleY = 2.0;

// The applyTransforms() method applies these transformations
// by modifying the canvas context state
Transformable with rotation and scaling

5. Shape

The Shape class extends Transformable and serves as the base class for all visual elements in GCanvas. It adds styling properties and is extended by specific shape implementations like Circle, Rectangle, etc.

Key Features:

Example: Creating a Shape with styling properties
// Create a Shape object (base class for visual elements)
const shape = new Shape({
  x: 100,
  y: 100,
  width: 50,
  height: 30,
  color: "#ff0000",        // Fill color
  stroke: "#000000",       // Stroke color
  lineWidth: 2,            // Stroke width
  lineJoin: "round",       // Line join style
  lineCap: "round"         // Line cap style
});

// Specific shape classes (Circle, Rectangle, etc.) extend Shape
// and implement their own draw() method 
ctx.fill();
ctx.stroke();
ctx.restore();

// Draw triangle
ctx.save();
ctx.translate(triangle.x, triangle.y);
ctx.beginPath();
ctx.moveTo(0, -triangle.size/2);
ctx.lineTo(triangle.size/2, triangle.size/2);
ctx.lineTo(-triangle.size/2, triangle.size/2);
ctx.closePath();
ctx.fillStyle = triangle.color;
ctx.strokeStyle = triangle.stroke;
ctx.lineWidth = triangle.lineWidth;
ctx.fill();
ctx.stroke();
ctx.restore();
Shape implementations (Rectangle, Circle, Triangle)

Available Shapes

GCanvas provides a variety of shape classes that extend the base Shape class. Each specialized shape implements its own draw() method to render the specific geometry.

Circle

Circular shape with radius

Rectangle

Rectangular shape with width and height

Square

Square shape with equal sides

Triangle

Triangular shape

Star

Star shape with configurable points

Polygon

Multi-sided shape

TextShape

Text rendering with styling

Heart

Heart-shaped geometry

Line

Simple line segment

Cross

Cross shape

Cloud

Cloud-like shape

Cube

3D cube with perspective

Cylinder

3D cylinder with perspective

Cone

3D cone with perspective

Sphere

3D sphere with shading

Prism

3D prism with perspective

Ring

Ring or donut shape

Diamond

Diamond shape

SVGPath

SVG path rendering

Composing Shapes with Group

The Group class is a special container that inherits from Transformable. It allows multiple shapes to be grouped together and transformed as a single unit.

Key Features:

Example: Creating a group of shapes
// Create a Group to hold multiple shapes
const group = new Group({
  x: 100,
  y: 100
});

// Add shapes to the group
const rect = new Rectangle({
  width: 100,
  height: 50,
  color: "#ff0000"
});

const circle = new Circle(25, {
  x: 50,
  y: 0,
  color: "#0000ff"
});

const text = new TextShape("Hello", {
  x: 0,
  y: 0,
  color: "#ffffff",
  align: "center",
  baseline: "middle"
});

// Add shapes to the group
group.add(rect);
group.add(circle);
group.add(text);

// Moving the group moves all contained shapes
group.x = 200;
group.y = 150;

// Rotating or scaling the group affects all shapes
group.rotation = Math.PI / 6;  // 30 degrees
group.scaleX = 1.5;
group.scaleY = 1.5;

// Changes to the group's opacity affect all children
group.opacity = 0.7;

// Draw the group and all its children
group.draw();
Shape implementations (Rectangle, Circle, Triangle)