Changeset 484

Show
Ignore:
Timestamp:
09/04/08 15:29:15 (4 months ago)
Author:
stefan
Message:

initial changes

Location:
nodebox/branches/try-qt-painter/nodebox
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • nodebox/branches/try-qt-painter/nodebox/graphics/qt.py

    </
    r286 r484  
    33from random import choice, shuffle 
    44 
    5 from PyQt4.QtGui import QPainterPath, QColor, QTransform, QBrush, QPen, QImage, QPrinter, QPainter, QFontMetrics, QFont 
     5from PyQt4.QtGui import QPainterPath, QColor, QTransform, QBrush, QPen, QImage, QPrinter, QPainter, QFontMetrics, QFontMetricsF, QFont, QTextLayout, QTextOption 
    66from PyQt4.QtCore import Qt, QSize, QPointF, QRectF 
    77from PyQt4.QtSvg import QSvgGenerator 
     
    3636CORNER = "corner" 
    3737 
    38 MOVETO = 0 
    39 LINETO = 1 
    40 CURVETO = 2 
    41 CLOSE = 3 
     38MOVETO = QPainterPath.MoveToElement 
     39LINETO = QPainterPath.LineToElement 
     40CURVETO = QPainterPath.CurveToElement 
     41CLOSE = "close" 
    4242 
    4343LEFT = 0 
     
    212212        ColorMixin.__init__(self, **kwargs) 
    213213        self._segment_cache = None 
     214        self._qpath_segment_cache = None 
    214215        if path is None: 
    215216            self._qpath = QPainterPath() 
     
    237238    def moveto(self, x, y): 
    238239        self._segment_cache = None 
     240        self._qpath_segment_cache = None 
    239241        self._qpath.moveTo(x, y) 
    240242 
    241243    def lineto(self, x, y): 
    242244        self._segment_cache = None 
     245        self._qpath_segment_cache = None 
    243246        self._qpath.lineTo(x, y) 
    244247 
    245248    def curveto(self, x1, y1, x2, y2, x3, y3): 
    246249        self._segment_cache = None 
     250        self._qpath_segment_cache = None 
    247251        self._qpath.cubicTo(x1, y1, x2, y2, x3, y3) 
    248252 
    249253    def closepath(self): 
    250254        self._segment_cache = None 
     255        self._qpath_segment_cache = None 
    251256        self._qpath.closeSubpath() # XXX: Is this correct? 
    252257 
     
    272277    def rect(self, x, y, width, height): 
    273278        self._segment_cache = None 
     279        self._qpath_segment_cache = None 
    274280        self._qpath.addRect(x, y, width, height) 
    275281         
    276282    def oval(self, x, y, width, height): 
    277283        self._segment_cache = None 
     284        self._qpath_segment_cache = None 
    278285        self._qpath.addEllipse(x, y, width, height) 
    279286         
    280287    def line(self, x1, y1, x2, y2): 
    281288        self._segment_cache = None 
     289        self._qpath_segment_cache = None 
    282290        self._qpath.moveTo(x1, y1) 
    283291        self._qpath.lineTo(x2, y2) 
     
    286294 
    287295    def __getitem__(self, index): 
    288         el = self._qpath.elementAt(index) 
    289         return PathElement(el) 
     296        if self._qpath_segment_cache == None: 
     297            self._set_qpath_segment_cache() 
     298        cmd, el = self._qpath_segment_cache[index] 
     299        return PathElement(cmd, el) 
    290300 
    291301    def __iter__(self): 
     
    294304 
    295305    def __len__(self): 
    296         return self._qpath.elementCount() 
     306        if self._qpath_segment_cache == None: 
     307            self._set_qpath_segment_cache() 
     308        return len(self._qpath_segment_cache) 
     309 
     310    def _set_qpath_segment_cache(self): 
     311        self._qpath_segment_cache = [] 
     312        length = self._qpath.elementCount() 
     313        temp = [] 
     314        for i in range(length): 
     315            el = self._qpath.elementAt(i) 
     316            if el.type in [LINETO, MOVETO, CURVETO, CLOSE]: 
     317                temp.append(i) 
     318        for i in temp: 
     319            el = self._qpath.elementAt(i) 
     320            if el.type in [LINETO, MOVETO, CLOSE]: 
     321                self._qpath_segment_cache.append((el.type, ((el.x, el.y),))) 
     322            elif el.type == CURVETO: 
     323                ctrl1 = self._qpath.elementAt(i+1) 
     324                ctrl2 = self._qpath.elementAt(i+2) 
     325                self._qpath_segment_cache.append((el.type, ((el.x, el.y), (ctrl1.x, ctrl1.y), (ctrl2.x, ctrl2.y)))) 
    297326 
    298327    def extend(self, pathElements): 
    299328        self._segment_cache = None 
     329        self._qpath_segment_cache = None 
    300330        for el in pathElements: 
    301331            if isinstance(el, (list, tuple)): 
     
    313343    def append(self, el): 
    314344        self._segment_cache = None 
     345        self._qpath_segment_cache = None 
    315346        if el.cmd == MOVETO: 
    316347            self.moveto(el.x, el.y) 
     
    355386        painter.restore() 
    356387         
     388    def fit(self, x=None, y=None, width=None, height=None, stretch=False): 
     389 
     390        """Fits this path to the specified bounds. 
     391     
     392        All parameters are optional; if no parameters are specified, nothing will happen. 
     393        Specifying a parameter will constrain its value: 
     394     
     395        - x: The path will be positioned at the specified x value 
     396        - y: The path will be positioned at the specified y value 
     397        - width: The path will be of the specified width 
     398        - height: The path will be of the specified height 
     399        - stretch: If both width and height are defined, either stretch the path or 
     400                keep the aspect ratio. 
     401        """ 
     402 
     403        (px, py), (pw, ph) = self.bounds 
     404        t = Transform() 
     405        if x is not None and y is None: 
     406            t.translate(x, py) 
     407        elif x is None and y is not None: 
     408            t.translate(px, y) 
     409        elif x is not None and y is not None: 
     410            t.translate(x, y) 
     411        else: 
     412            t.translate(px, py) 
     413        if width is not None and height is None: 
     414            t.scale(width / pw) 
     415        elif width is None and height is not None: 
     416            t.scale(height / ph) 
     417        elif width is not None and height is not None: 
     418            if stretch: 
     419                t.scale(width /pw, height / ph) 
     420            else: 
     421                t.scale(min(width /pw, height / ph)) 
     422        t.translate(-px, -py) 
     423        self._qpath = t.transformBezierPath(self)._qpath 
     424         
    357425    ### Mathematics ### 
    358426     
     
    394462    def addpoint(self, t): 
    395463        import bezier 
    396         self._nsBezierPath = bezier.insert_point(self, t)._nsBezierPath 
     464        self._qPath = bezier.insert_point(self, t)._qPath 
    397465        self._segment_cache = None 
     466        self._qpath_segment_cache = None 
     467 
     468    ### Clipping operations ### 
     469 
     470    def intersects(self, other): 
     471        return self._qpath.intersects(other._qpath) 
     472 
     473    def union(self, other, flatness=0.6): 
     474        return BezierPath(self._ctx, self._qpath.united(other._qpath)) 
     475 
     476    def intersect(self, other, flatness=0.6): 
     477        return BezierPath(self._ctx, self._qpath.intersected(other._qpath)) 
     478 
     479    def difference(self, other, flatness=0.6): 
     480        return BezierPath(self._ctx, self._qpath.subtracted(other._qpath)) 
     481 
     482    def xor(self, other, flatness=0.6): 
     483        union = self._qpath.united(other._qpath) 
     484        intersection = self._qpath.intersected(other._qpath) 
     485        return BezierPath(self._ctx, union.subtracted(intersection)) 
    398486 
    399487class PathElement(object): 
     
    456544        self._grobs.append(grob) 
    457545         
    458     def _draw(self): 
    459         _save() 
    460         cp = self.path.transform.transformBezierPath(self.path) 
    461         cp._nsBezierPath.addClip() 
     546    def _draw(self, painter): 
     547        painter.save() 
     548        transform = self.path.transform 
     549        cp = transform.transformBezierPath(self.path) 
     550        painter.setClipPath(cp._qpath) 
    462551        for grob in self._grobs: 
    463             grob._draw() 
    464         _restore() 
     552            grob._draw(painter) 
     553        painter.restore() 
    465554 
    466555class Rect(BezierPath): 
     
    468557    def __init__(self, ctx, x, y, width, height, **kwargs): 
    469558        warnings.warn("Rect is deprecated. Use BezierPath's rect method.", DeprecationWarning, stacklevel=2) 
    470         r = (x,y), (width,height) 
    471         super(Rect, self).__init__(ctx, NSBezierPath.bezierPathWithRect_(r), **kwargs) 
     559        p=QPainterPath() 
     560        p.addRect(x, y, width, height) 
     561        super(Rect, self).__init__(ctx, p, **kwargs) 
    472562 
    473563    def copy(self): 
     
    478568    def __init__(self, ctx, x, y, width, height, **kwargs): 
    479569        warnings.warn("Oval is deprecated. Use BezierPath's oval method.", DeprecationWarning, stacklevel=2) 
    480         r = (x,y), (width,height) 
    481         super(Oval, self).__init__(ctx, NSBezierPath.bezierPathWithOvalInRect_(r), **kwargs) 
     570        p=QPainterPath() 
     571        p.addEllipse(x, y, width, height) 
     572        super(Oval, self).__init__(ctx, p, **kwargs) 
    482573 
    483574    def copy(self): 
     
    519610            args = self._normalizeList(args) 
    520611            h, s, b = args 
     612            if h == 1.0: 
     613                h = .99998 
    521614            clr = QColor.fromHsvF(h, s, b, 1) 
    522615        elif params == 4 and self._ctx._colormode == RGB: # RGB and alpha 
     
    527620            args = self._normalizeList(args) 
    528621            h, s, b, a = args 
     622            if h == 1.0: 
     623                h = .99998 
    529624            clr = QColor.fromHsvF(h, s, b, a) 
    530625        elif params == 4 and self._ctx._colormode == CMYK: # CMYK, no alpha 
     
    557652    qColor = property(_get_qColor) 
    558653         
    559  
    560654    def copy(self): 
    561655        new = self.__class__(self._ctx) 
    562656        new._rgb = QColor(self._rgb) 
    563         new._updateCmyk() 
     657#        new._updateCmyk() 
    564658        return new 
    565659 
     
    573667 
    574668    def _get_hue(self): 
    575         return self._rgb.hueF() 
     669        hue = self._rgb.hueF() 
     670        if round(hue, 4) == 1.0: 
     671            return 1.0 
     672        if hue < 0.0: 
     673            return 0.0 
     674        return hue 
    576675    def _set_hue(self, val): 
    577676        val = self._normalize(val) 
    578         c = self._rgb 
    579         h, s, b, a = c.hueF(), c.saturationF(), c.valueF(), c.alpha() 
     677        if val == 1.0: 
     678           val = .99998 
     679        h, s, b, a = self.hsba 
    580680        self._rgb.setHsvF(val, s, b, a) 
    581681        self._updateCmyk() 
    582682    h = hue = property(_get_hue, _set_hue, doc="the hue of the color") 
     683 
     684    def _get_saturation(self): 
     685        return self._rgb.saturationF() 
     686    def _set_saturation(self, val): 
     687        val = self._normalize(val) 
     688        h, s, b, a = self.hsba 
     689        self._rgb.setHsvF(h, val, b, a) 
     690        self._updateCmyk() 
     691    s = saturation = property(_get_saturation, _set_saturation, doc="the saturation of the color") 
     692 
     693    def _get_brightness(self): 
     694        return self._rgb.valueF() 
     695    def _set_brightness(self, val): 
     696        val = self._normalize(val) 
     697        h, s, b, a = self.hsba 
     698        self._rgb.setHsvF(h, s, val, a) 
     699        self._updateCmyk() 
     700    v = brightness = property(_get_brightness, _set_brightness, doc="the saturation of the color") 
     701 
     702    def _get_hsba(self): 
     703        c = self._rgb 
     704        return c.hueF(), c.saturationF(), c.valueF(), c.alphaF() 
     705    def _set_hsba(self, values): 
     706        values = self._normalizeList(values) 
     707        h, s, b, a = values 
     708        self._rgb.setHsvF(h, s, b, a) 
     709    hsba = property(_get_hsba, _set_hsba, doc="the hue, saturation, brightness and alpha of the color") 
     710 
     711    def _get_red(self): 
     712        return self._rgb.redF() 
     713    def _set_red(self, val): 
     714        val = self._normalize(val) 
     715        r, g, b, a = self.rgba 
     716        self._rgb.setRgbF(val, g, b, a) 
     717        self._updateCmyk()         
     718    r = red = property(_get_red, _set_red, doc="the red component of the color") 
     719 
     720    def _get_green(self): 
     721        return self._rgb.greenF() 
     722    def _set_green(self, val): 
     723        val = self._normalize(val) 
     724        r, g, b, a = self.rgba 
     725        self._rgb.setRgbF(r, val, b, a) 
     726        self._updateCmyk()         
     727    g = green = property(_get_green, _set_green, doc="the green component of the color") 
     728 
     729    def _get_blue(self): 
     730        return self._rgb.blueF() 
     731    def _set_blue(self, val): 
     732        val = self._normalize(val) 
     733        r, g, b, a = self.rgba 
     734        self._rgb.setRgbF(r, g, val, a) 
     735        self._updateCmyk()         
     736    b = blue = property(_get_blue, _set_blue, doc="the blue component of the color") 
     737 
     738    def _get_alpha(self): 
     739        return self._rgb.alphaF() 
     740    def _set_alpha(self, val): 
     741        val = self._normalize(val) 
     742        r, g, b, a = self.rgba 
     743        self._rgb.setRgbF(r, g, b, val) 
     744        self._updateCmyk()         
     745    a = alpha = property(_get_alpha, _set_alpha, doc="the alpha component of the color") 
     746    
     747    def _get_rgba(self): 
     748        c = self._rgb 
     749        return c.redF(), c.greenF(), c.blueF(), c.alphaF() 
     750    def _set_rgba(self, values): 
     751        values = self._normalizeList(values) 
     752        r, g, b, a = values 
     753        self._rgb.setRgbF(r, g, b, a) 
     754    rgba = property(_get_rgba, _set_rgba, doc="the red, green, blue and alpha values of the color") 
     755 
     756    def _get_cyan(self): 
     757        return self._rgb.cyanF() 
     758    def _set_cyan(self, val): 
     759        val = self._normalize(val) 
     760        c, m, y, k, a = self.cmyka 
     761        self._rgb.setCmykF(val, m, y, k, a) 
     762        self._updateRgb()         
     763    c = cyan = property(_get_cyan, _set_cyan, doc="the cyan component of the color") 
     764 
     765    def _get_magenta(self): 
     766        return self._rgb.magentaF() 
     767    def _set_magenta(self, val): 
     768        val = self._normalize(val) 
     769        c, m, y, k, a = self.cmyka 
     770        self._rgb.setCmykF(c, val, y, k, a) 
     771        self._updateRgb()         
     772    m = magenta = property(_get_magenta, _set_magenta, doc="the magenta component of the color") 
     773 
     774    def _get_yellow(self): 
     775        return self._rgb.yellowF() 
     776    def _set_yellow(self, val): 
     777        val = self._normalize(val) 
     778        c, m, y, k, a = self.cmyka 
     779        self._rgb.setCmykF(c, m, val, k, a) 
     780        self._updateRgb()         
     781    y = yellow = property(_get_yellow, _set_yellow, doc="the yellow component of the color") 
     782 
     783    def _get_black(self): 
     784        return self._rgb.blackF() 
     785    def _set_black(self, val): 
     786        val = self._normalize(val) 
     787        c, m, y, k, a = self.cmyka 
     788        self._rgb.setCmykF(c, m, y, val, a) 
     789        self._updateRgb()         
     790    k = black = property(_get_black, _set_black, doc="the black component of the color") 
     791 
     792    def _get_cmyka(self): 
     793        c = self._rgb 
     794        return c.cyanF(), c.magentaF(), c.yellowF(), c.blackF(), c.alphaF() 
     795    cmyka = property(_get_cmyka, doc="a tuple containing the CMYKA values for this color") 
    583796 
    584797    def _normalize(self, v): 
     
    604817        elif isinstance(transform, (list, tuple)): 
    605818            matrix = tuple(transform) 
    606             transform = QTransform() 
    607             transform.setMatrix(*matrix) 
     819            transform = QTransform(*matrix) 
    608820        elif isinstance(transform, QTransform): 
    609821            pass 
     
    622834    def concat(self, painter): 
    623835        trans = painter.transform() 
    624         painter.setTransform(trans * self._qtransform) 
     836        painter.setTransform(self._qtransform * trans) 
    625837 
    626838    def copy(self): 
     
    637849    def _get_matrix(self): 
    638850        q = self._qtransform 
    639         return (q.m11(), q.m12(), q.m13(), q.m21(), q.m22(), q.m23(), q.m31(), q.m32(), q.m33()) 
     851        return (q.m11(), q.m12(), q.m21(), q.m22(), q.m31(), q.m32()) 
    640852    def _set_matrix(self, value): 
    641         self._qtransform.setMatrix(value) 
     853        self._qtransform = QTransform(*value) 
    642854    matrix = property(_get_matrix, _set_matrix) 
    643855 
     
    657869 
    658870    def skew(self, x=0, y=0): 
    659         self._qtransform.shear(x, y) 
     871        import math 
     872        x = math.pi * x / 180. 
     873        y = math.pi * y / 180. 
     874        t = Transform() 
     875        t.matrix = 1, math.tan(y), -math.tan(x), 1, 0, 0 
     876        self.prepend(t) 
    660877 
    661878    def invert(self): 
     
    711928        TransformMixin.__init__(self) 
    712929        if data is not None: 
    713             self._nsImage = QImage(data) 
     930            self._qimage = QImage(data) 
    714931            if self._qimage is None: 
    715932                raise NodeBoxError, "can't read image %r" % path 
     
    753970 
    754971    def getSize(self): 
    755         return self._nsImage.size() 
     972        return self._qimage.width(), self._qimage.height() 
    756973 
    757974    size = property(getSize) 
     
    760977        """Draw an image on the given coordinates.""" 
    761978 
    762         srcW, srcH = self._qimage.width(), self._qimage.height() 
     979        srcW, srcH = float(self._qimage.width()), float(self._qimage.height()) 
    763980        srcRect = ((0, 0), (srcW, srcH)) 
    764981 
     
    777994                # This is the hardest case: center-mode transformations with given width or height. 
    778995                # Order is very important in this code. 
    779  
    780996                # Set the position first, before any of the scaling or transformations are done. 
    781997                # Context transformations might change the translation, and we don't want that. 
     
    783999                t.translate(self.x, self.y) 
    7841000                t.concat(painter) 
    785  
     1001                 
    7861002                # Set new width and height factors. Note that no scaling is done yet: they're just here 
    787                 # to set the new center of the image according to the scaling factors. 
     1003                # to set the new center of the image according to the scaling factors 
    7881004                srcW = srcW * factor 
    7891005                srcH = srcH * factor 
    790  
    791                 # Move image to newly calculated center. 
     1006                 
     1007                # Move image to newly calculated center.                 
    7921008                dX = srcW / 2 
    7931009                dY = srcH / 2 
     
    7991015                self._transform.concat(painter) 
    8001016 
    801                 # Move back to the previous position. 
     1017                # Move back to the previous position.                 
    8021018                t = Transform() 
    8031019                t.translate(-dX, -dY) 
    8041020                t.concat(painter) 
    8051021 
    806                 # Finally, scale the image according to the factors. 
     1022                # Finally, scale the image according to the factors.                 
    8071023                t = Transform() 
    8081024                t.scale(factor) 
    809                 t.concat(painter) 
     1025                t.concat(painter)           
    8101026            else: 
    8111027                # Do current transformation 
    812                 #self._transform.concat() 
     1028                self._transform.concat(painter) 
    8131029                # Scale according to width or height factor 
    8141030                t = Transform() 
     
    8191035            # A debugImage draws a black rectangle instead of an image. 
    8201036            if self.debugImage: 
    821                 painter.setBrush(QBrush(Qt.SolidPattern)) 
    822                 painter.fillRect(QRectF(0, 0, srcW / factor, srcH / factor)) 
     1037                painter.setBrush(QBrush(Qt.black)) 
     1038                painter.setPen(QPen(Qt.NoPen)) 
     1039                painter.drawRect(QRectF(0, 0, srcW / factor, srcH / factor)) 
    8231040            else: 
    824                 # TODO: Stuff with composition modes to allow for alpha transparency 
    825                 painter.drawImage(QPointF(0, 0), self._qimage, QRectF(0, 0, srcW, srcH)) 
     1041                painter.setOpacity(self.alpha) 
     1042                painter.drawImage(0, 0, self._qimage) 
    8261043            painter.restore() 
    8271044        # No width or height given 
     
    8421059            # A debugImage draws a black rectangle instead of an image. 
    8431060            if self.debugImage: 
    844                 painter.setBrush(QBrush(Qt.SolidPattern)) 
    845                 painter.fillRect(QRectF(0, 0, srcW, srcH)) 
     1061                painter.setBrush(QBrush(Qt.black)) 
     1062                painter.setPen(QPen(Qt.NoPen)) 
     1063                painter.drawRect(QRectF(x, y, srcW, srcH)) 
    8461064            else: 
    847                 # TODO: Stuff with composition modes to allow for alpha transparency 
    848                 painter.drawImage(QPointF(0, 0), self._qimage, QRectF(0, 0, srcW, srcH)) 
     1065                t = Transform() 
     1066                t.translate(x, y) 
     1067                t.concat(painter) 
     1068                painter.setOpacity(self.alpha) 
     1069                painter.drawImage(0, 0, self._qimage) 
    8491070            painter.restore() 
    8501071 
     
    8551076 
    8561077    __dummy_color = QColor() 
    857     __alignMap = { LEFT: Qt.AlignLeft, RIGHT: Qt.AlignRight, CENTER: Qt.AlignCenter, JUSTIFY: Qt.AlignJustify } 
     1078    __alignMap = { LEFT: Qt.AlignLeft, RIGHT: Qt.AlignRight, CENTER: Qt.AlignHCenter, JUSTIFY: Qt.AlignJustify } 
    8581079     
    8591080    def __init__(self, ctx, text, x=0, y=0, width=None, height=None, **kwargs): 
     
    8851106 
    8861107    def _get_font(self): 
    887         return QFont(self._fontname, self._fontsize) 
     1108        f = QFont(self._fontname) 
     1109        f.setPointSizeF(self._fontsize / textScaleFactor) 
     1110        return f 
    8881111    _qfont = property(_get_font) 
    8891112 
    8901113    def _draw(self, painter): 
    891         if self.width is None: 
    892             w = 100000 
    893         else: 
    894             w = self.width 
    895         if self.height is None: 
    896             h = 100000 
    897         else: 
    898             h = self.height 
    899         fm = painter.fontMetrics() 
    900         flags = self.__alignMap[self._align] 
    901         r = fm.boundingRect(self.x, self.y, w, h, flags, self.text) 
    902  
    9031114        if self._fillcolor is None: return 
    904         x,y = r.x(), r.y() 
     1115        flags = self.__alignMap[self._align] | Qt.TextWordWrap 
     1116        fm = QFontMetricsF(self._qfont)                 
     1117        w = self.width or 100000 
     1118        h = self.height or 100000 
     1119        preferredWidth, preferredHeight = w, h 
     1120        r = fm.boundingRect(QRectF(self.x, self.y, w, h), flags, self.text) 
     1121        x, y = r.x(), r.y() 
    9051122        w, h = r.width(), r.height() 
    906         preferredWidth, preferredHeight = r.width(), r.height() 
    9071123        if self.width is not None: 
    9081124            if self._align == RIGHT: 
     
    9111127                x += preferredWidth/2 - w/2 
    9121128 
     1129        textLayout = QTextLayout() 
     1130        textLayout.setFont(self._qfont) 
     1131        textLayout.setText(self.text) 
     1132        opt = QTextOption() 
     1133        opt.setAlignment(self.__alignMap[self._align]) 
     1134        opt.setWrapMode(QTextOption.WrapAtWordBoundaryOrAnywhere) 
     1135        textLayout.setTextOption(opt) 
     1136        textLayout.beginLayout() 
     1137        lineSpacing = (fm.ascent() + fm.descent() + fm.leading()) * self._lineheight 
     1138 
     1139        advance = 0 
     1140        while True: 
     1141            line = textLayout.createLine() 
     1142            if not line.isValid(): 
     1143                break 
     1144            line.setLineWidth(w) 
     1145            line.setPosition(QPointF(0, advance)) 
     1146            advance += lineSpacing 
     1147        textLayout.endLayout() 
     1148         
    9131149        painter.save() 
    914         painter.setFont(self._qfont) 
    915         self._fillcolor._set(painter) 
    916         #painter.setBrush(QBrush(self._fillcolor)) 
     1150        p = QPen(QBrush(self._fillcolor._rgb), 0) 
     1151        painter.setPen(p) 
     1152         
    9171153        # Center-mode transforms: translate to image center 
    9181154        if self._transformmode == CENTER: 
     1155            lc = textLayout.lineCount()*lineSpacing 
    9191156            deltaX = w / 2 
    9201157            deltaY = h / 2 
    9211158            t = Transform() 
    922             #t.translate(x+deltaX, y+fm.ascent()+deltaY) 
     1159            t.translate(deltaX,lc/2) 
    9231160            t.concat(painter) 
    9241161            self._transform.concat(painter) 
    925             painter.drawText(x, y, w, h, flags, self.text) 
    926             #layoutManager.drawGlyphsForGlyphRange_atPoint_(glyphRange, (-deltaX-dx,-deltaY-dy)) 
     1162            t = Transform() 
     1163            t.translate(-deltaX,-lc/2) 
     1164            t.concat(painter) 
    9271165        else: 
    928             self._transform.concat() 
    929             painter.drawText(x, y, w, h, flags, self.text) 
    930             #layoutManager.drawGlyphsForGlyphRange_atPoint_(glyphRange, (x-dx,y-dy-self.font.defaultLineHeightForFont())) 
     1166            self._transform.concat(painter) 
     1167 
     1168        textLayout.draw(painter, QPointF(x, y)) 
    9311169        painter.restore() 
    9321170        return (w, h) 
     
    9341172    def _get_metrics(self):