예제 #1
0
    def __addRadialGradient(self, element, fill):
        root = fill.getRoot()
        stops = fill
        while len(stops) == 0 and stops.href:
            stops = root.getElementById(stops.href[1:])
        background = []

        #座標補正
        gradientTransform = fill.gradientTransform.toMatrix()
        center = svg.Point(fill.cx, fill.cy)
        finish = svg.Point(fill.fx, fill.fy)
        center = gradientTransform * center
        finish = gradientTransform * finish

        if fill.gradientUnits == "userSpaceOnUse":
            stroke = svg.Length(element.style.get("stroke-width", 0))
            center = svg.Point(center.x - svg.Length(self["left"]) - stroke,
                               center.y - svg.Length(self["top"]) - stroke)
            finish = svg.Point(finish.x - svg.Length(self["left"]) - stroke,
                               finish.y - svg.Length(self["top"]) - stroke)

        #半径の決定
        zero = svg.Length("0")
        point0 = gradientTransform * svg.Point(zero, zero)
        rx = svg.Length(
            abs(gradientTransform * svg.Point(fill.r, zero) - point0), "px")
        ry = svg.Length(
            abs(gradientTransform * svg.Point(zero, fill.r) - point0), "px")
        r = fill.r

        gradient = ""
        for stop in stops:
            color = svg.Color(stop.style["stop-color"])
            if float(stop.style.get("stop-opacity", "1")) <= 0.999:
                color.a = float(stop.style.get("stop-opacity", "1"))
            gradient += ",%s %.1f%%" % (color, stop.offset * 100)
        background.append("radial-gradient(%s %s,%s %s%s)" %
                          (center.x, center.y, rx, ry, gradient))
        background.append("-o-radial-gradient(%s %s,%s %s%s)" %
                          (center.x, center.y, rx, ry, gradient))
        background.append("-moz-radial-gradient(%s %s,circle%s)" %
                          (center.x, center.y, gradient))
        background.append("-moz-radial-gradient(%s %s,%s %s%s)" %
                          (center.x, center.y, rx, ry, gradient))
        background.append("-ms-radial-gradient(%s %s,%s %s%s)" %
                          (center.x, center.y, rx, ry, gradient))
        background.append("-webkit-radial-gradient(%s %s,%s %s%s)" %
                          (center.x, center.y, rx, ry, gradient))

        self["background"] = background
예제 #2
0
    def image(self, x):
        name = self.newName(x)
        if name not in self._css_classes:
            self._css_classes.add(name)
            css = CSSStyle()
            stroke = svg.Length(0)

            #クリップパスの設定
            self.__clipPath(name, x)

            #位置と大きさの設定
            css["position"] = "absolute"
            css["left"] = x.x
            css["top"] = x.y
            css["width"] = x.width
            css["height"] = x.height

            #変形
            if x.transform:
                #CSSとSVGの原点の違いを補正
                transform = x.transform.toMatrix()
                transform = transform * svg.Transform.Translate(
                    x.x + x.width / 2, x.y + x.height / 2)
                transform = svg.Transform.Translate(
                    -x.x - x.width / 2, -x.y - x.height / 2) * transform
                css["transform"] = transform

            #出力
            self._css(cls=name, style=css)

        #クリップの設定
        if name in self.__clipnames:
            clipname = self.__clipnames[name]
            self._html(
                '<div class="%s"><div class="%sinverse"><image class="%s" src=%s /></div></div>\n'
                % (clipname, clipname, name, quoteattr(os.path.basename(
                    x.href))))
            return

        self._html('<image class="%s" src=%s />\n' %
                   (name, quoteattr(os.path.basename(x.href))))
예제 #3
0
    def __text_contents(self, x, x0=0, y0=0, blur=0):
        name = self.newName(x)
        if name not in self._css_classes:
            self._css_classes.add(name)
            css = CSSStyle()

            #フォントに関する属性をコピー
            if "font-size" in x.style:
                css["font-size"] = svg.Length(x.style["font-size"])
            if "fill" in x.style:
                css["color"] = svg.Color(x.style["fill"])
                if "fill-opacity" in x.style:
                    css["color"].a = float(x.style["fill-opacity"])
                if blur > 0.001:
                    css["text-shadow"] = "0px 0px %s %s" % (blur, css["color"])
                    css["color"] = [css["color"], svg.Color(0, 0, 0, 0)]
            for stylename in ["font-style", "font-weight", "font-family"]:
                if stylename in x.style:
                    css[stylename] = x.style[stylename]

            if x.role == "line":
                css["display"] = "block"

            if x.x or x.y:
                css["position"] = "absolute"
                css["left"] = x.x - x0
                css["top"] = x.y - y0

            #出力
            self._css(cls=name, style=css)

        self._html('<span class="%s">' % name)
        if x.x or x.y:
            self._html('<span class="svg-text-adj">&nbsp;</span>')
        for a in x:
            if isinstance(a, svg.TSpan):
                self.__text_contents(a, x.x, x.y, blur)
            elif isinstance(a, svg.Characters):
                self._html(escape(a.content))
        self._html('</span>')
예제 #4
0
    def __addLinearGradient(self, element, fill):
        root = fill.getRoot()
        stops = fill
        while len(stops) == 0 and stops.href:
            stops = root.getElementById(stops.href[1:])
        background = []

        #座標補正
        point1 = svg.Point(fill.x1, fill.y1)
        point2 = svg.Point(fill.x2, fill.y2)
        point1 = fill.gradientTransform.toMatrix() * point1
        point2 = fill.gradientTransform.toMatrix() * point2
        if fill.gradientUnits == "userSpaceOnUse":
            stroke = svg.Length(element.style.get("stroke-width", 0))
            point1 = svg.Point(point1.x - svg.Length(self["left"]) - stroke,
                               point1.y - svg.Length(self["top"]) - stroke)
            point2 = svg.Point(point2.x - svg.Length(self["left"]) - stroke,
                               point2.y - svg.Length(self["top"]) - stroke)

        def svgOffsetToPoint(offset):
            return point1 * (1 - offset) + point2 * offset

        #css3のデフォルト
        rad = -math.atan2(point2.y - point1.y, point2.x - point1.x)
        vec = svg.Point(math.cos(rad), -math.sin(rad))
        deg = rad / math.pi * 180
        width = svg.Length(self["width"])
        height = svg.Length(self["height"])
        point0 = svg.Point(0, 0)
        if 0 < deg < 90:
            point0 = svg.Point(0, height)
        elif 90 <= deg:
            point0 = svg.Point(width, height)
        elif deg < -90:
            point0 = svg.Point(width, 0)
        gradientlen = (svg.Point(width, height) - point0 * 2) * vec

        def pointToCSSOffset(point):
            offset = (point - point0) * vec / gradientlen
            return offset

        def svgOffsetToCSSOffset(offset):
            return pointToCSSOffset(svgOffsetToPoint(offset))

        gradient = "(%.1fdeg" % deg
        color_stops = []
        for stop in stops:
            color = svg.Color(stop.style["stop-color"])
            if float(stop.style.get("stop-opacity", "1")) <= 0.999:
                color.a = float(stop.style.get("stop-opacity", "1"))
            gradient += ",%s %.1f%%" % (
                color, svgOffsetToCSSOffset(stop.offset) * 100)

        gradient += ")"
        background.append("linear-gradient" + gradient)
        background.append("-o-linear-gradient" + gradient)
        background.append("-moz-linear-gradient" + gradient)
        background.append("-ms-linear-gradient" + gradient)
        background.append("-webkit-linear-gradient" + gradient)

        #webkit
        webkit = "-webkit-gradient(linear,%f %f,%f %f," % (
            point1.x.px(), point1.y.px(), point2.x.px(), point2.y.px())
        color = svg.Color(stops[0].style["stop-color"])
        if float(stops[0].style.get("stop-opacity", "1")) <= 0.999:
            color.a = float(stops[0].style.get("stop-opacity", "1"))
        webkit += "from(%s)," % color
        if len(stops) > 2:
            for stop in stops[1:-1]:
                color = svg.Color(stop.style["stop-color"])
                if float(stop.style.get("stop-opacity", "1")) <= 0.999:
                    color.a = float(stop.style.get("stop-opacity", "1"))
                webkit += "color-stop(%f,%s)," % (stop.offset, color)
        color = svg.Color(stops[-1].style["stop-color"])
        if float(stops[-1].style.get("stop-opacity", "1")) <= 0.999:
            color.a = float(stops[-1].style.get("stop-opacity", "1"))
        webkit += "to(%s))" % color
        background.append(webkit)

        self["background"] = background
예제 #5
0
    def text(self, x):
        name = self.newName(x)

        if name in self.__clipnames:
            clipname = self.__clipnames[name]
            self._html('<div class="%s"><div class="%sinverse">\n' %
                       (clipname, clipname))

        blur = 0
        filterURL = getURL(x.style.get("filter", ""))
        if filterURL:
            filter = x.getRoot().getElementById(filterURL)
            if filter and isinstance(filter[0], svg.FEGaussianBlur):
                blur = filter[0].stdDeviation * 1.7

        self._html('<div class="%s"><span class="svg-text-adj">&nbsp;</span>' %
                   name)
        for a in x:
            if isinstance(a, svg.TSpan):
                self.__text_contents(a, x.x, x.y, blur)
            elif isinstance(a, svg.Characters):
                self._html(a.content)
        self._html('</div>\n')

        if name in self.__clipnames:
            clipname = self.__clipnames[name]
            self._html('</div></div>\n')

        #スタイル定義を出力
        if name not in self._css_classes:
            self._css_classes.add(name)
            css = CSSStyle()

            #クリップパスの設定
            self.__clipPath(name, x)

            css["position"] = "absolute"
            css["margin"] = "0px"

            #フォントに関する属性をコピー
            if "font-size" in x.style:
                css["font-size"] = svg.Length(x.style["font-size"])
            if "fill" in x.style:
                css["color"] = svg.Color(x.style["fill"])
                if "fill-opacity" in x.style:
                    css["color"].a = float(x.style["fill-opacity"])
                if blur > 0.001:
                    css["text-shadow"] = "0px 0px %s %s" % (blur, css["color"])
                    css["color"] = [css["color"], svg.Color(0, 0, 0, 0)]

            for stylename in ["font-style", "font-weight", "font-family"]:
                if stylename in x.style:
                    css[stylename] = x.style[stylename]
            css["left"] = x.x
            css["top"] = x.y - svg.Length("1000px")

            #変形
            if x.transform:
                transform = x.transform.toMatrix()
                css["transform"] = transform

            css["white-space"] = "pre"

            #出力
            self._css(cls=name, style=css)

        if "svg-text-adj" not in self._css_classes:
            self._css_classes.add("svg-text-adj")
            self._css(".svg-text-adj{font-size:0px;vertical-align: 1000px;}\n")
예제 #6
0
    def __blured_round_rect(self,
                            element,
                            x,
                            y,
                            width,
                            height,
                            rx=0,
                            ry=0,
                            blur=0):
        name = self.newName(element)
        namefill = name + "-fill"
        namestroke = name + "-stroke"
        hasfill = "fill" in element.style and element.style["fill"] != 'none'
        hasstroke = "stroke" in element.style and element.style[
            "stroke"] != 'none'

        #フィルの描画
        if not hasstroke and hasfill:
            if namefill not in self._css_classes:
                self._css_classes.add(namefill)
                css = CSSStyle()

                #クリップパスの設定
                self.__clipPath(namefill, element)

                #位置と大きさの設定
                css["position"] = "absolute"
                css["left"] = x - 10000
                css["top"] = y - 10000
                css["width"] = width
                css["height"] = height

                #角を丸める
                if rx and ry:
                    css["border-radius"] = "%s/%s" % (rx, ry)
                elif rx:
                    css["border-radius"] = rx
                elif ry:
                    css["border-radius"] = ry

                #フィルを指定する
                css.addFill(element)

                #ぼかしを適用
                css["box-shadow"] = "10000px 10000px %s %s" % (
                    blur, css["background-color"])
                css["-webkit-box-shadow"] = "10000px 10000px %s %s" % (
                    blur * 1.8, css["background-color"])
                css["-o-box-shadow"] = "10000px 10000px %s %s" % (
                    blur * 1.8, css["background-color"])

                #変形
                if element.transform:
                    #CSSとSVGの原点の違いを補正
                    transform = element.transform.toMatrix()
                    transform = transform * svg.Transform.Translate(
                        x - 10000 + width / 2, y - 10000 + height / 2)
                    transform = svg.Transform.Translate(
                        -x + 10000 - width / 2,
                        -y + 10000 - height / 2) * transform
                    css["left"] += transform.e
                    css["top"] += transform.f
                    transform.e = 0
                    transform.f = 0
                    css["transform"] = transform

                    #透明度を指定
                if "opacity" in element.style:
                    css["opacity"] = element.style["opacity"]

                #出力
                self._css(cls=namefill, style=css)

            #クリップの設定
            if namefill in self.__clipnames:
                clipname = self.__clipnames[namefill]
                self._html(
                    '<div class="%s"><div class="%sinverse"><div class="%s"></div></div></div>\n'
                    % (clipname, clipname, name))
                return

            self._html('<div class="%s"></div>\n' % namefill)

        #ストロークの描画
        if hasstroke:
            if namestroke not in self._css_classes:
                self._css_classes.add(namestroke)
                css = CSSStyle()

                #クリップパスの設定
                self.__clipPath(namestroke, element)

                #位置と大きさの設定
                css["position"] = "absolute"
                css["left"] = x
                css["top"] = y
                css["width"] = width
                css["height"] = height

                #角を丸める
                if rx and ry:
                    css["border-radius"] = "%s/%s" % (str(rx), str(ry))
                elif rx:
                    css["border-radius"] = rx
                elif ry:
                    css["border-radius"] = ry

                #ぼかしを適用
                stroke = svg.Length(element.style.get("stroke-width", 0))
                color = svg.Color(element.style["stroke"])
                if "stroke-opacity" in element.style:
                    color.a = float(element.style["stroke-opacity"])
                css["box-shadow"] = "0px 0px %s %s %s" % (
                    blur, stroke / 2, color) + ", 0px 0px %s %s %s inset" % (
                        blur, stroke / 2, color)

                #フィルを指定する
                css.addFill(element)

                #変形
                if element.transform:
                    #CSSとSVGの原点の違いを補正
                    transform = element.transform.toMatrix()
                    transform = transform * svg.Transform.Translate(
                        x + width / 2, y + height / 2)
                    transform = svg.Transform.Translate(
                        -x - width / 2, -y - height / 2) * transform
                    css["left"] += transform.e
                    css["top"] += transform.f
                    transform.e = 0
                    transform.f = 0
                    css["transform"] = transform

                #透明度を指定
                if "opacity" in element.style:
                    css["opacity"] = element.style["opacity"]

                #出力
                self._css(cls=namestroke, style=css)

            #クリップの設定
            if namestroke in self.__clipnames:
                namestroke = self.__clipnames[name]
                self._html(
                    '<div class="%s"><div class="%sinverse"><div class="%s"></div></div></div>\n'
                    % (clipname, clipname, name))
                return

            self._html('<div class="%s"></div>\n' % namestroke)
예제 #7
0
    def __round_rect(self, element, x, y, width, height, rx=0, ry=0):
        blur = 0
        filterURL = getURL(element.style.get("filter", ""))
        if filterURL:
            filter = element.getRoot().getElementById(filterURL)
            if filter and isinstance(filter[0], svg.FEGaussianBlur):
                blur = filter[0].stdDeviation * 1.7
                try:
                    self.__blured_round_rect(element, x, y, width, height, rx,
                                             ry, blur)
                    return
                except:
                    pass

        name = self.newName(element)
        if name not in self._css_classes:
            self._css_classes.add(name)
            css = CSSStyle()
            stroke = svg.Length(0)

            #クリップパスの設定
            self.__clipPath(name, element)

            #ストロークの描画
            if "stroke" in element.style and element.style["stroke"] != 'none':
                try:
                    stroke = svg.Length(element.style.get("stroke-width", 0))
                    css["border-width"] = stroke
                    css["border-style"] = "solid"
                    color = svg.Color(element.style["stroke"])
                    if "stroke-opacity" in element.style:
                        color.a = float(element.style["stroke-opacity"])
                    css["border-color"] = color
                except:
                    pass

            #位置と大きさの設定
            css["position"] = "absolute"
            css["left"] = x - stroke / 2
            css["top"] = y - stroke / 2
            css["width"] = width - stroke
            css["height"] = height - stroke

            #角を丸める
            if rx and ry:
                css["border-radius"] = "%s/%s" % (str(rx + stroke / 2),
                                                  str(ry + stroke / 2))
            elif rx:
                css["border-radius"] = rx + stroke / 2
            elif ry:
                css["border-radius"] = ry + stroke / 2

            #フィルを指定する
            css.addFill(element)

            #変形
            if element.transform:
                #CSSとSVGの原点の違いを補正
                transform = element.transform.toMatrix()
                transform = transform * svg.Transform.Translate(
                    x + width / 2, y + height / 2)
                transform = svg.Transform.Translate(
                    -x - width / 2, -y - height / 2) * transform
                css["left"] += transform.e
                css["top"] += transform.f
                transform.e = 0
                transform.f = 0
                css["transform"] = transform

            #透明度を指定
            if "opacity" in element.style:
                css["opacity"] = element.style["opacity"]

            #出力
            self._css(cls=name, style=css)

        #クリップの設定
        if name in self.__clipnames:
            clipname = self.__clipnames[name]
            self._html(
                '<div class="%s"><div class="%sinverse"><div class="%s"></div></div></div>\n'
                % (clipname, clipname, name))
            return

        self._html('<div class="%s"></div>\n' % name)