Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@ All notable changes to Q1View are documented here. Releases follow [semantic ver

---

## [2.7.27] — 2026-10-04

### Changed
- Windows Viewer and Comparator: finish Pretendard typography for help prose, align shortcut columns using measured text with wrapping and scroll access, and share DPI/system-text-size-aware font roles while keeping numeric monospace and native Windows fonts. (issue #117)

- Windows Viewer and Comparator: use normal-weight Pretendard in the main application menus with wider horizontal spacing and roomier dropdown rows, preserving native menu tracking, command shortcuts, selection states and accessible names. (issue #117)

- Windows Viewer and Comparator: match window titles to 14 DIP Pretendard menus using a client-painted title with native DWM window buttons, accessible menu buttons, wrapped narrow-window menu rows and retained popup commands; preserve the same application menu across Viewer full-screen transitions and use the native frame in high-contrast mode. (issue #117)

- Windows Comparator: apply the shared Pretendard popup typography to pane color-format selection and pane context menus, which are independent of the main application menu. (issue #117)

- Windows Comparator: limit the metrics graph to one third of the content height so enlarged Windows text leaves useful space for the compared images. (issue #117)

---

## [2.7.26] — 2026-09-27

### Fixed
Expand Down Expand Up @@ -460,7 +475,8 @@ All notable changes to Q1View are documented here. Releases follow [semantic ver

---

[Unreleased]: https://github.com/chammoru/Q1View/compare/v2.7.26...HEAD
[Unreleased]: https://github.com/chammoru/Q1View/compare/v2.7.27...HEAD
[2.7.27]: https://github.com/chammoru/Q1View/compare/v2.7.26...v2.7.27
[2.7.26]: https://github.com/chammoru/Q1View/compare/v2.7.25...v2.7.26
[2.7.25]: https://github.com/chammoru/Q1View/compare/v2.7.24...v2.7.25
[2.7.24]: https://github.com/chammoru/Q1View/compare/v2.7.23...v2.7.24
Expand Down
16 changes: 15 additions & 1 deletion Comparator/Comparator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ BOOL CComparatorApp::InitInstance()
Gdiplus::GdiplusStartup(&mGdiplusToken, &gdiplusStartupInput, NULL);

SetRegistryKey(_T("Chammoru"));
#ifdef Q1VIEW_COMPARER_TESTS
SetRegistryKey(_T("Q1ViewComparerTests"));
#endif
LoadStdProfileSettings(4); // Load standard INI file options (including MRU)

// Register the application's document templates. Document templates
Expand Down Expand Up @@ -112,13 +115,24 @@ BOOL CComparatorApp::InitInstance()

// call DragAcceptFiles only if there's a suffix
// In an SDI app, this should occur after ProcessShellCommand
#ifdef Q1VIEW_COMPARER_TESTS
extern int RunComparerTypographyTests();
mTestExitCode = RunComparerTypographyTests();
m_pMainWnd->SendMessage(WM_CLOSE);
return FALSE;
#endif
return TRUE;
}

int CComparatorApp::ExitInstance()
{
Gdiplus::GdiplusShutdown(mGdiplusToken);
return CWinApp::ExitInstance();
const int result = CWinApp::ExitInstance();
#ifdef Q1VIEW_COMPARER_TESTS
return mTestExitCode;
#else
return result;
#endif
}


Expand Down
3 changes: 3 additions & 0 deletions Comparator/Comparator.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ class CComparatorApp : public CWinApp
afx_msg void OnFileOpen();

private:
#ifdef Q1VIEW_COMPARER_TESTS
int mTestExitCode = 0;
#endif
ULONG_PTR mGdiplusToken;
};

Expand Down
6 changes: 6 additions & 0 deletions Comparator/Comparator.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,12 @@ copy /Y "$(ProjectDir)..\assets\fonts\Pretendard-LICENSE.txt" "$(TargetDir)Fonts
<Project>{9f2e09be-9cc5-4460-80a0-0ab612f78ba0}</Project>
</ProjectReference>
</ItemGroup>
<ItemDefinitionGroup Condition="'$(Q1ViewComparerTests)'=='true'">
<ClCompile><PreprocessorDefinitions>Q1VIEW_COMPARER_TESTS;%(PreprocessorDefinitions)</PreprocessorDefinitions></ClCompile>
</ItemDefinitionGroup>
<ItemGroup Condition="'$(Q1ViewComparerTests)'=='true'">
<ClCompile Include="..\Tests\ComparerTypographyIntegrationTests.cpp"><PrecompiledHeader>NotUsing</PrecompiledHeader></ClCompile>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
Expand Down
65 changes: 34 additions & 31 deletions Comparator/ComparatorView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,19 @@ BEGIN_MESSAGE_MAP(CComparatorView, CScrollView)
ON_WM_RBUTTONUP()
END_MESSAGE_MAP()

LRESULT CComparatorView::WindowProc(UINT message, WPARAM wp, LPARAM lp)
{
if (message == WM_INITMENUPOPUP && !HIWORD(lp))
mUiPopupMenus.SyncPopup(m_hWnd, reinterpret_cast<HMENU>(wp));
if (message == WM_MEASUREITEM && mUiPopupMenus.Measure(reinterpret_cast<MEASUREITEMSTRUCT*>(lp))) return TRUE;
if (message == WM_DRAWITEM && mUiPopupMenus.Draw(reinterpret_cast<DRAWITEMSTRUCT*>(lp))) return TRUE;
if (message == WM_MENUCHAR) {
LRESULT result;
if (mUiPopupMenus.MenuChar(LOWORD(wp), reinterpret_cast<HMENU>(lp), result)) return result;
}
return CScrollView::WindowProc(message, wp, lp);
}

// Right-click popup items, mirroring the MFC Viewer's mouse menu. The command
// IDs are ID_MOUSEMENU_START + this index.
enum QMouseMenuId {
Expand Down Expand Up @@ -246,6 +259,7 @@ void CComparatorView::OnDraw(CDC *pDC)

if (!mMemDC.GetSafeHdc())
return;
q1view::WindowsUiDcState dcState(mMemDC.GetSafeHdc());

if (pDoc->mWDst < mWCanvas || pDoc->mHDst < mHCanvas)
mMemDC.FillSolidRect(CRect(0, 0, mWCanvas, mHCanvas), Q1UI_COLOR_CANVAS_BG);
Expand Down Expand Up @@ -628,13 +642,8 @@ void CComparatorView::DrawSelection(CDC *pDC, CComparatorDoc *pDoc)

// Size readout (width x height in source pixels) pinned just inside the
// rectangle's top-left corner, on a translucent plate for legibility.
LOGFONT lf;
mDefPixelTextFont.GetLogFont(&lf);
lf.lfHeight = 14;
lf.lfWeight = FW_NORMAL;
CFont sizeFont;
sizeFont.CreateFontIndirect(&lf);
CFont *prevFont = pDC->SelectObject(&sizeFont);
CFont *prevFont = pDC->SelectObject(CFont::FromHandle(
mUiFonts.Get(q1view::WindowsUiFontRole::Numeric, m_hWnd)));

CString label;
label.Format(_T("%d\x00D7%d"), r - l + 1, b - t + 1);
Expand Down Expand Up @@ -671,14 +680,8 @@ void CComparatorView::DrawCursorCoord(CDC *pDC, CComparatorDoc *pDoc, Comparator
? pDoc->mCursorY
: int((long long)pDoc->mCursorY * srcH / pDoc->mH);

LOGFONT lf;
mDefPixelTextFont.GetLogFont(&lf);
lf.lfHeight = 16;
lf.lfWeight = FW_NORMAL;
CFont coordFont;
coordFont.CreateFontIndirect(&lf);

CFont *prevFont = pDC->SelectObject(&coordFont);
CFont *prevFont = pDC->SelectObject(CFont::FromHandle(
mUiFonts.Get(q1view::WindowsUiFontRole::Numeric, m_hWnd)));

CString coord;
coord.Format(_T("x:%d,y:%d"), dispX, dispY);
Expand Down Expand Up @@ -799,19 +802,8 @@ void CComparatorView::DrawEmptyPane(CDC *pDC, CComparatorDoc *pDoc)
CRect canvas(0, mRcControls.bottom, mWClient, mHClient);
pDC->FillSolidRect(canvas, Q1UI_COLOR_CANVAS_BG);

LOGFONT lf;
mDefPixelTextFont.GetLogFont(&lf);
::lstrcpy(lf.lfFaceName, q1view::WindowsUiTextFontFamily());

CFont titleFont;
lf.lfHeight = 18;
lf.lfWeight = FW_SEMIBOLD;
titleFont.CreateFontIndirect(&lf);

CFont bodyFont;
lf.lfHeight = 13;
lf.lfWeight = FW_NORMAL;
bodyFont.CreateFontIndirect(&lf);
CFont *titleFont = CFont::FromHandle(mUiFonts.Get(q1view::WindowsUiFontRole::EmptyTitle, m_hWnd));
CFont *bodyFont = CFont::FromHandle(mUiFonts.Get(q1view::WindowsUiFontRole::Body, m_hWnd));

CString title(_T("Drop an image or video"));
CString body(_T("Use 2-4 panes to compare images, raw dumps, or video frames"));
Expand All @@ -824,10 +816,10 @@ void CComparatorView::DrawEmptyPane(CDC *pDC, CComparatorDoc *pDoc)
bodyRect.top = canvas.CenterPoint().y + 6;

pDC->SetBkMode(TRANSPARENT);
CFont *prevFont = pDC->SelectObject(&titleFont);
CFont *prevFont = pDC->SelectObject(titleFont);
pDC->SetTextColor(Q1UI_COLOR_TEXT);
pDC->DrawText(title, &titleRect, DT_SINGLELINE | DT_CENTER | DT_BOTTOM | DT_END_ELLIPSIS);
pDC->SelectObject(&bodyFont);
pDC->SelectObject(bodyFont);
pDC->SetTextColor(Q1UI_COLOR_TEXT_MUTED);
pDC->DrawText(body, &bodyRect, DT_SINGLELINE | DT_CENTER | DT_TOP | DT_END_ELLIPSIS);
pDC->SelectObject(prevFont);
Expand Down Expand Up @@ -1051,6 +1043,17 @@ void CComparatorView::OnSize(UINT nType, int cx, int cy)
return;

mRcControls.right = cx;
if (mCsQMenu.GetSafeHwnd() && mNameQMenu.GetSafeHwnd()) {
CRect measured(0, 0, 0, 0);
mCsQMenu.CalcRect(&measured);
const int padding = q1view::WindowsUiPixels(QMENUITEM_IN_MARGIN_H, q1view::WindowsUiDpi(m_hWnd));
mRcCsQMenu.SetRect(0, 0, measured.Width(), measured.Height() + padding);
mRcControls.bottom = mRcCsQMenu.bottom;
mCsQMenu.MoveWindow(mRcCsQMenu);
mRcNameQMenu.left = mRcCsQMenu.right;
mRcNameQMenu.top = 0;
mRcNameQMenu.bottom = mRcControls.bottom;
}

mWClient = cx;
mHClient = cy;
Expand Down Expand Up @@ -1263,7 +1266,7 @@ void CComparatorView::OnCsChange(UINT nID)
CComparatorDoc* pDoc = GetDocument();

CString str;
mCsMenu.GetMenuString(nID, str, MF_BYCOMMAND);
str = mUiPopupMenus.Text(mCsMenu.GetSafeHmenu(), nID).c_str();
str.MakeLower();

const struct qcsc_info * const ci =
Expand Down
5 changes: 5 additions & 0 deletions Comparator/ComparatorView.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// CComparatorView view
#include "QMenuItem.h"
#include "QViewerCmn.h"
#include "Q1UiFontWin.h"
#include "Q1UiMenuWin.h"

namespace Gdiplus {
class Pen;
Expand All @@ -29,6 +31,7 @@ class CComparatorView : public CScrollView
protected:
virtual void OnDraw(CDC *pDC); // overridden to draw this view
virtual void OnInitialUpdate(); // first time after construct
virtual LRESULT WindowProc(UINT message, WPARAM wp, LPARAM lp) override;
std::vector<CComparatorView *> GetOhterViews(CComparatorDoc *pDoc);
ComparatorPane *GetPane(CComparatorDoc* pDoc) const;

Expand All @@ -54,6 +57,8 @@ class CComparatorView : public CScrollView
int mRgbBufSize;
BYTE *mRgbBuf;
CFont mDefPixelTextFont;
q1view::WindowsUiFontCache mUiFonts;
q1view::WindowsUiMenus mUiPopupMenus;
CFont mPixelTextFont;
LONG mPixelTextFontHeight;
CDC mMemDC;
Expand Down
1 change: 1 addition & 0 deletions Comparator/FrmInfoView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ int CFrmInfoView::OnCreate(LPCREATESTRUCT lpCreateStruct)

void CFrmInfoView::OnDraw(CDC* pDC)
{
q1view::EnsureWindowsUiFont(mStateFont, q1view::WindowsUiFontRole::Body, m_hWnd);
CComparatorDoc *pDoc = GetDocument();

CString frameState = pDoc->mFrmState;
Expand Down
22 changes: 14 additions & 8 deletions Comparator/FrmsInfoView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@ static void DrawCenteredMessage(CDC *pDC, CRect rect, CFont *titleFont, CFont *b

void CFrmsInfoView::OnDraw(CDC* pDC)
{
q1view::EnsureWindowsUiFont(mLabelFont, q1view::WindowsUiFontRole::Numeric, m_hWnd);
q1view::EnsureWindowsUiFont(mResultFont, q1view::WindowsUiFontRole::Status, m_hWnd);
q1view::EnsureWindowsUiFont(mBodyFont, q1view::WindowsUiFontRole::Body, m_hWnd);
CComparatorDoc* pDoc = GetDocument();

CDC memDC;
Expand All @@ -98,7 +101,7 @@ void CFrmsInfoView::OnDraw(CDC* pDC)
size_t stepCount = pDoc->mMinFrames;
if (stepCount <= 0) {
DrawCenteredMessage(&memDC, CRect(0, 0, mWClient, mHClient),
&mResultFont, &mLabelFont, _T("Metrics"),
&mResultFont, &mBodyFont, _T("Metrics"),
_T("Open two sources to calculate PSNR or SSIM"));
pDC->BitBlt(0, 0, mWClient, mHClient, &memDC, 0, 0, SRCCOPY);

Expand All @@ -109,13 +112,14 @@ void CFrmsInfoView::OnDraw(CDC* pDC)
size_t itemCount = mPsnrCal->CalculateCoords(&mGraphRect, pMainFrm->mMetricIdx);
if (itemCount <= 0) {
DrawCenteredMessage(&memDC, CRect(0, 0, mWClient, mHClient),
&mResultFont, &mLabelFont, _T("Scanning"),
&mResultFont, &mBodyFont, _T("Scanning"),
_T("Per-frame measurements will appear as frames are processed"));
pDC->BitBlt(0, 0, mWClient, mHClient, &memDC, 0, 0, SRCCOPY);
return;
}

memDC.SetBkMode(TRANSPARENT);
mPsnrCal->UpdateFont(memDC.GetSafeHdc(), static_cast<HFONT>(mLabelFont.GetSafeHandle()));

mPsnrCal->DrawCmpResult(&memDC, &mResultFont);
mPsnrCal->DrawYLabel(&memDC, &mYLabelRect, &mLabelFont);
Expand Down Expand Up @@ -159,16 +163,18 @@ void CFrmsInfoView::Dump(CDumpContext& dc) const
void CFrmsInfoView::OnSize(UINT nType, int cx, int cy)
{
CView::OnSize(nType, cx, cy);
const UINT dpi = q1view::WindowsUiDpi(m_hWnd);
const double scale = q1view::WindowsUiSettings().Scale();
const int left = q1view::WindowsUiPixels(GRAPH_OUT_MARGIN_L, dpi, scale);
const int right = q1view::WindowsUiPixels(GRAPH_OUT_MARGIN_R, dpi, scale);
const int bottom = q1view::WindowsUiPixels(18, dpi, scale);

GetClientRect(&mGraphRect);
mGraphRect.DeflateRect(GRAPH_OUT_MARGIN_L,
GRAPH_OUT_MARGIN_T,
GRAPH_OUT_MARGIN_R,
GRAPH_OUT_MARGIN_B);
mGraphRect.DeflateRect(left, GRAPH_OUT_MARGIN_T, right, bottom);
mYLabelRect.SetRect(0,
Y_LABEL_MARGIN_T,
GRAPH_OUT_MARGIN_L,
cy - Y_LABEL_MARGIN_B);
left,
cy - bottom);
mAverageRect.SetRect(mGraphRect.right + AVG_MARGIN_L,
AVG_MARGIN_T,
cx - AVG_MARGIN_R,
Expand Down
2 changes: 1 addition & 1 deletion Comparator/FrmsInfoView.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class CFrmsInfoView : public CView
int mWClient, mHClient;
CRect mGraphRect, mYLabelRect, mAverageRect;
FileScanThread *mFileScanThread;
CFont mLabelFont, mResultFont;
CFont mLabelFont, mResultFont, mBodyFont;
ULONG_PTR mGdiplusToken;
MetricCal *mPsnrCal;

Expand Down
Loading
Loading