[Added] Mechanism to install fonts and colors

This commit is contained in:
Salvador E. Tropea 2023-04-04 13:49:21 -03:00
parent 69c2890a10
commit 6feddd06a5
14 changed files with 409 additions and 2 deletions

View File

@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `field_tolerance` field/s to look for resistor tolerance.
- `default_resistor_tolerance` which tolerance to use when none found.
- `cache_3d_resistors` to avoid generating them all the time.
- `resources_dir` to specify fonts and colors to install (CI/CD)
- 3D: colored 3D models for THT resistors
- Datasheet download: now the warnings mention which reference failed.
- Plot related outputs and PCB_Print:

View File

@ -106,6 +106,8 @@ test_docker_local_1_ki7:
docker run --rm -v $(CWD):$(CWD) --workdir="$(CWD)" ghcr.io/inti-cmnb/kicad_auto_test:ki7 \
/bin/bash -c "python3-coverage run src/kibot --help-outputs > /dev/null; pytest-3 --log-cli-level debug -k '$(SINGLE_TEST)' --test_dir=output ; $(PY_COV) html; chown -R $(USER_ID):$(GROUP_ID) output/ tests/board_samples/ tests/.config/kiplot/plugins/__pycache__/ tests/test_plot/fake_pcbnew/__pycache__/ tests/.config/kibot/plugins/__pycache__/ .coverage htmlcov/"
t1k7: test_docker_local_1_ki7
test_docker_local:
rm -rf output
rm -f tests/.local

View File

@ -832,6 +832,11 @@ global:
Currently known are FR1 to FR5.
- `remove_adhesive_for_dnp`: [boolean=true] When applying filters and variants remove the adhesive (glue) for components that won't be included.
- `remove_solder_paste_for_dnp`: [boolean=true] When applying filters and variants remove the solder paste for components that won't be included.
- `resources_dir`: [string='kibot_resources'] Directory where various resources are stored. Currently we support colors and fonts.
They must be stored in sub-dirs. I.e. kibot_resources/fonts/MyFont.ttf
Note this is mainly useful for CI/CD, so you can store fonts and colors in your repo.
Also note that the fonts are installed using a mechanism known to work on Debian,
which is used by the KiBot docker images, on other OSs *your mileage may vary*.
- `restore_project`: [boolean=false] Restore the KiCad project after execution.
Note that this option will undo operations like `set_text_variables`.
- `set_text_variables_before_output`: [boolean=false] Run the `set_text_variables` preflight before running each output that involves variants.

View File

@ -277,6 +277,12 @@ class Globals(FiltersOptions):
self.cache_3d_resistors = False
""" Use a cache for the generated 3D models of colored resistors.
Will save time, but you could need to remove the cache if you need to regenerate them """
self.resources_dir = 'kibot_resources'
""" Directory where various resources are stored. Currently we support colors and fonts.
They must be stored in sub-dirs. I.e. kibot_resources/fonts/MyFont.ttf
Note this is mainly useful for CI/CD, so you can store fonts and colors in your repo.
Also note that the fonts are installed using a mechanism known to work on Debian,
which is used by the KiBot docker images, on other OSs *your mileage may vary* """
self.set_doc('filters', " [list(dict)] KiBot warnings to be ignored ")
self._filter_what = 'KiBot warnings'
self.filters = FilterOptionsKiBot

View File

@ -154,6 +154,7 @@ class GS(object):
global_pcb_material = None
global_remove_solder_paste_for_dnp = None
global_remove_adhesive_for_dnp = None
global_resources_dir = None
global_restore_project = None
global_set_text_variables_before_output = None
global_silk_screen_color = None

View File

@ -66,7 +66,8 @@ def load_color_theme(name):
fn = os.path.join(GS.get_resource_path('kicad_colors'), name+'.json')
else:
KiConf.init(GS.pcb_file)
fn = os.path.join(KiConf.config_dir, 'colors', name+'.json')
cfg_dir = KiConf.config_dir or GS.kicad_conf_path or ''
fn = os.path.join(cfg_dir, 'colors', name+'.json')
fn = os.path.abspath(fn)
global CACHE
if fn in CACHE:

View File

@ -14,7 +14,7 @@ import re
from sys import exit
from sys import path as sys_path
import shlex
from shutil import which
from shutil import which, copy2
from subprocess import run, PIPE, STDOUT, Popen, CalledProcessError
from glob import glob
from importlib.util import spec_from_file_location, module_from_spec
@ -513,6 +513,7 @@ def _generate_outputs(outputs, targets, invert, skip_pre, cli_order, no_priority
def generate_outputs(outputs, targets, invert, skip_pre, cli_order, no_priority, dont_stop=False):
setup_resources()
prj = None
if GS.global_restore_project:
# Memorize the project content to restore it at exit
@ -976,6 +977,54 @@ def _walk(path, depth):
yield from _walk(entry.path, depth)
def setup_fonts(source):
if not os.path.isdir(source):
logger.debug('No font resources dir')
return
dest = os.path.expanduser('~/.fonts/')
installed = False
for f in glob(os.path.join(source, '*.ttf')):
fname = os.path.basename(f)
fdest = os.path.join(dest, fname)
if os.path.isfile(fdest):
logger.debug('Font {} already installed'.format(fname))
continue
logger.info('Installing font {}'.format(fname))
if not os.path.isdir(dest):
os.makedirs(dest)
copy2(f, fdest)
installed = True
if installed:
run_command(['fc-cache'])
def setup_colors(source):
if not os.path.isdir(source):
logger.debug('No color resources dir')
return
if not GS.kicad_conf_path:
return
dest = os.path.join(GS.kicad_conf_path, 'colors')
for f in glob(os.path.join(source, '*.json')):
fname = os.path.basename(f)
fdest = os.path.join(dest, fname)
if os.path.isfile(fdest):
logger.debug('Color {} already installed'.format(fname))
continue
logger.info('Installing color {}'.format(fname))
if not os.path.isdir(dest):
os.makedirs(dest)
copy2(f, fdest)
def setup_resources():
if not GS.global_resources_dir:
logger.debug('No resources dir')
return
setup_fonts(os.path.join(GS.global_resources_dir, 'fonts'))
setup_colors(os.path.join(GS.global_resources_dir, 'colors'))
def generate_examples(start_dir, dry, types):
if not start_dir:
start_dir = '.'
@ -987,6 +1036,8 @@ def generate_examples(start_dir, dry, types):
glb = GS.class_for_global_opts()
glb.set_tree({})
glb.config(None)
# Install the resources
setup_resources()
# Look for candidate dirs
k_files_regex = re.compile(r'([^/]+)\.(kicad_pcb|kicad_sch|sch)$')
candidates = set()

View File

@ -0,0 +1,89 @@
(kicad_pcb (version 20221018) (generator pcbnew)
(general
(thickness 1.6)
)
(paper "A4")
(layers
(0 "F.Cu" signal)
(31 "B.Cu" signal)
(32 "B.Adhes" user "B.Adhesive")
(33 "F.Adhes" user "F.Adhesive")
(34 "B.Paste" user)
(35 "F.Paste" user)
(36 "B.SilkS" user "B.Silkscreen")
(37 "F.SilkS" user "F.Silkscreen")
(38 "B.Mask" user)
(39 "F.Mask" user)
(40 "Dwgs.User" user "User.Drawings")
(41 "Cmts.User" user "User.Comments")
(42 "Eco1.User" user "User.Eco1")
(43 "Eco2.User" user "User.Eco2")
(44 "Edge.Cuts" user)
(45 "Margin" user)
(46 "B.CrtYd" user "B.Courtyard")
(47 "F.CrtYd" user "F.Courtyard")
(48 "B.Fab" user)
(49 "F.Fab" user)
(50 "User.1" user)
(51 "User.2" user)
(52 "User.3" user)
(53 "User.4" user)
(54 "User.5" user)
(55 "User.6" user)
(56 "User.7" user)
(57 "User.8" user)
(58 "User.9" user)
)
(setup
(pad_to_mask_clearance 0)
(pcbplotparams
(layerselection 0x00010fc_ffffffff)
(plot_on_all_layers_selection 0x0000000_00000000)
(disableapertmacros false)
(usegerberextensions false)
(usegerberattributes true)
(usegerberadvancedattributes true)
(creategerberjobfile true)
(dashed_line_dash_ratio 12.000000)
(dashed_line_gap_ratio 3.000000)
(svgprecision 4)
(plotframeref false)
(viasonmask false)
(mode 1)
(useauxorigin false)
(hpglpennumber 1)
(hpglpenspeed 20)
(hpglpendiameter 15.000000)
(dxfpolygonmode true)
(dxfimperialunits true)
(dxfusepcbnewfont true)
(psnegative false)
(psa4output false)
(plotreference true)
(plotvalue true)
(plotinvisibletext false)
(sketchpadsonfab false)
(subtractmaskfromsilk false)
(outputformat 1)
(mirror false)
(drillshape 1)
(scaleselection 1)
(outputdirectory "")
)
)
(net 0 "")
(gr_rect (start 100 70) (end 150 121)
(stroke (width 0.2) (type default)) (fill none) (layer "Edge.Cuts") (tstamp cd1c9c8d-3ccc-4c8b-b847-9a6aa1c9d599))
(gr_text "4" (at 105 110) (layer "F.Cu") (tstamp 1dbcdcd1-a8e9-4623-9731-77c1e65b8868)
(effects (font (size 20 20) (thickness 5) bold) (justify left bottom))
)
(gr_text "4" (at 125 110) (layer "F.Cu") (tstamp d892df33-6ec0-4783-b75f-e6ee5f7aacc6)
(effects (font (face "Archivo SemiBold") (size 20 20) (thickness 5) bold) (justify left bottom))
)
)

View File

@ -0,0 +1,218 @@
{
"3d_viewer": {
"background_bottom": "rgb(102, 102, 128)",
"background_top": "rgb(204, 204, 230)",
"board": "rgba(51, 43, 23, 0.902)",
"copper": "rgb(179, 156, 0)",
"silkscreen_bottom": "rgb(230, 230, 230)",
"silkscreen_top": "rgb(230, 230, 230)",
"soldermask_bottom": "rgba(20, 51, 36, 0.831)",
"soldermask_top": "rgba(20, 51, 36, 0.831)",
"solderpaste": "rgb(128, 128, 128)",
"use_board_stackup_colors": true
},
"board": {
"anchor": "rgb(255, 38, 226)",
"aux_items": "rgb(255, 255, 255)",
"b_adhes": "rgb(0, 0, 132)",
"b_crtyd": "rgb(38, 233, 255)",
"b_fab": "rgb(88, 93, 132)",
"b_mask": "rgba(2, 255, 238, 0.400)",
"b_paste": "rgba(0, 194, 194, 0.902)",
"b_silks": "rgb(232, 178, 167)",
"background": "rgb(0, 16, 35)",
"cmts_user": "rgb(89, 148, 220)",
"conflicts_shadow": "rgba(255, 0, 5, 0.502)",
"copper": {
"b": "rgb(77, 127, 196)",
"f": "rgb(114, 194, 200)",
"in1": "rgb(127, 200, 127)",
"in10": "rgb(237, 124, 51)",
"in11": "rgb(91, 195, 235)",
"in12": "rgb(247, 111, 142)",
"in13": "rgb(167, 165, 198)",
"in14": "rgb(40, 204, 217)",
"in15": "rgb(232, 178, 167)",
"in16": "rgb(242, 237, 161)",
"in17": "rgb(237, 124, 51)",
"in18": "rgb(91, 195, 235)",
"in19": "rgb(247, 111, 142)",
"in2": "rgb(206, 125, 44)",
"in20": "rgb(167, 165, 198)",
"in21": "rgb(40, 204, 217)",
"in22": "rgb(232, 178, 167)",
"in23": "rgb(242, 237, 161)",
"in24": "rgb(237, 124, 51)",
"in25": "rgb(91, 195, 235)",
"in26": "rgb(247, 111, 142)",
"in27": "rgb(167, 165, 198)",
"in28": "rgb(40, 204, 217)",
"in29": "rgb(232, 178, 167)",
"in3": "rgb(79, 203, 203)",
"in30": "rgb(242, 237, 161)",
"in4": "rgb(219, 98, 139)",
"in5": "rgb(167, 165, 198)",
"in6": "rgb(40, 204, 217)",
"in7": "rgb(232, 178, 167)",
"in8": "rgb(242, 237, 161)",
"in9": "rgb(141, 203, 129)"
},
"cursor": "rgb(255, 255, 255)",
"drc_error": "rgba(215, 91, 107, 0.800)",
"drc_exclusion": "rgba(255, 255, 255, 0.800)",
"drc_warning": "rgba(255, 208, 66, 0.800)",
"dwgs_user": "rgb(194, 194, 194)",
"eco1_user": "rgb(180, 219, 210)",
"eco2_user": "rgb(216, 200, 82)",
"edge_cuts": "rgb(149, 210, 48)",
"f_adhes": "rgb(132, 0, 132)",
"f_crtyd": "rgb(255, 38, 226)",
"f_fab": "rgb(175, 175, 175)",
"f_mask": "rgba(216, 100, 255, 0.400)",
"f_paste": "rgba(180, 160, 154, 0.902)",
"f_silks": "rgb(242, 237, 161)",
"footprint_text_invisible": "rgb(132, 132, 132)",
"grid": "rgb(132, 132, 132)",
"grid_axes": "rgb(194, 194, 194)",
"locked_shadow": "rgba(255, 38, 226, 0.502)",
"margin": "rgb(255, 38, 226)",
"pad_plated_hole": "rgb(194, 194, 0)",
"pad_through_hole": "rgb(227, 183, 46)",
"page_limits": "rgb(132, 132, 132)",
"plated_hole": "rgb(26, 196, 210)",
"ratsnest": "rgba(0, 248, 255, 0.349)",
"user_1": "rgb(194, 194, 194)",
"user_2": "rgb(89, 148, 220)",
"user_3": "rgb(180, 219, 210)",
"user_4": "rgb(216, 200, 82)",
"user_5": "rgb(194, 194, 194)",
"user_6": "rgb(89, 148, 220)",
"user_7": "rgb(180, 219, 210)",
"user_8": "rgb(216, 200, 82)",
"user_9": "rgb(232, 178, 167)",
"via_blind_buried": "rgb(187, 151, 38)",
"via_hole": "rgb(227, 183, 46)",
"via_micro": "rgb(0, 132, 132)",
"via_through": "rgb(236, 236, 236)",
"worksheet": "rgb(200, 114, 171)"
},
"gerbview": {
"axes": "rgb(0, 0, 132)",
"background": "rgb(0, 0, 0)",
"dcodes": "rgb(255, 255, 255)",
"grid": "rgb(132, 132, 132)",
"layers": [
"rgb(200, 52, 52)",
"rgb(127, 200, 127)",
"rgb(206, 125, 44)",
"rgb(79, 203, 203)",
"rgb(219, 98, 139)",
"rgb(167, 165, 198)",
"rgb(40, 204, 217)",
"rgb(232, 178, 167)",
"rgb(242, 237, 161)",
"rgb(141, 203, 129)",
"rgb(237, 124, 51)",
"rgb(91, 195, 235)",
"rgb(247, 111, 142)",
"rgb(77, 127, 196)",
"rgb(200, 52, 52)",
"rgb(127, 200, 127)",
"rgb(206, 125, 44)",
"rgb(79, 203, 203)",
"rgb(219, 98, 139)",
"rgb(167, 165, 198)",
"rgb(40, 204, 217)",
"rgb(232, 178, 167)",
"rgb(242, 237, 161)",
"rgb(141, 203, 129)",
"rgb(237, 124, 51)",
"rgb(91, 195, 235)",
"rgb(247, 111, 142)",
"rgb(77, 127, 196)",
"rgb(200, 52, 52)",
"rgb(127, 200, 127)",
"rgb(206, 125, 44)",
"rgb(79, 203, 203)",
"rgb(219, 98, 139)",
"rgb(167, 165, 198)",
"rgb(40, 204, 217)",
"rgb(232, 178, 167)",
"rgb(242, 237, 161)",
"rgb(141, 203, 129)",
"rgb(237, 124, 51)",
"rgb(91, 195, 235)",
"rgb(247, 111, 142)",
"rgb(77, 127, 196)",
"rgb(200, 52, 52)",
"rgb(127, 200, 127)",
"rgb(206, 125, 44)",
"rgb(79, 203, 203)",
"rgb(219, 98, 139)",
"rgb(167, 165, 198)",
"rgb(40, 204, 217)",
"rgb(232, 178, 167)",
"rgb(242, 237, 161)",
"rgb(141, 203, 129)",
"rgb(237, 124, 51)",
"rgb(91, 195, 235)",
"rgb(247, 111, 142)",
"rgb(77, 127, 196)",
"rgb(200, 52, 52)",
"rgb(127, 200, 127)",
"rgb(206, 125, 44)",
"rgb(79, 203, 203)"
],
"negative_objects": "rgb(132, 132, 132)",
"page_limits": "rgb(132, 132, 132)",
"worksheet": "rgb(0, 0, 132)"
},
"meta": {
"name": "test_color",
"version": 5
},
"schematic": {
"anchor": "rgb(0, 0, 255)",
"aux_items": "rgb(0, 0, 0)",
"background": "rgb(245, 244, 239)",
"brightened": "rgb(255, 0, 255)",
"bus": "rgb(0, 0, 132)",
"bus_junction": "rgb(0, 0, 132)",
"component_body": "rgb(255, 255, 194)",
"component_outline": "rgb(132, 0, 0)",
"cursor": "rgb(15, 15, 15)",
"erc_error": "rgba(230, 9, 13, 0.800)",
"erc_exclusion": "rgba(94, 194, 194, 0.800)",
"erc_warning": "rgba(209, 146, 0, 0.800)",
"fields": "rgb(132, 0, 132)",
"grid": "rgb(181, 181, 181)",
"grid_axes": "rgb(0, 0, 132)",
"hidden": "rgb(94, 194, 194)",
"hovered": "rgb(0, 0, 255)",
"junction": "rgb(0, 150, 0)",
"label_global": "rgb(132, 0, 0)",
"label_hier": "rgb(114, 86, 0)",
"label_local": "rgb(15, 15, 15)",
"netclass_flag": "rgb(72, 72, 72)",
"no_connect": "rgb(0, 0, 132)",
"note": "rgb(0, 0, 194)",
"note_background": "rgba(0, 0, 0, 0.000)",
"override_item_colors": false,
"page_limits": "rgb(181, 181, 181)",
"pin": "rgb(132, 0, 0)",
"pin_name": "rgb(0, 100, 100)",
"pin_number": "rgb(169, 0, 0)",
"private_note": "rgb(72, 72, 255)",
"reference": "rgb(0, 100, 100)",
"shadow": "rgba(102, 179, 255, 0.800)",
"sheet": "rgb(132, 0, 0)",
"sheet_background": "rgba(255, 255, 255, 0.000)",
"sheet_fields": "rgb(132, 0, 132)",
"sheet_filename": "rgb(114, 86, 0)",
"sheet_label": "rgb(0, 100, 100)",
"sheet_name": "rgb(0, 100, 100)",
"value": "rgb(0, 100, 100)",
"wire": "rgb(0, 150, 0)",
"worksheet": "rgb(132, 0, 0)"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@ -1626,3 +1626,13 @@ def test_panelize_1(test_dir):
ctx.run(extra=[])
ctx.compare_image(prj+'-panel.png')
ctx.clean_up(keep_project=True)
@pytest.mark.skipif(not context.ki7(), reason="Uses fonts")
def test_font_and_colors_1(test_dir):
prj = 'font_and_colors'
ctx = context.TestContext(test_dir, prj, 'resources_1')
ctx.run()
ctx.compare_image(prj+'-top.png')
ctx.compare_image(prj+'-assembly_page_01.png')
ctx.clean_up()

View File

@ -0,0 +1,23 @@
kiplot:
version: 1
globals:
resources_dir: tests/data/kibot_resources_1
outputs:
- name: PcbDraw
comment: "PcbDraw font test"
type: pcbdraw
options:
format: png
- name: 'print_front'
comment: "Font and colors"
type: pcb_print
options:
plot_sheet_reference: false
scaling: 3
format: PNG
color_theme: test_color
pages:
- layers: [F.Cu, Edge.Cuts]