Mailing list archives : pcb-rnd

Date:Fri, 22 Jan 2021 17:10:51 +0100 (CET)
Subject:[pcb-rnd] new: render script
Hi all,
TL;DR: layer group order in rendering became scriptable. You can tune it 
in the config. You can get holes drawn under mask if you want.
I. How it worked before
There's a function in the code that is responsible for driving the 
render. It's called draw_everything(). It was derived from a code we 
inherited from the 2011 version of gEDA/PCB (but I guess it did not 
change much in that project). It got almost completly rewritten 
incrementally, becuase of API changes, but the essence, the logic of the 
code did not change: it determines in what order layers are rendered. In 
other words this is the function that makes mask appear between copper and 
It is a rather complicated piece of code, in the sense that 
literally decades of historical "do foo before bar, but don't do baz 
if..." accumulated in a long C function. 
I got feature requests like:
1. hole under mask
"I use microvias and mask covers my via holes in reality, but pcb-rnd 
renders it as if holes pierced through mask!"
2. hole vs. silk
Similar story on silk not being drilled, but holes are covered with silk 
(some fabs avoid this and they do remove parts of the silk graphics above 
holes, so you don't always see this)
3. paste vs. non-copper
It's also an interesting question where to render paste; in the process, 
it goes over everything, as it's put on last, and we render it like that. 
But that doesn't necessarily make visual inspection easy, when a silk line 
accidentally gets under a paste object. (Well, we should catch that with 
DRC anyway).
I didn't want to complicate that convoluted C code any further so these 
feature request generally ended up as "just make this scriptable" in the 
II. What's new
New is a config node that holds a simple script that tells the code what 
layer groups and other things to render, in the order the script is 
running. It can also execute some rendering step upon conditions, for 
example some things (like subcircuit marks) should appear only on screen, 
not in exports.
We have a new, very small and simple Domain Specific Language for this 
script, designed to be extremely fast to execute (it runs on every 
rendering, e.g. for every frame when you are panning!) and to avoid the 
possibility of accidentally creating infinite loops.
You can find the example script, which is the original C code translated 
to this script language 1:1, in pcb-conf.lht in the render_script string.
Note: we still have the old C code as well; it is used as fallback if the 
script is not available or has runtime errors.
III. How does it affect you
If you are happy with the rendering order we always had, this does not 
affect you at all.
If you want to change the rendering order, you can easily do that changing 
the script via config. Since this is a plain config node, you can do this 
in your user config, or if you have only one project or board that wants 
it differently in the project file or board file.
Note: the scope of this effort is limited to the coordination of 
rendering, more specifically to the _order_ of layer groups and other 
groupped things are rendered. So it won't let you change how things look 
and won't give you any fine grain control over graphical details, as 
these things are all in the low level render code.
Warning: if you change your render script, you will need to update it if 
upstream adds new things. It doesn't happen very often, but sometimes it 
does. For example when new layer types appear. If you forget to update 
your custom script, it may simply not render the new features. It's a bit 
like the problem we had with custom menu files before the menu patch 
system, except that these scripts are real small and there are much much 
fewer changes in upstream so manual maintenance of such custom scripts 
sound viable. 
IV. History of this feature
Originally pcb (and its predecessor, router) back in the early 90s, had 
only a few layers to deal with - it was pretty much a "copper only, 2 
layer board I could etch in the kitchen" kind of editor. Then new layers 
got added gradually, with a lot of implications and automatism. That's why 
it was only the silk layer that could be edited in gEDA/pcb, not mask or 
paste or fab or assy. Or in other words, any layer beyond copper was 
special cased in one way or another.
These special case layers got added over more than 2 decades of project 
history. Plus more export targets got gradually added too, which yielded 
new combination of special cases: gerber wanted one layer group per file 
while ps and png wanted to combine them. The rendering code grew 
spontenously, seemingly without much though about long term code 
maintaining aspects.
This led to a real long and convoluted piece of code that was also 
fragile: if you changed anything, you risked some special case rendered 
wrong on GUI or on some rarely used export target.
In the same time, there were legit feature requests that could only be 
solved by complicating this piece of code with even more options and 
conditions and branches. Since this was already a complicated and fragile 
and essential/central piece of code, I decided not to add the complication 
required for those features.
Making the whole thing scriptable is a nice way to escape from the 
ever-growing spaghetti: instead of a dozen of special boolean settings 
such as "render hole below mask", we can keep things simple and flat and 
still let the user change rendering order. In fact it's even more flexible 
this way as the user can use a lot more combinations of ordering, things 
the programmer did not think about and could not add a boolean switch for.
Best regards,

Reply subtree:
4669 [pcb-rnd] new: render script from