Graphics: 경로 + 셰이딩 + 변환 프리미티브
한눈에 보기
섹션 제목: “한눈에 보기”Graphics 모듈은 그리려는 내용을 PDF 그래픽 연산자로 변환합니다. 경로, 선 스타일, 색 공간, 변환, 셰이딩, 패턴, 하프톤, 이미지 로딩을 다룹니다.
composer require nextpdf/core:^3개념 개요
섹션 제목: “개념 개요”Graphics는 벡터 및 래스터 그리기 계층입니다. ContentStream 및 Writer 모듈이 PDF로 직렬화하는 연산자 시퀀스를 생성합니다. 콘텐츠 스트림은 페이지 콘텐츠를 그래픽 연산자의 정렬된 시퀀스로 인코딩합니다 — ISO 32000-2 §8. 이 모듈은 해당 연산자를 출력할 뿐, 파일을 기록하지는 않습니다.
DrawingEngine이 기본 표면입니다. 플루언트하며 상태를 보유하는 빌더입니다. 각 setter는 self를 반환하고, 그래픽 상태 변경 또는 경로 페인팅 연산자를 누적해 getStream()으로 읽는 내부 버퍼에 추가합니다. 이 엔진은 PDF 그래픽 상태를 직접 모델링합니다 — 선 너비, 선 스타일, 획 및 채우기 색상, 알파 및 블렌드 모드, 마이터 한계, 소프트 마스크, 클리핑, 오버프린트, 평탄도, 매끄러움, 렌더링 인텐트, 검정 생성, 언더컬러 제거가 각각 문서화된 연산자에 매핑됩니다. 색상 관련 setter는 Color 값 객체 또는 명시적인 ColorSpace를 받으므로, 디바이스 색 공간과 CIE 기반 색 공간이 하나의 호출 형태를 공유합니다.
엔진 주변에는 세 가지 계열이 있습니다. 첫 번째는 이미지 입력 계열입니다. ImageLoader는 파일 또는 메모리 내 blob을 ImageLoadResult로 디코딩합니다. ImageRegistry는 MemoryReport를 통해 디코딩된 이미지를 중복 제거하고 추적하므로, 대규모 문서를 메모리 예산 안에서 유지할 수 있습니다. 두 번째는 벡터 가져오기 계열입니다. SvgParser와 EpsParser는 외부 벡터 형식을 동일한 연산자 스트림으로 변환하며, 레이아웃을 위해 getBoundingBox()를 노출합니다. 세 번째는 디바이스 색상 충실도 계열입니다: 셰이딩(ShadingManager, Type2/Type3 및 메시 계열), 패턴(PatternFill), 하프톤(Type1/Type5/Type6/ Type10/Type16), 전송 함수, ICC 기반 색 공간이 여기에 속합니다.
TransformEngine은 좌표 변환에 특화된 보조 도구입니다. 변환을 startTransform()과 stopTransform()으로 감싸며, 이는 q 및 Q save/restore 쌍을 출력합니다. 명명된 아핀 헬퍼를 제공합니다 — scale, translate, rotate, skew, mirrorH, mirrorV — 각각 선택적 피벗을 받습니다. 변환 행렬은 내부 좌표 공간을 대상 좌표 공간으로 매핑합니다. 이는 ISO 32000-2가 셰이딩 도메인에 적용하는 것과 동일한 모델입니다 — §8.7.4.
색상 관리는 ADR-012를 따릅니다: ICCBased 및 CIE 기반 색 공간은 디바이스 색상 폴백에 의존하는 대신 명시적인 cs/CS 콘텐츠 스트림 연산자를 출력합니다. ICC 프로파일은 ISO 32000-2 §8.6.5.5에 따라 구성 요소 수가 올바른 ICCBased 스트림으로 래핑됩니다.
API 표면
섹션 제목: “API 표면”| 클래스 | 주요 메서드 | 역할 |
|---|---|---|
DrawingEngine | getStream(), reset(), setLineWidth(), setLineStyle(), setDrawColor(), setFillColor(), setAlpha(), setSoftMask(), clip(), setOverprint(), setRenderingIntent(), line(), rect(), circle(), ellipse(), polygon(), linearGradient() | 상태를 보유하는 경로 + 그래픽 상태 연산자 빌더 |
TransformEngine | startTransform(), stopTransform(), scale(), translate(), rotate(), skew(), mirrorH(), mirrorV(), getStream() | 아핀 좌표 변환 |
ImageLoader | load(string $filePath), loadFromString(string $data, string $mimeType) | 이미지 디코딩 결과인 ImageLoadResult |
ImageRegistry | load(), loadFromString(), getMetadata(), memoryUsage(), reset() | 메모리 리포팅을 지원하는 중복 제거 이미지 캐시 |
SvgParser | parse(), parseFile() | SVG를 연산자 스트림으로 변환 |
EpsParser | parse(), parseFile(), getBoundingBox() | EPS를 연산자 스트림으로 변환 |
ShadingManager | 셰이딩 등록 + 딕셔너리 출력 | 축형, 방사형, 메시 셰이딩 |
Halftone (추상) | halftoneType(), toDict(), hasStream(), getStream() | Type 1/5/6/10/16 하프톤 스크린 |
전체 PHPDoc 표를 보려면 composer docs:generate-api-php -- --module=Graphics 명령을 실행하십시오.
코드 샘플 — 빠른 시작
섹션 제목: “코드 샘플 — 빠른 시작”소스: examples/06-colors-and-drawing.php.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Graphics\Color;use NextPDF\Graphics\DrawingEngine;use NextPDF\Graphics\LineStyle;
$engine = new DrawingEngine();
$engine ->setLineWidth(1.5) ->setDrawColor(Color::rgb(0, 51, 102)) ->setFillColor(Color::rgb(230, 240, 250)) ->rect(20.0, 20.0, 160.0, 80.0) ->line(20.0, 110.0, 180.0, 110.0, new LineStyle(dash: [3.0, 2.0]));
$contentStreamBytes = $engine->getStream();코드 샘플 — 프로덕션
섹션 제목: “코드 샘플 — 프로덕션”이 예제는 메모리 리포팅을 지원하는 이미지 레지스트리와 변환 브래킷을 연결합니다. examples/07-images.php 및 examples/21-transforms.php에서 사용된 구조를 기반으로 합니다.
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Graphics\DrawingEngine;use NextPDF\Graphics\ImageRegistry;use NextPDF\Graphics\TransformEngine;
$registry = new ImageRegistry();$image = $registry->load('/srv/assets/logo.png');
$report = $registry->memoryUsage();if ($report->bytes > 32 * 1024 * 1024) { // Decoded image cache exceeded the budget — reset before the next page. $registry->reset();}
$transform = new TransformEngine();$transform ->startTransform() ->translate(40.0, 700.0) ->scale(0.5, 0.5) ->stopTransform();
$engine = new DrawingEngine();$engine->reset();$page = $transform->getStream() . $engine->getStream();엣지 케이스 및 주의 사항
섹션 제목: “엣지 케이스 및 주의 사항”DrawingEngine은 상태를 가집니다. 서로 독립적인 페이지 사이에서는reset()을 호출하십시오. 그렇지 않으면 이전 그래픽 상태가 다음 스트림으로 누출됩니다.TransformEngine에는 일치하는startTransform()/stopTransform()쌍이 필요합니다. 짝이 맞지 않는 브래킷은 짝이 없는q를 남기고 Writer 하위 단계의 save/restore 스택을 손상시킵니다.setSoftMask(),setOverprint(),setBlackGeneration(),setUnderColorRemoval()은 확장 그래픽 상태 마커를 기록합니다. 이 기능을 허용하지 않는 프로파일에서는 비활성화됩니다. 시각적 결과에 의존하기 전에 프로파일 가드를 확인하십시오.ImageRegistry는 콘텐츠를 기준으로 중복을 제거합니다. 동일한 바이트를 가진 두 경로는 하나의 객체를 공유합니다.load()호출 하나가 PDF 이미지 하나를 만든다고 가정하지 마십시오.EpsParser::getBoundingBox()는 페이지 박스가 아니라 파싱된 바운딩 박스를 반환합니다. EPS가 대상 직사각형을 넘어가는 경우 직접 클리핑을 적용하십시오.- 블랙 포인트 보정은 권고 성격이며 마커 기반입니다. 그 자체로 픽셀을 변환하지는 않습니다.
검증 및 오류 처리
섹션 제목: “검증 및 오류 처리”생산자 측 변경 사항 두 가지는 호환되지 않는 변경입니다. 두 변경 모두 이전에는 조용히 발생하던 손상을 호출 지점의 명시적 실패로 바꿉니다.
이제 입력 검증이 예외를 던집니다(마이그레이션 참고). 그리기 입력은 연산자 스트림에 도달하기 전에 검증되며, 잘못된 형식의 값은 InvalidArgumentException으로 거부됩니다. 이전에는 NaN, Infinity 또는 범위를 벗어난 값을 전달해도 조용히 손상된 연산자가 생성됐지만, 이제 동일한 입력에서는 예외가 발생합니다. 검증되는 제약 조건은 다음과 같습니다:
- 색상 알파는 유한해야 하며
[0, 1]범위 안에 있어야 합니다. - CTM 피연산자, 템플릿 치수, 그라데이션 정점 좌표, 메시 패치 좌표는 유한해야 합니다 —
NaN또는Infinity는 허용되지 않습니다. - 그라데이션 패치 에지 플래그는
{0, 1, 2, 3}중 하나여야 합니다. - Type 2/3/4 함수 매개변수와 하프톤 매개변수는 범위 검사를 거칩니다.
- 색료 이름은 이스케이프 처리됩니다.
- OCG(선택적 콘텐츠) 레이어 이름은 비어 있지 않아야 합니다.
업그레이드하기 전에 상류 데이터에서 좌표나 알파를 계산하는 호출 지점을 감사하십시오: 이전에는 통과되던 값이 이제는 명백한 오류가 됩니다.
ICCBased /N은 기본적으로 fail-closed입니다. 일반 PDF 출력은 /N 구성 요소 수가 {1, 3, 4}을 벗어난 ICCBased 색 공간을 거부하고, 선언된 /N을 임베드된 프로파일 및 /Alternate 공간과 대조해 조정합니다. 이는 /N을 /Alternate 공간과 함께 담고 있는 ICCBased 스트림에 대한 ISO 32000-2 §8.6.5.5 규칙을 따릅니다. N 채널 ICC 프로파일(예를 들어 N = 6인 헥사크롬 프로파일)은 PDF/A 또는 PDF/X 프로파일이 활성화되어 있고 IccConformancePolicy::ProfileGated를 통해 옵트인된 경우에만 유지됩니다. 이는 구성 요소 수에 대한 구조적 게이트이며, PDF/A 또는 PDF/X 인증을 주장하는 것이 아닙니다.
연산자 출력은 그리기 호출 수에 선형적으로 비례합니다 — 버퍼에 대한 O(n) 추가이며, 리플로는 없습니다. 이미지 디코딩 비용은 레지스트리가 아니라 코덱과 픽셀 수가 좌우합니다. 레지스트리의 콘텐츠 해시 중복 제거는 대규모 문서를 위한 주요 수단입니다: 재사용된 자산은 한 번의 디코딩과 하나의 PDF 객체만 사용합니다. 이 모듈의 기준 워크로드에 대한 performance_budget은 벽시계 시간 1500 ms, 최대 64 MB입니다. 디코딩된 이미지의 메모리 사용량을 관찰하려면 ImageRegistry::memoryUsage()를 사용하고, 페이지 그룹 사이에서 이를 해제하려면 reset()을 사용하십시오.
보안 참고 사항
섹션 제목: “보안 참고 사항”SvgParser와 EpsParser는 신뢰할 수 없는 벡터 입력을 처리합니다. 둘 다 적대적인 데이터의 파서로 취급하십시오. parse()를 호출하기 전에 입력 크기 제한을 적용하십시오. 소스가 사용자 제공이라면 제한된 워커에서 추출을 실행하십시오. EPS는 PostScript의 한 방언입니다. 파서는 제한된 부분 집합을 변환하며 범용 인터프리터를 실행하지 않지만, 그럼에도 입력 크기와 파싱 시간을 제한해야 합니다. 이미지 로더는 서드파티 코덱을 디코딩합니다. 런타임 이미지 확장을 최신 상태로 유지하고 디코딩된 크기에 상한을 두십시오. 신뢰 경계 및 워커 격리 지침은 /modules/core/security/의 엔진 위협 모델을 참조하십시오.
적합성
섹션 제목: “적합성”이 모듈은 ISO 32000-2 §8과 일치하는 PDF 그래픽 연산자 구조, §8.6.5.5에 따른 ICCBased 색 공간 딕셔너리, 그리고 Domain, Function, Matrix, BBox가 §8.7.4를 따르는 셰이딩 딕셔너리를 출력합니다. 이는 구현상의 사실입니다: 연산자 및 딕셔너리 형태는 src/Graphics/에 의해 생성되며 tests/Unit/Graphics/ 및 tests/Golden/PdfWriter/PdfWriterShadingGoldenBaselineSmokeTest 및 PdfWriterExtGStateGoldenSmokeTest 베이스라인에 의해 검증됩니다. 이는 종단 간 PDF 2.0 또는 PDF/X 적합성에 대한 진술이 아닙니다. 전체 문서 적합성은 /modules/core/conformance/에 설명된 오라클 및 골든 스위트에 의해 별도로 검증됩니다. ICC OutputIntents에 대한 프로파일 동작은 이 모듈 단독이 아니라 ADR-011 및 ADR-012에 의해 결정됩니다.