- 用紙設計キャンバス(1/100mm 基準)・テキスト/画像/矩形/直線アイテム - コピー/複製/Zオーダー/整列/グリッドスナップ、原紙(下絵)読込と印刷可否 - GDI 直接印刷、.otz 保存/再読込(版数つき) - MFC/CRT 静的リンクで VS2022 IDE から F5 デバッグ可
80 lines
3.2 KiB
C++
80 lines
3.2 KiB
C++
// CoordMap.h : 物理単位(1/100mm) ⇔ デバイス単位(ピクセル) 変換
|
|
//
|
|
// 設計の背骨:
|
|
// - すべてのジオメトリ(用紙サイズ・各アイテムの矩形)は 1/100 mm の整数で保持する。
|
|
// - 画面エディタも印刷(OnPrint)も「同じ」描画コード Draw(CDC&, CoordMap&) を呼ぶ。
|
|
// 違いはこの CoordMap が保持する DPI とズーム倍率だけ。
|
|
// - これにより、画面(≒96dpi)とサーマルラベルプリンタ(≒203dpi)で
|
|
// 同一レイアウトが物理的に正しいサイズで出力される。
|
|
//
|
|
// 単位系メモ: 1 inch = 25.4 mm = 2540 (1/100mm)
|
|
#pragma once
|
|
|
|
class CoordMap
|
|
{
|
|
public:
|
|
// dpiX/dpiY : 出力デバイスの解像度(GetDeviceCaps(LOGPIXELSX/Y))
|
|
// zoom : 画面表示倍率(印刷時は 1.0)
|
|
// originDevX/Y : デバイス座標の原点オフセット(スクロール量や印刷可能領域オフセット)
|
|
CoordMap(int dpiX = 96, int dpiY = 96, double zoom = 1.0,
|
|
int originDevX = 0, int originDevY = 0)
|
|
: m_dpiX(dpiX), m_dpiY(dpiY), m_zoom(zoom),
|
|
m_originX(originDevX), m_originY(originDevY)
|
|
{
|
|
}
|
|
|
|
void SetZoom(double zoom) { m_zoom = zoom; }
|
|
double Zoom() const { return m_zoom; }
|
|
|
|
void SetOrigin(int devX, int devY) { m_originX = devX; m_originY = devY; }
|
|
|
|
// 1/100mm → デバイス(ピクセル)。原点オフセットとズームを適用。
|
|
int MmToDevX(int hu) const { return m_originX + ScaleX(hu); }
|
|
int MmToDevY(int hu) const { return m_originY + ScaleY(hu); }
|
|
|
|
// 寸法(長さ)変換: 原点オフセットを加えない
|
|
int LenToDevX(int hu) const { return ScaleX(hu); }
|
|
int LenToDevY(int hu) const { return ScaleY(hu); }
|
|
|
|
CRect MmToDev(const CRect& huRect) const
|
|
{
|
|
return CRect(MmToDevX(huRect.left), MmToDevY(huRect.top),
|
|
MmToDevX(huRect.right), MmToDevY(huRect.bottom));
|
|
}
|
|
|
|
CPoint MmToDev(const CPoint& huPt) const
|
|
{
|
|
return CPoint(MmToDevX(huPt.x), MmToDevY(huPt.y));
|
|
}
|
|
|
|
// デバイス(ピクセル) → 1/100mm
|
|
int DevToMmX(int dev) const { return UnscaleX(dev - m_originX); }
|
|
int DevToMmY(int dev) const { return UnscaleY(dev - m_originY); }
|
|
|
|
CPoint DevToMm(const CPoint& devPt) const
|
|
{
|
|
return CPoint(DevToMmX(devPt.x), DevToMmY(devPt.y));
|
|
}
|
|
|
|
// ポイント(1pt = 1/72inch) → デバイス上のフォント高さ(論理ピクセル, ズーム込み)
|
|
int PointToDevHeight(double pt) const
|
|
{
|
|
// pt → 1/100mm → デバイス
|
|
int hu = (int)(pt * 2540.0 / 72.0 + 0.5);
|
|
return LenToDevY(hu);
|
|
}
|
|
|
|
private:
|
|
// hu(1/100mm) → デバイス: dev = hu / 2540 * dpi * zoom
|
|
int ScaleX(int hu) const { return (int)((double)hu * m_dpiX * m_zoom / 2540.0 + (hu >= 0 ? 0.5 : -0.5)); }
|
|
int ScaleY(int hu) const { return (int)((double)hu * m_dpiY * m_zoom / 2540.0 + (hu >= 0 ? 0.5 : -0.5)); }
|
|
int UnscaleX(int dev) const { return (int)((double)dev * 2540.0 / (m_dpiX * m_zoom) + (dev >= 0 ? 0.5 : -0.5)); }
|
|
int UnscaleY(int dev) const { return (int)((double)dev * 2540.0 / (m_dpiY * m_zoom) + (dev >= 0 ? 0.5 : -0.5)); }
|
|
|
|
int m_dpiX;
|
|
int m_dpiY;
|
|
double m_zoom;
|
|
int m_originX;
|
|
int m_originY;
|
|
};
|