COMPO · 6.00 · CANVAS / FORMAT SCHEMA / ASPECT RATIO

Canvas / format
schema &
aspect ratio.

Entry point темы 6: explicit canvas extent, top-left +Y-down coordinate frame, canonical rectangular CanvasDomainBoundary и intrinsic aspect-ratio geometry. 6.00 делает формат активным вычислимым constraint, не забирая orientation behavior, physical metadata, normalization или reflow у 6.01–6.04.

ModuleCompo 6.00
Scopecanvas geometry / aspect ratio
Ownsraw extent + domain
Behaviordeferred 6.01
Topic6 · FORMAT
Next6.01

Canvas — это constraint, а не фон

00 / module api

6.00 вводит canonical CanvasDescriptor и делает формат явной геометрией. Он ещё не решает, как композиция должна вести себя в portrait/landscape.

SCOPE

extent, coordinate frame, rectangular canvas domain, intrinsic aspect ratio.

OWNS

raw canvas geometry only.

FINALITY

CANVAS SCHEMA + ASPECT-RATIO GEOMETRY.

CANVAS ≠ CONTENT BOUNDS. Размер холста всегда приходит explicit. 6.00 не обрезает canvas по объектам и не выводит формат из bounding box контента.

Canonical shell

01 / CanvasDescriptor

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

02 / extent geometry

Все линейные величины остаются в одной и той же declared canvas unit.

width = explicit > 0 height = explicit > 0 shortSide = min(width,height) longSide = max(width,height) area = width × height diagonal = √(width² + height²)
RAW VALUES. `shortSide` здесь — исходная геометрия. Нормированные единицы и `CanvasNormalizationContext` канонизируются только в 6.03.

Aspect ratio без вкусовой интерпретации

03 / aspect ratio

6.00 фиксирует две эквивалентные числовые формы: обычное отношение и log-ratio.

Ratio

r = width / height r > 0 not clamped not scored

Log-ratio

ℓ = ln(width / height) swap axes: r' = 1/r ℓ' = -ℓ
NO ORIENTATION PREFERENCE. `r>1` не означает «landscape лучше», `r<1` не означает «portrait хуже». Поведение форматов принадлежит 6.01.

4:5, 16:9, 1:1 — только когда это exact

04 / reduced ratio

Readable ratio pair допускается только для явно целочисленной raster extent.

For integer raster dimensions: g = gcd(widthPx,heightPx) reducedIntegerRatio = [ widthPx / g, heightPx / g ] Examples: 1080×1350 → 4:5 1920×1080 → 16:9 1080×1080 → 1:1 For arbitrary floating CANVAS_UNIT: reducedIntegerRatio = N/A
NO RATIONAL GUESSING. `1.333333` не превращается молча в `4:3`. Approximation policy, если понадобится, должна иметь отдельный owner/provenance.

CanvasCoordinateFrame

05 / coordinate frame

Продолжаем общую для 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]
CUSTOM FRAME. Другой coordinate frame допустим только через explicit adapter. 6.00 не делает скрытый flip/rotation.

CanvasDomainBoundary

06 / downstream domain

Это закрывает давний внешний dependency Topic 5: full-canvas CompositionSpaceDomain теперь имеет canonical upstream source.

CanvasDomainBoundary {
  boundaryRef:
    "canvas::boundary",

  domainRef:
    "canvas::domain",

  coordinateFrame,
  polygon,
  area,
  provenance
}
When Topic5 analyzes the full canvas: CompositionSpaceDomain.boundaryRef ← CanvasDomainBoundary.boundaryRef If Topic5 analyzes crop/viewport/custom domain: it uses another explicit domain adapter and does NOT mutate CanvasDescriptor.

Axis relation ≠ format behavior

07 / exact axis relation

6.00 может констатировать только exact relation между width и height.

Raw descriptorConditionBehavior owner
WIDTH_EQ_HEIGHTW = H6.01
WIDTH_GT_HEIGHTW > H
WIDTH_LT_HEIGHTW < H
NO NEAR-SQUARE HEURISTIC YET. 1000×999 остаётся exact `WIDTH_GT_HEIGHT`. Нужен ли tolerance и как при нём адаптировать layout — вопрос 6.01.

Что сознательно не делаем

08 / ownership firewall

Тема 6 разбита MAIN именно для того, чтобы не смешать геометрию формата с физикой и adaptation.

6.01

Orientation behavior

square / portrait / landscape policies.

6.02

Physical

mm, A-series, DPI/PPI, viewing context.

6.03

Normalization

cross-format normalized coordinates and scale invariance.

6.04

Adaptation

format-change hooks and Topic6 regression.

Не забираем чужие владельения

09 / cross-topic boundaries

Canvas geometry становится upstream context, но не новым super-owner всей сцены.

ConceptOwner
visual massTopic 4
occupied/free-space geometryTopic 5
canvas extent/aspect ratio6.00
safe zones / bleedTopic 7
grid occupancyTopic 8
object transformsTopic 3 / Core adapter boundary
global balance / hierarchy / eye-flowfuture global owners

Dirty graph

10 / recompute

Изменение 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: три холста, одна геометрическая модель

11 / visual lab

Показываем только raw format geometry — без утверждений о том, где должен стоять контент.

A · 1:1 1080×1080 · r=1 · log r=0 axis: WIDTH_EQ_HEIGHT B · 4:5 1080×1350 · r=.8 axis: WIDTH_LT_HEIGHT C · 16:9 1920×1080 · r=1.777… axis: WIDTH_GT_HEIGHT canonical origin = top-left · +x right · +y down aspect ratio = geometry descriptor, not layout preference 6.01 decides behavior · 6.02 physical metadata · 6.03 normalization · 6.04 adaptation full-canvas boundary can feed Topic5 CompositionSpaceDomain

Reference geometry tests

12 / deterministic tests

Проверяем exact formulas, reciprocal/swap invariants, common-scale invariance, integer ratio, N/A semantics и ownership boundaries.

Tests not run yet.

DATA FOR LAYOUT ENGINE

13 / machine contract

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"
  }
}
ARCHITECTURE CHECKPOINT · 6.00 OWNS EXPLICIT CANVAS EXTENT, COORDINATE FRAME, RECTANGULAR CANVAS DOMAIN AND INTRINSIC ASPECT-RATIO GEOMETRY ONLY. 6.01 OWNS SQUARE/PORTRAIT/LANDSCAPE BEHAVIOR; 6.02 PHYSICAL SIZE/A-SERIES/DPI/VIEWING CONTEXT; 6.03 NORMALIZATION/SCALE-INVARIANCE CONTRACT; 6.04 ADAPTATION HOOKS/TESTS. CANVAS EXTENT IS NOT CONTENT BOUNDS. ABSTRACT/Raster ASPECT MISMATCH REQUIRES EXPLICIT RASTER MAPPING. RAW SHORTSIDE IS NOT YET A NORMALIZATION CONTRACT. TOPIC7 SAFE/BLEED, TOPIC8 GRID OCCUPANCY, TOPIC5 FREE SPACE, TOPIC4 MASS AND GLOBAL BALANCE/HIERARCHY/EYE-FLOW REMAIN SEPARATE. NO BEAUTYSCORE.
VISITS / ...