Catalog · How the catalog works
PasWmfToSvg
- ★ 1 on GitHub
Anyone may press Interesting, signed in or not. It helps others find this project.
README
PasWmfToSvg
Перевод метафайлов Windows (EMF и WMF) в SVG на чистом Object Pascal. Работает без GDI, Java и внешних программ на Windows, Linux, macOS, Android и iOS (Delphi 10.3 и новее, проверено на Delphi 13).
Записи метафайла разбираются напрямую и повторяются так, как их рисует сама Windows. Отсюда ровный размер, полупиксельные сдвиги, исключённые правые и нижние края, штрихи перьев, узоры штриховки и фон текста как в GDI. Результат сверяется по пикселям с рисованием Windows (см. «Проверка»).
Использование
uses
PasWmfToSvg;
var
Info: TMfInfo;
Svg: string;
begin
Svg := MetafileToSvg(TFile.ReadAllBytes('picture.emf'), Info); // EMF или WMF - определяется по заголовку
TFile.WriteAllBytes('picture.svg', TEncoding.UTF8.GetBytes(Svg));
Writeln(Info.Format, ' ', Info.Width, 'x', Info.Height, ', пропущено записей: ', Info.Skipped);
end;MetafileToSvg(Data)/MetafileToSvg(Data, Info, Metrics). Неверные данные — исключениеEMetafileToSvg.TMfInfo: формат (EMF,WMF,WMF+EMF), размер картинки в пикселях, число записей, пропущенные записи и их типы.- Метрики шрифтов (
IMfFontMetrics) нужны для базовой линии текста и ширины строки (фон, выравнивание):- по умолчанию — встроенные таблицы 14 распространённых шрифтов (
PasWmfToSvg.FontTables.inc, измерены в GDI Windows); незнакомый шрифт берётся по семейству; - в Windows достаточно добавить в
usesмодульPasWmfToSvg.Gdi— метрики будет давать сама Windows; - можно передать свой поставщик.
- по умолчанию — встроенные таблицы 14 распространённых шрифтов (
- Потокобезопасно: у каждого вызова своё состояние.
Что поддерживается
| EMF | WMF | |
|---|---|---|
| фигуры | многоугольники, ломаные (и составные), отрезки, прямоугольники, эллипсы, скруглённые прямоугольники, дуги, хорды, секторы, кривые Безье | то же без кривых Безье, плюс SETPIXEL |
| перья | косметические и геометрические, штрихи (промежутки цветом фона при непрозрачном фоне), концы и стыки | косметические и геометрические, штрихи |
| кисти | сплошные, штриховка HS_* (фон при непрозрачном фоне), DIB-узор, начало узора |
сплошные, штриховка, DIB-узор |
| текст | EXTTEXTOUTW: выравнивание, фон, ETO_OPAQUE, межсимвольные расстояния, наклон, полужирный, курсив, подчёркивание |
TEXTOUT, EXTTEXTOUT (однобайтовый текст — по набору символов шрифта) |
| картинки | BITBLT, STRETCHBLT, STRETCHDIBITS, SETDIBITSTODEVICE, ALPHABLEND (альфа), PATBLT; DIB 1/4/8/16/24/32 бита |
DIBBITBLT, DIBSTRETCHBLT, STRETCHDIB, SETDIBTODEV, PATBLT |
| координаты | режимы отображения, окно и область вывода, мировое преобразование, SAVEDC/RESTOREDC |
окно, режимы отображения, SAVEDC/RESTOREDC |
- Размер SVG — рамка картинки: у EMF это
rclFrameв пикселях эталонного устройства, у WMF — рамка размещаемого заголовка при 96 точках на дюйм. Координаты — пиксели этого размера, точка GDI — центр пикселя. Масштаб SVG к картинке — ровно 1. Картинки и DIB-узоры встраиваются как PNG (data:). - В WMF, который Windows сделала из EMF (
GetWinMetaFileBits), исходный EMF вложен комментариями. Его и рисует преобразователь, как это делает сама Windows. - Не поддерживаются и пропускаются: пути (
BEGINPATH…), отсечение, регионы, растровые операции кроме копирования, EMF+ (двойные метафайлы рисуются их EMF-частью), картинки устройства (Bitmap16), сжатые DIB (RLE, JPEG, PNG).
Проверка
Сверка с рисованием Windows по пикселям (на Windows, нужны Delphi, Python 3 и Edge или Chrome):
python Tools\build.py Tools\MfSvgCheck.dpr --output build
build\MfSvgCheck.exe --make-samples build\samples :: ?????????????????????????? ?????????????????? ???????? ???????????????????????? ??????????????
build\MfSvgCheck.exe build\samples --out build\check :: SVG ?? ???????????????? GDI ?????????????? ??????????????????
python Tools\edge_compare.py --check build\check --worst 10 :: SVG ???????????? ??????????????, ?????????????????? ?? GDIMfSvgCheckдля папки.emf/.wmfсохраняет SVG, картинку GDI иmanifest.json. Ключи:--wmf— каждый EMF переводится в WMF;--wmf-pure— то же без вложенного EMF, проверка самих записей WMF;--builtin-metrics;--no-gdi --no-svg— только разбор.edge_compare.pyсчитает долю «несовпавших» пикселей (разница канала больше 96) от закрашенных в GDI и пишетreport.json. Худшие файлы сохраняются какworst_*.png: GDI | SVG | разница | другой SVG (--old).Samples/— синтетические метафайлы этой проверки (EMF и WMF без вложенного EMF).- Сборка ядра под другие платформы без их SDK:
python Tools\build.py Source\PasWmfToSvg.pas --platform linux64(а такжеwin64,osx64,osxarm64,android64,iosarm64).
Результат на 68 144 реальных EMF (чертежи оконных конструкций из программы расчёта):
| что | итог |
|---|---|
| разбор всех файлов | ошибок 0, пропущенных записей 0; 0,5 мс на файл, SVG в среднем 3,7 КБ |
| сверка с GDI в Edge, 2 059 случайных и самые большие | несовпавших пикселей: медиана 1,0 %, p95 3,1 %, p99 6,6 %; сдвиг 0 у всех. Прежний конвертер (wmf2svg, Java): медиана 12,6 %, p95 88 % |
| те же файлы как WMF с вложенным EMF | как EMF |
| те же файлы как WMF без вложенного EMF | медиана 3,2 %, p95 13 % (Windows округляет масштабированные координаты по-своему) |
Остаток разницы — сглаживание: браузер сглаживает наклонные линии и буквы, GDI — нет.
Инструменты
Tools/MfToSvg.dpr— перевод из командной строки:MfToSvg <метафайл> [<файл.svg>] [--builtin-metrics].Tools/MeasureFonts.dpr(Windows) — заново измеряет таблицы шрифтов и узоров штриховки вSource/PasWmfToSvg.FontTables.inc.Tools/build.py— сборка компилятором Delphi из командной строки.
Лицензия
MIT, см. LICENSE. Таблицы шрифтов — измеренные числа (ширины символов и высоты), без самих шрифтов.

