DOKIVO 為何未察覺 PDF 水印文字超出頁面邊界:修正檢查方式
Водяной знак вышел за границы PDF: почему проверка текста этого не заметила
DOKIVO 修正 PDF 中「Копия」水印超出頁面邊界、但文字擷取檢查仍判定成功的問題,將內容檢查與可見性檢查分開。新檢查會核對字元邊界是否在頁面內,並檢視渲染後的頁面。修正後的測試涵蓋 120 × 80 點頁面及兩種介面寬度,確認五個字元均在頁面內,PDF 結構檢查亦通過。
Команда DOKIVO (Докиво)
В цепочке «изображение → PDF → пометка “Копия”» оба шага завершились успешно, результат скачался, а извлечение текста вернуло нужное слово. Но на маленькой странице часть надписи оказалась за краем. Рассказываем, как разделили проверку содержимого и проверку его видимости.
Это разбор исправления в DOKIVO от 30 октября 2026 года. Примеры взяты из нашей контролируемой проверки, а не из документов клиентов.
Как получился ложный успех
У проблемного PDF страница была размером 120 × 80 пунктов. Это размеры страницы документа, не ширина окна браузера и не разрешение исходной фотографии.
Для центральной надписи использовался фиксированный размер шрифта 28 пунктов. Размещение, которое выглядит нормально на большом листе, оказалось неподходящим для маленькой страницы. В PDF при этом сохранялся весь текст «Копия» — наличие символов в документе не означало, что они целиком попадали в видимую область.
Проверка «нашли нужную строку в извлечённом тексте» ответила на свой вопрос правильно. Ошибка была в выводе: из наличия строки мы ожидали её полной видимости.
Исправление: учитывать страницу и ширину строки
Для центральной пометки мы использовали уже существующий в проекте расчёт размещения относительно страницы. Он учитывает ширину и высоту страницы, угол наклона и ширину конкретного текста в выбранном шрифте. В обработчике PDF дополнительно сохранён верхний предел размера шрифта — 28 пунктов.
Числа символов для такой задачи недостаточно: «ШШШ» и «111» могут занимать разную ширину. В pdf-lib ширину строки можно получить методом widthOfTextAtSize.
Для понимания геометрии полезна простая модель. Пусть неповёрнутый прямоугольник текста имеет ширину w, высоту h, а угол поворота равен a. Его габариты после поворота:
rotated_width = abs(w * cos(a)) + abs(h * sin(a))
rotated_height = abs(w * sin(a)) + abs(h * cos(a))
По этим габаритам можно ограничить масштаб и затем разместить надпись с запасом от краёв. Однако высота прямоугольника — лишь приближение: базовая линия, выносные элементы и метрики конкретных глифов требуют проверки конечного PDF. Формулы выше объясняют принцип, но не заменяют проверку реального шрифта.
Что проверять в готовом файле
Мы разделили проверки на три уровня.
Содержимое. В документе есть ожидаемое слово. Это ловит потерянную или неверную пометку, но само по себе не ловит обрезание.
Геометрия. Получаем прямоугольники символов из готового PDF и сравниваем с границами страницы. Если хотя бы один символ выходит за край, проверка завершается ошибкой. Для извлечения границ подходит, например, PdfTextPage.get_charbox в pypdfium2. При этом координаты символов и границы страницы нужно привести к одной системе координат.
для каждого символа пометки:
проверить left >= 0 и bottom >= 0
проверить right <= page_width и top <= page_height
Это упрощённый пример для страницы без дополнительного поворота и смещённой области обрезки. Для произвольного PDF следует отдельно учитывать поворот и действующую видимую область. Переносить такой псевдокод в обработчик любых документов без этих оговорок нельзя.
Видимость. Рендерим страницу и осматриваем изображение: надпись читается, исходная картинка сохранена, пометка не закрывает важную часть документа. Даже правильные прямоугольники символов не доказывают достаточный контраст.
Что получилось в нашем случае
После исправления повторили полный путь в браузере: загрузка изображения, создание PDF, добавление «Копия», скачивание результата. Сделали два запуска — при ширине интерфейса 1440 и 390 пикселей. Это проверка двух размеров интерфейса, не испытание физического телефона.
В обоих скачанных PDF:
- страница сохранила размер 120 × 80 пунктов;
- все пять символов «Копия» оказались внутри страницы;
- проверка структуры qpdf прошла;
- при просмотре рендера исходное изображение и полная пометка были видны.
В отдельных автоматических тестах проверили границы глифов для короткой и 120-символьной надписи на маленьких и узких страницах. Это ограниченный набор проверок размещения, а не доказательство одинаковой читаемости любых надписей на любых документах. Длинный текст может поместиться, но стать слишком мелким.
Проверка, которую стоит оставить в обработчике
Успешный статус задачи, корректная структура PDF и найденная строка отвечают на разные вопросы. Для функции, которая наносит видимую пометку, нужны ещё границы символов и просмотр итоговой страницы.
Мы оставили маленькие и узкие страницы в проверках, чтобы дальнейшие изменения не вернули обрезание. Проверять только привычный большой лист для такой функции недостаточно.
Этот случай возник при разработке готовых сценариев DOKIVO. Сценарий объединяет последовательные операции над файлом; качество результата каждой операции всё равно нужно проверять отдельно.
Текст подготовлен с помощью ИИ по исходникам и сохранённым результатам проверки команды DOKIVO. Описанный результат относится к указанным контрольным файлам.
來源:DEV Community · dev.to