if self.type == NUMBER:<EOL><INDENT>try:<EOL><INDENT>return clamp(self.min, self.max, float(val))<EOL><DEDENT>except ValueError:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT><DEDENT>elif self.type == TEXT:<EOL><INDENT>try:<EOL><INDENT>return unicode(str(val), "<STR_LIT>", "<STR_LIT:replace>")<EOL><DEDENT>except:<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT><DEDENT>elif self.type == BOOLEAN:<EOL><INDENT>if unicode(val).lower() in ("<STR_LIT:true>", "<STR_LIT:1>", "<STR_LIT:yes>"):<EOL><INDENT>return True<EOL><DEDENT>else:<EOL><INDENT>return False<EOL><DEDENT><DEDENT>

Given a Variable and a value, cleans it out


if self.type == v.type:<EOL><INDENT>if self.type == NUMBER:<EOL><INDENT>if self.value < self.min or self.value > self.max:<EOL><INDENT>return False<EOL><DEDENT><DEDENT>return True<EOL><DEDENT>return False<EOL>

Return whether I am compatible with the given var:
             - Type should be the same
             - My value should be inside the given vars' min/max range.


def _append_element(self, render_func, pe):

self._render_funcs.append(render_func)<EOL>self._elements.append(pe)<EOL>

Append a render function and the parameters to pass
an equivilent PathElement, or the PathElement itself.


for render_func in self._render_funcs:<EOL><INDENT>render_func(cairo_ctx)<EOL><DEDENT>


if self._bounds:<EOL><INDENT>return self._bounds<EOL><DEDENT>record_surface = cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, (-<NUM_LIT:1>, -<NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:1>))<EOL>dummy_ctx = cairo.Context(record_surface)<EOL>self._traverse(dummy_ctx)<EOL>self._bounds = dummy_ctx.path_extents()<EOL>return self._bounds<EOL>

Return cached bounds of this Grob.
If bounds are not cached, render to a meta surface, and
keep the meta surface and bounds cached.


if self._bounds:<EOL><INDENT>return self._bounds<EOL><DEDENT>record_surface = cairo.RecordingSurface(cairo.CONTENT_COLOR_ALPHA, (-<NUM_LIT:1>, -<NUM_LIT:1>, <NUM_LIT:1>, <NUM_LIT:1>))<EOL>dummy_ctx = cairo.Context(record_surface)<EOL>self._traverse(dummy_ctx)<EOL>in_fill = dummy_ctx.in_fill(x, y)<EOL>return in_fill<EOL>


if self._center:<EOL><INDENT>return self._center<EOL><DEDENT>(x1, y1, x2, y2) = self._get_bounds()<EOL>x = (x1 + x2) / <NUM_LIT:2><EOL>y = (y1 + y2) / <NUM_LIT:2><EOL>center = self._center = x, y<EOL>return center<EOL>


fillcolor = self.fill<EOL>strokecolor = self.stroke<EOL>strokewidth = self.strokewidth<EOL>def _render(cairo_ctx):<EOL><INDENT>'''<STR_LIT>'''<EOL>transform = self._call_transform_mode(self._transform)<EOL>if fillcolor is None and strokecolor is None:<EOL><INDENT>return<EOL><DEDENT>cairo_ctx.set_matrix(transform)<EOL>self._traverse(cairo_ctx)<EOL>cairo_ctx.set_matrix(cairo.Matrix())<EOL>if fillcolor is not None and strokecolor is not None:<EOL><INDENT>if strokecolor[<NUM_LIT:3>] < <NUM_LIT:1>:<EOL><INDENT>cairo_ctx.push_group()<EOL>cairo_ctx.set_source_rgba(*fillcolor)<EOL>cairo_ctx.fill_preserve()<EOL>e = cairo_ctx.stroke_extents()<EOL>cairo_ctx.set_source_rgba(*strokecolor)<EOL>cairo_ctx.set_operator(cairo.OPERATOR_SOURCE)<EOL>cairo_ctx.set_line_width(strokewidth)<EOL>cairo_ctx.stroke()<EOL>cairo_ctx.pop_group_to_source()<EOL>cairo_ctx.paint()<EOL><DEDENT>else:<EOL><INDENT>cairo_ctx.set_source_rgba(*fillcolor)<EOL>cairo_ctx.fill_preserve()<EOL>cairo_ctx.set_source_rgba(*strokecolor)<EOL>cairo_ctx.set_line_width(strokewidth)<EOL>cairo_ctx.stroke()<EOL><DEDENT><DEDENT>elif fillcolor is not None:<EOL><INDENT>cairo_ctx.set_source_rgba(*fillcolor)<EOL>cairo_ctx.fill()<EOL><DEDENT>elif strokecolor is not None:<EOL><INDENT>cairo_ctx.set_source_rgba(*strokecolor)<EOL>cairo_ctx.set_line_width(strokewidth)<EOL>cairo_ctx.stroke()<EOL><DEDENT><DEDENT>return _render<EOL>

Use a closure so that draw attributes can be saved


<EOL>contours = []<EOL>current_contour = None<EOL>empty = True<EOL>for i, el in enumerate(self._get_elements()):<EOL><INDENT>if el.cmd == MOVETO:<EOL><INDENT>if not empty:<EOL><INDENT>contours.append(current_contour)<EOL><DEDENT>current_contour = BezierPath(self._bot)<EOL>current_contour.moveto(el.x, el.y)<EOL>empty = True<EOL><DEDENT>elif el.cmd == LINETO:<EOL><INDENT>empty = False<EOL>current_contour.lineto(el.x, el.y)<EOL><DEDENT>elif el.cmd == CURVETO:<EOL><INDENT>empty = False<EOL>current_contour.curveto(el.c1x, el.c1y, el.c2x, el.c2y, el.x, el.y)<EOL><DEDENT>elif el.cmd == CLOSE:<EOL><INDENT>current_contour.closepath()<EOL><DEDENT><DEDENT>if not empty:<EOL><INDENT>contours.append(current_contour)<EOL><DEDENT>return contours<EOL>

Returns a list of contours in the path, as BezierPath objects.
A contour is a sequence of lines and curves separated from the next contour by a MOVETO.
For example, the glyph "o" has two contours: the inner circle and the outer circle.


<EOL>if segments is None:<EOL><INDENT>segments = self._segment_lengths(relative=True)<EOL><DEDENT>if len(segments) == <NUM_LIT:0>:<EOL><INDENT>raise PathError("<STR_LIT>")<EOL><DEDENT>for i, el in enumerate(self._get_elements()):<EOL><INDENT>if i == <NUM_LIT:0> or el.cmd == MOVETO:<EOL><INDENT>closeto = Point(el.x, el.y)<EOL><DEDENT>if t <= segments[i] or i == len(segments) - <NUM_LIT:1>:<EOL><INDENT>break<EOL><DEDENT>else:<EOL><INDENT>t -= segments[i]<EOL><DEDENT><DEDENT>try:<EOL><INDENT>t /= segments[i]<EOL><DEDENT>except ZeroDivisionError:<EOL><INDENT>pass<EOL><DEDENT>if i == len(segments) - <NUM_LIT:1> and segments[i] == <NUM_LIT:0>:<EOL><INDENT>i -= <NUM_LIT:1><EOL><DEDENT>return (i, t, closeto)<EOL>

Locates t on a specific segment in the path.
            Returns (index, t, PathElement)
            A path is a combination of lines and curves (segments).
            The returned index indicates the start of the segment that contains point t.
            The returned t is the absolute time on that segment,
            in contrast to the relative t on the whole of the path.
            The returned point is the last MOVETO, any subsequent CLOSETO after i closes to that point.
            When you supply the list of segment lengths yourself, as returned from length(path, segmented=True),
            point() works about thirty times faster in a for-loop since it doesn't need to recalculate
            the length during each iteration.


<EOL>if len(self._elements) == <NUM_LIT:0>:<EOL><INDENT>raise PathError("<STR_LIT>")<EOL><DEDENT>if self._segments is None:<EOL><INDENT>self._segments = self._get_length(segmented=True, precision=<NUM_LIT:10>)<EOL><DEDENT>i, t, closeto = self._locate(t, segments=self._segments)<EOL>x0, y0 = self[i].x, self[i].y<EOL>p1 = self[i + <NUM_LIT:1>]<EOL>if p1.cmd == CLOSE:<EOL><INDENT>x, y = self._linepoint(t, x0, y0, closeto.x, closeto.y)<EOL>return PathElement(LINETO, x, y)<EOL><DEDENT>elif p1.cmd in (LINETO, MOVETO):<EOL><INDENT>x1, y1 = p1.x, p1.y<EOL>x, y = self._linepoint(t, x0, y0, x1, y1)<EOL>return PathElement(LINETO, x, y)<EOL><DEDENT>elif p1.cmd == CURVETO:<EOL><INDENT>x3, y3, x1, y1, x2, y2 = p1.x, p1.y, p1.ctrl1.x, p1.ctrl1.y, p1.ctrl2.x, p1.ctrl2.y<EOL>x, y, c1x, c1y, c2x, c2y = self._curvepoint(t, x0, y0, x1, y1, x2, y2, x3, y3)<EOL>return PathElement(CURVETO, c1x, c1y, c2x, c2y, x, y)<EOL><DEDENT>else:<EOL><INDENT>raise PathError("<STR_LIT>" % (p1.cmd, p1))<EOL><DEDENT>

Returns the PathElement at time t (0.0-1.0) on the path.

Returns coordinates for point at t on the path.
Gets the length of the path, based on the length of each curve and line in the path.
Determines in what segment t falls. Gets the point on that segment.
When you supply the list of segment lengths yourself, as returned from length(path, segmented=True),
point() works about thirty times faster in a for-loop since it doesn't need to recalculate
the length during each iteration.


def points(self, amount=<NUM_LIT:100>, start=<NUM_LIT:0.0>, end=<NUM_LIT:1.0>, segments=None):

<EOL>if len(self._elements) == <NUM_LIT:0>:<EOL><INDENT>raise PathError("<STR_LIT>")<EOL><DEDENT>n = end - start<EOL>d = n<EOL>if amount > <NUM_LIT:1>:<EOL><INDENT>d = float(n) / (amount - <NUM_LIT:1>)<EOL><DEDENT>for i in range(int(amount)):<EOL><INDENT>yield self.point(start + d * i, segments)<EOL><DEDENT>

Returns an iterator with a list of calculated points for the path.
            To omit the last point on closed paths: end=1-1.0/amount


def _linepoint(self, t, x0, y0, x1, y1):

<EOL>out_x = x0 + t * (x1 - x0)<EOL>out_y = y0 + t * (y1 - y0)<EOL>return (out_x, out_y)<EOL>

Returns coordinates for point at t on the line.
            Calculates the coordinates of x and y for a point at t on a straight line.
            The t parameter is a number between 0.0 and 1.0,
            x0 and y0 define the starting point of the line,
            x1 and y1 the ending point of the line.


<EOL>a = pow(abs(x0 - x1), <NUM_LIT:2>)<EOL>b = pow(abs(y0 - y1), <NUM_LIT:2>)<EOL>return sqrt(a + b)<EOL>


def _curvepoint(self, t, x0, y0, x1, y1, x2, y2, x3, y3, handles=False):

<EOL>mint = <NUM_LIT:1> - t<EOL>x01 = x0 * mint + x1 * t<EOL>y01 = y0 * mint + y1 * t<EOL>x12 = x1 * mint + x2 * t<EOL>y12 = y1 * mint + y2 * t<EOL>x23 = x2 * mint + x3 * t<EOL>y23 = y2 * mint + y3 * t<EOL>out_c1x = x01 * mint + x12 * t<EOL>out_c1y = y01 * mint + y12 * t<EOL>out_c2x = x12 * mint + x23 * t<EOL>out_c2y = y12 * mint + y23 * t<EOL>out_x = out_c1x * mint + out_c2x * t<EOL>out_y = out_c1y * mint + out_c2y * t<EOL>if not handles:<EOL><INDENT>return (out_x, out_y, out_c1x, out_c1y, out_c2x, out_c2y)<EOL><DEDENT>else:<EOL><INDENT>return (out_x, out_y, out_c1x, out_c1y, out_c2x, out_c2y, x01, y01, x23, y23)<EOL><DEDENT>

Returns coordinates for point at t on the spline.
            Calculates the coordinates of x and y for a point at t on the cubic bezier spline,
            and its control points, based on the de Casteljau interpolation algorithm.
            The t parameter is a number between 0.0 and 1.0,
            x0 and y0 define the starting point of the spline,
            x1 and y1 its control point,
            x3 and y3 the ending point of the spline,
            x2 and y2 its control point.
            If the handles parameter is set, returns not only the point at t,
            but the modified control points of p0 and p3 should this point split the path as well.


def _curvelength(self, x0, y0, x1, y1, x2, y2, x3, y3, n=<NUM_LIT:20>):

<EOL>length = <NUM_LIT:0><EOL>xi = x0<EOL>yi = y0<EOL>for i in range(n):<EOL><INDENT>t = <NUM_LIT:1.0> * (i + <NUM_LIT:1>) / n<EOL>pt_x, pt_y, pt_c1x, pt_c1y, pt_c2x, pt_c2y =self._curvepoint(t, x0, y0, x1, y1, x2, y2, x3, y3)<EOL>c = sqrt(pow(abs(xi - pt_x), <NUM_LIT:2>) + pow(abs(yi - pt_y), <NUM_LIT:2>))<EOL>length += c<EOL>xi = pt_x<EOL>yi = pt_y<EOL><DEDENT>return length<EOL>

Returns the length of the spline.
            Integrates the estimated length of the cubic bezier spline defined by x0, y0, ... x3, y3,
            by adding the lengths of lineair lines between points at t.
            The number of points is defined by n
            (n=10 would add the lengths of lines between 0.0 and 0.1, between 0.1 and 0.2, and so on).
            The default n=20 is fine for most cases, usually resulting in a deviation of less than 0.01.


def _segment_lengths(self, relative=False, n=<NUM_LIT:20>):

<EOL>lengths = []<EOL>first = True<EOL>for el in self._get_elements():<EOL><INDENT>if first is True:<EOL><INDENT>close_x, close_y = el.x, el.y<EOL>first = False<EOL><DEDENT>elif el.cmd == MOVETO:<EOL><INDENT>close_x, close_y = el.x, el.y<EOL>lengths.append(<NUM_LIT:0.0>)<EOL><DEDENT>elif el.cmd == CLOSE:<EOL><INDENT>lengths.append(self._linelength(x0, y0, close_x, close_y))<EOL><DEDENT>elif el.cmd == LINETO:<EOL><INDENT>lengths.append(self._linelength(x0, y0, el.x, el.y))<EOL><DEDENT>elif el.cmd == CURVETO:<EOL><INDENT>x3, y3, x1, y1, x2, y2 = el.x, el.y, el.c1x, el.c1y, el.c2x, el.c2y<EOL>lengths.append(self._curvelength(x0, y0, x1, y1, x2, y2, x3, y3, n))<EOL><DEDENT>if el.cmd != CLOSE:<EOL><INDENT>x0 = el.x<EOL>y0 = el.y<EOL><DEDENT><DEDENT>if relative:<EOL><INDENT>length = sum(lengths)<EOL>try:<EOL><INDENT>return [l / length for l in lengths]<EOL><DEDENT>except ZeroDivisionError:<EOL><INDENT>return [<NUM_LIT:0.0>] * len(lengths)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>return lengths<EOL><DEDENT>

Returns a list with the lengths of each segment in the path.


def _get_length(self, segmented=False, precision=<NUM_LIT:10>):

<EOL>if not segmented:<EOL><INDENT>return sum(self._segment_lengths(n=precision), <NUM_LIT:0.0>)<EOL><DEDENT>else:<EOL><INDENT>return self._segment_lengths(relative=True, n=precision)<EOL><DEDENT>

Returns the length of the path.
            Calculates the length of each spline in the path, using n as a number of points to measure.
            When segmented is True, returns a list containing the individual length of each spline
            as values between 0.0 and 1.0, defining the relative length of each spline
            in relation to the total path length.


for index, el in enumerate(self._elements):<EOL><INDENT>if isinstance(el, tuple):<EOL><INDENT>el = PathElement(*el)<EOL>self._elements[index] = el<EOL><DEDENT>yield el<EOL><DEDENT>


if isinstance(item, slice):<EOL><INDENT>indices = item.indices(len(self))<EOL>return [self.__getitem__(i) for i in range(*indices)]<EOL><DEDENT>else:<EOL><INDENT>el = self._elements[item]<EOL>if isinstance(el, tuple):<EOL><INDENT>el = PathElement(*el)<EOL>self._elements[item] = el<EOL><DEDENT>return el<EOL><DEDENT>

el is either a PathElement or the parameters to pass
to one.
If el is a PathElement return it
If el is parameters, create a PathElement and return it


x = (self.x + self.width / <NUM_LIT:2>)<EOL>y = (self.y + self.height / <NUM_LIT:2>)<EOL>return (x, y)<EOL>

Returns the center point of the path, disregarding transforms.


<EOL>_ctx.push()<EOL>_fill =_ctx.fill()<EOL>_stroke = _ctx.stroke()<EOL>sc = (<NUM_LIT:1.0> / _ctx.HEIGHT) * float(y * <NUM_LIT:0.5>) * <NUM_LIT><EOL>_ctx.strokewidth(sc * <NUM_LIT>)<EOL>_ctx.stroke('<STR_LIT>')<EOL>_ctx.line(x + (sin(x * <NUM_LIT:0.1>) * <NUM_LIT>), y + <NUM_LIT>, x + sin(_ctx.FRAME * <NUM_LIT:0.1>), y)<EOL>_ctx.translate(-<NUM_LIT:20>, <NUM_LIT:0>)<EOL>_ctx.scale(sc)<EOL>_ctx.fill(color)<EOL>_ctx.nostroke()<EOL>for angle in xrange(<NUM_LIT:0>, <NUM_LIT>, <NUM_LIT>):<EOL><INDENT>_ctx.rotate(degrees=<NUM_LIT>)<EOL>_ctx.rect(x, y, <NUM_LIT>, <NUM_LIT:8>, <NUM_LIT:1>)<EOL><DEDENT>_ctx.fill('<STR_LIT>')<EOL>_ctx.ellipse(x + <NUM_LIT:15>, y, <NUM_LIT:10>, <NUM_LIT:10>)<EOL>_ctx.fill(_fill)<EOL>_ctx.stroke(_stroke)<EOL>_ctx.pop()<EOL>


def fft_bandpassfilter(data, fs, lowcut, highcut):

fft = np.fft.fft(data)<EOL>bp = fft.copy()<EOL>bp *= fft.dot(fft) / bp.dot(bp)<EOL>ibp = <NUM_LIT:12> * np.fft.ifft(bp)<EOL>return ibp<EOL>


_len = len(audio.spectrogram)<EOL>for i, v in enumerate(audio.spectrogram):<EOL><INDENT>yield scale * (i * v) / _len<EOL><DEDENT>

Produces a nicer graph, I'm not sure if this is correct


data = np.zeros(len(fft))<EOL>for i, v in enumerate(fft):<EOL><INDENT>data[i] = scale * (i * v) / NUM_SAMPLES<EOL><DEDENT>return data<EOL>


if self.running:<EOL><INDENT>self.running = False<EOL>self.join()<EOL><DEDENT>


def draw_cornu_flat(x0, y0, t0, t1, s0, c0, flip, cs, ss, cmd):

for j in range(<NUM_LIT:0>, <NUM_LIT:100>):<EOL><INDENT>t = j * <NUM_LIT><EOL>s, c = eval_cornu(t0 + t * (t1 - t0))<EOL>s *= flip<EOL>s -= s0<EOL>c -= c0<EOL>x = c * cs - s * ss<EOL>y = s * cs + c * ss<EOL>print_pt(x0 + x, y0 + y, cmd)<EOL>cmd = '<STR_LIT>'<EOL><DEDENT>return cmd<EOL>

Raph Levien's code draws fast LINETO segments.


def draw_cornu_bezier(x0, y0, t0, t1, s0, c0, flip, cs, ss, cmd, scale, rot):

s = None<EOL>for j in range(<NUM_LIT:0>, <NUM_LIT:5>):<EOL><INDENT>t = j * <NUM_LIT><EOL>t2 = t+ <NUM_LIT><EOL>curvetime = t0 + t * (t1 - t0)<EOL>curvetime2 = t0 + t2 * (t1 - t0)<EOL>Dt = (curvetime2 - curvetime) * scale<EOL>if not s:<EOL><INDENT>s, c = eval_cornu(curvetime)<EOL>s *= flip<EOL>s -= s0<EOL>c -= c0<EOL>dx1 =  cos(pow(curvetime, <NUM_LIT:2>) + (flip * rot))  <EOL>dy1 =  flip * sin(pow(curvetime, <NUM_LIT:2>) + (flip *rot))<EOL>x = ((c * cs - s * ss) +x0)<EOL>y = ((s * cs + c * ss) + y0)<EOL><DEDENT>s2,c2 = eval_cornu(curvetime2) <EOL>s2 *= flip<EOL>s2 -= s0<EOL>c2 -= c0<EOL>dx2 = cos(pow(curvetime2, <NUM_LIT:2>) + (flip * rot)) <EOL>dy2 = flip * sin(pow(curvetime2, <NUM_LIT:2>) + (flip * rot))<EOL>x3 = ((c2 * cs - s2 * ss)+x0)<EOL>y3 = ((s2 * cs + c2 * ss)+y0)<EOL>x1 = (x + ((Dt/<NUM_LIT>) * dx1))<EOL>y1 = (y + ((Dt/<NUM_LIT>) * dy1))   <EOL>x2 = (x3 - ((Dt/<NUM_LIT>) * dx2))<EOL>y2 = (y3 - ((Dt/<NUM_LIT>) * dy2))<EOL>if cmd == '<STR_LIT>':<EOL><INDENT>print_pt(x, y, cmd)<EOL>cmd = '<STR_LIT>'<EOL><DEDENT>print_crv(x1, y1, x2, y2, x3, y3)<EOL>dx1, dy1 = dx2, dy2<EOL>x,y = x3, y3<EOL><DEDENT>return cmd<EOL>

Mark Meyer's code draws elegant CURVETO segments.


def overlap(self, x1, y1, x2, y2, r=<NUM_LIT:5>):

if abs(x2-x1) < r and abs(y2-y1) < r:<EOL><INDENT>return True<EOL><DEDENT>else:<EOL><INDENT>return False<EOL><DEDENT>

Returns True when point 1 and point 2 overlap.

        There is an r treshold in which point 1 and point 2
        are considered to overlap.


rx = x0 - (x-x0)<EOL>ry = y0 - (y-y0)<EOL>return rx, ry<EOL>

Reflects the point x, y through origin x0, y0.


a = degrees( atan((y1-y0) / (x1-x0+<NUM_LIT>)) ) + <NUM_LIT><EOL>if x1-x0 < <NUM_LIT:0>: a += <NUM_LIT><EOL>return a<EOL>

Calculates the angle between two points.


return sqrt(pow(x1-x0, <NUM_LIT:2>) + pow(y1-y0, <NUM_LIT:2>))<EOL>

Calculates the distance between two points.


def coordinates(self, x0, y0, distance, angle):

x = x0 + cos(radians(angle)) * distance<EOL>y = y0 + sin(radians(angle)) * distance<EOL>return Point(x, y)<EOL>

Calculates the coordinates of a point from the origin.


def contains_point(self, x, y, d=<NUM_LIT:2>):

if self.path != None and len(self.path) > <NUM_LIT:1>and self.path.contains(x, y):<EOL><INDENT>if not self.path.contains(x+d, y)or not self.path.contains(x, y+d)or not self.path.contains(x-d, y)or not self.path.contains(x, y-d)or not self.path.contains(x+d, y+d)or not self.path.contains(x-d, y-d)or not self.path.contains(x+d, y-d)or not self.path.contains(x-d, y+d):<EOL><INDENT>return True<EOL><DEDENT><DEDENT>return False<EOL>

Returns true when x, y is on the path stroke outline.


try: <EOL><INDENT>bezier = _ctx.ximport("<STR_LIT>")<EOL><DEDENT>except:<EOL><INDENT>from nodebox.graphics import bezier<EOL><DEDENT>n = <NUM_LIT:100><EOL>closest = None<EOL>dx0 = float("<STR_LIT>") <EOL>dy0 = float("<STR_LIT>")<EOL>for i in range(n):<EOL><INDENT>t = float(i)/n<EOL>pt = self.path.point(t)<EOL>dx = abs(pt.x-x)<EOL>dy = abs(pt.y-y)<EOL>if dx+dy <= dx0+dy0:<EOL><INDENT>dx0 = dx<EOL>dy0 = dy<EOL>closest = t<EOL><DEDENT><DEDENT>decimals = [<NUM_LIT:3>,<NUM_LIT:4>]<EOL>for d in decimals:<EOL><INDENT>d = <NUM_LIT:1.0>/pow(<NUM_LIT:10>,d)<EOL>for i in range(<NUM_LIT:20>):<EOL><INDENT>t = closest-d + float(i)*d*<NUM_LIT:0.1><EOL>if t < <NUM_LIT:0.0>: t = <NUM_LIT:1.0>+t<EOL>if t > <NUM_LIT:1.0>: t = t-<NUM_LIT:1.0><EOL>pt = self.path.point(t)<EOL>dx = abs(pt.x-x)<EOL>dy = abs(pt.y-y)<EOL>if dx <= dx0 and dy <= dy0:<EOL><INDENT>dx0 = dx<EOL>dy0 = dy<EOL>closest_precise = t<EOL><DEDENT><DEDENT>closest = closest_precise   <EOL><DEDENT>p = bezier.insert_point(self.path, closest_precise)<EOL>i, t, pt = bezier._locate(self.path, closest_precise)<EOL>i += <NUM_LIT:1><EOL>pt = PathElement()<EOL>pt.cmd = p[i].cmd<EOL>pt.x = p[i].x<EOL>pt.y = p[i].y<EOL>pt.ctrl1 = Point(p[i].ctrl1.x, p[i].ctrl1.y)<EOL>pt.ctrl2 = Point(p[i].ctrl2.x, p[i].ctrl2.y)<EOL>pt.freehand = False<EOL>self._points.insert(i, pt)<EOL>self._points[i-<NUM_LIT:1>].ctrl1 = Point(p[i-<NUM_LIT:1>].ctrl1.x, p[i-<NUM_LIT:1>].ctrl1.y)<EOL>self._points[i+<NUM_LIT:1>].ctrl1 = Point(p[i+<NUM_LIT:1>].ctrl1.x, p[i+<NUM_LIT:1>].ctrl1.y)<EOL>self._points[i+<NUM_LIT:1>].ctrl2 = Point(p[i+<NUM_LIT:1>].ctrl2.x, p[i+<NUM_LIT:1>].ctrl2.y)<EOL>

Inserts a point on the path at the mouse location.

        We first need to check if the mouse location is on the path.
        Inserting point is time intensive and experimental.


x, y = mouse()<EOL>if self.show_grid:<EOL><INDENT>x, y = self.grid.snap(x, y)<EOL><DEDENT>if _ctx._ns["<STR_LIT>"]and not self.freehand:<EOL><INDENT>self._dirty = True<EOL>if self.edit != Noneand not self.drag_pointand not self.drag_handle1and not self.drag_handle2:<EOL><INDENT>pt = self._points[self.edit]<EOL>dx = pt.x+self.btn_x<EOL>dy = pt.y+self.btn_y<EOL>if self.overlap(dx, dy, x, y, r=self.btn_r):<EOL><INDENT>self.delete = self.edit<EOL>return<EOL><DEDENT>dx += self.btn_r*<NUM_LIT:2> + <NUM_LIT:2><EOL>if self.edit == len(self._points) -<NUM_LIT:1> andself.overlap(dx, dy, x, y, r=self.btn_r):<EOL><INDENT>self.moveto = self.edit<EOL>return<EOL><DEDENT><DEDENT>if self.insert:<EOL><INDENT>self.inserting = True<EOL>return<EOL><DEDENT>if not self.drag_point andnot self.drag_handle1 andnot self.drag_handle2:<EOL><INDENT>self.editing = False<EOL>indices = range(len(self._points))<EOL>indices.reverse()<EOL>for i in indices:<EOL><INDENT>pt = self._points[i]<EOL>if pt != self.newand self.overlap(x, y, pt.x, pt.y)and self.new == None:<EOL><INDENT>if self.edit == i+<NUM_LIT:1>and self.overlap(self._points[i+<NUM_LIT:1>].ctrl1.x,<EOL>self._points[i+<NUM_LIT:1>].ctrl1.y, x, y):<EOL><INDENT>continue<EOL><DEDENT>else:<EOL><INDENT>self.edit = i<EOL>self.editing = True<EOL>break<EOL><DEDENT><DEDENT><DEDENT><DEDENT>if not self.editing:<EOL><INDENT>if self.edit != None:<EOL><INDENT>pt = self._points[self.edit]<EOL>if self.overlap(pt.ctrl1.x, pt.ctrl1.y, x, y) orself.overlap(pt.ctrl2.x, pt.ctrl2.y, x, y):<EOL><INDENT>self.editing = True<EOL><DEDENT>else:<EOL><INDENT>self.edit = None<EOL><DEDENT><DEDENT><DEDENT>if self.edit == None:<EOL><INDENT>if self.new == None:<EOL><INDENT>self.new = PathElement()<EOL>if self.moveto == Trueor len(self._points) == <NUM_LIT:0>:<EOL><INDENT>cmd = MOVETO<EOL>self.moveto = None<EOL>self.last_moveto = self.new<EOL><DEDENT>else:<EOL><INDENT>cmd = CURVETO<EOL><DEDENT>self.new.cmd = cmd<EOL>self.new.x = x<EOL>self.new.y = y<EOL>self.new.ctrl1 = Point(x, y)<EOL>self.new.ctrl2 = Point(x, y)<EOL>self.new.freehand = False<EOL>if len(self._points) > <NUM_LIT:0>:<EOL><INDENT>prev = self._points[-<NUM_LIT:1>]<EOL>rx, ry = self.reflect(prev.x, prev.y, prev.ctrl2.x, prev.ctrl2.y)<EOL>self.new.ctrl1 = Point(rx, ry)<EOL><DEDENT>self._points.append(self.new)<EOL><DEDENT>else:<EOL><INDENT>rx, ry = self.reflect(self.new.x, self.new.y, x, y)<EOL>self.new.ctrl2 = Point(rx, ry)<EOL><DEDENT><DEDENT>elif self.new == None:<EOL><INDENT>pt = self._points[self.edit]<EOL>if self.overlap(pt.x, pt.y, x, y)and not self.drag_handle1and not self.drag_handle2and not self.new != None:<EOL><INDENT>self.drag_point = True<EOL>self.drag_handle1 = False<EOL>self.drag_handle2 = False<EOL><DEDENT>if self.overlap(pt.ctrl1.x, pt.ctrl1.y, x, y)and pt.cmd == CURVETOand not self.drag_pointand not self.drag_handle2:<EOL><INDENT>self.drag_point = False<EOL>self.drag_handle1 = True<EOL>self.drag_handle2 = False<EOL><DEDENT>if self.overlap(pt.ctrl2.x, pt.ctrl2.y, x, y)and pt.cmd == CURVETOand not self.drag_pointand not self.drag_handle1:<EOL><INDENT>self.drag_point = False<EOL>self.drag_handle1 = False<EOL>self.drag_handle2 = True<EOL><DEDENT>if self.drag_point == True:<EOL><INDENT>dx = x - pt.x<EOL>dy = y - pt.y<EOL>pt.x = x<EOL>pt.y = y<EOL>pt.ctrl2.x += dx<EOL>pt.ctrl2.y += dy<EOL>if self.edit < len(self._points)-<NUM_LIT:1>:<EOL><INDENT>rx, ry = self.reflect(pt.x, pt.y, x, y)<EOL>next = self._points[self.edit+<NUM_LIT:1>]<EOL>next.ctrl1.x += dx<EOL>next.ctrl1.y += dy<EOL><DEDENT><DEDENT>if self.drag_handle1 == True:<EOL><INDENT>pt.ctrl1 = Point(x, y)<EOL>if self.edit > <NUM_LIT:0>and self.last_key != "<STR_LIT:x>":<EOL><INDENT>prev = self._points[self.edit-<NUM_LIT:1>]<EOL>d = self.distance(prev.x, prev.y, prev.ctrl2.x, prev.ctrl2.y)<EOL>a = self.angle(prev.x, prev.y, pt.ctrl1.x, pt.ctrl1.y)<EOL>prev.ctrl2 = self.coordinates(prev.x, prev.y, d, a+<NUM_LIT>)                        <EOL><DEDENT><DEDENT>if self.drag_handle2 == True:   <EOL><INDENT>pt.ctrl2 = Point(x, y)<EOL>if self.edit < len(self._points)-<NUM_LIT:1>and self.last_key != "<STR_LIT:x>":<EOL><INDENT>next = self._points[self.edit+<NUM_LIT:1>]<EOL>d = self.distance(pt.x, pt.y, next.ctrl1.x, next.ctrl1.y)<EOL>a = self.angle(pt.x, pt.y, pt.ctrl2.x, pt.ctrl2.y)<EOL>next.ctrl1 = self.coordinates(pt.x, pt.y, d, a+<NUM_LIT>)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>elif not self.freehand:<EOL><INDENT>self.new = None<EOL>self.drag_point = False<EOL>self.drag_handle1 = False<EOL>self.drag_handle2 = False<EOL>if self.delete != None and len(self._points) > <NUM_LIT:0>:<EOL><INDENT>i = self.delete<EOL>cmd = self._points[i].cmd<EOL>del self._points[i]<EOL>if <NUM_LIT:0> < i < len(self._points):<EOL><INDENT>prev = self._points[i-<NUM_LIT:1>]<EOL>rx, ry = self.reflect(prev.x, prev.y, prev.ctrl2.x, prev.ctrl2.y)<EOL>self._points[i].ctrl1 = Point(rx, ry)<EOL><DEDENT>start_i = i<EOL>while i > <NUM_LIT:1>:<EOL><INDENT>i -= <NUM_LIT:1><EOL>pt = self._points[i]<EOL>if pt.freehand:<EOL><INDENT>del self._points[i]<EOL><DEDENT>elif i < start_i-<NUM_LIT:1> and pt.freehand == False:<EOL><INDENT>if pt.cmd == MOVETO:<EOL><INDENT>del self._points[i]<EOL><DEDENT>break<EOL><DEDENT><DEDENT>if len(self._points) > <NUM_LIT:0>and (cmd == MOVETO or i == <NUM_LIT:0>):<EOL><INDENT>self.last_moveto = self._points[<NUM_LIT:0>]<EOL>for pt in self._points:<EOL><INDENT>if pt.cmd == MOVETO:<EOL><INDENT>self.last_moveto = pt<EOL><DEDENT><DEDENT><DEDENT>self.delete = None<EOL>self.edit = None<EOL><DEDENT>elif isinstance(self.moveto, int):<EOL><INDENT>self.moveto = True<EOL>self.edit = None<EOL><DEDENT>elif self.edit == Noneand self.contains_point(x, y, d=<NUM_LIT:2>):<EOL><INDENT>self.insert = True<EOL><DEDENT>else:<EOL><INDENT>self.insert = False<EOL><DEDENT>if self.insertingand self.contains_point(x, y, d=<NUM_LIT:2>): <EOL><INDENT>self.insert_point(x, y)<EOL>self.insert = False<EOL><DEDENT>self.inserting = False<EOL>if self._dirty == True:<EOL><INDENT>self.export_svg()<EOL>self._dirty = False<EOL><DEDENT><DEDENT>if _ctx._ns["<STR_LIT>"]:<EOL><INDENT>self.last_key = _ctx._ns["<STR_LIT:key>"]<EOL>self.last_keycode = _ctx._ns["<STR_LIT>"]<EOL><DEDENT>if not _ctx._ns["<STR_LIT>"] and self.last_key != None:<EOL><INDENT>if self.last_keycode == KEY_TAB:<EOL><INDENT>self.show_grid = not self.show_grid<EOL><DEDENT>if self.last_key == "<STR_LIT:f>":<EOL><INDENT>self.edit = None<EOL>self.freehand = not self.freehand<EOL>if self.freehand:<EOL><INDENT>self.msg = "<STR_LIT>"<EOL><DEDENT>else:<EOL><INDENT>self.msg = "<STR_LIT>"<EOL><DEDENT><DEDENT>if self.last_keycode == KEY_ESC:<EOL><INDENT>self.edit = None<EOL><DEDENT>if self.last_keycode == _ctx.KEY_BACKSPACEand self.edit != None:<EOL><INDENT>self.delete = self.edit<EOL><DEDENT>self.last_key = None<EOL>self.last_code = None<EOL><DEDENT>if _ctx._ns["<STR_LIT>"]:<EOL><INDENT>dx = <NUM_LIT:0><EOL>dy = <NUM_LIT:0><EOL>keycode = _ctx._ns["<STR_LIT>"]<EOL>if keycode == _ctx.KEY_LEFT:<EOL><INDENT>dx = -<NUM_LIT:10><EOL><DEDENT>elif keycode == _ctx.KEY_RIGHT:<EOL><INDENT>dx = <NUM_LIT:10><EOL><DEDENT>if keycode == _ctx.KEY_UP:<EOL><INDENT>dy = -<NUM_LIT:10><EOL><DEDENT>elif keycode == _ctx.KEY_DOWN:<EOL><INDENT>dy = <NUM_LIT:10><EOL><DEDENT>if dx != <NUM_LIT:0> or dy != <NUM_LIT:0>:<EOL><INDENT>for pt in self._points:<EOL><INDENT>pt.x += dx<EOL>pt.y += dy<EOL>pt.ctrl1.x += dx<EOL>pt.ctrl1.y += dy<EOL>pt.ctrl2.x += dx<EOL>pt.ctrl2.y += dy<EOL><DEDENT><DEDENT><DEDENT>

Update runs each frame to check for mouse interaction.

        Alters the path by allowing the user to add new points,
        drag point handles and move their location.
        Updates are automatically stored as SVG
        in the given filename.


<EOL>self.update()<EOL>x, y = mouse()<EOL>if self.show_grid:<EOL><INDENT>self.grid.draw()<EOL>x, y = self.grid.snap(x, y)<EOL><DEDENT>_ctx.strokewidth(self.strokewidth)<EOL>if self.freehand:<EOL><INDENT>self.draw_freehand()<EOL><DEDENT>r = <NUM_LIT:4><EOL>_ctx.nofill()<EOL>if len(self._points) > <NUM_LIT:0>:<EOL><INDENT>first = True            <EOL>for i in range(len(self._points)):<EOL><INDENT>pt = self._points[i]<EOL>if first:<EOL><INDENT>_ctx.beginpath(pt.x, pt.y)<EOL>first = False<EOL><DEDENT>else:<EOL><INDENT>if pt.cmd == CLOSE:<EOL><INDENT>_ctx.closepath()<EOL><DEDENT>elif pt.cmd == MOVETO:<EOL><INDENT>_ctx.moveto(pt.x, pt.y)<EOL><DEDENT>elif pt.cmd == LINETO:<EOL><INDENT>_ctx.lineto(pt.x, pt.y)<EOL><DEDENT>elif pt.cmd == CURVETO:<EOL><INDENT>_ctx.curveto(pt.ctrl1.x, pt.ctrl1.y, <EOL>pt.ctrl2.x, pt.ctrl2.y, <EOL>pt.x, pt.y)<EOL><DEDENT><DEDENT>if ((i == self.edit and self.new == None)or pt == self.new)and pt.cmd == CURVETOand not pt.freehand:<EOL><INDENT>_ctx.stroke(self.handle_color)<EOL>_ctx.nofill()<EOL>_ctx.oval(pt.x-r, pt.y-r, r*<NUM_LIT:2>, r*<NUM_LIT:2>)<EOL>_ctx.stroke(self.handle_color)<EOL>_ctx.line(pt.ctrl2.x, pt.ctrl2.y, pt.x, pt.y)<EOL>_ctx.fill(self.handle_color)<EOL><DEDENT>if pt == self.newand not pt.freehand:<EOL><INDENT>rx, ry = self.reflect(pt.x, pt.y, pt.ctrl2.x, pt.ctrl2.y)<EOL>_ctx.stroke(self.handle_color)<EOL>_ctx.line(rx, ry, pt.x, pt.y)<EOL>_ctx.nostroke()<EOL>_ctx.fill(self.handle_color)<EOL>_ctx.oval(rx-r/<NUM_LIT:2>, ry-r/<NUM_LIT:2>, r, r)<EOL><DEDENT>if i == self.editand self.new == Noneand pt.cmd == CURVETOand not pt.freehand:<EOL><INDENT>_ctx.oval(pt.ctrl2.x-r/<NUM_LIT:2>, pt.ctrl2.y-r/<NUM_LIT:2>, r, r)<EOL>if i > <NUM_LIT:0>:<EOL><INDENT>prev = self._points[i-<NUM_LIT:1>]<EOL>_ctx.line(pt.ctrl1.x, pt.ctrl1.y, prev.x, prev.y)<EOL>_ctx.oval(pt.ctrl1.x-r/<NUM_LIT:2>, pt.ctrl1.y-r/<NUM_LIT:2>, r, r)<EOL><DEDENT>if i > <NUM_LIT:0> and self._points[i-<NUM_LIT:1>].cmd != MOVETO:<EOL><INDENT>_ctx.line(prev.ctrl2.x, prev.ctrl2.y, prev.x, prev.y)<EOL><DEDENT>if i < len(self._points)-<NUM_LIT:1>:<EOL><INDENT>next = self._points[i+<NUM_LIT:1>]<EOL>if next.cmd == CURVETO:<EOL><INDENT>_ctx.line(next.ctrl1.x, next.ctrl1.y, pt.x, pt.y)<EOL><DEDENT><DEDENT><DEDENT>elif self.overlap(x, y, pt.x, pt.y)and not pt.freehand:<EOL><INDENT>self.insert = False <EOL>_ctx.nofill()<EOL>_ctx.stroke(self.handle_color)<EOL>_ctx.oval(pt.x-r, pt.y-r, r*<NUM_LIT:2>, r*<NUM_LIT:2>)<EOL><DEDENT>_ctx.fontsize(<NUM_LIT:9>)<EOL>_ctx.fill(self.handle_color)<EOL>txt = "<STR_LIT>"+str(int(pt.x))+"<STR_LIT:U+002CU+0020>"+str(int(pt.y))+"<STR_LIT:)>"<EOL>if (i == self.edit and self.new == None)or pt == self.newand not pt.freehand:<EOL><INDENT>_ctx.text(txt, pt.x+r, pt.y+<NUM_LIT:2>)                                       <EOL><DEDENT>elif self.overlap(x, y, pt.x, pt.y)and not pt.freehand:<EOL><INDENT>_ctx.text(txt, pt.x+r, pt.y+<NUM_LIT:2>)<EOL><DEDENT>if not pt.freehand:<EOL><INDENT>if pt.cmd != MOVETO:<EOL><INDENT>_ctx.fill(self.path_color)<EOL>_ctx.nostroke()<EOL><DEDENT>else:<EOL><INDENT>_ctx.stroke(self.path_color)<EOL>_ctx.nofill()<EOL><DEDENT>_ctx.oval(pt.x-r/<NUM_LIT:2>, pt.y-r/<NUM_LIT:2>, r, r)<EOL><DEDENT><DEDENT>_ctx.stroke(self.path_color)<EOL>_ctx.fill(self.path_fill)<EOL>_ctx.autoclosepath(False)    <EOL>p = _ctx.endpath()<EOL>self.path = p<EOL>if self.insert:<EOL><INDENT>_ctx.stroke(self.handle_color)<EOL>_ctx.nofill()<EOL>_ctx.oval(x-r*<NUM_LIT>, y-r*<NUM_LIT>, r*<NUM_LIT>, r*<NUM_LIT>)<EOL><DEDENT>if self.edit == Noneand self.new == Noneand self.moveto != Trueand not self.freehand:<EOL><INDENT>_ctx.nofill()<EOL>_ctx.stroke(self.new_color)<EOL>rx, ry = self.reflect(pt.x, pt.y, pt.ctrl2.x, pt.ctrl2.y)<EOL>_ctx.beginpath(pt.x, pt.y)<EOL>_ctx.curveto(rx, ry, x, y, x, y)<EOL>_ctx.endpath()<EOL>if self.last_moveto != None:<EOL><INDENT>start = self.last_moveto<EOL><DEDENT>else:<EOL><INDENT>start = self._points[<NUM_LIT:0>]<EOL><DEDENT>p = _ctx.line(x, y, start.x, start.y, draw=False)<EOL>try: p._nsBezierPath.setLineDash_count_phase_([<NUM_LIT:2>,<NUM_LIT:4>], <NUM_LIT:2>, <NUM_LIT:50>)<EOL>except:<EOL><INDENT>pass<EOL><DEDENT>_ctx.drawpath(p)<EOL><DEDENT>elif self.edit == Noneand self.new == Noneand self.moveto != None:<EOL><INDENT>_ctx.stroke(self.new_color)<EOL>_ctx.nofill()<EOL>_ctx.oval(x-r*<NUM_LIT>, y-r*<NUM_LIT>, r*<NUM_LIT>, r*<NUM_LIT>)<EOL><DEDENT>if self.edit != None:<EOL><INDENT>pt = self._points[self.edit]<EOL>x = pt.x + self.btn_x<EOL>y = pt.y + self.btn_y<EOL>r = self.btn_r<EOL>_ctx.nostroke()<EOL>_ctx.fill(<NUM_LIT:0>,<NUM_LIT:0>,<NUM_LIT:0>,<NUM_LIT>)<EOL>_ctx.fill(self.handle_color)<EOL>_ctx.oval(x-r, y-r, r*<NUM_LIT:2>, r*<NUM_LIT:2>)<EOL>_ctx.fill(<NUM_LIT:1>)<EOL>_ctx.rotate(<NUM_LIT>)<EOL>_ctx.rect(x-r+<NUM_LIT:2>, y-<NUM_LIT>, r+<NUM_LIT:1>, <NUM_LIT>)<EOL>_ctx.rotate(-<NUM_LIT>)<EOL>_ctx.rect(x-r+<NUM_LIT:2>, y-<NUM_LIT>, r+<NUM_LIT:1>, <NUM_LIT>)<EOL>_ctx.reset()<EOL>if self.edit == len(self._points)-<NUM_LIT:1>:<EOL><INDENT>_ctx.fill(self.handle_color)<EOL>_ctx.oval(x+r*<NUM_LIT:2>+<NUM_LIT:2>-r, y-r, r*<NUM_LIT:2>, r*<NUM_LIT:2>)<EOL>_ctx.fill(<NUM_LIT:1>)<EOL>_ctx.rect(x+r*<NUM_LIT:2>+<NUM_LIT:2>-<NUM_LIT>, y-r+<NUM_LIT:3>, <NUM_LIT>, r-<NUM_LIT:1>)<EOL>_ctx.rect(x+r*<NUM_LIT:2>+<NUM_LIT:2>+<NUM_LIT>, y-r+<NUM_LIT:3>, <NUM_LIT>, r-<NUM_LIT:1>)<EOL><DEDENT><DEDENT><DEDENT>if self.msg != "<STR_LIT>":<EOL><INDENT>self.msg_alpha -= <NUM_LIT:0.1><EOL>_ctx.nostroke()<EOL>_ctx.fill(<NUM_LIT:0>,<NUM_LIT:0>,<NUM_LIT:0>, self.msg_alpha)<EOL>_ctx.fontsize(<NUM_LIT>)<EOL>_ctx.lineheight(<NUM_LIT:1>)<EOL>w = _ctx.textwidth(self.msg)<EOL>_ctx.rect(_ctx.WIDTH/<NUM_LIT:2>-w/<NUM_LIT:2>-<NUM_LIT:9>, _ctx.HEIGHT/<NUM_LIT:2>-<NUM_LIT>, w+<NUM_LIT>, <NUM_LIT>, roundness=<NUM_LIT>)<EOL>_ctx.fill(<NUM_LIT:1>,<NUM_LIT:1>,<NUM_LIT:1>, <NUM_LIT>)<EOL>_ctx.align(CENTER) <EOL>_ctx.text(self.msg, <NUM_LIT:0>, _ctx.HEIGHT/<NUM_LIT:2>, width=_ctx.WIDTH)<EOL><DEDENT>if self.msg_alpha <= <NUM_LIT:0.0>:<EOL><INDENT>self.msg = "<STR_LIT>"<EOL>self.msg_alpha = <NUM_LIT:1.0><EOL><DEDENT>

Draws the editable path and interface elements.


if _ctx._ns["<STR_LIT>"]:<EOL><INDENT>x, y = mouse()<EOL>if self.show_grid:<EOL><INDENT>x, y = self.grid.snap(x, y)<EOL><DEDENT>if self.freehand_move == True:<EOL><INDENT>cmd = MOVETO<EOL>self.freehand_move = False<EOL><DEDENT>else:<EOL><INDENT>cmd = LINETO<EOL><DEDENT>pt = PathElement()<EOL>if cmd != MOVETO:<EOL><INDENT>pt.freehand = True <EOL><DEDENT>else:<EOL><INDENT>pt.freehand = False<EOL><DEDENT>pt.cmd = cmd<EOL>pt.x = x<EOL>pt.y = y<EOL>pt.ctrl1 = Point(x,y)<EOL>pt.ctrl2 = Point(x,y)<EOL>self._points.append(pt)<EOL>r = <NUM_LIT:4><EOL>_ctx.nofill()<EOL>_ctx.stroke(self.handle_color)<EOL>_ctx.oval(pt.x-r, pt.y-r, r*<NUM_LIT:2>, r*<NUM_LIT:2>)<EOL>_ctx.fontsize(<NUM_LIT:9>)<EOL>_ctx.fill(self.handle_color)<EOL>_ctx.text("<STR_LIT>"+str(int(pt.x))+"<STR_LIT:U+002CU+0020>"+str(int(pt.y))+"<STR_LIT:)>", pt.x+r, pt.y)<EOL>self._dirty = True<EOL><DEDENT>else:<EOL><INDENT>self.freehand_move = True<EOL>if self._dirty:<EOL><INDENT>self._points[-<NUM_LIT:1>].freehand = False<EOL>self.export_svg()<EOL>self._dirty = False<EOL><DEDENT><DEDENT>


d = "<STR_LIT>"<EOL>if len(self._points) > <NUM_LIT:0>:<EOL><INDENT>d += "<STR_LIT>"+str(self._points[<NUM_LIT:0>].x)+"<STR_LIT:U+0020>"+str(self._points[<NUM_LIT:0>].y)+"<STR_LIT:U+0020>"<EOL>for pt in self._points:<EOL><INDENT>if pt.cmd == MOVETO:<EOL><INDENT>d += "<STR_LIT>"+str(pt.x)+"<STR_LIT:U+0020>"+str(pt.y)+"<STR_LIT:U+0020>"<EOL><DEDENT>elif pt.cmd == LINETO:<EOL><INDENT>d += "<STR_LIT>"+str(pt.x)+"<STR_LIT:U+0020>"+str(pt.y)+"<STR_LIT:U+0020>"<EOL><DEDENT>elif pt.cmd == CURVETO:<EOL><INDENT>d += "<STR_LIT>"<EOL>d += str(pt.ctrl1.x)+"<STR_LIT:U+0020>"+str(pt.ctrl1.y)+"<STR_LIT:U+0020>"<EOL>d += str(pt.ctrl2.x)+"<STR_LIT:U+0020>"+str(pt.ctrl2.y)+"<STR_LIT:U+0020>"<EOL>d += str(pt.x)+"<STR_LIT:U+0020>"+str(pt.y)+"<STR_LIT:U+0020>"<EOL><DEDENT><DEDENT><DEDENT>c = "<STR_LIT>"<EOL>c += str(int(self.path_color.r*<NUM_LIT:255>)) + "<STR_LIT:U+002C>"<EOL>c += str(int(self.path_color.g*<NUM_LIT:255>)) + "<STR_LIT:U+002C>"<EOL>c += str(int(self.path_color.b*<NUM_LIT:255>)) + "<STR_LIT:)>"<EOL>s  = '<STR_LIT>'<EOL>s += '<STR_LIT>'+str(_ctx.WIDTH)+'<STR_LIT>'+str(_ctx.HEIGHT)+'<STR_LIT>'<EOL>s += '<STR_LIT>'<EOL>s += '<STR_LIT>'+d+'<STR_LIT>'+c+'<STR_LIT>'+str(self.strokewidth)+'<STR_LIT>'<EOL>s += '<STR_LIT>'<EOL>s += '<STR_LIT>'<EOL>f = open(self.file+"<STR_LIT>", "<STR_LIT:w>")<EOL>f.write(s)<EOL>f.close()<EOL>

Exports the path as SVG.

        Uses the filename given when creating this object.
        The file is automatically updated to reflect
        changes to the path.


self.interpolation = BILINEAR<EOL>self.layers = Layers()<EOL>self.w = w<EOL>self.h = h<EOL>img = Image.new("<STR_LIT>", (w,h), (<NUM_LIT:255>,<NUM_LIT:255>,<NUM_LIT:255>,<NUM_LIT:0>))<EOL>self.layer(img, name="<STR_LIT>")<EOL>

Creates a new canvas.

        Creates the working area on which to blend layers.
        The canvas background is transparent,
        but a background color could be set using the fill() function.


def layer(self, img, x=<NUM_LIT:0>, y=<NUM_LIT:0>, name="<STR_LIT>"):

from types import StringType<EOL>if isinstance(img, Image.Image):<EOL><INDENT>img = img.convert("<STR_LIT>")<EOL>self.layers.append(Layer(self, img, x, y, name))<EOL>return len(self.layers)-<NUM_LIT:1><EOL><DEDENT>if isinstance(img, Layer):<EOL><INDENT>img.canvas = self<EOL>self.layers.append(img)<EOL>return len(self.layers)-<NUM_LIT:1>                 <EOL><DEDENT>if type(img) == StringType: <EOL><INDENT>img = Image.open(img)<EOL>img = img.convert("<STR_LIT>")<EOL>self.layers.append(Layer(self, img, x, y, name))<EOL>return len(self.layers)-<NUM_LIT:1><EOL><DEDENT>

Creates a new layer from file, Layer, PIL Image.

        If img is an image file or PIL Image object,
        Creates a new layer with the given image file.
        The image is positioned on the canvas at x, y.

        If img is a Layer,
        uses that layer's x and y position and name.


def fill(self, rgb, x=<NUM_LIT:0>, y=<NUM_LIT:0>, w=None, h=None, name="<STR_LIT>"):

if w == None: w = self.w - x<EOL>if h == None: h = self.h - y<EOL>img = Image.new("<STR_LIT>", (w,h), rgb)<EOL>self.layer(img, x, y, name)<EOL>

Creates a new fill layer.

        Creates a new layer filled with the given rgb color.
        For example, fill((255,0,0)) creates a red fill.
        The layers fills the entire canvas by default.


def gradient(self, style=LINEAR, w=<NUM_LIT:1.0>, h=<NUM_LIT:1.0>, name="<STR_LIT>"):

from types import FloatType<EOL>w0 = self.w <EOL>h0 = self.h<EOL>if type(w) == FloatType: w *= w0<EOL>if type(h) == FloatType: h *= h0<EOL>img = Image.new("<STR_LIT:L>", (int(w),int(h)), <NUM_LIT:255>)<EOL>draw = ImageDraw.Draw(img)<EOL>if style == LINEAR:<EOL><INDENT>for i in range(int(w)):<EOL><INDENT>k = <NUM_LIT> * i/w<EOL>draw.rectangle((i, <NUM_LIT:0>, i, h), fill=int(k))<EOL><DEDENT><DEDENT>if style == RADIAL:<EOL><INDENT>r = min(w,h)/<NUM_LIT:2><EOL>for i in range(int(r)):<EOL><INDENT>k = <NUM_LIT:255> - <NUM_LIT> * i/r<EOL>draw.ellipse((w/<NUM_LIT:2>-r+i, h/<NUM_LIT:2>-r+i, w/<NUM_LIT:2>+r-i, h/<NUM_LIT:2>+r-i), fill=int(k))<EOL><DEDENT><DEDENT>if style == DIAMOND:<EOL><INDENT>r = max(w,h)<EOL>for i in range(int(r)):<EOL><INDENT>x = int(i*w/r*<NUM_LIT:0.5>)<EOL>y = int(i*h/r*<NUM_LIT:0.5>)<EOL>k = <NUM_LIT> * i/r<EOL>draw.rectangle((x, y, w-x, h-y), outline=int(k))<EOL><DEDENT><DEDENT>img = img.convert("<STR_LIT>")<EOL>self.layer(img, <NUM_LIT:0>, <NUM_LIT:0>, name="<STR_LIT>")<EOL>

Creates a gradient layer.

        Creates a gradient layer, that is usually used
        together with the mask() function.

        All the image functions work on gradients,
        so they can easily be flipped, rotated, scaled, inverted,
        made brighter or darker, ...

        Styles for gradients are LINEAR, RADIAL and DIAMOND.


layers.sort()<EOL>if layers[<NUM_LIT:0>] == <NUM_LIT:0>: del layers[<NUM_LIT:0>]<EOL>self.flatten(layers)<EOL>

Flattens the given layers on the canvas.

        Merges the given layers with the indices in the list
        on the bottom layer in the list.
        The other layers are discarded.


<EOL>if layers == []: <EOL><INDENT>layers = range(<NUM_LIT:1>, len(self.layers))<EOL><DEDENT>background = self.layers._get_bg()<EOL>background.name = "<STR_LIT>"<EOL>for i in layers:<EOL><INDENT>layer = self.layers[i]<EOL>x = max(<NUM_LIT:0>, layer.x)<EOL>y = max(<NUM_LIT:0>, layer.y)<EOL>w = min(background.w, layer.x+layer.w)<EOL>h = min(background.h, layer.y+layer.h)<EOL>base = background.img.crop((x, y, w, h))<EOL>x = max(<NUM_LIT:0>, -layer.x)<EOL>y = max(<NUM_LIT:0>, -layer.y)<EOL>w -= layer.x<EOL>h -= layer.y<EOL>blend = layer.img.crop((x, y, w, h))<EOL>if layer.blend == NORMAL:<EOL><INDENT>buffer = blend<EOL><DEDENT>if layer.blend == MULTIPLY:<EOL><INDENT>buffer = ImageChops.multiply(base, blend)<EOL><DEDENT>if layer.blend == SCREEN:<EOL><INDENT>buffer = ImageChops.screen(base, blend)<EOL><DEDENT>if layer.blend == OVERLAY:<EOL><INDENT>buffer = Blend().overlay(base, blend)<EOL><DEDENT>if layer.blend == HUE:<EOL><INDENT>buffer = Blend().hue(base, blend)<EOL><DEDENT>if layer.blend == COLOR:<EOL><INDENT>buffer = Blend().color(base, blend)<EOL><DEDENT>alpha = buffer.split()[<NUM_LIT:3>]<EOL>if i == <NUM_LIT:1>:<EOL><INDENT>buffer = Image.composite(base, buffer, base.split()[<NUM_LIT:3>])<EOL><DEDENT>else:<EOL><INDENT>buffer = Image.composite(buffer, base, alpha)<EOL><DEDENT>alpha = ImageChops.lighter(alpha, base.split()[<NUM_LIT:3>])<EOL>buffer.putalpha(alpha)<EOL>base = Image.blend(base, buffer, layer.alpha)<EOL>x = max(<NUM_LIT:0>, layer.x)<EOL>y = max(<NUM_LIT:0>, layer.y)<EOL>background.img.paste(base, (x,y))<EOL><DEDENT>layers.reverse()<EOL>for i in layers: del self.layers[i]<EOL>img = Image.new("<STR_LIT>", (self.w,self.h), (<NUM_LIT:255>,<NUM_LIT:255>,<NUM_LIT:255>,<NUM_LIT:0>))<EOL>self.layers._set_bg(Layer(self, img, <NUM_LIT:0>, <NUM_LIT:0>, name="<STR_LIT>"))<EOL>if len(self.layers) == <NUM_LIT:1>:<EOL><INDENT>self.layers.append(background)<EOL><DEDENT>else:<EOL><INDENT>self.layers.insert(layers[-<NUM_LIT:1>], background)<EOL><DEDENT>

Flattens all layers according to their blend modes.

        Merges all layers to the canvas,
        using the blend mode and opacity defined for each layer.
        Once flattened, the stack of layers is emptied except
        for the transparent background (bottom layer).


self.flatten()<EOL>self.layers[<NUM_LIT:1>].img.save(filename)<EOL>return filename<EOL>

Exports the flattened canvas.

        Flattens the canvas.
        PNG retains the alpha channel information.
        Other possibilities are JPEG and GIF.


try:<EOL><INDENT>from time import time<EOL>import md5<EOL>from os import unlink<EOL>m = md5.new()<EOL>m.update(str(time()))<EOL>filename = "<STR_LIT>" + str(m.hexdigest()) + "<STR_LIT>"<EOL>self.export(filename)<EOL>_ctx.image(filename, x, y)<EOL>unlink(filename)<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT>

Places the flattened canvas in NodeBox.

        Exports to a temporary PNG file.
        Draws the PNG in NodeBox using the image() command.
        Removes the temporary file.


self. interpolation = interpolation<EOL>

Settings that influence image manipulation.

        Currently, only defines the image interpolation,
        which can be set to NEAREST, BICUBIC or BILINEAR.


for i in range(len(self.canvas.layers)):<EOL><INDENT>if self.canvas.layers[i] == self: break<EOL><DEDENT>if self.canvas.layers[i] == self: <EOL><INDENT>return i<EOL><DEDENT>else:<EOL><INDENT>return None<EOL><DEDENT>

Returns this layer's index in the canvas.layers[].

        Searches the position of this layer in the canvas'
        layers list, return None when not found.


layer = Layer(None, self.img.copy(), self.x, self.y, self.name)<EOL>layer.w = self.w<EOL>layer.h = self.h<EOL>layer.alpha = self.alpha<EOL>layer.blend = self.blend<EOL>return layer<EOL>

Returns a copy of the layer.

        This is different from the duplicate() method,
        which duplicates the layer as a new layer on the canvas.
        The copy() method returns a copy of the layer
        that can be added to a different canvas.


i = self.index()<EOL>if i != None: del self.canvas.layers[i]<EOL>


i = self.index()<EOL>if i != None:<EOL><INDENT>del self.canvas.layers[i]<EOL>i = min(len(self.canvas.layers), i+<NUM_LIT:1>)<EOL>self.canvas.layers.insert(i, self)<EOL><DEDENT>

Moves the layer up in the stacking order.


i = self.index()<EOL>if i != None:<EOL><INDENT>del self.canvas.layers[i]<EOL>i = max(<NUM_LIT:0>, i-<NUM_LIT:1>)<EOL>self.canvas.layers.insert(i, self)<EOL><DEDENT>

Moves the layer down in the stacking order.


return self.img.size<EOL>

Returns the size of the layer.

        This is the width and height of the bounding box,
        the invisible rectangle around the layer.


w, h = self.img.size<EOL>mask = Image.new("<STR_LIT:L>", (w,h), <NUM_LIT:0>)<EOL>draw = ImageDraw.Draw(mask)<EOL>draw = ImageDraw.Draw(mask)<EOL>draw.polygon(path, fill=<NUM_LIT:255>)<EOL>if feather:<EOL><INDENT>mask = mask.filter(ImageFilter.SMOOTH_MORE)<EOL>mask = mask.filter(ImageFilter.SMOOTH_MORE)<EOL><DEDENT>mask = ImageChops.darker(mask, self.img.split()[<NUM_LIT:3>])<EOL>self.img.putalpha(mask)<EOL>

Applies the polygonal lasso tool on a layer.

        The path paramater is a list of points,
        either [x1, y1, x2, y2, x3, y3, ...]
        or [(x1,y1), (x2,y2), (x3,y3), ...]

        The parts of the layer that fall outside
        this polygonal area are cut.

        The selection is not anti-aliased,
        but the feather parameter creates soft edges.


if len(self.canvas.layers) < <NUM_LIT:2>: return<EOL>i = self.index()<EOL>if i == <NUM_LIT:0>: return<EOL>layer = self.canvas.layers[i-<NUM_LIT:1>]<EOL>alpha = Image.new("<STR_LIT:L>", layer.img.size, <NUM_LIT:0>)<EOL>mask = self.canvas.layers[i]        <EOL>flat = ImageChops.darker(mask.img.convert("<STR_LIT:L>"), mask.img.split()[<NUM_LIT:3>])<EOL>alpha.paste(flat, (mask.x,mask.y))<EOL>alpha = ImageChops.darker(alpha, layer.img.split()[<NUM_LIT:3>])<EOL>layer.img.putalpha(alpha)<EOL>self.delete()<EOL>

Masks the layer below with this layer.

        Commits the current layer to the alpha channel of
        the previous layer. Primarily, mask() is useful when
        using gradient layers as masks on images below.

        For example:
        canvas.layer("image.jpg")
        canvas.gradient()
        canvas.layer(2).flip()
        canvas.layer(2).mask()

        Adds a white-to-black linear gradient to
        the alpha channel of image.jpg,
        making it evolve from opaque on
        the left to transparent on the right.


i = self.canvas.layer(self.img.copy(), self.x, self.y, self.name)<EOL>clone = self.canvas.layers[i]<EOL>clone.alpha = self.alpha<EOL>clone.blend = self.blend<EOL>

Creates a copy of the current layer.

        This copy becomes the top layer on the canvas.


b = ImageEnhance.Brightness(self.img) <EOL>self.img = b.enhance(value)<EOL>

Increases or decreases the brightness in the layer.

        The given value is a percentage to increase
        or decrease the image brightness,
        for example 0.8 means brightness at 80%.


c = ImageEnhance.Contrast(self.img) <EOL>self.img = c.enhance(value)<EOL>

Increases or decreases the contrast in the layer.

        The given value is a percentage to increase
        or decrease the image contrast,
        for example 1.2 means contrast at 120%.


alpha = self.img.split()[<NUM_LIT:3>]<EOL>self.img = self.img.convert("<STR_LIT:L>")<EOL>self.img = self.img.convert("<STR_LIT>")<EOL>self.img.putalpha(alpha)<EOL>

Desaturates the layer, making it grayscale.

        Instantly removes all color information from the layer,
        while maintaing its alpha channel.


alpha = self.img.split()[<NUM_LIT:3>]<EOL>self.img = self.img.convert("<STR_LIT>")<EOL>self.img = ImageOps.invert(self.img)<EOL>self.img = self.img.convert("<STR_LIT>")<EOL>self.img.putalpha(alpha)<EOL>


self.x = x<EOL>self.y = y<EOL>

Positions the layer at the given coordinates.

        The x and y parameters define where to position
        the top left corner of the layer,
        measured from the top left of the canvas.


def scale(self, w=<NUM_LIT:1.0>, h=<NUM_LIT:1.0>):

from types import FloatType<EOL>w0, h0 = self.img.size<EOL>if type(w) == FloatType: w = int(w*w0)<EOL>if type(h) == FloatType: h = int(h*h0)<EOL>self.img = self.img.resize((w,h), INTERPOLATION)<EOL>self.w = w<EOL>self.h = h<EOL>

Resizes the layer to the given width and height.

        When width w or height h is a floating-point number,
        scales percentual,
        otherwise scales to the given size in pixels.


def distort(self, x1=<NUM_LIT:0>,y1=<NUM_LIT:0>, x2=<NUM_LIT:0>,y2=<NUM_LIT:0>, x3=<NUM_LIT:0>,y3=<NUM_LIT:0>, x4=<NUM_LIT:0>,y4=<NUM_LIT:0>):

w, h = self.img.size<EOL>quad = (-x1,-y1, -x4,h-y4, w-x3,w-y3, w-x2,-y2)<EOL>self.img = self.img.transform(self.img.size, Image.QUAD, quad, INTERPOLATION)<EOL>

Distorts the layer.

        Distorts the layer by translating
        the four corners of its bounding box to the given coordinates:
        upper left (x1,y1), upper right(x2,y2),
        lower right (x3,y3) and lower left (x4,y4).


<EOL>from math import sqrt, pow, sin, cos, degrees, radians, asin<EOL>w0, h0 = self.img.size<EOL>d = sqrt(pow(w0,<NUM_LIT:2>) + pow(h0,<NUM_LIT:2>))<EOL>d_angle = degrees(asin((w0*<NUM_LIT:0.5>) / (d*<NUM_LIT:0.5>)))<EOL>angle = angle % <NUM_LIT><EOL>if angle > <NUM_LIT> and angle <= <NUM_LIT>: d_angle += <NUM_LIT><EOL>w = sin(radians(d_angle + angle)) * d<EOL>w = max(w, sin(radians(d_angle - angle)) * d)<EOL>w = int(abs(w))<EOL>h = cos(radians(d_angle + angle)) * d<EOL>h = max(h, cos(radians(d_angle - angle)) * d)<EOL>h = int(abs(h))<EOL>dx = int((w-w0) / <NUM_LIT:2>)<EOL>dy = int((h-h0) / <NUM_LIT:2>)<EOL>d = int(d)<EOL>bg = ImageStat.Stat(self.img).mean<EOL>bg = (int(bg[<NUM_LIT:0>]), int(bg[<NUM_LIT:1>]), int(bg[<NUM_LIT:2>]), <NUM_LIT:0>)<EOL>box = Image.new("<STR_LIT>", (d,d), bg)<EOL>box.paste(self.img, ((d-w0)/<NUM_LIT:2>, (d-h0)/<NUM_LIT:2>))<EOL>box = box.rotate(angle, INTERPOLATION)<EOL>box = box.crop(((d-w)/<NUM_LIT:2>+<NUM_LIT:2>, (d-h)/<NUM_LIT:2>, d-(d-w)/<NUM_LIT:2>, d-(d-h)/<NUM_LIT:2>))<EOL>self.img = box<EOL>self.x += (self.w-w)/<NUM_LIT:2><EOL>self.y += (self.h-h)/<NUM_LIT:2><EOL>self.w = w<EOL>self.h = h<EOL>

Rotates the layer.

        Rotates the layer by given angle.
        Positive numbers rotate counter-clockwise,
        negative numbers rotate clockwise.

        Rotate commands are executed instantly,
        so many subsequent rotates will distort the image.


if axis == HORIZONTAL:<EOL><INDENT>self.img = self.img.transpose(Image.FLIP_LEFT_RIGHT)<EOL><DEDENT>if axis == VERTICAL:<EOL><INDENT>self.img = self.img.transpose(Image.FLIP_TOP_BOTTOM)<EOL><DEDENT>

Flips the layer, either HORIZONTAL or VERTICAL.


self.img = self.img.filter(ImageFilter.BLUR)<EOL>


s = ImageEnhance.Sharpness(self.img) <EOL>self.img = s.enhance(value)<EOL>

Increases or decreases the sharpness in the layer.

        The given value is a percentage to increase
        or decrease the image sharpness,
        for example 0.8 means sharpness at 80%.


h = self.img.histogram()<EOL>r = h[<NUM_LIT:0>:<NUM_LIT:255>]<EOL>g = h[<NUM_LIT>:<NUM_LIT>]<EOL>b = h[<NUM_LIT>:<NUM_LIT>]<EOL>a = h[<NUM_LIT>:<NUM_LIT>]<EOL>return r, g, b, a<EOL>

Returns a histogram for each RGBA channel.

        Returns a 4-tuple of lists, r, g, b, and a.
        Each list has 255 items, a count for each pixel value.


p1 = list(img1.getdata())<EOL>p2 = list(img2.getdata())<EOL>for i in range(len(p1)):<EOL><INDENT>p3 = ()<EOL>for j in range(len(p1[i])):<EOL><INDENT>a = p1[i][j] / <NUM_LIT><EOL>b = p2[i][j] / <NUM_LIT><EOL>if j == <NUM_LIT:3>:<EOL><INDENT>d = min(a,b)<EOL><DEDENT>elif a > <NUM_LIT:0.5>: <EOL><INDENT>d = <NUM_LIT:2>*(a+b-a*b)-<NUM_LIT:1><EOL><DEDENT>else: <EOL><INDENT>d = <NUM_LIT:2>*a*b            <EOL><DEDENT>p3 += (int(d*<NUM_LIT:255>),)<EOL><DEDENT>p1[i] = p3<EOL><DEDENT>img = Image.new("<STR_LIT>", img1.size, <NUM_LIT:255>)<EOL>img.putdata(p1)<EOL>return img<EOL>

Applies the overlay blend mode.

        Overlays image img2 on image img1.
        The overlay pixel combines multiply and screen:
        it multiplies dark pixels values and screen light values.
        Returns a composite image with the alpha channel retained.


import colorsys<EOL>p1 = list(img1.getdata())<EOL>p2 = list(img2.getdata())<EOL>for i in range(len(p1)):<EOL><INDENT>r1, g1, b1, a1 = p1[i]<EOL>r1 = r1 / <NUM_LIT><EOL>g1 = g1 / <NUM_LIT><EOL>b1 = b1 / <NUM_LIT><EOL>h1, s1, v1 = colorsys.rgb_to_hsv(r1, g1, b1)<EOL>r2, g2, b2, a2 = p2[i]<EOL>r2 = r2 / <NUM_LIT><EOL>g2 = g2 / <NUM_LIT><EOL>b2 = b2 / <NUM_LIT><EOL>h2, s2, v2 = colorsys.rgb_to_hsv(r2, g2, b2)<EOL>r3, g3, b3 = colorsys.hsv_to_rgb(h2, s1, v1)<EOL>r3 = int(r3*<NUM_LIT:255>)<EOL>g3 = int(g3*<NUM_LIT:255>)<EOL>b3 = int(b3*<NUM_LIT:255>)<EOL>p1[i] = (r3, g3, b3, a1)<EOL><DEDENT>img = Image.new("<STR_LIT>", img1.size, <NUM_LIT:255>)<EOL>img.putdata(p1)<EOL>return img<EOL>

Applies the hue blend mode.

        Hues image img1 with image img2.
        The hue filter replaces the hues of pixels in img1
        with the hues of pixels in img2.
        Returns a composite image with the alpha channel retained.


import colorsys<EOL>p1 = list(img1.getdata())<EOL>p2 = list(img2.getdata())<EOL>for i in range(len(p1)):<EOL><INDENT>r1, g1, b1, a1 = p1[i]<EOL>r1 = r1 / <NUM_LIT><EOL>g1 = g1 / <NUM_LIT><EOL>b1 = b1 / <NUM_LIT><EOL>h1, s1, v1 = colorsys.rgb_to_hsv(r1, g1, b1)<EOL>r2, g2, b2, a2 = p2[i]<EOL>r2 = r2 / <NUM_LIT><EOL>g2 = g2 / <NUM_LIT><EOL>b2 = b2 / <NUM_LIT><EOL>h2, s2, v2 = colorsys.rgb_to_hsv(r2, g2, b2)<EOL>r3, g3, b3 = colorsys.hsv_to_rgb(h2, s2, v1)<EOL>r3 = int(r3*<NUM_LIT:255>)<EOL>g3 = int(g3*<NUM_LIT:255>)<EOL>b3 = int(b3*<NUM_LIT:255>)<EOL>p1[i] = (r3, g3, b3, a1)<EOL><DEDENT>img = Image.new("<STR_LIT>", img1.size, <NUM_LIT:255>)<EOL>img.putdata(p1)<EOL>return img<EOL>

Applies the color blend mode.

        Colorize image img1 with image img2.
        The color filter replaces the hue and saturation of pixels in img1
        with the hue and saturation of pixels in img2.
        Returns a composite image with the alpha channel retained.


def convolute(self, kernel, scale=None, offset=<NUM_LIT:0>):

if len(kernel)   ==  <NUM_LIT:9>: size = (<NUM_LIT:3>,<NUM_LIT:3>)<EOL>elif len(kernel) == <NUM_LIT>: size = (<NUM_LIT:5>,<NUM_LIT:5>)<EOL>else: return<EOL>if scale == None:<EOL><INDENT>scale = <NUM_LIT:0><EOL>for x in kernel: scale += x<EOL>if scale == <NUM_LIT:0>: scale = <NUM_LIT:1><EOL><DEDENT>f = ImageFilter.BuiltinFilter()<EOL>f.filterargs = size, scale, offset, kernel<EOL>self.layer.img = self.layer.img.filter(f)<EOL>

A (3,3) or (5,5) convolution kernel.

        The kernel argument is a list with either 9 or 25 elements,
        the weight for each surrounding pixels to convolute.


self._name = name.rstrip("<STR_LIT>")<EOL>self._con = sqlite.connect(self._name + "<STR_LIT>")<EOL>self._cur = self._con.cursor()<EOL>self._tables = []<EOL>self._cur.execute("<STR_LIT>")<EOL>for r in self._cur: self._tables.append(r[<NUM_LIT:0>])<EOL>self._indices = []<EOL>self._cur.execute("<STR_LIT>")<EOL>for r in self._cur: self._indices.append(r[<NUM_LIT:0>])<EOL>for t in self._tables:<EOL><INDENT>self._cur.execute("<STR_LIT>"+t+"<STR_LIT:)>")<EOL>fields = []<EOL>key = "<STR_LIT>"<EOL>for r in self._cur:<EOL><INDENT>fields.append(r[<NUM_LIT:1>])<EOL>if r[<NUM_LIT:2>] == "<STR_LIT>": key = r[<NUM_LIT:1>]<EOL><DEDENT>setattr(self, t, Table(self, t, key, fields))<EOL><DEDENT>

Generic database.

        Opens the SQLite database with the given name.
        The .db extension is automatically appended to the name.
        For each table in the database an attribute is created,
        and assigned a Table object.

        You can do: database.table or database[table].


self._name = name.rstrip("<STR_LIT>")<EOL>from os import unlink<EOL>if overwrite: <EOL><INDENT>try: unlink(self._name + "<STR_LIT>")<EOL>except: pass       <EOL><DEDENT>self._con = sqlite.connect(self._name + "<STR_LIT>")<EOL>self._cur = self._con.cursor()<EOL>

Creates an SQLite database file.

        Creates an SQLite database with the given name.
        The .box file extension is added automatically.
        Overwrites any existing database by default.


def create_table(self, name, fields=[], key="<STR_LIT:id>"):

for f in fields: <EOL><INDENT>if f == key: fields.remove(key)<EOL><DEDENT>sql  = "<STR_LIT>"+name+"<STR_LIT:U+0020>"<EOL>sql += "<STR_LIT:(>"+key+"<STR_LIT>"<EOL>for f in fields: sql += "<STR_LIT:U+002CU+0020>"+f+"<STR_LIT>"<EOL>sql += "<STR_LIT:)>"<EOL>self._cur.execute(sql)<EOL>self._con.commit()<EOL>self.index(name, key, unique=True)<EOL>self.connect(self._name)<EOL>

Creates a new table.

        Creates a table with the given name,
        containing the list of given fields.
        Since SQLite uses manifest typing, no data type need be supplied.
        The primary key is "id" by default,
        an integer that can be set or otherwise autoincrements.


def create_index(self, table, field, unique=False, ascending=True):

if unique: u = "<STR_LIT>"<EOL>else: u = "<STR_LIT>"<EOL>if ascending: a = "<STR_LIT>"<EOL>else: a = "<STR_LIT>"<EOL>sql  = "<STR_LIT>"+u+"<STR_LIT>"+table+"<STR_LIT:_>"+field+"<STR_LIT:U+0020>"<EOL>sql += "<STR_LIT>"+table+"<STR_LIT:(>"+field+"<STR_LIT:U+0020>"+a+"<STR_LIT:)>"<EOL>self._cur.execute(sql)<EOL>self._con.commit()<EOL>

Creates a table index.

        Creates an index on the given table,
        on the given field with unique values enforced or not,
        in ascending or descending order.


self._commit = each<EOL>self._con.commit()<EOL>

Sets the commit frequency.

        Modifications to the database,
        e.g. row insertions are commited in batch,
        specified by the given number.
        A number that is reasonably high allows for faster transactions.
        Commits anything still pending.


self._con.commit()<EOL>self._cur.close()<EOL>self._con.close()<EOL>

Commits any pending transactions and closes the database.


self._cur.execute(sql)<EOL>if sql.lower().find("<STR_LIT>") >= <NUM_LIT:0>:<EOL><INDENT>matches = []<EOL>for r in self._cur: matches.append(r)<EOL>return matches<EOL><DEDENT>

Executes a raw SQL statement on the database.


self._con.commit()<EOL>if ext == "<STR_LIT>":<EOL><INDENT>return self._dump_xml()<EOL><DEDENT>

Dumps the data in the tables into another format (like XML).


def __init__(self, db, name, key, fields):

self._db = db<EOL>self._name = name<EOL>self._key = key<EOL>self._fields = fields<EOL>for f in self._fields:<EOL><INDENT>import new<EOL>im = lambda t, q, operator="<STR_LIT:=>", fields="<STR_LIT:*>", _field=f: t.find(q, operator, fields, _field)<EOL>setattr(self, f, new.instancemethod(im, self, None))<EOL><DEDENT>

Generic table.

        Constructs a table with the given name, primary key and columns.
        Each of the column names becomes the name of a table method
        that fetches rows from the table.

        For example, a table with an id field has the following method:
        table.id(query, operator="=")


sql = "<STR_LIT>"+self._key+"<STR_LIT>"+self._name<EOL>self._db._cur.execute(sql)<EOL>i = <NUM_LIT:0><EOL>for r in self._db._cur: i += <NUM_LIT:1><EOL>return i<EOL>

The row count of the table. This should be optimized.


def find(self, q, operator="<STR_LIT:=>", fields="<STR_LIT:*>", key=None):

if key == None: key = self._key<EOL>if fields != "<STR_LIT:*>": fields = "<STR_LIT:U+002CU+0020>".join(fields)<EOL>try: q = unicode(q)<EOL>except: pass<EOL>if q != "<STR_LIT:*>" and (q[<NUM_LIT:0>] == "<STR_LIT:*>" or q[-<NUM_LIT:1>] == "<STR_LIT:*>"):<EOL><INDENT>if q[<NUM_LIT:0>]  == "<STR_LIT:*>": q = "<STR_LIT:%>"+q.lstrip("<STR_LIT:*>")<EOL>if q[-<NUM_LIT:1>] == "<STR_LIT:*>": q = q.rstrip("<STR_LIT:*>")+"<STR_LIT:%>"<EOL>operator = "<STR_LIT>"<EOL><DEDENT>if q != "<STR_LIT:*>":<EOL><INDENT>sql = "<STR_LIT>"+fields+"<STR_LIT>"+self._name+"<STR_LIT>"+key+"<STR_LIT:U+0020>"+operator+"<STR_LIT>"<EOL>self._db._cur.execute(sql, (q,))<EOL><DEDENT>else:<EOL><INDENT>sql = "<STR_LIT>"+fields+"<STR_LIT>"+self._name<EOL>self._db._cur.execute(sql)<EOL><DEDENT>matches = []<EOL>for r in self._db._cur: matches.append(r)<EOL>return matches<EOL>

A simple SQL SELECT query.

        Retrieves all rows from the table
        where the given query value is found in the given column (primary key if None).
        A different comparison operator (e.g. >, <, like) can be set.
        The wildcard character is * and automatically sets the operator to "like".
        Optionally, the fields argument can be a list of column names to select.
        Returns a list of row tuples containing fields.


return self.find("<STR_LIT:*>")<EOL>


return self._fields<EOL>

Returns the column names.

        Returns the name of each column in the database,
        in the same order row fields are returned from find().


if args and kw: <EOL><INDENT>return<EOL><DEDENT>if args and type(args[<NUM_LIT:0>]) == dict:<EOL><INDENT>fields = [k for k in args[<NUM_LIT:0>]]<EOL>v = [args[<NUM_LIT:0>][k] for k in args[<NUM_LIT:0>]]<EOL><DEDENT>if kw:<EOL><INDENT>fields = [k for k in kw]<EOL>v = [kw[k] for k in kw]<EOL><DEDENT>q = "<STR_LIT:U+002CU+0020>".join(["<STR_LIT:?>" for x in fields])<EOL>sql  = "<STR_LIT>"+self._name+"<STR_LIT>"+"<STR_LIT:U+002CU+0020>".join(fields)+"<STR_LIT>"<EOL>sql += "<STR_LIT>"+q+"<STR_LIT:)>"<EOL>self._db._cur.execute(sql, v)<EOL>self._db._i += <NUM_LIT:1><EOL>if self._db._i >= self._db._commit:<EOL><INDENT>self._db._i = <NUM_LIT:0><EOL>self._db._con.commit()<EOL><DEDENT>

Adds a new row to a table.

        Adds a row to the given table.
        The column names and their corresponding values
        must either be supplied as a dictionary of {fields:values},
        or a series of keyword arguments of field=value style.


if args and kw: <EOL><INDENT>return<EOL><DEDENT>if args and type(args[<NUM_LIT:0>]) == dict:<EOL><INDENT>fields = [k for k in args[<NUM_LIT:0>]]<EOL>v = [args[<NUM_LIT:0>][k] for k in args[<NUM_LIT:0>]]<EOL><DEDENT>if kw:<EOL><INDENT>fields = [k for k in kw]<EOL>v = [kw[k] for k in kw]<EOL><DEDENT>sql  = "<STR_LIT>"+self._name+"<STR_LIT>"+"<STR_LIT>".join(fields)+"<STR_LIT>"+self._key+"<STR_LIT:=>"+unicode(id)<EOL>self._db._cur.execute(sql, v)<EOL>self._db._i += <NUM_LIT:1><EOL>if self._db._i >= self._db._commit:<EOL><INDENT>self._db._i = <NUM_LIT:0><EOL>self._db._con.commit()<EOL><DEDENT>


def remove(self, id, operator="<STR_LIT:=>", key=None):

if key == None: key = self._key<EOL>try: id = unicode(id)<EOL>except: pass        <EOL>sql = "<STR_LIT>"+self._name+"<STR_LIT>"+key+"<STR_LIT:U+0020>"+operator+"<STR_LIT>"<EOL>self._db._cur.execute(sql, (id,))<EOL>


self._segments = <NUM_LIT:0><EOL>self._duration = <NUM_LIT:0><EOL>

Resets the number of drawn segments and the duration.

        To calculate the number of segments or the total time needed,
        we need to recurse through LSystem._grow().
        Before that, the draw(), segments() and duration() command
        will reset both tally variables.


def _grow(self, generation, rule, angle, length, time=maxint, draw=True):

if generation == <NUM_LIT:0>:<EOL><INDENT>self._duration = <NUM_LIT:1> + maxint-time<EOL><DEDENT>if length <= self.threshold:<EOL><INDENT>self._duration = <NUM_LIT:1> + maxint-time<EOL>return<EOL><DEDENT>if rule in self.commands:<EOL><INDENT>self.commands[rule](self, generation, rule, angle, length, time)<EOL><DEDENT>if draw:<EOL><INDENT>if rule == "<STR_LIT:f>":<EOL><INDENT>_ctx.translate(<NUM_LIT:0>, -min(length, length*time))<EOL><DEDENT>elif rule == "<STR_LIT:->":<EOL><INDENT>_ctx.rotate(max(-angle, -angle*time))<EOL><DEDENT>elif rule == "<STR_LIT:+>":<EOL><INDENT>_ctx.rotate(min(+angle, +angle*time))<EOL><DEDENT>elif rule == "<STR_LIT:|>":<EOL><INDENT>_ctx.rotate(<NUM_LIT>)<EOL><DEDENT>elif rule == "<STR_LIT:[>":<EOL><INDENT>_ctx.push()<EOL><DEDENT>elif rule == "<STR_LIT:]>":<EOL><INDENT>_ctx.pop()<EOL><DEDENT><DEDENT>if rule in self.rulesand generation > <NUM_LIT:0>and time > <NUM_LIT:0>:<EOL><INDENT>for cmd in self.rules[rule]:<EOL><INDENT>if cmd == "<STR_LIT:F>":<EOL><INDENT>time -= self.cost<EOL><DEDENT>elif cmd == "<STR_LIT:!>":<EOL><INDENT>angle = -angle<EOL><DEDENT>elif cmd == "<STR_LIT:(>":<EOL><INDENT>angle *= <NUM_LIT><EOL><DEDENT>elif cmd == "<STR_LIT:)>":<EOL><INDENT>angle *= <NUM_LIT><EOL><DEDENT>elif cmd == "<STR_LIT:<>":<EOL><INDENT>length *= <NUM_LIT><EOL><DEDENT>elif cmd == "<STR_LIT:>>":<EOL><INDENT>length *= <NUM_LIT><EOL><DEDENT>self._grow(<EOL>generation-<NUM_LIT:1>,<EOL>cmd,<EOL>angle,<EOL>length*self.decrease,<EOL>time,<EOL>draw<EOL>)<EOL><DEDENT><DEDENT>elif rule == "<STR_LIT:F>"or (rule in self.rules and self.rules[rule] == "<STR_LIT>"):<EOL><INDENT>self._segments += <NUM_LIT:1><EOL>if draw and time > <NUM_LIT:0>:<EOL><INDENT>length = min(length, length*time)<EOL>if self._timed:<EOL><INDENT>self.segment(length, generation, time, id=self._segments)<EOL><DEDENT>else:<EOL><INDENT>self.segment(length, generation, None, id=self._segments)<EOL><DEDENT>_ctx.translate(<NUM_LIT:0>, -length)<EOL><DEDENT><DEDENT>

Recurse through the system.

        When a segment is drawn, the LSsytem.segment() method will be called.
        You can customize this method to create your own visualizations.
        It takes an optional time parameter.

        If you divide this parameter by LSsytem.duration() you get
        a number between 0.0 and 1.0 you can use as an alpha value for example.

        The method also has an id parameter which is a unique number
        between 0 and LSystem.segments.


def draw(self, x, y, generation, time=None, ease=None):

angle = self.angle<EOL>if time is not None and ease:<EOL><INDENT>angle = min(self.angle, self.angle * time / ease)<EOL><DEDENT>self._timed = True<EOL>if not time:<EOL><INDENT>self._timed = False<EOL>time = maxint<EOL><DEDENT>mode = _ctx.transform()<EOL>_ctx.transform(CORNER)<EOL>_ctx.push()<EOL>_ctx.translate(x, y)<EOL>self._reset()<EOL>self._grow(generation, self.root, angle, self.d, time, draw=True)<EOL>_ctx.pop()<EOL>_ctx.transform(mode)<EOL>

Draws a number of generations at the given position.

        The time parameter can be used to progress the system in an animatiom.
        As time nears LSystem.duration(generation), more segments will be drawn.

        The ease parameter can be used to gradually increase the branching angle
        as more segments are drawn.


def segments(self, generation, time=None):

if not time:<EOL><INDENT>time = maxint<EOL><DEDENT>_ctx.push()<EOL>self._reset()<EOL>self._grow(generation, self.root, self.angle, self.d, time, draw=False)<EOL>_ctx.pop()<EOL>return self._segments<EOL>

Returns the number of segments drawn for a number of generations.

        The number of segments that are drawn to the screen
        depends of the number of generations and the amount of time.
        Each F command has a cost that depletes time.
        Segments will stop being drawn if generation reaches 0,
        when there is no time left
        or when the segment length falls below LSystem.threshold.


_ctx.push()<EOL>self._reset()<EOL>self._grow(generation, self.root, self.angle, self.d, draw=False)<EOL>_ctx.pop()<EOL>return max(self._duration, <NUM_LIT:0.1>)<EOL>

Returns the total draw time needed based on the current cost.

        In an animation, the system will expand as time progresses.
        Each F command that draws a segment has a cost that depletes time.
        To calculate the total amount of time for a number of generations,
        we need to recurse through the system.
        Time does not flow through the system linearly,
        it "branches" from generation to generation.


raise NotImplementedError<EOL>

The method which gets executed when a new state of the object was
received.


raise NotImplementedError<EOL>

The text that should be shown in the object reprentation.


self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)<EOL>self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, <NUM_LIT:1>)<EOL>self.socket.setblocking(<NUM_LIT:0>)<EOL>self.socket.bind((self.host, self.port))<EOL>

Opens the socket and binds to the given host and port. Uses
SO_REUSEADDR to be as robust as possible.


self.socket.close()<EOL>


return self.current_frame >= self.last_frame<EOL>


_profiles = {}<EOL>for name, klass in inspect.getmembers(profiles):<EOL><INDENT>if inspect.isclass(klass) and name.endswith('<STR_LIT>') and name != '<STR_LIT>':<EOL><INDENT>profile = klass()<EOL>_profiles[profile.address] = profile<EOL>try:<EOL><INDENT>setattr(self, profile.list_label, profile.objs)<EOL><DEDENT>except AttributeError:<EOL><INDENT>continue<EOL><DEDENT>self.manager.add(self.callback, profile.address)<EOL><DEDENT><DEDENT>return _profiles<EOL>

Loads all possible TUIO profiles and returns a dictionary with the
profile addresses as keys and an instance of a profile as the value


return self.profiles.get(profile, None)<EOL>

Returns a specific profile from the profile list and otherwise None


return list([profile.list_label for profile in self.profiles.values()])<EOL>

Returns a list of helper functions that provide access to the
        objects of each profile.


try:<EOL><INDENT>self.manager.handle(self.socket.recv(<NUM_LIT>))<EOL><DEDENT>except socket.error:<EOL><INDENT>pass<EOL><DEDENT>

Tells the connection manager to receive the next 1024 byte of messages
to analyze.


message = incoming[<NUM_LIT:0>]<EOL>if message:<EOL><INDENT>address, command = message[<NUM_LIT:0>], message[<NUM_LIT:2>]<EOL>profile = self.get_profile(address)<EOL>if profile is not None:<EOL><INDENT>try:<EOL><INDENT>getattr(profile, command)(self, message)<EOL><DEDENT>except AttributeError:<EOL><INDENT>pass<EOL><DEDENT><DEDENT><DEDENT>

Gets called by the CallbackManager if a new message was received


for i in range(len(bytes)):<EOL><INDENT>sys.stdout.write("<STR_LIT>" % (ord(bytes[i])))<EOL>if (i+<NUM_LIT:1>) % <NUM_LIT:8> == <NUM_LIT:0>:<EOL><INDENT>print(repr(bytes[i-<NUM_LIT:7>:i+<NUM_LIT:1>]))<EOL><DEDENT><DEDENT>if(len(bytes) % <NUM_LIT:8> != <NUM_LIT:0>):<EOL><INDENT>print(string.rjust("<STR_LIT>", <NUM_LIT:11>), repr(bytes[i-len(bytes)%<NUM_LIT:8>:i+<NUM_LIT:1>]))<EOL><DEDENT>

Useful utility; prints the string in hexadecimal


high, low = struct.unpack("<STR_LIT>", data[<NUM_LIT:0>:<NUM_LIT:8>])<EOL>big = (int(high) << <NUM_LIT:32>) + low<EOL>rest = data[<NUM_LIT:8>:]<EOL>return (big, rest)<EOL>

Tries to interpret the next 8 bytes of the data
    as a 64-bit signed integer.


if type(next) == type("<STR_LIT>"):<EOL><INDENT>length = len(next)<EOL>padded = math.ceil((len(next)) / <NUM_LIT>) * <NUM_LIT:4><EOL>binary = struct.pack("<STR_LIT>" % (padded), length, next)<EOL>tag    = '<STR_LIT:b>'<EOL><DEDENT>else:<EOL><INDENT>tag    = '<STR_LIT>'<EOL>binary = '<STR_LIT>'<EOL><DEDENT>return (tag, binary)<EOL>

Convert a string into an OSC Blob,
    returning a (typetag, data) tuple.


if type(next) == type("<STR_LIT>"):<EOL><INDENT>OSCstringLength = math.ceil((len(next)+<NUM_LIT:1>) / <NUM_LIT>) * <NUM_LIT:4><EOL>binary  = struct.pack("<STR_LIT>" % (OSCstringLength), next)<EOL>tag = "<STR_LIT:s>"<EOL><DEDENT>elif type(next) == type(<NUM_LIT>):<EOL><INDENT>binary  = struct.pack("<STR_LIT>", next)<EOL>tag = "<STR_LIT:f>"<EOL><DEDENT>elif type(next) == type(<NUM_LIT>):<EOL><INDENT>binary  = struct.pack("<STR_LIT>", next)<EOL>tag = "<STR_LIT:i>"<EOL><DEDENT>else:<EOL><INDENT>binary  = "<STR_LIT>"<EOL>tag = "<STR_LIT>"<EOL><DEDENT>return (tag, binary)<EOL>

Convert some Python types to their
    OSC binary representations, returning a
    (typetag, data) tuple.


parsed = []<EOL>for arg in args:<EOL><INDENT>print(arg)<EOL>arg = arg.strip()<EOL>interpretation = None<EOL>try:<EOL><INDENT>interpretation = float(arg)<EOL>if string.find(arg, "<STR_LIT:.>") == -<NUM_LIT:1>:<EOL><INDENT>interpretation = int(interpretation)<EOL><DEDENT><DEDENT>except:<EOL><INDENT>interpretation = arg<EOL>pass<EOL><DEDENT>parsed.append(interpretation)<EOL><DEDENT>return parsed<EOL>

Given a list of strings, produces a list
    where those strings have been parsed (where
    possible) as floats or integers.


table = {"<STR_LIT:i>":readInt, "<STR_LIT:f>":readFloat, "<STR_LIT:s>":readString, "<STR_LIT:b>":readBlob}<EOL>decoded = []<EOL>address,  rest = readString(data)<EOL>typetags = "<STR_LIT>"<EOL>if address == "<STR_LIT>":<EOL><INDENT>time, rest = readLong(rest)<EOL>decoded.append(address)<EOL>decoded.append(time)<EOL>while len(rest)><NUM_LIT:0>:<EOL><INDENT>length, rest = readInt(rest)<EOL>decoded.append(decodeOSC(rest[:length]))<EOL>rest = rest[length:]<EOL><DEDENT><DEDENT>elif len(rest) > <NUM_LIT:0>:<EOL><INDENT>typetags, rest = readString(rest)<EOL>decoded.append(address)<EOL>decoded.append(typetags)<EOL>if typetags[<NUM_LIT:0>] == "<STR_LIT:U+002C>":<EOL><INDENT>for tag in typetags[<NUM_LIT:1>:]:<EOL><INDENT>value, rest = table[tag](rest)<EOL>decoded.append(value)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>print("<STR_LIT>")<EOL><DEDENT><DEDENT>return decoded<EOL>

Converts a typetagged OSC message to a Python list.


def append(self, argument, typehint = None):

if typehint == '<STR_LIT:b>':<EOL><INDENT>binary = OSCBlob(argument)<EOL><DEDENT>else:<EOL><INDENT>binary = OSCArgument(argument)<EOL><DEDENT>self.typetags = self.typetags + binary[<NUM_LIT:0>]<EOL>self.rawAppend(binary[<NUM_LIT:1>])<EOL>

Appends data to the message,
        updating the typetags based on
        the argument's type.
        If the argument is a blob (counted string)
        pass in 'b' as typehint.


self.message = self.message + data<EOL>

Appends raw data to the message.  Use append().


address  = OSCArgument(self.address)[<NUM_LIT:1>]<EOL>typetags = OSCArgument(self.typetags)[<NUM_LIT:1>]<EOL>return address + typetags + self.message<EOL>

Returns the binary message (so far) with typetags.


decoded = decodeOSC(data)<EOL>self.dispatch(decoded, source)<EOL>

Given OSC data, tries to call the callback with the
        right address.


def dispatch(self, message, source = None):

msgtype = "<STR_LIT>"<EOL>try:<EOL><INDENT>if type(message[<NUM_LIT:0>]) == str:<EOL><INDENT>address = message[<NUM_LIT:0>]<EOL>self.callbacks[address](message)<EOL><DEDENT>elif type(message[<NUM_LIT:0>]) == list:<EOL><INDENT>for msg in message:<EOL><INDENT>self.dispatch(msg)<EOL><DEDENT><DEDENT><DEDENT>except KeyError as key:<EOL><INDENT>print('<STR_LIT>' % (address, key, message))<EOL>pprint.pprint(message)<EOL><DEDENT>except IndexError as e:<EOL><INDENT>print('<STR_LIT>' % (e, message))<EOL>pass<EOL><DEDENT>except None as e:<EOL><INDENT>print("<STR_LIT>", address, "<STR_LIT>", e)<EOL><DEDENT>return<EOL>

Sends decoded OSC data to an appropriate calback


if callback == None:<EOL><INDENT>del self.callbacks[name]<EOL><DEDENT>else:<EOL><INDENT>self.callbacks[name] = callback<EOL><DEDENT>

Adds a callback to our set of callbacks,
        or removes the callback with name if callback
        is None.


<EOL>for message in messages[<NUM_LIT:2>:]:<EOL><INDENT>self.dispatch(message)<EOL><DEDENT>

Dispatch the messages in a decoded bundle.


raise NotImplementedError<EOL>

The state of each alive (but unchanged) fiducial is periodically
resent with 'set' messages.


raise NotImplementedError<EOL>

The 'alive' message contains the session ids of all alive fiducials
known to reacTIVision.


client.last_frame = client.current_frame<EOL>client.current_frame = message[<NUM_LIT:3>]<EOL>

fseq messages associate a unique frame id with a set of set
and alive messages


for obj in self.objects.itervalues():<EOL><INDENT>if obj.sessionid in self.sessions:<EOL><INDENT>yield obj<EOL><DEDENT><DEDENT>

Returns a generator list of tracked objects which are recognized with
this profile and are in the current session.


hex = hex.lstrip("<STR_LIT:#>")<EOL>if len(hex) < <NUM_LIT:6>:<EOL><INDENT>hex += hex[-<NUM_LIT:1>] * (<NUM_LIT:6> - len(hex))<EOL><DEDENT>r, g, b = hex[<NUM_LIT:0>:<NUM_LIT:2>], hex[<NUM_LIT:2>:<NUM_LIT:4>], hex[<NUM_LIT:4>:]<EOL>r, g, b = [int(n, <NUM_LIT:16>) / <NUM_LIT> for n in (r, g, b)]<EOL>return r, g, b<EOL>

Returns RGB values for a hex color string.


y = (l + <NUM_LIT:16>) / <NUM_LIT><EOL>x = a / <NUM_LIT> + y<EOL>z = y - b / <NUM_LIT><EOL>v = [x, y, z]<EOL>for i in _range(<NUM_LIT:3>):<EOL><INDENT>if pow(v[i], <NUM_LIT:3>) > <NUM_LIT>:<EOL><INDENT>v[i] = pow(v[i], <NUM_LIT:3>)<EOL><DEDENT>else:<EOL><INDENT>v[i] = (v[i] - <NUM_LIT:16> / <NUM_LIT>) / <NUM_LIT><EOL><DEDENT><DEDENT>x = v[<NUM_LIT:0>] * <NUM_LIT> / <NUM_LIT:100><EOL>y = v[<NUM_LIT:1>] * <NUM_LIT> / <NUM_LIT:100><EOL>z = v[<NUM_LIT:2>] * <NUM_LIT> / <NUM_LIT:100><EOL>r = x * <NUM_LIT> + y * -<NUM_LIT> + z * -<NUM_LIT><EOL>g = x * -<NUM_LIT> + y * <NUM_LIT> + z * <NUM_LIT><EOL>b = x * <NUM_LIT> + y * -<NUM_LIT> + z * <NUM_LIT><EOL>v = [r, g, b]<EOL>for i in _range(<NUM_LIT:3>):<EOL><INDENT>if v[i] > <NUM_LIT>:<EOL><INDENT>v[i] = <NUM_LIT> * pow(v[i], <NUM_LIT:1> / <NUM_LIT>) - <NUM_LIT><EOL><DEDENT>else:<EOL><INDENT>v[i] = <NUM_LIT> * v[i]<EOL><DEDENT><DEDENT>r, g, b = v[<NUM_LIT:0>], v[<NUM_LIT:1>], v[<NUM_LIT:2>]<EOL>return r, g, b<EOL>

Converts CIE Lab to RGB components.

    First we have to convert to XYZ color space.
    Conversion involves using a white point,
    in this case D65 which represents daylight illumination.

    Algorithm adopted from:
    http://www.easyrgb.com/math.php


r = <NUM_LIT:1.0> - min(<NUM_LIT:1.0>, c + k)<EOL>g = <NUM_LIT:1.0> - min(<NUM_LIT:1.0>, m + k)<EOL>b = <NUM_LIT:1.0> - min(<NUM_LIT:1.0>, y + k)<EOL>return r, g, b<EOL>

Cyan, magenta, yellow, black to red, green, blue.
    ReportLab, http://www.koders.com/python/fid5C006F554616848C01AC7CB96C21426B69D2E5A9.aspx
    Results will differ from the way NSColor converts color spaces.


if s == <NUM_LIT:0>: return v, v, v<EOL>h = h / (<NUM_LIT> / <NUM_LIT>)<EOL>i = floor(h)<EOL>f = h - i<EOL>p = v * (<NUM_LIT:1> - s)<EOL>q = v * (<NUM_LIT:1> - s * f)<EOL>t = v * (<NUM_LIT:1> - s * (<NUM_LIT:1> - f))<EOL>if i == <NUM_LIT:0>:<EOL><INDENT>r = v;<EOL>g = t;<EOL>b = p<EOL><DEDENT>elif i == <NUM_LIT:1>:<EOL><INDENT>r = q;<EOL>g = v;<EOL>b = p<EOL><DEDENT>elif i == <NUM_LIT:2>:<EOL><INDENT>r = p;<EOL>g = v;<EOL>b = t<EOL><DEDENT>elif i == <NUM_LIT:3>:<EOL><INDENT>r = p;<EOL>g = q;<EOL>b = v<EOL><DEDENT>elif i == <NUM_LIT:4>:<EOL><INDENT>r = t;<EOL>g = p;<EOL>b = v<EOL><DEDENT>else:<EOL><INDENT>r = v;<EOL>g = p;<EOL>b = q<EOL><DEDENT>return r, g, b<EOL>

Hue, saturation, brightness to red, green, blue.
    http://www.koders.com/python/fidB2FE963F658FE74D9BF74EB93EFD44DCAE45E10E.aspx
    Results will differ from the way NSColor converts color spaces.


clr = color(clr)<EOL>colors = colorlist(clr)<EOL>colors.append(clr.complement)<EOL>return colors<EOL>

Returns the color and its complement in a list.


clr = color(clr)<EOL>colors = colorlist(clr)<EOL>c = clr.copy()<EOL>if clr.brightness > <NUM_LIT>:<EOL><INDENT>c.brightness = <NUM_LIT:0.1> + c.brightness * <NUM_LIT><EOL><DEDENT>else:<EOL><INDENT>c.brightness = <NUM_LIT:1.0> - c.brightness * <NUM_LIT><EOL><DEDENT>colors.append(c)<EOL>c = clr.copy()<EOL>c.brightness = <NUM_LIT> + c.brightness<EOL>c.saturation = <NUM_LIT:0.1> + c.saturation * <NUM_LIT><EOL>colors.append(c)<EOL>clr = clr.complement<EOL>c = clr.copy()<EOL>if clr.brightness > <NUM_LIT>:<EOL><INDENT>c.brightness = <NUM_LIT:0.1> + clr.brightness * <NUM_LIT><EOL><DEDENT>else:<EOL><INDENT>c.brightness = <NUM_LIT:1.0> - c.brightness * <NUM_LIT><EOL><DEDENT>colors.append(c)<EOL>colors.append(clr)<EOL>c = clr.copy()<EOL>c.brightness = <NUM_LIT> + c.brightness<EOL>c.saturation = <NUM_LIT:0.1> + c.saturation * <NUM_LIT><EOL>colors.append(c)<EOL>return colors<EOL>

Returns a list of complementary colors.

The complement is the color 180 degrees across
the artistic RYB color wheel.
The list contains darker and softer contrasting
and complementing colors.


clr = color(clr)<EOL>colors = colorlist(clr)<EOL>clr = clr.complement<EOL>colors.append(clr.rotate_ryb(-<NUM_LIT:30>).lighten(<NUM_LIT:0.1>))<EOL>colors.append(clr.rotate_ryb(<NUM_LIT:30>).lighten(<NUM_LIT:0.1>))<EOL>return colors<EOL>

Returns a list with the split complement of the color.

The split complement are the two colors to the left and right
of the color's complement.


left = split_complementary(clr)[<NUM_LIT:1>]<EOL>colors = complementary(clr)<EOL>colors[<NUM_LIT:3>].h = left.h<EOL>colors[<NUM_LIT:4>].h = left.h<EOL>colors[<NUM_LIT:5>].h = left.h<EOL>colors = colorlist(<EOL>colors[<NUM_LIT:0>], colors[<NUM_LIT:2>], colors[<NUM_LIT:1>], colors[<NUM_LIT:3>], colors[<NUM_LIT:4>], colors[<NUM_LIT:5>]<EOL>)<EOL>return colors<EOL>

Returns the left half of the split complement.

A list is returned with the same darker and softer colors
as in the complementary list, but using the hue of the
left split complement instead of the complement itself.


right = split_complementary(clr)[<NUM_LIT:2>]<EOL>colors = complementary(clr)<EOL>colors[<NUM_LIT:3>].h = right.h<EOL>colors[<NUM_LIT:4>].h = right.h<EOL>colors[<NUM_LIT:5>].h = right.h<EOL>colors = colorlist(<EOL>colors[<NUM_LIT:0>], colors[<NUM_LIT:2>], colors[<NUM_LIT:1>], colors[<NUM_LIT:5>], colors[<NUM_LIT:4>], colors[<NUM_LIT:3>]<EOL>)<EOL>return colors<EOL>

Returns the right half of the split complement.


def analogous(clr, angle=<NUM_LIT:10>, contrast=<NUM_LIT>):

contrast = max(<NUM_LIT:0>, min(contrast, <NUM_LIT:1.0>))<EOL>clr = color(clr)<EOL>colors = colorlist(clr)<EOL>for i, j in [(<NUM_LIT:1>, <NUM_LIT>), (<NUM_LIT:2>, <NUM_LIT:1>), (-<NUM_LIT:1>, -<NUM_LIT:0.5>), (-<NUM_LIT:2>, <NUM_LIT:1>)]:<EOL><INDENT>c = clr.rotate_ryb(angle * i)<EOL>t = <NUM_LIT> - j * <NUM_LIT:0.1><EOL>if clr.brightness - contrast * j < t:<EOL><INDENT>c.brightness = t<EOL><DEDENT>else:<EOL><INDENT>c.brightness = clr.brightness - contrast * j<EOL><DEDENT>c.saturation -= <NUM_LIT><EOL>colors.append(c)<EOL><DEDENT>return colors<EOL>

Returns colors that are next to each other on the wheel.

These yield natural color schemes (like shades of water or sky).
The angle determines how far the colors are apart,
making it bigger will introduce more variation.
The contrast determines the darkness/lightness of
the analogue colors in respect to the given colors.


def _wrap(x, min, threshold, plus):<EOL><INDENT>if x - min < threshold:<EOL><INDENT>return x + plus<EOL><DEDENT>else:<EOL><INDENT>return x - min<EOL><DEDENT><DEDENT>colors = colorlist(clr)<EOL>c = clr.copy()<EOL>c.brightness = _wrap(clr.brightness, <NUM_LIT:0.5>, <NUM_LIT>, <NUM_LIT>)<EOL>c.saturation = _wrap(clr.saturation, <NUM_LIT>, <NUM_LIT:0.1>, <NUM_LIT>)<EOL>colors.append(c)<EOL>c = clr.copy()<EOL>c.brightness = _wrap(clr.brightness, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>)<EOL>colors.append(c)<EOL>c = clr.copy()<EOL>c.brightness = max(<NUM_LIT>, clr.brightness + (<NUM_LIT:1> - clr.brightness) * <NUM_LIT>)<EOL>c.saturation = _wrap(clr.saturation, <NUM_LIT>, <NUM_LIT:0.1>, <NUM_LIT>)<EOL>colors.append(c)<EOL>c = clr.copy()<EOL>c.brightness = _wrap(clr.brightness, <NUM_LIT:0.5>, <NUM_LIT>, <NUM_LIT>)<EOL>colors.append(c)<EOL>return colors<EOL>

Returns colors in the same hue with varying brightness/saturation.


clr = color(clr)<EOL>colors = colorlist(clr)<EOL>colors.append(clr.rotate_ryb(angle).lighten(<NUM_LIT:0.1>))<EOL>colors.append(clr.rotate_ryb(-angle).lighten(<NUM_LIT:0.1>))<EOL>return colors<EOL>

Returns a triad of colors.

The triad is made up of this color and two other colors
that together make up an equilateral triangle on
the artistic color wheel.


clr = color(clr)<EOL>colors = colorlist(clr)<EOL>c = clr.rotate_ryb(angle)<EOL>if clr.brightness < <NUM_LIT:0.5>:<EOL><INDENT>c.brightness += <NUM_LIT><EOL><DEDENT>else:<EOL><INDENT>c.brightness -= -<NUM_LIT><EOL><DEDENT>colors.append(c)<EOL>c = clr.rotate_ryb(angle * <NUM_LIT:2>)<EOL>if clr.brightness < <NUM_LIT:0.5>:<EOL><INDENT>c.brightness += <NUM_LIT:0.1><EOL><DEDENT>else:<EOL><INDENT>c.brightness -= -<NUM_LIT:0.1><EOL><DEDENT>colors.append(c)<EOL>colors.append(clr.rotate_ryb(angle * <NUM_LIT:3>).lighten(<NUM_LIT:0.1>))<EOL>return colors<EOL>

Returns a tetrad of colors.

The tetrad is made up of this color and three other colors
that together make up a cross on the artistic color wheel.


def _wrap(x, min, threshold, plus):<EOL><INDENT>if x - min < threshold:<EOL><INDENT>return x + plus<EOL><DEDENT>else:<EOL><INDENT>return x - min<EOL><DEDENT><DEDENT>d = <NUM_LIT:1><EOL>if flip: d = -<NUM_LIT:1><EOL>clr = color(clr)<EOL>colors = colorlist(clr)<EOL>c = clr.rotate_ryb(<NUM_LIT:30> * d)<EOL>c.brightness = _wrap(clr.brightness, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>)<EOL>colors.append(c)<EOL>c = clr.rotate_ryb(<NUM_LIT:30> * d)<EOL>c.saturation = _wrap(clr.saturation, <NUM_LIT>, <NUM_LIT:0.1>, <NUM_LIT>)<EOL>c.brightness = _wrap(clr.brightness, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>)<EOL>colors.append(c)<EOL>c = clr.rotate_ryb(<NUM_LIT> * d)<EOL>c.saturation = _wrap(clr.saturation, <NUM_LIT>, <NUM_LIT:0.1>, <NUM_LIT>)<EOL>c.brightness = max(<NUM_LIT>, clr.brightness)<EOL>colors.append(c)<EOL>c = clr.rotate_ryb(<NUM_LIT> * d)<EOL>c.saturation = _wrap(clr.saturation, <NUM_LIT:0.1>, <NUM_LIT>, <NUM_LIT:0.1>)<EOL>c.brightness = _wrap(clr.brightness, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>)<EOL>colors.append(c)<EOL>c = clr.rotate_ryb(<NUM_LIT> * d)<EOL>c.saturation = _wrap(clr.saturation, <NUM_LIT:0.1>, <NUM_LIT>, <NUM_LIT:0.1>)<EOL>c.brightness = _wrap(clr.brightness, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>)<EOL>return colors<EOL>

Roughly the complement and some far analogs.


def outline(path, colors, precision=<NUM_LIT>, continuous=True):

<EOL>def _point_count(path, precision):<EOL><INDENT>return max(int(path.length * precision * <NUM_LIT:0.5>), <NUM_LIT:10>)<EOL><DEDENT>n = sum([_point_count(contour, precision) for contour in path.contours])<EOL>contour_i = <NUM_LIT:0><EOL>contour_n = len(path.contours) - <NUM_LIT:1><EOL>if contour_n == <NUM_LIT:0>: continuous = False<EOL>i = <NUM_LIT:0><EOL>for contour in path.contours:<EOL><INDENT>if not continuous: i = <NUM_LIT:0><EOL>j = _point_count(contour, precision)<EOL>first = True<EOL>for pt in contour.points(j):<EOL><INDENT>if first:<EOL><INDENT>first = False<EOL><DEDENT>else:<EOL><INDENT>if not continuous:<EOL><INDENT>clr = float(i) / j * len(colors)<EOL><DEDENT>else:<EOL><INDENT>clr = float(i) / n * len(colors) - <NUM_LIT:1> * contour_i / contour_n<EOL><DEDENT>_ctx.stroke(colors[int(clr)])<EOL>_ctx.line(x0, y0, pt.x, pt.y)<EOL><DEDENT>x0 = pt.x<EOL>y0 = pt.y<EOL>i += <NUM_LIT:1><EOL><DEDENT>pt = contour.point(<NUM_LIT>)  <EOL>_ctx.line(x0, y0, pt.x, pt.y)<EOL>contour_i += <NUM_LIT:1><EOL><DEDENT>

Outlines each contour in a path with the colors in the list.

Each contour starts with the first color in the list,
and ends with the last color in the list.

Because each line segment is drawn separately,
works only with corner-mode transforms.


clr = Color(clr)<EOL>if clr.is_transparent: return "<STR_LIT>"<EOL>if clr.is_black: return "<STR_LIT>"<EOL>if clr.is_white: return "<STR_LIT>"<EOL>if clr.is_black: return "<STR_LIT>"<EOL>for name in named_colors:<EOL><INDENT>try:<EOL><INDENT>r, g, b = named_colors[name]<EOL><DEDENT>except:<EOL><INDENT>continue<EOL><DEDENT>if r == clr.r and g == clr.g and b == clr.b:<EOL><INDENT>return name<EOL><DEDENT><DEDENT>for shade in shades:<EOL><INDENT>if clr in shade:<EOL><INDENT>return shade.name + "<STR_LIT:U+0020>" + clr.nearest_hue()<EOL>break<EOL><DEDENT><DEDENT>return clr.nearest_hue()<EOL>

Guesses the shade and hue name of a color.

If the given color is named in the named_colors list, return that name.
Otherwise guess its nearest hue and shade range.


def shader(x, y, dx, dy, radius=<NUM_LIT>, angle=<NUM_LIT:0>, spread=<NUM_LIT>):

if angle != None:<EOL><INDENT>radius *= <NUM_LIT:2><EOL><DEDENT>d = sqrt((dx - x) ** <NUM_LIT:2> + (dy - y) ** <NUM_LIT:2>)<EOL>a = degrees(atan2(dy - y, dx - x)) + <NUM_LIT><EOL>if d <= radius:<EOL><INDENT>d1 = <NUM_LIT:1.0> * d / radius<EOL><DEDENT>else:<EOL><INDENT>d1 = <NUM_LIT:1.0><EOL><DEDENT>if angle is None:<EOL><INDENT>return <NUM_LIT:1> - d1<EOL><DEDENT>angle = <NUM_LIT> - angle % <NUM_LIT><EOL>spread = max(<NUM_LIT:0>, min(spread, <NUM_LIT>))<EOL>if spread == <NUM_LIT:0>:<EOL><INDENT>return <NUM_LIT:0.0><EOL><DEDENT>d = abs(a - angle)<EOL>if d <= spread / <NUM_LIT:2>:<EOL><INDENT>d2 = d / spread + d1<EOL><DEDENT>else:<EOL><INDENT>d2 = <NUM_LIT:1.0><EOL><DEDENT>if <NUM_LIT> - angle <= spread / <NUM_LIT:2>:<EOL><INDENT>d = abs(<NUM_LIT> - angle + a)<EOL>if d <= spread / <NUM_LIT:2>:<EOL><INDENT>d2 = d / spread + d1<EOL><DEDENT><DEDENT>if angle < spread / <NUM_LIT:2>:<EOL><INDENT>d = abs(<NUM_LIT> + angle - a)<EOL>if d <= spread / <NUM_LIT:2>:<EOL><INDENT>d2 = d / spread + d1<EOL><DEDENT><DEDENT>return <NUM_LIT:1> - max(<NUM_LIT:0>, min(d2, <NUM_LIT:1>))<EOL>

Returns a 0.0 - 1.0 brightness adjusted to a light source.

The light source is positioned at dx, dy.
The returned float is calculated for x, y position
(e.g. an oval at x, y should have this brightness).

The radius influences the strength of the light,
angle and spread control the direction of the light.


global _aggregated_name, _aggregated_dict<EOL>if _aggregated_name != cache:<EOL><INDENT>_aggregated_name = cache<EOL>_aggregated_dict = {}<EOL>for path in glob(os.path.join(cache, "<STR_LIT:*>")):<EOL><INDENT>if os.path.isdir(path):<EOL><INDENT>p = os.path.basename(path)<EOL>_aggregated_dict[p] = glob(os.path.join(path, "<STR_LIT:*>"))<EOL>_aggregated_dict[p] = [os.path.basename(f)[:-<NUM_LIT:4>] for f in _aggregated_dict[p]]<EOL><DEDENT><DEDENT><DEDENT>return _aggregated_dict<EOL>

A dictionary of all aggregated words.

They keys in the dictionary correspond to subfolders in the aggregated cache.
Each key has a list of words. Each of these words is the name of an XML-file
in the subfolder. The XML-file contains color information harvested from the web
(or handmade).


def search_engine(query, top=<NUM_LIT:5>, service="<STR_LIT>", license=None,<EOL>cache=os.path.join(DEFAULT_CACHE, "<STR_LIT>")):

<EOL>try:<EOL><INDENT>a = theme(query, cache=cache)<EOL>return a<EOL><DEDENT>except:<EOL><INDENT>pass<EOL><DEDENT>if service == "<STR_LIT>":<EOL><INDENT>from web import google<EOL>search_engine = google<EOL><DEDENT>if service == "<STR_LIT>":<EOL><INDENT>from web import yahoo<EOL>search_engine = yahoo<EOL>if license:<EOL><INDENT>yahoo.license_key = license<EOL><DEDENT><DEDENT>sorted_colors = search_engine.sort(<EOL>[h for h in primary_hues] + ["<STR_LIT>", "<STR_LIT>"],<EOL>context=query, strict=True, cached=True<EOL>)<EOL>sorted_shades = search_engine.sort(<EOL>[str(s) for s in shades],<EOL>context=query, strict=True, cached=True<EOL>)<EOL>f = lambda x: x.strip("<STR_LIT>").split()[<NUM_LIT:0>]<EOL>n2 = sum([w for h, w in sorted_colors[:top]])<EOL>sorted_colors = [(color(f(h)), w / n2) for h, w in sorted_colors[:top]]<EOL>n2 = sum([w for s, w in sorted_shades[:<NUM_LIT:3>]])<EOL>sorted_shades = [(shade(f(s)), w / n2) for s, w in sorted_shades[:<NUM_LIT:3>]]<EOL>a = theme(cache=cache)<EOL>a.name = query<EOL>for clr, w1 in sorted_colors:<EOL><INDENT>for rng, w2 in sorted_shades:<EOL><INDENT>a.add_range(rng, clr, w1 * w2)<EOL><DEDENT><DEDENT>a._save()<EOL>return a<EOL>

Return a color aggregate from colors and ranges parsed from the web.
T. De Smedt, http://nodebox.net/code/index.php/Prism


def morguefile(query, n=<NUM_LIT:10>, top=<NUM_LIT:10>):

from web import morguefile<EOL>images = morguefile.search(query)[:top]<EOL>path = choice(images).download(thumbnail=True, wait=<NUM_LIT:10>)<EOL>return ColorList(path, n, name=query)<EOL>

Returns a list of colors drawn from a morgueFile image.

With the Web library installed,
downloads a thumbnail from morgueFile and retrieves pixel colors.


self.name = "<STR_LIT>"<EOL>RGB = Bot.RGB<EOL>HSB = Bot.HSB<EOL>mode, range = _ctx.color_mode, _ctx.color_range<EOL>modes = [RGB, HSB]<EOL>if len(args) == <NUM_LIT:1>and isinstance(args[<NUM_LIT:0>], (str, unicode)):<EOL><INDENT>if args[<NUM_LIT:0>].startswith("<STR_LIT:#>"):<EOL><INDENT>r, g, b = hex_to_rgb(args[<NUM_LIT:0>])<EOL>a = <NUM_LIT:1.0><EOL><DEDENT>else:<EOL><INDENT>v = self.str_to_rgb(args[<NUM_LIT:0>])<EOL>if len(v) == <NUM_LIT:3>:<EOL><INDENT>r, g, b = v<EOL>a = <NUM_LIT:1.0><EOL><DEDENT>else:<EOL><INDENT>r, g, b, a = v<EOL><DEDENT>self.name = args[<NUM_LIT:0>]<EOL><DEDENT>_ctx.colormode(RGB, <NUM_LIT:1.0>)<EOL>BaseColor.__init__(self, r, g, b, a, mode='<STR_LIT>', color_range=<NUM_LIT:1.0>)<EOL><DEDENT>elif len(args) == <NUM_LIT:1>and isinstance(args[<NUM_LIT:0>], BaseColor):<EOL><INDENT>_ctx.colormode(RGB, <NUM_LIT:1.0>)<EOL>BaseColor.__init__(self, args[<NUM_LIT:0>].r, args[<NUM_LIT:0>].g, args[<NUM_LIT:0>].b, args[<NUM_LIT:0>].a, mode='<STR_LIT>', color_range=<NUM_LIT:1.0>)<EOL><DEDENT>elif kwargs.has_key("<STR_LIT>")and kwargs["<STR_LIT>"].lower() == "<STR_LIT>":<EOL><INDENT>if kwargs.has_key("<STR_LIT:l>") andkwargs.has_key("<STR_LIT:a>") andkwargs.has_key("<STR_LIT:b>"):<EOL><INDENT>r, g, b = lab_to_rgb(kwargs["<STR_LIT:l>"], kwargs["<STR_LIT:a>"], kwargs["<STR_LIT:b>"])<EOL><DEDENT>else:<EOL><INDENT>r, g, b = lab_to_rgb(*args)<EOL><DEDENT>_ctx.colormode(RGB, <NUM_LIT:1.0>)<EOL>BaseColor.__init__(self, r, g, b, <NUM_LIT:1>, mode='<STR_LIT>', color_range=<NUM_LIT:1.0>)<EOL><DEDENT>elif (kwargs.has_key("<STR_LIT>")and kwargs["<STR_LIT>"].lower() in modes)or mode in modes:<EOL><INDENT>m, ra = mode, range<EOL>if kwargs.has_key("<STR_LIT>"): m = kwargs["<STR_LIT>"]<EOL>if kwargs.has_key("<STR_LIT>"):<EOL><INDENT>ra = kwargs["<STR_LIT>"]<EOL><DEDENT>else:<EOL><INDENT>ra = <NUM_LIT:1.0><EOL><DEDENT>if m == "<STR_LIT>":<EOL><INDENT>if kwargs.has_key("<STR_LIT:h>") andkwargs.has_key("<STR_LIT:s>") andkwargs.has_key("<STR_LIT:v>"):<EOL><INDENT>r, g, b = hsv_to_rgb(kwargs["<STR_LIT:h>"], kwargs["<STR_LIT:s>"], kwargs["<STR_LIT:v>"])<EOL><DEDENT>else:<EOL><INDENT>h, s, l, a = (args)<EOL>r, g, b = hsv_to_rgb(h, s, l)<EOL><DEDENT><DEDENT>elif m == "<STR_LIT>":<EOL><INDENT>if kwargs.has_key("<STR_LIT:r>") andkwargs.has_key("<STR_LIT:g>") andkwargs.has_key("<STR_LIT:b>"):<EOL><INDENT>r, g, b = kwargs["<STR_LIT:r>"], kwargs["<STR_LIT:g>"], kwargs["<STR_LIT:b>"]<EOL><DEDENT>else:<EOL><INDENT>if len(args) == <NUM_LIT:3>:<EOL><INDENT>r, g, b = args<EOL>a = <NUM_LIT:1.0><EOL><DEDENT>else:<EOL><INDENT>r, g, b, a = (args)<EOL><DEDENT><DEDENT>_ctx.colormode(RGB, ra)<EOL>BaseColor.__init__(self, r, g, b, a, mode='<STR_LIT>', color_range=ra)<EOL><DEDENT><DEDENT>if kwargs.has_key("<STR_LIT:name>") and kwargs["<STR_LIT:name>"] != "<STR_LIT>":<EOL><INDENT>self.name = kwargs["<STR_LIT:name>"]<EOL><DEDENT>elif self.name == "<STR_LIT>":<EOL><INDENT>self.name = self.nearest_hue()<EOL><DEDENT>_ctx.colormode(mode, range)<EOL>

Color object with string input and adjustment methods.

        Accepts strings that are (or resemble) named colors, hex strings,
        RGB, CMYK, HSB and Lab values.

        You can supply a "name" parameter.
        Other valid named parameters are "mode" and "range",
        which default to the state colormode and color range.


str = str.lower()<EOL>for ch in "<STR_LIT>":<EOL><INDENT>str = str.replace(ch, "<STR_LIT>")<EOL><DEDENT>if named_colors.has_key(str):<EOL><INDENT>return named_colors[str]<EOL><DEDENT>for suffix in ["<STR_LIT>", "<STR_LIT>", "<STR_LIT:y>", "<STR_LIT>"]:<EOL><INDENT>str = re.sub("<STR_LIT>" + suffix + "<STR_LIT:$>", "<STR_LIT>", str)<EOL><DEDENT>str = re.sub("<STR_LIT>", "<STR_LIT>", str)<EOL>matches = []<EOL>for name in named_colors:<EOL><INDENT>if name in str or str in name:<EOL><INDENT>matches.append(named_colors[name])<EOL><DEDENT><DEDENT>if len(matches) > <NUM_LIT:0>:<EOL><INDENT>return choice(matches)<EOL><DEDENT>return named_colors["<STR_LIT>"]<EOL>

Returns RGB values based on a descriptive string.

        If the given str is a named color, return its RGB values.
        Otherwise, return a random named color that has str
        in its name, or a random named color which name appears in str.

        Specific suffixes (-ish, -ed, -y and -like) are recognised
        as well, for example, if you need a random variation of "red"
        you can use reddish (or greenish, yellowy, etc.)


h = self.h * <NUM_LIT><EOL>angle = angle % <NUM_LIT><EOL>wheel = [<EOL>(<NUM_LIT:0>, <NUM_LIT:0>), (<NUM_LIT:15>, <NUM_LIT:8>),<EOL>(<NUM_LIT:30>, <NUM_LIT>), (<NUM_LIT>, <NUM_LIT>),<EOL>(<NUM_LIT>, <NUM_LIT>), (<NUM_LIT>, <NUM_LIT>),<EOL>(<NUM_LIT>, <NUM_LIT>), (<NUM_LIT>, <NUM_LIT>),<EOL>(<NUM_LIT>, <NUM_LIT>), (<NUM_LIT>, <NUM_LIT>),<EOL>(<NUM_LIT>, <NUM_LIT>), (<NUM_LIT>, <NUM_LIT>),<EOL>(<NUM_LIT>, <NUM_LIT>), (<NUM_LIT>, <NUM_LIT>),<EOL>(<NUM_LIT>, <NUM_LIT>), (<NUM_LIT>, <NUM_LIT>),<EOL>(<NUM_LIT>, <NUM_LIT>), (<NUM_LIT:255>, <NUM_LIT>),<EOL>(<NUM_LIT>, <NUM_LIT>), (<NUM_LIT>, <NUM_LIT>),<EOL>(<NUM_LIT>, <NUM_LIT>), (<NUM_LIT>, <NUM_LIT>),<EOL>(<NUM_LIT>, <NUM_LIT>), (<NUM_LIT>, <NUM_LIT>),<EOL>(<NUM_LIT>, <NUM_LIT:0>)<EOL>]<EOL>for i in _range(len(wheel) - <NUM_LIT:1>):<EOL><INDENT>x0, y0 = wheel[i]<EOL>x1, y1 = wheel[i + <NUM_LIT:1>]<EOL>if y1 < y0:<EOL><INDENT>y1 += <NUM_LIT><EOL><DEDENT>if y0 <= h <= y1:<EOL><INDENT>a = <NUM_LIT:1.0> * x0 + (x1 - x0) * (h - y0) / (y1 - y0)<EOL>break<EOL><DEDENT><DEDENT>a = (a + angle) % <NUM_LIT><EOL>for i in _range(len(wheel) - <NUM_LIT:1>):<EOL><INDENT>x0, y0 = wheel[i]<EOL>x1, y1 = wheel[i + <NUM_LIT:1>]<EOL>if y1 < y0:<EOL><INDENT>y1 += <NUM_LIT><EOL><DEDENT>if x0 <= a <= x1:<EOL><INDENT>h = <NUM_LIT:1.0> * y0 + (y1 - y0) * (a - x0) / (x1 - x0)<EOL>break<EOL><DEDENT><DEDENT>h = h % <NUM_LIT><EOL>return Color(h / <NUM_LIT>, self.s, self.brightness, self.a, mode="<STR_LIT>", name="<STR_LIT>")<EOL>

Returns a color rotated on the artistic RYB color wheel.

        An artistic color wheel has slightly different opposites
        (e.g. purple-yellow instead of purple-lime).
        It is mathematically incorrect but generally assumed
        to provide better complementary colors.

        http://en.wikipedia.org/wiki/RYB_color_model


if self.is_black:<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT>elif self.is_white:<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT>elif self.is_grey:<EOL><INDENT>return "<STR_LIT>"<EOL><DEDENT>if primary:<EOL><INDENT>hues = primary_hues<EOL><DEDENT>else:<EOL><INDENT>hues = named_hues.keys()<EOL><DEDENT>nearest, d = "<STR_LIT>", <NUM_LIT:1.0><EOL>for hue in hues:<EOL><INDENT>if abs(self.hue - named_hues[hue]) % <NUM_LIT:1> < d:<EOL><INDENT>nearest, d = hue, abs(self.hue - named_hues[hue]) % <NUM_LIT:1><EOL><DEDENT><DEDENT>return nearest<EOL>

Returns the name of the nearest named hue.

        For example,
        if you supply an indigo color (a color between blue and violet),
        the return value is "violet". If primary is set  to True,
        the return value is "purple".

        Primary colors leave out the fuzzy lime, teal,
        cyan, azure and violet hues.


def blend(self, clr, factor=<NUM_LIT:0.5>):

r = self.r * (<NUM_LIT:1> - factor) + clr.r * factor<EOL>g = self.g * (<NUM_LIT:1> - factor) + clr.g * factor<EOL>b = self.b * (<NUM_LIT:1> - factor) + clr.b * factor<EOL>a = self.a * (<NUM_LIT:1> - factor) + clr.a * factor<EOL>return Color(r, g, b, a, mode="<STR_LIT>")<EOL>


coord = lambda a, d: (cos(radians(a)) * d, sin(radians(a)) * d)<EOL>x0, y0 = coord(self.h * <NUM_LIT>, self.s)<EOL>x1, y1 = coord(clr.h * <NUM_LIT>, clr.s)<EOL>z0 = self.brightness<EOL>z1 = clr.brightness<EOL>d = sqrt((x1 - x0) ** <NUM_LIT:2> + (y1 - y0) ** <NUM_LIT:2> + (z1 - z0) ** <NUM_LIT:2>)<EOL>return d<EOL>

Returns the Euclidean distance between two colors (0.0-1.0).

Consider colors arranged on the color wheel:
- hue is the angle of a color along the center
- saturation is the distance of a color from the center
- brightness is the elevation of a color from the center
  (i.e. we're on color a sphere)


def swatch(self, x, y, w=<NUM_LIT>, h=<NUM_LIT>, roundness=<NUM_LIT:0>):

_ctx.fill(self)<EOL>_ctx.rect(x, y, w, h, roundness)<EOL>