Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow setting image sizes #218

Merged
merged 14 commits into from
May 10, 2016
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{image: (( content.argument|search_image ))}
{image: "(( content.filename|search_image ))" ((content.size|render_size))}
4 changes: 2 additions & 2 deletions patacrep/data/templates/songs/chordpro/latex/content_image
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(* block image *)
(* set image = content.argument|search_image|path2posix *)
(* set image = content.filename|search_image|path2posix *)
(* if image *)
\image{(( image ))}
\image[(( content.size|render_size ))]{(( image ))}
(*- endif *)
(*- endblock *)
1 change: 1 addition & 0 deletions patacrep/data/templates/styles/patacrep.sty
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
\NeedsTeXFormat{LaTeX2e}[1994/06/01]
\ProvidesPackage{patacrep}[2014/06/17 Patacrep Package, version 1]

\RequirePackage[space]{grffile}
\RequirePackage{graphicx,xcolor} %
\RequirePackage{epstopdf} %
\RequirePackage{fancybox}
Expand Down
39 changes: 39 additions & 0 deletions patacrep/songs/chordpro/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def _filters(self):
'search_partition': self.search_partition,
'escape_specials': self._escape_specials,
'escape_url': self._escape_url,
'render_size': self._render_size,
})
return filters

Expand Down Expand Up @@ -94,6 +95,10 @@ def _render_ast(context, content):
context.vars['content'] = content
return context.environment.get_template(content.template()).render(context)

@staticmethod
def _render_size(size):
raise NotImplementedError()

def _escape_specials(self, content, chars=None, *, translation_map=None):
if translation_map is None:
translation_map = self._translation_map
Expand Down Expand Up @@ -124,6 +129,10 @@ def search_file(self, filename, extensions=None, *, datadirs=None):
)
return None

@staticmethod
def _render_size(size):
return "TODO"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Serais-ce un reste de développement ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non, un TODO pour #109. Mais c'est mal supposer que le rendu html utilisera aussi ce filtre jinja2. Corrigé : 5f05d8c.


class Chordpro2LatexSong(ChordproSong):
"""Render chordpro song to latex code"""

Expand Down Expand Up @@ -203,6 +212,20 @@ def lang2babel(self, lang):
self.errors.append(new_error)
return error.babel

@staticmethod
def _render_size(size):
if size is None:
return ""
if size[0] == "size":
sizelist = []
if size[1] != (None, None):
sizelist.append("width=" + "".join(size[1]))
if size[2] != (None, None):
sizelist.append("height=" + "".join(size[2]))
return ", ".join(sizelist)
if size[0] == "scale":
return "scale=" + size[1]

class Chordpro2ChordproSong(ChordproSong):
"""Render chordpro song to chordpro code"""

Expand All @@ -223,6 +246,22 @@ def search_file(self, filename, extensions=None, *, datadirs=None):
# pylint: disable=unused-variable
return filename

@staticmethod
def _render_size(size):
if size is None:
return ""
if size[0] == "size":
text = "size="
if size[1] != (None, None):
text += "".join(size[1])
text += "x"
if size[2] != (None, None):
text += "".join(size[2])
return text
if size[0] == "scale":
return "scale=" + size[1]


SONG_RENDERERS = {
"tsg": {
'csg': Chordpro2LatexSong,
Expand Down
14 changes: 14 additions & 0 deletions patacrep/songs/chordpro/ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,20 @@ def pretty_key(self):
def __str__(self):
return None

class Image(Directive):
"""An image

.. attribute:: filename
The filename of the image.
.. attribute:: size
A tuple of ``(width, height)`` of the image. Both can be ``None``.
"""

def __init__(self, filename, size=None):
self.filename = filename
self.size = size
super().__init__("image", None)

class Tab(AST):
"""Tablature"""

Expand Down
77 changes: 76 additions & 1 deletion patacrep/songs/chordpro/syntax.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import logging
import re
import shlex

import ply.yacc as yacc

Expand Down Expand Up @@ -124,10 +125,62 @@ def _parse_define(groups):
fingers=fingers,
)

def _parse_image_size(self, argument, *, lineno):
if argument is None:
return None
if argument.startswith("size="):
match = re.compile(
r"""
^
size=
((?P<widthvalue>\d*\.\d+|\d+)(?P<widthunit>%|cm|em|pt))?
x
((?P<heightvalue>\d*\.\d+|\d+)(?P<heightunit>%|cm|em|pt))?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idée spontanée (mais pas forcément réfléchie) : est-ce que le x ne pourrait pas faire partie de la ligne 138 actuelle?

r"""
^
    size=
    ((?P<heightvalue>\d*\.\d+|\d+)(?P<heightunit>%|cm|em|pt))?
    (x(?P<heightvalue>\d*\.\d+|\d+)(?P<heightunit>%|cm|em|pt))?
"""

Ainsi size=3cm est valide (et impose seulement la largeur).


Autre proposition (totalement indépendante) : remplacer le x par *
2cm*3cm à la place de 2cmx3cm

En revanche, si seule la hauteur est personnalisée, ça donne size=*3cm, ce qui pe paraître assez bizarre)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pour le size=3cm, ça ne me parait pas évident que le 3cm désigne la largeur et non pas la hauteur. C'est pour ça que j'ai imposé le size=3cmx, qui n'est pas ambigü. Mais si tu préfères, le x peut être optionnel : avec ma pataretraite qui est proche, vu que c'est vous qui allez gérer, autant faire comme vous le souhaitez.

Pour remplacer le x par *, c'est possible, on peut aussi autoriser les deux. Comme tu veux.

$
""",
re.VERBOSE
).match(argument)
if match is None:
self.error(
line=lineno,
message="Cannot parse image size '{}'.".format(argument),
)
return None
groupdict = match.groupdict()
return (
'size',
(groupdict['widthvalue'], groupdict['widthunit']),
(groupdict['heightvalue'], groupdict['heightunit']),
)
elif argument.startswith("scale="):
match = re.compile(
r"""
^
scale=
(?P<scale>\d*\.\d+|\d+)
$
""",
re.VERBOSE
).match(argument)
if match is None:
self.error(
line=lineno,
message="Cannot parse image size '{}'.".format(argument),
)
return None
return ('scale', match.groupdict()['scale'])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Est-ce qu'il y a une différence entre : size=200%x et scale=2 ?

Si il n'y en a pas, est-ce que cela pourrait être un motif pour garder seulement size ? (et abandonner scale)

Copy link
Contributor Author

@paternal paternal May 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

En fait, size=200%x n'est plus valide, et devrait être abandonné. Par contre, tu me fais penser qu'on peut remplacer l'option scale=2 par size=200%. Je ferai cela quand j'aurai le temps.

Comme expliqué plus haut, on ne peut pas définir une largeur ou hauteur relative (mais seulement une échelle globale relative), parce que cela autoriserait size=200%x300%, ce qui est trop compliqué à faire en LaTeX.

Du coup, ça me fait penser que le size= n'est plus nécessaire : on pourrait écrire {image: foo.png 2cmx3cm} plutôt que {image: foo.png size=2cmx3cm}, mais je n'arrive pas à savoir si c'est mieux ou pas.

self.error(
line=lineno,
message="Cannot parse image size '{}'.".format(argument),
)
return None


def p_directive(self, symbols):
"""directive : LBRACE KEYWORD directive_next RBRACE
| LBRACE SPACE KEYWORD directive_next RBRACE
"""
# pylint: disable=too-many-branches
if len(symbols) == 5:
keyword = symbols[2]
argument = symbols[3]
Expand Down Expand Up @@ -171,7 +224,29 @@ def p_directive(self, symbols):
symbols[0] = ast.Error()
return
self._directives.append(define)

elif keyword == "image":
splitted = shlex.split(argument)
if len(splitted) < 1:
self.error(
line=symbols.lexer.lineno,
message="Missing filename for image directive",
)
symbols[0] = ast.Error()
else:
if len(splitted) > 2:
self.error(
line=symbols.lexer.lineno,
message=(
"Ignoring extra arguments for image directive: " +
" ".join(['"{}"'.format(arg) for arg in splitted[2:]])
),
)
if len(splitted) == 1:
splitted.append(None)
symbols[0] = ast.Image(
splitted[0],
self._parse_image_size(splitted[1], lineno=symbols.lexer.lineno),
)
else:
directive = ast.Directive(keyword, argument)
if directive.inline:
Expand Down
8 changes: 4 additions & 4 deletions test/test_book/datadir.tex.control
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ Chordpro}[


\lilypond{scores/datadir.ly}
\image{img/datadir.png}
\image[]{img/datadir.png}


\endsong
Expand All @@ -138,7 +138,7 @@ Chordpro}[


\lilypond{scores/datadir2.ly}
\image{img/datadir2.png}
\image[]{img/datadir2.png}


\endsong
Expand All @@ -165,7 +165,7 @@ Chordpro}[


\lilypond{@TEST_FOLDER@/datadir_datadir/songs/./relative.ly}
\image{@TEST_FOLDER@/datadir_datadir/songs/./relative.png}
\image[]{@TEST_FOLDER@/datadir_datadir/songs/./relative.png}


\endsong
Expand All @@ -192,7 +192,7 @@ Chordpro}[


\lilypond{@TEST_FOLDER@/datadir_datadir/songs/./subdir/subdir.ly}
\image{@TEST_FOLDER@/datadir_datadir/songs/./subdir/subdir.png}
\image[]{@TEST_FOLDER@/datadir_datadir/songs/./subdir/subdir.png}


\endsong
Expand Down
64 changes: 61 additions & 3 deletions test/test_book/syntax.tex.control
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@





%% Automatically generated document.
%% You may edit this file but all changes will be overwritten.
%% If you want to change this document, have a look at
Expand Down Expand Up @@ -91,6 +89,66 @@ guitar,
\addcontentsline{toc}{section}{\songlistname}

\begin{songs}{titleidx,authidx}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% songs/./images.csg

\selectlanguage{english}

\beginsong{}[
by={
},
]


\image[]{img/image.png}
\image[]{img/image with spaces.png}



\image[scale=.2]{img/image.png}
\image[scale=.20]{img/image with spaces.png}
\image[scale=1.2]{img/image.png}



\image[width=2cm]{img/image.png}
\image[height=2cm]{img/image with spaces.png}
\image[width=2cm, height=1cm]{img/image.png}



\image[width=2em]{img/image.png}
\image[height=2em]{img/image with spaces.png}
\image[width=2em, height=1em]{img/image.png}



\image[width=50pt]{img/image.png}
\image[height=50pt]{img/image with spaces.png}
\image[width=50pt, height=100pt]{img/image.png}



\image[width=2.5cm]{img/image.png}
\image[height=2.5cm]{img/image with spaces.png}
\image[width=2.5cm, height=1.5cm]{img/image.png}



\image[width=3cm, height=10pt]{img/image.png}
\image[width=10pt, height=3cm]{img/image with spaces.png}
\image[]{img/image.png}



\image[]{img/image.png}
\image[]{img/image with spaces.png}
\image[]{img/image with spaces.png}
\image[]{img/image.png}


\endsong

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% songs/./musicnote.csg

Expand All @@ -117,4 +175,4 @@ guitar,



\end{document}
\end{document}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added test/test_book/syntax_datadir/img/image.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
32 changes: 32 additions & 0 deletions test/test_book/syntax_datadir/songs/images.csg
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{image: image.png}
{image: "image with spaces.png"}

{image: image.png scale=.2 }
{image: "image with spaces.png" scale=.20}
{image: image.png scale=1.2}

{image: image.png size=2cmx}
{image: "image with spaces.png" size=x2cm}
{image: image.png size=2cmx1cm}

{image: image.png size=2emx}
{image: "image with spaces.png" size=x2em}
{image: image.png size=2emx1em}

{image: image.png size=50ptx}
{image: "image with spaces.png" size=x50pt}
{image: image.png size=50ptx100pt}

{image: image.png size=2.5cmx}
{image: "image with spaces.png" size=x2.5cm}
{image: image.png size=2.5cmx1.5cm}

{image: image.png size=3cmx10pt}
{image: "image with spaces.png" size=10ptx3cm}
{image: image.png size=x}

{image: image.png error=foo}
{image: "image with spaces.png" not_a_size}
{image: "image with spaces.png" too many arguments}
{image: image.png size=2exx3km}
{image: }
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.