Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2""" 

3@file 

4@brief Various functions about :epkg:`blockdiag`. 

5 

6.. versionadded:: 1.1 

7""" 

8import os 

9import io 

10import glob 

11 

12 

13def _create_fontmap(fontmap, font): 

14 """ 

15 Inspired from :epkg:`blockdiag` source file (*_bootstrap.py*). 

16 """ 

17 from blockdiag.utils.fontmap import FontMap 

18 fontmap = FontMap(fontmap) 

19 if fontmap.find().path is None or font: 

20 fontpath = _detectfont(font) 

21 fontmap.set_default_font(fontpath) 

22 return fontmap 

23 

24 

25def _build_diagram(module, builder, drawer, tree, type, code, 

26 fontmap=None, antialias=True, nodoctype=False, 

27 transparency=False, size=None): 

28 """ 

29 Inspired from :epkg:`blockdiag` source file (*_bootstrap.py*). 

30 """ 

31 ScreenNodeBuilder = builder.ScreenNodeBuilder 

32 diagram = ScreenNodeBuilder.build(tree, None) 

33 

34 DiagramDraw = drawer.DiagramDraw 

35 drawer = DiagramDraw(type, diagram, fontmap=fontmap, 

36 code=code, antialias=antialias, 

37 nodoctype=nodoctype, transparency=transparency) 

38 drawer.draw() 

39 

40 if size: 

41 return drawer.save(size=size) 

42 else: 

43 return drawer.save() 

44 

45 

46def _detectfont(font): 

47 fontdirs = [ 

48 '/usr/share/fonts', 

49 '/Library/Fonts', 

50 '/System/Library/Fonts', 

51 'c:/windows/fonts', 

52 '/usr/local/share/font-*', 

53 ] 

54 fontfiles = [ 

55 'ipagp.ttf', 

56 'ipagp.otf', 

57 'VL-PGothic-Regular.ttf', 

58 'Hiragino Sans GB W3.otf', 

59 'AppleGothic.ttf', 

60 'msgothic.ttf', 

61 'msgoth04.ttf', 

62 'msgothic.ttc', 

63 ] 

64 

65 fontpath = None 

66 if font: 

67 from blockdiag.utils.fontmap import parse_fontpath 

68 for path in font: 

69 _path, _ = parse_fontpath(path) 

70 if os.path.isfile(_path): 

71 fontpath = path 

72 break 

73 else: 

74 msg = 'fontfile is not found: %s' % font 

75 raise RuntimeError(msg) 

76 

77 if fontpath is None: 

78 globber = (glob.glob(d) for d in fontdirs) 

79 for fontdir in sum(globber, []): 

80 for root, _, files in os.walk(fontdir): 

81 for font_ in fontfiles: 

82 if font_ in files: 

83 fontpath = os.path.join(root, font_) 

84 break 

85 

86 return fontpath 

87 

88 

89def draw_diagram(graph, module="blockdiag", format="pillow", **options): 

90 """ 

91 Draws a graph based on module :epkg:`blockdiag`. 

92 

93 @param graph graph definition, 

94 see `syntax <http://blockdiag.com/en/blockdiag/examples.html>`_ 

95 @param module ``'blockdiag'`` (only available value) 

96 @param format can be a filename or a module name (``'pillow'``) 

97 @param options additional options for :epkg:`blockdiag` 

98 @return graph 

99 

100 :: 

101 

102 blockdiag { 

103 A -> B -> C -> D; 

104 A -> E -> F -> G; 

105 } 

106 

107 See notebook :ref:`drawdiagramrst`. 

108 """ 

109 if module == "blockdiag": 

110 import blockdiag # pylint: disable=C0415 

111 module = blockdiag 

112 import blockdiag.parser # pylint: disable=C0415 

113 parser = blockdiag.parser 

114 import blockdiag.builder # pylint: disable=C0415 

115 builder = blockdiag.builder 

116 import blockdiag.drawer # pylint: disable=C0415 

117 drawer = blockdiag.drawer 

118 else: 

119 raise ValueError( 

120 "Unexected value for 'blockdiag': '{0}'".format(module)) 

121 

122 if format in ("pillow", "png"): 

123 ftype = "png" 

124 elif format == "svg": 

125 ftype = "svg" 

126 else: 

127 raise ValueError("format should in ['pillow', 'svg']") 

128 

129 fontmap = _create_fontmap(fontmap=options.get('fontmap', None), 

130 font=options.get('font', None)) 

131 tree = parser.parse_string(graph) 

132 res = _build_diagram(module=module, builder=builder, drawer=drawer, 

133 tree=tree, code=graph, fontmap=fontmap, type=ftype, 

134 antialias=options.get('antialias', True), 

135 nodoctype=options.get('nodoctype', False), 

136 transparency=options.get('transparency', False), 

137 size=options.get('size', None)) 

138 if format == "pillow": 

139 from PIL import Image 

140 image = Image.open(io.BytesIO(res)) 

141 return image 

142 else: 

143 return res