Skip to content

Commit d741fa1

Browse files
committed
Start to split off formatting routines..
from builtin
1 parent 5682345 commit d741fa1

File tree

6 files changed

+288
-158
lines changed

6 files changed

+288
-158
lines changed

mathics/builtin/drawing/graphics3d.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22

33
"""
4-
Graphics (3D)
4+
Three-Dimensional Graphics
55
"""
66

77

@@ -778,9 +778,6 @@ def __init__(self, content, evaluation, neg_y=False):
778778
def extent(self, completely_visible_only=False):
779779
return total_extent_3d([element.extent() for element in self.elements])
780780

781-
def to_svg(self):
782-
return "\n".join(element.to_svg() for element in self.elements)
783-
784781
def to_asy(self):
785782
return "\n".join([element.to_asy() for element in self.elements])
786783

mathics/builtin/graphics.py

Lines changed: 16 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77

88

99
from math import floor, ceil, log10, sin, cos, pi, sqrt, atan2, degrees, radians, exp
10-
import json
1110
import base64
1211
from itertools import chain
1312

@@ -33,6 +32,8 @@
3332
system_symbols_dict,
3433
from_python,
3534
)
35+
from mathics.core.formatter import lookup_method
36+
3637
from mathics.builtin.drawing.colors import convert as convert_color
3738
from mathics.core.numbers import machine_epsilon
3839

@@ -323,7 +324,11 @@ def _extract_graphics(graphics, format, evaluation):
323324
if format == "asy":
324325
code = "\n".join(element.to_asy() for element in elements.elements)
325326
elif format == "svg":
326-
code = elements.to_svg()
327+
format_fn = lookup_method(elements, "svg")
328+
if format_fn is not None:
329+
code = format_fn(elements)
330+
else:
331+
code = elements.to_svg()
327332
else:
328333
raise NotImplementedError
329334

@@ -1231,26 +1236,6 @@ def extent(self):
12311236
)
12321237
return result
12331238

1234-
def to_svg(self, offset=None):
1235-
l = self.style.get_line_width(face_element=True)
1236-
x1, y1 = self.p1.pos()
1237-
x2, y2 = self.p2.pos()
1238-
xmin = min(x1, x2)
1239-
ymin = min(y1, y2)
1240-
w = max(x1, x2) - xmin
1241-
h = max(y1, y2) - ymin
1242-
if offset:
1243-
x1, x2 = x1 + offset[0], x2 + offset[0]
1244-
y1, y2 = y1 + offset[1], y2 + offset[1]
1245-
style = create_css(self.edge_color, self.face_color, l)
1246-
return '<rect x="%f" y="%f" width="%f" height="%f" style="%s" />' % (
1247-
xmin,
1248-
ymin,
1249-
w,
1250-
h,
1251-
style,
1252-
)
1253-
12541239
def to_asy(self):
12551240
l = self.style.get_line_width(face_element=True)
12561241
x1, y1 = self.p1.pos()
@@ -1302,21 +1287,6 @@ def extent(self):
13021287
ry += l
13031288
return [(x - rx, y - ry), (x - rx, y + ry), (x + rx, y - ry), (x + rx, y + ry)]
13041289

1305-
def to_svg(self, offset=None):
1306-
x, y = self.c.pos()
1307-
rx, ry = self.r.pos()
1308-
rx -= x
1309-
ry = y - ry
1310-
l = self.style.get_line_width(face_element=self.face_element)
1311-
style = create_css(self.edge_color, self.face_color, stroke_width=l)
1312-
return '<ellipse cx="%f" cy="%f" rx="%f" ry="%f" style="%s" />' % (
1313-
x,
1314-
y,
1315-
rx,
1316-
ry,
1317-
style,
1318-
)
1319-
13201290
def to_asy(self):
13211291
x, y = self.c.pos()
13221292
rx, ry = self.r.pos()
@@ -1390,11 +1360,15 @@ def _arc_params(self):
13901360
return x, y, abs(rx), abs(ry), sx, sy, ex, ey, large_arc
13911361

13921362
def to_svg(self, offset=None):
1363+
# FIXME: figure out how to put in svg.py
13931364
if self.arc is None:
13941365
return super(_ArcBox, self).to_svg(offset)
13951366

13961367
x, y, rx, ry, sx, sy, ex, ey, large_arc = self._arc_params()
13971368

1369+
format_fn = lookup_method(self, "svg")
1370+
if format_fn is not None:
1371+
return format_fn(self, offset)
13981372
def path(closed):
13991373
if closed:
14001374
yield "M %f,%f" % (x, y)
@@ -1522,26 +1496,6 @@ def init(self, graphics, style, item=None):
15221496
else:
15231497
raise BoxConstructError
15241498

1525-
def to_svg(self, offset=None):
1526-
point_size, _ = self.style.get_style(PointSize, face_element=False)
1527-
if point_size is None:
1528-
point_size = PointSize(self.graphics, value=0.005)
1529-
size = point_size.get_size()
1530-
1531-
style = create_css(
1532-
edge_color=self.edge_color, stroke_width=0, face_color=self.face_color
1533-
)
1534-
svg = ""
1535-
for line in self.lines:
1536-
for coords in line:
1537-
svg += '<circle cx="%f" cy="%f" r="%f" style="%s" />' % (
1538-
coords.pos()[0],
1539-
coords.pos()[1],
1540-
size,
1541-
style,
1542-
)
1543-
return svg
1544-
15451499
def to_asy(self):
15461500
pen = create_pens(face_color=self.face_color, is_face_element=False)
15471501

@@ -1586,17 +1540,6 @@ def init(self, graphics, style, item=None, lines=None):
15861540
else:
15871541
raise BoxConstructError
15881542

1589-
def to_svg(self, offset=None):
1590-
l = self.style.get_line_width(face_element=False)
1591-
style = create_css(edge_color=self.edge_color, stroke_width=l)
1592-
svg = ""
1593-
for line in self.lines:
1594-
svg += '<polyline points="%s" style="%s" />' % (
1595-
" ".join(["%f,%f" % coords.pos() for coords in line]),
1596-
style,
1597-
)
1598-
return svg
1599-
16001543
def to_asy(self):
16011544
l = self.style.get_line_width(face_element=False)
16021545
pen = create_pens(edge_color=self.edge_color, stroke_width=l)
@@ -1741,16 +1684,6 @@ def init(self, graphics, style, item, options):
17411684
raise BoxConstructError
17421685
self.spline_degree = spline_degree.get_int_value()
17431686

1744-
def to_svg(self, offset=None):
1745-
l = self.style.get_line_width(face_element=False)
1746-
style = create_css(edge_color=self.edge_color, stroke_width=l)
1747-
1748-
svg = ""
1749-
for line in self.lines:
1750-
s = " ".join(_svg_bezier((self.spline_degree, [xy.pos() for xy in line])))
1751-
svg += '<path d="%s" style="%s"/>' % (s, style)
1752-
return svg
1753-
17541687
def to_asy(self):
17551688
l = self.style.get_line_width(face_element=False)
17561689
pen = create_pens(edge_color=self.edge_color, stroke_width=l)
@@ -1828,22 +1761,6 @@ def parse_component(segments):
18281761
else:
18291762
raise BoxConstructError
18301763

1831-
def to_svg(self, offset=None):
1832-
l = self.style.get_line_width(face_element=False)
1833-
style = create_css(
1834-
edge_color=self.edge_color, face_color=self.face_color, stroke_width=l
1835-
)
1836-
1837-
def components():
1838-
for component in self.components:
1839-
transformed = [(k, [xy.pos() for xy in p]) for k, p in component]
1840-
yield " ".join(_svg_bezier(*transformed)) + " Z"
1841-
1842-
return '<path d="%s" style="%s" fill-rule="evenodd"/>' % (
1843-
" ".join(components()),
1844-
style,
1845-
)
1846-
18471764
def to_asy(self):
18481765
l = self.style.get_line_width(face_element=False)
18491766
pen = create_pens(edge_color=self.edge_color, stroke_width=l)
@@ -1933,32 +1850,6 @@ def process_option(self, name, value):
19331850
else:
19341851
raise BoxConstructError
19351852

1936-
def to_svg(self, offset=None):
1937-
l = self.style.get_line_width(face_element=True)
1938-
if self.vertex_colors is None:
1939-
face_color = self.face_color
1940-
else:
1941-
face_color = None
1942-
style = create_css(
1943-
edge_color=self.edge_color, face_color=face_color, stroke_width=l
1944-
)
1945-
svg = ""
1946-
if self.vertex_colors is not None:
1947-
mesh = []
1948-
for index, line in enumerate(self.lines):
1949-
data = [
1950-
[coords.pos(), color.to_js()]
1951-
for coords, color in zip(line, self.vertex_colors[index])
1952-
]
1953-
mesh.append(data)
1954-
svg += '<meshgradient data="%s" />' % json.dumps(mesh)
1955-
for line in self.lines:
1956-
svg += '<polygon points="%s" style="%s" />' % (
1957-
" ".join("%f,%f" % coords.pos() for coords in line),
1958-
style,
1959-
)
1960-
return svg
1961-
19621853
def to_asy(self):
19631854
l = self.style.get_line_width(face_element=True)
19641855
if self.vertex_colors is None:
@@ -2617,35 +2508,6 @@ def extent(self):
26172508
y = p[1] - h / 2.0 + opos[1] * h / 2.0
26182509
return [(x, y), (x + w, y + h)]
26192510

2620-
def to_svg(self, offset=None):
2621-
x, y = self.pos.pos()
2622-
if offset:
2623-
x = x + offset[0]
2624-
y = y + offset[1]
2625-
2626-
if hasattr(self.content, "to_svg"):
2627-
content = self.content.to_svg(noheader=True, offset=(x, y))
2628-
svg = "\n" + content + "\n"
2629-
else:
2630-
css_style = create_css(
2631-
font_color=self.color,
2632-
edge_color=self.color,
2633-
face_color=self.color,
2634-
opacity=self.opacity,
2635-
)
2636-
text_pos_opts = f'x="{x}" y="{y}" ox="{self.opos[0]}" oy="{self.opos[1]}"'
2637-
# FIXME: don't hard code text_style_opts, but allow these to be adjustable.
2638-
text_style_opts = "text-anchor:middle; dominant-baseline:middle;"
2639-
content = self.content.boxes_to_text(evaluation=self.graphics.evaluation)
2640-
svg = f'<text {text_pos_opts} style="{text_style_opts} {css_style}">{content}</text>'
2641-
2642-
# content = self.content.boxes_to_mathml(evaluation=self.graphics.evaluation)
2643-
# style = create_css(font_color=self.color)
2644-
# svg = (
2645-
# '<foreignObject x="%f" y="%f" ox="%f" oy="%f" style="%s">'
2646-
# "<math>%s</math></foreignObject>")
2647-
2648-
return svg
26492511

26502512
def to_asy(self):
26512513
x, y = self.pos.pos()
@@ -2960,9 +2822,6 @@ def extent(self, completely_visible_only=False):
29602822
ymax *= 2
29612823
return xmin, xmax, ymin, ymax
29622824

2963-
def to_svg(self, offset=None):
2964-
return "\n".join(element.to_svg(offset) for element in self.elements)
2965-
29662825
def to_asy(self):
29672826
return "\n".join(element.to_asy() for element in self.elements)
29682827

@@ -3265,7 +3124,11 @@ def to_svg(self, leaves=None, **options):
32653124

32663125
elements.view_width = w
32673126

3268-
svg = elements.to_svg(offset=options.get("offset", None))
3127+
format_fn = lookup_method(elements, "svg")
3128+
if format_fn is not None:
3129+
svg = format_fn(elements)
3130+
else:
3131+
svg = elements.to_svg(offset=options.get("offset", None))
32693132

32703133
if self.background_color is not None:
32713134
svg = '<rect x="%f" y="%f" width="%f" height="%f" style="fill:%s"/>%s' % (

mathics/core/definitions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ def __init__(
8484

8585
if add_builtin:
8686
from mathics.builtin import modules, contribute
87-
from mathics.core.evaluation import Evaluation
8887
from mathics.settings import ROOT_DIR
8988

9089
loaded = False
@@ -126,6 +125,7 @@ def __init__(
126125
self.builtin.update(self.user)
127126
self.user = {}
128127
self.clear_cache()
128+
import mathics.formatter.svg
129129

130130
def load_pymathics_module(self, module, remove_on_quit=True):
131131
"""

mathics/core/formatter.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# key is str: to_xxx name, value is formatter function to call
2+
format2fn = {}
3+
import inspect
4+
5+
def lookup_method(self, format: str):
6+
for cls in inspect.getmro(type(self)):
7+
format_fn = format2fn.get(("svg", cls), None)
8+
if format_fn is not None:
9+
return format_fn
10+
raise RuntimeError(f"Can't find formatter {format} for {type(self)}")

mathics/formatter/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)