am 8d3f3c06: Merge "Expand hardware accel doc" into jb-mr2-dev

* commit '8d3f3c061709eefe202e0ff7a612fcdf8cfeeb63':
  Expand hardware accel doc
This commit is contained in:
Chris Craik
2013-04-23 03:51:18 -07:00
committed by Android Git Automerger

View File

@@ -47,35 +47,24 @@ parent.link=index.html
</div> </div>
</div> </div>
<p>Beginning in Android 3.0 (API level 11), the Android 2D rendering pipeline is designed to <p>Beginning in Android 3.0 (API level 11), the Android 2D rendering pipeline supports hardware
better support hardware acceleration. Hardware acceleration carries out all drawing operations acceleration, meaning that all drawing operations that are performed on a {@link
that are performed on a {@link android.view.View}'s canvas using the GPU. Because of the android.view.View}'s canvas use the GPU. Because of the increased resources required to enable
increased resources required to enable hardware acceleration, your app will consume more RAM.</p> hardware acceleration, your app will consume more RAM.</p>
<p>The easiest way to enable hardware acceleration is to turn it on <p>Hardware acceleration is enabled by default if your Target API level is &gt;=14, but can also
globally for your entire application. If your application uses only standard views and {@link be explicitly enabled. If your application uses only standard views and {@link
android.graphics.drawable.Drawable}s, turning it on globally should not cause any adverse android.graphics.drawable.Drawable}s, turning it on globally should not cause any adverse drawing
drawing effects. However, because hardware acceleration is not supported for all of the 2D drawing effects. However, because hardware acceleration is not supported for all of the 2D drawing
operations, turning it on might affect some of your applications that use custom views or drawing operations, turning it on might affect some of your custom views or drawing calls. Problems
calls. Problems usually manifest themselves as invisible elements, exceptions, or wrongly usually manifest themselves as invisible elements, exceptions, or wrongly rendered pixels. To
rendered pixels. To remedy this, Android gives you the option to enable or disable hardware remedy this, Android gives you the option to enable or disable hardware acceleration at multiple
acceleration at the following levels:</p> levels. See <a href="#controlling">Controlling Hardware Acceleration</a>.</p>
<ul>
<li>Application</li>
<li>Activity</li>
<li>Window</li>
<li>View</li>
</ul>
<p>If your application performs custom drawing, test your application on actual hardware
devices with hardware acceleration turned on to find any problems. The <a
href="#drawing-support">Unsupported drawing operations</a> section describes known issues with
drawing operations that cannot be hardware accelerated and how to work around them.</p>
<p>If your application performs custom drawing, test your application on actual hardware devices
with hardware acceleration turned on to find any problems. The <a
href="#drawing-support">Unsupported drawing operations</a> section describes known issues with
hardware acceleration and how to work around them.</p>
<h2 id="controlling">Controlling Hardware Acceleration</h2> <h2 id="controlling">Controlling Hardware Acceleration</h2>
<p>You can control hardware acceleration at the following levels:</p> <p>You can control hardware acceleration at the following levels:</p>
@@ -100,12 +89,12 @@ drawing operations that cannot be hardware accelerated and how to work around th
</pre> </pre>
<h4>Activity level</h4> <h4>Activity level</h4>
<p>If your application does not behave properly with hardware acceleration turned on globally, <p>If your application does not behave properly with hardware acceleration turned on globally, you
you can control it for individual activities as well. To enable or disable hardware acceleration can control it for individual activities as well. To enable or disable hardware acceleration at
at the activity level, you can use the <code>android:hardwareAccelerated</code> the activity level, you can use the <code>android:hardwareAccelerated</code> attribute for
attribute for the <a href="{@docRoot}guide/topics/manifest/activity-element.html"> the <a href="{@docRoot}guide/topics/manifest/activity-element.html">
<code>&lt;activity&gt;</code></a> element. The following example enables hardware acceleration <code>&lt;activity&gt;</code></a> element. The following example enables hardware acceleration for
for the entire application but disables it for one activity:</p> the entire application but disables it for one activity:</p>
<pre> <pre>
&lt;application android:hardwareAccelerated="true"&gt; &lt;application android:hardwareAccelerated="true"&gt;
@@ -228,8 +217,7 @@ changed.</li>
<p>With this model, you cannot rely on a view intersecting the dirty region to have its {@link <p>With this model, you cannot rely on a view intersecting the dirty region to have its {@link
android.view.View#draw draw()} method executed. To ensure that the Android system records a android.view.View#draw draw()} method executed. To ensure that the Android system records a
views display list, you must call {@link android.view.View#invalidate invalidate()}. Forgetting views display list, you must call {@link android.view.View#invalidate invalidate()}. Forgetting
to do so causes a view to look the same even after changing it, which is an easier bug to find if to do so causes a view to look the same even after it has been changed.</p>
it happens.</p>
<p>Using display lists also benefits animation performance because setting specific properties, <p>Using display lists also benefits animation performance because setting specific properties,
such as alpha or rotation, does not require invalidating the targeted view (it is done such as alpha or rotation, does not require invalidating the targeted view (it is done
@@ -275,7 +263,7 @@ changed.</li>
<p>The following table describes the support level of various operations across API levels:</p> <p>The following table describes the support level of various operations across API levels:</p>
<style type="text/css"> <style type="text/css">
.tblGenFixed,.tblGeneric{font-size:15px}.tblGenFixed td {padding:0 3px;letter-spacing:0;word-spacing:0;background-color:#fff;z-index:1;border-top:0px none;border-left:0px none;border-bottom:1px solid #CCC;border-right:1px solid #CCC;} .dn {display:none} .tblGenFixed td.s0 {background-color:white;border-top:1px solid #CCC;border-left:1px solid #CCC;} .tblGenFixed td.s2 {background-color:#d9d9d9;color:#000000;text-align:center;} .tblGenFixed td.s1 {background-color:#434343;color:#ffffff;text-align:center;border-top:1px solid #CCC;} .tblGenFixed td.s9 {background-color:;color:#6aa84f;text-align:center;} .tblGenFixed td.s12 {background-color:white;color:#6aa84f;text-align:center;} .tblGenFixed td.s13 {background-color:#d9d9d9;color:#6aa84f;text-align:center;} .tblGenFixed td.s7 {background-color:#d9d9d9;color:#980000;text-align:center;} .tblGenFixed td.s8 {background-color:;color:#980000;text-align:center;} .tblGenFixed td.s5 {background-color:#434343;color:#ffffff;text-align:left;border-left:1px solid #CCC;} .tblGenFixed td.s6 {background-color:;font-family:courier new,monospace;color:;text-align:right;border-left:1px solid #CCC;} .tblGenFixed td.s10 {background-color:white;font-family:courier new,monospace;color:#000000;text-align:right;border-left:1px solid #CCC;} .tblGenFixed td.s3 {background-color:white;color:#000000;text-align:center;} .tblGenFixed td.s11 {background-color:white;color:#980000;text-align:center;} .tblGenFixed td.s4 {background-color:#d9d9d9;color:#000000;text-align:center;} .tblGenFixed, .tblGeneric{font-size:15px}.tblGenFixed td {padding:0 3px;letter-spacing:0;word-spacing:0;background-color:#fff;z-index:1;border-top:0px none;border-left:0px none;border-bottom:1px solid #CCC;border-right:1px solid #CCC;} .dn {display:none} .tblGenFixed td.s0 {background-color:white;border-top:1px solid #CCC;border-left:1px solid #CCC;} .tblGenFixed td.s1 {background-color:#434343;color:#ffffff;text-align:center;border-top:1px solid #CCC;} .tblGenFixed td.s2 {background-color:#d9d9d9;color:#000000;text-align:center;} .tblGenFixed td.s3 {background-color:white;color:#000000;text-align:center;} .tblGenFixed td.s5 {background-color:#434343;color:#ffffff;text-align:left;border-left:1px solid #CCC;} .tblGenFixed td.s10 {background-color:white;font-family:courier new,monospace;color:#000000;text-align:right;border-left:1px solid #CCC;} .tblGenFixed td.g_pos {background-color:#d9d9d9;color:#6aa84f;text-align:center;} .tblGenFixed td.g_neg {background-color:#d9d9d9;color:#980000;text-align:center;} .tblGenFixed td.w_pos {background-color:white;color:#6aa84f;text-align:center;} .tblGenFixed td.w_neg {background-color:white;color:#980000;text-align:center;}
</style> </style>
<table border="0" cellpadding="0" cellspacing="0" class="tblGenFixed" id="tblMain"> <table border="0" cellpadding="0" cellspacing="0" class="tblGenFixed" id="tblMain">
<tbody> <tbody>
@@ -294,242 +282,329 @@ changed.</li>
<td style="display:none;"></td> <td style="display:none;"></td>
<td class="s2">&lt; 16</td> <td class="s2">&lt; 16</td>
<td class="s3">16</td> <td class="s3">16</td>
<td class="s4">17</td> <td class="s2">17</td>
<td class="s3">18</td> <td class="s3">18</td>
</tr> </tr>
<tr> <tr>
<td colspan="5" class="s5">Canvas</td> <td colspan="5" class="s5">Canvas</td>
</tr> </tr>
<tr>
<td class="s6">clipPath()</td>
<td class="s7">&#10007;</td>
<td class="s8">&#10007;</td>
<td class="s7">&#10007;</td>
<td class="s9">&#10003;</td>
</tr>
<tr>
<td class="s10">clipRegion()</td>
<td class="s7">&#10007;</td>
<td class="s11">&#10007;</td>
<td class="s7">&#10007;</td>
<td class="s12">&#10003;</td>
</tr>
<tr>
<td class="s10">clipRect(Region.Op.XOR)</td>
<td class="s7">&#10007;</td>
<td class="s11">&#10007;</td>
<td class="s7">&#10007;</td>
<td class="s12">&#10003;</td>
</tr>
<tr>
<td class="s10">clipRect(Region.Op.Difference)</td>
<td class="s7">&#10007;</td>
<td class="s11">&#10007;</td>
<td class="s7">&#10007;</td>
<td class="s12">&#10003;</td>
</tr>
<tr>
<td class="s10">clipRect(Region.Op.ReverseDifference)</td>
<td class="s7">&#10007;</td>
<td class="s11">&#10007;</td>
<td class="s7">&#10007;</td>
<td class="s12">&#10003;</td>
</tr>
<tr> <tr>
<td class="s10">drawBitmapMesh() (colors array)</td> <td class="s10">drawBitmapMesh() (colors array)</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">drawPicture()</td> <td class="s10">drawPicture()</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">drawPosText()</td> <td class="s10">drawPosText()</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
<td class="s13">&#10003;</td> <td class="g_pos">&#10003;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">drawTextOnPath()</td> <td class="s10">drawTextOnPath()</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
<td class="s13">&#10003;</td> <td class="g_pos">&#10003;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">drawVertices()</td> <td class="s10">drawVertices()</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">setDrawFilter()</td> <td class="s10">setDrawFilter()</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
<td class="s13">&#10003;</td> <td class="g_pos">&#10003;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
</tr>
<tr>
<td class="s10">clipPath()</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_neg">&#10007;</td>
<td class="w_pos">&#10003;</td>
</tr>
<tr>
<td class="s10">clipRegion()</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_neg">&#10007;</td>
<td class="w_pos">&#10003;</td>
</tr>
<tr>
<td class="s10">clipRect(Region.Op.XOR)</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_neg">&#10007;</td>
<td class="w_pos">&#10003;</td>
</tr>
<tr>
<td class="s10">clipRect(Region.Op.Difference)</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_neg">&#10007;</td>
<td class="w_pos">&#10003;</td>
</tr>
<tr>
<td class="s10">clipRect(Region.Op.ReverseDifference)</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_neg">&#10007;</td>
<td class="w_pos">&#10003;</td>
</tr>
<tr>
<td class="s10">clipRect() with rotation/perspective</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_neg">&#10007;</td>
<td class="w_pos">&#10003;</td>
</tr> </tr>
<tr> <tr>
<td colspan="5" class="s5">Paint</td> <td colspan="5" class="s5">Paint</td>
</tr> </tr>
<tr> <tr>
<td class="s6">setAntiAlias() (for text)</td> <td class="s10">setAntiAlias() (for text)</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
</tr> </tr>
<tr> <tr>
<td class="s6">setAntiAlias() (for lines)</td> <td class="s10">setAntiAlias() (for lines)</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
<td class="s13">&#10003;</td> <td class="g_pos">&#10003;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
</tr> </tr>
<tr> <tr>
<td class="s6">setFilterBitmap()</td> <td class="s10">setFilterBitmap()</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s13">&#10003;</td> <td class="g_pos">&#10003;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
</tr> </tr>
<tr> <tr>
<td class="s6">setLinearText()</td> <td class="s10">setLinearText()</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s8">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s8">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">setMaskFilter()</td> <td class="s10">setMaskFilter()</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">setPathEffect() (for lines)</td> <td class="s10">setPathEffect() (for lines)</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">setRasterizer()</td> <td class="s10">setRasterizer()</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">setShadowLayer() (other than text)</td> <td class="s10">setShadowLayer() (other than text)</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">setStrokeCap() (for lines)</td> <td class="s10">setStrokeCap() (for lines)</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s12">&#10003;</td> <td class="w_pos">&#10003;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">setStrokeCap() (for points)</td> <td class="s10">setStrokeCap() (for points)</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">setSubpixelText()</td> <td class="s10">setSubpixelText()</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td colspan="5" class="s5">Xfermode</td> <td colspan="5" class="s5">Xfermode</td>
</tr> </tr>
<tr> <tr>
<td class="s6">AvoidXfermode</td> <td class="s10">AvoidXfermode</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s8">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s8">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">PixelXorXfermode</td> <td class="s10">PixelXorXfermode</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">PorterDuff.Mode.DARKEN (framebuffer)</td> <td class="s10">PorterDuff.Mode.DARKEN (framebuffer)</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s8">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s8">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">PorterDuff.Mode.LIGHTEN (framebuffer)</td> <td class="s10">PorterDuff.Mode.LIGHTEN (framebuffer)</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">PorterDuff.Mode.OVERLAY (framebuffer)</td> <td class="s10">PorterDuff.Mode.OVERLAY (framebuffer)</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td colspan="5" class="s5">Shader</td> <td colspan="5" class="s5">Shader</td>
</tr> </tr>
<tr> <tr>
<td class="s10">ComposeShader inside ComposeShader</td> <td class="s10">ComposeShader inside ComposeShader</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">Same type shaders inside ComposeShader</td> <td class="s10">Same type shaders inside ComposeShader</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
</tr> </tr>
<tr> <tr>
<td class="s10">Local matrix on ComposeShader</td> <td class="s10">Local matrix on ComposeShader</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10007;</td> <td class="w_neg">&#10007;</td>
<td class="s7">&#10007;</td> <td class="g_neg">&#10007;</td>
<td class="s11">&#10003;</td> <td class="w_pos">&#10003;</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<h3 id="scaling">Canvas Scaling</h3>
<p>The hardware accelerated 2D rendering pipeline was built first to support unscaled drawing,
with some drawing operations degrading quality significantly at higher scale values. These
operations are implemented as textures drawn at scale 1.0, transformed by the GPU. In API level
&lt;17, using these operations will result in scaling artifacts increasing with scale.</p>
The following table shows when implementation was changed to correctly handle large scales:
<table border="0" cellpadding="0" cellspacing="0" class="tblGenFixed" id="tblMain">
<tbody>
<tr class="rShim">
<td class="rShim" style="width:380px;"></td>
<td class="rShim" style="width:120px;"></td>
<td class="rShim" style="width:120px;"></td>
<td class="rShim" style="width:120px;"></td>
</tr>
<tr>
<td rowspan="2" class="s0"></td>
<td colspan="4" class="s1">API level</td>
</tr>
<tr>
<td style="display:none;"></td>
<td class="s2">&lt; 17</td>
<td class="s3">17</td>
<td class="s2">18</td>
</tr>
<tr>
<td colspan="5" class="s5">Support for large scale factors</td>
</tr>
<tr>
<td class="s10">drawText()</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_pos">&#10003;</td>
</tr>
<tr>
<td class="s10">drawPosText()</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_neg">&#10007;</td>
</tr>
<tr>
<td class="s10">drawTextOnPath()</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_neg">&#10007;</td>
</tr>
<tr>
<td class="s10">Simple Shapes*</td>
<td class="g_neg">&#10007;</td>
<td class="w_pos">&#10003;</td>
<td class="g_pos">&#10003;</td>
</tr>
<tr>
<td class="s10">Complex Shapes*</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_neg">&#10007;</td>
</tr>
<tr>
<td class="s10">drawPath()</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_neg">&#10007;</td>
</tr>
<tr>
<td class="s10">Shadow layer</td>
<td class="g_neg">&#10007;</td>
<td class="w_neg">&#10007;</td>
<td class="g_neg">&#10007;</td>
</tr>
</tbody>
</table>
<p class="note"><strong>Note</strong>: 'Simple' shapes are <code>drawRect()</code>,
<code>drawCircle()</code>, <code>drawOval()</code>, <code>drawRoundRect()</code>, and
<code>drawArc()</code> (with useCenter=false) commands issued with a Paint that doesn't have a
PathEffect, and doesn't contain non-default joins (via <code>setStrokeJoin()</code> /
<code>setStrokeMiter()</code>). Other instances of those draw commands fall under 'Complex,' in
the above chart.</p>
<p>If your application is affected by any of these missing features or limitations, you can turn <p>If your application is affected by any of these missing features or limitations, you can turn
off hardware acceleration for just the affected portion of your application by calling off hardware acceleration for just the affected portion of your application by calling {@link
{@link android.view.View#setLayerType setLayerType(View.LAYER_TYPE_SOFTWARE, null)}. This way, android.view.View#setLayerType setLayerType(View.LAYER_TYPE_SOFTWARE, null)}. This way, you can
you can still take advantage of hardware acceleratin everywhere else. See <a still take advantage of hardware acceleration everywhere else. See <a
href="#controlling">Controlling Hardware Acceleration</a> for more information on how to enable and href="#controlling">Controlling Hardware Acceleration</a> for more information on how to enable
disable hardware acceleration at different levels in your application. and disable hardware acceleration at different levels in your application.
<h2 id="layers">View Layers</h2> <h2 id="layers">View Layers</h2>