[Therion] Custom label style for a custom point

Tarquin Wilton-Jones tarquin.wilton-jones at ntlworld.com
Wed Nov 27 18:20:00 CET 2019


I think I actually might have got it...

Pretty sure that some optimisations are possible; eg. I am using a set
of hardcoded S numbers -> TEX sizing strings. There might be an inbuilt
method to do that for you, but I couldn't immediately see it. I don't
know if these numbers are subject to change either - do different base
scales change the value of S, for example?

But it works. You can set the size of the text, the ornamentation of the
text (using Therion's inbuilt string->TEX functionality), and the
alignment of the text. Some ornamentation styles do not respect rotation
- that is a bug in Therion's text processing. Perhaps someone will now
point out a glaring problem (like strings containing \foo or } which I
think will break the TEX, but I also think this happens elsewhere in
Therion...). But hopefully this gives a nice base for other people who
needed this functionality to work from.

I don't quite know what the "\framed { text here }" part does, since it
seems to have no effect, but Therion uses it for all of the ornamented
labels but not for basic labels.

vardef create_styled_label (expr plaintext,P,R,S,A,defaultstyle)=
  save textsize, style;
  string textsize;
  if S = 0.5:
    textsize:="\thtinysize";
  elseif S = 0.7:
    textsize:="\thsmallsize";
  elseif S = 1.4:
    textsize:="\thlargesize";
  elseif S = 2:
    textsize:="\thhugesize";
  else: % normal is 1
    textsize:="\thnormalsize";
  fi;
  if known ATTR_labelstyle:
    style:=scantokens(ATTR_labelstyle);
  else:
    style:=defaultstyle;
  fi;
  picture thetext;
  thetext:=thTEX("\thframed {" & textsize & plaintext & "}");
  if A = (-1,1):
    p_label.ulft(thetext,P,R,style);
  elseif A = (0,1):
    p_label.top(thetext,P,R,style);
  elseif A = (1,1):
    p_label.urt(thetext,P,R,style);
  elseif A = (-1,0):
    p_label.lft(thetext,P,R,style);
  elseif A = (1,0):
    p_label.rt(thetext,P,R,style);
  elseif A = (-1,-1):
    p_label.llft(thetext,P,R,style);
  elseif A = (0,-1):
    p_label.bot(thetext,P,R,style);
  elseif A = (1,-1):
    p_label.lrt(thetext,P,R,style);
  else:
    p_label(thetext,P,R,style);
  fi;
enddef;

def p_u_ropelength (expr P,R,S,A)=
  T:=identity shifted P;
  U:=(0,0);
  if known ATTR_text:
    % approximate size (varies with proportional font)
    U:=(S*u*(length ATTR_text)/4,S*u*(length ATTR_text)/4);
    create_styled_label(ATTR_text,P,R,S,A,p_label_mode_passageheight);
  fi;
enddef;
initsymbol("p_u_ropelength");

You can see that all it does is to produce the right TEX string (so it
respects scaling), and then calls the right version of p_label (so it
respects alignment). It relies on p_label to support rotation. If the
symbol has "-attr labelstyle 5" it will use that label style.

There is then an example point symbol that uses it with a string stored
in "-attr text", and sets its T and U accordingly. However, there is no
requirement for it to be a dedicated point symbol - you could just as
easily call it to put a label anywhere you choose, such as beside some
existing symbol (so you could have a warning triangle symbol, with some
text in a box beside it, for example).

Aside;
One other issue with replacing the p_label macro like Stacho suggested
is that you end up using a small chunk of the existing Therion code.
This in turn means that you need to license all of yours under GPL
(because it is GPL not LGPL). If your survey is intended to be released
under some other license, you can't make a derivative work from a chunk
of Therion code.



More information about the Therion mailing list