Multi-layer compositing system with blend modes and advanced effects.
// Create layer manager
layerManager := advancegg.NewLayerManager(800, 600)
// Add layers
background := layerManager.AddLayer("background")
content := layerManager.AddLayer("content")
overlay := layerManager.AddLayer("overlay")
// Each layer is a full Context that you can draw on
background.SetRGB(0.2, 0.2, 0.4)
background.Clear()
content.SetRGB(1, 0.5, 0)
content.DrawCircle(400, 300, 100)
content.Fill()
overlay.SetRGBA(1, 1, 1, 0.5)
overlay.DrawString("Overlay Text", 350, 320)
// Get layer by name
layer := layerManager.GetLayer("content")
// Remove layer
layerManager.RemoveLayer("overlay")
// Duplicate layer
layerManager.DuplicateLayer("content", "content_copy")
// Reorder layers
layerManager.MoveLayerUp("background")
layerManager.MoveLayerDown("overlay")
layerManager.MoveLayerToTop("content")
layerManager.MoveLayerToBottom("background")
// Get layer list
layerNames := layerManager.GetLayerNames()
for _, name := range layerNames {
fmt.Printf("Layer: %s\n", name)
}
// Set layer opacity (0.0 to 1.0)
layerManager.SetLayerOpacity("content", 0.8) // 80% opacity
layerManager.SetLayerOpacity("overlay", 0.5) // 50% opacity
// Get layer opacity
opacity := layerManager.GetLayerOpacity("content")
fmt.Printf("Layer opacity: %f\n", opacity)
// Fade layer in/out
for i := 0; i <= 100; i++ {
opacity := float64(i) / 100.0
layerManager.SetLayerOpacity("content", opacity)
// Render frame
}
// Show/hide layers
layerManager.SetLayerVisible("background", true)
layerManager.SetLayerVisible("overlay", false)
// Toggle visibility
layerManager.ToggleLayerVisibility("content")
// Check if layer is visible
visible := layerManager.IsLayerVisible("content")
fmt.Printf("Layer visible: %v\n", visible)
// Lock/unlock layers
layerManager.SetLayerLocked("background", true) // Prevent modifications
layerManager.SetLayerLocked("content", false) // Allow modifications
// Check if layer is locked
locked := layerManager.IsLayerLocked("background")
fmt.Printf("Layer locked: %v\n", locked)
// Set blend mode for layer
layerManager.SetLayerBlendMode("content", advancegg.BlendModeNormal) // Default
layerManager.SetLayerBlendMode("overlay", advancegg.BlendModeMultiply)
layerManager.SetLayerBlendMode("highlight", advancegg.BlendModeScreen)
// Available blend modes:
// Normal, Multiply, Screen, Overlay, SoftLight, HardLight,
// ColorDodge, ColorBurn, Darken, Lighten, Difference, Exclusion
// Color blend modes
layerManager.SetLayerBlendMode("color", advancegg.BlendModeColor)
layerManager.SetLayerBlendMode("hue", advancegg.BlendModeHue)
layerManager.SetLayerBlendMode("saturation", advancegg.BlendModeSaturation)
layerManager.SetLayerBlendMode("luminosity", advancegg.BlendModeLuminosity)
// Special effects
layerManager.SetLayerBlendMode("glow", advancegg.BlendModeLinearDodge)
layerManager.SetLayerBlendMode("shadow", advancegg.BlendModeLinearBurn)
layerManager.SetLayerBlendMode("vivid", advancegg.BlendModeVividLight)
layerManager.SetLayerBlendMode("pin", advancegg.BlendModePinLight)
// Define custom blend function
customBlend := func(base, overlay color.Color) color.Color {
br, bg, bb, ba := base.RGBA()
or, og, ob, oa := overlay.RGBA()
// Custom blending logic
r := (br + or) / 2
g := (bg + og) / 2
b := (bb + ob) / 2
a := (ba + oa) / 2
return color.RGBA{uint8(r >> 8), uint8(g >> 8), uint8(b >> 8), uint8(a >> 8)}
}
// Register and use custom blend mode
advancegg.RegisterBlendMode("custom", customBlend)
layerManager.SetLayerBlendMode("special", "custom")
// Add drop shadow to layer
shadow := advancegg.DropShadowEffect{
OffsetX: 5,
OffsetY: 5,
Blur: 10,
Color: color.RGBA{0, 0, 0, 128},
Spread: 2,
}
layerManager.AddLayerEffect("content", shadow)
// Inner shadow
innerShadow := advancegg.InnerShadowEffect{
OffsetX: -2,
OffsetY: -2,
Blur: 5,
Color: color.RGBA{0, 0, 0, 100},
}
layerManager.AddLayerEffect("content", innerShadow)
// Outer glow
outerGlow := advancegg.OuterGlowEffect{
Size: 15,
Color: color.RGBA{255, 255, 0, 200},
Spread: 5,
Quality: advancegg.EffectQualityHigh,
}
layerManager.AddLayerEffect("content", outerGlow)
// Inner glow
innerGlow := advancegg.InnerGlowEffect{
Size: 10,
Color: color.RGBA{255, 255, 255, 150},
Source: advancegg.GlowSourceCenter,
}
layerManager.AddLayerEffect("content", innerGlow)
// Stroke (outline)
stroke := advancegg.StrokeEffect{
Size: 3,
Color: color.RGBA{255, 0, 0, 255},
Position: advancegg.StrokePositionOutside,
FillType: advancegg.StrokeFillColor,
}
layerManager.AddLayerEffect("content", stroke)
// Gradient stroke
gradientStroke := advancegg.StrokeEffect{
Size: 5,
Position: advancegg.StrokePositionCenter,
FillType: advancegg.StrokeFillGradient,
Gradient: myGradient,
}
layerManager.AddLayerEffect("content", gradientStroke)
// Bevel effect
bevel := advancegg.BevelEffect{
Style: advancegg.BevelStyleInner,
Technique: advancegg.BevelTechniqueSmoothChisel,
Depth: 5,
Direction: advancegg.BevelDirectionUp,
Size: 10,
Soften: 2,
Angle: 120,
Altitude: 30,
HighlightMode: advancegg.BlendModeScreen,
ShadowMode: advancegg.BlendModeMultiply,
}
layerManager.AddLayerEffect("content", bevel)
// Create layer mask
mask := layerManager.CreateLayerMask("content")
// Draw on mask (white = visible, black = hidden)
mask.SetRGB(1, 1, 1) // White
mask.DrawCircle(400, 300, 100)
mask.Fill()
// Gradient mask
mask.SetRGB(0, 0, 0) // Black
mask.Clear()
gradient := advancegg.NewLinearGradient(0, 0, 800, 0)
gradient.AddColorStop(0, color.RGBA{255, 255, 255, 255}) // White (visible)
gradient.AddColorStop(1, color.RGBA{0, 0, 0, 255}) // Black (hidden)
mask.SetFillStyle(gradient)
mask.DrawRectangle(0, 0, 800, 600)
mask.Fill()
// Enable/disable mask
layerManager.SetLayerMaskEnabled("content", true)
layerManager.SetLayerMaskEnabled("content", false)
// Invert mask
layerManager.InvertLayerMask("content")
// Apply mask (merge with layer)
layerManager.ApplyLayerMask("content")
// Delete mask
layerManager.DeleteLayerMask("content")
// Mask from selection
selection := advancegg.CreateSelection(selectionPath)
layerManager.CreateLayerMaskFromSelection("content", selection)
// Create vector mask from path
path := advancegg.NewPath2D()
path.MoveTo(100, 100)
path.LineTo(700, 100)
path.LineTo(700, 500)
path.LineTo(100, 500)
path.ClosePath()
vectorMask := layerManager.CreateVectorMask("content", path)
// Feather vector mask
vectorMask.SetFeather(10) // 10 pixel feather
// Vector mask operations
vectorMask.Subtract(anotherPath)
vectorMask.Intersect(anotherPath)
vectorMask.Add(anotherPath)
vectorMask.Exclude(anotherPath)
// Create layer group
group := layerManager.CreateLayerGroup("UI Elements")
// Add layers to group
layerManager.AddLayerToGroup("button", "UI Elements")
layerManager.AddLayerToGroup("text", "UI Elements")
layerManager.AddLayerToGroup("icon", "UI Elements")
// Group properties
layerManager.SetGroupOpacity("UI Elements", 0.8)
layerManager.SetGroupBlendMode("UI Elements", advancegg.BlendModeMultiply)
layerManager.SetGroupVisible("UI Elements", false)
// Nested groups
subGroup := layerManager.CreateLayerGroup("Buttons", "UI Elements")
layerManager.AddLayerToGroup("primary_button", "Buttons")
layerManager.AddLayerToGroup("secondary_button", "Buttons")
// Collapse/expand group
layerManager.SetGroupCollapsed("UI Elements", true)
// Duplicate group
layerManager.DuplicateGroup("UI Elements", "UI Elements Copy")
// Merge group
layerManager.MergeGroup("UI Elements")
// Ungroup
layerManager.Ungroup("UI Elements")
// Get group layers
groupLayers := layerManager.GetGroupLayers("UI Elements")
for _, layerName := range groupLayers {
fmt.Printf("Group layer: %s\n", layerName)
}
// Flatten all layers
result := layerManager.Flatten()
// Flatten specific layers
layersToFlatten := []string{"background", "content"}
flattened := layerManager.FlattenLayers(layersToFlatten)
// Flatten visible layers only
visibleFlattened := layerManager.FlattenVisible()
// Flatten with options
options := advancegg.FlattenOptions{
IncludeHidden: false,
PreserveAlpha: true,
BackgroundColor: color.RGBA{255, 255, 255, 255},
}
customFlattened := layerManager.FlattenWithOptions(options)
// Export individual layers
for _, layerName := range layerManager.GetLayerNames() {
layer := layerManager.GetLayer(layerName)
layer.SavePNG(fmt.Sprintf("layer_%s.png", layerName))
}
// Export with transparency
layerManager.ExportLayerPNG("content", "content_with_alpha.png", true)
// Export layer bounds only
bounds := layerManager.GetLayerBounds("content")
cropped := layerManager.ExportLayerBounds("content", bounds)
// Export as PSD (Photoshop format)
layerManager.ExportPSD("project.psd")
package main
import (
"image/color"
"github.com/GrandpaEJ/advancegg"
)
func main() {
// Create layer manager
lm := advancegg.NewLayerManager(1200, 800)
// Background layer with gradient
bg := lm.AddLayer("background")
bgGradient := advancegg.NewLinearGradient(0, 0, 0, 800)
bgGradient.AddColorStop(0, color.RGBA{20, 30, 60, 255})
bgGradient.AddColorStop(1, color.RGBA{60, 30, 20, 255})
bg.SetFillStyle(bgGradient)
bg.DrawRectangle(0, 0, 1200, 800)
bg.Fill()
// Mountains layer
mountains := lm.AddLayer("mountains")
mountains.SetRGBA(0.1, 0.2, 0.3, 0.8)
drawMountains(mountains)
lm.SetLayerBlendMode("mountains", advancegg.BlendModeMultiply)
// Stars layer
stars := lm.AddLayer("stars")
drawStars(stars, 100)
lm.SetLayerOpacity("stars", 0.7)
// Moon layer with glow effect
moon := lm.AddLayer("moon")
moon.SetRGB(1, 1, 0.9)
moon.DrawCircle(900, 150, 60)
moon.Fill()
// Add glow effect to moon
glow := advancegg.OuterGlowEffect{
Size: 30,
Color: color.RGBA{255, 255, 200, 100},
Spread: 10,
}
lm.AddLayerEffect("moon", glow)
// Text layer with effects
text := lm.AddLayer("title")
text.LoadFontFace("fonts/arial-bold.ttf", 48)
text.SetRGB(1, 1, 1)
text.DrawStringAnchored("Starry Night", 600, 400, 0.5, 0.5)
// Add text effects
shadow := advancegg.DropShadowEffect{
OffsetX: 3,
OffsetY: 3,
Blur: 8,
Color: color.RGBA{0, 0, 0, 150},
}
lm.AddLayerEffect("title", shadow)
stroke := advancegg.StrokeEffect{
Size: 2,
Color: color.RGBA{100, 100, 200, 255},
Position: advancegg.StrokePositionOutside,
}
lm.AddLayerEffect("title", stroke)
// Create layer group for UI
ui := lm.CreateLayerGroup("UI")
// Watermark layer
watermark := lm.AddLayer("watermark")
lm.AddLayerToGroup("watermark", "UI")
watermark.SetRGBA(1, 1, 1, 0.3)
watermark.LoadFontFace("fonts/arial.ttf", 16)
watermark.DrawStringAnchored("© AdvanceGG 2024", 1150, 750, 1, 1)
// Set group properties
lm.SetGroupOpacity("UI", 0.8)
// Flatten and save
result := lm.Flatten()
result.SavePNG("starry-night-composition.png")
// Save individual layers for editing
lm.ExportPSD("starry-night-project.psd")
}
func drawMountains(dc *advancegg.Context) {
// Draw mountain silhouettes
dc.MoveTo(0, 600)
dc.LineTo(200, 400)
dc.LineTo(400, 500)
dc.LineTo(600, 350)
dc.LineTo(800, 450)
dc.LineTo(1000, 300)
dc.LineTo(1200, 400)
dc.LineTo(1200, 800)
dc.LineTo(0, 800)
dc.ClosePath()
dc.Fill()
}
func drawStars(dc *advancegg.Context, count int) {
dc.SetRGB(1, 1, 1)
for i := 0; i < count; i++ {
x := rand.Float64() * 1200
y := rand.Float64() * 400
size := 1 + rand.Float64()*2
dc.DrawCircle(x, y, size)
dc.Fill()
}
}