Skip to content

Commit

Permalink
added TextLabel type, used to replace text drawing code elsewhere
Browse files Browse the repository at this point in the history
  • Loading branch information
cracked-machine committed Feb 9, 2024
1 parent 0ce59a2 commit 9ea12db
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 46 deletions.
10 changes: 5 additions & 5 deletions doc/example/report.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
![memory map diagram](report.png)
|name|origin|size|remaining|collisions
|:-|:-|:-|:-|:-|
|<span style='color:cornflowerblue'>kernel</span>|0x10|0x50|-0x10|{'rootfs': '0x50'}|
|<span style='color:limegreen'>uboot</span>|0xD0|0x50|-0x10|{'uboot-scr': '0x110'}|
|<span style='color:lightskyblue'>rootfs</span>|0x50|0x30|0x10|{'kernel': '0x50'}|
|<span style='color:mediumspringgreen'>dtb</span>|0x90|0x30|0x10|{}|
|<span style='color:lawngreen'>uboot-scr</span>|0x110|0x30|0x50|{'uboot': '0x110'}|
|<span style='color:gray'>kernel</span>|0x10|0x50|-0x10|{'rootfs': '0x50'}|
|<span style='color:dimgray'>uboot</span>|0xD0|0x50|-0x10|{'uboot-scr': '0x110'}|
|<span style='color:slategrey'>rootfs</span>|0x50|0x30|0x10|{'kernel': '0x50'}|
|<span style='color:lawngreen'>dtb</span>|0x90|0x30|0x10|{}|
|<span style='color:sienna'>uboot-scr</span>|0x110|0x30|0x50|{'uboot': '0x110'}|
Binary file modified doc/example/report.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
37 changes: 15 additions & 22 deletions mm/diagram.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,33 +67,26 @@ def _create_diagram(self, region_list: List[mm.types.MemoryRegion]):
region.create_img(img_width=MemoryMap.width - self._legend_width)
if not region.img:
continue
img_main.paste(region.img, (self._legend_width + region.draw_indent, region.origin), region.img)

# Origin Address Text
origin_text_label = mm.types.TextLabel(region._origin, 8)
img_main.paste(origin_text_label.img, (0, region.origin - origin_text_label.height + 1))

# Address Text
addr_text_font = PIL.ImageFont.load_default(8)
# add text for the region origin
origin_text_img = PIL.Image.new("RGB", (30, 10), color=(255, 255, 255))
origin_text_canvas = PIL.ImageDraw.Draw(origin_text_img)
origin_text_canvas.text((0, 0), region._origin, fill="black", font=addr_text_font)
origin_text_img = origin_text_img.rotate(180)
# add text for the region end
endaddr = region.origin + region.size
endaddr_text_img = PIL.Image.new("RGB", (30, 10), color=(255, 255, 255))
endaddr_text_canvas = PIL.ImageDraw.Draw(endaddr_text_img)
endaddr_text_canvas.text((0, 0), hex(endaddr), fill="black", font=addr_text_font)
endaddr_text_img = endaddr_text_img.rotate(180)
# Region End Address Text
end_addr_val = region.origin + region.size
end_addr_text_label = mm.types.TextLabel(hex(end_addr_val).upper(), 8)
img_main.paste(end_addr_text_label.img, (0, end_addr_val - end_addr_text_label.height + 1))

line_width = 1
line_canvas = PIL.ImageDraw.Draw(img_main)
for x in range(40, 90, 4):
line_canvas.line((x, endaddr - line_width, x+2, endaddr - line_width), fill="black", width=line_width)
line_canvas.line((x, region.origin - line_width, x+2, region.origin - line_width), fill="black", width=1)

# paste all the layers onto the main image
img_main.paste(region.img, (self._legend_width + region.draw_indent, region.origin), region.img)
img_main.paste(endaddr_text_img, (0, endaddr - 6))
img_main.paste(origin_text_img, (0, region.origin - 4))
dash_gap = 4
dash_len = dash_gap / 2
for x in range(40, 90, dash_gap):
line_canvas.line((x, end_addr_val - line_width, x + dash_len, end_addr_val - line_width), fill="black", width=line_width)
line_canvas.line((x, region.origin - line_width, x + dash_len, region.origin - line_width), fill="black", width=1)

# rotate so the origin is at the bottom
# rotate the entire diagram so the origin is at the bottom
img_main = img_main.rotate(180)

# output image file
Expand Down
64 changes: 45 additions & 19 deletions mm/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import PIL.Image
import PIL.ImageDraw
import PIL.ImageColor
import PIL.ImageFont
from typing import List, Dict
import logging

Expand Down Expand Up @@ -31,10 +32,7 @@ def __init__(self, name: str, origin: str, size: str):
"""Map of collision regions by name (str) and distance (hex)"""
self.draw_indent = 0
"""Index counter for incrementally shrinking the drawing indent"""
self.txtlbl_bgcolour = "oldlace"
"""The background colour to use for the region text label"""
self.txtlbl_fgcolour = "black"
"""The foreground colour to use for the region text label"""

self.img: PIL.Image

# both 'lightslategray' and 'lightslategrey' are the same colour
Expand Down Expand Up @@ -141,7 +139,7 @@ def calc_nearest_region(self, region_list: List['MemoryRegion']):

@typeguard.typechecked
class MemoryRegion(Region):

def create_img(self, img_width: int):

logging.info(self)
Expand All @@ -162,25 +160,53 @@ def create_img(self, img_width: int):
)

# draw name text
ntext_img_width = 60
ntext_img_height = 7
ntext_font = PIL.ImageFont.load_default(ntext_img_height)
ntext_img = PIL.Image.new("RGB", (ntext_img_width, ntext_img_height), color=self.txtlbl_bgcolour)
region_img.paste(TextLabel(text=self.name, font_size=7).img, (5, 5))

ntext_canvas = PIL.ImageDraw.Draw(ntext_img)
self.img = region_img

_, _, ntext_width, ntext_height = ntext_canvas.textbbox(
(0, 0), self.name, font=ntext_font)

ntext_canvas.text(((ntext_img_width-ntext_width)/2,
(ntext_img_height-ntext_height)/2-1),
self.name, fill=self.txtlbl_fgcolour,
font=ntext_font)
@typeguard.typechecked
class TextLabel():
def __init__(self, text: str, font_size: int):
self.text = text
"""The display label text"""

ntext_img = ntext_img.rotate(180)
region_img.paste(ntext_img, (5, 5))
self.font = PIL.ImageFont.load_default(font_size)
"""The font used to display the text"""

self.img = region_img
_, top, right, bottom = self.font.getbbox(self.text)
"""The dimensions required for the text"""

self.width = right
"""The label width"""

self.height = bottom - top
"""The label height"""

self.bgcolour = "oldlace"
"""The background colour to use for the region text label"""

self.fgcolour = "black"
"""The foreground colour to use for the region text label"""

self.img: PIL.Image
"""The image object. Use this with PIL.Image.paste()"""

self._create_img()

def _create_img(self):

# make the image bigger than the actual text bbox so there is plenty of space for the text
self.img = PIL.Image.new("RGB", (self.width * 2, self.height * 2), color=self.bgcolour)
canvas = PIL.ImageDraw.Draw(self.img)
# center the text in the oversized image, bias the y-pos by 1/5
canvas.text(xy=(self.width / 2, (self.height / 2 - (self.height / 5))),
text=self.text,
fill=self.fgcolour,
font=self.font)

# the final diagram image will be flipped so start with the text upside down
self.img = self.img.rotate(180)


@typeguard.typechecked
Expand Down

0 comments on commit 9ea12db

Please sign in to comment.