Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import xml.dom.minidom;
- import os;
- import math;
- import svgwrite;
- import kanji_lists;
- from svgwrite import cm, mm, rgb;
- # I had trouble rendering the now very css heavy designs in my normal
- # svg to pdf converter - so I now just build them all into one long
- # html file and print them from chrome - see here for a gist that
- # gives the basic idea:
- # https://gist.githubusercontent.com/s417-lama/84bf66de1096c4587e8187092fb41684/raw/e42345dcc91e198ca2983aaef93b87da6a70aa37/svg2pdf.bash
- # you will need a kanjivg archive (e.g. kanjivg-20160426-all.zip ) unpacked
- # locally into the directory kanji/
- # this program depends on the svgwrite and kanji_lists modules, both of which
- # can be obtained from pip
- # still can't make it work? curious.jp@gmail.com
- ## paper dimensions ########################################################
- # a4 sheets of paper are 210x297mm
- # four item coordinates are l, t, r, b
- class Configuration:
- def __init__( self, width = 210, height = 297,
- inner_gutter = (15,15,15,15), outer_gutter = (10,10,10,10),
- box_size = 30,
- label_size = None, label_offset = (15,15),
- stroke_dot_size = None ):
- self.page_width = width;
- self.page_height = height;
- self._inner_gutter = inner_gutter;
- self._outer_gutter = outer_gutter;
- self._box_size = box_size;
- self._label_size = label_size;
- self._label_offset = label_offset;
- self._stroke_dot_size = stroke_dot_size;
- def drawOuterGutter( self, dwg ):
- if( self._outer_gutter == None ):
- return;
- r_l = self._outer_gutter[ 0 ];
- r_t = self._outer_gutter[ 1 ];
- r_r = self.page_width - self._outer_gutter[ 2 ];
- r_b = self.page_height - self._outer_gutter[ 3 ];
- r_w = r_r - r_l;
- r_h = r_b - r_t;
- rectangle = dwg.rect( insert = ( mm( r_l ), mm( r_t ) ),
- size = ( mm( r_w ), mm( r_h ) ),
- fill = "none",
- stroke = "black" );
- dwg.add( rectangle );
- return;
- def drawLabel( self, label, dwg ):
- if( self._label_size == None ):
- return;
- # right aligned
- if( self._label_offset[ 0 ] > self.page_width / 2 ):
- l_s = "dominant-baseline: hanging; text-anchor: end";
- # left aligned
- else:
- l_s = "dominant-baseline: hanging; text-anchor: start";
- l_l, l_t = self._label_offset;
- text = dwg.text( label,
- insert = ( mm( l_l ), mm( l_t ) ),
- font_size = mm( self._label_size ),
- fill = "black",
- stroke = "none",
- style = l_s );
- dwg.add( text );
- return;
- def _getGridDimensions( self ):
- avail_h = self.page_height - self._inner_gutter[ 1 ] - self._inner_gutter[ 3 ];
- boxes_h = math.floor( avail_h / self._box_size );
- avail_w = self.page_width - self._inner_gutter[ 0 ] - self._inner_gutter[ 2 ];
- boxes_w = math.floor( avail_w / self._box_size );
- hline_w = boxes_w * self._box_size;
- hline_l = self._inner_gutter[ 0 ] + ( avail_w - hline_w ) / 2;
- hline_r = hline_l + hline_w;
- vline_h = boxes_h * self._box_size;
- vline_t = self._inner_gutter[ 1 ] + ( avail_h - vline_h ) / 2;
- vline_b = vline_t + vline_h;
- return ( boxes_w, boxes_h, hline_l, hline_r, vline_t, vline_b );
- def drawGrid( self, dwg ):
- boxes_w, boxes_h, hline_l, hline_r, vline_t, vline_b = self._getGridDimensions();
- # vertical guideline
- for col in range( boxes_w ):
- rule = dwg.line( stroke = "lightgrey",
- start = ( mm( hline_l + col * self._box_size + .5 * self._box_size ), mm( vline_t ) ),
- end = ( mm( hline_l + col * self._box_size + .5 * self._box_size ), mm( vline_b ) ),
- stroke_dasharray = "4" );
- dwg.add( rule );
- # vertical box edge
- for col in range( boxes_w + 1 ):
- rule = dwg.line( stroke = "grey",
- start = ( mm( hline_l + col * self._box_size ), mm( vline_t ) ),
- end = ( mm( hline_l + col * self._box_size ), mm( vline_b ) ) );
- dwg.add( rule );
- # horizontal guideline
- for row in range( boxes_h + 1 ):
- rule = dwg.line( stroke = "lightgrey",
- start = ( mm( hline_l ), mm( vline_t + row * self._box_size + 0.5 * self._box_size ) ),
- end = ( mm( hline_r ), mm( vline_t + row * self._box_size + 0.5 * self._box_size ) ),
- stroke_dasharray = "4" );
- dwg.add( rule );
- # horizontal box edge
- for row in range( boxes_h + 1 ):
- rule = dwg.line( stroke = "grey",
- start = ( mm( hline_l ), mm( vline_t + row * self._box_size ) ),
- end = ( mm( hline_r ), mm( vline_t + row * self._box_size ) ) );
- dwg.add( rule );
- return;
- def drawCharacters( self, k, dwg ):
- boxes_w, boxes_h, hline_l, hline_r, vline_t, vline_b = self._getGridDimensions();
- k_viewbox, k_strokes = loadStrokes( k );
- subdrawing = svgwrite.container.SVG( id = "ghost", x = mm( 0 ), y = mm( 0 ),
- size = ( mm( self._box_size ), mm( self._box_size ) ),
- viewBox = k_viewbox,
- style = 'stroke-linecap:round;stroke-linejoin:round', fill = 'none' );
- stroke_counter = 0;
- for stroke in k_strokes:
- subdrawing.add( dwg.path( d = stroke, style="marker-start: var(--stroke-{0}-marker); stroke: var(--stroke-{0}-colour); stroke-width: var(--stroke-{0}-width)".format( stroke_counter ) ) );
- stroke_counter += 1;
- dwg.defs.add( subdrawing );
- marker = dwg.marker( id = "pen_marker", insert = (2, 2), size = (4, 4) );
- marker.add( dwg.circle( ( 2, 2 ), r = 1, fill = 'red' ) );
- dwg.defs.add( marker );
- for stroke in range( len( k_strokes ) ):
- dwg.defs.add( dwg.style( ".tutor{0} {{ --stroke-{0}-colour: black; --stroke-{0}-width: 3; }}".format( stroke ) ) );
- dwg.defs.add( dwg.style( ".finaltutor{0} {{ --stroke-{0}-colour: red; --stroke-{0}-marker: url(#pen_marker); }}".format( stroke ) ) );
- dwg.defs.add( dwg.style( ".grey { stroke: grey; stroke-width: 2; }" ) );
- cell_number = 0;
- for row in range( boxes_h ):
- for col in range( boxes_w ):
- if( cell_number < len( k_strokes ) ):
- css_class_string = " ".join( [ "tutor{0}".format( x ) for x in range( cell_number + 1 ) ] ) + " finaltutor{0} grey".format( cell_number );
- else:
- css_class_string = "grey";
- dwg.add( dwg.use( href="#ghost", class_ = css_class_string, insert = ( mm( hline_l + col * self._box_size ), mm( vline_t + row * self._box_size ) ) ) );
- cell_number += 1;
- return;
- def loadStrokes( kanji ):
- codePoint = ord( kanji[0] );
- codePointFN = os.path.join( "kanji", "{0:05x}.svg".format( codePoint ) );
- kanjiSVG = xml.dom.minidom.parse( codePointFN );
- # obtain the viewport size for scaling purposes
- svgTag = kanjiSVG.getElementsByTagName( "svg" )[ 0 ];
- viewBox = svgTag.getAttribute( "viewBox" );
- # obtain strokes
- strokeLeader = "kvg:{0:05x}-s".format( codePoint );
- strokes = [ ( int( x.getAttribute( "id" ).replace( strokeLeader, "" ) ), x.getAttribute( "d" ) )
- for x in svgTag.getElementsByTagName( "path" )
- if x.getAttribute( "id" ).startswith( strokeLeader ) ];
- return ( viewBox, [ x[1] for x in sorted( strokes, key = lambda y: y[0] ) ] );
- def draw_page( item, filename, config ):
- dwg = svgwrite.Drawing( filename = filename, size = ( mm( config.page_width ), mm( config.page_height ) ) );
- config.drawOuterGutter( dwg );
- config.drawLabel( item, dwg );
- config.drawGrid( dwg );
- config.drawCharacters( item, dwg );
- dwg.save();
- if __name__ == '__main__':
- config = Configuration( outer_gutter = (5,5,5,5), inner_gutter = ( 10, 297/3, 10, 10 ), label_size = 64, label_offset = ( 200, 25 ) );
- index = 0;
- #for item in kanji_lists.JLPT.N5:
- for item in kanji_lists.JOYO:
- fn = "jy-{0}-{1:04}.svg".format( item, index );
- index += 1;
- draw_page( item, fn, config );
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement