1# This file is part of MyPaint.
2# Copyright (C) 2015 by Andrew Chadwick <a.t.chadwick@gmail.com>
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2 of the License, or
7# (at your option) any later version.
8
9
10"""UIColor conversion routines
11
12These are functions which convert
13our display color classes (see `lib.color.UIColor`)
14to and from GDK's equivalents.
15They can't be part of lib/ because of the GDK dependency.
16
17"""
18
19from __future__ import division, print_function
20
21import struct
22
23from lib.gibindings import Gdk
24
25from lib.color import RGBColor
26from lib.helpers import clamp
27
28
29def from_gdk_color(gdk_color):
30    """Construct a new UIColor from a Gdk.Color.
31
32    >>> from_gdk_color(Gdk.Color(0.0000, 0x8000, 0xffff))
33    <RGBColor r=0.0000, g=0.5000, b=1.0000>
34
35    """
36    rgb16 = (gdk_color.red, gdk_color.green, gdk_color.blue)
37    return RGBColor(*[c / 65535 for c in rgb16])
38
39
40def to_gdk_color(color):
41    """Convert a UIColor to a Gdk.Color.
42
43    >>> gcol = to_gdk_color(RGBColor(1,1,1))
44    >>> gcol.to_string()
45    '#ffffffffffff'
46
47    """
48    return Gdk.Color(*[int(c*65535) for c in color.get_rgb()])
49
50
51def from_gdk_rgba(gdk_rgba):
52    """Construct a new UIColor from a `Gdk.RGBA` (omitting alpha)
53
54    >>> from_gdk_rgba(Gdk.RGBA(0.5, 0.8, 0.2, 1))
55    <RGBColor r=0.5000, g=0.8000, b=0.2000>
56
57    """
58    rgbflt = (gdk_rgba.red, gdk_rgba.green, gdk_rgba.blue)
59    return RGBColor(*[clamp(c, 0., 1.) for c in rgbflt])
60
61
62def to_gdk_rgba(color):
63    """Convert to a `GdkRGBA` (with alpha=1.0).
64
65    >>> col = RGBColor(1,1,1)
66    >>> rgba = to_gdk_rgba(col)
67    >>> rgba.to_string()
68    'rgb(255,255,255)'
69
70    """
71    rgba = list(color.get_rgb())
72    rgba.append(1.0)
73    return Gdk.RGBA(*rgba)
74
75
76def from_drag_data(bytes):
77    """Construct from drag+dropped bytes of type application/x-color.
78
79    The data format is 8 bytes, RRGGBBAA, with assumed native endianness.
80    Alpha is ignored.
81    """
82    r, g, b, a = [h / 0xffff for h in struct.unpack("=HHHH", bytes)]
83    return RGBColor(r, g, b)
84    # TODO: check endianness
85
86
87def to_drag_data(color):
88    """Converts to bytes for dragging as application/x-color."""
89    rgba = [int(c * 0xffff) for c in color.get_rgb()]
90    rgba.append(0xffff)
91    return struct.pack("=HHHH", *rgba)
92
93
94def _test():
95    import doctest
96    doctest.testmod()
97
98
99if __name__ == '__main__':
100    _test()
101
102