Pro 에디션
Flow Layout — 심층 참조
한눈에 보기
섹션 제목: “한눈에 보기”이 페이지는 Pro Flow Layout 모듈의 심층 참조입니다. 배치 엔진, 요소 모델, 페이지 나눔 전략, 그 동작 계약과 실패 모드를 다룹니다. StreamingLayoutEngine은 FlowElement 값의 목록을 순서대로 순회합니다. 각 요소에 0부터 시작하는 페이지 인덱스와 LayoutRegion 내의 위치를 할당합니다. 결과는 불변 PlacedElement 레코드로 이루어진 LayoutResult입니다. 이 모듈은 배치만 계산합니다. 아무것도 렌더링하지 않으며 I/O도 수행하지 않습니다.
가용성 및 라이선스
섹션 제목: “가용성 및 라이선스”이 기능은 NextPDF Pro(nextpdf/pro)에 포함되며 Pro 등급 라이선스 봉투로 활성화됩니다. 해당 자격이 없는 배포는 이 기능의 클래스를 로드하지 않습니다. 에디션 비교 및 라이선스 받기.
기능별 라이선스 플래그는 존재하지 않습니다. 이것은 Pro 에디션 기능입니다.
공개 API 표면
섹션 제목: “공개 API 표면”모든 심볼은 NextPDF\Pro\FlowLayout 네임스페이스에 있습니다. 모든 값 객체는 final이며 불변입니다.
| 심볼 | 매개변수 | 기본 동작 | 반환 | 예외 또는 실패 | 참고 |
|---|---|---|---|---|---|
StreamingLayoutEngine::__construct | LayoutRegion $region, PageBreakStrategy $strategy = PageBreakStrategy::Greedy | 페이지별 콘텐츠 영역을 나눔 전략에 바인딩 | StreamingLayoutEngine | — | 전략 기본값은 Greedy입니다. |
StreamingLayoutEngine::layout | list<FlowElement> $elements | 단일 전진 패스; 전략 기반 페이지 나눔으로 순차 배치 | LayoutResult | 예외를 던지지 않음 | 빈 목록은 빈 페이지 하나를 산출합니다. |
StreamingLayoutEngine::withStrategy | PageBreakStrategy $strategy | 동일한 영역으로 새 엔진을 파생 | self | — | 수신자는 변경되지 않습니다. |
StreamingLayoutEngine::withRegion | LayoutRegion $region | 동일한 전략으로 새 엔진을 파생 | self | — | 수신자는 변경되지 않습니다. |
FlowElement::__construct | FlowElementType $type, string $content, float $widthPt = 0, float $heightPt = 0, float $marginTopPt = 0, float $marginBottomPt = 0, bool $keepWithNext = false | 불변 요소 값 객체 | FlowElement | — | Table 요소의 유일한 생성 경로입니다. |
FlowElement::text | string $content, float $height | 호출자가 측정한 높이를 가진 텍스트 요소 | self (static) | — | 너비 0은 배치 시점에 영역 너비로 해석됩니다. |
FlowElement::image | string $path, float $width, float $height | 이미지 요소; content가 경로를 담습니다 | self (static) | — | 엔진은 파일을 열지 않습니다. |
FlowElement::spacer | float $height | 빈 콘텐츠의 수직 공백 | self (static) | — | — |
FlowElement::pageBreak | — | 명시적 나눔 마커 | self (static) | — | PlacedElement를 방출하지 않습니다. |
FlowElement::totalHeight | — | 높이에 상단 및 하단 여백을 더한 값 | float | — | 모든 맞춤 검사는 이 값을 사용합니다. |
FlowElementType | 열거형 케이스 Text, Image, Table, Spacer, PageBreak | 문자열 기반: text, image, table, spacer, page_break | — | — | — |
FlowElementType::isBreakable | — | Text와 Table은 true를, 나머지는 false를 반환 | bool | — | 분류 전용입니다. 아래 원자적 배치 계약을 참조하세요. |
LayoutRegion::__construct | float $x, float $y, float $width, float $height | 좌상단 원점 콘텐츠 상자, 포인트 단위로 측정 | LayoutRegion | — | 검증 없음. 값은 주어진 그대로 취합니다. |
LayoutRegion::contains | float $px, float $py | 경계를 포함하는 영역 내 점 검사 | bool | — | — |
LayoutRegion::remainingHeight | float $currentY | 영역 높이에서 소비된 수직 오프셋을 뺀 값 | float | — | 커서가 넘친 뒤에는 0 또는 음수입니다. |
LayoutResult::__construct | list<PlacedElement> $placements, int $pageCount, float $totalHeightPt | 불변 레이아웃 결과 | LayoutResult | — | — |
LayoutResult::placementsOnPage | int $pageIndex | 0부터 시작하는 페이지 인덱스로 배치를 필터링 | list<PlacedElement> | — | 반환된 목록은 재인덱싱됩니다. |
LayoutResult::isEmpty | — | 배치된 요소가 없을 때 true | bool | — | 빈 입력과 나눔 전용 입력에 대해 true입니다. |
PageBreakStrategy | 열거형 케이스 Greedy, AvoidOrphans, KeepTogether | 문자열 기반: greedy, avoid_orphans, keep_together | — | — | — |
PageBreakStrategy::label | — | 사람이 읽을 수 있는 전략 레이블 | string | — | — |
PlacedElement::__construct | FlowElement $element, int $pageIndex, float $x, float $y, float $width, float $height | 불변 배치 레코드 | PlacedElement | — | 좌표는 포인트 단위, 좌상단 원점입니다. |
public function layout(array $elements): LayoutResultpublic function withStrategy(PageBreakStrategy $strategy): selfpublic function withRegion(LayoutRegion $region): selfpublic static function text(string $content, float $height): selfpublic static function image(string $path, float $width, float $height): selfpublic static function spacer(float $height): selfpublic static function pageBreak(): self동작 계약
섹션 제목: “동작 계약”StreamingLayoutEngine::layout()은 입력 목록에 대해 한 번의 전진 패스를 수행합니다. 각 요소에 대해 맞춤을 검사하고, 필요할 때 페이지를 나눈 다음 PlacedElement를 기록합니다. 빈 입력 목록은 배치가 없고, 페이지 수가 1이며, 전체 높이가 0인 LayoutResult를 반환합니다.
배치 기하는 결정론적입니다:
x는 영역의 왼쪽 가장자리입니다.y는 현재 커서 위치에 요소의 상단 여백을 더한 값입니다.width는 요소의widthPt가 양수일 때 그 값이며, 그렇지 않으면 영역 너비입니다.height는 요소의heightPt이며, 공급된 그대로 정확히 사용됩니다.
각 배치 후 커서는 여백을 포함해 totalHeight()만큼 전진합니다. 같은 양이 LayoutResult::totalHeightPt에 누적됩니다.
페이지 나눔 규칙, 평가 순서대로:
- 명시적
PageBreak요소는 페이지 인덱스를 증가시키고 커서를 영역 상단으로 재설정합니다. 배치를 방출하지 않으며 전체 높이에 아무것도 더하지 않습니다. - 요소의
totalHeight()가 남은 높이를 초과하면 엔진이 나눕니다 — 커서가 이미 페이지 상단에 있는 경우는 예외입니다. Greedy는 추가 조건을 더하지 않습니다. 맞는 요소는 항상 배치됩니다.AvoidOrphans는 배치 후 남는 공간이 양수이면서도 요소 자체 필요 높이의 절반 미만일 때, 맞는 요소 앞에서 나눕니다. 참조 단위는 요소 자신의 높이이고 고정 제수는 2이며, 어떤 폰트 메트릭도 관여하지 않습니다. 페이지 상단에서는 결코 나누지 않습니다.KeepTogether는 맞는 요소의keepWithNext플래그가 설정되고, 다음 요소가 존재하며, 커서가 페이지 상단이 아니고, 두 요소의 결합된totalHeight()가 남은 공간을 초과할 때 그 요소 앞에서 나눕니다. 마지막 요소의 플래그는 아무 효과가 없습니다.
원자적 배치: 엔진은 모든 요소를 하나의 단위로 배치합니다. 요소 콘텐츠를 여러 페이지에 걸쳐 분할하는 일은 결코 없습니다. FlowElementType::isBreakable()은 호출자가 어떤 유형을 더 작은 요소로 사전 분할할 수 있는지 분류하며, 엔진 자체는 이를 참조하지 않습니다.
무상태성과 결정론: 엔진은 자신의 영역과 전략만 보유합니다. layout()은 호출 간에 상태를 공유하지 않으며, 동일한 입력은 동일한 결과를 산출합니다. withStrategy()와 withRegion()은 새 엔진을 반환하며 수신자를 결코 변경하지 않습니다.
엣지 케이스 및 실패 모드
섹션 제목: “엣지 케이스 및 실패 모드”- 이 모듈의 어떤 메서드도 예외를 던지지 않습니다. 잡아야 할 예외 계층 구조가 없습니다.
- 생성자는 아무것도 검증하지 않습니다. 음수 또는 0인 영역 치수, 음수 요소 높이, 음수 여백이 그대로 수용되어 산술 연산을 변경 없이 통과합니다.
- 영역보다 큰 요소도 여전히 배치됩니다. 페이지 상단에서는 그 자리에 배치되어 넘치고, 다른 곳에서는 엔진이 먼저 나눈 뒤 새 페이지에서 넘칩니다. 그러면 다음 요소가 항상 나눔을 유발하므로, 넘침은 한 페이지에 국한됩니다.
- 선두의
PageBreak는 첫 콘텐츠 요소를 페이지 인덱스 1에 배치하여 페이지 수를 최소 2로 만듭니다. - 연속된
PageBreak요소는 각각 페이지 카운터를 전진시켜 빈 페이지를 만듭니다. 마지막에 오는 것은pageCount에 마지막 빈 페이지를 남깁니다. - keep-together는 짝을 이룬 두 요소가 한 페이지에 함께 맞을 때만 성립합니다. 결합 높이가 전체 페이지를 초과하는 쌍은 여전히 분할됩니다.
- 양수가 아닌
widthPt는 영역 너비로 해석됩니다. 치환 검사는 엄격하게 0보다 큰지를 봅니다. remainingHeight()는 커서가 넘친 뒤에는 0 또는 음수를 반환할 수 있습니다.contains()는 영역 경계를 내부로 취급합니다.- 범위를 벗어난 인덱스로 호출한
placementsOnPage()는 빈 목록을 반환합니다. - 이 모듈은 어떤 암호화 연산도 수행하지 않으며 FIPS 관련 동작을 정의하지 않습니다.
적합성
섹션 제목: “적합성”Flow Layout는 NextPDF가 정의한 배치 동작을 구현합니다. 외부 레이아웃 또는 타이포그래피 표준을 대상으로 하지 않으므로, 이 페이지에는 규범 인용 표가 없습니다. 페이지 나눔 전략은 NextPDF 시맨틱이며, CSS 프래그먼테이션 속성이나 어떤 XSL-FO keep 모델의 구현이 아닙니다. 모든 치수는 Core 작성기가 소비하는 단위에 맞춰 포인트로 표현됩니다.
이 진술들은 기능만을 기술합니다. NextPDF는 어떤 적합성 인증도 보유하지 않으며, 어떠한 인증 주장도 이루어지거나 암시되지 않습니다.
개발 노트
섹션 제목: “개발 노트”- 콘텐츠는 상류에서 측정하세요. 엔진은 호출자가 공급한 높이를 소비합니다. 폰트 메트릭이 없으며 텍스트 측정을 수행하지 않습니다.
- 긴 텍스트나 표 콘텐츠는 레이아웃 전에 여러 요소로 사전 분할하세요. 청커가 어떤 유형을 분할할 수 있는지 결정하려면
isBreakable()을 사용하세요. - 페이지 기하마다 엔진 하나를 재사용하세요.
withStrategy()와withRegion()으로 변형을 저렴하게 파생하세요. - 페이지별로 렌더링할 때는
placementsOnPage()로 출력을 페이지별로 그룹화하세요. - 레이아웃은 단일 패스이고 요소 수에 대해 선형이며 문서 트리를 보유하지 않습니다. 결과가 결정론적이어서 골든 파일 테스트에 적합합니다.
- HTML-투-PDF 렌더링에는 대신 Core HTML 파이프라인을 사용하세요. 이 모듈은 HTML이나 CSS 엔진이 아닙니다.
게시 경계
섹션 제목: “게시 경계”이 페이지는 외부에서 관찰 가능한 동작과 지원되는 공개 API 표면만 문서화합니다. 내부 네임스페이스 경로, 헬퍼 클래스, 메커니즘 표, 런북 파일명, 티켓 접두사는 범위 밖입니다.