#
#   Python GUI - Drawing - Macintosh
#

from Carbon.Qd import \
    NewRgn, RectRgn, SectRgn, GetPort, SetPort, SetOrigin, GetClip, SetClip, \
    RGBForeColor, RGBBackColor, GetForeColor, GetBackColor, \
    GetPenState, SetPenState, GetPen, PenSize, MoveTo, LineTo, \
    TextFont, TextSize, TextFace, DrawText, OpenPoly, ClosePoly, OffsetPoly, \
    FrameRect, PaintRect, FrameOval, PaintOval, FrameArc, PaintArc, FramePoly, PaintPoly
from GCanvases import Canvas as GCanvas

class Canvas(GCanvas):

    _coords = GCanvas._int_coords

    def __init__(self, mac_initial_clip_rgn):
        self._mac_initial_clip_rgn = mac_initial_clip_rgn
        self._pensize = 1
        GCanvas.__init__(self)
    
    def get_forecolor(self):
        return Color._with_rgb(GetForeColor())
    
    def set_forecolor(self, c):
        RGBForeColor(c._rgb)
    
    def get_backcolor(self):
        return Color._with_rgb(GetBackColor())
    
    def set_backcolor(self, c):
        RGBBackColor(c._rgb)
    
    def get_pensize(self):
        return self._pensize
    
    def set_pensize(self, d):
        self._pensize = d
        PenSize(d, d)
    
    def get_font(self):
        return Font._from_mac_port()
    
    def set_font(self, f):
        f._mac_set_font()
    
    def initclip(self):
        SetClip(self._mac_initial_clip_rgn)
    
    def rectclip(self, r):
        cur_clip = NewRgn()
        GetClip(cur_clip)
        new_clip = NewRgn()
        RectRgn(new_clip, r)
        SectRgn(cur_clip, new_clip, new_clip)
        SetClip(new_clip)
    
    def gsave(self):
        port = GetPort()
        clip_rgn = NewRgn()
        GetClip(clip_rgn)
        self._gstack.append((
            self._current_point,
            self._pensize,
            GetForeColor(), 
            GetBackColor(),
            GetPenState(),
            port.GetPortTextFont(), 
            port.GetPortTextSize(), 
            port.GetPortTextFace(),
            clip_rgn))
    
    def grestore(self):
        (self._current_point,
            self._pensize,
            forecolor, 
            backcolor,
            penstate,
            textfont, 
            textsize, 
            textface,
            clip_rgn) = self._gstack.pop()
        RGBForeColor(forecolor)
        RGBBackColor(backcolor)
        SetPenState(penstate)
        TextFont(textfont)
        TextSize(textsize)
        TextFace(textface)
        SetClip(clip_rgn)
    
    def stroke(self):
        d = -int(self._pensize / 2)
        for subpath in self._path:
            poly = _mac_poly(subpath)
            OffsetPoly(poly, d, d)
            FramePoly(poly)
    
    def fill(self):
        for subpath in self._path:
            poly = _mac_poly(subpath)
            PaintPoly(poly)
    
    def show_text(self, text):
        MoveTo(*self._current_point)
        DrawText(text, 0, len(text))
        self._current_point = GetPen()
    
    def frame_rect(self, r):
        FrameRect(_mac_rect(r))
    
    def fill_rect(self, r):
        PaintRect(_mac_rect(r))
    
    def frame_oval(self, r):
        FrameOval(_mac_rect(r))
    
    def fill_oval(self, r):
        PaintOval(_mac_rect(r))
    
    def frame_arc(self, r, a1, a2):
        start, arc = _mac_angles(a1, a2)
        FrameArc(_mac_rect(r), start, arc)
    
    def fill_arc(self, r, a1, a2):
        start, arc = _mac_angles(a1, a2)
        PaintArc(_mac_rect(r), start, arc)
    
    def fill_poly(self, points):
        _coords = self._coords
        def poly_coords():
            for p in points:
                yield _coords(p)
        PaintPoly(_mac_poly(poly_coords()))


def _mac_rect((l, t, r, b)):
    return int(round(l)), int(round(t)), int(round(r)), int(round(b))

def _mac_angles(a1, a2):
    start = int(round(a1))
    end = int(round(a2 - a1))
    return 90 + start, end - start

def _mac_poly(points):
    poly = OpenPoly()
    piter = iter(points)
    x, y = piter.next()
    MoveTo(x, y)
    for x, y in piter:
        LineTo(x, y)
    ClosePoly()
    return poly
