我有一个包含如下数据的文本文件:
word: 'Swine'; conf: 92.03;pointsize:'48':,font_name:'Verdana_Bold',X1:'152', X2:'283', Y1: '166', Y2: '202
word: 'flu'; conf: 93.43;pointsize:'48':,font_name:'Verdana_Bold',X1:'299', X2:'354', Y1: '164', Y2: '202
word: 'tightens'; conf: 90.12;pointsize:'48':,font_name:'Verdana_Bold',X1:'370', X2:'551', Y1: '164', Y2: '211
word: 'its'; conf: 96.04;pointsize:'48':,font_name:'Verdana_Bold',X1:'568', X2:'617', Y1: '166', Y2: '202
word: 'grip'; conf: 90.41;pointsize:'48':,font_name:'Verdana_Bold',X1:'632', X2:'716', Y1: '166', Y2: '211
word: 'over'; conf: 94.29;pointsize:'48':,font_name:'Verdana_Bold',X1:'732', X2:'831', Y1: '175', Y2: '202
word: 'India'; conf: 94.00;pointsize:'48':,font_name:'Verdana_Bold',X1:'848', X2:'953', Y1: '164', Y2: '202
其含义如下:
Word: Actual word to be printed
Pointsize : Font size
Font name: Name of font used
X1,X2,Y1,Y2: Coordinates of location of word in the document
我想获取所有这些数据,并将其原封不动地放在 latex 文档中。现在,我知道我必须为此编写一个 C++ 代码,首先打开一个 .tex 文件,然后通过从文本文件中读取数据来开始记录数据。我面临的问题是,如何设置文件中提到的文本的确切字体和大小?谢谢!
编辑:最后,我想使用终端命令从生成的 .tex 文件中创建一个 pdf 文件。另外,我引用了链接:https://priyankacool10.wordpress.com/2012/05/10/creating-tex-file-using-c-program/
我只想知道,为了创建 .tex 文件,我需要在 C++ 代码中编写哪些内容。我不需要完整的 C++ 代码,只需要确切的语法和包详细信息。
示例输出:
编辑2:我需要一个 C++ 代码来从文本文件中读取输入的单词并将其写入 tex 文件。还有其他方法吗?
编辑3:(错误)
* Redefining document command \oldstylenums with arg. spec. 'm' on line 128.
*************************************************
) (/usr/share/texlive/texmf-dist/tex/latex/fontspec/fontspec-luatex.sty
(/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty
! Package fontenc Error: Encoding file `eu2enc.def' not found.
(fontenc) You might have misspelt the name of the encoding.
See the fontenc package documentation for explanation.
Type H <return> for immediate help.
...
l.99 \ProcessOptions*
答案1
看来 TeX 可以直接读取文件,我认为你不需要 C++
如果你输入的文本是,text1.txt
那么上面的内容就是由下面的tex,经过xelatex处理而成的。
\documentclass{article}
\usepackage{fontspec}
\newread\dfile
\openin\dfile=text1.txt
\def\printword#1: '#2'#3pointsize:'#4'#5font_name:'#6'#7\relax{%
\fontsize{#4}{\numexpr#4+6\relax}\selectfont\dofont{#6}#2 }
\def\dofont#1{\csname do #1\endcsname}
\expandafter\def\csname do Verdana_Bold\endcsname{\bfseries\fontspec{Verdana}}
\def\partest{\par}
\begin{document}
\raggedright
\loop
\ifeof\dfile\else
\read\dfile to \tmp
\ifx\tmp\partest
\par
\else
\expandafter\printword\tmp\relax
\fi
\repeat
\end{document}
对于新问题和新数据文件,您需要使用图片模式
虽然对于 48pt 文本来说坐标似乎相当接近,但这确实符合要求吗?
字体可以缩放到指定大小的比例(比如说一半)。
\documentclass{article}
\usepackage{fontspec}
\textwidth60cm
\pdfpagewidth80cm
\makeatletter
\newread\dfile
\openin\dfile=text2.txt
\def\printword#1: '#2'#3pointsize:'#4'#5font_name:'#6'#7\relax{%
\edef\tmp{\zap@space#7 \@empty}%
\expandafter\getcoords\tmp\relax
{\fontsize{#4}{\numexpr#4+6\relax}\selectfont\dofont{#6}#2}}
\def\dofont#1{\csname do #1\endcsname}
\expandafter\def\csname do Verdana_Bold\endcsname{\bfseries\fontspec{Verdana}}
\def\getcoords#1X1:'#2'#3Y1:'#4'#5\relax{%
\typeout{#2/#4}%
\put(#2,4)}
\def\partest{\par}
\begin{document}
\hspace*{-10cm}\begin{picture}(200,200)
\loop
\ifeof\dfile\else
\read\dfile to \tmp
\ifx\tmp\partest
\par
\else
\expandafter\printword\tmp\relax
\fi
\repeat
\end{picture}
\end{document}
答案2
我知道 Python 不是 C++,但我想练习一下这种语言。
即使字体大小缩小了 75% 左右,指定的字体大小和区域位置也不太匹配。因此,我习惯将\resizebox
文本强制为指定区域位置的大小。单词是通过环境放置的\put
。picture
还有更强大的绘图环境,如 TikZ 或pstricks
。但这里不需要高级功能,而且picture
效率更高、速度更快。
坐标经过变换,因为垂直轴的方向与环境所需的 y 值相反picture
。程序计算最小值和最大值,并将左下角设置为新原点。
在设置单词之前,程序会设置一些线条来显示指定的矩形。
可以使用文本文件名作为参数来调用 Python 程序。如果没有参数,则文本数据将从标准输入中获取。输出是标准输出,可以重定向到 TeX 文件。
字体和大小设置经过优化,字体只需定义一次。如果字体发生变化,也只需为一个单词设置字体。
由于有包,生成的文件会用 LuaLaTeX 或 XeLaTeX 进行处理fontspec
。这样就可以更轻松地使用任意字体名称,只要 LuaTeX 或 XeTeX 知道在哪里可以找到它们即可。
有些字符在 TeX 中需要特殊处理,请参阅程序代码作为示例,了解如何处理这些字符。
更优雅一点的方法是将 TeX 序言放入新的 LaTeX 类文件中。这样生成的 TeX 文件就只包含\documentclass{...}
整个序言。
#!/usr/bin/env python
import fileinput;
import re;
line_pattern = re.compile(
r"word:\s*'(?P<word>[^']+)';\s*"
r"conf:\s*[0-9\.]+;\s*"
r"pointsize:\s*'(?P<pointsize>\d+)':,"
r"font_name:\s*'(?P<font_name>[^']+)',\s*"
r"X1:\s*'(?P<X1>\d+)',\s*"
r"X2:\s*'(?P<X2>\d+)',\s*"
r"Y1:\s*'(?P<Y1>\d+)',\s*"
r"Y2:\s*'(?P<Y2>\d+)'\s*")
# Mapping from character to TeX representation
tex_char_map = {}
for c in "%#$&":
tex_char_map[c] = "\\" + c
for c in "_^~\\{}":
tex_char_map[c] = r"\symbol{" + str(ord(c)) + "}"
fonts = set()
words = []
x_min = None
x_max = None
y_min = None
y_max = None
for line in fileinput.input():
match = line_pattern.match(line)
if match:
word = match.group("word")
pointsize = match.group("pointsize")
font_name = match.group("font_name")
X1 = int(match.group("X1"))
X2 = int(match.group("X2"))
Y1 = int(match.group("Y1"))
Y2 = int(match.group("Y2"))
fonts.add(font_name)
data = (word, pointsize, font_name, X1, X2, Y1, Y2)
words.append(data)
# assuming X1 <= X2 and Y1 <= Y2
if x_min is None or X1 < x_min:
x_min = X1
if x_max is None or X2 > x_max:
x_max = X2
if y_min is None or Y1 < y_min:
y_min = Y1
if y_max is None or Y2 > y_max:
y_max = Y2
tex_preamble = r"""\NeedsTeXFormat{LaTeX2e}
\documentclass[border=10pt]{standalone}
\usepackage{fontspec}
\newcommand*{\NewFont}[1]{%
\expandafter\newfontfamily\csname#1\endcsname{#1}%
}
\newcommand*{\SetFont}[1]{%
\csname#1\endcsname
\ignorespaces
}
\newdimen\FontSize
\newdimen\FontUnitLength
\setlength{\FontUnitLength}{.75bp}
\newcommand*{\SetSize}[1]{%
\setlength{\FontSize}{#1\FontUnitLength}%
\fontsize{\FontSize}{1.2\FontSize}\selectfont
\ignorespaces
}
%\usepackage{graphicx}
\newcommand*{\Put}{}
\def\Put(#1,#2)(#3,#4)#5{%
\put(#1,#2){\line(1,0){#3}\line(0,1){#4}}%
\put(#1,#2){\line(0,1){#4}}%
\put(#1,#2){\put(0,#4){\line(1,0){#3}}}%
%\put(#1,#2){\makebox(#3,#4)[lb]{\resizebox{#3\unitlength}{!}{#5}}}%
\put(#1,#2){%
\makebox(#3,#4)[lb]{%
\resizebox{#3\unitlength}{#4\unitlength}{%
\raisebox{\depth}{#5}%
}%
}%
}%
%\put(#1,#2){\makebox(#3,#4)[lb]{#5}}%
}
\setlength{\unitlength}{1bp}"""
print(tex_preamble)
for font in fonts:
print(r"\NewFont{" + font + "}")
print(r"\begin{document}")
picture_width = x_max - x_min
picture_height = y_max - y_min
print(r"\begin{picture}(%d,%d)" % (picture_width, picture_height))
current_font = ""
current_pointsize = ""
for word, pointsize, font_name, X1, X2, Y1, Y2 in words:
if font != current_font:
print(r"\SetFont{" + font + "}")
current_font = font
if pointsize != current_pointsize:
print(r"\SetSize{" + pointsize + "}")
current_pointsize = pointsize
w = ""
for c in word:
if c in tex_char_map:
w += tex_char_map[c]
else:
w += c
width = X2 - X1
height = Y2 - Y1
x = X1 - x_min
y = picture_height - (Y2 - y_min)
print(r"\Put(%d,%d)(%d,%d){%s}" % (x, y, width, height, w))
print(r"\end{picture}")
print(r"\end{document}")
输入数据(为 的值添加了结束单引号Y2
):
word: 'Swine'; conf: 92.03;pointsize:'48':,font_name:'Verdana_Bold',X1:'152', X2:'283', Y1: '166', Y2: '202'
word: 'flu'; conf: 93.43;pointsize:'48':,font_name:'Verdana_Bold',X1:'299', X2:'354', Y1: '164', Y2: '202'
word: 'tightens'; conf: 90.12;pointsize:'48':,font_name:'Verdana_Bold',X1:'370', X2:'551', Y1: '164', Y2: '211'
word: 'its'; conf: 96.04;pointsize:'48':,font_name:'Verdana_Bold',X1:'568', X2:'617', Y1: '166', Y2: '202'
word: 'grip'; conf: 90.41;pointsize:'48':,font_name:'Verdana_Bold',X1:'632', X2:'716', Y1: '166', Y2: '211'
word: 'over'; conf: 94.29;pointsize:'48':,font_name:'Verdana_Bold',X1:'732', X2:'831', Y1: '175', Y2: '202'
word: 'India'; conf: 94.00;pointsize:'48':,font_name:'Verdana_Bold',X1:'848', X2:'953', Y1: '164', Y2: '202'
生成的 LaTeX 文件:
\NeedsTeXFormat{LaTeX2e}
\documentclass[border=10pt]{standalone}
\usepackage{fontspec}
\newcommand*{\NewFont}[1]{%
\expandafter\newfontfamily\csname#1\endcsname{#1}%
}
\newcommand*{\SetFont}[1]{%
\csname#1\endcsname
\ignorespaces
}
\newdimen\FontSize
\newdimen\FontUnitLength
\setlength{\FontUnitLength}{.75bp}
\newcommand*{\SetSize}[1]{%
\setlength{\FontSize}{#1\FontUnitLength}%
\fontsize{\FontSize}{1.2\FontSize}\selectfont
\ignorespaces
}
%\usepackage{graphicx}
\newcommand*{\Put}{}
\def\Put(#1,#2)(#3,#4)#5{%
\put(#1,#2){\line(1,0){#3}\line(0,1){#4}}%
\put(#1,#2){\line(0,1){#4}}%
\put(#1,#2){\put(0,#4){\line(1,0){#3}}}%
%\put(#1,#2){\makebox(#3,#4)[lb]{\resizebox{#3\unitlength}{!}{#5}}}%
\put(#1,#2){%
\makebox(#3,#4)[lb]{%
\resizebox{#3\unitlength}{#4\unitlength}{%
\raisebox{\depth}{#5}%
}%
}%
}%
%\put(#1,#2){\makebox(#3,#4)[lb]{#5}}%
}
\setlength{\unitlength}{1bp}
\NewFont{Verdana_Bold}
\begin{document}
\begin{picture}(801,47)
\SetFont{Verdana_Bold}
\SetSize{48}
\Put(0,9)(131,36){Swine}
\Put(147,9)(55,38){flu}
\Put(218,0)(181,47){tightens}
\Put(416,9)(49,36){its}
\Put(480,0)(84,45){grip}
\Put(580,9)(99,27){over}
\Put(696,9)(105,38){India}
\end{picture}
\end{document}