def _get_font(self):
     _font = AppKit.NSFont.fontWithName_size_(self._fontName, self.fontSize)
     if _font == None:
         ff = self._fallbackFontName or _FALLBACKFONT
         warnings.warn(
             "font: %s is not installed, back to the fallback font: %s" %
             (self._fontName, ff))
         self._fontName = ff
         _font = AppKit.NSFont.fontWithName_size_(ff, self.fontSize)
     coreTextfeatures = []
     for featureTag, value in self.openTypeFeatures.items():
         if not value:
             featureTag = "%s_off" % featureTag
         if featureTag in openType.featureMap:
             feature = openType.featureMap[featureTag]
             coreTextfeatures.append(feature)
     fontDescriptor = _font.fontDescriptor()
     fontAttributes = {
         CoreText.NSFontFeatureSettingsAttribute: coreTextfeatures,
     }
     if self._fallbackFontName:
         fontAttributes[CoreText.NSFontCascadeListAttribute] = [
             AppKit.NSFontDescriptor.fontDescriptorWithName_size_(
                 self._fallbackFontName, self.fontSize)
         ]
     fontDescriptor = fontDescriptor.fontDescriptorByAddingAttributes_(
         fontAttributes)
     _font = AppKit.NSFont.fontWithDescriptor_size_(fontDescriptor,
                                                    self.fontSize)
     return _font
 def appendGlyph(self, *glyphNames):
     """
     Appends a glyph by his glyph name using the current `font`.
     """
     # use a non breaking space as replacement character
     baseString = unichr(0x00A0)
     font = None
     if self._font:
         font = AppKit.NSFont.fontWithName_size_(self._font, self._fontSize)
     if font is None:
         warnings.warn(
             "font: %s is not installed, back to the fallback font: %s" %
             (self._font, _FALLBACKFONT))
         font = AppKit.NSFont.fontWithName_size_(_FALLBACKFONT,
                                                 self._fontSize)
     fallbackFont = self._fallbackFont
     self._fallbackFont = None
     for glyphName in glyphNames:
         glyph = font.glyphWithName_(glyphName)
         if glyph:
             self.append(baseString)
             glyphInfo = AppKit.NSGlyphInfo.glyphInfoWithGlyph_forFont_baseString_(
                 glyph, font, baseString)
             self._attributedString.addAttribute_value_range_(
                 AppKit.NSGlyphInfoAttributeName, glyphInfo,
                 (len(self) - 1, 1))
         else:
             warnings.warn("font %s has no glyph with the name %s" %
                           (font.fontName(), glyphName))
     self._fallbackFont = fallbackFont
示例#3
0
 def _pen_width(self):
     i = int(round(value * 300 / 72))
     if i > 10:
         i = 10
         max_pt = (i + 0.4 ) * 72 / 300
         warnings.warn("Stroke widths > %0.2f are not supported in the HPGL context." % max_pt)
     self._hpglData.write(["PW%i;" % i])
示例#4
0
 def _get_font(self):
     _font = AppKit.NSFont.fontWithName_size_(self._fontName, self.fontSize)
     if _font == None:
         warnings.warn("font: %s is not installed, back to the falllback font: %s" % (self._fontName, self._backupFont))
         self._fontName = self._backupFont
         _font = AppKit.NSFont.fontWithName_size_(self._backupFont, self.fontSize)
     return _font
示例#5
0
 def cmykRadialGradient(self,
                        startPoint=None,
                        endPoint=None,
                        colors=None,
                        locations=None,
                        startRadius=0,
                        endRadius=100):
     warnings.warn("cmykRadialGradient is not supported in a svg context")
    def text(self, txt, font=_FALLBACKFONT, fontSize=10, offset=None, box=None):
        """
        Draws a `txt` with a `font` and `fontSize` at an `offset` in the bezier path.

        Optionally `txt` can be a `FormattedString` and be drawn inside a `box`, a tuple of (x, y, width, height).
        """
        try:
            txt = txt.decode("utf-8")
        except:
            pass
        if isinstance(txt, FormattedString):
            attributedString = txt.getNSObject()
        else:
            fontName = font
            font = AppKit.NSFont.fontWithName_size_(font, fontSize)
            if font is None:
                warnings.warn("font: %s is not installed, back to the fallback font: %s" % (fontName, _FALLBACKFONT))
                font = AppKit.NSFont.fontWithName_size_(_FALLBACKFONT, fontSize)

            attributes = {
                AppKit.NSFontAttributeName: font
            }
            attributedString = AppKit.NSAttributedString.alloc().initWithString_attributes_(txt, attributes)
        w, h = attributedString.size()
        setter = CoreText.CTFramesetterCreateWithAttributedString(attributedString)
        path = Quartz.CGPathCreateMutable()
        if offset:
            x, y = offset
        else:
            x = y = 0
        if box:
            bx, by, w, h = box
            x += bx
            y += by
            Quartz.CGPathAddRect(path, None, Quartz.CGRectMake(0, 0, w, h))
        else:
            Quartz.CGPathAddRect(path, None, Quartz.CGRectMake(0, -h, w*2, h*2))
        box = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None)
        ctLines = CoreText.CTFrameGetLines(box)
        origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None)

        if origins and box is not None:
            x -= origins[-1][0]
            y -= origins[-1][1]
        for i, (originX, originY) in enumerate(origins):
            ctLine = ctLines[i]
            ctRuns = CoreText.CTLineGetGlyphRuns(ctLine)
            for ctRun in ctRuns:
                attributes = CoreText.CTRunGetAttributes(ctRun)
                font = attributes.get(AppKit.NSFontAttributeName)
                glyphCount = CoreText.CTRunGetGlyphCount(ctRun)
                for i in range(glyphCount):
                    glyph = CoreText.CTRunGetGlyphs(ctRun, (i, 1), None)[0]
                    ax, ay = CoreText.CTRunGetPositions(ctRun, (i, 1), None)[0]
                    if glyph:
                        self._path.moveToPoint_((x+originX+ax, y+originY+ay))
                        self._path.appendBezierPathWithGlyph_inFont_(glyph, font)
        self.optimizePath()
示例#7
0
 def _get_font(self):
     _font = AppKit.NSFont.fontWithName_size_(self._fontName, self.fontSize)
     if _font == None:
         warnings.warn(
             "font: %s is not installed, back to the fallback font: %s" %
             (self._fontName, self._backupFont))
         self._fontName = self._backupFont
         _font = AppKit.NSFont.fontWithName_size_(self._backupFont,
                                                  self.fontSize)
     return _font
 def fontLeading(self):
     """
     Returns the current font leading, based on the current `font` and `fontSize`.
     """
     font = AppKit.NSFont.fontWithName_size_(self._font, self._fontSize)
     if font is None:
         ff = self._fallbackFont or _FALLBACKFONT
         warnings.warn("font: %s is not installed, back to the fallback font: %s" % (self._font, ff))
         font = AppKit.NSFont.fontWithName_size_(ff, self._fontSize)
     return font.leading()
    def text(self, txt, font=_FALLBACKFONT, fontSize=10, offset=None):
        """
        Draws a `txt` with a `font` and `fontSize` at an `offset` in the bezier path.

        Optionally `txt` can be a `FormattedString`.
        """
        if isinstance(txt, FormattedString):
            attributedString = txt.getNSObject()
        else:
            fontName = font
            font = AppKit.NSFont.fontWithName_size_(font, fontSize)
            if font is None:
                warnings.warn(
                    "font: %s is not installed, back to the fallback font: %s"
                    % (fontName, _FALLBACKFONT))
                font = AppKit.NSFont.fontWithName_size_(
                    _FALLBACKFONT, fontSize)

            attributes = {AppKit.NSFontAttributeName: font}
            attributedString = AppKit.NSAttributedString.alloc(
            ).initWithString_attributes_(txt, attributes)
        w, h = attributedString.size()
        setter = CoreText.CTFramesetterCreateWithAttributedString(
            attributedString)
        path = Quartz.CGPathCreateMutable()
        Quartz.CGPathAddRect(path, None,
                             Quartz.CGRectMake(0, -h, w * 2, h * 2))
        box = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None)
        ctLines = CoreText.CTFrameGetLines(box)
        origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None)
        if offset:
            x, y = offset
        else:
            x = y = 0
        if origins:
            x -= origins[-1][0]
            y -= origins[-1][1]
        for i, (originX, originY) in enumerate(origins):
            ctLine = ctLines[i]
            # path around a bug somewhere
            # create a new CTLine from a substring with the same range...
            rng = CoreText.CTLineGetStringRange(ctLine)
            txtLine = attributedString.attributedSubstringFromRange_(rng)
            ctLine = CoreText.CTLineCreateWithAttributedString(txtLine)
            ctRuns = CoreText.CTLineGetGlyphRuns(ctLine)
            self._path.moveToPoint_((x + originX, y + originY))
            for ctRun in ctRuns:
                glyphs = CoreText.CTRunGetGlyphs(
                    ctRun, CoreText.CTRunGetStringRange(ctRun), None)
                attributes = CoreText.CTRunGetAttributes(ctRun)
                font = attributes.get(AppKit.NSFontAttributeName)
                glyphs = [g for g in glyphs if g != 0]
                self._path.appendBezierPathWithGlyphs_count_inFont_(
                    glyphs, len(glyphs), font)
 def fontLeading(self):
     """
     Returns the current font leading, based on the current `font` and `fontSize`.
     """
     font = AppKit.NSFont.fontWithName_size_(self._font, self._fontSize)
     if font is None:
         ff = self._fallbackFont or _FALLBACKFONT
         warnings.warn(
             "font: %s is not installed, back to the fallback font: %s" %
             (self._font, ff))
         font = AppKit.NSFont.fontWithName_size_(ff, self._fontSize)
     return font.leading()
 def _writeDataToFile(self, data, path, options):
     frameRate = round(1.0 / self._frameDurations[0], 3)
     frameDurations = set(self._frameDurations)
     if len(frameDurations) > 1:
         warnings.warn("Exporting to mp4 doesn't support varying frame durations, only the first value was used.")
     options["multipage"] = True
     codec = options.get("ffmpegCodec", "libx264")
     tempDir = tempfile.mkdtemp(suffix=".mp4tmp")
     try:
         super(MP4Context, self)._writeDataToFile(data, os.path.join(tempDir, "frame.png"), options)
         generateMP4(os.path.join(tempDir, "frame_%d.png"), path, frameRate, codec)
     finally:
         shutil.rmtree(tempDir)
 def _writeDataToFile(self, data, path, options):
     frameRate = round(1.0 / self._frameDurations[0], 3)
     frameDurations = set(self._frameDurations)
     if len(frameDurations) > 1:
         warnings.warn("Exporting to mp4 doesn't support varying frame durations, only the first value was used.")
     options["multipage"] = True
     codec = options.get("ffmpegCodec", "libx264")
     tempDir = tempfile.mkdtemp(suffix=".mp4tmp")
     try:
         super(MP4Context, self)._writeDataToFile(data, os.path.join(tempDir, "frame.png"), options)
         generateMP4(os.path.join(tempDir, "frame_%d.png"), path, frameRate, codec)
     finally:
         shutil.rmtree(tempDir)
 def fontLineHeight(self):
     """
     Returns the current line height, based on the current `font` and `fontSize`.
     If a `lineHeight` is set, this value will be returned.
     """    
     if self._lineHeight is not None:
         return self._lineHeight
     font = AppKit.NSFont.fontWithName_size_(self._font, self._fontSize)
     if font is None:
         ff = self._fallbackFont or _FALLBACKFONT
         warnings.warn("font: %s is not installed, back to the fallback font: %s" % (self._font, ff))
         font = AppKit.NSFont.fontWithName_size_(ff, self._fontSize)
     return font.defaultLineHeightForFont()
 def fontLineHeight(self):
     """
     Returns the current line height, based on the current `font` and `fontSize`.
     If a `lineHeight` is set, this value will be returned.
     """
     if self._lineHeight is not None:
         return self._lineHeight
     font = AppKit.NSFont.fontWithName_size_(self._font, self._fontSize)
     if font is None:
         ff = self._fallbackFont or _FALLBACKFONT
         warnings.warn(
             "font: %s is not installed, back to the fallback font: %s" %
             (self._font, ff))
         font = AppKit.NSFont.fontWithName_size_(ff, self._fontSize)
     return font.defaultLineHeightForFont()
    def text(self, txt, font=_FALLBACKFONT, fontSize=10, offset=None):
        """
        Draws a `txt` with a `font` and `fontSize` at an `offset` in the bezier path.

        Optionally `txt` can be a `FormattedString`.
        """
        if isinstance(txt, FormattedString):
            attributedString = txt.getNSObject()
        else:
            fontName = font
            font = AppKit.NSFont.fontWithName_size_(font, fontSize)
            if font is None:
                warnings.warn("font: %s is not installed, back to the fallback font: %s" % (fontName, _FALLBACKFONT))
                font = AppKit.NSFont.fontWithName_size_(_FALLBACKFONT, fontSize)

            attributes = {
                AppKit.NSFontAttributeName : font
            }
            attributedString = AppKit.NSAttributedString.alloc().initWithString_attributes_(txt, attributes)
        w, h = attributedString.size()
        setter = CoreText.CTFramesetterCreateWithAttributedString(attributedString)
        path = Quartz.CGPathCreateMutable()
        Quartz.CGPathAddRect(path, None, Quartz.CGRectMake(0, -h, w*2, h*2))
        box = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None)
        ctLines = CoreText.CTFrameGetLines(box)
        origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None)
        if offset:
            x, y = offset
        else:
            x = y = 0
        if origins:
            x -= origins[-1][0]
            y -= origins[-1][1]
        for i, (originX, originY) in enumerate(origins):
            ctLine = ctLines[i]
            # path around a bug somewhere
            # create a new CTLine from a substring with the same range...
            rng = CoreText.CTLineGetStringRange(ctLine)
            txtLine = attributedString.attributedSubstringFromRange_(rng)
            ctLine = CoreText.CTLineCreateWithAttributedString(txtLine)
            ctRuns = CoreText.CTLineGetGlyphRuns(ctLine)
            self._path.moveToPoint_((x+originX, y+originY))
            for ctRun in ctRuns:
                glyphs = CoreText.CTRunGetGlyphs(ctRun, CoreText.CTRunGetStringRange(ctRun), None)
                attributes = CoreText.CTRunGetAttributes(ctRun)
                font = attributes.get(AppKit.NSFontAttributeName)
                glyphs = [g for g in glyphs if g != 0]
                self._path.appendBezierPathWithGlyphs_count_inFont_(glyphs, len(glyphs), font)
示例#16
0
 def radialGradient(self,
                    startPoint=None,
                    endPoint=None,
                    colors=None,
                    locations=None,
                    startRadius=0,
                    endRadius=100):
     super(SVGContext,
           self).radialGradient(startPoint, endPoint, colors, locations,
                                startRadius, endRadius)
     if startRadius != 0:
         warnings.warn(
             "radialGradient will clip the startRadius to '0' in a svg context."
         )
     if self._state.gradient is not None:
         self._state.gradient.writeDefs(self._svgContext)
示例#17
0
 def _get_font(self):
     _font = AppKit.NSFont.fontWithName_size_(self._fontName, self.fontSize)
     if _font == None:
         warnings.warn("font: %s is not installed, back to the fallback font: %s" % (self._fontName, _FALLBACKFONT))
         self._fontName = _FALLBACKFONT
         _font = AppKit.NSFont.fontWithName_size_(_FALLBACKFONT, self.fontSize)
     coreTextfeatures = []
     for featureTag, value in self.openTypeFeatures.items():
         if not value:
             featureTag = "%s_off" % featureTag
         if featureTag in openType.featureMap:
             feature = openType.featureMap[featureTag]
             coreTextfeatures.append(feature)
     fontDescriptor = _font.fontDescriptor()
     fontDescriptor = fontDescriptor.fontDescriptorByAddingAttributes_({CoreText.NSFontFeatureSettingsAttribute : coreTextfeatures})
     _font = AppKit.NSFont.fontWithDescriptor_size_(fontDescriptor, self.fontSize)
     return _font
示例#18
0
def getFontVariationAttributes(font, fontVariations):
    coreTextFontVariations = dict()
    if fontVariations:
        existingAxes = getVariationAxesForFont(font)
        for axis, value in fontVariations.items():
            if axis in existingAxes:
                existinsAxis = existingAxes[axis]
                # clip variation value within the min max value
                if value < existinsAxis["minValue"]:
                    value = existinsAxis["minValue"]
                if value > existinsAxis["maxValue"]:
                    value = existinsAxis["maxValue"]
                coreTextFontVariations[convertVariationTagToInt(axis)] = value
            else:
                warnings.warn("variation axis '%s' not available for '%s'" %
                              (axis, font.fontName()))
    return coreTextFontVariations
示例#19
0
    def _writeDataToFile(self, data, path, options):
        if os.path.exists(path):
            os.remove(path)
        warnings.warn("export to '.mov' is deprecated, use '.mp4' instead.")
        movie, error = QTKit.QTMovie.alloc().initToWritableFile_error_(path, None)
        if error:
            raise DrawBotError("Could not create a quick time movie, %s" % error.localizedDescription())

        pdfDocument = Quartz.PDFDocument.alloc().initWithData_(data)

        for index in range(pdfDocument.pageCount()):
            pool = AppKit.NSAutoreleasePool.alloc().init()
            try:
                frameLength, frameScale = self._frameDurationData[index]
                duration = QTKit.QTMakeTime(frameLength, frameScale)
                page = pdfDocument.pageAtIndex_(index)
                image = AppKit.NSImage.alloc().initWithData_(page.dataRepresentation())
                movie.addImage_forDuration_withAttributes_(image, duration, self._saveMovieAttributes)
            finally:
                del pool
        movie.updateMovieFile()
 def _get_font(self):
     _font = AppKit.NSFont.fontWithName_size_(self._fontName, self.fontSize)
     if _font is None:
         ff = self._fallbackFontName or _FALLBACKFONT
         warnings.warn("font: %s is not installed, back to the fallback font: %s" % (self._fontName, ff))
         self._fontName = ff
         _font = AppKit.NSFont.fontWithName_size_(ff, self.fontSize)
     coreTextfeatures = []
     for featureTag, value in self.openTypeFeatures.items():
         if not value:
             featureTag = "%s_off" % featureTag
         if featureTag in openType.featureMap:
             feature = openType.featureMap[featureTag]
             coreTextfeatures.append(feature)
     fontDescriptor = _font.fontDescriptor()
     fontAttributes = {
         CoreText.NSFontFeatureSettingsAttribute: coreTextfeatures,
         }
     if self._fallbackFontName:
         fontAttributes[CoreText.NSFontCascadeListAttribute] = [AppKit.NSFontDescriptor.fontDescriptorWithName_size_(self._fallbackFontName, self.fontSize)]
     fontDescriptor = fontDescriptor.fontDescriptorByAddingAttributes_(fontAttributes)
     _font = AppKit.NSFont.fontWithDescriptor_size_(fontDescriptor, self.fontSize)
     return _font
 def appendGlyph(self, *glyphNames):
     """
     Appends a glyph by his glyph name using the current `font`.
     """
     # use a non breaking space as replacement character
     baseString = unichr(0x00A0)
     font = None
     if self._font:
         font = AppKit.NSFont.fontWithName_size_(self._font, self._fontSize)
     if font is None:
         warnings.warn("font: %s is not installed, back to the fallback font: %s" % (self._font, _FALLBACKFONT))
         font = AppKit.NSFont.fontWithName_size_(_FALLBACKFONT, self._fontSize)
     fallbackFont = self._fallbackFont
     self._fallbackFont = None
     for glyphName in glyphNames:
         glyph = font.glyphWithName_(glyphName)
         if glyph:
             self.append(baseString)
             glyphInfo = AppKit.NSGlyphInfo.glyphInfoWithGlyph_forFont_baseString_(glyph, font , baseString)
             self._attributedString.addAttribute_value_range_(AppKit.NSGlyphInfoAttributeName, glyphInfo, (len(self)-1, 1))
         else:
             warnings.warn("font %s has no glyph with the name %s" % (font.fontName(), glyphName))
     self._fallbackFont = fallbackFont
 def cmykShadow(self, offset, blur, color):
     warnings.warn("cmykShadow is not supported in a svg context")
 def cmykRadialGradient(self, startPoint=None, endPoint=None, colors=None, locations=None, startRadius=0, endRadius=100):
     warnings.warn("cmykRadialGradient is not supported in a svg context")
 def cmykLinearGradient(self, startPoint=None, endPoint=None, colors=None, locations=None):
     warnings.warn("cmykLinearGradient is not supported in a svg context")
 def cmykStroke(self, c, m, y, k, a=1):
     warnings.warn("cmykStroke is not supported in a svg context")
 def cmykFill(self, c, m, y, k, a=1):
     warnings.warn("cmykFill is not supported in a svg context")
示例#27
0
class SVGContext(BaseContext):

    _graphicsStateClass = SVGGraphicsState
    _shadowClass = SVGShadow
    _colorClass = SVGColor
    _gradientClass = SVGGradient

    _svgFileClass = SVGFile

    _svgTagArguments = {
        "version": "1.1",
        "xmlns": "http://www.w3.org/2000/svg",
        "xmlns:xlink": "http://www.w3.org/1999/xlink"
    }

    _svgLineJoinStylesMap = {
        AppKit.NSMiterLineJoinStyle: "miter",
        AppKit.NSRoundLineJoinStyle: "round",
        AppKit.NSBevelLineJoinStyle: "bevel"
    }

    _svgLineCapStylesMap = {
        AppKit.NSButtLineCapStyle: "butt",
        AppKit.NSSquareLineCapStyle: "square",
        AppKit.NSRoundLineCapStyle: "round",
    }

    fileExtensions = ["svg"]

    def __init__(self):
        super(SVGContext, self).__init__()
        self._pages = []

    # not supported in a svg context

    def openTypeFeatures(self, *args, **features):
        warnings.warn("openTypeFeatures is not supported in a svg context")

    def cmykFill(self, c, m, y, k, a=1):
        warnings.warn("cmykFill is not supported in a svg context")

    def cmykStroke(self, c, m, y, k, a=1):
        warnings.warn("cmykStroke is not supported in a svg context")

    def cmykLinearGradient(self,
                           startPoint=None,
                           endPoint=None,
                           colors=None,
                           locations=None):
        warnings.warn("cmykLinearGradient is not supported in a svg context")

    def cmykRadialGradient(self,
                           startPoint=None,
                           endPoint=None,
                           colors=None,
                           locations=None,
                           startRadius=0,
                           endRadius=100):
        warnings.warn("cmykRadialGradient is not supported in a svg context")

    def cmykShadow(self, offset, blur, color):
        warnings.warn("cmykShadow is not supported in a svg context")

    # svg overwrites

    def shadow(self, offset, blur, color):
        super(SVGContext, self).shadow(offset, blur, color)
        if self._state.shadow is not None:
            self._state.shadow.writeDefs(self._svgContext)

    def linearGradient(self,
                       startPoint=None,
                       endPoint=None,
                       colors=None,
                       locations=None):
        super(SVGContext, self).linearGradient(startPoint, endPoint, colors,
                                               locations)
        if self._state.gradient is not None:
            self._state.gradient.writeDefs(self._svgContext)

    def radialGradient(self,
                       startPoint=None,
                       endPoint=None,
                       colors=None,
                       locations=None,
                       startRadius=0,
                       endRadius=100):
        super(SVGContext,
              self).radialGradient(startPoint, endPoint, colors, locations,
                                   startRadius, endRadius)
        if startRadius != 0:
            warnings.warn(
                "radialGradient will clip the startRadius to '0' in a svg context."
            )
        if self._state.gradient is not None:
            self._state.gradient.writeDefs(self._svgContext)

    # svg

    def _newPage(self, width, height):
        if hasattr(self, "_svgContext"):
            self._svgContext.endtag("svg")
        self.reset()
        self.size(width, height)
        self._svgData = self._svgFileClass()
        self._pages.append(self._svgData)
        self._svgContext = XMLWriter(self._svgData, encoding="utf-8")
        self._svgContext.width = self.width
        self._svgContext.height = self.height
        self._svgContext.begintag("svg",
                                  width=self.width,
                                  height=self.height,
                                  **self._svgTagArguments)
        self._svgContext.newline()
        self._state.transformMatrix = self._state.transformMatrix.scale(
            1, -1).translate(0, -self.height)

    def _saveImage(self, path, multipage):
        if multipage is None:
            multipage = False
        self._svgContext.endtag("svg")
        fileName, fileExt = os.path.splitext(path)
        firstPage = 0
        pageCount = len(self._pages)
        pathAdd = "_1"
        if not multipage:
            firstPage = pageCount - 1
            pathAdd = ""
        for index in range(firstPage, pageCount):
            page = self._pages[index]
            svgPath = fileName + pathAdd + fileExt
            page.writeToFile(svgPath)
            pathAdd = "_%s" % (index + 2)

    def _save(self):
        pass

    def _restore(self):
        pass

    def _drawPath(self):
        if self._state.path:
            self._svgBeginClipPath()
            data = self._svgDrawingAttributes()
            data["d"] = self._svgPath(self._state.path)
            data["transform"] = self._svgTransform(self._state.transformMatrix)
            if self._state.shadow is not None:
                data["filter"] = "url(#%s)" % self._state.shadow.tagID
            if self._state.gradient is not None:
                data["fill"] = "url(#%s)" % self._state.gradient.tagID
            self._svgContext.simpletag("path", **data)
            self._svgContext.newline()
            self._svgEndClipPath()

    def _clipPath(self):
        uniqueID = self._getUniqueID()
        self._svgContext.begintag("clipPath", id=uniqueID)
        self._svgContext.newline()
        data = dict()
        data["d"] = self._svgPath(self._state.path)
        data["transform"] = self._svgTransform(self._state.transformMatrix)
        data["clip-rule"] = "evenodd"
        self._svgContext.simpletag("path", **data)
        self._svgContext.newline()
        self._svgContext.endtag("clipPath")
        self._svgContext.newline()
        self._state.clipPathID = uniqueID

    def _textBox(self, txt, (x, y, w, h), align):
        canDoGradients = not isinstance(txt, FormattedString)
        if align == "justified":
            warnings.warn("justified text is not supported in a svg context")
        attrString = self.attributedString(txt, align=align)
        if self._state.text.hyphenation:
            attrString = self.hyphenateAttributedString(attrString, w)
        txt = attrString.string()

        setter = CoreText.CTFramesetterCreateWithAttributedString(attrString)
        path = CoreText.CGPathCreateMutable()
        CoreText.CGPathAddRect(path, None, CoreText.CGRectMake(x, y, w, h))
        box = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None)

        self._svgBeginClipPath()
        defaultData = self._svgDrawingAttributes()

        data = {"text-anchor": "start"}
        if self._state.shadow is not None:
            data["filter"] = "url(#%s_flipped)" % self._state.shadow.tagID
        self._svgContext.begintag("text", **data)
        self._svgContext.newline()

        ctLines = CoreText.CTFrameGetLines(box)
        origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None)
        for i, (originX, originY) in enumerate(origins):
            ctLine = ctLines[i]
            # bounds = CoreText.CTLineGetImageBounds(ctLine, self._pdfContext)
            # if bounds.size.width == 0:
            #     continue
            ctRuns = CoreText.CTLineGetGlyphRuns(ctLine)
            for ctRun in ctRuns:
                attributes = CoreText.CTRunGetAttributes(ctRun)
                font = attributes.get(AppKit.NSFontAttributeName)
                fillColor = attributes.get(
                    AppKit.NSForegroundColorAttributeName)
                strokeColor = attributes.get(AppKit.NSStrokeColorAttributeName)
                strokeWidth = attributes.get(AppKit.NSStrokeWidthAttributeName,
                                             self._state.strokeWidth)

                fontName = font.fontName()
                fontSize = font.pointSize()

                spanData = dict(defaultData)
                spanData["fill"] = self._colorClass(fillColor).svgColor()
                spanData["stroke"] = self._colorClass(strokeColor).svgColor()
                spanData["stroke-width"] = strokeWidth
                spanData["font-family"] = fontName
                spanData["font-size"] = fontSize

                if canDoGradients and self._state.gradient is not None:
                    spanData[
                        "fill"] = "url(#%s_flipped)" % self._state.gradient.tagID

                self._save()

                r = CoreText.CTRunGetStringRange(ctRun)
                runTxt = txt.substringWithRange_((r.location, r.length))
                while runTxt and runTxt[-1] == " ":
                    runTxt = runTxt[:-1]
                runTxt = runTxt.replace("\n", "")
                runTxt = runTxt.encode("utf-8")

                runPos = CoreText.CTRunGetPositions(ctRun, (0, 1), None)
                runX = runY = 0
                if runPos:
                    runX = runPos[0].x
                    runY = runPos[0].y

                spanData["x"] = originX + runX + x
                spanData["y"] = self.height - y - originY - runY
                self._svgContext.begintag("tspan", **spanData)
                self._svgContext.newline()
                self._svgContext.write(runTxt)
                self._svgContext.newline()
                self._svgContext.endtag("tspan")
                self._svgContext.newline()
                self._restore()

        self._svgContext.endtag("text")
        self._svgContext.newline()
        self._svgEndClipPath()
示例#28
0
 def cmykStroke(self, c, m, y, k, a=1):
     warnings.warn("cmykStroke is not supported in a svg context")
示例#29
0
 def cmykFill(self, c, m, y, k, a=1):
     warnings.warn("cmykFill is not supported in a svg context")
示例#30
0
 def cmykShadow(self, offset, blur, color):
     warnings.warn("cmykShadow is not supported in a svg context")
示例#31
0
 def cmykLinearGradient(self, startPoint=None, endPoint=None, colors=None, locations=None):
     warnings.warn("cmykLinearGradient is not supported in a svg context")
    def append(self,
               txt,
               font=None,
               fallbackFont=None,
               fontSize=None,
               fill=None,
               cmykFill=None,
               stroke=None,
               cmykStroke=None,
               strokeWidth=None,
               align=None,
               lineHeight=None,
               openTypeFeatures=None):
        """
        Add `txt` to the formatted string with some additional text formatting attributes:

        * `font`: the font to be used for the given text
        * `fallbackFont`: the fallback font
        * `fontSize`: the font size to be used for the given text
        * `fill`: the fill color to be used for the given text
        * `cmykFill`: the cmyk fill color to be used for the given text
        * `stroke`: the stroke color to be used for the given text
        * `cmykStroke`: the cmyk stroke color to be used for the given text
        * `strokeWidth`: the strokeWidth to be used for the given text
        * `align`: the alignment to be used for the given text
        * `lineHeight`: the lineHeight to be used for the given text
        * `openTypeFeatures`: enable OpenType features

        All formatting attributes follow the same notation as other similar DrawBot methods.
        A color is a tuple of `(r, g, b, alpha)`, and a cmykColor is a tuple of `(c, m, y, k, alpha)`.

        Text can also be added with `formattedString += "hello"`. It will append the text with the current settings of the formatted string.
        """
        if font is None:
            font = self._font
        else:
            self._font = font

        if fallbackFont is None:
            fallbackFont = self._fallbackFont
        else:
            self._fallbackFont = fallbackFont

        if fontSize is None:
            fontSize = self._fontSize
        else:
            self._fontSize = fontSize

        if fill is None and cmykFill is None:
            fill = self._fill
            cmykFill = self._cmykFill
        elif fill is not None:
            self._fill = fill
            self._cmykFill = None
        elif cmykFill is not None:
            self._cmykFill = cmykFill
            self._fill = None

        if stroke is None and cmykStroke is None:
            stroke = self._stroke
            cmykStroke = self._cmykStroke
        elif stroke is not None:
            self._stroke = stroke
            self._cmykStroke = None
        elif cmykStroke is not None:
            self._cmykStroke = cmykStroke
            self._stroke = None

        if strokeWidth is None:
            strokeWidth = self._strokeWidth
        else:
            self._strokeWidth = strokeWidth

        if align is None:
            align = self._align
        else:
            self._align = align

        if lineHeight is None:
            lineHeight = self._lineHeight
        else:
            self._lineHeight = lineHeight

        if openTypeFeatures is None:
            openTypeFeatures = self._openTypeFeatures
        else:
            self._openTypeFeatures = openTypeFeatures

        if isinstance(txt, FormattedString):
            self._attributedString.appendAttributedString_(txt.getNSObject())
            return
        attributes = {}
        if font:
            fontName = font
            font = AppKit.NSFont.fontWithName_size_(fontName, fontSize)
            if font is None:
                ff = fallbackFont
                if ff is None:
                    ff = _FALLBACKFONT
                warnings.warn(
                    "font: %s is not installed, back to the fallback font: %s"
                    % (fontName, ff))
                font = AppKit.NSFont.fontWithName_size_(ff, fontSize)
            coreTextfeatures = []
            for featureTag, value in openTypeFeatures.items():
                if not value:
                    featureTag = "%s_off" % featureTag
                if featureTag in openType.featureMap:
                    feature = openType.featureMap[featureTag]
                    coreTextfeatures.append(feature)
            fontDescriptor = font.fontDescriptor()
            fontAttributes = {
                CoreText.NSFontFeatureSettingsAttribute: coreTextfeatures,
            }
            if fallbackFont:
                fontAttributes[CoreText.NSFontCascadeListAttribute] = [
                    AppKit.NSFontDescriptor.fontDescriptorWithName_size_(
                        fallbackFont, fontSize)
                ]
            fontDescriptor = fontDescriptor.fontDescriptorByAddingAttributes_(
                fontAttributes)
            font = AppKit.NSFont.fontWithDescriptor_size_(
                fontDescriptor, fontSize)
            attributes[AppKit.NSFontAttributeName] = font
        elif fontSize:
            font = AppKit.NSFont.fontWithName_size_(_FALLBACKFONT, fontSize)
            attributes[AppKit.NSFontAttributeName] = font
        if fill or cmykFill:
            if fill:
                fillColor = self._colorClass.getColor(fill).getNSObject()
            elif cmykFill:
                fillColor = self._cmykColorClass.getColor(
                    cmykFill).getNSObject()
            attributes[AppKit.NSForegroundColorAttributeName] = fillColor
        if stroke or cmykStroke:
            if stroke:
                strokeColor = self._colorClass.getColor(stroke).getNSObject()
            elif cmykStroke:
                strokeColor = self._cmykColorClass.getColor(
                    cmykStroke).getNSObject()
            attributes[AppKit.NSStrokeColorAttributeName] = strokeColor
            attributes[AppKit.NSStrokeWidthAttributeName] = -abs(strokeWidth)
        para = AppKit.NSMutableParagraphStyle.alloc().init()
        if align:
            para.setAlignment_(self._textAlignMap[align])
        if lineHeight:
            #para.setLineSpacing_(lineHeight)
            para.setMaximumLineHeight_(lineHeight)
            para.setMinimumLineHeight_(lineHeight)
        attributes[AppKit.NSParagraphStyleAttributeName] = para
        txt = AppKit.NSAttributedString.alloc().initWithString_attributes_(
            txt, attributes)
        self._attributedString.appendAttributedString_(txt)
示例#33
0
 def openTypeFeatures(self, *args, **features):
     warnings.warn("openTypeFeatures is not supported in a svg context")
示例#34
0
    def _textBox(self, rawTxt, box, align):
        path, (x, y) = self._getPathForFrameSetter(box)
        canDoGradients = True
        if align == "justified":
            warnings.warn("justified text is not supported in a svg context")
        attrString = self.attributedString(rawTxt, align=align)
        if self._state.hyphenation:
            attrString = self.hyphenateAttributedString(attrString, path)
        txt = attrString.string()
        setter = CoreText.CTFramesetterCreateWithAttributedString(attrString)
        box = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None)

        self._svgBeginClipPath()
        defaultData = self._svgDrawingAttributes()

        data = {
            "text-anchor": "start",
            "transform": self._svgTransform(self._state.transformMatrix.translate(x, y + self.height).scale(1, -1))
        }
        if self._state.shadow is not None:
            data["filter"] = "url(#%s_flipped)" % self._state.shadow.tagID
        if isinstance(rawTxt, FormattedString):
            if rawTxt.svgID:
                data["id"] = rawTxt.svgID
            if rawTxt.svgClass:
                data["class"] = rawTxt.svgClass
            if rawTxt.svgLink:
                self._svgContext.begintag("a", **{"xlink:href": rawTxt.svgLink})
                self._svgContext.newline()
        self._svgContext.begintag("text", **data)
        self._svgContext.newline()

        ctLines = CoreText.CTFrameGetLines(box)
        origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None)
        for i, (originX, originY) in enumerate(origins):
            ctLine = ctLines[i]
            # bounds = CoreText.CTLineGetImageBounds(ctLine, self._pdfContext)
            # if bounds.size.width == 0:
            #     continue
            ctRuns = CoreText.CTLineGetGlyphRuns(ctLine)
            for ctRun in ctRuns:
                stringRange = CoreText.CTRunGetStringRange(ctRun)
                attributes = CoreText.CTRunGetAttributes(ctRun)
                font = attributes.get(AppKit.NSFontAttributeName)
                fontDescriptor = font.fontDescriptor()
                fillColor = attributes.get(AppKit.NSForegroundColorAttributeName)
                strokeColor = attributes.get(AppKit.NSStrokeColorAttributeName)
                strokeWidth = attributes.get(AppKit.NSStrokeWidthAttributeName, self._state.strokeWidth)
                baselineShift = attributes.get(AppKit.NSBaselineOffsetAttributeName, 0)
                openTypeFeatures = attributes.get("drawbot.openTypeFeatures")
                underline = attributes.get(AppKit.NSUnderlineStyleAttributeName)
                url = attributes.get(AppKit.NSLinkAttributeName)

                fontName = font.fontName()
                fontSize = font.pointSize()
                fontFallbacks = [fallbackFont.postscriptName() for fallbackFont in fontDescriptor.get(CoreText.NSFontCascadeListAttribute, [])]
                fontNames = ", ".join([fontName] + fontFallbacks)

                style = dict()
                spanData = dict(defaultData)
                fill = self._colorClass(fillColor).svgColor()
                if fill:
                    c, a = fill
                    spanData["fill"] = c
                    if a != 1:
                        spanData["fill-opacity"] = a
                stroke = self._colorClass(strokeColor).svgColor()
                if stroke:
                    c, a = stroke
                    spanData["stroke"] = c
                    if a != 1:
                        spanData["stroke-opacity"] = a
                    spanData["stroke-width"] = formatNumber(abs(strokeWidth) * .5)
                spanData["font-family"] = fontNames
                spanData["font-size"] = formatNumber(fontSize)

                if openTypeFeatures:
                    style["font-feature-settings"] = self._svgStyleOpenTypeFeatures(openTypeFeatures)

                if canDoGradients and self._state.gradient is not None:
                    spanData["fill"] = "url(#%s_flipped)" % self._state.gradient.tagID

                if underline is not None:
                    style["text-decoration"] = "underline"
                    underlineStyle = self._svgUnderlineStylesMap.get(underline)
                    if underlineStyle:
                        style["text-decoration-style"] = underlineStyle

                if style:
                    spanData["style"] = self._svgStyle(**style)
                self._save()

                runTxt = txt.substringWithRange_((stringRange.location, stringRange.length))
                while runTxt and runTxt[-1] == " ":
                    runTxt = runTxt[:-1]
                runTxt = runTxt.replace("\n", "")
                runTxt = runTxt.encode("utf-8")

                runPos = CoreText.CTRunGetPositions(ctRun, (0, 1), None)
                runX = runY = 0
                if runPos:
                    runX = runPos[0].x
                    runY = runPos[0].y

                spanData["x"] = formatNumber(originX + runX)
                spanData["y"] = formatNumber(self.height - originY - runY + baselineShift)
                if url is not None:
                    self._svgContext.begintag("a", href=url.absoluteString())
                    self._svgContext.newline()
                self._svgContext.begintag("tspan", **spanData)
                self._svgContext.newline()
                self._svgContext.write(runTxt)
                self._svgContext.newline()
                self._svgContext.endtag("tspan")
                self._svgContext.newline()
                if url is not None:
                    self._svgContext.endtag("a")
                    self._svgContext.newline()
                self._restore()

        self._svgContext.endtag("text")
        self._svgContext.newline()
        if isinstance(rawTxt, FormattedString) and rawTxt.svgLink:
            self._svgContext.endtag("a")
            self._svgContext.newline()
        self._svgEndClipPath()
 def radialGradient(self, startPoint=None, endPoint=None, colors=None, locations=None, startRadius=0, endRadius=100):
     super(SVGContext, self).radialGradient(startPoint, endPoint, colors, locations, startRadius, endRadius)
     if startRadius != 0:
         warnings.warn("radialGradient will clip the startRadius to '0' in a svg context.")
     if self._state.gradient is not None:
         self._state.gradient.writeDefs(self._svgContext)
示例#36
0
 def openTypeFeatures(self, *args, **features):
     warnings.warn("openTypeFeatures is not supported in a svg context")
    def _textBox(self, txt, box, align):
        path, (x, y) = self._getPathForFrameSetter(box)
        canDoGradients = True
        if align == "justified":
            warnings.warn("justified text is not supported in a svg context")
        attrString = self.attributedString(txt, align=align)
        if self._state.hyphenation:
            attrString = self.hyphenateAttributedString(attrString, path)
        txt = attrString.string()
        setter = CoreText.CTFramesetterCreateWithAttributedString(attrString)
        box = CoreText.CTFramesetterCreateFrame(setter, (0, 0), path, None)

        self._svgBeginClipPath()
        defaultData = self._svgDrawingAttributes()

        data = {
            "text-anchor": "start",
            "transform": self._svgTransform(self._state.transformMatrix.translate(x, y + self.height).scale(1, -1))
        }
        if self._state.shadow is not None:
            data["filter"] = "url(#%s_flipped)" % self._state.shadow.tagID
        self._svgContext.begintag("text", **data)
        self._svgContext.newline()

        ctLines = CoreText.CTFrameGetLines(box)
        origins = CoreText.CTFrameGetLineOrigins(box, (0, len(ctLines)), None)
        for i, (originX, originY) in enumerate(origins):
            ctLine = ctLines[i]
            # bounds = CoreText.CTLineGetImageBounds(ctLine, self._pdfContext)
            # if bounds.size.width == 0:
            #     continue
            ctRuns = CoreText.CTLineGetGlyphRuns(ctLine)
            for ctRun in ctRuns:
                stringRange = CoreText.CTRunGetStringRange(ctRun)
                attributes = CoreText.CTRunGetAttributes(ctRun)
                font = attributes.get(AppKit.NSFontAttributeName)
                fontAttributes = font.fontDescriptor().fontAttributes()
                fillColor = attributes.get(AppKit.NSForegroundColorAttributeName)
                strokeColor = attributes.get(AppKit.NSStrokeColorAttributeName)
                strokeWidth = attributes.get(AppKit.NSStrokeWidthAttributeName, self._state.strokeWidth)
                baselineShift = attributes.get(AppKit.NSBaselineOffsetAttributeName, 0)
                openTypeFeatures = fontAttributes.get(CoreText.NSFontFeatureSettingsAttribute)

                fontName = font.fontName()
                fontSize = font.pointSize()

                spanData = dict(defaultData)
                fill = self._colorClass(fillColor).svgColor()
                if fill:
                    c, a = fill
                    spanData["fill"] = c
                    if a != 1:
                        spanData["fill-opacity"] = a
                stroke = self._colorClass(strokeColor).svgColor()
                if stroke:
                    c, a = stroke
                    spanData["stroke"] = c
                    if a != 1:
                        spanData["stroke-opacity"] = a
                    spanData["stroke-width"] = formatNumber(abs(strokeWidth) * .5)
                spanData["font-family"] = fontName
                spanData["font-size"] = formatNumber(fontSize)

                if openTypeFeatures:
                    featureTags = getFeatureTagsForFontAttributes(openTypeFeatures)
                    spanData["style"] = self._svgStyle(**{
                            "font-feature-settings": self._svgStyleOpenTypeFeatures(featureTags)
                        }
                    )

                if canDoGradients and self._state.gradient is not None:
                    spanData["fill"] = "url(#%s_flipped)" % self._state.gradient.tagID

                self._save()

                runTxt = txt.substringWithRange_((stringRange.location, stringRange.length))
                while runTxt and runTxt[-1] == " ":
                    runTxt = runTxt[:-1]
                runTxt = runTxt.replace("\n", "")
                runTxt = runTxt.encode("utf-8")

                runPos = CoreText.CTRunGetPositions(ctRun, (0, 1), None)
                runX = runY = 0
                if runPos:
                    runX = runPos[0].x
                    runY = runPos[0].y

                spanData["x"] = formatNumber(originX + runX)
                spanData["y"] = formatNumber(self.height - originY - runY + baselineShift)
                self._svgContext.begintag("tspan", **spanData)
                self._svgContext.newline()
                self._svgContext.write(runTxt)
                self._svgContext.newline()
                self._svgContext.endtag("tspan")
                self._svgContext.newline()
                self._restore()

        self._svgContext.endtag("text")
        self._svgContext.newline()
        self._svgEndClipPath()
    def append(self, txt,
                    font=None, fallbackFont=None, fontSize=None,
                    fill=None, cmykFill=None,
                    stroke=None, cmykStroke=None, strokeWidth=None,
                    align=None, lineHeight=None,
                    openTypeFeatures=None):
        """
        Add `txt` to the formatted string with some additional text formatting attributes:

        * `font`: the font to be used for the given text
        * `fallbackFont`: the fallback font
        * `fontSize`: the font size to be used for the given text
        * `fill`: the fill color to be used for the given text
        * `cmykFill`: the cmyk fill color to be used for the given text
        * `stroke`: the stroke color to be used for the given text
        * `cmykStroke`: the cmyk stroke color to be used for the given text
        * `strokeWidth`: the strokeWidth to be used for the given text
        * `align`: the alignment to be used for the given text
        * `lineHeight`: the lineHeight to be used for the given text
        * `openTypeFeatures`: enable OpenType features

        All formatting attributes follow the same notation as other similar DrawBot methods.
        A color is a tuple of `(r, g, b, alpha)`, and a cmykColor is a tuple of `(c, m, y, k, alpha)`.

        Text can also be added with `formattedString += "hello"`. It will append the text with the current settings of the formatted string.
        """
        if font is None:
            font = self._font
        else:
            self._font = font

        if fallbackFont is None:
            fallbackFont = self._fallbackFont
        else:
            self._fallbackFont = fallbackFont

        if fontSize is None:
            fontSize = self._fontSize
        else:
            self._fontSize = fontSize

        if fill is None and cmykFill is None:
            fill = self._fill
            cmykFill = self._cmykFill
        elif fill is not None:
            self._fill = fill
            self._cmykFill = None
        elif cmykFill is not None:
            self._cmykFill = cmykFill
            self._fill = None

        if stroke is None and cmykStroke is None:
            stroke = self._stroke
            cmykStroke = self._cmykStroke
        elif stroke is not None:
            self._stroke = stroke
            self._cmykStroke = None
        elif cmykStroke is not None:
            self._cmykStroke = cmykStroke
            self._stroke = None

        if strokeWidth is None:
            strokeWidth = self._strokeWidth
        else:
            self._strokeWidth = strokeWidth

        if align is None:
            align = self._align
        else:
            self._align = align

        if lineHeight is None:
            lineHeight = self._lineHeight
        else:
            self._lineHeight = lineHeight

        if openTypeFeatures is None:
            openTypeFeatures = self._openTypeFeatures
        else:
            self._openTypeFeatures = openTypeFeatures

        if isinstance(txt, FormattedString):
            self._attributedString.appendAttributedString_(txt.getNSObject())
            return
        attributes = {}
        if font:
            fontName = font
            font = AppKit.NSFont.fontWithName_size_(fontName, fontSize)
            if font is None:
                ff = fallbackFont
                if ff is None:
                    ff = _FALLBACKFONT
                warnings.warn("font: %s is not installed, back to the fallback font: %s" % (fontName, ff))
                font = AppKit.NSFont.fontWithName_size_(ff, fontSize)
            coreTextfeatures = []
            for featureTag, value in openTypeFeatures.items():
                if not value:
                    featureTag = "%s_off" % featureTag
                if featureTag in openType.featureMap:
                    feature = openType.featureMap[featureTag]
                    coreTextfeatures.append(feature)
            fontDescriptor = font.fontDescriptor()
            fontAttributes = {
                CoreText.NSFontFeatureSettingsAttribute : coreTextfeatures,
                }
            if fallbackFont:
                fontAttributes[CoreText.NSFontCascadeListAttribute] = [AppKit.NSFontDescriptor.fontDescriptorWithName_size_(fallbackFont, fontSize)]
            fontDescriptor = fontDescriptor.fontDescriptorByAddingAttributes_(fontAttributes)
            font = AppKit.NSFont.fontWithDescriptor_size_(fontDescriptor, fontSize)
            attributes[AppKit.NSFontAttributeName] = font
        elif fontSize:
            font = AppKit.NSFont.fontWithName_size_(_FALLBACKFONT, fontSize)
            attributes[AppKit.NSFontAttributeName] = font
        if fill or cmykFill:
            if fill:
                fillColor = self._colorClass.getColor(fill).getNSObject()
            elif cmykFill:
                fillColor = self._cmykColorClass.getColor(cmykFill).getNSObject()
            attributes[AppKit.NSForegroundColorAttributeName] = fillColor
        if stroke or cmykStroke:
            if stroke:
                strokeColor = self._colorClass.getColor(stroke).getNSObject()
            elif cmykStroke:
                strokeColor = self._cmykColorClass.getColor(cmykStroke).getNSObject()
            attributes[AppKit.NSStrokeColorAttributeName] = strokeColor
            attributes[AppKit.NSStrokeWidthAttributeName] = -abs(strokeWidth)
        para = AppKit.NSMutableParagraphStyle.alloc().init()
        if align:
            para.setAlignment_(self._textAlignMap[align])
        if lineHeight:
            #para.setLineSpacing_(lineHeight)
            para.setMaximumLineHeight_(lineHeight)
            para.setMinimumLineHeight_(lineHeight)
        attributes[AppKit.NSParagraphStyleAttributeName] = para
        txt = AppKit.NSAttributedString.alloc().initWithString_attributes_(txt, attributes)
        self._attributedString.appendAttributedString_(txt)