Информационные технологииStfw.Ru 🔍

PDF-документы

Графика, Flash, pdf
🕛 01.11.2006, 15:30
PDF-функции позволяют PHP создавать PDF-файлы с помощью библиотеки PDF, созданной Томасом Мерзем (http://www.pdflib.com/ pdflib/index.html); также могут потребоваться библиотеки JPEG (ftp:// ftp.uu.net/graphics/jpeg/) и TIFF (http://www.libtiff.org/).

С pdflib поставляется хорошая документация, описывающая возможности библиотеки. Имена функций и аргументы идентичны в библиотеке и РНР. Размеры и координаты измеряются в единицах Postscript (72 на дюйм), но это зависит от выбранного разрешения.

Аналогом библиотеки является ClibPDF (см. ниже).

Версии ниже 3.0 pdflib не поддерживаются в РНР 4. Для компиляции РНР с библиотекой pdflib используйте параметр - enable-shared-pdftib.

<?php $fp = fopenC'test.pdf". "w"):
$pdf = pdf_open($fp):
pdf_set_info($pdf. "Author". "Uwe Steinmann").
pdf_set_info($pdf. "Title". "Test for PHP PDFlib");
pdf_set_info($pdf. "Creator". "See Author"):
pdf_set_info($pdf. "Subject". "Testing");
pdf_begin_page(*pdf. 595. 842):
pdf_add_outline($pdf. "Page 1").
pdf_set_font($pdf. "Times-Roman". 30. "host").
pdf_set_value($pdf. "textrendenng". 1):
pdf_show_xy($pdf. "Times Roman outlined". 50. 750);
pdf_moveto($pdf. EO. 740); .
pdf_hneto($pdf. 330. 740).
pdf_stroke($pdf). pdf_end_page($pdf):
pdf_close($pdf): fclose($fp):
echo "<A HRFF=getpdf.php>finished</A>":
<?php // сценарий getpdf.php.
просто возвращает документ pdf '
$fp = fopenC'test.pdf". "r")
headert"Content-type: applncation/pdf").
fpassthru(Sfp); fclose($fp): ?>

Пример из комплекта pdflib создает документ, состоящий из страниц с изображением часов (каждая страница показывает текущее время создания):

<?php $pdffilename = "clock.pdf": // имя файла
Sradius = 200: // радиус циферблата
Smargin =20: // поля страницы
Spagecount =40; // число страниц
$fp = fopen($pdffilename. "w"). $pdf = pdf_open($fp);
while($pagecount- > 0) {
pdf_begin_page($pdf. 2 * (Sradius + Smargin).
2 * (Sradius + Smargin)):
pdf_set_parameter($pdf. "transition", "wipe"):
pdf_set_value($pdf. "duration". 0.5).
pdf_translate(Spdf. $radius + Smargin. Sradius + Smargin):
pdf_save(Spdf): pdf_setrgbcolor($pdf. 0.0 0 0. 1.0):
/* минутные метки */ pdf_cetlinewidth($pdf. 2 0):
for (.«alpha - 0: Salpha < 360: Salpha += 6) {
pdf_rotate($pdf. 6.0): pdf_moveto($pdf. Sradius. 0.0):
pdf_lineto($pdf. Sradius-Smargin/3. 0.0):
pdf_stroke(Spdf): } pdf_restore($pdf): pdf_save($pdf):
/* 5 минутные метки */ pdf_setlinewidth($pdf. 3.0):
for (Salpha - 0: Salpha < 360: Salpha += 30) {
pdf_rotate($pdf. 30.0):
pdf_moveto(Spdf. Sradius. 0.0):
L pdf_11neto($pdf. $radius-$margin. 0.0).
pdf_stroke(Spdf): $ltime = getdate():
/* часовая стрелка */ pdf_save($pdf):
pdf_rotate($pdf.-((SItime['minutes']/60.0)+
ntfme['hours']-3.Q)*30.0): pdf_moveto
($pdf. -Sradius/10. -Sradius/20):
pdf_lineto($pdf. $radius/2. 0.0):
pdf_lineto($pdf. -Sradius/10. Sradius/20):
pdf_closepath($pdf). pdf_fill($pdf): pdf_restore(Spdf):
/* минутная стрелка */ pdf_save(Spdf):
paf_rotate($pdf.(($ltime['seconds']/60 0)+
SltimeC'rmnjtes'MS.): pdf_moveto
($pdf. -$radius.'10. -$radius/20); pdf_lineto
($pdf. Sradius * 0.8. 0 0): pdf_lineto(
$pdf. -$radius/i(). $radius/20): pdf_closepath($pdf):
pdf_fi)l($pdf); pdf_restore($pdf):
/* секундная стрелка */
pdf_setrgbcolor($pdf. 1.0. 0.0. 0.0);
pdf_setlinewidth($pdf. 2): pdf_save($pdf):
pdf_rotate($pdf. -((SltTmei'seconds'] - 15.0) *6.0)):
pdf_moveto($pdf. -$radius/5. 0.0).
pdf_lineto($pdf. Sradius. 0.0);
pdf_stroke($odf); pdf_restore($pdf):
/* центр */ pdf_circle($pdf. 0. 0. $radius/30):
pdf_fnH$pdf): pdf_restore($pdf);
pdf_end_page($pdf); } $pdf - pdf_close($pdf):
fclose($fp): $fp = fopen($pdffilename. "r");
header("Content - type: appli cati on/pdf");
fpassthru($fp): fclose($fp): ?>

pdf_set_info

Заполнение поля информации документа

void pdf set_info (int pdf_document. string fieldname, string value)

Возможные поля fieldname: «Subject», «Title», «Creator», «Author», «Keywords» и одно, определяемое пользователем. Функция должна вызываться до создания страниц.

<?рhр $fd = fopent"test.pdf". "w"):
Spdfdoc - pdf open($fd).
pdf_set_1nfo($pdfdoc. "Author". "Имя автора");
pdf_setjnfo($pdfdoc. "Creator". "Название создателя");
pdf set info($pdfdoc. "Title", "Заголовок");
pdf_set_mfo($pdfdoc. "Subject". "Тема");
pdf_set_info($pdfdoc. "Keywords". "Ключевые, слова");
pdf_set_info($pdfdoc. "CustomField".
"Чего-то еще"); pdf_beg-in_page($pdfdoc. 595. 842);
pdf_end_page($pdfdoc). pdf_close($pdfdoc); ?>

Эта функция заменяет собой pdf_set_infoj<;e.ywords(), pdf_set_info_ title(), pdf_set_info_subject(), pdf_set_info_creator(), pdf_set_info_ sybject().

pdf_open

Открытие нового документа pdf 'int pdf_open (int file)

Функция делает файл, открытый функцией fopen(), документом pdf. Если не указывать дескриптор файла, он создается в памяти и затем может выводиться на стандартный поток вывода или отсылаться браузеру. Функция возвращает дескриптор документа, который следует указывать в последующих pdf-функциях.

См. также: fopen(), pdf_close().

pdf_close

Закрытие документа pdf

void pdf_close (int pdf_document)

См. также: pdf_open(), fclose().

pdf begin_page

Начало новой страницы

void pdf_begin_page (int pdf_document, double width, double height)

Аргументы height и width задают высоту и ширину страницы. После внесения на страницу информации ее следует закрыть функцией pdf_end_page().

См. также pdf_end_page().

pdf_end_page

Завершение страницы

void pdf_end_page (int pdf_docuraent)

После этого модификация этой страницы невозможна.

См. также pdf_begin_page().

pdf_show

Вывод текста в текущую позицию

void pdf_show (int pdf_document, string text)

Для вывода используются текущая позиция и текущий шрифт.

См. также: pdf_show_xy(), pdf_show_boxed(), pdf_set_text_pos(), pdf_set_ font().

pdf_show_boxed

Вывод текста в прямоугольную область

int pdf_show_boxed (int pdfjJocument, string text, double x, double y. double width, double height, string mode [, string feature])

Левый нижний угол области вывода задается (х,у); высота и ширина - height, width. Аргумент mode определяет выравнивание текста: если высота и ширина равна нулю, то возможны значения: «left», «right» или «center», если они не равны нулю, то - «justify» или «full justify».

Если аргумент feature содержит значение «blind», текст не отображается.

Возвращает число символов, которые не поместились в указанный прямоугольник.

См. также: pdf_show(), pdf_show_xy().

pdf_show_xy

Вывод текста в указанную позицию

void pdf_show_xy (int pdf_doc, string text, double x, double y)

См. также: pdf_show(), pdf_show_boxed().

pdf_set_font

Выбор шрифта, его размера и кодировки

void pdf_set_font (int pdf_document, string fontjiame, double size, string encoding [, int embed])

Аргумент вида кодировки encoding может принимать значения: «win-ansi» (по умолчанию), <-builtin», «host», «macroman» и т. п. Если для последнего аргумента задано значение 1, шрифт будет внедрен в документ pdf (иначе, нет). Если шрифт распространен, внедрять его не следует из-за увеличения размера документа.

Функция должна вызываться после pdf_begin_page().

pdf_ set_ leading

Установка промежутка между строками текста void pdf_set_leading (int pdf_document, double distance) Используется при выводе текста функцией pdf_continue_text().

См. также pdf continue text().

pdf_set_parameter

Установка строкового значения параметра pdflib

void pdf_set_parameter (Int pdf_document, string name, string value)

См. также: pdf_get_value(), pdf_set_value(), pdf_get_parameter().

pdf_get_parameter

Получение строкового значения параметра pdflib

string pdf_get_parameter (int pdf_doc, string name [, double modifier])

Аргумент modifier используется при необходимости.

См. также: pdf_get_value(), pdf_set_value(), pdf_set_parameter().

pdf_set_value

Установка численного значения параметра pdflib

void pdf_set_value (int pdf_document, string name, double value)

См. также: pdf_get_value(), pdf_get_parameter(), pdf_set_parameter().

pdf_get_value

Получение численного значения параметра pdflib

double pdf_get_value (int pdf_document, string name [, double modifier])

Аргумент modifier используется при необходимости.

См. также: pdf_set_value(), pdf_get_parameter(), pdf_set_parameter().

pdf_set_text_rendering

Установка метода вывода текста

void pdf_set_text_rendering (int pdf_document, int mode)

Устарела, используйте PDF_set_value().

pdf_set_horiz_scaling

Установка масштабирования текста по горизонтали

void pdf_set_horiz_scaling (int pdf_document, double scale)

pdf_set_text_rise

Установка подъема текста

void pdf_set_text_rise (int pdf_document, double rise)

pdf_set_text_matrix

Установка матрицы преобразования шрифта

void pdf_set_text_matrix (Int pdf_document, array matrix)

Начиная с версии pdflib 2.3 эта функция недоступна.

pdf_set_text_pos

Установка позиции текста

void pdf_set_text_pos (int pdf_document, double x-coor, double y-coor)

Устанавливает позицию вывода текста последующим вызовом pdf_ show().

См. также: pdf_show(), pdf_show_xy().

pdf_set_char_spacing

Установка интервала между символами

void pdf_set_char_spacing (int pdf_document, double space)

Устарела, используйте PDF_set_value().

См. также: pdf_set_word_spacing(), pdf_set_leading().

pdf_set_word_spacing

Установка интервала между символами

void pdf_set_word_spacing (int pdf_document, double space)

Устарела, используйте PDF_set_value().

См. также: pdf_set_char_spacing(), pdf_set_leading().

pdf_skew

Поворот системы координат

void pdf_skew (int pdf_document, double alpha, double beta) \

Угол поворота в градусах указывается относительно осей alpha (x) и beta (у). Углы не могут принимать значения 90 или 270 градусов.

pdf_continue_text

Вывод текста со следующей строки

void pdf_continue_text (int pdf_docuraent, string text)

Расстояние между строками может быть установлено функцией pdf_set_leading().

См. также: pdf_show_xy(), pdf_set_leading(), pdf_set_text_pos().

pdf_stringwidth

Вычисление ширины текста

double pdf strnngwidth (int pdf document, string text)

При вычислении длины строки используется текущий шрифт. Предварительно шрифт должен быть установлен с помощью pdf_set_font().

См. также pdf_set_font().

pdf_save

Сохранение текущих установок

void pdf_save (int pdf_document)

Действует подобно команде postscript gsave. Полезна при необходимости масштабировать или развернуть объект, не воздействуя на другие объекты. pdf_save() требует, чтобы затем была вызвана функция pdf_restore().

См. также pdf_restore().

pdf_restore

Восстановление ранее сохраненных установок

void pdf_restore (int pdf_document)

Восстанавливает установки, сохраненные pdf_save(). Действует подобно команде postscript grestore.

<?php rdf_save($pdf):
// всякие вращения и трансформации ...
pdf_reitore($pdf) ?>

См. также pdf_save().

pdf_translate

Установка начала системы координат

j void pdf_translate (int pdf_document, double x, double y) Координаты указываются относительно текущей точки отсчета. Затем, до начала рисования объектов, требуется установить текущую точку.

<?php pdf_moveto($pdf. 0. 0). pdf_lireto
($pdf. 100. 100). pdf_stn>ke($pd*):
pdfJranslateOpdf. 100. 100): pdf_mweto($pdf. 0. 0);
pdfjireto($pdf. 100. 100): pdf_stroke($pdf): ?>

pdf_scale

Установка масштабирования

void pdf_scale (int pdf_document, double x_scale, double y_scale)

<?pho pdf_scale($pdf. 72 0, 72.0).
pdf_llneto($pdf. l. 1): // дюйм
pdf_stroke($pdf). ?>

pdf_rotate

Установка угла вращения в градусах

void pdf_rotate (int pdf_document, double angle)

pdf_setflat

Установка равномерности

void pdf_setflat (int pdf_document, double value)

Возможные значения параметра - от 0 до 100.

pdf_setlinejoin

Установка параметра linejoin

void pdf_setlinejoin (int pdf_document. long value)

Возможные значения параметра - от 0 до 2.

pdf_setlinecap

Установка параметра linecap

void pdf_setlinecap (int pdf document, int value)

Возможные значения параметра - от 0 до 2.

pdf_setmiterlimit

Установка параметра miter limit

void pdf_setmiterlimit (int pdf_document. double value)

Возможные значения параметра - 1 и более.

pdf_setlinewidth

Установка ширины строк

void pdf_setlinewidth (int pdf_document. double width)

pdf_setdash

Установка вида штриховки

void pdf_setdash (int pdf_document. double white, double black)

Устанавливает размер белых и черных полос. Если оба аргумента равны 0, то линия будет непрерывной.

pdf_moveto

Установка текущей точки

void pdfjnoveto (int pdf_document, double x, double y)

pdf_curveto

Черчение кривой

void pdf_curveto (int pdf_document, double xl, double yl, double x2, double y2, double x3, double y3)

Чертит кривую Безьс от текущей точки до (хЗ.уЗ), используя точки (xl.yl) и (х2,у2) как ориентирующие.

См. также: pdfjnoveto(), pdf_lineto(), pdf_stroke().

pdf_lineto

Черчение отрезка

void pdfjineto (int pdf_document, double x, double y)

Чертит линию от текущей точки до указанной (х,у).

См. также: pdf_moveto(), pdf_curveto(), pdf_stroke().

pdf_circle

Черчение окружности

void pdf_circle (int pdf_document, double x, double y, double radius)

См. также: pdf_arc(), pdf_stroke().

pdf_arc

Черчение дуги

void pdf_arc (int pdf_document, double x, double y, double radius, double start, double end)

Начальный и конечный угол задаются start и end.

См. также: pdf_circle(), pdf_stroke().

pdf_rect

Черчение прямоугольника

void pdf_rect (int pdf_document, double x, double y, double width, double height)

Левый нижний угол задается (х,у); высота и ширина - height, width.

См. также pdf_stroke().

pdf_closepath

Завершение текущего пути

void pdf_closepath (int pdf_document)

Чертит линию от текущей точки до точки, где начиналась первая линия. Многие функции, например pdfjnovetoO, pdf_circle(), pdf_rect(), начинают новый путь.

pdf_stroke

Заштриховка пути

void pdf_stroke (int pdf_document)

Текущий путь - это совокупность всех линий. Без этой функции линии начерчены не будут.

См. также: pdf_closepath(), pdf_c1osepath_stroke().

pdf_closepath_stroke

Черчение и закрытие пути

void pdf_closepath_stroke (int pdf_document)

Это комбинация pdf_closepath() и pdf_stroke().

См. также: pdf_closepath(), pdf_stroke().

pdf_fill

Заполнение пути цветом

void pdf_fill (int pdf_document)

См. также: pdf_closepath(), pdf_stroke(), pdf_setgray_fill(), pdf_setgray(), pdf_setrgbcolor_fiTl (), pdf_setrgbcolor().

pdf_fill_stroke

Заполнение пути цветом и закрытие его

void pdf_fill_stroke (int pdf_document)

См. также: pdf_closepath(), pdf_stroke(), pdf_fill(), pdf_setgray_fill(), pdf_setgray(), pdf_setrgbcolor_fill(), pdf_setrgbcolor().

pdf_closepath_fill_stroke

Черчение, закрашивание и закрытие пути

void pdf_dosepath_fin_stroke (int pdfjjocument)

См. также: pdf_closepath(), pdf_stroke(), pdf_fill(), pdf_setgray_fill()) pdf_setgray(), pdf_setrgbcolor_fiTI(), pdf_setrgbcolor().

pdf_endpath

Завершение пути без его закрытия void pdf_endpath (int pdf_document)

См. также pdf_dosepath().

pdf_clip

Прикрепление всех линий к текущему пути

void pdf_c!ip (int pdf_docuraent)

pdf_setgray_fill

Установка заполнения серым цветом

void pdf_setgray_fill (int pdfjjocument, double gray_value)

См. также pdf_setrgbcolor_fill ().

pdf_setgray_stroke

Установка штриховки серым цветом

void pdf_setgray_stroke (int pdf_document, double gray_value)

См. также pdf_setrgbcolor_stroke().

pdf_setgray

Установка заполнения и штриховки серым цветом

void pdf_setgray (int pdf_document, double grayj/alue)

См. также: pdf_setrgbcolor_stroke(), pdf_setrgbcolor_fill().

pdf_setrgbcolor_fill

Установка заполнения цветом rgb

void pdf_setrgbcolor_fill (int pdf_document, double red_value, double green_value, double blue_value)

См. также pdf_setrgbcolor_fill().

pdf_setrgbcolor_stroke

Установка штриховки цветом rgb

void pdf_setrgbcolor_stroke (int pdfjjocument, double red_value, double green_value, double blue_value)

См. также pdf_setrgbcolor_stroke().

pdf_setrgbcolor

Установка заполнения и штриховки серым цветом rgb

void pdf_setrgbcolor (int pdf_document, double red_value, double green_value, double blue_value)

См. также: pdf_setrgbcolor_stroke(), pdf_setrgbcolor_fill().

pdf_add_outline

Добавление закладки для текущей страницы

int pdf_add_outline (int pdf_ document, string text [, int parent [, int open]])

Название закладки определяется аргументом text. Она становится дочерним объектом объекта parent и по умолчанию открыта (если аргумент open не равен 0). Возвращается идентификатор закладки, который может использоваться как родительский для других закладок.

pdf_set_transition

Установка режима перехода между страницами

void pdf_set_transition (int pdf_document, int transition)

Используйте функцию PDF_set_parameter() с параметром «transition».

См. также pdf_set_duration().

pdfset_duration

Установка интервала между страницами

void pdf_set_duration (int pdfjiocument, double duration)

См. также pdf_set_transition().

pdf_open_gif

Открытие рисунка GIF

int pdf_open_gif (int pdf_document, string filename)

Используйте функцию pdf_open_image_file().

<?php $im = pdf_open_gif($pdf. "test.gif"):
pdf_place_image($pdf. $im. 100. 100. 1):
pdf_close_image($pdf. Sim): ?> "

pdfopen_png

Открытие рисунка PNG

int pdf_open_png (int pdf, string png_file)

Используйте функцию pdf_open_image_file().

pdf_openjpeg

Открытие рисунка JPEG

int pdf_ppen_jpeg (int pdf_document, string filename)

Используйте функцию pdf_open_image_file().

pdf_open_tiff

Открытие рисунка TIFF

int pdf_open_tiff (int PDF-document, string filename)

Используйте функцию pdf_open_image_file().

pdf_open_image_file

Чтение рисунка из файла

int pdf_open_image_file (int PDF_document, string format, string filename)

Загружает рисунок формата format из файла filename и возвращает его идентификатор. Возможные форматы: PNG, TIFF, JPEG и GIF.

<?php $pim = pdf_open_image_file
($pdf. "png". "picture.png");
pdf place_image($pdf. $plm. 100, 100. 1):
pdf_close_image($pdf. Spim); ?>

Функция заменяет pdf_open_jpeg(), pdf_open_gif(), pdf_open_tiff(), pdf_ open_png().

См. также: pdf_close_image(), pdf_execute_image(), pdf_place_image(), pdf_ put_image().

pdf_open_memory_image

Открытие рисунка, созданного графическими функциями PHP

int pdf_open_memory_image (int pdfjJocument, int image)

Функция принимает дескриптор рисунка, созданного PHP, и делает его доступным для документа pdf. Функция возвращает идентификатор рисунка pdf.

<?php // Example: Including a memory image
$im = ImageCreateClOO. 100);
$col = ImageColorAllocate($im. 80. 45. 190);
ImageFiimim. 10. 10, $col);
$pim = pdf_open_memory_image($pdf. $im):
ImageDestroy($im):
pdf_place_image($pdf. $pim. 100. 100, 1);
pdf_close_image($pdf. Spim): ?>

См. также: pdf_clo.scjmage(), pdf_executejmage(), pdf_place_image(), pdf_ put_iraage().

pdf_closejmage

Закрытие рисунка

void pdf_close_image (int image)

Закрывает рисунок, открытый функциями pdf_open_ ().

См. также: pdf_open_jpeg(), pdf_open_gif(), pdf_open_memory_image().

pdf_get_image_height

Установка высоты рисунка в пикселах

string pdf_get_image_height (int pdf_document, int image)

См. также: pdf_open_image_file(), pdf_open_memory_image(), pdf_get_image_ width().

pdf_get_image_width

Установка ширины рисунка в пикселах

string pdf_get_image_width (int pdf_document. int image)

См. также: pdf_open_itnage_file(), pdf_openjnemory_image(), pdf_get_image_ height().

pdf_placejmage

Размещение рисунка на странице

void pdf_p!ace_image (int pdf_doc, int image, double x, double y, double scale)

Позиция размещения задается (х,у); масштаб - scale.

См. также pdf_put_image().

pdf_put_image

Сохранение рисунка в PDF для дальнейшего использования

void pdf_put_inage (int pdf_document, int image)

Внедряет рисунок в документ без его отображения. Затем рисунок может быть размещен на странице функцией pdf_execute_image() необходимое число раз. Полезно при многократной вставке рисунка (уменьшается размер файла).

Начиная с версии 2.01 pdflib функция бесполезна и выводит только предупреждение.

См. также: pdf_place_image(), pdf_execute_image().

pdf_execute_image

Размещение сохраненного рисунка на странице

void pdf_execute_image (int pdf_document, int image, double x, double y, double scale) :

Отображает рисунок, внедренный функцией pdf_put_image().

Начиная с версии 2.01 pdflib функция бесполезна и выводит только предупреждение.

Example I. Multiple show of an image
<?php
Sim = ImageCreatedOO. 100);
Scoll = ImageColorAllocate($im. 80. 45. 190);
ImageFill($im. 10. 10. Scoll):
$pim = pdf_open_memory_image($pdf. Sim);
pdf_put_image($pdf. $pim);
pdf_execute_image($pdf, $pim. 100. 100. 1);
pdf_execute_image($pdf. $pim. 200. 200. 2); // 200 %
pdf_close_image($pdf. $pim); ?>

pdf_add_annotation

Добавление примечания

void pdf_add_annotation (int pdf_document, double llx. double lly, double urx. double ury, string title, string content)

Примечание располагается в левом нижнем углу (Их, Пу), верхний правый угол (urx. ury).

pdf_set_border_style

Установка стиля обрамления примечаний и гиперссылок

void pdf_set_border_style (int pdf_document. string style, double width)

Аргумент style может принимать значения «solid» или «dashed». Ширина задастся аргументом width.

См. также: pdf_set_border_color(). pdf_set_border_dash().

pdf_set_border_color

Установка цвета обрамления ссылок и примечаний

void pdf_set_border_color (int pdf_document, double red, double green, double blue)

Три компонента цвета могут принимать значения из диапазона от 0.0 до 1.0.

См. также: pdf_set_border_style(), pdf_set_border_dash().

pdf_set_border_dash

Установка стиля окантовки ссылок и примечаний

void pdf_set_border_dash (int pdf_document. double black, double white)

Устанавливает длину черных и белых полос прерывистых линий.

См. также: pdf_set_border_style(), pdf_set_border_color().

Учебник по основам PHP   Теги:

Читать IT-новости в Telegram
Информационные технологии
Мы в соцсетях ✉