fix(viewer2d): correct Slug GPU text scale to match DWG cap-height

SlugTextBatch.add() scaled em-unit glyph outlines by the raw DWG
`height` value, but glyph ink only reaches capHeightEm (~0.74 em) of
the em box. Rendered cap height ended up ~26% short of spec (e.g. a
3.6-height TABLE cell text rendered at ~2.68), while the canvas-sprite
fallback already corrected for this via measured ascent. Divide by
capHeightEm so both paths agree.

Rebuilds dist2 (was stale since before the Entity selection/Property
Inspector/Layer panel work landed).
This commit is contained in:
minsung
2026-08-03 15:26:06 +09:00
parent b047dc44e2
commit fb8f7ca4eb
5 changed files with 5688 additions and 3 deletions
+100 -2
View File
@@ -96,8 +96,70 @@
}
#coords .lbl { color: var(--accent); margin-right: 6px; font-weight: 600; }
#coords .sep { color: var(--line); margin: 0 12px; }
/* 공통 패널 윈도우 스타일 (Properties & Layers - Draggable & Resizable) */
.cad-panel {
position: fixed; top: 56px; width: 320px; height: 480px;
min-width: 250px; min-height: 140px; max-width: 90vw; max-height: 90vh;
z-index: 15; background: rgba(22,27,34,.96); backdrop-filter: blur(12px);
border: 1px solid var(--line); border-radius: 10px; box-shadow: 0 10px 30px rgba(0,0,0,.5);
display: flex; flex-direction: column; overflow: hidden; resize: both;
transition: border-color .15s;
}
.cad-panel.collapsed {
height: 42px !important;
min-height: 42px !important;
max-height: 42px !important;
overflow: hidden !important;
resize: none !important;
}
.cad-panel .hdr {
padding: 10px 14px; border-bottom: 1px solid var(--line);
display: flex; align-items: center; justify-content: space-between;
background: rgba(13,17,23,.7); position: sticky; top: 0; z-index: 5;
cursor: grab; user-select: none; flex-shrink: 0;
}
.cad-panel .hdr:active { cursor: grabbing; }
.cad-panel .hdr h3 { margin: 0; font-size: 13px; font-weight: 700; color: var(--ink); display: flex; align-items: center; gap: 6px; }
.cad-panel .hdr-actions { display: flex; gap: 4px; align-items: center; }
.cad-panel .hdr-btn {
background: none; border: none; color: var(--muted); font-size: 13px;
cursor: pointer; padding: 2px 6px; border-radius: 4px; display: inline-flex;
align-items: center; justify-content: center; transition: all .15s;
}
.cad-panel .hdr-btn:hover { color: var(--ink); background: rgba(255,255,255,.1); }
#properties { right: 12px; }
#layers { right: 344px; display: none; }
#propBody { flex: 1; overflow-y: auto; display: flex; flex-direction: column; }
#layerBody { flex: 1; overflow-y: auto; display: flex; flex-direction: column; }
#layerList { flex: 1; overflow-y: auto; }
#zoomSelBtn {
font: 11px var(--sans); padding: 3px 8px; border-radius: 6px;
border: 1px solid var(--accent); background: rgba(63,185,80,.15); color: var(--accent);
cursor: pointer; display: none; align-items: center; gap: 4px; transition: all .15s;
}
#zoomSelBtn:hover { background: var(--accent); color: #fff; }
.layer-search-wrap { padding: 8px 10px; border-bottom: 1px solid var(--line); background: rgba(13,17,23,.3); }
.layer-search-input {
width: 100%; background: var(--bg); border: 1px solid var(--line);
border-radius: 6px; padding: 6px 10px; color: var(--ink); font-size: 12px;
outline: none; transition: border-color .15s;
}
.layer-search-input:focus { border-color: var(--accent); }
.layer-sub-actions {
display: flex; gap: 6px; padding: 6px 10px; border-bottom: 1px solid var(--line);
background: rgba(22,27,34,.5);
}
.layer-sub-btn {
font-size: 11px; padding: 2px 8px; border-radius: 4px; border: 1px solid var(--line);
background: transparent; color: var(--muted); cursor: pointer; transition: all .15s;
}
.layer-sub-btn:hover { color: var(--ink); border-color: var(--accent); background: rgba(63,185,80,.1); }
</style>
<script type="module" crossorigin src="/assets/index-B4PWk4UF.js"></script>
<script type="module" crossorigin src="/assets/index-CmUgC68r.js"></script>
</head>
<body>
<div id="app"></div>
@@ -114,6 +176,7 @@
<button id="fit" type="button">Fit (F)</button>
<button id="theme" type="button">Theme</button>
<button id="layersBtn" type="button">Layers</button>
<button id="propsBtn" type="button">Props (속성)</button>
<div id="status">ready</div>
</div>
@@ -123,7 +186,42 @@
<span class="lbl">Y</span><span id="coordY"></span>
</div>
<div id="layers"><h3>Layers</h3><div id="layerList"></div></div>
<!-- 레이어 (Layers) 관리 패널 -->
<div id="layers" class="cad-panel">
<div class="hdr">
<h3>
<span>🎨</span> 레이어 (Layers)
<span id="layerCount" style="font-family:var(--mono);font-size:11px;color:var(--muted);background:rgba(255,255,255,.08);padding:1px 6px;border-radius:4px;font-weight:400"></span>
</h3>
<div class="hdr-actions">
<button id="collapseLayersBtn" class="hdr-btn collapse-btn" type="button" title="접기"></button>
<button id="closeLayersBtn" class="hdr-btn" type="button" title="닫기"></button>
</div>
</div>
<div id="layerBody">
<div class="layer-search-wrap">
<input id="layerSearch" class="layer-search-input" type="text" placeholder="🔍 레이어 검색..." />
</div>
<div class="layer-sub-actions">
<button id="layerShowAll" class="layer-sub-btn" type="button">전체 켜기</button>
<button id="layerHideAll" class="layer-sub-btn" type="button">전체 끄기</button>
</div>
<div id="layerList"></div>
</div>
</div>
<!-- 속성 (Properties) 패널 -->
<div id="properties" class="cad-panel">
<div class="hdr">
<h3><span>📋</span> 속성 (Properties)</h3>
<div class="hdr-actions">
<button id="zoomSelBtn" type="button" title="선택 요소 위치로 확대">🔍 선택 확대</button>
<button id="collapsePropsBtn" class="hdr-btn collapse-btn" type="button" title="접기"></button>
<button id="closePropsBtn" class="hdr-btn" type="button" title="닫기"></button>
</div>
</div>
<div id="propBody"></div>
</div>
<aside id="recipe">
<h3>Module recipe</h3>