Open FaBjE opened 1 week ago
This is super helpful, thanks @FaBjE!!!
Apologies in advance if I'm incorrectly reading this class diagram, I tend to avoid object-oriented programming except for very simple cases, so these diagrams are unfamiliar to me, but they look great!
Could you help me to understand the interface between the rendering pipeline and the printer, which currently consists of just a link between RenderContext
and Printer
? Is the RenderContext
class supposed to be a container for a bitmap being sent by the renderer to the printer? Or is the printer providing information like px_per_mm
via the RenderContext
to the Renderer
?
My mental model of a printer is that it's something capable of printing certain bitmaps. If the RenderContext
is indeed a container for bitmaps, could we get by with directly using plain bitmaps? A bitmap already knows its width and height, so that seems redundant. And the printer already knows its px_per_mm
.
For the other direction (printer→renderer), it seems to me like the printer (with its label type) needs to tell the renderer, "these are the types of bitmaps I'm capable of printing". My expectation here is very similar to the LabelConfig
class. In particular, I'd expect fields max_width_px
and max_height_px
. (Given the int
type, I suspect your intended suffix for width/height is px
instead of mm
.)
In terms of units, it seems to me like mm
is a purely user-facing unit. Of course the print head must have some mechanism to communicate its px_per_mm
to the UI, but apart from that, would it be feasible to banish mm
to the user-interface and do all the core logic in terms of px
?
On a related note, there are many places in the code that use float
type for px
, which I find really confusing, since we can only print whole pixels. I'd rather have px
be always int
type, or if that's impossible, let's document very clearly why floats are required.
This is super helpful, thanks @FaBjE!!!
Apologies in advance if I'm incorrectly reading this class diagram, I tend to avoid object-oriented programming except for very simple cases, so these diagrams are unfamiliar to me, but they look great!
Could you help me to understand the interface between the rendering pipeline and the printer, which currently consists of just a link between
RenderContext
andPrinter
? Is theRenderContext
class supposed to be a container for a bitmap being sent by the renderer to the printer? Or is the printer providing information likepx_per_mm
via theRenderContext
to theRenderer
?My mental model of a printer is that it's something capable of printing certain bitmaps. If the
RenderContext
is indeed a container for bitmaps, could we get by with directly using plain bitmaps? A bitmap already knows its width and height, so that seems redundant. And the printer already knows itspx_per_mm
.
RenderContext is indeed a bitmap, with some extra data. Like the px_per_mm. I like to wrap these things in a container object so that they can be passed around easily. I probably missed something that we will need in the future. With this approach it is just a matter of adding it to the RenderContext object and it is available in all the places. px_per_mm is indeed filled by the printer. The whole RenderContext instance is made by the printer as only it knows the "printable area" for a particular label.
I tried to keep the rendering stuff as separated from the printer as possible. RenderContext are the things that do need to be "passed around". px_per_mm It's usage is/should be limited, but for example the GUI preview showing margins/sizes in mm will need it.
For the other direction (printer→renderer), it seems to me like the printer (with its label type) needs to tell the renderer, "these are the types of bitmaps I'm capable of printing". My expectation here is very similar to the
LabelConfig
class. In particular, I'd expect fieldsmax_width_px
andmax_height_px
. (Given theint
type, I suspect your intended suffix for width/height ispx
instead ofmm
.)
It's a bit of the other way around. You select/indicate a label type to the printer. and you ask the printer for a RenderContext. Which is basically: This is a "bitmap + metadata" I can print for you on the label, render what you like on it, and I'll print it.
LabelConfig sizes are intended to be in mm. Float may be a better datatype indeed. Why mm? Example: We want to support this type of labels: https://www.dymo.com/labels-tapes/labelwriter-labels/dymo-labelwriter-return-address-labels/SAP_30330.html These are 19x51mm. If you have a 300 dpi printer, the amount of printable pixels on this label differs from when you have a 600 dpi printer. To only have 1 LabelConfig type for each type of label, and not a LabelConfig type per label for each printer. We need to use mm.
The printer object will calculate the available pixels with the label sizes and its DPI, subtract it's print margins, and give this as a "Rendercontext".
For the margins we now use a simple lookup table as the amount of supported labels (tapes in this case) is limited. But I think this is not sustainable with large amounts of labels (just take a look online of the amount of available sizes). I also think that the printers have some kind of "generic" way to determine margins for a (series) of labels. This can be added into the printer object in combination with the PrinterConfig to store model specific data.
Technically we can allow the user to set/add custom label sizes (in mm) from for example the GUI as well. In case they have some custom label type.
In terms of units, it seems to me like
mm
is a purely user-facing unit. Of course the print head must have some mechanism to communicate itspx_per_mm
to the UI, but apart from that, would it be feasible to banishmm
to the user-interface and do all the core logic in terms ofpx
?
All core logic is in px. Indeed the GUI touching parts can use mm. I think the part we differ in view is the LabelConfig. For the reason stated above.
On a related note, there are many places in the code that use
float
type forpx
, which I find really confusing, since we can only print whole pixels. I'd rather havepx
be alwaysint
type, or if that's impossible, let's document very clearly why floats are required.
I completely agree with you. (px == int). I see no reason why it can´t be like that.
I think/assume/guess the reason that where pixels are calculated from say a size in mm it can make sense to use a float type as some programming languages (I have no clue how this relates to python!!) can optimize the following: "int = float / int" to "int = int(float) / int", instead of the expectation of "int = int(float / float(int))". In text: instead of doing the calculation as a floating point, the input is converted to an int an than calculated as an integer operation. Reasoning of the compiler: It is becoming an int, so why bother with the precision during the calculation.
Split-off from the discussion in the PR I've put my view for a maintainable codebase that can support many different printers and label types into a plant uml class diagram.
Image: Class Diagram
Edit link Don´t forget to share the link if you made changes. It won´t be saved on the server.
Global program flow:
Notes: