Android* 開発者向けラーニングシリーズ 9: SVG (Scalable Vector Graphics*) ライブラリーを使用してインテル® アーキテクチャー向け Android* でグラフィックをレンダリング
この記事は、インテル® デベロッパー・ゾーンに掲載されている「Intel for Android* Developers Learning Series #9:Using the Scalable Vector Graphics Library to Render Graphics on Android for Intel® Architecture」の日本語参考訳です。
SVG (Scalable Vector Graphics*) は XML ベースのファイル形式の仕様で、スタティックとダイナミック (つまり、インタラクティブまたは動画) の 2 次元ベクター・グラフィックス、テキスト、埋め込みラスター・グラフィックを表現します。SVG 仕様はロイヤルティー・フリーでベンダー中立のオープン標準です。1999 年から W3C (World Wide Web Consortium*) により開発が進められました。
SVG イメージとその動作は XML テキストファイルで定義します。このため、検索、インデックス作成、スクリプト化、さらに圧縮も可能です。SVG イメージは、通常のテキストエディターで XML ファイルとして作成および編集することができます。
SVG ファイルは小さく、高品質のグラフィックを Web、印刷、リソースの限られたハンドヘルド・デバイスに提供します。さらに、SVG はスクリプトや動画をサポートするため、インタラクティブなデータ駆動型のカスタム・グラフィックに最適です。
SVG には多くの利点があります。まず、解像度の異なる画像は必要ありません。スケーリングが必要ないためです。また、SVG は XML ファイルであるため、同じイメージでもラスターサイズ形式よりサイズが非常に小さくて済みます。これにより、イメージをすぐに変更できます。
SVG では、ベクター・グラフィック、ラスター・グラフィック、テキストの 3 種類のグラフィック・オブジェクトを作成できます。PNG や JPEG ラスターイメージを含むグラフィック・オブジェクトは、グループ化したり、スタイルを付けたり、変換したり、あるいはすでに描画されたオブジェクトに合成することができます。
ネイティブ Android* アプリケーションは SVG XML ファイルをサポートしませんが、Android* 3.0 以降ではブラウザーでパースできます (図 1 を参照)。この記事では、SVG-Android* オープンソース・ライブラリーをコードに統合し、インテル® アーキテクチャー向けの Android* Ice Cream Sandwich (ICS) におけるサンプルを紹介します。
1. SVG の機能
SVG 1.1 仕様では次の 14 種類の機能セットについて定義しています。
- パス
- 基本図形
- テキスト
- 塗り
- 色
- グラデーションとパターン
- クリッピング、マスク、合成
- フィルター効果
- 対話性
- リンク
- スクリプト
- アニメーション
- フォント
- メタデータ
2. SVG 図形
SVG の事前定義された図形要素は次のとおりです。
- 四角形 <rect>
- 円 <circle>
- 楕円 <ellipse>
- 線 <line>
- ポリライン <polyline>
- ポリゴン <polygon>
- パス <path>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"> <path d="M150 0 L75 200 L225 200 Z" />
図 1: Android* デバイスの SVG 実装
出典: インテル コーポレーション (2012 年)
3. SVG ライブラリーの統合
svgandroid.jar を示す svgandroid.xml という名前のファイルを作成します。svgandroid.jar を /system/framework に、svgandroid.xml を /etc/permissions フォルダーに置きます。svgandroid.xml によってアプリケーションは svgandroid.jar ライブラリーを見つけることができます。
svgandroid.xml に次のコードを記述します。
AndroidManifest.xml ファイルで <uses-library> を使って宣言します。このメソッドは svgandroid パッケージをロードします。自動的にはロードされません。
<uses-library android:name=”svgandroid” android:required=”true” />
上記で示すように、android:required=”true” にしてください。このライブラリーがないと、Android* システムでアプリケーションが許可されません。
このライブラリーなしでアプリケーションが Android* デバイスにインストールされると、次のエラーが発生します。
Failure [INSTALL_FAILED_MISSING_SHARED_LIBRARY]
この要素はまた、Market のアプリケーションの利用可否に影響します。ライブラリーがないと、Android* デバイスはこのアプリケーションを Market でリストできません。
4. 変更後の SVG を使用したファイルのレンダリング
このセクションでは、ライブラリー統合後の SVG を使用したファイルのレンダリング方法を説明します。
4.1. SAX とは?
SAX (Simple API for XML) は、イベントベースのシーケンシャル・アクセス・パーサー API で、XML-DEV メーリングリストにより策定されました。XML 文書を読み込む SAX の手法は、DOM (Document Object Model) とは全く異なります。DOM は文書を全体として操作しますが、SAX パーサーは XML 文書を先頭からシーケンシャルに操作します。
4.2. 利点
SAX パーサーには DOM スタイルパーサーより優れた点があります。SAX パーサーは通常、DOM パーサーよりメモリー使用量が少なくて済みます。DOM パーサーは最初にメモリー上にツリー全体を展開する必要があるため、メモリー使用量は入力データのサイズに完全に依存します。対照的に、SAX パーサーのメモリー要件は、XML ファイルの最大の深さ (XML ツリーの最大の深さ) と、1 つの XML 要素の XML 属性に格納される最大データ量にのみ依存します。これらは、パースされたツリーのサイズより常に小さいでしょう。
SAX パーサーは、そのイベント駆動型の性質によって、DOM スタイルパーサーより文書を高速に処理できます。メモリーの割り当てには時間がかかるため、DOM のより大きなメモリー要件はパフォーマンスの問題にもなります。
DOM の特性により、ディスクからのストリームを読み込むことはできません。メインメモリーより大きな XML 文書を処理することも、DOM パーサーではできませんが、SAX パーサーなら可能です。ただし、この制限への対策として、DOM パーサーはディスク領域をメモリーとして利用できます。
4.3. 欠点
イベント駆動型モデルの SAX は、XML パースには役立ちますが欠点もあります。
特定の種類の XML 検証には文書への完全なアクセスが必要になります。例えば、DTD IDREF 属性には、DTD ID 属性として指定された文字列を使用する文書の要素がなければなりません。SAX パーサーでこれを検証するには、各 ID と IDREF 属性が一致したかどうかを追跡しなければなりません。さらに、IDREF が ID と一致しない場合、文書がパースされた後にのみこれが判明します。このリンクが出力の生成に重要である場合、文書全体の処理は時間を無駄にする結果になります。
また、XML 処理によっては文書全体へのアクセスを必要とするものもあるでしょう。例えば、XSLT と XPath では、パースされた XML ツリーのノードに常にアクセスできなければなりません。SAX パーサーはツリーなどの構造に使用できますが、DOM はすでに意図的にそのように設計されています。
4.4. SAX パーサーを Android* に実装する方法
SAX パーサーの実装時、クラスは “DefaultHandler” を継承する必要があります。この “DefaultHandler” (Android* の SAX2 イベントハンドラーのデフォルト・ベースクラス) を継承する際、無効にしなければならないメソッドがいくつかあります。これらのメソッドには startElement、endElement、startDocument、endDocument などがあります。名前から各メソッドの動作を想像できるでしょう。例えば、startDocument は、SAX が文書のパースを開始する際、イベントをトリガーして startDocument メソッドを呼び出します。SAX がXML ファイルのタグをパースすると、startElement が呼び出され、タグ名、属性、その他のタグに関連する情報が取得できます。その他のメソッド、endDocument、startElement、endElement は一目瞭然でしょう。
4.5. オリジナルの SVG ライブラリーを変更する理由
オリジナルのライブラリーは、グループタグ (<g>) の属性で SVG ファイルをレンダリングすることができないため、<g> タグに style 属性を設定して登録します。style 属性がすでに内側のレンダー要素にある場合、style 属性は <g> タグのものと置き換わります。
SVG ファイルをパースするには SAX を使用することを推奨します。<g> タグをパースする際、属性全体を取得して、インスタンス –g_prop にします。これは、プロパティーの内部クラスです。
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { …… } else if (localName.equals("g")) { …… pushTransform(atts); g_prop = new Properties(atts); } …… } public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { …… } else if (localName.equals("g")) { …… pushTransform(atts); g_prop = new Properties(atts); } …… }
<rectangle>、<path>、その他のレンダリング・タグをパースする際、そのタグに関連付けられたスタイルがないかチェックする必要があります。もしある場合は、その属性を取得しなければなりません。doFill、doStroke メソッドは、canvas の fill や stroke のスタイルを初期化するのに役立ちます。これらのメソッドの呼び出し後、パースされた要素を canvas に描画できます。
Properties props = new Properties(atts); if (doFill(props, gradientMap)) { doLimits(p); canvas.drawPath(p, paint); } else { if(g_prop != null) { if(doFill(g_prop, gradientMap)) { doLimits(p); canvas.drawPath(p, paint); } } } if (doStroke(props)) canvas.drawPath(p, paint); else { if(g_prop != null) { if(doStroke(g_prop)) canvas.drawPath(p, paint); } } popTransform(); } Properties props = new Properties(atts); if (doFill(props, gradientMap)) { doLimits(p); canvas.drawPath(p, paint); } else { if(g_prop != null) { if(doFill(g_prop, gradientMap)) { doLimits(p); canvas.drawPath(p, paint); } } } if (doStroke(props)) canvas.drawPath(p, paint); else { if(g_prop != null) { if(doStroke(g_prop)) canvas.drawPath(p, paint); } } popTransform(); }
4.6. SVG XML ファイルのレンダリング・タグの属性
次の例は、SVG XML ファイルのレンダリング・タグの属性を示しています (図 2 を参照)。
<path display=”none” fill=”#FFFFFF”
d=”M268.461,471.01c2.526,0,4.575,2.048,4.575,4.571c0,2.529-2.049,4.576-4.575,4.576
c-2.525,0-4.574-2.047-4.574-4.576C263.887,473.058,265.936,471.01,268.461,471.01z”/>
図 2: Android* デバイスの SVG 実装
出典: インテル コーポレーション (2012 年)
5. SVG XML ファイルのグループタグの属性
次の例は、SVG XML ファイルのグループタグ属性を示しています。
<g style=”fill: #ffffff; stroke:#000000; stroke-width:0.172″>
<path d=”M-122.304 84.285C-122.304 84.285 -122.203 86.179 -123.027 86.16C-123.851 86.141 -140.305 38.066 -160.833 40.309C-160.833 40.309 -143.05 32.956 -122.304 84.285z”/>
</g>
図 3: Android* デバイスの SVG 実装
出典: インテル コーポレーション (2012 年)
コンパイラーの最適化に関する詳細は、最適化に関する注意事項を参照してください。