SimpleCap - Selection History Expose [6] 座標系変換(flippedからnon-flippedへ)

2010年10月31日日曜日 | Published in | 0 コメント

このエントリーをはてなブックマークに追加

[前回] Cocoaの日々: SimpleCap - Selection History Expose [5] Core Animation で表示

今回は座標系変換について。


flippedから non-flippedへ


SimpleCap のメインとなるビューの CaptureView は、NSViewのサブクラスなので通常は座標系は左下原点だが、フリップ(flipped)させているので左上原点となっている。

一方、Core Animation(CALayer)の座標系は左下が原点となっている。

この為、CaptureView の座標を使って CALayer へ描画する際は flippedな座標系から、non-flippedな座標系への変換が必要になる。


変換


ここでは矩形(NSRect or CGRect)を変換対象と考えてみる。NSRect flippedRect から nonFlippedRect へ変換する場合、スクリーンが1つの場合は簡単でこんな感じで求められる。
NSRect screenFrame = [[NSScreen mainScreen] frame];
nonFlippedRect = flippedRect;
nonFlippedRect.origin.y = screenFrame.size.height - flippedRect.origin.y - flippedRect.size.height;

やっかいなのはマルチスクリーンの場合。上記コードのmainScreen以外も考慮に入れる必要がある。

以前調査したようにスクリーンの配置の仕方によって各スクリーンが置かれる座標が異なる。

[参考情報] (旧) Cocoaの日々: β版バグ修正 - マルチスクリーン

今回は下記のケースはこの時の「b. SimpleCapのメインビューのローカル座標系」から「a. スクリーン座標系」への変換に該当する。

まず X座標については変換は不要。flippedの有無は Y座標のみ関係していて、それを除けば基本的に同じ座標系だから。

Y座標についてはサブ画面の位置によって次の2つのケースを考える。
[a] サブ画面が上に載るケース
[b] サブ画面が下に載るケース

変換の考え方は原点を中心に考えるとわかりやすい。
[参考情報] (旧) Cocoaの日々: β版バグ修正 - マルチスクリーン(その2)

そのアプローチで考えた数式は次の通り。
cx1 = lx1;
 cy1 = sy2 - ly1 - lh1;
・スクリーン座標系上での全画面範囲(左下)-(右上):(sx1, sy1)-(sx2, sy2)
・fliipedな座標系内の NSRect:(lx1, ly1),(lw1, lh1)
・(non-flippedな)変換後の座標:(cx1,cy1)

スクリーン1つの場合と似ているが、その時のスクリーンの高さを起点にしていたのに対してマルチスクリーンの場合はそこにスクリーン全体の座標で補正している点。


確認


シングルスクリーンでは問題なし。マルチスクリーンは手元に無いため未確認...。

Responses

Leave a Response

人気の投稿(過去 30日間)