3. Постановка задачи
Передо мной была поставлена задача: создать решение проблемы отображения математических и других формул для форума физико-математического факультета Орловского государственного университета, используя установленный форумный движок phpBB3, издательскую систему TeX, пакет расширений LaTeX и пакет для обработки графических файлов ImageMagick.
Рассмотрим вкратце то, что из перечисленного не было рассмотрено ранее.
LaTeX
LaTeX (произносится как «лэйтех» или «латех» аналогично TeXу; ударение допустимо на любой из слогов) – наиболее популярный набор макрорасширений (или макропакет) к TeX, который облегчает набор сложных документов. Важно заметить, что ни один из макропакетов для TeX'а не может расширить TeX'овских возможностей (всё, что можно сделать в LaTeX’е, можно сделать и в Plain TeX'е), но благодаря различным упрощениям использование макропакетов зачастую позволяет избежать весьма изощрённого программирования.
Пакет позволяет автоматизировать многие задачи набора текста и подготовки статей, включая набор текста на нескольких языках, нумерацию разделов и формул, перекрёстные ссылки, размещение иллюстраций и таблиц на странице, ведение библиографии и др. Кроме базового набора существует множество пакетов расширения LaTeX. Первая версия была выпущена Лесли Лампортом (Leslie Lamport) в 1984, текущая версия – LaTeX2ε, после создания в 1994 году испытывала некоторый период нестабильности, окончившийся к концу 90-х годов, а в настоящее время стабилизировалась (хотя раз в год выходит новая версия).
Общий внешний вид документа в LaTeX определяется стилевым файлом. Существует несколько стандартных стилевых файлов для статей, книг, писем и т.д., кроме того, многие издательства и журналы предоставляют свои собственные стилевые файлы, что позволяет быстро оформить публикацию, соответствующую стандартам издания.
Во многих развитых компьютерных аналитических системах, например, Maple, Mathematica, Maxima возможен экспорт документов в формат *.tex. Для представления формул в Википедии также используется TeX-нотация.
Распространяемый под лицензией GNU GPL, LaTeX относится к свободному программному обеспечению.
LaTeX-редакторыДля облегчения набора и сборки документов LaTeX существует несколько интегрированных сред, например:
· Emacs + auctex + reftex + preview-latex
· Kile
· LEd
· LyX (http://www.lyx.org/)
· TeXmacs (http://www.texmacs.org/)
· Winefish (http://winefish.berlios.de/)
· Texmaker (англ.)
· TeXnicCenter (англ.)
· WinEdt – единственный коммерческий из перечисленных.
ImageMagick
ImageMagick – свободный и многоплатформенный пакет программ для неинтерактивной (пакетной) обработки графических файлов. Поддерживает множество графических форматов, выпущен под лицензией GPL. Может использоваться с языками Perl, C, C++, Python, Ruby, PHP, Pascal, Java, в скриптах командной оболочки или самостоятельно. В его состав входят такие программы как convert, dvips, identify.
4. Реализация поставленной задачи
Сначала опишем сам процесс, направленный на получение отображения необходимой формулы: участник форума во время написания сообщения может использовать тег [TeX] (обязателен закрывающий тег [/TeX]), внутри которого необходимо написать требуемую формулу, используя язык разметки TeX.
Далее первый хук перехватывает весь текст сообщения и изменяет теги [TeX] и [/TeX] на теги вида [TeX:$uid] и [/TeX:$uid] для возможной дальнейшей более тесной интеграции с форумом.
Второй хук выполняет непосредственные преобразования всех формул, заключенных в теги [TeX] и [/TeX] в картинки необходимого формата (gif или png) с последующим вставлением картинок в отправляемый текст сообщения. При наведении курсора на картинку всплывает исходный текст формулы.
Преобразование формул в картинки происходит следующим образом:
1. весь текст между тегами формул заносится в массив для удобной обработки;
2. далее идет обработка каждой формулы: проверка на корректность;
3. во временной директории создается файл с расширением tex, который содержит стандартное оформление документа с отдельной формулой, и случайным именем;
4. создается dvi файл, используя latex;
5. этот dvi файл конвертируется в Postscript (ps), используя dvips (tetex);
6. конвертирование, обрезка и добавление прозрачности, используя convert из пакета ImageMagick, в результате получается требуемая картинка;
7. далее имя конечной картинки рассчитывается через применение функции необратимого шифрования md5 (), которая является стандартной в языке PHP, параметром этой функции является текст формулы; полученное имя является уникальным для данной формулы;
8. очистка временной директории от использовавшихся файлов;
9. в текст сообщения передается ссылка на получившуюся картинку;
10. в случае ошибки при данном процессе выводится соответствующее предупреждение («[unparseable or potentially dangerous latex formula]»).
Практическая часть.
Часть php-скрипта («posting.php») форума, в которую были внесены необходимые изменения(хуки) для перехвата текста сообщения:
if ($submit || $preview || $refresh) // Отправка, предварительный просмотр написанного сообщения
{
$post_data ['topic_cur_post_id'] = request_var ('topic_cur_post_id', 0);
$post_data ['post_subject'] = utf8_normalize_nfc (request_var ('subject', «, true));
$text = utf8_normalize_nfc (request_var ('message', «, true)); // Перехват сообщения
include_once ('latexrender/phpbb_hook_1.php'); // Первый хук
include_once ('latexrender/phpbb_hook_2.php'); // Второй хук
$message_parser->message = $text; // Дальнейшая обработка сообщения средствами форума
$post_data['username'] = utf8_normalize_nfc (request_var ('username', $post_data['username'], true));
…
Первый хук:
<? php
$text = preg_replace(«#\[tex\] (.*?)\[/tex\]#si», «[tex:$uid]\\1 [/tex:$uid]», $text);
?>
Второй хук:
<? php
$latexrender_path = «latexrender»;
$latexrender_path_http = «latexrender»;
include_once ($latexrender_path. "/class.latexrender.php»);
preg_match_all(«#\[tex:$uid\] (.*?)\[/tex:$uid\]#si»,$text,$tex_matches);
$latex = new LatexRender ($latexrender_path. "/pictures», $latexrender_path_http. "/pictures», $latexrender_path. "/tmp»);
for ($i=0; $i < count ($tex_matches[0]); $i++) {
$pos = strpos ($text, $tex_matches[0] [$i]);
$latex_formula = html_entity_decode ($tex_matches[1] [$i]);
$url = $latex->getFormulaURL ($latex_formula);
$alt_latex_formula = htmlentities ($latex_formula, ENT_QUOTES);
$alt_latex_formula = str_replace («\r», « »,$alt_latex_formula);
$alt_latex_formula = str_replace («\n», « »,$alt_latex_formula);
if ($url!= false) {
$text = substr_replace ($text, «<img src='».$url. «' title='»..$alt_latex_formula. «' alt='».$alt_latex_formula. «' align='absmiddle'>», $pos, strlen ($tex_matches[0] [$i]));
} else {
$text = substr_replace ($text, «[unparseable or potentially dangerous latex formula]»,$pos, strlen ($tex_matches[0] [$i]));
}
}
?>
Скрипт, используемый для обработки формул в массиве, включающий в себя класс:
<? php
class LatexRender {
var $_picture_path =».»;
var $_picture_path_httpd =».»;
var $_tmp_dir =».»;
var $_latex_path = «/usr/bin/latex»;
var $_dvips_path = «/usr/bin/dvips»;
var $_convert_path = «/usr/bin/convert»;
var $_identify_path=»/usr/bin/identify»;
var $_formula_density = 120;
var $_xsize_limit = 500;
var $_ysize_limit = 500;
var $_string_length_limit = 500;
var $_font_size = 10;
var $_latexclass = «article»;
var $_tmp_filename;
var $_image_format = «gif»; // или «png»
var $_latex_tags_blacklist = array (
«include», «def», «command», «loop», «repeat», «open», «toks», «output», «input», «catcode», «name», «^^», «\\every», «\\errhelp», «\\errorstopmode», «\\scrollmode», «\\nonstopmode», «\\batchmode», «\\read», «\\write», «csname», «\\newhelp», «\\uppercase», «\\lowercase», «\\relax», «\\aftergroup», «\\afterassignment», «\\expandafter», «\\noexpand», «\\special»
);
var $_errorcode = 0;
var $_errorextra = «»;
function LatexRender ($picture_path,$picture_path_httpd,$tmp_dir) {
$this->_picture_path = $picture_path;
$this->_picture_path_httpd = $picture_path_httpd;
$this->_tmp_dir = $tmp_dir;
$this->_tmp_filename = md5 (rand());
}
function setPicturePath($name) {
$this->_picture_path = $name;
}
function getPicturePath() {
return $this->_picture_path;
}
function setPicturePathHTTPD($name) {
$this->_picture_path_httpd = $name;
}
function getPicturePathHTTPD() {
return $this->_picture_path_httpd;
}
function getFormulaURL ($latex_formula) {
$latex_formula = preg_replace («/>/i», «>», $latex_formula);
$latex_formula = preg_replace («/</i», «<», $latex_formula);
$formula_hash = md5 ($latex_formula);
$filename = $formula_hash.».».$this->_image_format;
$full_path_filename = $this->getPicturePath(). "/».$filename;
if (is_file ($full_path_filename)) {
return $this->getPicturePathHTTPD(). "/».$filename;
} else {
if (strlen ($latex_formula) > $this->_string_length_limit) {
this->_errorcode = 1;
return false;
}
for ($i=0;$i<sizeof ($this->_latex_tags_blacklist);$i++) {
if (stristr ($latex_formula,$this->_latex_tags_blacklist[$i])) {
$this->_errorcode = 2;
return false;
}
}
if ($this->renderLatex ($latex_formula)) {
return $this->getPicturePathHTTPD(). "/».$filename;
} else {
return false;
}
}
}
function wrap_formula ($latex_formula) {
$string = «\documentclass [».$this->_font_size. «pt] {».$this->_latexclass.»}\n»;
$string.= «\usepackage[latin1] {inputenc}\n»;
$string.= «\usepackage{amsmath}\n»;
$string.= «\usepackage{amsfonts}\n»;
$string.= «\usepackage{amssymb}\n»;
$string.= «\pagestyle{empty}\n»;
$string.= «\begin{document}\n»;
$string.= «$».$latex_formula. «$\n»;
$string.= «\end{document}\n»;
return $string;
}
function getDimensions($filename) {
$output=exec ($this->_identify_path. "».$filename);
$result=explode(«»,$output);
$dim=explode («x»,$result[2]);
$dim [«x»] = $dim[0];
$dim [«y»] = $dim[1];
return $dim;
}
function renderLatex ($latex_formula) {
$latex_document = $this->wrap_formula ($latex_formula);
$current_dir = getcwd();
chdir ($this->_tmp_dir);
$fp = fopen ($this->_tmp_filename.».tex», «a+»);
fputs ($fp,$latex_document);
fclose($fp);
$command = $this->_latex_path.» – interaction=nonstopmode».$this-> _tmp_filename.».tex»;
$status_code = exec($command);
if (!$status_code) {$this->cleanTemporaryDirectory(); chdir ($current_dir); $this->_errorcode = 4; return false;}
$command = $this->_dvips_path.» – E».$this->_tmp_filename.».dvi».» – o».$this->_tmp_filename.».ps»;
$status_code = exec($command);
$command = $this->_convert_path.» – density».$this->_formula_density. .» – trim – transparent \ «#FFFFFF\»».$this->_tmp_filename.».ps».
$this->_tmp_filename.».».$this->_image_format;
$status_code = exec($command);
$dim = $this->getDimensions ($this->_tmp_filename.».».$this-> _image_format);
if (($dim [«x»] > $this->_xsize_limit) or ($dim [«y»] > $this->_ysize_limit)) {
$this->cleanTemporaryDirectory();
chdir ($current_dir);
$this->_errorcode = 5;
$this->_errorextra =»: «. $dim [«x»]. «x». number_format ($dim[«y»], 0, «», «»);
return false;
}
$latex_hash = md5 ($latex_formula);
$filename = $this->getPicturePath(). "/».$latex_hash.».».$this->_image_format;
$status_code = copy ($this->_tmp_filename.».».$this->_image_format,»../../». $filename);
$this->cleanTemporaryDirectory();
if (!$status_code) {chdir ($current_dir); $this->_errorcode = 6; return false;}
chdir ($current_dir);
return true;
}
function cleanTemporaryDirectory() {
$current_dir = getcwd();
chdir(»../../»);
unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».tex»);
unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».aux»);
unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».log»);
unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».dvi»);
unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».ps»);
unlink ($this->_tmp_dir. "/».$this->_tmp_filename.».».$this->_image_format);
chdir ($current_dir);
}
}
?>
Заключение
В данной работе были достигнуты следующие результаты:
· Собран и изучен материал, связанный с использованием формул в Интернете;
· Изучен форумный движок phpBB3;
· Созданы PHP скрипты для взаимодействия с форумом.
Список литературы
1. Афонин С.М. Программирование на языке PHP / Афонин С.М. – М.: НТ Пресс, 2007. – 256 с.: ил.
2. Колисниченко Д.Н. Самоучитель PHP 5. – СПб: Наука и техника, 2004. 576 с.: ил.
3. Мазуркевич А. PHP: настольная книга программиста / Александр Мазуркевич, Дмитрий Еловой. – Мн.: Новое знание, 2003. – 480 с.: ил.
4. Томсон Лаура. Разработка Web-приложений на РНР и MySQL: Пер. с англ. / Лаура Томсон, Люк Веллинг. – 2-е изд., испр. – СПб: ООО «ДиаСофтЮП», 2003. – 672 с.
5. Ульман Л. Основы программирования на РНР: Пер. с англ. – М.: ДМК Пресс, 2001. – 288 с.: ил. (Самоучитель).
6. Харрис Э. PHP/MySQL для начинающих / Пер. с англ. – М.: КУДИЦ-ОБРАЗ, 2005. – 384 с.
7. http://ru.wikipedia.org
8. http://lib.mexmat.ru
9. http://avi.ru
10. http://teacode.com
0 комментариев