Compare commits
2 Commits
f5ddbf4a69
...
9a032b1ebd
Author | SHA1 | Date | |
---|---|---|---|
9a032b1ebd | |||
946f4a3b5c |
29
main.py
29
main.py
@ -1,6 +1,29 @@
|
|||||||
|
import argparse
|
||||||
|
|
||||||
from schema import InstructionSetSchema
|
from schema import InstructionSetSchema
|
||||||
|
|
||||||
|
description = """Examples:
|
||||||
|
- Default theme (black on white):
|
||||||
|
python main.py schema.xml -o out.jpg
|
||||||
|
|
||||||
|
- Dark theme (white on black):
|
||||||
|
python main.py schema.xml -o out.jpg -c dark.json
|
||||||
|
|
||||||
|
- Blueprint theme (white on blue):
|
||||||
|
python main.py schema.xml -o out.jpg -c blueprint.json
|
||||||
|
|
||||||
|
- Transparent background:
|
||||||
|
python main.py schema.xml -o out.png -c transparent.json
|
||||||
|
"""
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
schema = InstructionSetSchema("example1.yaml")
|
parser = argparse.ArgumentParser(description=description, formatter_class=argparse.RawTextHelpFormatter)
|
||||||
schema.save("example1_v2.jpg")
|
parser.add_argument("schema", help="Path to the schema description. Accepted formats are: YAML, JSON and XML")
|
||||||
input()
|
parser.add_argument("-o", "--output", help="Output path", default="out.jpg")
|
||||||
|
parser.add_argument("-c", "--config", help="Path to the config file", default="config.json")
|
||||||
|
parser.add_argument("-D", "--display", help="Enable pygame display of the result", action="store_true")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
schema = InstructionSetSchema(args.schema, args.config, args.display)
|
||||||
|
schema.save(args.output)
|
45
renderer.py
45
renderer.py
@ -1,4 +1,5 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
import os
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from config import Config
|
from config import Config
|
||||||
@ -14,25 +15,33 @@ class Renderer:
|
|||||||
WIDTH = 1200
|
WIDTH = 1200
|
||||||
HEIGHT = 800
|
HEIGHT = 800
|
||||||
|
|
||||||
def __init__(self, config: Config) -> None:
|
def __init__(self, config: Config, display: bool = False) -> None:
|
||||||
self.config = config
|
self.config = config
|
||||||
|
self.display = display
|
||||||
pygame.init()
|
pygame.init()
|
||||||
self.win = pygame.display.set_mode([Renderer.WIDTH, Renderer.HEIGHT])
|
if self.display:
|
||||||
|
self.win = pygame.display.set_mode([Renderer.WIDTH, Renderer.HEIGHT])
|
||||||
|
|
||||||
|
self.surf = pygame.Surface([Renderer.WIDTH, Renderer.HEIGHT], pygame.SRCALPHA)
|
||||||
self.font = pygame.font.SysFont(self.config.DEFAULT_FONT_FAMILY, self.config.DEFAULT_FONT_SIZE)
|
self.font = pygame.font.SysFont(self.config.DEFAULT_FONT_FAMILY, self.config.DEFAULT_FONT_SIZE)
|
||||||
self.italicFont = pygame.font.SysFont(self.config.ITALIC_FONT_FAMILY, self.config.ITALIC_FONT_SIZE, italic=True)
|
self.italicFont = pygame.font.SysFont(self.config.ITALIC_FONT_FAMILY, self.config.ITALIC_FONT_SIZE, italic=True)
|
||||||
|
|
||||||
self.margins = self.config.MARGINS
|
self.margins = self.config.MARGINS
|
||||||
|
|
||||||
def render(self, schema: InstructionSetSchema) -> None:
|
def render(self, schema: InstructionSetSchema) -> None:
|
||||||
|
self.surf.fill(self.config.BACKGROUND_COLOR)
|
||||||
self.win.fill(self.config.BACKGROUND_COLOR)
|
|
||||||
|
|
||||||
self.drawStructure(schema.structures["main"], schema.structures, self.margins[3], self.margins[0])
|
self.drawStructure(schema.structures["main"], schema.structures, self.margins[3], self.margins[0])
|
||||||
|
|
||||||
pygame.display.flip()
|
if self.display:
|
||||||
|
name = os.path.basename(schema.path)
|
||||||
|
pygame.display.set_caption(f"Rivet - {name}")
|
||||||
|
self.win.fill(self.config.BACKGROUND_COLOR)
|
||||||
|
self.win.blit(self.surf, [0, 0])
|
||||||
|
pygame.display.flip()
|
||||||
|
|
||||||
def save(self, path: str) -> None:
|
def save(self, path: str) -> None:
|
||||||
pygame.image.save(self.win, path)
|
pygame.image.save(self.surf, path)
|
||||||
|
|
||||||
def drawStructure(self,
|
def drawStructure(self,
|
||||||
struct: Structure,
|
struct: Structure,
|
||||||
@ -52,20 +61,20 @@ class Renderer:
|
|||||||
startBit = struct.start
|
startBit = struct.start
|
||||||
|
|
||||||
# Draw rectangle around structure
|
# Draw rectangle around structure
|
||||||
pygame.draw.rect(self.win, borderCol, [bitsX, bitsY, bitsWidth, bitH], 2)
|
pygame.draw.rect(self.surf, borderCol, [bitsX, bitsY, bitsWidth, bitH], 2)
|
||||||
|
|
||||||
for i in range(struct.bits):
|
for i in range(struct.bits):
|
||||||
bitX = ox + i * bitW
|
bitX = ox + i * bitW
|
||||||
|
|
||||||
bitITxt = self.font.render(str(struct.bits - i - 1 + startBit), True, txtCol)
|
bitITxt = self.font.render(str(struct.bits - i - 1 + startBit), True, txtCol)
|
||||||
self.win.blit(bitITxt, [
|
self.surf.blit(bitITxt, [
|
||||||
bitX + (bitW - bitITxt.get_width())/2,
|
bitX + (bitW - bitITxt.get_width())/2,
|
||||||
oy + (bitH - bitITxt.get_height())/2
|
oy + (bitH - bitITxt.get_height())/2
|
||||||
])
|
])
|
||||||
|
|
||||||
# Draw separator
|
# Draw separator
|
||||||
if i != 0:
|
if i != 0:
|
||||||
pygame.draw.line(self.win, borderCol, [bitX, bitsY], [bitX, bitsY + bitH])
|
pygame.draw.line(self.surf, borderCol, [bitX, bitsY], [bitX, bitsY + bitH])
|
||||||
|
|
||||||
ranges = struct.getSortedRanges()
|
ranges = struct.getSortedRanges()
|
||||||
descX = ox + max(0, (struct.bits-12) * bitW)
|
descX = ox + max(0, (struct.bits-12) * bitW)
|
||||||
@ -81,8 +90,8 @@ class Renderer:
|
|||||||
nameTxt = self.font.render(range_.name, True, txtCol)
|
nameTxt = self.font.render(range_.name, True, txtCol)
|
||||||
nameX = rStartX + (rWidth - nameTxt.get_width())/2
|
nameX = rStartX + (rWidth - nameTxt.get_width())/2
|
||||||
nameY = bitsY + (bitH - nameTxt.get_height())/2
|
nameY = bitsY + (bitH - nameTxt.get_height())/2
|
||||||
pygame.draw.rect(self.win, bgCol, [rStartX + bitW/2, nameY, rWidth - bitW, nameTxt.get_height()], 0)
|
pygame.draw.rect(self.surf, bgCol, [rStartX + bitW/2, nameY, rWidth - bitW, nameTxt.get_height()], 0)
|
||||||
self.win.blit(nameTxt, [nameX, nameY])
|
self.surf.blit(nameTxt, [nameX, nameY])
|
||||||
|
|
||||||
if range_.description:
|
if range_.description:
|
||||||
descX, descY = self.drawDescription(range_, rStartX, bitsY, rWidth, descX, descY)
|
descX, descY = self.drawDescription(range_, rStartX, bitsY, rWidth, descX, descY)
|
||||||
@ -103,7 +112,7 @@ class Renderer:
|
|||||||
y0 = bitsY + bitH * 1.25
|
y0 = bitsY + bitH * 1.25
|
||||||
y1 = bitsY + bitH * 1.5
|
y1 = bitsY + bitH * 1.5
|
||||||
|
|
||||||
pygame.draw.lines(self.win, self.config.LINK_COLOR, False, [
|
pygame.draw.lines(self.surf, self.config.LINK_COLOR, False, [
|
||||||
[x0, y0],
|
[x0, y0],
|
||||||
[x0, y1],
|
[x0, y1],
|
||||||
[x1, y1],
|
[x1, y1],
|
||||||
@ -114,7 +123,7 @@ class Renderer:
|
|||||||
bitH = self.config.BIT_HEIGHT
|
bitH = self.config.BIT_HEIGHT
|
||||||
arrowMargin = self.config.ARROW_MARGIN
|
arrowMargin = self.config.ARROW_MARGIN
|
||||||
|
|
||||||
pygame.draw.lines(self.win, self.config.LINK_COLOR, False, [
|
pygame.draw.lines(self.surf, self.config.LINK_COLOR, False, [
|
||||||
[startX, startY + bitH*1.5],
|
[startX, startY + bitH*1.5],
|
||||||
[startX, endY + bitH/2],
|
[startX, endY + bitH/2],
|
||||||
[endX - arrowMargin, endY + bitH/2]
|
[endX - arrowMargin, endY + bitH/2]
|
||||||
@ -139,7 +148,7 @@ class Renderer:
|
|||||||
self.drawLink(midX, rStartY, descX, descY)
|
self.drawLink(midX, rStartY, descX, descY)
|
||||||
|
|
||||||
descTxt = self.font.render(range_.description, True, self.config.TEXT_COLOR)
|
descTxt = self.font.render(range_.description, True, self.config.TEXT_COLOR)
|
||||||
self.win.blit(descTxt, [descX, descY + (bitH - descTxt.get_height())/2])
|
self.surf.blit(descTxt, [descX, descY + (bitH - descTxt.get_height())/2])
|
||||||
|
|
||||||
descY += descTxt.get_height()
|
descY += descTxt.get_height()
|
||||||
|
|
||||||
@ -158,7 +167,7 @@ class Renderer:
|
|||||||
for val, desc in sorted(values.items(), key=lambda vd: vd[0]):
|
for val, desc in sorted(values.items(), key=lambda vd: vd[0]):
|
||||||
descY += gap
|
descY += gap
|
||||||
valTxt = self.italicFont.render(f"{val} = {desc}", True, textCol)
|
valTxt = self.italicFont.render(f"{val} = {desc}", True, textCol)
|
||||||
self.win.blit(valTxt, [descX + bitW/2, descY])
|
self.surf.blit(valTxt, [descX + bitW/2, descY])
|
||||||
descY += valTxt.get_height()
|
descY += valTxt.get_height()
|
||||||
|
|
||||||
return (descX, descY)
|
return (descX, descY)
|
||||||
@ -243,21 +252,21 @@ class Renderer:
|
|||||||
for i in range(dashes):
|
for i in range(dashes):
|
||||||
a = start + d * i * (dashLen + dashSpace)
|
a = start + d * i * (dashLen + dashSpace)
|
||||||
b = a + d*dashLen
|
b = a + d*dashLen
|
||||||
pygame.draw.line(self.win, linkCol, [a.x, a.y], [b.x, b.y])
|
pygame.draw.line(self.surf, linkCol, [a.x, a.y], [b.x, b.y])
|
||||||
|
|
||||||
n = Vec(d.y, -d.x)
|
n = Vec(d.y, -d.x)
|
||||||
|
|
||||||
width = arrowSize / 1.5
|
width = arrowSize / 1.5
|
||||||
p1 = end - d * arrowSize + n * width
|
p1 = end - d * arrowSize + n * width
|
||||||
p2 = end - d * arrowSize - n * width
|
p2 = end - d * arrowSize - n * width
|
||||||
pygame.draw.polygon(self.win, linkCol, [
|
pygame.draw.polygon(self.surf, linkCol, [
|
||||||
[end.x, end.y],
|
[end.x, end.y],
|
||||||
[p1.x, p1.y],
|
[p1.x, p1.y],
|
||||||
[p2.x, p2.y]], 0)
|
[p2.x, p2.y]], 0)
|
||||||
|
|
||||||
if label:
|
if label:
|
||||||
txt = self.italicFont.render(label, True, textCol)
|
txt = self.italicFont.render(label, True, textCol)
|
||||||
self.win.blit(txt, [
|
self.surf.blit(txt, [
|
||||||
(start.x + end.x - txt.get_width())/2,
|
(start.x + end.x - txt.get_width())/2,
|
||||||
(start.y + end.y)/2 + arrowLabelDist
|
(start.y + end.y)/2 + arrowLabelDist
|
||||||
])
|
])
|
@ -13,8 +13,9 @@ class UnsupportedFormatException(Exception):
|
|||||||
class InstructionSetSchema:
|
class InstructionSetSchema:
|
||||||
VALID_EXTENSIONS = ("yaml", "json", "xml")
|
VALID_EXTENSIONS = ("yaml", "json", "xml")
|
||||||
|
|
||||||
def __init__(self, path: str, configPath: str = "config.json") -> None:
|
def __init__(self, path: str, configPath: str = "config.json", display: bool = False) -> None:
|
||||||
self.config = Config(configPath)
|
self.config = Config(configPath)
|
||||||
|
self.display = display
|
||||||
self.path = path
|
self.path = path
|
||||||
self.load()
|
self.load()
|
||||||
|
|
||||||
@ -43,6 +44,8 @@ class InstructionSetSchema:
|
|||||||
self.structures[id_] = Structure.load(id_, data)
|
self.structures[id_] = Structure.load(id_, data)
|
||||||
|
|
||||||
def save(self, path: str) -> None:
|
def save(self, path: str) -> None:
|
||||||
renderer = Renderer(self.config)
|
renderer = Renderer(self.config, self.display)
|
||||||
renderer.render(self)
|
renderer.render(self)
|
||||||
renderer.save(path)
|
renderer.save(path)
|
||||||
|
if self.display:
|
||||||
|
input("Press ENTER to quit")
|
7
transparent.json
Normal file
7
transparent.json
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"backgroundColor": [0, 0, 0, 0],
|
||||||
|
"textColor": [128, 128, 128],
|
||||||
|
"linkColor": [128, 128, 128],
|
||||||
|
"bitIColor": [128, 128, 128],
|
||||||
|
"borderColor": [128, 128, 128]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user