Recently, I switched from XeTeX to LuaTex for a document of mine. However, there is a feature which I do not immediately see how to convert: Accessing specific characters. In particular, I need the upright double quote. In the font I use, however, the standard \dq command produces upper 99 quotes. In XeTeX, I therefore redefined the command:

  1. How can I do that in general, ie. how can I access all the glyphs in the font, whereever they might be placed (even without a codepoint, perhaps)?
  2. Is there another way to access the upright double quote?

You should be able to enter any characters from your font directly into your source, just like in XeTeX. With respect to the double upright quote, you need to load the font without the [Ligatures=TeX] option (or if you want the most of the TeX replacements, but not the " replacement, you can specifically turn off the TeX quote replacement feature:)

\setmainfont[Ligatures=TeX,RawFeature=-trep]{Linux Libertine O}
"This is in upright quotes but will preserve e.g. --- replacement"

"This has replaced quotes"

"This is in upright quotes and doesn't preserve e.g. --- replacement"

The raw features are described in the luaotfload manual; the rest is plain fontspec. The default behaviour (if you don't load a font explicitly) is to turn on both features so as to mimic standard TeX behaviour.

  • Thank you for the pointer to luaotfload. I’m very reluctant to drop Ligatures at this stage of the document process (not for my own text, but for packages relying on them, such as BibTeX), but luckily local changes to font features are easy enough. – MPi Jan 24 '11 at 14:21
  • @MPi If you're going to be doing this quite a bit, you should use \newfontfamily to define a version of your font with the quote replacement removed. e.g. \newfontfamily\nolig[RawFeature=-trep;-tlig]{Linux Libertine O} and then use \nolig (perhaps inside an environment) when you need to use the upright quotes. – Alan Munn Jan 24 '11 at 14:50
  • @ Alan: no need for RawFeature=-trep;-tlig if you don't explicitly ask for Ligatures=TeX it will not be activated. – Khaled Hosny Jan 24 '11 at 15:30
  • @Khaled That seems to be partially true: if you don't explicitly set the font, it seems that fontspec (or luaotfload) loads the default font with ligatures enabled. It's true that if you use \setmainfont with no options, the replacements aren't activated. – Alan Munn Jan 24 '11 at 15:51
  • @Alan: I was specifically referring to the comment above mine. – Khaled Hosny Jan 24 '11 at 16:03

Assuming you are using luaotfload (which is true if you are using fontspec as well), you can use the lua function fonts.otf.char() which takes either glyph name or glyph index, e.g.:

\setmainfont{TeX Gyre Pagella}


  • This is the perfect answer for part one, but unfortunately for my specific problem, it did not help, at least not without also disabling the TeX ligatures as suggested in the other answer. – MPi Jan 24 '11 at 14:23
  • @ MPi: I don't usually use Ligature=TeX, and your question lacks a complete example and one can't guess your setup :) – Khaled Hosny Jan 24 '11 at 15:27
  • No offence meant, I even upvoted your answer although I accepted the other. I didn’t post a complete example since I couldn’t imagine it would matter. I used XeTeX together with Ligatures and the above XeTeXglyph produced the letter I requested instead of some substitute. Rather the effect I would expect. I find the XeTeX semantics a bit more sensible here than the LuaTeX semantics. – MPi Jan 24 '11 at 21:00
  • @MPi: No offence taken. The difference is that XeTeX's mapping (which what is really used when you specify Ligatures=TeX) works at character level, i.e. all " in your input are converted to curly quotes and that is passed to TeX, so when you insert a glyph it does not see it, while luaotfload's trep works as a font feature and thus gets applied much later in the process and thus it sees your " glyph node and acts on it, no matter how that node ended there. – Khaled Hosny Jan 24 '11 at 21:51
  • 2
    @KhaledHosny, fonts.otf.char doesn’t work anymore, it seems. Q120736 has a working, but much longer solution. – Crissov Jul 14 '14 at 19:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.