Show
Ignore:
Timestamp:
09/18/07 10:59:03 (16 months ago)
Author:
fdb
Message:

- Put direct objects on the canvas, not bound methods
- Add "ClippingPath?" object -- object contains BezierPath? and other grobs.
- Text now converts to unicode text.
- bezierpath.copy voor drawpath
- try/catch rond draw: "error while drawing"
- outputmode
- fixed the blacks
- inheritFromContext uses kwargs to know what to ignore
- keyword args for all states
- updated examples and play scripts

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • nodebox/trunk/src/DrawingPrimitives.py

    r89 r147  
     1import os 
     2from random import choice, shuffle 
    13from AppKit import * 
    24from Foundation import * 
    3 from random import choice, shuffle 
    4 import os 
    55 
    66__all__ = [ 
     
    1313        "NORMAL","FORTYFIVE", 
    1414        "NUMBER", "TEXT", "BOOLEAN","BUTTON", 
    15         "Point", "Grob", "BezierPath", "PathElement", "Rect", "Oval", "Color", "Transform", "Image", "Text", 
     15        "Point", "Grob", "BezierPath", "PathElement", "ClippingPath", "Rect", "Oval", "Color", "Transform", "Image", "Text", 
    1616        "Variable", "Canvas", "Context", 
    1717        "grid", "random","choice", "files","autotext", 
     
    4848BOOLEAN = 3 
    4949BUTTON = 4 
     50 
     51_STATE_NAMES = { 
     52    '_outputmode':    'outputmode', 
     53    '_colorrange':    'colorrange', 
     54    '_fillcolor':     'fill', 
     55    '_strokecolor':   'stroke', 
     56    '_strokewidth':   'strokewidth', 
     57    '_transform':     'transform', 
     58    '_transformmode': 'transformmode', 
     59    '_fontname':      'font', 
     60    '_fontsize':      'fontsize', 
     61    '_align':         'align', 
     62    '_lineheight':    'lineheight', 
     63} 
    5064 
    5165def _save(): 
     
    89103        """Appends the grob to the canvas. 
    90104           This will result in a draw later on, when the scene graph is rendered.""" 
    91         self._ctx._canvas.append( (self._draw) ) 
    92  
    93 class BezierPath(Grob): 
     105        self._ctx._canvas.append( self ) 
     106         
     107    def copy(self): 
     108        """Returns a deep copy of this grob.""" 
     109        raise NotImplementedError, "Copy is not implemented on this Grob class." 
     110         
     111    def inheritFromContext(self, ignore=()): 
     112        attrs_to_copy = list(self.__class__.stateAttributes) 
     113        [attrs_to_copy.remove(k) for k, v in _STATE_NAMES.items() if v in ignore] 
     114        _copy_attrs(self._ctx, self, attrs_to_copy) 
     115         
     116    def checkKwargs(self, kwargs): 
     117        remaining = [arg for arg in kwargs.keys() if arg not in self.kwargs] 
     118        if remaining: 
     119            raise NodeBoxError, "Unknown argument(s) '%s'" % ", ".join(remaining) 
     120    checkKwargs = classmethod(checkKwargs) 
     121 
     122class TransformMixin(object): 
     123 
     124    """Mixin class for transformation support. 
     125    Adds the _transform and _transformmode attributes to the class.""" 
     126     
     127    def __init__(self): 
     128        self._reset() 
     129         
     130    def _reset(self): 
     131        self._transform = Transform() 
     132        self._transformmode = CENTER 
     133         
     134    def transform(self, mode): 
     135        self._transformmode = mode 
     136         
     137    def translate(self, x, y): 
     138        self._transform.translate(x, y) 
     139         
     140    def transform(self, mode=None): 
     141        if mode is not None: 
     142            self._transformmode = mode 
     143        return self._transformmode 
     144 
     145    def reset(self): 
     146        self._transform = Transform() 
     147 
     148    def rotate(self, degrees=0, radians=0): 
     149        self._transform.rotate(-degrees,-radians) 
     150 
     151    def translate(self, x=0, y=0): 
     152        self._transform.translate(x,y) 
     153 
     154    def scale(self, x=1, y=None): 
     155        self._transform.scale(x,y) 
     156 
     157    def skew(self, x=0, y=0): 
     158        self._transform.skew(x,y) 
     159         
     160class ColorMixin(object): 
     161     
     162    """Mixin class for color support. 
     163    Adds the _fillcolor, _strokecolor and _strokewidth attributes to the class.""" 
     164 
     165    def __init__(self, **kwargs): 
     166        try: 
     167            self._fillcolor = Color(self._ctx, kwargs['fill']) 
     168        except KeyError: 
     169            self._fillcolor = Color(self._ctx) 
     170        try: 
     171            self._strokecolor = Color(self._ctx, kwargs['stroke']) 
     172        except KeyError: 
     173            self._strokecolor = None 
     174        self._strokewidth = kwargs.get('strokewidth', 1.0) 
     175 
     176    def nofill(self): 
     177        self._fillcolor = None 
     178 
     179    def fill(self, *args): 
     180        if len(args) > 0: 
     181            self._fillcolor = Color(self._ctx, *args) 
     182        return self._fillcolor 
     183 
     184    def nostroke(self): 
     185        self._strokecolor = None 
     186 
     187    def stroke(self, *args): 
     188        if len(args) > 0: 
     189            self._strokecolor = Color(self._ctx, *args) 
     190        return self._strokecolor 
     191 
     192    def strokewidth(self, width=None): 
     193        if width is not None: 
     194            self._strokewidth = width 
     195        return self._strokewidth 
     196 
     197class BezierPath(Grob, TransformMixin, ColorMixin): 
    94198    """A BezierPath provides a wrapper around NSBezierPath.""" 
    95  
    96     def __init__(self, ctx, path=None): 
    97         Grob.__init__(self, ctx) 
     199     
     200    stateAttributes = ('_fillcolor', '_strokecolor', '_strokewidth', '_transform', '_transformmode') 
     201    kwargs = ('fill', 'stroke', 'strokewidth') 
     202 
     203    def __init__(self, ctx, path=None, **kwargs): 
     204        super(BezierPath, self).__init__(ctx) 
     205        TransformMixin.__init__(self) 
     206        ColorMixin.__init__(self, **kwargs) 
     207        self._segment_cache = None 
    98208        if path is None: 
    99209            self.path = NSBezierPath.bezierPath() 
     
    101211            self.path = NSBezierPath.bezierPath() 
    102212            self.extend(path) 
     213        elif isinstance(path, BezierPath): 
     214            self.path = path.path.copy() 
     215            _copy_attrs(path, self, self.stateAttributes) 
     216        elif isinstance(path, NSBezierPath): 
     217            self.path = path 
    103218        else: 
    104             self.path = path 
    105         self._transform = Transform(self._ctx) 
    106         self.transformmode = CENTER 
    107         self.fillcolor = Color(self._ctx) 
    108         self.strokecolor = None 
    109         self.strokewidth = 1.0 
    110         self._segment_cache = None 
    111  
    112     def inheritFromContext(self): 
    113         self.fillcolor = self._ctx._fillcolor 
    114         self.strokecolor = self._ctx._strokecolor 
    115         self.strokewidth = self._ctx._strokewidth 
    116         self._transform = self._ctx._transform.copy() 
    117         self.transformmode = self._ctx._transformmode 
    118  
    119     def addclip(self): 
    120         self.inheritFromContext() 
    121         self._ctx._canvas.append(self._addclip) 
    122     addClip = addclip 
    123  
    124     def _addclip(self): 
    125         p = self.transform.transformBezierPath(self) 
    126         p.path.addClip() 
    127  
    128     def setclip(self): 
    129         self.inheritFromContext() 
    130         self._ctx._canvas.append(self._setclip) 
    131     setClip = setclip 
    132  
    133     def _setclip(self): 
    134         # XXX: setClip here has the effect of setting the clip independent of the view, 
    135         # meaning that we can draw over the bounds of the view, which is not good. 
    136         # 
    137         # setclip should restore the original graphicscontext (and save it back immediately 
    138         # so the stack is left intact) and add (not set) the clip there. 
    139         # Also, we need a place for endclip to store its code, since it can not 
    140         # be part of the current path. 
    141         p = self.transform.transformBezierPath(self) 
    142         _restore() 
    143         _save() 
    144         p.path.addClip() 
     219            raise NodeBoxError, "Don't know what to do with %s." % path 
     220 
     221    def copy(self): 
     222        return self.__class__(self._ctx, self) 
    145223 
    146224    ### Path methods ### 
     
    176254    def contains(self, x, y): 
    177255        return self.path.containsPoint_((x,y)) 
     256         
     257    ### Basic shapes ### 
     258     
     259    def rect(self, x, y, width, height): 
     260        self._segment_cache = None 
     261        self.path.appendBezierPathWithRect_( ((x, y), (width, height)) ) 
     262         
     263    def oval(self, x, y, width, height): 
     264        self._segment_cache = None 
     265        self.path.appendBezierPathWithOvalInRect_( ((x, y), (width, height)) ) 
     266         
     267    def line(self, x1, y1, x2, y2): 
     268        self._segment_cache = None 
     269        self.path.moveToPoint_( (x1, y1) ) 
     270        self.path.lineToPoint_( (x2, y2) ) 
    178271 
    179272    ### List methods ### 
     
    216309        trans = self._transform.copy() 
    217310 
    218         if (self.transformmode == CENTER): 
     311        if (self._transformmode == CENTER): 
    219312            (x, y), (w, h) = self.bounds 
    220313            deltax = x+w/2 
    221314            deltay = y+h/2 
    222             t = Transform(self._ctx) 
     315            t = Transform() 
    223316            t.translate(-deltax,-deltay) 
    224317            trans.prepend(t) 
    225             t = Transform(self._ctx) 
     318            t = Transform() 
    226319            t.translate(deltax,deltay) 
    227320            trans.append(t) 
     
    234327        _save() 
    235328        self.transform.concat() 
    236         if (self.fillcolor): 
    237             self.fillcolor.set() 
     329        if (self._fillcolor): 
     330            self._fillcolor.set() 
    238331            self.path.fill() 
    239         if (self.strokecolor): 
    240             self.strokecolor.set() 
    241             self.path.setLineWidth_(self.strokewidth) 
     332        if (self._strokecolor): 
     333            self._strokecolor.set() 
     334            self.path.setLineWidth_(self._strokewidth) 
    242335            self.path.stroke() 
    243336        _restore() 
     
    286379 
    287380class PathElement(object): 
     381 
    288382    def __init__(self, cmd=None, pts=None): 
    289383        self.cmd = cmd 
     
    312406            self.ctrl1 = Point() 
    313407            self.ctrl2 = Point() 
    314         #else: 
    315         #    raise NodeBoxError, "PathElement: unknown command %s" % cmd 
    316408 
    317409    def __repr__(self): 
     
    335427        return not self.__eq__(other) 
    336428 
     429class ClippingPath(Grob): 
     430 
     431    def __init__(self, ctx, path): 
     432        self._ctx = ctx 
     433        self.path = path 
     434        self._grobs = [] 
     435         
     436    def append(self, grob): 
     437        self._grobs.append(grob) 
     438         
     439    def _draw(self): 
     440        _save() 
     441        cp = self.path.transform.transformBezierPath(self.path) 
     442        cp.path.addClip() 
     443        for grob in self._grobs: 
     444            grob._draw() 
     445        _restore() 
     446 
    337447class Rect(BezierPath): 
    338     def __init__(self, ctx, x, y, width, height): 
     448 
     449    def __init__(self, ctx, x, y, width, height, **kwargs): 
    339450        r = (x,y), (width,height) 
    340         BezierPath.__init__(self, ctx, NSBezierPath.bezierPathWithRect_(r)) 
     451        super(Rect, self).__init__(ctx, NSBezierPath.bezierPathWithRect_(r), **kwargs) 
     452 
     453    def copy(self): 
     454        raise NotImplementedError, "Please don't use Rect anymore" 
    341455 
    342456class Oval(BezierPath): 
    343     def __init__(self, ctx, x, y, width, height): 
     457 
     458    def __init__(self, ctx, x, y, width, height, **kwargs): 
    344459        r = (x,y), (width,height) 
    345         BezierPath.__init__(self, ctx, NSBezierPath.bezierPathWithOvalInRect_(r)) 
     460        super(Oval, self).__init__(ctx, NSBezierPath.bezierPathWithOvalInRect_(r), **kwargs) 
     461 
     462    def copy(self): 
     463        raise NotImplementedError, "Please don't use Oval anymore" 
    346464 
    347465class Color(object): 
     
    352470 
    353471        # Decompose the arguments into tuples.  
    354         # This is done in a loop, because giving a fill with a tuple 
    355         # wraps the tuple in a tuple. 
    356         while(params == 1 and isinstance(args[0], tuple)): 
     472        if params == 1 and isinstance(args[0], tuple): 
    357473            args = args[0] 
    358474            params = len(args) 
     
    365481            args = self._normalizeList(args) 
    366482            g, = args 
    367             clr = NSColor.colorWithDeviceCyan_magenta_yellow_black_alpha_(0, 0, 0, 1.0-g, 1) 
     483            clr = NSColor.colorWithDeviceWhite_alpha_(g, 1) 
    368484        elif params == 2: # Gray and alpha 
    369485            args = self._normalizeList(args) 
    370486            g, a = args 
    371             clr = NSColor.colorWithDeviceCyan_magenta_yellow_black_alpha_(0, 0, 0, 1.0-g, a) 
     487            clr = NSColor.colorWithDeviceWhite_alpha_(g, a) 
    372488        elif params == 3 and self._ctx._colormode == RGB: # RGB, no alpha 
    373489            args = self._normalizeList(args) 
    374490            r,g,b = args 
    375             clr = NSColor.colorWithCalibratedRed_green_blue_alpha_(r, g, b, 1) 
     491            clr = NSColor.colorWithDeviceRed_green_blue_alpha_(r, g, b, 1) 
    376492        elif params == 3 and self._ctx._colormode == HSB: # HSB, no alpha 
    377493            args = self._normalizeList(args) 
    378494            h, s, b = args 
    379             clr = NSColor.colorWithCalibratedHue_saturation_brightness_alpha_(h, s, b, 1) 
     495            clr = NSColor.colorWithDeviceHue_saturation_brightness_alpha_(h, s, b, 1) 
    380496        elif params == 4 and self._ctx._colormode == RGB: # RGB and alpha 
    381497            args = self._normalizeList(args) 
    382498            r,g,b, a = args 
    383             clr = NSColor.colorWithCalibratedRed_green_blue_alpha_(r, g, b, a) 
     499            clr = NSColor.colorWithDeviceRed_green_blue_alpha_(r, g, b, a) 
    384500        elif params == 4 and self._ctx._colormode == HSB: # HSB and alpha 
    385501            args = self._normalizeList(args) 
    386502            h, s, b, a = args 
    387             clr = NSColor.colorWithCalibratedHue_saturation_brightness_alpha_(h, s, b, a) 
     503            clr = NSColor.colorWithDeviceHue_saturation_brightness_alpha_(h, s, b, a) 
    388504        elif params == 4 and self._ctx._colormode == CMYK: # CMYK, no alpha 
    389505            args = self._normalizeList(args) 
     
    395511            clr = NSColor.colorWithDeviceCyan_magenta_yellow_black_alpha_(c, m, y, k, a) 
    396512        else: 
    397             clr = NSColor.colorWithDeviceCyan_magenta_yellow_black_alpha_(0, 0, 0, 1, 1) 
     513            clr = NSColor.colorWithDeviceWhite_alpha_(0, 1) 
    398514 
    399515        self._cmyk = clr.colorUsingColorSpaceName_(NSDeviceCMYKColorSpace) 
    400         self._rgb = clr.colorUsingColorSpaceName_(NSCalibratedRGBColorSpace) 
     516        self._rgb = clr.colorUsingColorSpaceName_(NSDeviceRGBColorSpace) 
    401517 
    402518    def __repr__(self): 
     
    405521 
    406522    def set(self): 
    407         self._cmyk.set() 
     523        if self._ctx._outputmode == RGB: 
     524            self._rgb.set() 
     525        else: 
     526            self._cmyk.set() 
    408527 
    409528    def copy(self): 
    410         return self.__class__(color=self._rgb.copy()) 
     529        new = self.__class__(self._ctx) 
     530        new._rgb = self._rgb.copy() 
     531        new._updateCmyk() 
     532        return new 
    411533 
    412534    def _updateCmyk(self): 
     
    414536 
    415537    def _updateRgb(self): 
    416         self._rgb = self._cmyk.colorUsingColorSpaceName_(NSCalibratedRGBColorSpace) 
     538        self._rgb = self._cmyk.colorUsingColorSpaceName_(NSDeviceRGBColorSpace) 
    417539 
    418540    def _get_hue(self): 
     
    421543        val = self._normalize(val) 
    422544        h, s, b, a = self._rgb.getHue_saturation_brightness_alpha_() 
    423         self._rgb = NSColor.colorWithCalibratedHue_saturation_brightness_alpha_(val, s, b, a) 
     545        self._rgb = NSColor.colorWithDeviceHue_saturation_brightness_alpha_(val, s, b, a) 
    424546        self._updateCmyk() 
    425547    h = hue = property(_get_hue, _set_hue, doc="the hue of the color") 
     
    430552        val = self._normalize(val) 
    431553        h, s, b, a = self._rgb.getHue_saturation_brightness_alpha_() 
    432         self._rgb = NSColor.colorWithCalibratedHue_saturation_brightness_alpha_(h, val, b, a) 
     554        self._rgb = NSColor.colorWithDeviceHue_saturation_brightness_alpha_(h, val, b, a) 
    433555        self._updateCmyk() 
    434556    s = saturation = property(_get_saturation, _set_saturation, doc="the saturation of the color") 
     
    439561        val = self._normalize(val) 
    440562        h, s, b, a = self._rgb.getHue_saturation_brightness_alpha_() 
    441         self._rgb = NSColor.colorWithCalibratedHue_saturation_brightness_alpha_(h, s, val, a) 
     563        self._rgb = NSColor.colorWithDeviceHue_saturation_brightness_alpha_(h, s, val, a) 
    442564        self._updateCmyk() 
    443565    v = brightness = property(_get_brightness, _set_brightness, doc="the brightness of the color") 
     
    448570        val = self._normalize(val) 
    449571        h, s, b, a = values 
    450         self._rgb = NSColor.colorWithCalibratedHue_saturation_brightness_alpha_(h, s, b, a) 
     572        self._rgb = NSColor.colorWithDeviceHue_saturation_brightness_alpha_(h, s, b, a) 
    451573        self._updateCmyk() 
    452574    hsba = property(_get_hsba, _set_hsba, doc="the hue, saturation, brightness and alpha of the color") 
     
    457579        val = self._normalize(val) 
    458580        r, g, b, a = self._rgb.getRed_green_blue_alpha_() 
    459         self._rgb = NSColor.colorWithCalibratedRed_green_blue_alpha_(val, g, b, a) 
     581        self._rgb = NSColor.colorWithDeviceRed_green_blue_alpha_(val, g, b, a) 
    460582        self._updateCmyk() 
    461583    r = red = property(_get_red, _set_red, doc="the red component of the color") 
     
    466588        val = self._normalize(val) 
    467589        r, g, b, a = self._rgb.getRed_green_blue_alpha_() 
    468         self._rgb = NSColor.colorWithCalibratedRed_green_blue_alpha_(r, val, b, a) 
     590        self._rgb = NSColor.colorWithDeviceRed_green_blue_alpha_(r, val, b, a) 
    469591        self._updateCmyk() 
    470592    g = green = property(_get_green, _set_green, doc="the green component of the color") 
     
    475597        val = self._normalize(val) 
    476598        r, g, b, a = self._rgb.getRed_green_blue_alpha_() 
    477         self._rgb = NSColor.colorWithCalibratedRed_green_blue_alpha_(r, g, val, a) 
     599        self._rgb = NSColor.colorWithDeviceRed_green_blue_alpha_(r, g, val, a) 
    478600        self._updateCmyk() 
    479601    b = blue = property(_get_blue, _set_blue, doc="the blue component of the color") 
     
    484606        val = self._normalize(val) 
    485607        r, g, b, a = self._rgb.getRed_green_blue_alpha_() 
    486         self._rgb = NSColor.colorWithCalibratedRed_green_blue_alpha_(r, g, b, val) 
     608        self._rgb = NSColor.colorWithDeviceRed_green_blue_alpha_(r, g, b, val) 
    487609        self._updateCmyk() 
    488610    a = alpha = property(_get_alpha, _set_alpha, doc="the alpha component of the color") 
     
    493615        val = self._normalizeList(val) 
    494616        r, g, b, a = val 
    495         self._rgb = NSColor.colorWithCalibratedRed_green_blue_alpha_(r, g, b, a) 
     617        self._rgb = NSColor.colorWithDeviceRed_green_blue_alpha_(r, g, b, a) 
    496618        self._updateCmyk() 
    497619    rgba = property(_get_rgba, _set_rgba, doc="the red, green, blue and alpha values of the color") 
     
    556678color = Color 
    557679 
    558 def Gray(ctx, g, alpha=1): 
    559     return Color(ctx, g, g, g, alpha) 
    560  
    561680class Transform(object): 
    562     def __init__(self, ctx, transform=None): 
    563         self._ctx = ctx 
     681    def __init__(self, transform=None): 
    564682        if transform is None: 
    565683            transform = NSAffineTransform.transform() 
     
    577695 
    578696    def copy(self): 
    579         return self.__class__(self._ctx, self.transform.copy()) 
     697        return self.__class__(self.transform.copy()) 
    580698 
    581699    def __repr__(self): 
     
    611729        x = math.pi * x / 180 
    612730        y = math.pi * y / 180 
    613         t = Transform(self._ctx) 
     731        t = Transform() 
    614732        t.matrix = 1, math.tan(y), -math.tan(x), 1, 0, 0 
    615733        self.prepend(t) 
     
    633751    def transformBezierPath(self, path): 
    634752        if isinstance(path, BezierPath): 
     753            ctx = path._ctx 
    635754            path = path.path 
     755        elif isinstance(path, NSBezierPath): 
     756            ctx = None 
     757        else: 
     758            raise NodeBoxError, "Can only transform BezierPaths" 
    636759        path = self.transform.transformBezierPath_(path) 
    637         return BezierPath(self._ctx, path) 
    638  
    639 class Image(Grob): 
     760        return BezierPath(ctx, path) 
     761 
     762class Image(Grob, TransformMixin): 
     763 
     764    stateAttributes = ('_transform', '_transformmode') 
     765    kwargs = () 
     766 
    640767    def __init__(self, ctx, path=None, x=0, y=0, width=None, height=None, alpha=1.0, image=None, data=None): 
    641768        """ 
     
    652779         - data: a stream of bytes of image data. 
    653780        """ 
    654         Grob.__init__(self, ctx) 
     781        super(Image, self).__init__(ctx) 
     782        TransformMixin.__init__(self) 
    655783        if data is not None: 
    656784            d = NSData.dataWithBytes_length_(data, len(data)) 
     
    684812        self.width = width 
    685813        self.height = height 
    686         self.transform = Transform(self._ctx) 
    687814        self.alpha = alpha 
    688815        self.debugImage = False 
    689816 
     817    def copy(self): 
     818        new = self.__class__(self._ctx) 
     819        _copy_attrs(self, new, ('image', 'x', 'y', 'width', 'height', '_transform', '_transformmode', 'alpha', 'debugImage')) 
     820        return new 
     821 
    690822    def getSize(self): 
    691823        return self.image.size() 
    692824 
    693825    size = property(getSize) 
    694  
    695     def inheritFromContext(self): 
    696         self.transform = self._ctx._transform.copy() 
    697         self.transformmode = self._ctx._transformmode 
    698826 
    699827    def _draw(self): 
     
    714842 
    715843            # Center-mode transforms: translate to image center 
    716             if self.transformmode == CENTER: 
     844            if self._transformmode == CENTER: 
    717845                # This is the hardest case: center-mode transformations with given width or height. 
    718846                # Order is very important in this code. 
     
    720848                # Set the position first, before any of the scaling or transformations are done. 
    721849                # Context transformations might change the translation, and we don't want that. 
    722                 t = Transform(self._ctx) 
     850                t = Transform() 
    723851                t.translate(self.x, self.y) 
    724852                t.concat() 
     
    732860                dX = srcW / 2 
    733861                dY = srcH / 2 
    734                 t = Transform(self._ctx) 
     862                t = Transform() 
    735863                t.translate(dX, dY) 
    736864                t.concat() 
    737865 
    738866                # Do current transformation. 
    739                 self.transform.concat() 
     867                self._transform.concat() 
    740868 
    741869                # Move back to the previous position. 
    742                 t = Transform(self._ctx) 
     870                t = Transform() 
    743871                t.translate(-dX, -dY) 
    744872                t.concat() 
    745873 
    746874                # Finally, scale the image according to the factors. 
    747                 t = Transform(self._ctx) 
     875                t = Transform() 
    748876                t.scale(factor) 
    749877                t.concat() 
    750878            else: 
    751879                # Do current transformation 
    752                 self.transform.concat() 
     880                self._transform.concat() 
    753881                # Scale according to width or height factor 
    754                 t = Transform(self._ctx) 
     882                t = Transform() 
    755883                t.translate(self.x, self.y) # Here we add the positioning of the image. 
    756884                t.scale(factor) 
     
    769897            x,y = self.x, self.y 
    770898            # Center-mode transforms: translate to image center 
    771             if self.transformmode == CENTER: 
     899            if self._transformmode == CENTER: 
    772900                deltaX = srcW / 2 
    773901                deltaY = srcH / 2 
    774                 t = Transform(self._ctx) 
     902                t = Transform() 
    775903                t.translate(x+deltaX, y+deltaY) 
    776904                t.concat() 
     
    778906                y = -deltaY 
    779907            # Do current transformation 
    780             self.transform.concat() 
     908            self._transform.concat() 
    781909            # A debugImage draws a black rectangle instead of an image. 
    782910            if self.debugImage: 
     
    791919                # is better: always use zero coordinates for drawAtPoint and use a transform to set the 
    792920                # final position. 
    793                 t = Transform(self._ctx) 
     921                t = Transform() 
    794