KiBot/kibot/kicad/color_theme.py

111 lines
3.8 KiB
Python

# -*- coding: utf-8 -*-
# Copyright (c) 2022 Salvador E. Tropea
# Copyright (c) 2022 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
"""
KiCad 6 color theme loader
"""
import os
import json
from pcbnew import BOARD, PCBNEW_LAYER_ID_START, PCB_LAYER_ID_COUNT
from ..gs import GS
from ..misc import W_COLORTHEME, W_WRONGCOLOR
from .config import KiConf
from .. import log
logger = log.get_logger()
BUILT_IN = {'_builtin_classic', '_builtin_default'}
KI6_KI5 = {'b_adhesive': 'b_adhes',
'f_adhesive': 'f_adhes',
'b_silkscreen': 'b_silks',
'f_silkscreen': 'f_silks',
'user_drawings': 'dwgs_user',
'user_comments': 'cmts_user',
'user_eco1': 'eco1_user',
'user_eco2': 'eco2_user',
'b_courtyard': 'b_crtyd',
'f_courtyard': 'f_crtyd'}
BOARD_COLORS = {'worksheet': 'pcb_frame',
'pad_through_hole': 'pad_through_hole',
'via_through': 'via_through',
'via_blind_buried': 'via_blind_buried',
'via_micro': 'via_micro'}
CACHE = {}
class KiCadColors(object):
def __init__(self):
self.layer_id2color = {}
self.pcb_frame = "#480000"
self.pad_through_hole = "#C2C200"
self.via_through = "#C2C2C2"
def parse_color(val):
if val.startswith('rgb('):
vals = val[4:-1].split(',')
elif val.startswith('rgba('):
vals = val[5:-1].split(',')
else:
logger.warning(W_WRONGCOLOR+"Wrong KiCad color: {}".format(val))
return "#000000"
res = '#'
for c, v in enumerate(vals):
res += '%02X' % (int(v) if c < 3 else int(float(v)*255))
return res
def load_color_theme(name):
logger.debug('Looking for color theme `{}`'.format(name))
is_built_in = name in BUILT_IN
if not is_built_in and GS.ki5:
logger.warning(W_COLORTHEME, "KiCad 5 doesn't support color themes ({})".format(name))
return None
if is_built_in:
fn = os.path.join(os.path.dirname(__file__), '..', 'kicad_colors', name+'.json')
else:
KiConf.init(GS.pcb_file)
fn = os.path.join(KiConf.config_dir, 'colors', name+'.json')
fn = os.path.abspath(fn)
global CACHE
if fn in CACHE:
return CACHE[fn]
if not os.path.isfile(fn):
logger.warning(W_COLORTHEME, "Missing color theme: {}".format(fn))
return None
with open(fn, 'rt') as f:
text = f.read()
data = json.loads(text)
c = KiCadColors()
cl = c.layer_id2color
board = data['board']
copper = board['copper']
extra_debug = GS.debug_level >= 3
for id in range(PCBNEW_LAYER_ID_START, PCBNEW_LAYER_ID_START+PCB_LAYER_ID_COUNT):
c_name = c_name_ori = BOARD.GetStandardLayerName(id)
c_name = c_name.lower()
if c_name == 'rescue':
continue
if c_name.endswith('.cu'):
c_name = c_name[:-3]
if c_name in copper:
cl[id] = parse_color(copper[c_name])
else:
logger.warning(W_WRONGCOLOR+"The `{}` theme doesn't define a color for the {} layer".format(name, c_name_ori))
else:
c_name = c_name.replace('.', '_')
c_name = KI6_KI5.get(c_name, c_name)
if c_name in board:
cl[id] = parse_color(board[c_name])
else:
logger.warning(W_WRONGCOLOR+"The `{}` theme doesn't define a color for the {} layer".format(name, c_name_ori))
if extra_debug:
logger.debug('- Color for layer {} ({}): {}'.format(c_name_ori, id, cl[id]))
# Other colors (Title block and frame color, vias, etc.)
for color, member in BOARD_COLORS.items():
if color in board:
setattr(c, member, parse_color(board[color]))
CACHE[fn] = c
return c