am 11ea3347: Allow for screen density drawables in compatibility mode.

Merge commit '11ea33471e1a14a8594f0b2cd012d86340dd3bd8'

* commit '11ea33471e1a14a8594f0b2cd012d86340dd3bd8':
  Allow for screen density drawables in compatibility mode.
This commit is contained in:
Dianne Hackborn
2009-07-24 16:08:56 -07:00
committed by Android Git Automerger
29 changed files with 807 additions and 365 deletions

View File

@@ -40,7 +40,6 @@ public class BitmapFactory {
*/
public Options() {
inDither = true;
inDensity = 0;
inScaled = true;
}
@@ -80,22 +79,87 @@ public class BitmapFactory {
public boolean inDither;
/**
* The desired pixel density of the bitmap.
* The pixel density to use for the bitmap. This will always result
* in the returned bitmap having a density set for it (see
* {@link Bitmap#setDensity(int) Bitmap.setDensity(int)). In addition,
* if {@link #inScaled} is set (which it is by default} and this
* density does not match {@link #inTargetDensity}, then the bitmap
* will be scaled to the target density before being returned.
*
* <p>If this is 0,
* {@link BitmapFactory#decodeResource(Resources, int)},
* {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
* and {@link BitmapFactory#decodeResourceStream}
* will fill in the density associated with the resource. The other
* functions will leave it as-is and no density will be applied.
*
* @see android.util.DisplayMetrics#DENSITY_DEFAULT
* @see android.util.DisplayMetrics#density
* @see #inTargetDensity
* @see #inScreenDensity
* @see #inScaled
* @see Bitmap#setDensity(int)
* @see android.util.DisplayMetrics#densityDpi
*/
public int inDensity;
/**
* </p>If the bitmap is loaded from {@link android.content.res.Resources} and
* this flag is turned on, the bitmap will be scaled to match the default
* display's pixel density.</p>
* The pixel density of the destination this bitmap will be drawn to.
* This is used in conjunction with {@link #inDensity} and
* {@link #inScaled} to determine if and how to scale the bitmap before
* returning it.
*
* <p>If this is 0,
* {@link BitmapFactory#decodeResource(Resources, int)},
* {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
* and {@link BitmapFactory#decodeResourceStream}
* will fill in the density associated the Resources object's
* DisplayMetrics. The other
* functions will leave it as-is and no scaling for density will be
* performed.
*
* @see #inDensity
* @see #inScreenDensity
* @see #inScaled
* @see android.util.DisplayMetrics#densityDpi
*/
public int inTargetDensity;
/**
* The pixel density of the actual screen that is being used. This is
* purely for applications running in density compatibility code, where
* {@link #inTargetDensity} is actually the density the application
* sees rather than the real screen density.
*
* <p>By setting this, you
* allow the loading code to avoid scaling a bitmap that is currently
* in the screen density up/down to the compatibility density. Instead,
* if {@link #inDensity} is the same as {@link #inScreenDensity}, the
* bitmap will be left as-is. Anything using the resulting bitmap
* must also used {@link Bitmap#getScaledWidth(int)
* Bitmap.getScaledWidth} and {@link Bitmap#getScaledHeight
* Bitmap.getScaledHeight} to account for any different between the
* bitmap's density and the target's density.
*
* <p>This is never set automatically for the caller by
* {@link BitmapFactory} itself. It must be explicitly set, since the
* caller must deal with the resulting bitmap in a density-aware way.
*
* @see #inDensity
* @see #inTargetDensity
* @see #inScaled
* @see android.util.DisplayMetrics#densityDpi
*/
public int inScreenDensity;
/**
* When this flag is set, if {@link #inDensity} and
* {@link #inTargetDensity} are not 0, the
* bitmap will be scaled to match {@link #inTargetDensity} when loaded,
* rather than relying on the graphics system scaling it each time it
* is drawn to a Canvas.
*
* </p>This flag is turned on by default and should be turned off if you need
* a non-scaled version of the bitmap. In this case,
* {@link android.graphics.Bitmap#setAutoScalingEnabled(boolean)} can be used
* to properly scale the bitmap at drawing time.</p>
* <p>This flag is turned on by default and should be turned off if you need
* a non-scaled version of the bitmap. Nine-patch bitmaps ignore this
* flag and are always scaled.
*/
public boolean inScaled;
@@ -236,58 +300,32 @@ public class BitmapFactory {
* Decode a new Bitmap from an InputStream. This InputStream was obtained from
* resources, which we pass to be able to scale the bitmap accordingly.
*/
public static Bitmap decodeStream(Resources res, TypedValue value, InputStream is,
Rect pad, Options opts) {
public static Bitmap decodeResourceStream(Resources res, TypedValue value,
InputStream is, Rect pad, Options opts) {
if (opts == null) {
opts = new Options();
}
Bitmap bm = decodeStream(is, pad, opts);
if (bm != null && res != null && value != null) {
if (opts.inDensity == 0 && value != null) {
final int density = value.density;
if (density == TypedValue.DENSITY_NONE) {
return bm;
}
byte[] np = bm.getNinePatchChunk();
final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
if (opts.inDensity == 0) {
opts.inDensity = density == TypedValue.DENSITY_DEFAULT ?
DisplayMetrics.DENSITY_DEFAULT : density;
}
float scale = opts.inDensity / (float) DisplayMetrics.DENSITY_DEFAULT;
if (opts.inScaled || isNinePatch) {
bm.setDensityScale(1.0f);
bm.setAutoScalingEnabled(false);
// Assume we are going to prescale for the screen
scale = res.getDisplayMetrics().density / scale;
if (scale != 1.0f) {
// TODO: This is very inefficient and should be done in native by Skia
final Bitmap oldBitmap = bm;
bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f),
(int) (bm.getHeight() * scale + 0.5f), true);
oldBitmap.recycle();
if (isNinePatch) {
np = nativeScaleNinePatch(np, scale, pad);
bm.setNinePatchChunk(np);
}
}
} else {
bm.setDensityScale(scale);
bm.setAutoScalingEnabled(true);
if (density == TypedValue.DENSITY_DEFAULT) {
opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
} else if (density != TypedValue.DENSITY_NONE) {
opts.inDensity = density;
}
}
return bm;
if (opts.inTargetDensity == 0 && res != null) {
opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
}
return decodeStream(is, pad, opts);
}
/**
* Decode an image referenced by a resource ID.
* Synonym for opening the given resource and calling
* {@link #decodeResourceStream}.
*
* @param res The resources object containing the image data
* @param id The resource id of the image data
@@ -304,7 +342,7 @@ public class BitmapFactory {
final TypedValue value = new TypedValue();
final InputStream is = res.openRawResource(id, value);
bm = decodeStream(res, value, is, null, opts);
bm = decodeResourceStream(res, value, is, null, opts);
is.close();
} catch (java.io.IOException e) {
/* do nothing.
@@ -316,7 +354,8 @@ public class BitmapFactory {
}
/**
* Decode an image referenced by a resource ID.
* Synonym for {@link #decodeResource(Resources, int, android.graphics.BitmapFactory.Options)}
* will null Options.
*
* @param res The resources object containing the image data
* @param id The resource id of the image data
@@ -413,6 +452,39 @@ public class BitmapFactory {
bm = nativeDecodeStream(is, tempStorage, outPadding, opts);
}
if (bm == null || opts == null) {
return bm;
}
final int density = opts.inDensity;
if (density == 0) {
return bm;
}
bm.setDensity(density);
final int targetDensity = opts.inTargetDensity;
if (targetDensity == 0 || density == targetDensity
|| density == opts.inScreenDensity) {
return bm;
}
byte[] np = bm.getNinePatchChunk();
final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np);
if (opts.inScaled || isNinePatch) {
float scale = targetDensity / (float)density;
// TODO: This is very inefficient and should be done in native by Skia
final Bitmap oldBitmap = bm;
bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f),
(int) (bm.getHeight() * scale + 0.5f), true);
oldBitmap.recycle();
if (isNinePatch) {
np = nativeScaleNinePatch(np, scale, outPadding);
bm.setNinePatchChunk(np);
}
bm.setDensity(targetDensity);
}
return bm;
}