跳到正文
DEV Community· Dmitry K·· 3 小時前AI 評分41

DOKIVO 為何未察覺 PDF 水印文字超出頁面邊界:修正檢查方式

Водяной знак вышел за границы PDF: почему проверка текста этого не заметила

AI 導讀

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