diff --git a/src/SheetMe.Designer/Diagnostics/ClearTypeCheck.cs b/src/SheetMe.Designer/Diagnostics/ClearTypeCheck.cs
index 80d78ff..bbe1d44 100644
--- a/src/SheetMe.Designer/Diagnostics/ClearTypeCheck.cs
+++ b/src/SheetMe.Designer/Diagnostics/ClearTypeCheck.cs
@@ -73,6 +73,14 @@ internal static class ClearTypeCheck
if (target is { ActualWidth: > 0 })
{
samples.Add((label, target, true));
+ // ── 흐림의 두 번째 축 ──
+ // 색 번짐이 있어도(=ClearType 켜짐) TextFormattingMode 가 Ideal 이면
+ // 글리프가 픽셀 격자에 안 맞아 11~14px 글자가 눌린 듯 흐려 보인다.
+ // 색 번짐을 세는 방식으로는 두 값이 구분되지 않는다 — 그래서 두 번 놓쳤다.
+ // 이건 픽셀이 아니라 속성 값으로 잠근다.
+ var mode = TextOptions.GetTextFormattingMode(target);
+ Check($"{label} → 화면 글자는 Display 로 그린다",
+ mode == TextFormattingMode.Display, $"실제 {mode}");
}
else
{
diff --git a/src/SheetMe.Designer/Diagnostics/EditSmoke.cs b/src/SheetMe.Designer/Diagnostics/EditSmoke.cs
index 07b9b6e..32d5f35 100644
--- a/src/SheetMe.Designer/Diagnostics/EditSmoke.cs
+++ b/src/SheetMe.Designer/Diagnostics/EditSmoke.cs
@@ -79,6 +79,24 @@ public static class EditSmoke
}
}
+ /// 시각 트리에서 첫 TextBlock — 없으면 null
+ private static System.Windows.Controls.TextBlock? FindFirstTextBlock(DependencyObject root)
+ {
+ if (root is System.Windows.Controls.TextBlock block)
+ {
+ return block;
+ }
+ var count = System.Windows.Media.VisualTreeHelper.GetChildrenCount(root);
+ for (var i = 0; i < count; i++)
+ {
+ if (FindFirstTextBlock(System.Windows.Media.VisualTreeHelper.GetChild(root, i)) is { } found)
+ {
+ return found;
+ }
+ }
+ return null;
+ }
+
public static int Run(string reportPath)
{
var lines = new List();
@@ -426,6 +444,37 @@ public static class EditSmoke
$"요소 {livePages} → {liveAfterAdd} (안 늘면 생성자에서 한 번만 그린 것)");
live.Close();
+ // 종이 글자는 Display 로 바뀌지 않았는가 — 대조군이자 회귀 방어다.
+ // 화면 UI 를 Display 로 돌리면서 종이까지 끌려가면 글리프 자릿수가 달라져
+ // 레거시와 다른 지면이 된다. --db-render md5 가 잠그고 있지만
+ // 그건 서식 하나뿐이므로 여기서 속성 값으로도 못 박는다.
+ {
+ var paperPage = new FormDocument();
+ var paperOnly = new FormPage { Width = 720, Height = 856 };
+ paperPage.Pages.Add(paperOnly);
+ var paperLabel = new ControlElement
+ {
+ Type = "Label", Id = "종이글자",
+ Bounds = new LayoutRect { X = 20, Y = 20, W = 200, H = 20 },
+ };
+ paperLabel.Props.SetText("Text", "종이");
+ paperOnly.Controls.Add(paperLabel);
+ var paperVm = new DesignerViewModel(paperPage);
+ var paperVisual = (System.Windows.FrameworkElement)
+ Services.PrintService.BuildPageVisual(paperVm.Pages[0]);
+ paperVisual.Measure(new System.Windows.Size(720, 856));
+ paperVisual.Arrange(new Rect(0, 0, 720, 856));
+ paperVisual.UpdateLayout();
+ var paperBlock = FindFirstTextBlock(paperVisual);
+ Check("종이 글자는 Ideal 을 유지한다(화면 Display 와 분리)",
+ paperBlock is not null
+ && System.Windows.Media.TextOptions.GetTextFormattingMode(paperBlock)
+ == System.Windows.Media.TextFormattingMode.Ideal,
+ paperBlock is null
+ ? "종이에서 TextBlock 을 못 찾아 판정 불가"
+ : System.Windows.Media.TextOptions.GetTextFormattingMode(paperBlock).ToString());
+ }
+
// 태그가 종이에서 값이 되는가.
// 지금까지 미리보기는 태그를 글자 그대로 찍었다 — PAT_이름 이 종이에 그렇게 인쇄됐다.
// 해석기를 붙이면 값이 나오는 것은 값으로, 못 나오는 것은 사유로 바뀌어야 한다
diff --git a/src/SheetMe.Designer/Themes/DesignerTheme.xaml b/src/SheetMe.Designer/Themes/DesignerTheme.xaml
index 386df64..68c080f 100644
--- a/src/SheetMe.Designer/Themes/DesignerTheme.xaml
+++ b/src/SheetMe.Designer/Themes/DesignerTheme.xaml
@@ -28,6 +28,18 @@
+
+
@@ -37,7 +49,12 @@