Merge branch 'subtree'
[fanfix.git] / src / be / nikiroo / fanfix / output / LaTeX.java
CommitLineData
08fe2e33
NR
1package be.nikiroo.fanfix.output;
2
3d247bc3 3import java.io.BufferedWriter;
08fe2e33 4import java.io.File;
3d247bc3 5import java.io.FileOutputStream;
08fe2e33 6import java.io.IOException;
3d247bc3 7import java.io.OutputStreamWriter;
08fe2e33
NR
8
9import be.nikiroo.fanfix.Instance;
10import be.nikiroo.fanfix.bundles.Config;
11import be.nikiroo.fanfix.bundles.StringId;
12import be.nikiroo.fanfix.data.Chapter;
13import be.nikiroo.fanfix.data.MetaData;
08fe2e33 14import be.nikiroo.fanfix.data.Paragraph.ParagraphType;
3d247bc3 15import be.nikiroo.fanfix.data.Story;
08fe2e33
NR
16
17class LaTeX extends BasicOutput {
3d247bc3 18 protected BufferedWriter writer;
08fe2e33
NR
19 private boolean lastWasQuote = false;
20
21 // quote chars
d66deb8d
NR
22 private char openQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_SINGLE_QUOTE);
23 private char closeQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_SINGLE_QUOTE);
24 private char openDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.OPEN_DOUBLE_QUOTE);
25 private char closeDoubleQuote = Instance.getInstance().getTrans().getCharacter(StringId.CLOSE_DOUBLE_QUOTE);
08fe2e33
NR
26
27 @Override
28 public File process(Story story, File targetDir, String targetName)
29 throws IOException {
30 String targetNameOrig = targetName;
10d558d2 31 targetName += getDefaultExtension(false);
08fe2e33
NR
32
33 File target = new File(targetDir, targetName);
34
3d247bc3
NR
35 writer = new BufferedWriter(new OutputStreamWriter(
36 new FileOutputStream(target), "UTF-8"));
08fe2e33
NR
37 try {
38 super.process(story, targetDir, targetNameOrig);
39 } finally {
40 writer.close();
41 writer = null;
42 }
43
44 return target;
45 }
46
47 @Override
10d558d2 48 public String getDefaultExtension(boolean readerTarget) {
08fe2e33
NR
49 return ".tex";
50 }
51
52 @Override
53 protected void writeStoryHeader(Story story) throws IOException {
54 String date = "";
55 String author = "";
56 String title = "\\title{}";
57 String lang = "";
58 if (story.getMeta() != null) {
59 MetaData meta = story.getMeta();
60 title = "\\title{" + latexEncode(meta.getTitle()) + "}";
61 date = "\\date{" + latexEncode(meta.getDate()) + "}";
62 author = "\\author{" + latexEncode(meta.getAuthor()) + "}";
63 lang = meta.getLang().toLowerCase();
64 if (lang != null && !lang.isEmpty()) {
d66deb8d 65 lang = Instance.getInstance().getConfig().getStringX(Config.CONF_LATEX_LANG, lang);
08fe2e33 66 if (lang == null) {
d66deb8d 67 System.err.println(Instance.getInstance().getTrans().getString(StringId.LATEX_LANG_UNKNOWN, lang));
08fe2e33
NR
68 }
69 }
70 }
71
72 writer.append("%\n");
73 writer.append("% This LaTeX document was auto-generated by Fanfic Reader, created by Niki.\n");
74 writer.append("%\n\n");
75 writer.append("\\documentclass[a4paper]{book}\n");
76 if (lang != null && !lang.isEmpty()) {
77 writer.append("\\usepackage[" + lang + "]{babel}\n");
78 }
79 writer.append("\\usepackage[utf8]{inputenc}\n");
80 writer.append("\\usepackage[T1]{fontenc}\n");
81 writer.append("\\usepackage{lmodern}\n");
82 writer.append("\\newcommand{\\br}{\\vspace{10 mm}}\n");
83 writer.append("\\newcommand{\\say}{--- \\noindent\\emph}\n");
84 writer.append("\\hyphenpenalty=1000\n");
85 writer.append("\\tolerance=5000\n");
86 writer.append("\\begin{document}\n");
87 if (story.getMeta() != null && story.getMeta().getDate() != null)
88 writer.append(date + "\n");
89 writer.append(title + "\n");
90 writer.append(author + "\n");
91 writer.append("\\maketitle\n");
92 writer.append("\n");
93
94 // TODO: cover
95 }
96
97 @Override
98 protected void writeStoryFooter(Story story) throws IOException {
99 writer.append("\\end{document}\n");
100 }
101
102 @Override
103 protected void writeChapterHeader(Chapter chap) throws IOException {
104 writer.append("\n\n\\chapter{" + latexEncode(chap.getName()) + "}"
105 + "\n");
106 }
107
108 @Override
109 protected void writeChapterFooter(Chapter chap) throws IOException {
110 writer.write("\n");
111 }
112
113 @Override
114 protected String enbold(String word) {
115 return "\\textsc{" + word + "}";
116 }
117
118 @Override
119 protected String italize(String word) {
120 return "\\emph{" + word + "}";
121 }
122
123 @Override
124 protected void writeTextLine(ParagraphType type, String line)
125 throws IOException {
126
127 line = decorateText(latexEncode(line));
128
129 switch (type) {
130 case BLANK:
131 writer.write("\n");
132 lastWasQuote = false;
133 break;
134 case BREAK:
135 writer.write("\n\\br");
136 writer.write("\n");
137 lastWasQuote = false;
138 break;
139 case NORMAL:
140 writer.write(line);
141 writer.write("\n");
142 lastWasQuote = false;
143 break;
144 case QUOTE:
145 writer.write("\n\\say{" + line + "}\n");
146 if (lastWasQuote) {
147 writer.write("\n\\noindent{}");
148 }
149 lastWasQuote = true;
150 break;
151 case IMAGE:
17625a9f 152 // TODO what about images in LaTeX?
08fe2e33
NR
153 break;
154 }
155 }
156
157 private String latexEncode(String input) {
158 StringBuilder builder = new StringBuilder();
159 for (char car : input.toCharArray()) {
160 // TODO: check restricted chars?
161 if (car == '^' || car == '$' || car == '\\' || car == '#'
162 || car == '%') {
163 builder.append('\\');
164 builder.append(car);
165 } else if (car == openQuote) {
166 builder.append('`');
167 } else if (car == closeQuote) {
168 builder.append('\'');
169 } else if (car == openDoubleQuote) {
170 builder.append("``");
171 } else if (car == closeDoubleQuote) {
172 builder.append("''");
173 } else {
174 builder.append(car);
175 }
176 }
177
178 return builder.toString();
179 }
180}