Exemplo n.º 1
0
 def _plotTextOverlayTokenCountTable(self, theSvg, theDatumL, theTpt):
     """Plots the token count table as text+alternate text."""
     assert (not self.isRoot)
     self.commentFunctionBegin(theSvg, File=self._fileName)
     myDatumL = self._bb.plotPointSelf(theDatumL)
     # Move to center
     myDatumL = Coord.newPt(
         myDatumL,
         incX=self._bb.width,  #.scale(0.5),
         incY=None)
     #                 incY=self._bb.depth.scale(0.5))
     triggerBoxL = self._bb.box
     if self.__mustPlotSelfHistogram():
         myDatumL = Coord.newPt(myDatumL, None, self.HIST_DEPTH)
         triggerBoxL = Coord.Box(triggerBoxL.width,
                                 triggerBoxL.depth - self.HIST_DEPTH)
         if self.__mustPlotChildHistogram():
             myDatumL = Coord.newPt(myDatumL, None, self.HIST_DEPTH)
             triggerBoxL = Coord.Box(triggerBoxL.width,
                                     triggerBoxL.depth - self.HIST_DEPTH)
     myDatumP = theTpt.pt(myDatumL)
     altTextS = self._altTextsForTokenCount()
     self.writeAltTextAndMouseOverRect(
         theSvg,
         theSvg.id,
         myDatumP,
         altTextS,
         myDatumP,
         theTpt.boxP(triggerBoxL),
     )
     self.commentFunctionEnd(theSvg, File=self._fileName)
Exemplo n.º 2
0
    def test_07(self):
        """TestSVGlWriter.test_07(): text.
        Based on http://www.w3.org/TR/2003/REC-SVG11-20030114/text.html#TextElement"""
        myF = io.StringIO()
        myViewPort = Coord.Box(
            Coord.Dim(12, 'cm'),
            Coord.Dim(4, 'cm'),
        )
        with SVGWriter.SVGWriter(myF, myViewPort,
                                 {'viewBox': "0 0 1000 300"}) as xS:
            with XmlWrite.Element(xS, 'desc'):
                xS.characters("Example text01 - 'Hello, out there' in blue")
            myPt = Coord.Pt(Coord.baseUnitsDim(250), Coord.baseUnitsDim(150))
            with SVGWriter.SVGText(xS, myPt, "Verdans", 55, {'fill': "blue"}):
                xS.characters('Hello, out there')
            #xS.comment(" Show outline of canvas using 'rect' element ")
            myPt = Coord.Pt(Coord.baseUnitsDim(1), Coord.baseUnitsDim(1))
            myBx = Coord.Box(Coord.baseUnitsDim(998), Coord.baseUnitsDim(298))
            with SVGWriter.SVGRect(xS, myPt, myBx, {
                    'fill': "none",
                    'stroke': "blue",
                    'stroke-width': "2"
            }):
                pass
        #print
        #print myF.getvalue()
        self.assertEqual(
            myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="4.00cm" version="1.1" viewBox="0 0 1000 300" width="12.00cm" xmlns="http://www.w3.org/2000/svg">
  <desc>Example text01 - &apos;Hello, out there&apos; in blue</desc>
  <text fill="blue" font-family="Verdans" font-size="55" x="250px" y="150px">Hello, out there</text>
  <rect fill="none" height="298px" stroke="blue" stroke-width="2" width="998px" x="1px" y="1px" />
</svg>
""")
Exemplo n.º 3
0
 def setUp(self):
     self._canvas = Coord.Box(
         Coord.Dim(300, None),
         Coord.Dim(500, None),
     )
     self._box = Coord.Box(
         Coord.Dim(80, None),
         Coord.Dim(20, None),
     )
Exemplo n.º 4
0
    def test_06(self):
        """TestSVGlWriter.test_06(): a polygon.
        Based on http://www.w3.org/TR/2003/REC-SVG11-20030114/shapes.html#PolygonElement"""
        myF = io.StringIO()
        myViewPort = Coord.Box(
            Coord.Dim(12, 'cm'),
            Coord.Dim(4, 'cm'),
        )
        with SVGWriter.SVGWriter(myF, myViewPort,
                                 {'viewBox': "0 0 1200 400"}) as xS:
            with XmlWrite.Element(xS, 'desc'):
                xS.characters(
                    'Example line01 - lines expressed in user coordinates')
            #xS.comment(" Show outline of canvas using 'rect' element ")
            myPt = Coord.Pt(Coord.baseUnitsDim(1), Coord.baseUnitsDim(1))
            myBx = Coord.Box(Coord.baseUnitsDim(1198), Coord.baseUnitsDim(398))
            with SVGWriter.SVGRect(xS, myPt, myBx, {
                    'fill': "none",
                    'stroke': "blue",
                    'stroke-width': "2"
            }):
                pass
            # Make a group
            with SVGWriter.SVGPolygon(xS, [
                    Coord.Pt(Coord.baseUnitsDim(350), Coord.baseUnitsDim(75)),
                    Coord.Pt(Coord.baseUnitsDim(379), Coord.baseUnitsDim(161)),
                    Coord.Pt(Coord.baseUnitsDim(469), Coord.baseUnitsDim(161)),
                    Coord.Pt(Coord.baseUnitsDim(397), Coord.baseUnitsDim(215)),
                    Coord.Pt(Coord.baseUnitsDim(423), Coord.baseUnitsDim(301)),
                    Coord.Pt(Coord.baseUnitsDim(350), Coord.baseUnitsDim(250)),
                    Coord.Pt(Coord.baseUnitsDim(277), Coord.baseUnitsDim(301)),
                    Coord.Pt(Coord.baseUnitsDim(303), Coord.baseUnitsDim(215)),
                    Coord.Pt(Coord.baseUnitsDim(231), Coord.baseUnitsDim(161)),
                    Coord.Pt(Coord.baseUnitsDim(321), Coord.baseUnitsDim(161)),
            ], {
                    'fill': 'red',
                    'stroke': 'blue',
                    'stroke-width': "10"
            }):
                pass
        #print
        #print myF.getvalue()
        self.assertEqual(
            myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="4.00cm" version="1.1" viewBox="0 0 1200 400" width="12.00cm" xmlns="http://www.w3.org/2000/svg">
  <desc>Example line01 - lines expressed in user coordinates</desc>
  <rect fill="none" height="398px" stroke="blue" stroke-width="2" width="1198px" x="1px" y="1px" />
  <polygon fill="red" points="350,75 379,161 469,161 397,215 423,301 350,250 277,301 303,215 231,161 321,161" stroke="blue" stroke-width="10" />
</svg>
""")
Exemplo n.º 5
0
 def _plotHistogram(self, theSvg, theHistDl, theTpt, theTokCounter):
     myTokCountTotal = theTokCounter.totalAllUnconditional
     # Avoid divide by zero errors
     assert (theTokCounter.tokenCountNonWs(isAll=False) > 0)
     assert (myTokCountTotal > 0)
     #myPos = Coord.Dim(0, self.COMMON_UNITS)
     myHistDl = theHistDl  #self._bb.plotPointSelf(theDl)
     for k, myFill in self.HIST_PP_TOKEN_TYPES_COLOURS:
         tCount = theTokCounter.tokenCount(k, isAll=False)
         if tCount > 0:
             myWidth = self._bb.width.scale(tCount /
                                            (1.0 * myTokCountTotal))
             myBox = Coord.Box(myWidth, self.HIST_DEPTH)
             # Convert to physical and plot
             with SVGWriter.SVGRect(
                     theSvg,
                     theTpt.boxDatumP(myHistDl, myBox),
                     theTpt.boxP(myBox),
                 {
                     'fill': myFill,
                     'stroke': self.HIST_RECT_COLOUR_STROKE,
                     'stroke-width': self.HIST_RECT_STROKE_WIDTH,
                 },
             ):
                 pass
             # Increment the datum
             myHistDl = Coord.newPt(myHistDl, incX=myWidth, incY=None)
Exemplo n.º 6
0
 def _plotFileNameStackPopup(self, theSvg, theDatumL, theTpt, idStack):
     """Writes out the file name at the top with a pop-up with the
     absolute path."""
     self.commentFunctionBegin(theSvg, File=self._fileName)
     if self._bb.hasSetArea:
         textPointP = self._fileNamePoint(theDatumL, theTpt)
         assert textPointP is not None
         # Make the trigger box 14 points high to cover the 12 pt text and
         # 12pts per char in the
         triggerBoxP = Coord.Box(
             Coord.baseUnitsDim(12 * len(os.path.basename(self.nodeName))),
             Coord.baseUnitsDim(14))
         triggerPointP = Coord.newPt(
             textPointP,
             triggerBoxP.width.scale(-0.5),
             triggerBoxP.depth.scale(-0.5),
         )
         self.writeAltTextAndMouseOverRect(
             theSvg,
             theSvg.id,
             textPointP,
             self._fileIdStackToListOfStr(idStack),
             triggerPointP,
             triggerBoxP,
         )
     self.commentFunctionEnd(theSvg, File=self._fileName)
Exemplo n.º 7
0
 def setUp(self):
     self._pnbcObj = PlotNode.PlotNodeBboxBoxy()
     self._pnbcObj.width = Coord.Dim(12, 'mm')
     self._pnbcObj.depth = Coord.Dim(8, 'mm')
     #print '\nTRACE self._pnbcObj', self._pnbcObj
     self._pnbcObj.bbSelfPadding = Coord.Pad(
         Coord.Dim(1, 'mm'),  # prev
         Coord.Dim(3, 'mm'),  # next
         Coord.Dim(5, 'mm'),  # parent
         Coord.Dim(7, 'mm'),  # child
     )
     self._pnbcObj.bbSpaceChildren = Coord.Dim(16, 'mm')
     self.assertEqual(True, self._pnbcObj.bbChildrenWidth is None)
     self.assertEqual(True, self._pnbcObj.bbChildrenDepth is None)
     self.assertEqual(0, self._pnbcObj.numChildren)
     self._pnbcObj.extendChildBbox(
         Coord.Box(
             Coord.Dim(15, 'mm'),
             Coord.Dim(7, 'mm'),
         ))
     # Child box now w:15, d:7
     self.assertEqual(1, self._pnbcObj.numChildren)
     self.assertEqual(self._pnbcObj.bbChildrenWidth, Coord.Dim(15, 'mm'))
     self.assertEqual(self._pnbcObj.bbChildrenDepth, Coord.Dim(7, 'mm'))
     self._pnbcObj.extendChildBbox(
         Coord.Box(
             Coord.Dim(31, 'mm'),
             Coord.Dim(29, 'mm'),
         ))
     # Child box now w:15+31=46, d:max(7,29)=29
     self.assertEqual(2, self._pnbcObj.numChildren)
     self.assertEqual(self._pnbcObj.bbChildrenWidth, Coord.Dim(46, 'mm'))
     self.assertEqual(self._pnbcObj.bbChildrenDepth, Coord.Dim(29, 'mm'))
     self._pnbcObj.extendChildBbox(
         Coord.Box(
             Coord.Dim(11, 'mm'),
             Coord.Dim(9, 'mm'),
         ))
     # Child box now w:46+11=57, d:max(29,9)=29
     self.assertEqual(3, self._pnbcObj.numChildren)
     self.assertEqual(self._pnbcObj.bbChildrenWidth, Coord.Dim(57, 'mm'))
     self.assertEqual(self._pnbcObj.bbChildrenDepth, Coord.Dim(29, 'mm'))
     # Logical datum
     self._logicalDatum = Coord.Pt(
         Coord.Dim(21, 'mm'),
         Coord.Dim(180, 'mm'),
     )
Exemplo n.º 8
0
 def testSigma_03(self):
     """Tests PlotNode() get sigma width and depth (parent is null node)."""
     myObj = PlotNode.PlotNodeBbox()
     myObj.width = None
     self.assertEqual(myObj.width, None)
     myObj.depth = None
     self.assertEqual(myObj.depth, None)
     myPad = Coord.Pad(
         Coord.Dim(0.5, 'in'),  # prev
         Coord.Dim(0.5, 'in'),  # next
         Coord.Dim(0.5, 'in'),  # parent
         Coord.Dim(0.5, 'in'),  # child
     )
     myObj.bbSelfPadding = myPad
     myObj.bbSpaceChildren = Coord.Dim(0.5, 'in')
     self.assertEqual(myObj.bbSpaceChildren, Coord.Dim(0.5, 'in'))
     myObj.bbChildren = Coord.Box(
         Coord.Dim(4, 'in'),
         Coord.Dim(2.5, 'in'),
     )
     self.assertEqual(
         myObj.bbChildrenWidth,
         Coord.Dim(4, 'in'),
     )
     self.assertEqual(
         myObj.bbChildrenDepth,
         Coord.Dim(2.5, 'in'),
     )
     self.assertEqual(myObj.bbChildren,
                      Coord.Box(
                          Coord.Dim(4, 'in'),
                          Coord.Dim(2.5, 'in'),
                      ))
     self.assertEqual(
         myObj.bbSigmaWidth,
         Coord.Dim(4.0, 'in'),
     )
     self.assertEqual(
         myObj.bbSigmaDepth,
         Coord.Dim(2.5, 'in'),
     )
     self.assertEqual(
         myObj.bbSigma,
         Coord.Box(
             Coord.Dim(4.0, 'in'),
             Coord.Dim(2.5, 'in'),
         ))
Exemplo n.º 9
0
    def writeAltTextAndMouseOverRect(self, theSvg, theId, theAltPt, theAltS,
                                     theTrigPt, theTrigRect):
        """Composes and writes the (pop-up) alternate text.
        Also writes a trigger rectangle."""
        # Write a grouping element and give it the alternate ID
        with SVGWriter.SVGGroup(theSvg, {
                'id': 't%s%s' % (theId, self.ALT_ID_SUFFIX),
                'opacity': '0.0'
        }):
            altFontSize = self.ALT_FONT_PROPERTIES[
                self.ALT_FONT_FAMILY]['size']
            altFontLenFactor = self.ALT_FONT_PROPERTIES[
                self.ALT_FONT_FAMILY]['lenFactor']
            altFontHeightFactor = self.ALT_FONT_PROPERTIES[
                self.ALT_FONT_FAMILY]['heightFactor']
            # Compute masking box for alternate
            maxChars = max([len(s) for s in theAltS])
            # Take around 80% of character length
            boxWidth = Coord.Dim(altFontSize * maxChars * altFontLenFactor,
                                 'pt')
            if len(theAltS) < 2:
                boxHeight = Coord.Dim(altFontSize * 2, 'pt')
            else:
                boxHeight = Coord.Dim(
                    altFontSize * len(theAltS) * altFontHeightFactor, 'pt')

            boxAttrs = {'fill': self.ALT_RECT_FILL}
            with SVGWriter.SVGRect(
                    theSvg,
                    theAltPt,
                    Coord.Box(boxWidth, boxHeight),
                    boxAttrs,
            ):
                pass
            # As the main text is centered and the alt text is left
            # justified we need to move the text plot point left by a bit.
            myAltTextPt = Coord.newPt(
                theAltPt,
                incX=Coord.Dim(1 * altFontSize * 3 * altFontLenFactor / 2.0,
                               'pt'),
                incY=Coord.Dim(12, 'pt'),
            )
            with SVGWriter.SVGText(theSvg, myAltTextPt, 'Courier', altFontSize,
                                   {
                                       'font-weight': "normal",
                                   }):
                self._writeStringListToTspan(theSvg, myAltTextPt, theAltS)
        # Add the trigger rectangle for writing on finalise
        boxAttrs = {
            'class' : self.CLASS_RECT_INVIS,
            'id'                : 't%s' % theId,
            'onmouseover'       : "swapOpacity('t%s', 't%s')" \
                        % (theId, theId+self.ALT_ID_SUFFIX),
            'onmouseout'        : "swapOpacity('t%s', 't%s')" \
                        % (theId, theId+self.ALT_ID_SUFFIX),
        }
        self._triggerS.append((theTrigPt, theTrigRect, boxAttrs))
Exemplo n.º 10
0
 def setUp(self):
     self._canvas = Coord.Box(
         Coord.Dim(300, None),
         Coord.Dim(500, None),
     )
     self._pt = Coord.Pt(
         Coord.Dim(17, None),
         Coord.Dim(29, None),
     )
Exemplo n.º 11
0
 def testIncWD_right(self):
     """TestTreePlotTransformBoxP.boxP(): right."""
     myObj = TreePlotTransform.TreePlotTransform(self._canvas,
                                                 rootPos='right')
     self.assertEqual(
         myObj.boxP(self._box),
         Coord.Box(
             Coord.Dim(20, None),
             Coord.Dim(80, None),
         ),
     )
Exemplo n.º 12
0
 def testBbChildren(self):
     """Tests PlotNode() set/get bbChildren."""
     myObj = PlotNode.PlotNodeBbox()
     myObj.bbChildren = Coord.Box(
         Coord.Dim(1, 'px'),
         Coord.Dim(2, 'px'),
     )
     self.assertEqual(myObj.bbChildren,
                      Coord.Box(
                          Coord.Dim(1, 'px'),
                          Coord.Dim(2, 'px'),
                      ))
     self.assertEqual(
         myObj.bbChildrenWidth,
         Coord.Dim(1, 'px'),
     )
     self.assertEqual(
         myObj.bbChildrenDepth,
         Coord.Dim(2, 'px'),
     )
Exemplo n.º 13
0
    def test_02(self):
        """TestSVGlWriter.test_02(): a circle.
        From http://www.w3.org/TR/2003/REC-SVG11-20030114/shapes.html#CircleElement"""
        myF = io.StringIO()
        myViewPort = Coord.Box(
            Coord.Dim(12, 'cm'),
            Coord.Dim(4, 'cm'),
        )
        with SVGWriter.SVGWriter(myF, myViewPort) as xS:
            with XmlWrite.Element(xS, 'desc'):
                xS.characters(
                    'Example circle01 - circle filled with red and stroked with blue'
                )
            #xS.comment(" Show outline of canvas using 'rect' element ")
            myPt = Coord.Pt(Coord.baseUnitsDim(1), Coord.baseUnitsDim(1))
            myBx = Coord.Box(Coord.baseUnitsDim(1198), Coord.baseUnitsDim(398))
            with SVGWriter.SVGRect(xS, myPt, myBx, {
                    'fill': "none",
                    'stroke': "blue",
                    'stroke-width': "2"
            }):
                pass
            myPt = Coord.Pt(Coord.baseUnitsDim(600), Coord.baseUnitsDim(200))
            myRad = Coord.baseUnitsDim(100)
            with SVGWriter.SVGCircle(xS, myPt, myRad, {
                    'fill': "red",
                    'stroke': "blue",
                    'stroke-width': "10"
            }):
                pass
        #print
        #print myF.getvalue()
        self.assertEqual(
            myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="4.00cm" version="1.1" width="12.00cm" xmlns="http://www.w3.org/2000/svg">
  <desc>Example circle01 - circle filled with red and stroked with blue</desc>
  <rect fill="none" height="398px" stroke="blue" stroke-width="2" width="1198px" x="1px" y="1px" />
  <circle cx="600px" cy="200px" fill="red" r="100px" stroke="blue" stroke-width="10" />
</svg>
""")
Exemplo n.º 14
0
 def testCanvasP_left(self):
     """TestTreePlotTransformCanvas.canvasP(): left."""
     myO = TreePlotTransform.TreePlotTransform(self._boxDefault,
                                               rootPos='left')
     expValue = Coord.Box(
         Coord.Dim(500, None),
         Coord.Dim(300, None),
     )
     self.assertEqual(
         myO.canvasP(),
         expValue,
     )
Exemplo n.º 15
0
 def setUp(self):
     self._canvas = Coord.Box(
         Coord.Dim(300, None),
         Coord.Dim(800, None),
     )
     self._pt = Coord.Pt(
         Coord.Dim(400, None),
         Coord.Dim(250, None),
     )
     self._childIncS = [
         Coord.Dim(36, None),
         Coord.Dim(101, None),
         Coord.Dim(74, None),
     ]
Exemplo n.º 16
0
    def test_00(self):
        """TestSVGWriter.test_00(): construction."""
        myF = io.StringIO()
        myViewPort = Coord.Box(
            Coord.Dim(100, 'mm'),
            Coord.Dim(20, 'mm'),
        )
        with SVGWriter.SVGWriter(myF, myViewPort):
            pass
        #print
        #print myF.getvalue()
        self.assertEqual(
            myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="20.0mm" version="1.1" width="100.0mm" xmlns="http://www.w3.org/2000/svg" />\n"""
        )
Exemplo n.º 17
0
    def test_01(self):
        """TestSVGlWriter.test_01(): <desc> and four rectangles.
        From second example in http://www.w3.org/TR/2003/REC-SVG11-20030114/struct.html#NewDocumentOverview"""
        myF = io.StringIO()
        myViewPort = Coord.Box(
            Coord.Dim(5, 'cm'),
            Coord.Dim(4, 'cm'),
        )
        with SVGWriter.SVGWriter(myF, myViewPort) as xS:
            with XmlWrite.Element(xS, 'desc'):
                xS.characters('Four separate rectangles')
            myPt = Coord.Pt(Coord.Dim(0.5, 'cm'), Coord.Dim(0.5, 'cm'))
            myBx = Coord.Box(Coord.Dim(2.0, 'cm'), Coord.Dim(1.0, 'cm'))
            with SVGWriter.SVGRect(xS, myPt, myBx):
                pass
            myPt = Coord.Pt(Coord.Dim(0.5, 'cm'), Coord.Dim(2.0, 'cm'))
            myBx = Coord.Box(Coord.Dim(1.0, 'cm'), Coord.Dim(1.5, 'cm'))
            with SVGWriter.SVGRect(xS, myPt, myBx):
                pass
            myPt = Coord.Pt(Coord.Dim(3.0, 'cm'), Coord.Dim(0.5, 'cm'))
            myBx = Coord.Box(Coord.Dim(1.5, 'cm'), Coord.Dim(2.0, 'cm'))
            with SVGWriter.SVGRect(xS, myPt, myBx):
                pass
            myPt = Coord.Pt(Coord.Dim(3.5, 'cm'), Coord.Dim(3.0, 'cm'))
            myBx = Coord.Box(Coord.Dim(1.0, 'cm'), Coord.Dim(0.5, 'cm'))
            with SVGWriter.SVGRect(xS, myPt, myBx):
                pass
            myPt = Coord.Pt(Coord.Dim(0.01, 'cm'), Coord.Dim(0.01, 'cm'))
            myBx = Coord.Box(Coord.Dim(4.98, 'cm'), Coord.Dim(3.98, 'cm'))
            with SVGWriter.SVGRect(xS,
                                   myPt,
                                   myBx,
                                   attrs={
                                       'fill': "none",
                                       'stroke': "blue",
                                       'stroke-width': ".02cm",
                                   }):
                pass
        #print
        #print myF.getvalue()
        self.assertEqual(
            myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="4.00cm" version="1.1" width="5.00cm" xmlns="http://www.w3.org/2000/svg">
  <desc>Four separate rectangles</desc>
  <rect height="1.00cm" width="2.00cm" x="0.50cm" y="0.50cm" />
  <rect height="1.50cm" width="1.00cm" x="0.50cm" y="2.00cm" />
  <rect height="2.00cm" width="1.50cm" x="3.00cm" y="0.50cm" />
  <rect height="0.50cm" width="1.00cm" x="3.50cm" y="3.00cm" />
  <rect fill="none" height="3.98cm" stroke="blue" stroke-width=".02cm" width="4.98cm" x="0.01cm" y="0.01cm" />
</svg>
""")
Exemplo n.º 18
0
 def _plotTextOverlayHistogram(self, theSvg, theHistDl, theTpt):
     """Plot the text associated with a histogram."""
     myCentreL = Coord.newPt(theHistDl, self._bb.width.scale(0.5),
                             self.HIST_DEPTH.scale(0.5))
     myPointP = theTpt.pt(myCentreL)
     # TODO: The myPointP.x.value + 2, myPointP.y.value - 2
     # looks wrong. It is not using theTpt.
     myAttrs = {
           'class'       : self.CLASS_RECT_INVIS,
         'onmouseover'       : "showHistogram(%s, %s)" \
             % (myPointP.x.value + 3, myPointP.y.value + 2),
         'onmouseout'    : "hideHistogram()",
     }
     myWidth = self._bb.width
     myBox = Coord.Box(myWidth, self.HIST_DEPTH)
     with SVGWriter.SVGRect(theSvg, theTpt.boxDatumP(theHistDl, myBox),
                            theTpt.boxP(myBox), myAttrs):
         pass
Exemplo n.º 19
0
 def _writeAlternateText(self, theSvg, thePoint, theId, theText, theAltS, yOffs=Coord.Dim(0, 'pt')):
     """Composes and writes the (pop-up) alternate text.
     thePoint is the physical point to locate both texts."""
     # Write a grouping element and give it the alternate ID
     with SVGWriter.SVGGroup(theSvg, {'id' : 't%s%s' % (theId, self.ALT_ID_SUFFIX), 'opacity' : '0.0'}):
         altFontSize = self.ALT_FONT_PROPERTIES[self.ALT_FONT_FAMILY]['size']
         altFontLenFactor = self.ALT_FONT_PROPERTIES[self.ALT_FONT_FAMILY]['lenFactor']
         altFontHeightFactor = self.ALT_FONT_PROPERTIES[self.ALT_FONT_FAMILY]['heightFactor']
         # Compute masking box for alternate
         maxChars = max([len(s) for s in theAltS])
         # Take around 80% of character length
         boxWidth = Coord.Dim(altFontSize * maxChars * altFontLenFactor, 'pt')
         if len(theAltS) < 2:
             boxHeight = Coord.Dim(altFontSize * 2, 'pt')
         else:
             boxHeight = Coord.Dim(altFontSize * len(theAltS) * altFontHeightFactor, 'pt')
              
         boxAttrs = { 'fill' : self.ALT_RECT_FILL }
         with SVGWriter.SVGRect(
                 theSvg,
                 # Edge the plot point up and left by a bit
                 Coord.newPt(
                     thePoint,
                     incX=Coord.Dim(-1 * altFontSize * (1 + len(theText) * altFontLenFactor / 2.0), 'pt'),
                     incY=Coord.Dim(-1*altFontHeightFactor * altFontSize, 'pt') + yOffs,
                 ),
                 Coord.Box(boxWidth, boxHeight),
                 boxAttrs,
             ):
             pass
         # As the main text is centered and the alt text is left
         # justified we need to move the text plot point left by a bit.
         myAltTextPt = Coord.newPt(
             thePoint,
             incX=Coord.Dim(-1 * altFontSize * len(theText) * altFontLenFactor / 2.0, 'pt'),
             incY=yOffs,
         )
         with SVGWriter.SVGText(theSvg, myAltTextPt, 'Courier', altFontSize,
                     {
                         'font-weight'       : "normal",
                     }
                 ):
             self._writeStringListToTspan(theSvg, myAltTextPt, theAltS)
Exemplo n.º 20
0
def processIncGraphToSvg(theLex, theFilePath, theClass, tptPos, tptSweep):
    """Convert a Include graph from a PpLexer to SVG in theFilePath."""
    myVis = FileIncludeGraph.FigVisitorTree(theClass)
    theLex.fileIncludeGraphRoot.acceptVisitor(myVis)
    # Tree is now a graph of: theClass
    myIgs = myVis.tree()
    # Pad the canvass
    myWidth = CANVAS_PADDING.prev \
                + myIgs.plotCanvas.width \
                + CANVAS_PADDING.next
    myDepth = CANVAS_PADDING.parent \
                + myIgs.plotCanvas.depth \
                + CANVAS_PADDING.child
    # Round up
    myWidth = Coord.Dim(int(myWidth.value+0.5), myWidth.units)
    myDepth = Coord.Dim(int(myDepth.value+0.5), myDepth.units)
    myCanvas = Coord.Box(myWidth, myDepth)
    #Create a plot configuration
    myTpt = TreePlotTransform.TreePlotTransform(myCanvas, tptPos, tptSweep)
    # Write to file
    myIgs.plotToFilePath(theFilePath, myTpt)
Exemplo n.º 21
0
 def _plotHistogramLegend(self, theSvg, theTpt):
     """Plot a standardised legend. This is plotted as a group within a defs."""
     myDatumP = Coord.Pt(
         Coord.Dim(0.0, self.COMMON_UNITS),
         Coord.Dim(0.0, self.COMMON_UNITS),
     )
     with SVGWriter.SVGGroup(theSvg, {
             'id': self.HIST_LEGEND_ID,
             'opacity': '0.0'
     }):
         idVal = 0
         # Outline rectangle
         with SVGWriter.SVGRect(
                 theSvg,
                 myDatumP,
                 Coord.Box(
                     Coord.Dim(48.0, self.COMMON_UNITS),
                     Coord.Dim(40.0, self.COMMON_UNITS),
                 ),
             {
                 'fill': self.ALT_RECT_FILL,
                 'id': '%d' % idVal,
             },
         ):
             idVal += 2
         myDatumP = Coord.newPt(
             myDatumP,
             incX=Coord.Dim(2.0, self.COMMON_UNITS),
             incY=Coord.Dim(2.0, self.COMMON_UNITS),
         )
         myTokIdxS = list(range(len(self.HIST_PP_TOKEN_TYPES_COLOURS)))
         if theTpt.positiveSweepDir:
             myTokIdxS.reverse()
         for iC in myTokIdxS:
             myBox = Coord.Box(self.HIST_DEPTH, self.HIST_DEPTH)
             # Convert to physical and plot
             with SVGWriter.SVGRect(
                     theSvg,
                     myDatumP,
                     myBox,
                 {
                     'fill': self.HIST_PP_TOKEN_TYPES_COLOURS[iC][1],
                     'stroke': self.HIST_RECT_COLOUR_STROKE,
                     'stroke-width': self.HIST_RECT_STROKE_WIDTH,
                     'id': '%d' % idVal
                 },
             ):
                 idVal += 2
             myTextDatumP = Coord.newPt(
                 myDatumP,
                 incX=self.HIST_DEPTH + Coord.Dim(2.0, self.COMMON_UNITS),
                 incY=self.HIST_DEPTH.scale(0.5),
             )
             with SVGWriter.SVGText(
                     theSvg, myTextDatumP, None, None, {
                         'font-family': 'Verdana',
                         'font-size': '10',
                         'dominant-baseline': 'middle',
                         'id': '%d' % idVal,
                     }):
                 theSvg.characters(self.HIST_PP_TOKEN_TYPES_COLOURS[iC][0])
                 idVal += 2
             # Increment the datum
             myDatumP = Coord.newPt(myDatumP,
                                    incX=None,
                                    incY=self.HIST_DEPTH)
Exemplo n.º 22
0
 def setUp(self):
     self._boxDefault = Coord.Box(
         Coord.Dim(300, None),
         Coord.Dim(500, None),
     )
Exemplo n.º 23
0
 def testBbChildren_00(self):
     """TestPlotNodeBboxWithChildren.testBbChildren_00() - three children."""
     myObj = PlotNode.PlotNodeBbox()
     myObj.width = Coord.Dim(12, 'mm')
     myObj.depth = Coord.Dim(8, 'mm')
     #print '\nTRACE myObj', myObj
     myObj.bbSelfPadding = Coord.Pad(
         Coord.Dim(1, 'mm'),  # prev
         Coord.Dim(3, 'mm'),  # next
         Coord.Dim(5, 'mm'),  # parent
         Coord.Dim(7, 'mm'),  # child
     )
     myObj.bbSpaceChildren = Coord.Dim(16, 'mm')
     self.assertEqual(True, myObj.bbChildrenWidth is None)
     self.assertEqual(True, myObj.bbChildrenDepth is None)
     self.assertEqual(0, myObj.numChildren)
     myObj.extendChildBbox(
         Coord.Box(
             Coord.Dim(15, 'mm'),
             Coord.Dim(7, 'mm'),
         ))
     # Child box now w:15, d:7
     self.assertEqual(1, myObj.numChildren)
     self.assertEqual(myObj.bbChildrenWidth, Coord.Dim(15, 'mm'))
     self.assertEqual(myObj.bbChildrenDepth, Coord.Dim(7, 'mm'))
     myObj.extendChildBbox(
         Coord.Box(
             Coord.Dim(31, 'mm'),
             Coord.Dim(29, 'mm'),
         ))
     # Child box now w:15+31=46, d:max(7,29)=29
     self.assertEqual(2, myObj.numChildren)
     self.assertEqual(myObj.bbChildrenWidth, Coord.Dim(46, 'mm'))
     self.assertEqual(myObj.bbChildrenDepth, Coord.Dim(29, 'mm'))
     myObj.extendChildBbox(
         Coord.Box(
             Coord.Dim(11, 'mm'),
             Coord.Dim(9, 'mm'),
         ))
     # Child box now w:46+11=57, d:max(29,9)=29
     self.assertEqual(3, myObj.numChildren)
     self.assertEqual(myObj.bbChildrenWidth, Coord.Dim(57, 'mm'))
     self.assertEqual(myObj.bbChildrenDepth, Coord.Dim(29, 'mm'))
     # bbSigma:
     # Width is 57mm as children are wider than me
     # Depth is 5 + 8 + 7 + 16 + 29 = 65mm
     #print
     #print 'myObj.bbSigma:', myObj.bbSigma
     self.assertEqual(myObj.bbSigma,
                      Coord.Box(
                          Coord.Dim(57, 'mm'),
                          Coord.Dim(65, 'mm'),
                      ))
     # Set my datum up
     myD = Coord.Pt(
         Coord.Dim(135, 'mm'),
         Coord.Dim(19, 'mm'),
     )
     # x should be 135 + 0.5 * (57-(1+12+3) + 1) = 135 + 0.5 * 41 + 1 = 156.5
     #print
     #print 'myObj.plotPointSelf:', myObj.plotPointSelf(myD)
     self.assertEqual(
         myObj.plotPointSelf(myD),
         Coord.Pt(
             Coord.Dim(156.5, 'mm'),
             Coord.Dim(24, 'mm'),
         ))
     #childBboxDatum
     #print
     #print 'myObj.childBboxDatum:', myObj.childBboxDatum(myD)
     self.assertEqual(myObj.childBboxDatum(myD),
                      Coord.Pt(
                          Coord.Dim(135, 'mm'),
                          Coord.Dim(55, 'mm'),
                      ))
Exemplo n.º 24
0
    def plotToFileObj(self, theFileObj, theTpt):
        """Root level call to plot to a file object. The SVG stream is
        created here."""
        if self._numPassesToPlotSelf < 1:
            raise ValueError('No self._numPassesToPlotSelf set!')
        # Make viewBox user coordinates * self.VIEWBOX_SCALE
        myRootAttrs = {
#             'viewBox' : '0 0 %d %d' \
#                 % (
#                     theTpt.canvasP().width.value * self.VIEWBOX_SCALE,
#                     theTpt.canvasP().depth.value * self.VIEWBOX_SCALE,
#                     ),
            'xmlns:xlink'   : self.NAMESPACE_XLINK,
        }
        # Bit of a hacky way to add enough margin for the pop-ups or rather
        # drop downs. This adds space for the bottom most boxes.
        canvasY = theTpt.canvasP().depth + Coord.Dim(60, 'mm') + Coord.Dim(8, 'mm')
        myCanvas = Coord.Box(
                    theTpt.canvasP().width + Coord.Dim(60, 'mm'),
                    canvasY,
        )
        # Shrink canvas if it is a large plot
        yOffsetForScalingText =  Coord.Dim(10, 'mm')
        scaleIdx = self.SCALE_FACTORS.index(1)
        assert scaleIdx >= 0
        while scaleIdx > 0 and canvasY > self.SCALE_MAX_Y:
            canvasY = canvasY.scale(0.5)
            scaleIdx -= 1
        self._scale = self.SCALE_FACTORS[scaleIdx]
        with SVGWriter.SVGWriter(theFileObj, myCanvas, myRootAttrs, mustIndent=cpip.INDENT_ML) as myS:
            # yOffsetForScalingText is applied wrong, should respect theTpt
            myDatum = Coord.Pt(
                         CANVAS_PADDING.prev - yOffsetForScalingText,
                         CANVAS_PADDING.parent,
                    )
            self.writePreamble(myS)
            myS.comment(' Root position: %s, Sweep direction: %s canvas=%s datum=%s' \
                         % (theTpt.rootPos, theTpt.sweepDir, theTpt.canvasP(), myDatum),
                         newLine=True)
            # Shift the drawing down a bit to make way for the scale buttons.
            with SVGWriter.SVGGroup(myS, {'transform' : "translate(0, 24)"}):
                with SVGWriter.SVGGroup(myS,
                        {
                            'id' : 'graphic',
                            'transform' : "scale(%s)" % self.SCALE_FACTORS[scaleIdx]
                        }):
                    # Apply a group element for scaling the plot
                    # More hackery: yOffsetForScalingText is applied wrong, should respect theTpt
                    with SVGWriter.SVGRect(
                            myS,
                            Coord.newPt(
                                        Coord.zeroBaseUnitsPt(),
                                        incX=None,
                                        incY=yOffsetForScalingText),
                            theTpt.canvasP(),
                            {
                                'fill'         : 'none',
                                'stroke'       : 'grey',
                                'stroke-width' : '2',
                            },
                        ):
                        pass
                    # Start the plot
                    self.plotInitialise(myS, myDatum, theTpt)
                    # Now plot all contents
                    for p in range(self._numPassesToPlotSelf):
                        self.plotToSVGStream(myS, myDatum, theTpt, p, [])
                    # Finish the plot
                    self.plotFinalise(myS, myDatum, theTpt)
Exemplo n.º 25
0
    def _plotWhereWhyHow(self, theSvg, iChild, theDatumL, theTpt):
        """Plot description of Where/Why/How inclusion of a single child to a
        stream at the (self) logical datum point."""
        assert (not self.isRoot)
        assert (len(self._children) > 0)
        assert (iChild >= 0 and iChild < len(self._children))
        self.commentFunctionBegin(theSvg, File=self._fileName)
        #myDatumL = theDatumL
        #myDatumL = Coord.newPt(theDatumL, incX=self.FILE_PADDING.prev, incY=None)#self.FILE_PADDING.parent.scale(-1.0))
        myDatumL = self._children[iChild].bb.plotPointSelf(theDatumL)
        # Move logical datum logically 'up' and 'right' by half
        #         myDatumL = Coord.newPt(
        #                 myDatumL,
        #                 incX=self._children[iChild].bb.width.scale(0.5),
        #                 incY=self.FILE_PADDING.parent.scale(-0.5),
        #         )
        myAltTxtPointP = theTpt.pt(
            Coord.newPt(
                myDatumL,
                incX=self._children[iChild].bb.width.scale(0.5),
                incY=self.FILE_PADDING.parent.scale(-0.5),
            ))
        altTextS = []
        altTextS.append('Where: %s#%d ' \
                        % (self.nodeName, self._children[iChild].lineNum))
        if len(self._children[iChild].condComp) > 0:
            #             altTextS.append(
            #                 '  Why: %s since: %s ' \
            #                 % (
            #                     str(self._children[iChild].condCompState),
            #                     self._children[iChild].condComp
            #                     )
            #             )
            assert self._children[iChild].condCompState
            altTextS.append(
                '  Why: %s ' \
                % (
                    self._children[iChild].condComp
                    )
            )
        else:
            altTextS.append(
                '  Why: %s ' \
                    % (str(self._children[iChild].condCompState)
                    )
            )
        altTextS.append('  How: #include %s' %
                        ', '.join(self._children[iChild].findLogic))
        #         self.writeAltTextAndMouseOverText(
        #                 theSvg, myPointP, theSvg.id,
        #                 self.POPUP_TEXT, altTextS, Coord.Dim(20, 'pt'))
        triggerBoxP = theTpt.boxP(
            Coord.Box(self._children[iChild].bb.width,
                      self.FILE_PADDING.parent))
        #         triggerPointP = theTpt.pt(myDatumL)
        triggerPointP = theTpt.pt(
            Coord.newPt(
                myDatumL,
                incX=self._children[iChild].bb.width,
                incY=self.FILE_PADDING.parent.scale(-1.0),
            ))
        self.writeAltTextAndMouseOverRect(
            theSvg,
            theSvg.id,
            myAltTxtPointP,
            altTextS,
            triggerPointP,
            triggerBoxP,
        )

        self.commentFunctionEnd(theSvg, File=self._fileName)
Exemplo n.º 26
0
    def test_05(self):
        """TestSVGlWriter.test_05(): a polyline.
        Based on http://www.w3.org/TR/2003/REC-SVG11-20030114/shapes.html#PolylineElement"""
        myF = io.StringIO()
        myViewPort = Coord.Box(
            Coord.Dim(12, 'cm'),
            Coord.Dim(4, 'cm'),
        )
        with SVGWriter.SVGWriter(myF, myViewPort,
                                 {'viewBox': "0 0 1200 400"}) as xS:
            with XmlWrite.Element(xS, 'desc'):
                xS.characters(
                    'Example line01 - lines expressed in user coordinates')
            #xS.comment(" Show outline of canvas using 'rect' element ")
            myPt = Coord.Pt(Coord.baseUnitsDim(1), Coord.baseUnitsDim(1))
            myBx = Coord.Box(Coord.baseUnitsDim(1198), Coord.baseUnitsDim(398))
            with SVGWriter.SVGRect(xS, myPt, myBx, {
                    'fill': "none",
                    'stroke': "blue",
                    'stroke-width': "2"
            }):
                pass
            # Make a group
            with SVGWriter.SVGPolyline(xS, [
                    Coord.Pt(Coord.baseUnitsDim(50), Coord.baseUnitsDim(375)),
                    Coord.Pt(Coord.baseUnitsDim(150), Coord.baseUnitsDim(375)),
                    Coord.Pt(Coord.baseUnitsDim(150), Coord.baseUnitsDim(325)),
                    Coord.Pt(Coord.baseUnitsDim(250), Coord.baseUnitsDim(325)),
                    Coord.Pt(Coord.baseUnitsDim(250), Coord.baseUnitsDim(375)),
                    Coord.Pt(Coord.baseUnitsDim(350), Coord.baseUnitsDim(375)),
                    Coord.Pt(Coord.baseUnitsDim(350), Coord.baseUnitsDim(250)),
                    Coord.Pt(Coord.baseUnitsDim(450), Coord.baseUnitsDim(250)),
                    Coord.Pt(Coord.baseUnitsDim(450), Coord.baseUnitsDim(375)),
                    Coord.Pt(Coord.baseUnitsDim(550), Coord.baseUnitsDim(375)),
                    Coord.Pt(Coord.baseUnitsDim(550), Coord.baseUnitsDim(175)),
                    Coord.Pt(Coord.baseUnitsDim(650), Coord.baseUnitsDim(175)),
                    Coord.Pt(Coord.baseUnitsDim(650), Coord.baseUnitsDim(375)),
                    Coord.Pt(Coord.baseUnitsDim(750), Coord.baseUnitsDim(375)),
                    Coord.Pt(Coord.baseUnitsDim(750), Coord.baseUnitsDim(100)),
                    Coord.Pt(Coord.baseUnitsDim(850), Coord.baseUnitsDim(100)),
                    Coord.Pt(Coord.baseUnitsDim(850), Coord.baseUnitsDim(375)),
                    Coord.Pt(Coord.baseUnitsDim(950), Coord.baseUnitsDim(375)),
                    Coord.Pt(Coord.baseUnitsDim(950), Coord.baseUnitsDim(25)),
                    Coord.Pt(Coord.baseUnitsDim(1050), Coord.baseUnitsDim(25)),
                    Coord.Pt(Coord.baseUnitsDim(1050),
                             Coord.baseUnitsDim(375)),
                    Coord.Pt(Coord.baseUnitsDim(1150),
                             Coord.baseUnitsDim(375)),
            ], {
                    'fill': 'none',
                    'stroke': 'blue',
                    'stroke-width': "5"
            }):
                pass
        #print
        #print myF.getvalue()
        self.assertEqual(
            myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="4.00cm" version="1.1" viewBox="0 0 1200 400" width="12.00cm" xmlns="http://www.w3.org/2000/svg">
  <desc>Example line01 - lines expressed in user coordinates</desc>
  <rect fill="none" height="398px" stroke="blue" stroke-width="2" width="1198px" x="1px" y="1px" />
  <polyline fill="none" points="50,375 150,375 150,325 250,325 250,375 350,375 350,250 450,250 450,375 550,375 550,175 650,175 650,375 750,375 750,100 850,100 850,375 950,375 950,25 1050,25 1050,375 1150,375" stroke="blue" stroke-width="5" />
</svg>
""")
Exemplo n.º 27
0
    def test_04(self):
        """TestSVGlWriter.test_04(): a line.
        Based on http://www.w3.org/TR/2003/REC-SVG11-20030114/shapes.html#LineElement"""
        myF = io.StringIO()
        myViewPort = Coord.Box(
            Coord.Dim(12, 'cm'),
            Coord.Dim(4, 'cm'),
        )
        with SVGWriter.SVGWriter(myF, myViewPort) as xS:
            with XmlWrite.Element(xS, 'desc'):
                xS.characters(
                    'Example line01 - lines expressed in user coordinates')
            #xS.comment(" Show outline of canvas using 'rect' element ")
            myPt = Coord.Pt(Coord.baseUnitsDim(1), Coord.baseUnitsDim(1))
            myBx = Coord.Box(Coord.baseUnitsDim(1198), Coord.baseUnitsDim(398))
            with SVGWriter.SVGRect(xS, myPt, myBx, {
                    'fill': "none",
                    'stroke': "blue",
                    'stroke-width': "2"
            }):
                pass
            # Make a group
            with SVGWriter.SVGGroup(xS, {'stroke': 'green'}):
                with SVGWriter.SVGLine(
                        xS,
                        Coord.Pt(Coord.baseUnitsDim(100),
                                 Coord.baseUnitsDim(300)),
                        Coord.Pt(Coord.baseUnitsDim(300),
                                 Coord.baseUnitsDim(100)),
                    {'stroke-width': "5"}):
                    pass
                with SVGWriter.SVGLine(
                        xS,
                        Coord.Pt(Coord.baseUnitsDim(300),
                                 Coord.baseUnitsDim(300)),
                        Coord.Pt(Coord.baseUnitsDim(500),
                                 Coord.baseUnitsDim(100)),
                    {'stroke-width': "10"}):
                    pass
                with SVGWriter.SVGLine(
                        xS,
                        Coord.Pt(Coord.baseUnitsDim(500),
                                 Coord.baseUnitsDim(300)),
                        Coord.Pt(Coord.baseUnitsDim(700),
                                 Coord.baseUnitsDim(100)),
                    {'stroke-width': "15"}):
                    pass
                with SVGWriter.SVGLine(
                        xS,
                        Coord.Pt(Coord.baseUnitsDim(700),
                                 Coord.baseUnitsDim(300)),
                        Coord.Pt(Coord.baseUnitsDim(900),
                                 Coord.baseUnitsDim(100)),
                    {'stroke-width': "20"}):
                    pass
                with SVGWriter.SVGLine(
                        xS,
                        Coord.Pt(Coord.baseUnitsDim(900),
                                 Coord.baseUnitsDim(300)),
                        Coord.Pt(Coord.baseUnitsDim(1100),
                                 Coord.baseUnitsDim(100)),
                    {'stroke-width': "25"}):
                    pass
        #print
        #print myF.getvalue()
        self.assertEqual(
            myF.getvalue(), """<?xml version='1.0' encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg height="4.00cm" version="1.1" width="12.00cm" xmlns="http://www.w3.org/2000/svg">
  <desc>Example line01 - lines expressed in user coordinates</desc>
  <rect fill="none" height="398px" stroke="blue" stroke-width="2" width="1198px" x="1px" y="1px" />
  <g stroke="green">
    <line stroke-width="5" x1="100px" x2="300px" y1="300px" y2="100px" />
    <line stroke-width="10" x1="300px" x2="500px" y1="300px" y2="100px" />
    <line stroke-width="15" x1="500px" x2="700px" y1="300px" y2="100px" />
    <line stroke-width="20" x1="700px" x2="900px" y1="300px" y2="100px" />
    <line stroke-width="25" x1="900px" x2="1100px" y1="300px" y2="100px" />
  </g>
</svg>
""")