Example #1
0
 def _svgPath(self, path, transformMatrix=None):
     path = path.getNSBezierPath()
     if transformMatrix:
         path = path.copy()
         aT = AppKit.NSAffineTransform.transform()
         aT.setTransformStruct_(transformMatrix[:])
         path.transformUsingAffineTransform_(aT)
     svg = ""
     for i in range(path.elementCount()):
         instruction, points = path.elementAtIndex_associatedPoints_(i)
         if instruction == AppKit.NSMoveToBezierPathElement:
             svg += "M%s,%s " % (formatNumber(
                 points[0].x), formatNumber(points[0].y))
             previousPoint = points[-1]
         elif instruction == AppKit.NSLineToBezierPathElement:
             x = points[0].x - previousPoint.x
             y = points[0].y - previousPoint.y
             svg += "l%s,%s " % (formatNumber(x), formatNumber(y))
             previousPoint = points[-1]
         elif instruction == AppKit.NSCurveToBezierPathElement:
             offx1 = points[0].x - previousPoint.x
             offy1 = points[0].y - previousPoint.y
             offx2 = points[1].x - previousPoint.x
             offy2 = points[1].y - previousPoint.y
             x = points[2].x - previousPoint.x
             y = points[2].y - previousPoint.y
             svg += "c%s,%s,%s,%s,%s,%s " % (
                 formatNumber(offx1), formatNumber(offy1),
                 formatNumber(offx2), formatNumber(offy2), formatNumber(x),
                 formatNumber(y))
             previousPoint = points[-1]
         elif instruction == AppKit.NSClosePathBezierPathElement:
             svg += "Z "
     return svg.strip()
Example #2
0
 def _svgDrawingAttributes(self):
     data = dict()
     fill = self._svgFillColor()
     if fill:
         c, a = fill
         data["fill"] = c
         if a != 1:
             data["fill-opacity"] = a
     else:
         data["fill"] = "none"
     stroke = self._svgStrokeColor()
     if stroke:
         c, a = stroke
         data["stroke"] = c
         if a != 1:
             data["stroke-opacity"] = a
         data["stroke-width"] = formatNumber(abs(self._state.strokeWidth))
     if self._state.lineDash:
         data["stroke-dasharray"] = ",".join(
             [str(i) for i in self._state.lineDash])
     if self._state.lineJoin in self._svgLineJoinStylesMap:
         data["stroke-linejoin"] = self._svgLineJoinStylesMap[
             self._state.lineJoin]
     if self._state.lineCap in self._svgLineCapStylesMap:
         data["stroke-linecap"] = self._svgLineCapStylesMap[
             self._state.lineCap]
     return data
 def _svgPath(self, path, transformMatrix=None):
     path = path.getNSBezierPath()
     if transformMatrix:
         path = path.copy()
         aT = AppKit.NSAffineTransform.transform()
         aT.setTransformStruct_(transformMatrix[:])
         path.transformUsingAffineTransform_(aT)
     svg = ""
     for i in range(path.elementCount()):
         instruction, points = path.elementAtIndex_associatedPoints_(i)
         if instruction == AppKit.NSMoveToBezierPathElement:
             svg += "M%s,%s " % (formatNumber(points[0].x), formatNumber(points[0].y))
             previousPoint = points[-1]
         elif instruction == AppKit.NSLineToBezierPathElement:
             x = points[0].x - previousPoint.x
             y = points[0].y - previousPoint.y
             svg += "l%s,%s " % (formatNumber(x), formatNumber(y))
             previousPoint = points[-1]
         elif instruction == AppKit.NSCurveToBezierPathElement:
             offx1 = points[0].x - previousPoint.x
             offy1 = points[0].y - previousPoint.y
             offx2 = points[1].x - previousPoint.x
             offy2 = points[1].y - previousPoint.y
             x = points[2].x - previousPoint.x
             y = points[2].y - previousPoint.y
             svg += "c%s,%s,%s,%s,%s,%s " % (formatNumber(offx1), formatNumber(offy1), formatNumber(offx2), formatNumber(offy2), formatNumber(x), formatNumber(y))
             previousPoint = points[-1]
         elif instruction == AppKit.NSClosePathBezierPathElement:
             svg += "Z "
     return svg.strip()
Example #4
0
 def _svgDrawingAttributes(self):
     data = dict()
     fill = self._svgFillColor()
     if fill:
         data["fill"] = fill
     stroke = self._svgStrokeColor()
     if stroke:
         data["stroke"] = stroke
         data["stroke-width"] = formatNumber(abs(self._state.strokeWidth))
     if self._state.lineDash:
         data["stroke-dasharray"] = ",".join([str(i) for i in self._state.lineDash])
     if self._state.lineJoin in self._svgLineJoinStylesMap:
         data["stroke-linejoin"] = self._svgLineJoinStylesMap[self._state.lineJoin]
     if self._state.lineCap in self._svgLineCapStylesMap:
         data["stroke-linecap"] = self._svgLineCapStylesMap[self._state.lineCap]
     return data
    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()
Example #6
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()