File indexing completed on 2024-04-21 16:11:36

0001 #!/usr/bin/env python3
0002 import cairo
0003 import colorsys
0004 from math import pi
0005 import os
0006 import errno
0007 import sys
0008 import re
0009 import argparse
0010 
0011 
0012 def make_sure_path_exists(path):
0013     try:
0014         os.makedirs(path)
0015     except FileExistsError as exception:
0016         pass
0017     pass
0018 
0019 
0020 class ReadKdeGlobals():
0021     def __init__(self, base_file_name):
0022         self._colors = {}
0023         self._colors = self.read_globals(base_file_name)
0024 
0025     def read_globals(self, filename):
0026         with open(filename, 'r', encoding="utf-8") as _kde:
0027             for widget in ['Disabled', 'Inactive', 'Button', 'Selection',
0028                            'Tooltip', 'View', 'Window', 'WM']:
0029                 for line in _kde:
0030                     if line.strip().split(':')[-1].strip('[]') == widget:
0031                         break
0032                 for line in _kde:
0033                     if line == '\n':
0034                         break
0035                     key = '{0}{1}'.format(widget, line.strip().split('=')[0])
0036                     value = line.strip().split('=')[1]
0037                     if value == '':
0038                         continue
0039                     self._colors[key] = value
0040         return self._colors
0041 
0042 
0043 class Color(object):
0044     def __init__(self, colordict, name, name2=None, amount=0):
0045         color = colordict[name]
0046         self.colordict = colordict
0047 
0048         r = float(color.split(',')[0])
0049         g = float(color.split(',')[1])
0050         b = float(color.split(',')[2])
0051         if name2 is not None:
0052             color2 = colordict[name2]
0053             r = r * amount + float(color2.split(',')[0]) * (1 - amount)
0054             g = g * amount + float(color2.split(',')[1]) * (1 - amount)
0055             b = b * amount + float(color2.split(',')[2]) * (1 - amount)
0056 
0057         self.rgb255 = (int(r), int(g), int(b))
0058         self.rgb = (r/255, g/255, b/255)
0059         self.html = '#%02x%02x%02x' % self.rgb255
0060         self.insensitive = self._color_effect(
0061             self._intensity_effect(self.rgb, 'Disabled'), 'Disabled')
0062         self.insensitive_alpha = self._contrast_effect(self.rgb, 'Disabled')
0063 
0064         if self.colordict['InactiveEnable'] == 'false':
0065             self.inactive = self.rgb
0066             self.inactive_alpha = 1.0
0067         else:
0068             self.inactive = self._color_effect(
0069                 self._intensity_effect(self.rgb, 'Inactive'), 'Inactive')
0070             self.inactive_alpha = self._contrast_effect(self.rgb, 'Inactive')
0071         self.inactive_insensitive = self._color_effect(
0072             self._intensity_effect(self.inactive, 'Disabled'), 'Disabled')
0073         self.inactive_insensitive_alpha = max(
0074             self.inactive_alpha - (1 - self.insensitive_alpha), 0)
0075 
0076     def _mix(self, color, mix_color, amount):
0077         r = color[0] * amount + mix_color[0] * (1 - amount)
0078         g = color[1] * amount + mix_color[1] * (1 - amount)
0079         b = color[2] * amount + mix_color[2] * (1 - amount)
0080         return (r, g, b)
0081 
0082     def _lighter(self, color, amount):
0083         h, s, v = colorsys.rgb_to_hsv(color[0], color[1], color[2])
0084         v = min((1+amount)*v, 1)
0085         r, g, b = colorsys.hsv_to_rgb(h, s, v)
0086         return (r, g, b)
0087 
0088     def _darker(self, color, amount):
0089         h, s, v = colorsys.rgb_to_hsv(color[0], color[1], color[2])
0090         if amount == -1:
0091             v = 1
0092         else:
0093             v = min(v/(1+amount), 1)
0094         r, g, b = colorsys.hsv_to_rgb(h, s, v)
0095         return (r, g, b)
0096 
0097     def _desaturate(self, color, amount):
0098         h, s, v = colorsys.rgb_to_hsv(color[0], color[1], color[2])
0099         s = min(s * (1 - amount), 1)
0100         r, g, b = colorsys.hsv_to_rgb(h, s, v)
0101         return (r, g, b)
0102 
0103     def _intensity_effect(self, color, state):
0104         effect = int(self.colordict[state + 'IntensityEffect'])
0105         amount = float(self.colordict[state + 'IntensityAmount'])
0106         if effect == 0:
0107             (r, g, b) = color
0108         elif effect == 1:
0109             if amount >= 0:
0110                 (r, g, b) = self._mix((1.0, 1.0, 1.0), color, amount)
0111             else:
0112                 (r, g, b) = self._mix((0.0, 0.0, 0.0), color, amount)
0113         elif effect == 2:
0114             (r, g, b) = self._darker(color, amount)
0115         elif effect == 3:
0116             (r, g, b) = self._lighter(color, amount)
0117         return (r, g, b)
0118 
0119     def _color_effect(self, color, state):
0120         effect = int(self.colordict[state + 'ColorEffect'])
0121         amount = float(self.colordict[state + 'ColorAmount'])
0122         effect_color = self.colordict[state + 'Color']
0123         effect_color = (float(effect_color.split(',')[0])/255,
0124                         float(effect_color.split(',')[1])/255,
0125                         float(effect_color.split(',')[2])/255)
0126         if effect == 0:
0127             (r, g, b) = color
0128         elif effect == 1:
0129             (r, g, b) = self._desaturate(color, amount)
0130         else:
0131             (r, g, b) = self._mix(effect_color, color, amount)
0132         return (r, g, b)
0133 
0134     def _contrast_effect(self, color, state):
0135         effect = int(self.colordict[state + 'ContrastEffect'])
0136         amount = float(self.colordict[state + 'ContrastAmount'])
0137         if effect == 0:
0138             return 1.0
0139         else:
0140             return 1.0 - amount
0141 
0142     def lighten_color(self, amount):
0143         h, s, v = colorsys.rgb_to_hsv(self.rgb[0], self.rgb[1], self.rgb[2])
0144         v = (1+amount)*v
0145         r, g, b = colorsys.hsv_to_rgb(h, s, v)
0146         self.rgb = (r, g, b)
0147         self.rgb255 = (int(r*255), int(g*255), int(b*255))
0148 
0149     def gradient(self, state='', alpha=1.0):
0150         if state == 'active':
0151             stop1 = self._lighter(self.rgb, 0.03)
0152             stop2 = self._darker(self.rgb, 0.10)
0153             linear = cairo.LinearGradient(1, 1, 1, 19)
0154             linear.add_color_stop_rgba(
0155                 0.0, stop1[0], stop1[1], stop1[2], alpha)
0156             linear.add_color_stop_rgba(
0157                 1.0, stop2[0], stop2[1], stop2[2], alpha)
0158         else:
0159             stop1 = self._lighter(self.rgb, 0.01)
0160             stop2 = self._darker(self.rgb, 0.03)
0161             linear = cairo.LinearGradient(1, 1, 1, 19)
0162             linear.add_color_stop_rgba(
0163                 0.0, stop1[0], stop1[1], stop1[2], alpha)
0164             linear.add_color_stop_rgba(
0165                 1.0, stop2[0], stop2[1], stop2[2], alpha)
0166         return linear
0167 
0168 
0169 class Assets(object):
0170     def __init__(self, width, height, scl=1, rotation=0, filename='png'):
0171         self.w = width
0172         self.h = height
0173         if filename == 'png':
0174             self.surface = cairo.ImageSurface(
0175                 cairo.FORMAT_ARGB32, scl*width, scl*height)
0176         else:
0177             self.surface = cairo.SVGSurface(os.path.join(
0178                 assets_path, filename), scl*width, scl*height)
0179         cr = self.cr = cairo.Context(self.surface)
0180         if rotation != 0:
0181             cr.translate(scl*width/2, scl*height/2)
0182             cr.rotate(rotation*pi/2)
0183             cr.translate(-scl*width/2, -scl*height/2)
0184         cr.scale(scl, scl)
0185 
0186     def background(self, color):
0187         self.cr.rectangle(0, 0, self.w, self.h)
0188         self.cr.set_source_rgb(color[0], color[1], color[2])
0189         self.cr.fill()
0190 
0191     def line(self, color, x, y, width, height):
0192         self.cr.rectangle(x, y, width, height)
0193         self.cr.set_source_rgb(color[0], color[1], color[2])
0194         self.cr.fill()
0195 
0196     def rounded_rectancle(self, color, width, height, x, y, radius, alpha=1.0,
0197                           gradient=False):
0198         self.cr.new_sub_path()
0199         self.cr.arc(x + width - radius, y + radius, radius, -pi/2, 0)
0200         self.cr.arc(x + width - radius, y + height - radius, radius, 0, pi/2)
0201         self.cr.arc(x + radius, y + height - radius, radius, pi/2, pi)
0202         self.cr.arc(x + radius, y + radius, radius, pi, 3*pi/2)
0203         self.cr.close_path()
0204         if gradient:
0205             self.cr.set_source(color)
0206         elif color is None:
0207             self.cr.set_operator(cairo.OPERATOR_CLEAR)
0208         elif color == 'shadow':
0209             self.cr.set_source_rgba(0.0, 0.0, 0.0, 0.15)
0210         else:
0211             self.cr.set_source_rgba(color[0], color[1], color[2], alpha)
0212         self.cr.fill()
0213 
0214     def rounded_triangle(self, color, width, height, x, y, radius, alpha=1.0):
0215         self.cr.new_sub_path()
0216         self.cr.move_to(x + width, y)
0217         self.cr.line_to(x + width, y + height - radius)
0218         self.cr.arc(x + width - radius, y + height - radius, radius, 0, pi/2)
0219         self.cr.line_to(x, y + height)
0220         self.cr.close_path()
0221         self.cr.set_source_rgba(color[0], color[1], color[2], alpha)
0222         self.cr.fill()
0223 
0224     def circle(self, color, x, y, radius, alpha=1.0, gradient=False):
0225         self.cr.new_sub_path()
0226         self.cr.arc(x, y, radius, 0, 2*pi)
0227         self.cr.close_path()
0228         if gradient:
0229             self.cr.set_source(color)
0230         elif color is None:
0231             self.cr.set_operator(cairo.OPERATOR_CLEAR)
0232         elif color == 'shadow':
0233             self.cr.set_source_rgba(0.0, 0.0, 0.0, 0.15)
0234         else:
0235             self.cr.set_source_rgba(color[0], color[1], color[2], alpha)
0236         self.cr.fill()
0237 
0238     def half_circle(self, color, x, y, radius, alpha=1.0):
0239         self.cr.new_sub_path()
0240         self.cr.arc(x, y, radius, -pi/4, 3*pi/4)
0241         self.cr.close_path()
0242         self.cr.set_source_rgba(color[0], color[1], color[2], alpha)
0243         self.cr.fill()
0244 
0245     def arrow(self, color, alpha=1.0, shiftx=0, shifty=0):
0246         self.cr.new_sub_path()
0247         self.cr.move_to(shiftx + 1, shifty + 8)
0248         self.cr.line_to(shiftx + 6, shifty + 3)
0249         self.cr.line_to(shiftx + 11, shifty + 8)
0250         self.cr.set_source_rgba(color[0], color[1], color[2], alpha)
0251         self.cr.set_line_width(1.0)
0252         self.cr.stroke()
0253 
0254     def arrow_small(self, color, alpha=1.0):
0255         self.cr.new_sub_path()
0256         self.cr.move_to(1, 6)
0257         self.cr.line_to(4, 3)
0258         self.cr.line_to(7, 6)
0259         self.cr.set_source_rgba(color[0], color[1], color[2], alpha)
0260         self.cr.set_line_width(1.0)
0261         self.cr.stroke()
0262 
0263     def tab(self, color, width, height, x, y, radius, alpha=1.0):
0264         self.cr.move_to(width + x, y)
0265         self.cr.line_to(width + x, height - radius + y)
0266         self.cr.arc(width - radius + x, height - radius + y, radius, 0, pi/2)
0267         self.cr.line_to(radius + x, height + y)
0268         self.cr.arc(radius + x, height - radius + y, radius, pi/2, pi)
0269         self.cr.line_to(x, y)
0270         self.cr.close_path
0271         if color is None:
0272             self.cr.set_operator(cairo.OPERATOR_CLEAR)
0273         else:
0274             self.cr.set_source_rgba(color[0], color[1], color[2], alpha)
0275         self.cr.fill()
0276 
0277     def spinbutton(self, color, width, height, x, y, radius, alpha=1.0):
0278         self.cr.move_to(width + x, y)
0279         self.cr.line_to(width + x, height - radius + y)
0280         self.cr.arc(width - radius + x, height - radius + y, radius, 0, pi/2)
0281         self.cr.line_to(x, height + y)
0282         self.cr.line_to(x, y)
0283         self.cr.close_path()
0284         if color is None:
0285             self.cr.set_operator(cairo.OPERATOR_CLEAR)
0286         else:
0287             self.cr.set_source_rgba(color[0], color[1], color[2], alpha)
0288         self.cr.fill()
0289 
0290     def notebook(self, color, width, height, x, y, radius):
0291         self.cr.move_to(x, y)
0292         self.cr.line_to(x + width - radius, y)
0293         self.cr.arc(x + width - radius, y + radius, radius, -pi/2, 0)
0294         self.cr.line_to(x + width, y + height-radius)
0295         self.cr.arc(x + width - radius, y + height - radius, radius, 0, pi/2)
0296         self.cr.line_to(x + radius, y + height)
0297         self.cr.arc(x + radius, y + height - radius, radius, pi/2, pi)
0298         self.cr.close_path()
0299         self.cr.set_source_rgb(color[0], color[1], color[2])
0300         self.cr.fill()
0301 
0302     def minimize(self, color=None):
0303         self.cr.move_to(4, 7)
0304         self.cr.line_to(9, 12)
0305         self.cr.line_to(14, 7)
0306         if color is None:
0307             self.cr.set_operator(cairo.OPERATOR_CLEAR)
0308         else:
0309             self.cr.set_source_rgb(color[0], color[1], color[2])
0310         self.cr.set_line_width(1.0)
0311         self.cr.stroke()
0312 
0313     def maximize(self, color=None):
0314         self.cr.move_to(4, 11)
0315         self.cr.line_to(9, 6)
0316         self.cr.line_to(14, 11)
0317         if color is None:
0318             self.cr.set_operator(cairo.OPERATOR_CLEAR)
0319         else:
0320             self.cr.set_source_rgb(color[0], color[1], color[2])
0321         self.cr.set_line_width(1.0)
0322         self.cr.stroke()
0323 
0324     def maximize_maximized(self, color=None):
0325         self.cr.move_to(4.5, 9)
0326         self.cr.line_to(9, 4.5)
0327         self.cr.line_to(13.5, 9)
0328         self.cr.line_to(9, 13.5)
0329         self.cr.close_path()
0330         if color is None:
0331             self.cr.set_operator(cairo.OPERATOR_CLEAR)
0332         else:
0333             self.cr.set_source_rgb(color[0], color[1], color[2])
0334         self.cr.set_line_width(1.0)
0335         self.cr.stroke()
0336 
0337     def close(self, color=None):
0338         self.cr.move_to(5, 5)
0339         self.cr.line_to(13, 13)
0340         self.cr.move_to(13, 5)
0341         self.cr.line_to(5, 13)
0342         if color is None:
0343             self.cr.set_operator(cairo.OPERATOR_CLEAR)
0344         else:
0345             self.cr.set_source_rgb(color[0], color[1], color[2])
0346         self.cr.set_line_width(1.0)
0347         self.cr.stroke()
0348 
0349     def save(self, filename):
0350         self.surface.write_to_png(os.path.join(assets_path, filename))
0351 
0352 
0353 def check_items(color1, color2, state, alpha=1.0):
0354     for scl in [1, 2]:
0355         if scl == 2:
0356             ending = '@2.png'
0357         else:
0358             ending = '.png'
0359         # checkboxes
0360         box = Assets(20, 20, scl)
0361         box.rounded_rectancle('shadow', 18, 18, 2, 2, 3)
0362         box.rounded_rectancle(color2, 18, 18, 1, 1, 3)
0363         box.rounded_rectancle(color1, 18, 18, 1, 1, 3, alpha=alpha)
0364         box.rounded_rectancle(color2, 16, 16, 2, 2, 2)
0365         box.save('check-unchecked' + state + ending)
0366         if state != '':
0367             box.rounded_rectancle(color1, 12, 12, 4, 4, 1, alpha=alpha)
0368             box.save('check-checked' + state + ending)
0369             box.rounded_triangle(color2, 8, 8, 6, 6, 1, alpha=alpha)
0370             box.save('check-mixed' + state + ending)
0371 
0372         # radio
0373         radio = Assets(20, 20, scl)
0374         radio.circle('shadow', 11, 11, 9)
0375         radio.circle(color2, 10, 10, 9)
0376         radio.circle(color1, 10, 10, 9, alpha=alpha)
0377         radio.circle(color2, 10, 10, 8)
0378         radio.save('radio-unchecked' + state + ending)
0379         if state != '':
0380             radio.circle(color1, 10, 10, 6, alpha=alpha)
0381             radio.save('radio-checked' + state + ending)
0382             radio.half_circle(color2, 10, 10, 4, alpha=alpha)
0383             radio.save('radio-mixed' + state + ending)
0384 
0385         # selectionmode
0386         selectionmode = Assets(40, 40, scl)
0387         selectionmode.rounded_rectancle('shadow', 18, 18, 12, 12, 3)
0388         selectionmode.rounded_rectancle(color2, 18, 18, 11, 11, 3)
0389         selectionmode.rounded_rectancle(color1, 18, 18, 11, 11, 3, alpha=alpha)
0390         selectionmode.rounded_rectancle(color2, 16, 16, 12, 12, 2)
0391         selectionmode.save('check-selectionmode-unchecked' + state + ending)
0392         if state != '':
0393             selectionmode.rounded_rectancle(
0394                 color1, 12, 12, 14, 14, 1, alpha=alpha)
0395             selectionmode.save('check-selectionmode-checked' + state + ending)
0396 
0397 
0398 def buttons(color1, color2, color3, state, alpha=1.0):
0399     button = Assets(20, 20)
0400     button.rounded_rectancle('shadow', 18, 18, 2, 2, 3)
0401     button.rounded_rectancle(color1, 18, 18, 1, 1, 3)
0402     button.rounded_rectancle(color2, 18, 18, 1, 1, 3, alpha=alpha)
0403     if state == '-active':
0404         button.rounded_rectancle(color3, 18, 18, 1, 1, 3, gradient=True)
0405     else:
0406         button.rounded_rectancle(color1, 16, 16, 2, 2, 2)
0407         button.rounded_rectancle(color3, 16, 16, 2, 2, 2, gradient=True)
0408     button.save('button' + state + '.png')
0409 
0410 
0411 def togglebuttons(color1, color2, color3, state, alpha=1.0):
0412     button = Assets(20, 20)
0413     button.rounded_rectancle(color1, 18, 18, 1, 1, 3)
0414     button.rounded_rectancle(color2, 18, 18, 1, 1, 3, alpha=alpha)
0415     if state == '-active':
0416         button.rounded_rectancle(color3, 18, 18, 1, 1, 3, gradient=True)
0417     else:
0418         button.rounded_rectancle(color1, 16, 16, 2, 2, 2)
0419         button.rounded_rectancle(color3, 16, 16, 2, 2, 2, gradient=True)
0420     button.save('togglebutton' + state + '.png')
0421 
0422 
0423 def scale_slider(color1, color2, color3, state, alpha=1.0):
0424     scale = Assets(20, 20)
0425     scale.circle(color1, 10, 10, 10)
0426     scale.circle(color2, 10, 10, 10, alpha=alpha)
0427     scale.circle(color1, 10, 10, 9)
0428     scale.circle(color3, 10, 10, 9, gradient=True)
0429     scale.save('scale-slider' + state + '.png')
0430 
0431 
0432 def scale_trough(color):
0433     trough_h = Assets(20, 20)
0434     trough_h.rounded_rectancle(color, 20, 6, 0, 7, 3)
0435     trough_h.save('scale-trough-horizontal.png')
0436 
0437     trough_h = Assets(20, 20)
0438     trough_h.rounded_rectancle(color, 6, 20, 7, 0, 3)
0439     trough_h.save('scale-trough-vertical.png')
0440 
0441 
0442 def tabs(color1, color2, state):
0443     if state == '-inactive':
0444         alpha = 0.2
0445     else:
0446         alpha = 1.0
0447     direction = ['-bottom', '-left', '-top', '-right']
0448     for i in range(0, 4):
0449         tab = Assets(20, 20, rotation=i)
0450         tab.tab(color1, 20, 20, 0, 0, 3, alpha)
0451         if state == '-active':
0452             tab.tab(color2, 18, 19, 1, 0, 2)
0453         tab.save('tab' + direction[i] + state + '.png')
0454 
0455 
0456 def arrows(color, state, alpha=1.0):
0457     direction = ['-up', '-right', '-down', '-left']
0458     for i in range(0, 4):
0459         arw = Assets(12, 12, rotation=i)
0460         arw.arrow(color, alpha)
0461         arw.save('arrow' + direction[i] + state + '.png')
0462 
0463         arw = Assets(8, 8, rotation=i)
0464         arw.arrow_small(color, alpha)
0465         arw.save('arrow-small' + direction[i] + state + '.png')
0466 
0467 
0468 def menu_arrow(color, state, alpha=1.0):
0469     arrow = Assets(12, 12, rotation=1)
0470     arrow.arrow(color, alpha)
0471     arrow.save('menu-arrow' + state + '.png')
0472 
0473 
0474 def scrollbar_slider(color1, color2, color3):
0475     for scl in [1, 2]:
0476         if scl == 2:
0477             ending = '@2.png'
0478         else:
0479             ending = '.png'
0480         slider = Assets(30, 20, scl)
0481         slider.rounded_rectancle(color1, 30, 10, 0, 5, 5, 1)
0482         slider.save('scrollbar-slider-horizontal-active' + ending)
0483 
0484         slider = Assets(30, 20, scl)
0485         slider.rounded_rectancle(color2, 30, 6, 0, 7, 3, 1)
0486         slider.save('scrollbar-slider-horizontal-hover' + ending)
0487 
0488         slider = Assets(30, 20, scl)
0489         slider.rounded_rectancle(color3, 30, 6, 0, 7, 3, 0.4)
0490         slider.save('scrollbar-slider-horizontal' + ending)
0491 
0492         slider = Assets(20, 30, scl)
0493         slider.rounded_rectancle(color1, 10, 30, 5, 0, 5, 1)
0494         slider.save('scrollbar-slider-vertical-active' + ending)
0495 
0496         slider = Assets(20, 30, scl)
0497         slider.rounded_rectancle(color2, 6, 30, 7, 0, 3, 1)
0498         slider.save('scrollbar-slider-vertical-hover' + ending)
0499 
0500         slider = Assets(20, 30, scl)
0501         slider.rounded_rectancle(color3, 6, 30, 7, 0, 3, 0.4)
0502         slider.save('scrollbar-slider-vertical' + ending)
0503 
0504 
0505 def scrollbar_trough(color):
0506     for scl in [1, 2]:
0507         if scl == 2:
0508             ending = '@2.png'
0509         else:
0510             ending = '.png'
0511         trough = Assets(56, 20, scl)
0512         trough.rounded_rectancle(color, 49, 6, 3.5, 7, 3, 0.3)
0513         trough.save('scrollbar-trough-horizontal' + ending)
0514 
0515         trough = Assets(20, 56, scl)
0516         trough.rounded_rectancle(color, 6, 49, 7, 3.5, 3, 0.3)
0517         trough.save('scrollbar-trough-vertical' + ending)
0518 
0519 
0520 def titlebuttons(color1, color2, state):
0521     for scl in [1, 2]:
0522         if scl == 2:
0523             ending = '@2.png'
0524         else:
0525             ending = '.png'
0526         title_minimize = Assets(18, 18, scl)
0527         title_maximize = Assets(18, 18, scl)
0528         title_maximized = Assets(18, 18, scl)
0529         if state == '' or state == '-backdrop':
0530             title_minimize.minimize(color1)
0531             title_maximize.maximize(color1)
0532             title_maximized.maximize_maximized(color1)
0533         else:
0534             title_minimize.circle(color1, 9, 9, 9)
0535             title_maximize.circle(color1, 9, 9, 9)
0536             title_maximized.circle(color1, 9, 9, 9)
0537             title_minimize.minimize()
0538             title_maximize.maximize()
0539             title_maximized.maximize_maximized()
0540         title_minimize.save('titlebutton-minimize' + state + ending)
0541         title_maximize.save('titlebutton-maximize' + state + ending)
0542         title_maximized.save('titlebutton-maximize-maximized' + state + ending)
0543 
0544         title_close = Assets(18, 18, scl)
0545         title_close.circle(color2, 9, 9, 9)
0546         title_close.close()
0547         title_close.save('titlebutton-close' + state + ending)
0548 
0549 
0550 def entry(color1, color2, color3, state, alpha=1.0):
0551     entry = Assets(20, 20)
0552     entry.background(color1)
0553     entry.rounded_rectancle(color2, 18, 18, 1, 1, 3, alpha=alpha)
0554     entry.rounded_rectancle(color3, 16, 16, 2, 2, 2)
0555     entry.rounded_rectancle(color3, 16, 16, 2, 2, 2)
0556     entry.save('entry' + state + '.png')
0557 
0558     entry = Assets(20, 20, rotation=1)
0559     entry.background(color1)
0560     entry.tab(color2, 18, 19, 1, 0, 3, alpha=alpha)
0561     entry.tab(color3, 16, 18, 2, 0, 2)
0562     entry.save('combo-entry' + state + '.png')
0563 
0564     entry_button = Assets(20, 20, rotation=3)
0565     entry_button.background(color1)
0566     entry_button.tab(color2, 18, 19, 1, 0, 3, alpha=alpha)
0567     entry_button.tab(color3, 16, 18, 2, 0, 2)
0568     entry_button.save('combo-entry-button' + state + '.png')
0569 
0570     if state != '-active':
0571         direction = ['-down', '-down-rtl', '-up-rtl', '-up']
0572         for i in range(0, 4):
0573             spin = Assets(20, 20, rotation=i)
0574             spin.background(color1)
0575             spin.spinbutton(color2, 19, 19, 0, 0, 3, alpha=alpha)
0576             spin.spinbutton(color3, 18, 18, 0, 0, 2)
0577             spin.save('spinbutton' + direction[i] + state + '.png')
0578 
0579 
0580 def mixed(color1, color2, color3):
0581     nll = Assets(20, 20)
0582     nll.save('null.png')
0583 
0584     # Frame
0585     frame = Assets(20, 20)
0586     frame.rounded_rectancle(color1, 20, 20, 0, 0, 3)
0587     frame.rounded_rectancle(color2, 18, 18, 1, 1, 2)
0588     frame.save('frame.png')
0589 
0590     # Tree header
0591     header = Assets(20, 20)
0592     header.background(color2)
0593     header.line(color1, 0, 19, 20, 1)
0594     header.line(color1, 19, 0, 1, 20)
0595     header.save('tree-header.png')
0596 
0597     # Notebook gap
0598     notebook_gap = Assets(4, 2)
0599     notebook_gap.line(color2, 1, 0, 2, 2)
0600     notebook_gap.save('notebook-gap-horizontal.png')
0601 
0602     notebook_gap = Assets(2, 4)
0603     notebook_gap.line(color2, 0, 1, 2, 2)
0604     notebook_gap.save('notebook-gap-vertical.png')
0605 
0606     # Notebook frame
0607     direction = ['-top', '-right', '-bottom', '-bottom']
0608     for i in range(0, 4):
0609         notebook_frame = Assets(20, 20, rotation=i)
0610         notebook_frame.notebook(color1, 20, 20, 0, 0, 3)
0611         notebook_frame.notebook(color2, 18, 18, 1, 1, 2)
0612         notebook_frame.save('notebook-frame' + direction[i] + '.png')
0613 
0614     # Frame gap
0615     frame_gap = Assets(2, 1)
0616     frame_gap.line(color1, 1, 0, 1, 1)
0617     frame_gap.save('frame-gap-start.png')
0618 
0619     frame_gap = Assets(2, 1)
0620     frame_gap.line(color1, 0, 0, 1, 1)
0621     frame_gap.save('frame-gap-end.png')
0622 
0623     # Lines
0624     lines = Assets(20, 1)
0625     lines.line(color1, 0, 0, 20, 1)
0626     lines.save('line-h.png')
0627 
0628     lines = Assets(1, 20)
0629     lines.line(color1, 0, 0, 1, 20)
0630     lines.save('line-v.png')
0631 
0632     lines = Assets(20, 1)
0633     lines.line(color2, 0, 0, 20, 1)
0634     lines.save('handle-h.png')
0635 
0636     lines = Assets(1, 20)
0637     lines.line(color2, 0, 0, 1, 20)
0638     lines.save('handle-v.png')
0639 
0640     menubar = Assets(20, 20)
0641     menubar.line(color3, 1, 1, 18, 18)
0642     menubar.save('menubar-button.png')
0643 
0644 
0645 def toolbar(color1, color2, color3):
0646     # Toolbar background
0647     bar = Assets(20, 20)
0648     bar.background(color2)
0649     bar.save('toolbar-background.png')
0650 
0651     # Toolbutton toggled
0652     toolbutton = Assets(20, 20)
0653     toolbutton.rounded_rectancle(color1, 18, 18, 1, 1, 3)
0654     toolbutton.save('toolbutton-toggled.png')
0655 
0656     # Toolbutton hover
0657     toolbutton = Assets(20, 20)
0658     toolbutton.rounded_rectancle(color3, 18, 18, 1, 1, 3)
0659     toolbutton.rounded_rectancle(color2, 16, 16, 2, 2, 2)
0660     toolbutton.save('toolbutton-hover.png')
0661 
0662     # Toolbutton active
0663     toolbutton = Assets(20, 20)
0664     toolbutton.rounded_rectancle(color3, 18, 18, 1, 1, 3)
0665     toolbutton.save('toolbutton-active.png')
0666 
0667 
0668 def progressbar(color1, color2, state=''):
0669     bar = Assets(10, 10)
0670     bar.rounded_rectancle(color1, 10, 10, 0, 0, 3)
0671     bar.save('progressbar-bar' + state + '.png')
0672 
0673     trough = Assets(10, 10)
0674     trough.rounded_rectancle(color2, 10, 10, 0, 0, 3)
0675     trough.save('progressbar-trough' + state + '.png')
0676 
0677 
0678 def html(color):
0679     return '#%02x%02x%02x' % (int(color[0]*255),
0680                               int(color[1]*255),
0681                               int(color[2]*255))
0682 
0683 
0684 def mix(color, mix_color, amount):
0685     r = color[0] * amount + mix_color[0] * (1 - amount)
0686     g = color[1] * amount + mix_color[1] * (1 - amount)
0687     b = color[2] * amount + mix_color[2] * (1 - amount)
0688     return (r, g, b)
0689 # ___________________________________________________________________________________
0690 
0691 
0692 parser = argparse.ArgumentParser(
0693     description='Generates Breeze assets according to the specified color '
0694                 'scheme.')
0695 parser.add_argument('--colorscheme', '-c', action='store',
0696                     default='/usr/share/color-schemes/BreezeLight.colors',
0697                     help='color scheme to use')
0698 parser.add_argument('--basecolorscheme', '-b', action='store',
0699                     default='/usr/share/color-schemes/BreezeLight.colors',
0700                     help='base color scheme')
0701 
0702 parser.add_argument('--assets-dir', '-a', action='store',
0703                     default='assets',
0704                     help='location of the directory to place assets')
0705 parser.add_argument('--gtk2-dir', '-g', action='store', default='gtk2',
0706                     help='location of gtk2 directory to define the color '
0707                          'scheme variables')
0708 parser.add_argument('--gtk3-scss-dir', '-G', action='store', default='.',
0709                     help='location of global.scss to define the color '
0710                          'scheme variables')
0711 
0712 args = parser.parse_args()
0713 
0714 assets_path = args.assets_dir
0715 make_sure_path_exists(assets_path)
0716 
0717 _colors = ReadKdeGlobals(args.basecolorscheme).read_globals(args.colorscheme)
0718 
0719 border_color = Color(_colors, 'WindowBackgroundNormal',
0720                      'WindowForegroundNormal', 0.75)
0721 window_bg = Color(_colors, 'WindowBackgroundNormal')
0722 window_fg = Color(_colors, 'WindowForegroundNormal')
0723 check_color = Color(_colors, 'WindowBackgroundNormal',
0724                     'WindowForegroundNormal', 0.5)
0725 button_bg = Color(_colors, 'ButtonBackgroundNormal')
0726 button_fg = Color(_colors, 'ButtonForegroundNormal')
0727 button_hover = Color(_colors, 'ButtonDecorationHover')
0728 button_active = Color(_colors, 'ButtonDecorationFocus')
0729 selection_bg = Color(_colors, 'SelectionBackgroundNormal')
0730 selection_fg = Color(_colors, 'SelectionForegroundNormal')
0731 view_bg = Color(_colors, 'ViewBackgroundNormal')
0732 view_fg = Color(_colors, 'ViewForegroundNormal')
0733 view_hover = Color(_colors, 'ViewDecorationHover')
0734 view_active = Color(_colors, 'ViewDecorationFocus')
0735 titlebutton = Color(_colors, 'WMactiveForeground')
0736 titlebutton_active = Color(_colors, 'WMactiveForeground')
0737 closebutton_hover = Color(_colors, 'ViewForegroundNegative')
0738 closebutton_hover.lighten_color(0.5)
0739 closebutton_active = Color(_colors, 'ViewForegroundNegative')
0740 titlebutton_inactive = Color(_colors, 'WMinactiveForeground')
0741 titlebutton_inactive_active = Color(_colors, 'WMinactiveForeground')
0742 tooltip_fg = Color(_colors, 'TooltipForegroundNormal')
0743 tooltip_bg = Color(_colors, 'TooltipBackgroundNormal')
0744 
0745 check_items(check_color.rgb, window_bg.rgb, '')
0746 check_items(button_hover.rgb, window_bg.rgb, '-hover')
0747 check_items(button_active.rgb, window_bg.rgb, '-active')
0748 check_items(check_color.insensitive, window_bg.rgb,
0749             '-insensitive', border_color.insensitive_alpha)
0750 check_items(check_color.inactive, window_bg.rgb,
0751             '-backdrop', border_color.inactive_alpha)
0752 check_items(check_color.inactive_insensitive, window_bg.rgb,
0753             '-backdrop-insensitive', border_color.inactive_insensitive_alpha)
0754 
0755 buttons(window_bg.rgb, border_color.rgb, button_bg.gradient(), '')
0756 buttons(window_bg.rgb, button_hover.rgb, button_bg.gradient(), '-hover')
0757 buttons(window_bg.rgb, button_hover.rgb,
0758         button_hover.gradient('active'), '-active')
0759 buttons(window_bg.rgb, border_color.rgb,
0760         button_bg.gradient(alpha=button_bg.insensitive_alpha), '-insensitive',
0761         border_color.insensitive_alpha)
0762 
0763 togglebuttons(window_bg.rgb, border_color.rgb, button_bg.gradient(), '')
0764 togglebuttons(window_bg.rgb, button_hover.rgb, button_bg.gradient(), '-hover')
0765 togglebuttons(window_bg.rgb, button_hover.rgb,
0766               button_hover.gradient('active'), '-active')
0767 togglebuttons(window_bg.rgb, border_color.rgb,
0768               button_bg.gradient(alpha=button_bg.insensitive_alpha),
0769               '-insensitive', border_color.insensitive_alpha)
0770 
0771 scale_slider(window_bg.rgb, border_color.rgb, button_bg.gradient(), '')
0772 scale_slider(window_bg.rgb, button_hover.rgb, button_bg.gradient(), '-hover')
0773 scale_slider(window_bg.rgb, button_active.rgb, button_bg.gradient(), '-active')
0774 scale_slider(window_bg.rgb, border_color.rgb,
0775              button_bg.gradient(alpha=button_bg.insensitive_alpha),
0776              '-insensitive', border_color.insensitive_alpha)
0777 scale_trough(border_color.rgb)
0778 
0779 tabs(border_color.rgb, window_bg.rgb, '-active')
0780 tabs(window_fg.rgb, window_bg.rgb, '-inactive')
0781 
0782 arrows(button_fg.rgb, '')
0783 arrows(button_hover.rgb, '-hover')
0784 arrows(button_active.rgb, '-active')
0785 arrows(button_fg.insensitive, '-insensitive', button_fg.insensitive_alpha)
0786 menu_arrow(window_fg.rgb, '')
0787 menu_arrow(selection_fg.rgb, '-selected')
0788 menu_arrow(window_fg.insensitive, '-insensitive', window_fg.insensitive_alpha)
0789 
0790 scrollbar_slider(view_active.rgb, view_hover.rgb, view_fg.rgb)
0791 scrollbar_trough(window_fg.rgb)
0792 
0793 titlebuttons(titlebutton.rgb, titlebutton.rgb, '')
0794 titlebuttons(titlebutton.rgb, closebutton_hover.rgb, '-hover')
0795 titlebuttons(titlebutton_active.rgb, closebutton_active.rgb, '-active')
0796 titlebuttons(titlebutton_inactive.rgb, titlebutton_inactive.rgb, '-backdrop')
0797 titlebuttons(titlebutton_inactive.rgb,
0798              closebutton_hover.rgb, '-hover-backdrop')
0799 titlebuttons(titlebutton_inactive_active.rgb,
0800              closebutton_active.rgb, '-active-backdrop')
0801 
0802 entry(window_bg.rgb, border_color.rgb, view_bg.rgb, '')
0803 entry(window_bg.rgb, view_active.rgb, view_bg.rgb, '-active')
0804 entry(window_bg.rgb, border_color.insensitive, None,
0805       '-insensitive', border_color.insensitive_alpha)
0806 
0807 progressbar(selection_bg.rgb, mix(window_fg.rgb, window_bg.rgb, 0.3))
0808 
0809 mixed(border_color.rgb, window_bg.rgb, button_active.rgb)
0810 
0811 toolbar(border_color.rgb, window_bg.rgb, button_hover.rgb)
0812 
0813 gtk2 = open(os.path.join(args.gtk2_dir, 'gtkrc'), 'w')
0814 gtk2.write(
0815     '# Theme:       Breeze-gtk\n'
0816     '# Description: Breeze theme for GTK+2.0\n'
0817     '\n'
0818     'gtk-color-scheme = "text_color:' + html(window_fg.rgb) + '"\n'
0819     'gtk-color-scheme = "base_color:' + html(view_bg.rgb) + '"\n'
0820     'gtk-color-scheme = "insensitive_base_color:' +
0821     html(view_bg.insensitive) + '"\n'
0822     'gtk-color-scheme = "fg_color:' + html(window_fg.rgb) + '"\n'
0823     'gtk-color-scheme = "bg_color:' + html(window_bg.rgb) + '"\n'
0824     'gtk-color-scheme = "selected_fg_color:' + html(selection_fg.rgb) + '"\n'
0825     'gtk-color-scheme = "selected_bg_color:' + html(selection_bg.rgb) + '"\n'
0826     'gtk-color-scheme = "button_fg_color:' + html(button_fg.rgb) + '"\n'
0827     'gtk-color-scheme = "tooltip_fg_color:' + html(tooltip_fg.rgb) + '"\n'
0828     'gtk-color-scheme = "tooltip_bg_color:' + html(tooltip_bg.rgb) + '"\n'
0829     'gtk-color-scheme = "insensitive_fg_color:' +
0830     html(mix(window_fg.insensitive, window_bg.rgb,
0831              window_fg.insensitive_alpha)) + '"\n'
0832     'gtk-color-scheme = "insensitive_text_color:' +
0833     html(mix(view_fg.insensitive, view_bg.rgb,
0834              view_fg.insensitive_alpha)) + '"\n'
0835     'gtk-color-scheme = "button_insensitive_fg_color:' +
0836     html(mix(button_fg.insensitive, button_bg.rgb,
0837              button_fg.insensitive_alpha)) + '"\n'
0838     'gtk-color-scheme = "button_active:' + html(button_active.rgb) + '"\n'
0839     'gtk-color-scheme = "border_color:' + html(border_color.rgb) + '"\n'
0840     '\n'
0841     'include "widgets/default"\n'
0842     'include "widgets/buttons"\n'
0843     'include "widgets/menu"\n'
0844     'include "widgets/entry"\n'
0845     'include "widgets/notebook"\n'
0846     'include "widgets/range"\n'
0847     'include "widgets/scrollbar"\n'
0848     'include "widgets/toolbar"\n'
0849     'include "widgets/progressbar"\n'
0850     'include "widgets/misc"\n'
0851     'include "widgets/styles"\n'
0852 )
0853 gtk2.close()
0854 
0855 gtk3 = open(os.path.join(args.gtk3_scss_dir, '_global.scss'), 'w')
0856 for key in sorted(_colors):
0857     if key == 'DisabledColor' or key == 'InactiveColor':
0858         gtk3.write('${0}:rgb({1});\n'.format(key, _colors[key]))
0859     elif 'Disabled' in key or 'Inactive' in key:
0860         gtk3.write('${0}:{1};\n'.format(key, _colors[key]))
0861     elif re.match('[0-9]+,[0-9]+,[0-9]+', _colors[key]):
0862         gtk3.write('${0}:rgb({1});\n'.format(key, _colors[key]))
0863 gtk3.close()