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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Gladiator (Glimmer Editor)
.gladiator
.DS_Store
7 changes: 5 additions & 2 deletions pixelart/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ build/
# for a library or gem, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# Gemfile.lock
# .ruby-version
# .ruby-gemset
.ruby-version
.ruby-gemset

# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc

# Gladiator (Glimmer Editor)
.gladiator
.DS_Store
143 changes: 142 additions & 1 deletion pixelart/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,148 @@ require 'pixelart/base'



## Canvas Vector Graphics

You may utilize inline-DSL (Domain Specific Language) syntax for building vector graphics via a canvas `PixelArt::Vector` object:

```ruby
require 'pixelart/base'


canvas = PixelArt::Vector.new( 24, 24 )

## face
canvas.path( stroke: 'black', fill: '#c8fbfb' ).line(
6, 23, 6, 14,
5, 14, 5, 13, 4, 12,
5, 11, 6, 11, 6, 7, 7, 6, 8, 5,
14, 5, 15, 6,
16, 7, 16, 19, 15, 20, 14, 21, 10, 21, 10, 23 )

## mouth
canvas.path( stroke: 'black' ).line( 10, 18, 14, 18 )
## nose
canvas.path( stroke: '#9be0e0' ).line( 12, 16, 12, 14 )


## eyes
canvas.path( stroke: 'black' ).line( 9, 13, 9, 12 )
.line( 10, 12, 10, 11 )
.line( 14, 13, 14, 12 )
.line( 15, 12, 15, 11 )
canvas.path( stroke: '#9be0e0' ).line( 10, 13, 10, 12 )
.line( 15, 13, 15, 12 )
canvas.path( stroke: '#75bdbd' ).line( 9, 12, 9, 11 )
.line( 14, 12, 14, 11 )

## headband
canvas.path( stroke: '#1a6ed5' ).line( 7, 8, 15, 8 )
canvas.path( stroke: 'white' ).line( 7, 7, 15, 7 )


canvas.save( "./tmp/punk3100.svg" )
```

Voila!

<img src="i/punk3100.svg" height=96 />

## Modular "Glimmer" Version

You may utilize a [Glimmer](https://github.com/AndyObtiva/glimmer) DSL for Pixelart vector graphics by requiring `'pixelart/glimmer'` and including `Glimmer` module:

```ruby
require 'pixelart/glimmer'
include Glimmer # activates Glimmer DSL for Pixelart (in real apps, mix into a class instead)
```

Afterwards, you may build canvas vector graphics declaratively and hierarchically:

```ruby
def face
line {
coordinates 6, 23, 6, 14,
5, 14, 5, 13, 4, 12,
5, 11, 6, 11, 6, 7, 7, 6, 8, 5,
14, 5, 15, 6,
16, 7, 16, 19, 15, 20, 14, 21, 10, 21, 10, 23
fill '#c8fbfb'
stroke 'black'
}
end

def mouth
line( 10, 18, 14, 18 ) {
stroke 'black'
}
end

def nose
line( 12, 16, 12, 14 ) {
stroke '#9be0e0'
}
end

def eyes
path {
line( 9, 13, 9, 12 )
line( 10, 12, 10, 11 )
line( 14, 13, 14, 12 )
line( 15, 12, 15, 11 )

stroke 'black'
}

path {
line( 10, 13, 10, 12 )
line( 15, 13, 15, 12 )

stroke '#9be0e0'
}

path {
line( 9, 12, 9, 11 )
line( 14, 12, 14, 11 )

stroke '#75bdbd'
}
end

def headband
line( 7, 8, 15, 8 ) {
stroke '#1a6ed5'
}

line( 7, 7, 15, 7 ) {
stroke 'white'
}
end

image = canvas(24, 24) {
file './tmp/punk3100.svg' # auto-saves file when canvas expression closes

face
mouth
nose
eyes
headband
}

# Re-open content to modify attributes and add more shapes
image.content {
file './tmp/punk3100-round-nose.svg' # auto-saves file when content closes

## Round Nose
circle( 12, 15, 1 ) {
fill '#9be0e0'
}
}
```

Voila!

<img src="i/punk3100.svg" height=96 /> <img src="i/punk3100-round-nose.svg" height=96 />

## Install

Just install the gem:
Expand All @@ -288,4 +430,3 @@ Just install the gem:

The scripts are dedicated to the public domain.
Use it as you please with no restrictions whatsoever.

16 changes: 16 additions & 0 deletions pixelart/i/punk3100-round-nose.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions pixelart/i/punk3100.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions pixelart/lib/glimmer/dsl/pixelart/attribute_expression.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require 'glimmer/dsl/expression'

module Glimmer
module DSL
module Pixelart
class AttributeExpression < Expression
def can_interpret?(parent, keyword, *args, &block)
parent.respond_to?("#{keyword}=") && !args.empty? && block.nil?
end

def interpret(parent, keyword, *args, &block)
parent.send("#{keyword}=", *args)
end
end
end
end
end
16 changes: 16 additions & 0 deletions pixelart/lib/glimmer/dsl/pixelart/dsl.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require 'glimmer/dsl/engine'
Dir[File.expand_path('*_expression.rb', __dir__)].each {|f| require f}

module Glimmer
module DSL
module Pixelart
Engine.add_dynamic_expressions(
Pixelart,
%w[
attribute
element
]
)
end
end
end
28 changes: 28 additions & 0 deletions pixelart/lib/glimmer/dsl/pixelart/element_expression.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require 'glimmer/dsl/expression'
require 'glimmer/dsl/parent_expression'
require 'glimmer/dsl/top_level_expression'
require_relative '../../pixelart/element'

module Glimmer
module DSL
module Pixelart
class ElementExpression < Expression
include ParentExpression
include TopLevelExpression

def can_interpret?(parent, keyword, *args, &block)
Glimmer::Pixelart::Element.element_exist?(keyword)
end

def interpret(parent, keyword, *args, &block)
Glimmer::Pixelart::Element.element_class(keyword).new(parent, keyword, *args, &block)
end

def add_content(element, keyword, *args, &block)
super
element.post_add_content
end
end
end
end
end
53 changes: 53 additions & 0 deletions pixelart/lib/glimmer/pixelart/element.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
require 'facets/string/camelcase'

module Glimmer
module Pixelart
class Element
class << self
def element_exist?(keyword)
constants.include?(element_class_name(keyword)) && element_class(keyword).respond_to?(:new)
end

def element_class(keyword)
const_get(element_class_name(keyword))
end

def element_class_name(keyword)
keyword.to_s.camelcase(:upper).to_sym
end
end

attr_reader :parent, :keyword, :args, :block

def initialize(parent, keyword, *args, &block)
@parent = parent
@keyword = keyword
@args = args
@block = block
@children = []
@parent&.post_initialize_child(self)
post_add_content if @block.nil?
end

# Subclasses may optionally override and call super to have children built
def build
@children&.each(&:build)
end

def post_initialize_child(child)
@children << child
end

def post_add_content
# No Op (subclasses may override to do something at the closing of the element)
end

# Enables re-opening content and adding new shapes
def content(&block)
Glimmer::DSL::Engine.add_content(self, Glimmer::DSL::Pixelart::ElementExpression.new, @keyword, &block)
end
end
end
end

Dir[File.expand_path('./element/*.rb', __dir__)].each {|f| require f}
50 changes: 50 additions & 0 deletions pixelart/lib/glimmer/pixelart/element/canvas.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require 'pixelart/base'

module Glimmer
module Pixelart
class Element
class Canvas < Element
attr_reader :vector
attr_accessor :file

def width
@args[0]
end

def height
@args[1]
end

def width=(new_width)
@args[0] = new_width
end

def height=(new_height)
@args[1] = new_height
end

def post_add_content
build
end

def build
@vector = ::PixelArt::Vector.new(*@args)
super
@vector.save(@file) if @file
end

def respond_to?(method_name, include_private = true)
super || @vector.respond_to?(method_name, include_private)
end

def method_missing(method_name, *args, **kwargs, &block)
if @vector.respond_to?(method_name, true)
@vector.send(method_name, *args, **kwargs, &block)
else
super
end
end
end
end
end
end
Loading