陰影
陰影は、図 7-1 に示すように、陰影がグラフィックスオブジェクト上の光源キャストの効果を模倣するように、グラフィックスオブジェクトの下にペイントされ、オフセットされたイメージです。テキストに陰影をつけることもできます。陰影は、イメージを 3 次元または浮遊しているように見せることができます。
図 7-1 陰影
陰影には 3 つの特徴があります。
- 陰影がイメージからどのくらい水平方向にずれているかを指定する x オフセット。
- 陰影がイメージからどのくらい垂直方向にずれているかを指定する y オフセット。
- 図 7-2 の左側に示すように、イメージに硬い縁があるか、図の右側に示すように拡散した縁があるかを指定するブラー(blur) 値。
この章では、陰影の仕組みを説明し、Quartz 2D API を使用してそれらを作成する方法を示します。
図 7-2 ブラー(blur) のない陰影と柔らかい縁の陰影
陰影の仕組み
Quartz での陰影はグラフィックス状態の一部です。CGContextSetShadow 関数を呼び出し、グラフィックスコンテキスト、オフセット値、およびブラー値を渡します。陰影付けが設定された後、描画するオブジェクトには、デバイスの RGB 色空間に 1/3 のアルファ値を持った黒色で描かれた陰影が付きます。つまり、{0、0、0、1.0/3.0} に設定された RGBA 値を使用して陰影が描画されます。
CGContextSetShadowWithColor 関数を呼び出して、グラフィックスコンテキスト、オフセット値、ブラー(blur) 値、および CGColor オブジェクトを渡して、色付き陰影を描くことができます。色に指定する値は、描画する色空間によって異なります。
CGContextSetShadow または CGContextSetShadowWithColor 関数を呼び出す前にグラフィックス状態を保存すると、グラフィックス状態を復元して陰影付けをオフにできます。陰影の色を NULL に設定することによって、陰影を無効にすることもできます。
コンテキストに基づいて変化する陰影描画規則
先に説明したオフセットは、陰影を投じたイメージに関連して影陰影の位置を指定します。これらのオフセットはコンテキストによって解釈され、影の位置を計算するために使用されます。
- 正の x オフセットは、陰影がグラフィックスオブジェクトの右側にあることを示します。
- Mac OS X では、正の y オフセットは上方向の変位を示します。これは、Quartz 2D のデフォルトの座標系に一致します。
- iOS では、アプリケーションが Quartz 2D API を使用して PDF またはビットマップコンテキストを作成する場合、正の y オフセットは上方向の変位を示します。
- iOS では、UIView オブジェクトによって作成されたグラフィックスコンテキストや UIGraphicsBeginImageContextWithOptions 関数を呼び出して作成されたコンテキストなど、UIKit によってグラフィックスコンテキストが作成された場合、正の y オフセットは下方向の変位を示します。これは、UIKit 座標系の描画規則に一致します。
- 陰影の描画規則は、現在の変換配列の影響を受けません。
陰影を用いたペイント
陰影を用いてペイントするには、以下の手順に従って下さい。
- グラフィックス状態を保存します。
- CGContextSetShadow 関数を呼び出し、適切な値を渡します。
- 陰影を適用するすべての描画を実行します。
- グラフィックス状態を復元します。
色付きの陰影を用いてペイントするには、以下の手順に従って下さい。
- グラフィックス状態を保存します。
- CGColorSpace オブジェクトを作成して、Quartz が陰影の色値を正しく解釈するようにします。
- 使用する陰影の色を指定する CGColor オブジェクトを作成します。
- CGContextSetShadowWithColor 関数を呼び出し、適切な値を渡します。
- 陰影を適用するすべての描画を実行します。
- グラフィックス状態を復元します。
図 7-3 の 2 つの長方形は陰影付きで描画されています。1 つは色付きの影です。
図 7-3 色付きの陰影と灰色の陰影
リスト 7-1 の関数は、図 7-3 に示す長方形を描くように陰影を設定する方法を示しています。番号付きのコード行の詳細な説明は、リストの後に示します。
リスト 7-1 陰影を設定する関数
void MyDrawWithShadows (CGContextRef myContext, // 1 CGFloat wd, CGFloat ht); { CGSize myShadowOffset = CGSizeMake (-15, 20);// 2 CGFloat myColorValues[] = {1, 0, 0, .6};// 3 CGColorRef myColor;// 4 CGColorSpaceRef myColorSpace;// 5 CGContextSaveGState(myContext);// 6 CGContextSetShadow (myContext, myShadowOffset, 5); // 7 // Your drawing code here// 8 CGContextSetRGBFillColor (myContext, 0, 1, 0, 1); CGContextFillRect (myContext, CGRectMake (wd/3 + 75, ht/2 , wd/4, ht/4)); myColorSpace = CGColorSpaceCreateDeviceRGB ();// 9 myColor = CGColorCreate (myColorSpace, myColorValues);// 10 CGContextSetShadowWithColor (myContext, myShadowOffset, 5, myColor);// 11 // Your drawing code here// 12 CGContextSetRGBFillColor (myContext, 0, 0, 1, 1); CGContextFillRect (myContext, CGRectMake (wd/3-75,ht/2-100,wd/4,ht/4)); CGColorRelease (myColor);// 13 CGColorSpaceRelease (myColorSpace); // 14 CGContextRestoreGState(myContext);// 15 }
コードの動作は以下の通りです。
- グラフィックスコンテキストと、長方形を構築するときに使用する幅と高さという 3 つのパラメータをとります。
- 陰影のオフセット値を含む CGSize オブジェクトを宣言して作成します。これらの値は、オブジェクトの左に 15 ユニット、オブジェクトの上に 20 ユニットの陰影オフセットを指定します。
- 色値の配列を宣言します。この例では RGBA を使用していますが、Quartz が値を正しく解釈するために必要な色空間と共に Quartz に渡されるまで、これらの値は意味をなさないでしょう。
- 色参照のための記憶域を宣言します。
- 色空間参照のための記憶域を宣言します。
- 後で復元できるように、現在のグラフィック状態を保存します。
- 陰影に、以前に宣言されたオフセット値を設定し、ブラー(blur) 値を 5 に設定し、これは柔らかい陰影の端を指示します。陰影は {0、0、0、1/3} の RGBA 値を持つ灰色で表示されます。
- 次の 2 行のコードは、図 7-3 の右側に長方形を描きます。これらの行を、あなた独自の図面コードで置き換えられます。
- デバイスの RGB 色空間を作成します。CGColor オブジェクトを作成するときは、色空間を指定する必要があります。
- 以前に宣言したデバイス RGB 色空間と RGBA 値を提供して、CGColor オブジェクトを作成します。このオブジェクトは陰影の色を指定し、この場合それはアルファ値 0.6 の赤です。
- 色付きの陰影を設定し、作成したばかりの赤色を指定します。陰影は以前に作成されたオフセットと、柔らかい陰影の端を示すブラー(blur) 値 5 を使用します。
- 次の 2 行のコードは、図 7-3 の左側に長方形を描きます。これらの行は、あなた独自の図面コードで置き換えられます。
- 色オブジェクトが不要になったため、そのオブジェクトを解放します。
- 色空間オブジェクトが不要になったため、そのオブジェクトを解放します。
- 陰影を設定する前の状態にグラフィック状態を復元します。