Initial text support implementation, pt. III.

Generate TTF texture ad hoc.
This commit is contained in:
Lucio Andrés Illanes Albornoz 2018-07-02 22:49:43 +02:00
parent 22c4904c20
commit e656f549ff
7 changed files with 170 additions and 141 deletions

View File

@ -8,10 +8,12 @@
# 1) -A: render frame #1, render frame #2, ... # 1) -A: render frame #1, render frame #2, ...
# 2) -o: support at least {GIF,MP4,WEBM} # 2) -o: support at least {GIF,MP4,WEBM}
# 3) -s: effects: rotate, smash into bricks, swirl, wave, ... # 3) -s: effects: rotate, smash into bricks, swirl, wave, ...
# 4) XXX autodetect video width from widest mircart # 4) Feature: include ETA @ progress bar
# 5) XXX convert TTF to texture PNG & coords TXT, render accordingly # 5) Feature: autodetect video width from widest mircart
# 6) XXX dont stall GPU w/ glReadPixels(), switch to asynchronous model w/ FBO or PBO (http://www.songho.ca/opengl/gl_fbo.html, http://www.songho.ca/opengl/gl_pbo.html) # 6) Feature: render mircart as 3D blocks vs flat surface
# 7) XXX render mircart as 3D blocks vs flat surface # 7) Optimisation: dont stall GPU w/ glReadPixels(), switch to asynchronous model w/ FBO or PBO (http://www.songho.ca/opengl/gl_fbo.html, http://www.songho.ca/opengl/gl_pbo.html)
# 8) OpenGL: use VAOs + glVertexAttribFormat + glVertexAttribBinding
# 9) OpenGL: use glEnable(GL_BLEND) + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) & multiply texel * bgcolour (https://learnopengl.com/Advanced-OpenGL/Blending)
# #
from getopt import getopt, GetoptError from getopt import getopt, GetoptError
@ -21,6 +23,7 @@ import os, sys, time
import wx import wx
from ENNToolGLCanvasPanel import ENNToolGLCanvasPanel from ENNToolGLCanvasPanel import ENNToolGLCanvasPanel
from ENNToolGLTTFTexture import ENNToolGLTTFTexture
from ENNToolMiRCARTImporter import ENNToolMiRCARTImporter from ENNToolMiRCARTImporter import ENNToolMiRCARTImporter
class ENNToolApp(object): class ENNToolApp(object):
@ -91,7 +94,7 @@ class ENNToolApp(object):
MiRCART += ENNToolMiRCARTImporter(inFile).outMap MiRCART += ENNToolMiRCARTImporter(inFile).outMap
curY, rotateX, rotateY, translateY = 0, 0, 0, scrollRate curY, rotateX, rotateY, translateY = 0, 0, 0, scrollRate
artTextureId, artInfo = panelGLCanvas.initTexture(texturePathName) artTextureId, artInfo = ENNToolGLTTFTexture(MiRCART, optdict["-R"], optdict["-r"]).getParams()
artVbo, artVboLen, lastY, numVertices = panelGLCanvas.renderMiRCART(artInfo, MiRCART, cubeSize=optdict["-R"]) artVbo, artVboLen, lastY, numVertices = panelGLCanvas.renderMiRCART(artInfo, MiRCART, cubeSize=optdict["-R"])
if "-v" in optdict: if "-v" in optdict:
print("{} vertices".format(numVertices)) print("{} vertices".format(numVertices))

View File

@ -10,18 +10,14 @@
# Wed, 27 Jun 2018 16:02:12 +0200 [3] <https://www.khronos.org/opengl/wiki/How_lighting_works#Good_Settings.> # Wed, 27 Jun 2018 16:02:12 +0200 [3] <https://www.khronos.org/opengl/wiki/How_lighting_works#Good_Settings.>
# Wed, 27 Jun 2018 16:02:13 +0200 [4] <https://www.khronos.org/opengl/wiki/Common_Mistakes> # Wed, 27 Jun 2018 16:02:13 +0200 [4] <https://www.khronos.org/opengl/wiki/Common_Mistakes>
# Wed, 27 Jun 2018 16:02:14 +0200 [5] <https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_layout> # Wed, 27 Jun 2018 16:02:14 +0200 [5] <https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_layout>
# Thu, 28 Jun 2018 17:03:16 +0200 [6] <https://stackoverflow.com/questions/384759/how-to-convert-a-pil-image-into-a-numpy-array> # Thu, 28 Jun 2018 18:32:50 +0200 [6] <https://stackoverflow.com/questions/18935203/shader-position-vec4-or-vec3>
# Thu, 28 Jun 2018 17:04:59 +0200 [7] <https://www.khronos.org/opengl/wiki/Common_Mistakes#y-axis>
# Thu, 28 Jun 2018 18:32:50 +0200 [8] <https://stackoverflow.com/questions/18935203/shader-position-vec4-or-vec3>
# #
from OpenGL.GL import * from OpenGL.GL import *
from OpenGL.GL import shaders from OpenGL.GL import shaders
from PIL import Image
import cv2, numpy import cv2, numpy
import ctypes, os, sys, time import ctypes, os, sys, time
import wx, wx.glcanvas import wx, wx.glcanvas
import yaml
from ENNToolMiRCARTColours import ENNToolMiRCARTColoursFloat from ENNToolMiRCARTColours import ENNToolMiRCARTColoursFloat
@ -53,11 +49,7 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel):
void main() { void main() {
vec4 texel = texture2D(texture, fgTexCoord); vec4 texel = texture2D(texture, fgTexCoord);
if (texel.a > 0.0) {
gl_FragColor = vec4(texel.r, texel.g, texel.b, 1.0); gl_FragColor = vec4(texel.r, texel.g, texel.b, 1.0);
} else {
gl_FragColor = bgColour;
}
} }
""", GL_FRAGMENT_SHADER) """, GL_FRAGMENT_SHADER)
vs = shaders.compileShader(""" vs = shaders.compileShader("""
@ -82,37 +74,12 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel):
""", GL_VERTEX_SHADER) """, GL_VERTEX_SHADER)
self.shader = shaders.compileProgram(vs, fs) self.shader = shaders.compileProgram(vs, fs)
# }}} # }}}
# {{{ initTexture(self, pathName, infoPathName=os.path.join("assets", "textures.yaml")): XXX
def initTexture(self, pathName, infoPathName=os.path.join("assets", "textures.yaml")):
with open(infoPathName, "r") as fileObject:
artInfo = yaml.load(fileObject)
# [6], [7]
artTextureId = glGenTextures(1)
artTextureImage = Image.open(pathName).transpose(Image.FLIP_TOP_BOTTOM)
artTextureImageData = numpy.array(artTextureImage)
glBindTexture(GL_TEXTURE_2D, artTextureId)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
# [2]
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
# [4][5]
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
artTextureImage.size[0], artTextureImage.size[1],
0, GL_RGBA, GL_UNSIGNED_BYTE, artTextureImageData)
glBindTexture(GL_TEXTURE_2D, artTextureId)
return artTextureId, artInfo
# }}}
# {{{ initVideoWriter(self): XXX # {{{ initVideoWriter(self): XXX
def initVideoWriter(self, fourcc="XVID", fps=25): def initVideoWriter(self, fourcc="XVID", fps=25):
fourcc = cv2.VideoWriter_fourcc(*list(fourcc)) fourcc = cv2.VideoWriter_fourcc(*list(fourcc))
self.videoWriter = cv2.VideoWriter(self.videoPath, fourcc, fps, (self.width, self.height), True) self.videoWriter = cv2.VideoWriter(self.videoPath, fourcc, fps, (self.width, self.height), True)
# }}} # }}}
# {{{ renderFrame(self, artTextureId, artVbo, artVboLen): XXX # {{{ renderFrame(self, artTextureId, artVbo, artVboLen): XXX
def renderFrame(self, artTextureId, artVbo, artVboLen): def renderFrame(self, artTextureId, artVbo, artVboLen):
glEnableClientState(GL_VERTEX_ARRAY) glEnableClientState(GL_VERTEX_ARRAY)
@ -136,7 +103,7 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel):
glUniformMatrix4fv(glGetUniformLocation(self.shader, "projection"), 1, GL_FALSE, projection) glUniformMatrix4fv(glGetUniformLocation(self.shader, "projection"), 1, GL_FALSE, projection)
glUniform1i(glGetUniformLocation(self.shader, "texture"), 0) glUniform1i(glGetUniformLocation(self.shader, "texture"), 0)
# [8] # [6]
glEnableVertexAttribArray(0) glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 3, GL_FLOAT, False, 48, ctypes.c_void_p(0)) glVertexAttribPointer(0, 3, GL_FLOAT, False, 48, ctypes.c_void_p(0))
glEnableVertexAttribArray(1) glEnableVertexAttribArray(1)
@ -168,43 +135,39 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel):
if centre and (len(artMap[numRow]) < canvasCols): if centre and (len(artMap[numRow]) < canvasCols):
curPos[0] += (((canvasCols - len(artMap[numRow])) * cubeSize[0]) / 2) curPos[0] += (((canvasCols - len(artMap[numRow])) * cubeSize[0]) / 2)
for numCol in range(len(artMap[numRow])): for numCol in range(len(artMap[numRow])):
cubeColour = [*ENNToolMiRCARTColoursFloat[artMap[numRow][numCol][1]], 1.0] cubeFg = artMap[numRow][numCol][0]
if artMap[numRow][numCol][0] != artMap[numRow][numCol][1]: cubeBg = artMap[numRow][numCol][1]
colColour = artMap[numRow][numCol][0] cubeBgFloat = [*ENNToolMiRCARTColoursFloat[cubeBg], 1.0]
cubeAttrs = artMap[numRow][numCol][2]
cubeChar = artMap[numRow][numCol][3] cubeChar = artMap[numRow][numCol][3]
if ord(cubeChar) >= 128: artCell = artInfo[cubeFg][cubeBg][cubeAttrs][cubeChar]
print("dont have {}".format(cubeChar))
cubeChar = " "
else:
colColour = artMap[numRow][numCol][1]
cubeChar = " "
# Top Right # Top Right
vertices += curPos vertices += curPos
vertices += [0.0, 0.0, 1.0] vertices += [0.0, 0.0, 1.0]
vertices += cubeColour vertices += cubeBgFloat
vertices += [float(((ord(cubeChar) + 1) * artInfo["rowWidth"]) / artInfo["texWidth"]), ((colColour + 1) * artInfo["rowHeight"]) / float(artInfo["texHeight"])] vertices += artCell[0:2]
numVertices += 1 numVertices += 1
# Top Left # Top Left
vertices += [curPos[0]-cubeSize[0], curPos[1], curPos[2]] vertices += [curPos[0]-cubeSize[0], curPos[1], curPos[2]]
vertices += [0.0, 0.0, 1.0] vertices += [0.0, 0.0, 1.0]
vertices += cubeColour vertices += cubeBgFloat
vertices += [float(((ord(cubeChar) + 0) * artInfo["rowWidth"]) / artInfo["texWidth"]), ((colColour + 1) * artInfo["rowHeight"]) / float(artInfo["texHeight"])] vertices += artCell[2:4]
numVertices += 1 numVertices += 1
# Bottom Left # Bottom Left
vertices += [curPos[0]-cubeSize[0], curPos[1]-cubeSize[1], curPos[2]] vertices += [curPos[0]-cubeSize[0], curPos[1]-cubeSize[1], curPos[2]]
vertices += [0.0, 0.0, 1.0] vertices += [0.0, 0.0, 1.0]
vertices += cubeColour vertices += cubeBgFloat
vertices += [float(((ord(cubeChar) + 0) * artInfo["rowWidth"]) / artInfo["texWidth"]), ((colColour) * artInfo["rowHeight"]) / float(artInfo["texHeight"])] vertices += artCell[4:6]
numVertices += 1 numVertices += 1
# Bottom Right # Bottom Right
vertices += [curPos[0], curPos[1]-cubeSize[1], curPos[2]] vertices += [curPos[0], curPos[1]-cubeSize[1], curPos[2]]
vertices += [0.0, 0.0, 1.0] vertices += [0.0, 0.0, 1.0]
vertices += cubeColour vertices += cubeBgFloat
vertices += [float(((ord(cubeChar) + 1) * artInfo["rowWidth"]) / artInfo["texWidth"]), ((colColour) * artInfo["rowHeight"]) / float(artInfo["texHeight"])] vertices += artCell[6:8]
numVertices += 1 numVertices += 1
curPos[0] += cubeSize[0] curPos[0] += cubeSize[0]
@ -226,6 +189,7 @@ class ENNToolGLCanvasPanel(wx.glcanvas.GLCanvas, wx.Panel):
screenshot = numpy.flipud(numpy.frombuffer(screenshot, numpy.uint8).reshape((self.height, self.width, 3))) screenshot = numpy.flipud(numpy.frombuffer(screenshot, numpy.uint8).reshape((self.height, self.width, 3)))
self.videoWriter.write(screenshot) self.videoWriter.write(screenshot)
# }}} # }}}
# {{{ __init__(self, parent, size, defaultPos=(24,24), videoPath=None): initialisation method # {{{ __init__(self, parent, size, defaultPos=(24,24), videoPath=None): initialisation method
def __init__(self, parent, size, defaultPos=(24,24), videoPath=None): def __init__(self, parent, size, defaultPos=(24,24), videoPath=None):
super().__init__(parent, pos=defaultPos, size=size) super().__init__(parent, pos=defaultPos, size=size)

142
ENNToolGLTTFTexture.py Normal file
View File

@ -0,0 +1,142 @@
#!/usr/bin/env python3
#
# ENNTool -- mIRC art animation tool (for EFnet #MiRCART) (WIP)
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
# This project is licensed under the terms of the MIT license.
#
# References:
# Thu, 28 Jun 2018 17:03:16 +0200 [1] <https://stackoverflow.com/questions/384759/how-to-convert-a-pil-image-into-a-numpy-array>
# Thu, 28 Jun 2018 17:04:59 +0200 [2] <https://www.khronos.org/opengl/wiki/Common_Mistakes#y-axis>
# Wed, 27 Jun 2018 16:02:12 +0200 [3] <https://www.khronos.org/opengl/wiki/How_lighting_works#Good_Settings.>
# Wed, 27 Jun 2018 16:02:13 +0200 [4] <https://www.khronos.org/opengl/wiki/Common_Mistakes>
# Wed, 27 Jun 2018 16:02:14 +0200 [5] <https://www.khronos.org/opengl/wiki/Pixel_Transfer#Pixel_layout>
#
from collections import defaultdict
from OpenGL.GL import *
from PIL import Image, ImageDraw, ImageFont
import numpy
import os, string, sys
from ENNToolMiRCARTColours import ENNToolMiRCARTColours
from ENNToolMiRCARTImporter import ENNToolMiRCARTImporter
class ENNToolGLTTFTexture(object):
"""XXX"""
# {{{ _defaultDict(*args): XXX
@staticmethod
def _defaultDict(*args):
return defaultdict(*args)
# }}}
# {{{ _nestedDict(): XXX
@staticmethod
def _nestedDict():
return defaultdict(ENNToolGLTTFTexture._nestedDict)
# }}}
# {{{ _drawCharList(self, artInfo, charList, pilFontBold, pilFontNormal, pilFontSize, pilImageDraw, pilImageSize): XXX
def _drawCharList(self, artInfo, charList, pilFontBold, pilFontNormal, pilFontSize, pilImageDraw, pilImageSize):
curPos = [0, 0]
for newChar in charList:
pilFont, underLine = pilFontNormal, False
if newChar[2] & ENNToolMiRCARTImporter._CellState.CS_BOLD:
pilFont = pilFontBold
if newChar[2] & ENNToolMiRCARTImporter._CellState.CS_UNDERLINE:
underLine = True
pilImageDraw.rectangle((*curPos, curPos[0] + pilFontSize[0], curPos[1] + pilFontSize[1] - 1),
fill=(*ENNToolMiRCARTColours[newChar[1]], 255))
pilImageDraw.text(curPos, newChar[3], (*ENNToolMiRCARTColours[newChar[0]], 255), pilFont)
if underLine:
pilImageDraw.line(
xy=(curPos[0], curPos[1] + (pilFontSize[1] - 2),
curPos[0] + pilFontSize[0], curPos[1] + pilFontSize[1]),
fill=(*ENNToolMiRCARTColours[newChar[0]], 255))
artInfo[newChar[0]][newChar[1]][newChar[2]][newChar[3]] = []
# Top Right
artInfo[newChar[0]][newChar[1]][newChar[2]][newChar[3]] += [float(curPos[0] + pilFontSize[0]) / pilImageSize[0], 0.0]
# Top Left
artInfo[newChar[0]][newChar[1]][newChar[2]][newChar[3]] += [float(curPos[0]) / pilImageSize[0], 0.0]
# Bottom Left
artInfo[newChar[0]][newChar[1]][newChar[2]][newChar[3]] += [float(curPos[0]) / pilImageSize[0], float(pilFontSize[1]) / pilImageSize[1]]
# Bottom Right
artInfo[newChar[0]][newChar[1]][newChar[2]][newChar[3]] += [float(curPos[0] + pilFontSize[0]) / pilImageSize[0], float(pilFontSize[1]) / pilImageSize[1]]
curPos[0] += pilFontSize[0]
return artInfo
# }}}
# {{{ _initArtInfoCharList(self): XXX
def _initArtInfoCharList(self, artMap):
artInfo, charList = ENNToolGLTTFTexture._nestedDict(), []
for numRow in range(len(artMap)):
for numCol in range(len(artMap[numRow])):
artFg = artMap[numRow][numCol][0]
artBg = artMap[numRow][numCol][1]
artAttrs = artMap[numRow][numCol][2]
artChar = artMap[numRow][numCol][3]
if artInfo[artFg][artBg][artAttrs][artChar] == {}:
artInfo[artFg][artBg][artAttrs][artChar] = None
charList += [[artFg, artBg, artAttrs, artChar]]
return artInfo, charList
# }}}
# {{{ _initFonts(self): XXX
def _initFonts(self):
fontBoldPathName = os.path.join("assets", "DejaVuSansMono-Bold.ttf")
fontNormalPathName = os.path.join("assets", "DejaVuSansMono.ttf")
fontSize = int("26")
pilFontBold = ImageFont.truetype(fontBoldPathName, fontSize)
pilFontNormal = ImageFont.truetype(fontNormalPathName, fontSize)
pilFontSize = list(pilFontNormal.getsize("_")) # XXX
return pilFontBold, pilFontNormal, pilFontSize
# }}}
# {{{ _initImage(self, charList, pilFontSize): XXX
def _initImage(self, charList, pilFontSize):
pilImageSize = (pilFontSize[0] * len(charList), pilFontSize[1])
pilImage = Image.new("RGBA", pilImageSize, (0, 0, 0, 0))
pilImageDraw = ImageDraw.Draw(pilImage)
return pilImage, pilImageDraw, pilImageSize
# }}}
# {{{ _initTexture(self, pilImage): XXX
def _initTexture(self, pilImage):
# [1], [2]
artTextureId = glGenTextures(1)
artTextureImage = pilImage
artTextureImageData = numpy.array(artTextureImage)
glBindTexture(GL_TEXTURE_2D, artTextureId)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP)
# [3]
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
# [4][5]
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
artTextureImage.size[0], artTextureImage.size[1],
0, GL_RGBA, GL_UNSIGNED_BYTE, artTextureImageData)
glGenerateMipmap(GL_TEXTURE_2D)
return artTextureId
# }}}
# {{{ getParams(self): XXX
def getParams(self):
return self.artTextureId, self.artInfo
# }}}
# {{{ __init__(self): initialisation method
def __init__(self, artMap, cubeSize, videoSize):
artInfo, charList = self._initArtInfoCharList(artMap)
pilFontBold, pilFontNormal, pilFontSize = self._initFonts()
pilImage, pilImageDraw, pilImageSize = self._initImage(charList, pilFontSize)
artInfo = self._drawCharList(artInfo, charList,
pilFontBold, pilFontNormal, pilFontSize,
pilImageDraw, pilImageSize)
artTextureId = self._initTexture(pilImage)
self.artTextureId = artTextureId
self.artInfo = artInfo
# }}}
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -1,78 +0,0 @@
#!/usr/bin/env python3
#
# ENNTool -- mIRC art animation tool (for EFnet #MiRCART) (WIP)
# Copyright (c) 2018 Lucio Andrés Illanes Albornoz <lucio@lucioillanes.de>
# This project is licensed under the terms of the MIT license.
#
from PIL import Image, ImageDraw, ImageFont
import os, string, yaml, sys
from ENNToolMiRCARTColours import ENNToolMiRCARTColours
from ENNToolMiRCARTImporter import ENNToolMiRCARTImporter
#
# Entry point
def main(*argv):
fontNormalPathName = os.path.join("assets", "DejaVuSansMono.ttf")
fontBoldPathName = os.path.join("assets", "DejaVuSansMono-Bold.ttf")
fontSize = int("26")
outInfoFileName = os.path.join("assets", "textures.yaml")
outFileName = os.path.join("assets", "DejaVuSansMono.png")
if not os.path.exists(os.path.dirname(outInfoFileName)):
os.makedirs(os.path.dirname(outInfoFileName))
if not os.path.exists(os.path.dirname(outFileName)):
os.makedirs(os.path.dirname(outFileName))
pilFontNormal = ImageFont.truetype(fontNormalPathName, fontSize)
pilFontBold = ImageFont.truetype(fontBoldPathName, fontSize)
pilFontSize = list(pilFontNormal.getsize(" "))
pilFontSize[0] += (8 - (pilFontSize[0] % 8))
pilFontSize[1] = pilFontSize[0] * 2
pilImageSize = (pilFontSize[0] * 128, (pilFontSize[1] * 16 * 4))
print("font size: {}, image size: {}".format(pilFontSize, pilImageSize))
curPos = [0, 0]
pilImage = Image.new("RGBA", pilImageSize, (0, 0, 0, 0))
pilImageDraw = ImageDraw.Draw(pilImage)
pilImageTmp = Image.new("RGBA", pilFontSize, (0, 0, 0, 0))
pilImageTmpDraw = ImageDraw.Draw(pilImageTmp)
for fontAttr in [ENNToolMiRCARTImporter._CellState.CS_BOLD | ENNToolMiRCARTImporter._CellState.CS_UNDERLINE,
ENNToolMiRCARTImporter._CellState.CS_UNDERLINE,
ENNToolMiRCARTImporter._CellState.CS_BOLD,
ENNToolMiRCARTImporter._CellState.CS_NONE]:
for fontColour in reversed(range(16)):
for fontChar in [chr(n) for n in range(128)]:
pilFont, underLine = pilFontNormal, False
if fontAttr & ENNToolMiRCARTImporter._CellState.CS_BOLD:
pilFont = pilFontBold
if fontAttr & ENNToolMiRCARTImporter._CellState.CS_UNDERLINE:
underLine = True
if fontChar in string.printable:
pilImageTmpDraw.text((0, 0), fontChar,
(*ENNToolMiRCARTColours[fontColour], 255), pilFont)
pilImage.paste(pilImageTmp, tuple(curPos))
pilImageTmpDraw.rectangle((0, 0, pilFontSize[0], pilFontSize[1]),
fill=(0, 0, 0, 0))
if underLine:
pilImageDraw.line(
xy=(curPos[0], curPos[1] + (pilFontSize[1] - 2),
curPos[0] + pilFontSize[0], curPos[1] + (pilFontSize[1] - 2)),
fill=(*ENNToolMiRCARTColours[fontColour], 255))
curPos[0] += pilFontSize[0]
curPos[0], curPos[1] = 0, curPos[1] + pilFontSize[1]
pilImage.save(outFileName)
artInfo = {}
artInfo["rowHeight"] = pilFontSize[1]
artInfo["rowWidth"] = pilFontSize[0]
artInfo["texHeight"] = pilImageSize[1]
artInfo["texWidth"] = pilImageSize[0]
with open(outInfoFileName, "w") as fileObject:
yaml.dump(artInfo, fileObject)
if __name__ == "__main__":
main(*sys.argv)
# vim:expandtab foldmethod=marker sw=4 ts=4 tw=120

View File

@ -2,4 +2,4 @@
Copyright (c) 2018 Lucio Andrés Illanes Albornoz <<lucio@lucioillanes.de>> Copyright (c) 2018 Lucio Andrés Illanes Albornoz <<lucio@lucioillanes.de>>
This project is licensed under the terms of the MIT licence. This project is licensed under the terms of the MIT licence.
* Prerequisites on Windows: install Python v3.5.x and script dependencies w/ the following elevated command prompt command line: * Prerequisites on Windows: install Python v3.5.x and script dependencies w/ the following elevated command prompt command line:
`pip install chardet numpy opencv-python Pillow PyOpenGL PyYAML wxPython` `pip install chardet numpy opencv-python Pillow PyOpenGL wxPython`

View File

@ -1 +0,0 @@
DejaVuSansMono.png

View File

@ -1 +0,0 @@
{rowHeight: 48, rowWidth: 24, texHeight: 3072, texWidth: 3072}