Canvas — это constraint, а не фон
6.00 вводит canonical CanvasDescriptor и делает формат явной геометрией. Он ещё не решает, как композиция должна вести себя в portrait/landscape.
extent, coordinate frame, rectangular canvas domain, intrinsic aspect ratio.
raw canvas geometry only.
CANVAS SCHEMA + ASPECT-RATIO GEOMETRY.
Canonical shell
Descriptor связывает текущую геометрию с будущими owner-модулями 6.01–6.04.
CanvasDescriptor
{
canvasRef,
extent: {
width,
height,
unit
},
rasterExtentPx?,
coordinateFrame,
boundaryRef,
domainRef,
aspectRatioWH,
logAspectRatio,
axisRelation,
formatClassRef?, // 6.01
physicalMetadataRef?, // 6.02
normalizationContextRef?, // 6.03
adaptationHooksRef?, // 6.04
status,
confidence,
provenance
}Ownership
6.00 geometry 6.01 behavior 6.02 physical metadata 6.03 normalization 6.04 adaptation/tests Topic7 safe/bleed Topic8 grids Topic5 free space
Width / height / short / long
Все линейные величины остаются в одной и той же declared canvas unit.
Aspect ratio без вкусовой интерпретации
6.00 фиксирует две эквивалентные числовые формы: обычное отношение и log-ratio.
Ratio
Log-ratio
4:5, 16:9, 1:1 — только когда это exact
Readable ratio pair допускается только для явно целочисленной raster extent.
CanvasCoordinateFrame
Продолжаем общую для COMPO screen convention: origin сверху слева, +Y вниз.
Canonical frame
CANVAS_TOP_LEFT_Y_DOWN origin: (0,0) top-left +x: right +y: down
Boundary
(0,0) → (W,0) → (W,H) → (0,H) → close domain: [0,W] × [0,H]
CanvasDomainBoundary
Это закрывает давний внешний dependency Topic 5: full-canvas CompositionSpaceDomain теперь имеет canonical upstream source.
CanvasDomainBoundary {
boundaryRef:
"canvas::boundary",
domainRef:
"canvas::domain",
coordinateFrame,
polygon,
area,
provenance
}
Axis relation ≠ format behavior
6.00 может констатировать только exact relation между width и height.
| Raw descriptor | Condition | Behavior owner |
|---|---|---|
WIDTH_EQ_HEIGHT | W = H | 6.01 |
WIDTH_GT_HEIGHT | W > H | |
WIDTH_LT_HEIGHT | W < H |
Что сознательно не делаем
Тема 6 разбита MAIN именно для того, чтобы не смешать геометрию формата с физикой и adaptation.
Orientation behavior
square / portrait / landscape policies.
Physical
mm, A-series, DPI/PPI, viewing context.
Normalization
cross-format normalized coordinates and scale invariance.
Adaptation
format-change hooks and Topic6 regression.
Не забираем чужие владельения
Canvas geometry становится upstream context, но не новым super-owner всей сцены.
| Concept | Owner |
|---|---|
| visual mass | Topic 4 |
| occupied/free-space geometry | Topic 5 |
| canvas extent/aspect ratio | 6.00 |
| safe zones / bleed | Topic 7 |
| grid occupancy | Topic 8 |
| object transforms | Topic 3 / Core adapter boundary |
| global balance / hierarchy / eye-flow | future global owners |
Dirty graph
Изменение canvas geometry должно инвалидировать downstream spatial/layout evidence, но 6.00 не выполняет сам reflow.
CanvasChangeEvent {
canvasRef,
oldExtent?,
newExtent,
changedFields[],
provenance
}
6.00 publishes change evidence.
6.04 later owns:
adaptation hooks
recompute routing
candidate reflow policy
6.00 itself:
recomputes raw geometry only.
Visual Lab: три холста, одна геометрическая модель
Показываем только raw format geometry — без утверждений о том, где должен стоять контент.
Reference geometry tests
Проверяем exact formulas, reciprocal/swap invariants, common-scale invariance, integer ratio, N/A semantics и ownership boundaries.
DATA FOR LAYOUT ENGINE
Machine-readable entrypoint темы 6.
{
"module": "Compo 6.00",
"name": "canvas_format_schema_and_aspect_ratio",
"version": "1.1-corrective",
"canonical_main_title": "Canvas/format schema и aspect ratio",
"topic": "06_ФОРМАТ_ПОСТЕРА_И_СООТНОШЕНИЕ_СТОРОН",
"scope": "CANVAS_EXTENT_COORDINATE_FRAME_BOUNDARY_AND_INTRINSIC_ASPECT_RATIO_SCHEMA",
"main_topic_output": "CanvasDescriptor, format class, physical metadata, normalization contract",
"planned_files": {
"6.00": "Canvas/format schema и aspect ratio",
"6.01": "Square / portrait / landscape behavior",
"6.02": "Physical size, A-series, DPI, viewing context",
"6.03": "Format-normalization and scale invariance",
"6.04": "Tests and adaptation hooks"
},
"consumes": [
"explicit CanvasInput supplied by document/render/platform owner",
"optional raster pixel extent",
"optional abstract canvas-coordinate extent",
"coordinate-frame convention"
],
"provides": [
"CanvasDescriptor",
"CanvasExtent",
"CanvasCoordinateFrame",
"CanvasDomainBoundary",
"CanvasGeometryResult",
"MetricResult[canvas.geometry.width]",
"MetricResult[canvas.geometry.height]",
"MetricResult[canvas.geometry.aspectRatioWH]",
"MetricResult[canvas.geometry.logAspectRatio]",
"MetricResult[canvas.geometry.area]",
"MetricResult[canvas.geometry.shortSide]",
"MetricResult[canvas.geometry.longSide]",
"MetricResult[canvas.geometry.diagonal]",
"CanvasFormatCorrectionRequest[]",
"formatClassRef slot -> Compo6.01",
"physicalMetadataRef slot -> Compo6.02",
"normalizationContextRef slot -> Compo6.03",
"adaptationHooksRef slot -> Compo6.04"
],
"owns_metrics": [
"canvas.geometry.width",
"canvas.geometry.height",
"canvas.geometry.aspectRatioWH",
"canvas.geometry.logAspectRatio",
"canvas.geometry.area",
"canvas.geometry.shortSide",
"canvas.geometry.longSide",
"canvas.geometry.diagonal",
"canvas.geometry.confidence"
],
"descriptors_only": [
"canvas.canvasRef",
"canvas.extentUnit",
"canvas.axisRelation",
"canvas.reducedIntegerRatio",
"canvas.coordinateFrame",
"canvas.boundaryRef",
"canvas.domainRef",
"canvas.formatClassRef",
"canvas.physicalMetadataRef",
"canvas.normalizationContextRef",
"canvas.adaptationHooksRef",
"canvas.status",
"canvas.rasterMappingRef"
],
"canvas_input_schema": {
"canvasRef": "stable document/canvas id",
"extent": {
"width": "finite >0",
"height": "finite >0",
"unit": "PX|CANVAS_UNIT"
},
"rasterExtentPx": "optional {widthPx,heightPx}; positive integers; when extent.unit=PX it must agree with extent",
"coordinateFrame": "CANVAS_TOP_LEFT_Y_DOWN|CUSTOM_FRAME_REF",
"provenance": "object",
"rasterMappingRef": "optional explicit mapping ref required when abstract canvas aspect and raster aspect differ"
},
"canvas_extent_schema": {
"width": "finite >0",
"height": "finite >0",
"unit": "PX|CANVAS_UNIT",
"shortSide": "min(width,height)",
"longSide": "max(width,height)",
"area": "width*height in unit²",
"diagonal": "hypot(width,height) in unit",
"axisRelation": "WIDTH_EQ_HEIGHT|WIDTH_GT_HEIGHT|WIDTH_LT_HEIGHT"
},
"canvas_coordinate_frame": {
"canonical": "CANVAS_TOP_LEFT_Y_DOWN",
"origin": "(0,0) at top-left",
"xAxis": "+x right",
"yAxis": "+y down",
"boundary": "closed axis-aligned rectangle [0,width]×[0,height]",
"note": "custom frames require explicit adapter; 6.00 does not silently rotate/flip geometry"
},
"canvas_domain_boundary_schema": {
"boundaryRef": "canvas:<canvasRef>:boundary",
"domainRef": "canvas:<canvasRef>:domain",
"coordinateFrame": "same CanvasCoordinateFrame",
"polygon": "[(0,0),(width,0),(width,height),(0,height)]",
"area": "same as canvas.geometry.area",
"purpose": "canonical rectangular canvas domain consumed by Topic5 and later layout modules"
},
"aspect_ratio_semantics": {
"aspectRatioWH": "width/height; dimensionless",
"logAspectRatio": "ln(width/height); dimensionless and antisymmetric under width↔height",
"reducedIntegerRatio": "[w/gcd(w,h), h/gcd(w,h)] only when a raster/integer extent is explicitly available",
"axisSwap": "r' = 1/r and log(r') = -log(r)",
"commonScale": "multiplying width and height by the same positive scalar preserves aspectRatioWH/logAspectRatio",
"no_tolerance_classification": "6.00 does not decide near-square behavior; 6.01 owns square/portrait/landscape behavior"
},
"ownership_map": {
"6.00": "canvas extent, coordinate frame, rectangular canvas domain, intrinsic aspect-ratio geometry",
"6.01": "square/portrait/landscape classification behavior, near-square tolerance/policies and orientation-dependent behavior",
"6.02": "physical size, A-series, DPI/PPI, viewing context and pixel↔physical consistency",
"6.03": "normalization context, normalized coordinates/lengths/areas and cross-format scale invariance",
"6.04": "adaptation hooks, format-change recompute plan and consolidated Topic6 tests"
},
"handoff_contracts": {
"to_5.00": "CanvasDomainBoundary supplies the canonical CompositionSpaceDomain boundary when the full canvas is the requested domain",
"to_4.01": "canvas.geometry.shortSide is raw geometry evidence; Compo6.03 will later publish the canonical CanvasNormalizationContext.shortSide value/ref",
"to_6.01": "CanvasDescriptor + aspectRatioWH + axisRelation",
"to_6.02": "CanvasDescriptor + optional rasterExtentPx",
"to_6.03": "CanvasDescriptor raw extent/shortSide/longSide/area",
"to_6.04": "CanvasDescriptor version and change events"
},
"metric_policy": {
"aspect_ratio": "descriptor, not score",
"canvas_area": "physical coordinate-domain measure only, not content occupancy",
"short_long_sides": "raw same-unit geometry, not yet normalized values",
"direct_scoring": "FORBIDDEN in 6.00",
"square_is_better": "FORBIDDEN",
"portrait_is_better": "FORBIDDEN",
"landscape_is_better": "FORBIDDEN",
"larger_canvas_is_better": "FORBIDDEN"
},
"hard_constraints": [
"one metric = one owner",
"width and height must be explicit positive finite values; 6.00 must not infer canvas extent from content bounding boxes",
"width and height axes must use the same declared unit inside one CanvasExtent",
"aspectRatioWH is width/height and is never clamped or normalized to 0..1",
"logAspectRatio is ln(width/height) only for valid positive extents",
"canvas area is width*height of the canvas domain and is not occupied/content area",
"shortSide/longSide are raw extent descriptors; normalized coordinate contracts remain 6.03",
"when CANVAS_UNIT extent and rasterExtentPx have different aspect ratios, an explicit rasterMappingRef is required; 6.00 must not silently identify anisotropic logical and raster spaces",
"reducedIntegerRatio is published only from explicit integer raster dimensions; approximate floating ratios are not rationalized by guessing",
"6.00 exposes exact axisRelation only; near-square tolerance and square/portrait/landscape behavior remain 6.01",
"physical millimeters/inches, A-series, DPI/PPI and viewing distance remain 6.02",
"format normalization and cross-format scale invariance remain 6.03",
"adaptation/reflow hooks and consolidated Topic6 regression remain 6.04",
"margin/safe/bleed zones remain Topic7",
"grid occupancy remains Topic8",
"content occupancy/free-space remains Topic5",
"visual mass remains Topic4",
"object transforms remain Topic3/Core adapter boundary",
"no global balance/hierarchy/eye-flow ownership",
"N/A != 0",
"no beautyScore"
],
"initial_heuristics": {
"dimension_epsilon": {
"value": 1e-12,
"provenance": "IMPLEMENTATION_HEURISTIC"
},
"integer_ratio_max_safe_dimension": {
"value": 9007199254740991,
"provenance": "IMPLEMENTATION_HEURISTIC"
}
},
"correction_policy": {
"foreign_content_mutation": "FORBIDDEN",
"missing_extent": "request explicit document/canvas owner dimensions",
"invalid_extent": "request correction from document/canvas owner",
"orientation_behavior_issue": "route to Compo6.01",
"physical_metadata_issue": "route to Compo6.02",
"normalization_issue": "route to Compo6.03",
"format_adaptation_issue": "route to Compo6.04",
"safe_zone_issue": "route to Topic7"
},
"deferred_inputs": [
"Compo6.01 square/portrait/landscape behavior",
"Compo6.02 physical size/A-series/DPI/viewing context",
"Compo6.03 CanvasNormalizationContext and cross-format invariance",
"Compo6.04 adaptation hooks and regression",
"Topic7 margins/safe/bleed",
"Topic8 grids",
"future global balance/hierarchy/eye-flow"
],
"recompute_when": [
"explicit canvas width/height changes",
"extent unit changes",
"rasterExtentPx changes",
"coordinate-frame adapter changes",
"canvas identity/version changes"
],
"finality": "CANVAS_SCHEMA_AND_INTRINSIC_ASPECT_RATIO_GEOMETRY_ONLY",
"raster_extent_consistency": {
"PX_extent": "when extent.unit=PX, rasterExtentPx must exactly match width/height",
"CANVAS_UNIT_same_aspect": "raster extent may be attached without mapping ref when logical and raster aspect ratios agree",
"CANVAS_UNIT_different_aspect": "requires explicit rasterMappingRef; 6.00 does not silently treat anisotropic logical↔raster mapping as the same metric geometry",
"purpose": "prevent one CanvasDescriptor from silently carrying two conflicting format geometries"
}
}