def test_get_css_rules_from_svg_document04(self): # 'style' element # See also: svg/style8.css parser = SVGParser() root = parser.create_element('svg') style = root.create_sub_element('style') style.text = '@import url(http://localhost:8000/svg/style8.css);' style_sheets = get_css_style_sheets_from_svg_document(root) self.assertEqual(1, len(style_sheets)) css_style_sheet = style_sheets[0] self.assertIsNone(css_style_sheet.owner_rule) self.assertEqual('text/css', css_style_sheet.type) self.assertIsNone(css_style_sheet.href) self.assertEqual(style, css_style_sheet.owner_node) self.assertIsNone(css_style_sheet.parent_style_sheet) self.assertIsNone(css_style_sheet.title) self.assertEqual('all', css_style_sheet.media.media_text) css_rules = css_style_sheet.css_rules self.assertEqual(1, len(css_rules)) css_rule = css_rules[0] self.assertEqual(CSSRule.IMPORT_RULE, css_rule.type) css_stylesheet = css_rule.style_sheet self.assertEqual(15, len(css_stylesheet.css_rules), msg='http server may not be working.')
def test_inline_style01(self): parser = SVGParser() rect = parser.create_element('rect') self.assertIsInstance(rect.style, CSSStyleDeclaration) self.assertIsNone(rect.style.parent_rule) self.assertEqual(0, rect.style.length) self.assertEqual(0, len(rect.attributes)) rect.style.set_property('fill', 'red') rect.style.set_property('stroke', 'blue') rect.style.set_property('stroke-width', '5') self.assertEqual(3, rect.style.length) self.assertEqual('red', rect.style.get_property_value('fill')) self.assertEqual('blue', rect.style.get_property_value('stroke')) self.assertEqual('5', rect.style.get_property_value('stroke-width')) self.assertEqual(1, len(rect.attributes)) expected = 'fill: red; stroke-width: 5; stroke: blue;' self.assertEqual(expected, rect.get('style')) rect.style.remove_property('stroke-width') self.assertEqual(2, rect.style.length) self.assertEqual(1, len(rect.attributes)) expected = 'fill: red; stroke: blue;' self.assertEqual(expected, rect.get('style')) rect.style.set_property('fill', None) rect.style.set_property('stroke', '') rect.style.set_property('stroke', '') # no error self.assertEqual(0, rect.style.length) self.assertEqual(0, len(rect.attributes))
def test_get_css_rules_from_svg_document03(self): # 'link' element # See also: svg/style8.css parser = SVGParser() root = parser.create_element('svg') link = root.create_sub_element('link') link.attributes.update({ 'rel': 'stylesheet', 'href': 'http://localhost:8000/svg/style8.css', 'type': 'text/css', }) style_sheets = get_css_style_sheets_from_svg_document(root) self.assertEqual(1, len(style_sheets)) css_style_sheet = style_sheets[0] self.assertIsNone(css_style_sheet.owner_rule) self.assertEqual('text/css', css_style_sheet.type) self.assertEqual('http://localhost:8000/svg/style8.css', css_style_sheet.href) self.assertEqual(link, css_style_sheet.owner_node) self.assertIsNone(css_style_sheet.parent_style_sheet) self.assertIsNone(css_style_sheet.title) self.assertEqual(0, css_style_sheet.media.length) css_rules = css_style_sheet.css_rules self.assertEqual(15, len(css_rules), msg='http server may not be working.')
def test_inline_style02(self): parser = SVGParser() rect = parser.create_element('rect') rect.style.update({ 'fill': 'red', 'stroke': 'blue', 'stroke-width': '5', }) self.assertIsInstance(rect.style, CSSStyleDeclaration) self.assertIsNone(rect.style.parent_rule) self.assertEqual(3, rect.style.length) self.assertEqual('red', rect.style.get_property_value('fill')) self.assertEqual('blue', rect.style.get_property_value('stroke')) self.assertEqual('5', rect.style.get_property_value('stroke-width')) self.assertEqual(1, len(rect.attributes)) expected = 'fill: red; stroke-width: 5; stroke: blue;' self.assertEqual(expected, rect.get('style')) rect.style.update({'fill': 'white'}) self.assertEqual('white', rect.style.get_property_value('fill')) self.assertEqual(3, rect.style.length) self.assertEqual(1, len(rect.attributes)) del rect.style['fill'] self.assertEqual(2, rect.style.length) self.assertEqual(1, len(rect.attributes)) rect.style['stroke'] = None self.assertEqual(1, rect.style.length) self.assertEqual(1, len(rect.attributes)) rect.style['stroke-width'] = '' self.assertEqual(0, len(rect.attributes)) self.assertEqual(0, rect.style.length) rect.style['fill'] = 'white', 'IMPORTANT' # value with priority value = rect.style['fill'] priority = rect.style.get_property_priority('fill') self.assertEqual('white', value) self.assertEqual('important', priority) rect.style['fill'] = 'black' # value without priority value = rect.style['fill'] priority = rect.style.get_property_priority('fill') self.assertEqual('black', value) self.assertEqual('important', priority) rect.style.remove_property('fill') rect.style.set_property('fill', 'none') value = rect.style['fill'] priority = rect.style.get_property_priority('fill') self.assertEqual('none', value) self.assertEqual('', priority) rect.style.set_property('fill', 'blue', 'Important') value = rect.style.get_property_value('fill') priority = rect.style.get_property_priority('fill') self.assertEqual('blue', value) self.assertEqual('important', priority)
def test_get_css_style04(self): parser = SVGParser() svg = ''' <svg width="5cm" height="4cm" viewBox="0 0 500 400" xmlns="http://www.w3.org/2000/svg"> <style type="text/css"> @import url(svg/style8.css); @media screen { /* rule (1) */ /* hide navigation controls when printing */ #navigation { display: none } @media (max-width: 12cm) { /* rule (2) */ /* keep notes in flow when printing to narrow pages */ .note { float: none } } } @media screen and (min-width: 35em), print and (min-width: 40em) { #section_navigation { float: left; width: 10em; } } .Border { fill:none; stroke:blue; stroke-width:1 } .Connect { fill:none; stroke:#888888; stroke-width:2 } .SamplePath { fill:none; stroke:red; stroke-width:5 } .EndPoint { fill:none; stroke:#888888; stroke-width:2 } .CtlPoint { fill:#888888; stroke:none } .AutoCtlPoint { fill:none; stroke:blue; stroke-width:4 } .Label { font-size:22; font-family:Verdana } </style> <text id="heading" x="-280" y="-270"> SVG demonstration</text> <rect class="Border" x="1" y="1" width="498" height="398" id="rect01" /> <polyline class="Connect" points="100,200 100,100" id="polyline01" /> <path class="SamplePath" d="M100,200 C100,100 250,100 250,200 S400,300 400,200" id="path01" /> <circle class="EndPoint" cx="100" cy="200" r="10" id="circle01" /> <text class="Label" x="25" y="70" id="text01"> M100,200 C100,100 250,100 250,200</text> </svg> ''' root = parser.fromstring(svg) rect = root.get_element_by_id('rect01') css_rules = get_css_rules(rect) css_style, css_style_important = get_css_style(rect, css_rules) self.assertEqual(4, len(css_style)) self.assertEqual(0, len(css_style_important)) css_style = rect.get_computed_style() self.assertEqual('none', css_style.get('fill')) self.assertEqual('blue', css_style.get('stroke')) self.assertEqual(1, css_style.get('stroke-width')) text = root.get_element_by_id('heading') css_style = text.get_computed_style() self.assertEqual(24, css_style.get('font-size'), msg='http server may not be working.') self.assertEqual(700, css_style.get('font-weight'))
def test_new_value_percentage2(self): parser = SVGParser() root = parser.create_element('svg') group = root.create_sub_element('g') group.attributes.update({ 'font-size': '16', }) a = SVGLength(context=group) a.new_value(92.00042345, SVGLength.TYPE_PERCENTAGE) self.assertEqual(92.00042345, a.value(SVGLength.TYPE_PERCENTAGE)) self.assertEqual('%', a.unit) self.assertEqual('92%', a.tostring())
def test_get_css_rules_from_xml_stylesheet02(self): # xml-stylesheet svg = '''<?xml version="1.0" standalone="no"?> <?xml-stylesheet type="text/css" href="svg/style8.css" title="default"?> <?xml-stylesheet type="text/css" href="svg/ny1.css" title="extras"?> <?demo-pi ?> <!--comment--> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg width="600px" height="600px" viewBox="-300 -300 600 600" xmlns="http://www.w3.org/2000/svg"> </svg> ''' parser = SVGParser() tree = parser.parse(StringIO(svg)) root = tree.getroot() style_sheets = get_css_style_sheets_from_xml_stylesheet(root) self.assertEqual(2, len(style_sheets)) css_style_sheet = style_sheets[0] css_rules = css_style_sheet.css_rules self.assertEqual(15, len(css_rules)) css_rule = css_rules[0] self.assertEqual(CSSRule.STYLE_RULE, css_rule.type) self.assertEqual('svg', css_rule.selector_text) css_rule = css_rules[14] self.assertEqual(CSSRule.STYLE_RULE, css_rule.type) self.assertEqual('#inner-petals .segment:hover > .segment-edge', css_rule.selector_text) css_rules = style_sheets[1].css_rules self.assertEqual(7, len(css_rules)) css_rule = css_rules[0] self.assertEqual(CSSRule.STYLE_RULE, css_rule.type) self.assertEqual('text', css_rule.selector_text) css_rule = css_rules[6] self.assertEqual(CSSRule.STYLE_RULE, css_rule.type) self.assertEqual('.tick', css_rule.selector_text)
def test_font_size_vw(self): # 'vw unit' parser = SVGParser() root = parser.create_element('svg') root.attributes.update({ 'width': '200mm', }) group = root.create_sub_element('g') text = group.create_sub_element('text') text.attributes.update({ 'font-size': '8vw', }) a = SVGLength(text.attributes['font-size'].value, context=None) expected = 8 self.assertEqual(expected, a.value(), msg=a) a = SVGLength(text.attributes['font-size'].value, context=text) expected = 8 * 200 / 100 # 16mm self.assertAlmostEqual(expected, a.value(SVGLength.TYPE_MM), msg=a)
def test_get_css_style03(self): parser = SVGParser() svg = ''' <svg width="5cm" height="4cm" viewBox="0 0 500 400" xmlns="http://www.w3.org/2000/svg"> <style type="text/css"><![CDATA[ .Border { fill:none; stroke:blue; stroke-width:1 } .Connect { fill:none; stroke:#888888; stroke-width:2 } .SamplePath { fill:none; stroke:red; stroke-width:5 } .EndPoint { fill:none; stroke:#888888; stroke-width:2 } .CtlPoint { fill:#888888; stroke:none } .AutoCtlPoint { fill:none; stroke:blue; stroke-width:4 } .Label { font-size:22; font-family:Verdana } ]]></style> <rect class="Border" x="1" y="1" width="498" height="398" id="rect01" /> <polyline class="Connect" points="100,200 100,100" id="polyline01" /> <path class="SamplePath" d="M100,200 C100,100 250,100 250,200 S400,300 400,200" id="path01" /> <circle class="EndPoint" cx="100" cy="200" r="10" id="circle01" /> <text class="Label" x="25" y="70" id="text01"> M100,200 C100,100 250,100 250,200</text> </svg> ''' root = parser.fromstring(svg) rect = root.get_element_by_id('rect01') css_style = rect.get_computed_style() self.assertEqual('none', css_style.get('fill')) self.assertEqual('blue', css_style.get('stroke')) self.assertEqual(1, css_style.get('stroke-width')) path = root.get_element_by_id('path01') css_style = path.get_computed_style() self.assertEqual('none', css_style.get('fill')) self.assertEqual('red', css_style.get('stroke')) self.assertEqual(5, css_style.get('stroke-width')) text = root.get_element_by_id('text01') css_style = text.get_computed_style() self.assertEqual(['Verdana'], css_style.get('font-family')) self.assertEqual(22, css_style.get('font-size'))
def main(): """Usage: python3 sample.py filename """ if len(sys.argv) >= 2: source = sys.argv[1] print('"{}"'.format(source)) else: source = StringIO(PYTHON_SVG) parser = SVGParser() tree = parser.parse(source) root = tree.getroot() for element in root.iter(): print('node type: {}, node name: \'{}\''.format( element.node_type, element.node_name)) print('- class:', type(element)) if element.node_type == Node.COMMENT_NODE: continue print('- tag: \'{}\', tag name: \'{}\''.format(element.tag, element.tag_name)) print('- id: {}'.format( None if element.id is None else '\'{}\''.format(element.id))) print('- attributes: ' + repr(element.attributes)) if element.local_name == 'svg': vpx, vpy, vpw, vph = element.get_viewport_size() print('- viewport: x: {}, y: {}, width: {}, height: {}'.format( vpx.value(), vpy.value(), vpw.value(), vph.value())) if isinstance(element, SVGGraphicsElement): ctm = element.get_ctm() print('- ctm: {}'.format(ctm.tolist())) bbox = element.get_bbox() print('- bbox: x: {}, y: {}, width: {}, height: {}'.format( bbox.x, bbox.y, bbox.width, bbox.height)) if isinstance(element, SVGGeometryElement): print('- geometry: {}'.format(element.get_computed_geometry())) print('- total length: {:g}'.format(element.get_total_length())) print()
def test_get_css_style01(self): # 'style' element # See also: svg/style8.css parser = SVGParser() root = parser.create_element('svg') style = root.create_sub_element('style') style.text = '@import url(svg/style8.css);' text = root.create_sub_element('text') text.id = 'heading' css_rules = get_css_rules(text) css_style, css_style_important = get_css_style(text, css_rules) self.assertEqual('24px', css_style.get('font-size'), msg='http server may not be working.') self.assertEqual('bold', css_style.get('font-weight')) self.assertEqual(0, len(css_style_important)) css_style = text.get_computed_style() self.assertEqual(24, css_style.get('font-size')) self.assertEqual(700, css_style.get('font-weight'))
def test_font_relative_lengths_rem02(self): # See also: length02.html base_font_size = 18 element_font_size = 20 Font.default_font_size = base_font_size parser = SVGParser() root = parser.create_element('svg') group = root.create_sub_element('g') group.attributes.update({ 'font-family': 'IPAmjMincho, serif', 'font-size': str(element_font_size), }) text = group.create_sub_element('text') text.attributes.update({ 'font-size': '1em', }) a = SVGLength('1rem', context=text) expected = base_font_size self.assertAlmostEqual(expected, a.value(), msg=a)
def test_font_relative_lengths_ch01(self): # See also: length02.html base_font_size = 18 element_font_size = 20 Font.default_font_size = base_font_size parser = SVGParser() root = parser.create_element('svg') group = root.create_sub_element('g') group.attributes.update({ 'font-family': 'DejaVu Sans, sans-serif', 'font-size': str(element_font_size), }) text = group.create_sub_element('text') text.attributes.update({ 'font-size': '1em', }) a = SVGLength('1ch', context=text) expected = 12.724 self.assertAlmostEqual(expected, a.value(), msg=a, places=places)
def test_get_css_rules_from_svg_document01(self): # 'link' and 'style' elements svg = ''' <svg width="5cm" height="4cm" viewBox="0 0 500 400" xmlns="http://www.w3.org/2000/svg"> <link rel="stylesheet" href="svg/style8.css"/> <style type="text/css"><![CDATA[ .Border { fill:none; stroke:blue; stroke-width:1 } .Connect { fill:none; stroke:#888888; stroke-width:2 } .SamplePath { fill:none; stroke:red; stroke-width:5 } .EndPoint { fill:none; stroke:#888888; stroke-width:2 } .CtlPoint { fill:#888888; stroke:none } .AutoCtlPoint { fill:none; stroke:blue; stroke-width:4 } .Label { font-size:22; font-family:Verdana } ]]></style> <style> @media print { /* rule (1) */ /* hide navigation controls when printing */ #navigation { display: none } @media (max-width: 12cm) { /* rule (2) */ /* keep notes in flow when printing to narrow pages */ .note { float: none } } } @media screen and (min-width: 35em), print and (min-width: 40em) { #section_navigation { float: left; width: 10em; } } </style> <rect class="Border" x="1" y="1" width="498" height="398" id="rect01" /> <polyline class="Connect" points="100,200 100,100" id="polyline01" /> <path class="SamplePath" d="M100,200 C100,100 250,100 250,200 S400,300 400,200" id="path01" /> <circle class="EndPoint" cx="100" cy="200" r="10" id="circle01" /> <text class="Label" x="25" y="70" id="text01"> M100,200 C100,100 250,100 250,200</text> </svg> ''' parser = SVGParser() tree = parser.parse(StringIO(svg)) root = tree.getroot() style_sheets = get_css_style_sheets_from_svg_document(root) self.assertEqual(3, len(style_sheets)) # <link rel="stylesheet" href="svg/style8.css"/> css_style_sheet = style_sheets[0] self.assertEqual(15, len(css_style_sheet.css_rules)) css_rule = css_style_sheet.css_rules[0] self.assertEqual(CSSRule.STYLE_RULE, css_rule.type) self.assertEqual('svg', css_rule.selector_text) css_rule = css_style_sheet.css_rules[14] self.assertEqual(CSSRule.STYLE_RULE, css_rule.type) self.assertEqual('#inner-petals .segment:hover > .segment-edge', css_rule.selector_text) # <style type="text/css">... css_style_sheet = style_sheets[1] self.assertEqual(7, len(css_style_sheet.css_rules)) css_rule = css_style_sheet.css_rules[0] self.assertEqual(CSSRule.STYLE_RULE, css_rule.type) self.assertEqual('.Border', css_rule.selector_text) css_rule = css_style_sheet.css_rules[6] self.assertEqual(CSSRule.STYLE_RULE, css_rule.type) self.assertEqual('.Label', css_rule.selector_text) # <style> @media at-rule css_style_sheet = style_sheets[2] self.assertEqual(2, len(css_style_sheet.css_rules)) # @media 'print' css_rule = css_style_sheet.css_rules[0] self.assertEqual(CSSRule.MEDIA_RULE, css_rule.type) self.assertEqual('print', css_rule.media.media_text) # child rules self.assertEqual(2, len(css_rule.css_rules)) # (1) style rule child_css_rule = css_rule.css_rules[0] self.assertEqual(CSSRule.STYLE_RULE, child_css_rule.type) self.assertEqual('#navigation', child_css_rule.selector_text) # (2) @media at-rule child_css_rule = css_rule.css_rules[1] self.assertEqual(CSSRule.MEDIA_RULE, child_css_rule.type) self.assertEqual('(max-width: 12cm)', child_css_rule.media.media_text) css_rule = css_style_sheet.css_rules[1] self.assertEqual(CSSRule.MEDIA_RULE, css_rule.type) self.assertEqual( 'screen and (min-width: 35em), print and (min-width: 40em)', css_rule.media.media_text)
def test_convert01(self): # with context parser = SVGParser() root = parser.create_element('svg') group = root.create_sub_element('g') group.attributes.update({ 'font-family': 'DejaVu Sans, sans-serif', 'font-size': '16', }) # 1(rem) = 16(px) text = group.create_sub_element('text') a = SVGLength('1in', context=text) self.assertEqual('in', a.unit) self.assertEqual('1in', a.tostring()) a.convert(SVGLength.TYPE_CM) # 1(in) = 2.54(cm) self.assertEqual('cm', a.unit) self.assertEqual('2.54cm', a.tostring()) a.convert(SVGLength.TYPE_PX) # 2.54(cm) = 96(px) self.assertEqual('px', a.unit) self.assertEqual('96px', a.tostring()) a.convert(SVGLength.TYPE_NUMBER) # 96(px) = 96 self.assertIsNone(a.unit) self.assertEqual('96', a.tostring()) a.convert(SVGLength.TYPE_MM) # 96(px) = 25.4(mm) self.assertEqual('mm', a.unit) self.assertEqual('25.4mm', a.tostring()) # 100(%) = 16(px) a.convert(SVGLength.TYPE_PERCENTAGE) # 96(px) = 600(%) self.assertEqual('%', a.unit) self.assertEqual('600%', a.tostring()) # 100(%) = 1(em) a.convert(SVGLength.TYPE_EMS) # 600(%) = 6(em) self.assertEqual('em', a.unit) self.assertEqual('6em', a.tostring()) # 1(ex) = x-height(px) # 96(px) -> x-height: 53(px) # 96(px) / 53(px) = 1.8113... a.convert(SVGLength.TYPE_EXS) self.assertEqual('ex', a.unit) self.assertEqual('1.811ex', a.tostring()) # font-family: "DejaVu Sans", sans-serif # element font size: 16(px) -> 1(ex) = 9(px) # 1.8113(ex) = 1.8113 * 9 = 16.3017...(px) # 1(px) = 0.75(pt) # 16.3017 * 0.75 = 12.2263...(pt) a.convert(SVGLength.TYPE_PT) self.assertEqual('pt', a.unit) self.assertEqual('12.226pt', a.tostring()) # 1(pt) = 1 / 12(pc) # 12.2263(pt) = 1.0189...(pc) a.convert(SVGLength.TYPE_PC) self.assertEqual('pc', a.unit) self.assertEqual('1.019pc', a.tostring())