ページ

2008年3月21日金曜日

Clipping

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

画面キャプチャで複数ウィンドウを扱う時、選んだウィンドウをすべてハイライト表示にさせたい。その為にはマスク処理を見直す必要がある。そこでいろいろと試している。

今回は NSBezierPath のクリッピングを試すサンプルを作ってみた。

ClipSample.zip

実行すると壁紙のJPEG画像が表示される。


ここでボタンを押すと、円形にくりぬかれる。



NSViewの描画コードは次のとおり。
MyView.h

- (void)drawRect:(NSRect)rect {
if (_is_clip) {
[NSGraphicsContext saveGraphicsState];
NSBezierPath* path = [NSBezierPath bezierPath];
[path appendBezierPathWithOvalInRect:NSMakeRect(0, 0, 480, 360)];
[path addClip];
}

NSImage* image = [[NSImage alloc] initWithContentsOfFile:@"/Library/Desktop Pictures/Nature/Rocks.jpg"];
[self lockFocus];
[image compositeToPoint:NSZeroPoint operation:NSCompositeSourceOver];
[self unlockFocus];
[image release];

if (_is_clip) {
[NSGraphicsContext restoreGraphicsState];
}

}


ボタンを押すと _is_clipping が YES/NOと入れ替わる。YESの場合は NSBezierPath のクリッピングを実行している。今回は NSBezierPath#appendBezierPathWithOvalInRect: を使い円形のパスを作成した後、 #addClip で描画領域を限定している。この後の NSImageの描画は、このクリップ領域が有効に働いて、結果円形でくり抜いたような表示となる。

NSGraphicsContext#storeGraphicsState と #restoreGraphicsState はコンテキストの保存と復帰で使っている。これを行わないとウィンドウ内の描画がおかしくなる(実際 restoreGraphicsStateをしないと、ボタンの表示位置がおかしな場所になったりする)。


参照情報
ADC "Cocoa Drawing Guide: Setting the Clipping Region"

- - - -
クリップ領域はてっきり四角(Rect)しかできないと思っていたが、NSBezierPathを使うことでかなり複雑なことができそうだ。これを使って複数ウィンドウ選択のハイライトに挑戦してみよう。