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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user