Commit 4e10dc3c authored by gijs's avatar gijs

Plotting the chars

parent 1ceb1635
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from datetime import datetime
import subprocess
import time
from plottertools.shapes import box
from plottertools.font import Font
from plottertools.textbox import Textbox
from chiplotle.geometry.core.coordinate import Coordinate
from settings import db
import os.path
from flask import Flask, Response, app, request, render_template
marginleft = 30 # margin left in mm
marginbottom = (297 / 3) # margin bottom in mm
page = {
'left': marginleft * -40,
'right': (210 - marginleft) * 40,
'bottom': marginbottom * -40,
'top': (297 - marginbottom) * 40
}
pen = 1
speed = 10
force = 1
font=Font(path='fonts/converted/futural.fnt', resolution=1, scale=3)
app = Flask(__name__)
@app.route("/api/ploteps/")
def ploteps():
epsfile = request.args.get('epsfile')
hpglfile = '{}.hpgl'.format(os.path.splitext(epsfile)[0])
# converting eps to hpgl
subprocess.call([
'./eps2hpgl.sh',
'./{0}'.format(epsfile)
])
handle = open(hpglfile)
shape = ''.join(handle.readlines()).replace('\n', '')
textbox = Textbox(
font=font,
width = 50 * 40,
position = Coordinate(page['right'] - (55 * 40), page['bottom'] + (12 * 40)),
align = Textbox.alignLeft,
lineHeight=1.40
)
textbox.insertText('{0} \n{1} \n\ntype.code, Maison du Livre, Bruxelles'.format(hpglfile, datetime.now().strftime("%d-%m-%Y %H:%M")))
hpgl = 'SC{0},{1},{2},{3};SP{4};FS{5};VS{6};PU;{7};PU;'.format(page['left'], page['right'], page['bottom'], page['top'], pen, force, speed, shape)
# hpgl += box((page['left'] + 200, page['bottom'] + 200), 200 * 40, 287 * 40)
hpgl += textbox.hpgl()
db.plots.insert({'hpgl': hpgl, 'plotted': False})
return '100'
if __name__ == "__main__":
app.run(host="localhost", port=5555, debug=True)
\ No newline at end of file
File mode changed from 100644 to 100755
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
#!/usr/bin/env python
#! -*- coding: utf-8 -*-
from writer import Writer
from font import Font
from whitespace import Whitespace
from character import Character
from textline import Textline
from textbox import Textbox
from multilineTextbox import MultilineTextbox
from memory import enlargeMemory
from plottermargins import PlotterMargins
import shapes
\ No newline at end of file
#!/usr/bin/env python
#! -*- coding: utf-8 -*-
from copy import deepcopy
# Character object. Character information is stored inside this object
class Character (object):
def __init__ (self, source = False):
self.key = source["key"]
self._width = source["width"]
self._height = source["height"]
self._lines = source["lines"]
if 'margins' in source:
self._margins = source["margins"]
else:
self._margins = [0,0,0,0]
self.lines = deepcopy (self._lines)
self.shape = []
self.curve_resolution = 10
self.length = 0
self._scale = 1
@property
def width (self):
return self._width * self.scale
@property
def height (self):
return self._height * self.scale
@property
def margins (self):
return [val * self.scale for val in self._margins]
def render (self, resolution = False):
if resolution <> False:
self.curve_resolution = resolution
if len (self.lines) > 0 and len (self.lines[0]) > 0:
self.shape = []
position = (self._height, 0)
for line in self.lines:
points = []
for segment in line:
if len(segment) > 2:
# Curve
if len (points) > 0:
curve_points = [position]
else:
curve_points = []
for i in range (0,len(segment),2):
curve_points.append((segment[i], segment[i+1]))
for point in bezier_interpolation(curve_points, self.curve_resolution, 1):
points.append ((point[0] - position[0], point[1] - position[1]))
#points.append ((point[0], point[1]))
position = (point[0], point[1])
else:
points.append ((segment[0] - position[0], segment[1] - position[1]))
#points.append ((segment[0], segment[1]))
position = (segment[0], segment[1])
self.shape.append(points)
def hpgl (self, offset = (0,0)):
buff = ['PA{0},{1}'.format (self.x + offset[0], self.y + offset[1])]
for line in self.shape:
buff.append ('PR{0:.1f},{1:.1f}'.format (float (line[0][0]), float (line[0][1]))) # switch to relative.
points = ['{0:.1f},{1:.1f}'.format (float (point[0]), float (point[1])) for point in line[1:]]
buff.append ('PD{0}'.format (','.join (points)))
buff.append ('PU')
return ';'.join (buff)
@property
def scale (self):
return self._scale
@scale.setter
def scale (self, scale):
self._scale = scale
self.shape = [[(point[0] * scale, point[1] * scale) for point in line] for line in self.shape]
# Loop through all lines, and points to scale them
def validate (self):
return True if self.patt.match (self.source) <> None else False
\ No newline at end of file
#!/usr/bin/env python
#! -*- coding: utf-8 -*-
from character import Character
from copy import deepcopy
import os
import json
class Font (object):
def __init__ (self, path = False, resolution = False, scale = False):
self.path = ''
self.cache = True
self.source = {}
self.chars = {}
self.resolution = 10 if resolution == False else resolution
self.length = 0
self.name = ''
self.cacheDir = 'shape_font_cache' #'~/tmp/shape_font_cache'
self.cacheFilePath = '{0}/{1}-{2}.json' # Basepath, name, resolution
if path <> False:
self.load (path)
if resolution <> False:
self.render (resolution = resolution)
if scale <> False:
self.scale (scale)
def load (self, path = False):
if path <> False:
self.path = path
#try:
with open(self.path, 'r') as font_file:
self.source = json.load(font_file)
font_file.close()
self.name = self.source["name"]
for char in self.source["chars"]:
char = Character(char)
self.addChar(char)
#except:
#print 'could not load font'
#return False
#return True
def write (self, path = False):
self.scale (1)
writer = FontWriter (self)
return writer.write (path)
def get (self, key):
if key in self.chars:
return deepcopy (self.chars[key])
else:
return False
def addChar (self, char):
self.chars[char.key] = char
def getChar (self, char):
return self.get (ord (char))
def render (self, resolution = False):
if resolution <> False:
self.resolution = resolution
if self.cache == True:
if self.loadCache () == True:
return True
for key in self.chars:
self.chars[key].render(self.resolution)
if self.cache == True:
self.writeCache ()
def scale (self, scale = 1):
self.height = self.chars[self.chars.keys()[0]]._height * scale * 1.60
for key in self.chars:
self.chars[key].scale = scale
@property
def cacheFile (self):
return self.cacheFilePath.format (self.cacheDir, self.name, self.resolution)
def loadCache (self):
if self.cacheExists():
cache = json.load (open (self.cacheFile, 'r'))
self.putCacheObject (cache)
return True
else:
return False
def writeCache (self):
if self.cacheDirExists () == False:
self.createCacheDir ()
handle = open (self.cacheFile, 'w')
return json.dump (self.getCacheObject (), handle)
def cacheExists (self):
if os.path.exists (self.cacheFile):
return True
else:
if self.cacheDirExists () == False:
self.createCacheDir ()
return False
def cacheDirExists (self):
return os.path.exists (self.cacheDir)
def createCacheDir (self):
os.makedirs (self.cacheDir)
def getCacheObject (self):
return {char: self.chars[char].shape for char in self.chars}
def putCacheObject (self, cache):
for char in cache:
self.chars[int (char)].shape = cache[char]
\ No newline at end of file
#!/usr/bin/env python
#! -*- coding: utf-8 -*-
import re
from writer import Writer
# Exports the font object to an JSON file
class FontWriter (object):
pointReplacementPatt = re.compile("(\s+)(\-?\d+),\n\s+(\-?\d+)", flags=re.M)
def __init__ (self, font = False):
if font <> False:
self.font = font
def write (self, path):
if self.font <> False:
writeList = []
for char in self.font.chars:
#writeObject = {}
#writeObject['key'] = self.font.chars[char].key
#writeObject['width'] = self.font.chars[char].width
#writeObject['height'] = self.font.chars[char].height
#writeObject['lines'] = self.font.chars[char].lines
#
writeObject = dict (
key = self.font.chars[char].key,
width = self.font.chars[char].width,
height = self.font.chars[char].height,
lines = self.font.chars[char].lines,
margins = self.font.chars[char].margins
)
writeList.append (writeObject)
self.writer = Writer ({'name': self.font.name, 'chars': writeList})
buff = self.pointReplacementPatt.sub ("\\1\\2,\\3", self.writer.build ())
try:
with open (path, 'w') as self.f:
self.f.write (buff)
self.f.close ()
except IOError:
return False
return True
\ No newline at end of file
from chiplotle.geometry.core.coordinate import Coordinate
class PlotterMargins:
def __init__ (self, coordinates):
self.all_coordinates = coordinates
## PROPERTIES ##
@property
def left(self):
return self.all_coordinates[0]
@property
def bottom(self):
return self.all_coordinates[1]
@property
def right(self):
return self.all_coordinates[2]
@property
def top(self):
return self.all_coordinates[3]
@property
def width(self):
x1, y1, x2, y2 = self.all_coordinates
return x2 - x1
@property
def height(self):
x1, y1, x2, y2 = self.all_coordinates
return y2 - y1
@property
def center(self):
#return (self.right + self.left) / 2., (self.top + self.bottom) / 2.
x = (self.right + self.left) / 2.
y = (self.top + self.bottom) / 2.
return Coordinate(x, y)
@property
def bottom_left(self):
coords = self.all_coordinates
return Coordinate(*coords[0:2])
@property
def bottom_right(self):
coords = self.all_coordinates
return Coordinate(coords[2], coords[1])
@property
def top_right(self):
coords = self.all_coordinates
return Coordinate(*coords[2:4])
@property
def top_left(self):
coords = self.all_coordinates
return Coordinate(coords[0], coords[3])
@property
def all_coordinates(self):
self._plotter._serial_port.flushInput( )
self._plotter._write_string_to_port(self._queryCommand.format)
m = self._plotter._read_port( ).rstrip('\r').split(',')
return tuple([eval(n) for n in m])
\ No newline at end of file
#!/usr/bin/env python
#! -*- coding: utf-8 -*-
def enlargeMemory (plotter):
if plotter.type == "HP7550A":
plotter._serial_port.write (chr(27) + '.T10978;1778;0;0;44:')
plotter._send_query (chr(27) + '.L')
plotter._serial_port.write (chr(27) + '.@10978:')
plotter.buffer_size = int (plotter._buffer_space / 2)
elif plotter.type == "HP7596A":
plotter._serial_port.write (chr(27) + '.T20552;1024;0;0;0;1024:')
plotter._send_query (chr(27) + '.L')
plotter._serial_port.write (chr(27) + '.@20552:')
plotter.buffer_size = int (plotter._buffer_space / 2)
elif plotter.type == 0400 or plotter.type == 'GRX-400AG':
plotter._serial_port.write (chr(27) + '.T14337;3072;0;0;0;1024:')
plotter._send_query (chr(27) + '.L')
plotter._serial_port.write (chr(27) + '.@14337:')
plotter.buffer_size = int (plotter._buffer_space / 2)
elif plotter.type == 3500 or plotter.type == 'DXY-3500':
plotter._serial_port.write (chr(27) + '.T14337;3072;0;0;0;1024:')
plotter._send_query (chr(27) + '.L')
plotter._serial_port.write (chr(27) + '.@14337:')
plotter.buffer_size = int (plotter._buffer_space / 2)
return plotter.buffer_size
\ No newline at end of file
#!/usr/bin/env python
#! -*- coding: utf-8 -*-
# Textline combines wrapper for characters
class MultilineTextbox (object):
def __init__ (self, font = False, width = False, position = False, align = False, height = False, cols = 1, spacing = 400):
self.font = font
self.width = width
if isinstance(position, Coordinate):
self.position = position
else:
self.position = Coordinate (0, 0)
self.width = width if width <> False else 0
self.height = height if height <> False else False
self.maxCols = int (cols)
self.spacing = int (spacing)
self.cols = []
if isinstance (font, Font):
self.font = font
else:
self.font = None
if align <> False:
self.align = align
else:
self.align = Textbox.alignLeft
self.newCol()
@property
def colWidth (self):
return (self.width - ((self.maxCols - 1) * self.spacing)) / self.maxCols
def newCol (self):
if len(self.cols) < self.maxCols:
pos = Coordinate (self.position[0], self.position[1] + ((len(self.cols) * (self.colWidth + self.spacing))))
self.cols.append (Textbox (font = self.font, width = self.colWidth, position = pos, align = self.align, height = self.height))
return True
else:
return False
def insertText (self, text):
for char in text:
if self.cols[-1].insertText (char) == False:
if self.newCol ():
if self.cols[-1].insertText (char) == False:
return False
else:
return False
\ No newline at end of file
from chiplotle.geometry.core.coordinate import Coordinate
class PlotterMargins:
def __init__ (self, coordinates):
self.all_coordinates = coordinates
## PROPERTIES ##
@property
def left(self):
return self.all_coordinates[0]
@property
def bottom(self):
return self.all_coordinates[1]
@property
def right(self):
return self.all_coordinates[2]
@property
def top(self):
return self.all_coordinates[3]
@property
def width(self):
x1, y1, x2, y2 = self.all_coordinates
return x2 - x1
@property
def height(self):
x1, y1, x2, y2 = self.all_coordinates
return y2 - y1
@property
def center(self):
#return (self.right + self.left) / 2., (self.top + self.bottom) / 2.
x = (self.right + self.left) / 2.
y = (self.top + self.bottom) / 2.
return Coordinate(x, y)
@property
def bottom_left(self):
coords = self.all_coordinates
return Coordinate(*coords[0:2])
@property
def bottom_right(self):
coords = self.all_coordinates
return Coordinate(coords[2], coords[1])
@property
def top_right(self):
coords = self.all_coordinates
return Coordinate(*coords[2:4])
@property
def top_left(self):
coords = self.all_coordinates
return Coordinate(coords[0], coords[3])
@property
def all_coordinates(self):
self._plotter._serial_port.flushInput( )
self._plotter._write_string_to_port(self._queryCommand.format)
m = self._plotter._read_port( ).rstrip('\r').split(',')
return tuple([eval(n) for n in m])
\ No newline at end of file
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
def box (s, width, height):
return 'PA{0},{1};PD'.format(s[0], s[1]) \
+ '{0},{1},'.format(s[0], s[1] + height) \
+ '{0},{1},'.format(s[0] + width, s[1] + height) \
+ '{0},{1},'.format(s[0] + width, s[1]) \
+ '{0},{1};PU;'.format(s[0], s[1])
\ No newline at end of file
#!/usr/bin/env python
#! -*- coding: utf-8 -*-
from chiplotle.geometry.core.coordinate import Coordinate
from font import Font
from textline import Textline
from copy import deepcopy
class Charbuff (object):
chars = []
offset = 0
def __init__ (self, chars=None, offset=None):
if offset is not None:
self.offset = offset
if chars is not None:
self.chars = chars
def add(self, char):
self.chars.append(char)
@property
def width(self):
return reduce(lambda x, char: x + char.width + char.margins[1], self.chars, self.offset)
# Textbox. Wrapper for lines.
class Textbox (object):
alignLeft = 'left'
alignCenter = 'center'
alignRight = 'right'
def __init__ (self, font = False, width = False, position = False, align = False, height = False, lineHeight = 1):
if isinstance(position, Coordinate):
self.position = position
else:
self.position = Coordinate (0, 0)
self.width = width if width <> False else 0
self.maxHeight = height if height <> False else False
self.height = 0
self.int_y = 0
self.lineHeight = lineHeight
self._lines = []
if isinstance (font, Font):
self.font = font
else:
self.font = None
if align <> False:
self.align = align
print self.align
else:
self.align = self.alignLeft
self.newLine()
@property
def lines (self):
buff = []
for line in self._lines:
if self.align == self.alignCenter or self.align == self.alignRight:
line = deepcopy(line)
delta_x = (self.width - line.int_x) * .5 if self.align == self.alignCenter else (self.width - line.int_x)
line.offset((delta_x, 0))
buff.append(line)
return buff
def clear (self):
self._lines = []
self.newLine()
def newLine (self):
for line in self._lines:
line.offset((0, self.font.height * self.lineHeight))
self._lines.append(Textline(width = self.width, position = Coordinate(self.position[0], self.position[1])))
#self.int_y += self.font.height * self.lineHeight
self.height += self.font.height * self.lineHeight
return True
def setFont (self, font):
if isinstance (font, Font):
self.font = font
def setSize (self, size):
if type (size) == int:
self.size = size
def insertText (self, text):
buff = Charbuff([])
for char in text:
if char == '\n':
if self.newLine() == False:
# Could not add the new line. Return False
return False
else:
self.writeBuff(buff)
buff = Charbuff([])
else:
charObj = self.font.getChar(char)
if charObj <> False:
if char == ' ':
self.writeBuff(buff, charObj)
buff = Charbuff([])
else:<