Merge "Add path to get different DPI drawables"

This commit is contained in:
Kenny Root
2010-10-29 14:20:04 -07:00
committed by Android (Google) Code Review
5 changed files with 115 additions and 20 deletions

View File

@@ -149,7 +149,7 @@ public final class AssetManager {
/*package*/ final CharSequence getResourceText(int ident) {
synchronized (this) {
TypedValue tmpValue = mValue;
int block = loadResourceValue(ident, tmpValue, true);
int block = loadResourceValue(ident, (short) 0, tmpValue, true);
if (block >= 0) {
if (tmpValue.type == TypedValue.TYPE_STRING) {
return mStringBlocks[block].get(tmpValue.data);
@@ -190,10 +190,11 @@ public final class AssetManager {
/*package*/ final boolean getResourceValue(int ident,
int density,
TypedValue outValue,
boolean resolveRefs)
{
int block = loadResourceValue(ident, outValue, resolveRefs);
int block = loadResourceValue(ident, (short) density, outValue, resolveRefs);
if (block >= 0) {
if (outValue.type != TypedValue.TYPE_STRING) {
return true;
@@ -681,8 +682,8 @@ public final class AssetManager {
/** Returns true if the resource was found, filling in mRetStringBlock and
* mRetData. */
private native final int loadResourceValue(int ident, TypedValue outValue,
boolean resolve);
private native final int loadResourceValue(int ident, short density, TypedValue outValue,
boolean resolve);
/** Returns true if the resource was found, filling in mRetStringBlock and
* mRetData. */
private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,

View File

@@ -627,6 +627,50 @@ public class Resources {
}
}
/**
* Return a drawable object associated with a particular resource ID for the
* given screen density in DPI. This will set the drawable's density to be
* the device's density multiplied by the ratio of actual drawable density
* to requested density. This allows the drawable to be scaled up to the
* correct size if needed. Various types of objects will be returned
* depending on the underlying resource -- for example, a solid color, PNG
* image, scalable image, etc. The Drawable API hides these implementation
* details.
*
* @param id The desired resource identifier, as generated by the aapt tool.
* This integer encodes the package, type, and resource entry.
* The value 0 is an invalid identifier.
* @param density the desired screen density indicated by the resource as
* found in {@link DisplayMetrics}.
* @throws NotFoundException Throws NotFoundException if the given ID does
* not exist.
* @return Drawable An object that can be used to draw this resource.
* @hide
*/
public Drawable getDrawableForDensity(int id, int density) throws NotFoundException {
synchronized (mTmpValue) {
TypedValue value = mTmpValue;
getValueForDensity(id, density, value, true);
/*
* Pretend the requested density is actually the display density. If
* the drawable returned is not the requested density, then force it
* to be scaled later by dividing its density by the ratio of
* requested density to actual device density. Drawables that have
* undefined density or no density don't need to be handled here.
*/
if (value.density > 0 && value.density != TypedValue.DENSITY_NONE) {
if (value.density == density) {
value.density = DisplayMetrics.DENSITY_DEVICE;
} else {
value.density = (value.density * DisplayMetrics.DENSITY_DEVICE) / density;
}
}
return loadDrawable(value, id);
}
}
/**
* Return a movie object associated with the particular resource ID.
* @param id The desired resource identifier, as generated by the aapt
@@ -930,7 +974,7 @@ public class Resources {
*/
public void getValue(int id, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
boolean found = mAssets.getResourceValue(id, outValue, resolveRefs);
boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
if (found) {
return;
}
@@ -938,6 +982,29 @@ public class Resources {
+ Integer.toHexString(id));
}
/**
* Get the raw value associated with a resource with associated density.
*
* @param id resource identifier
* @param density density in DPI
* @param resolveRefs If true, a resource that is a reference to another
* resource will be followed so that you receive the actual final
* resource data. If false, the TypedValue will be filled in with
* the reference itself.
* @throws NotFoundException Throws NotFoundException if the given ID does
* not exist.
* @see #getValue(String, TypedValue, boolean)
* @hide
*/
public void getValueForDensity(int id, int density, TypedValue outValue, boolean resolveRefs)
throws NotFoundException {
boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
if (found) {
return;
}
throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
}
/**
* Return the raw data associated with a particular resource ID.
* See getIdentifier() for information on how names are mapped to resource

View File

@@ -701,6 +701,7 @@ static jstring android_content_AssetManager_getResourceEntryName(JNIEnv* env, jo
static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject clazz,
jint ident,
jshort density,
jobject outValue,
jboolean resolve)
{
@@ -713,7 +714,7 @@ static jint android_content_AssetManager_loadResourceValue(JNIEnv* env, jobject
Res_value value;
ResTable_config config;
uint32_t typeSpecFlags;
ssize_t block = res.getResource(ident, &value, false, &typeSpecFlags, &config);
ssize_t block = res.getResource(ident, &value, false, density, &typeSpecFlags, &config);
#if THROW_ON_BAD_ID
if (block == BAD_INDEX) {
jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
@@ -1703,7 +1704,7 @@ static JNINativeMethod gAssetManagerMethods[] = {
(void*) android_content_AssetManager_getResourceTypeName },
{ "getResourceEntryName","(I)Ljava/lang/String;",
(void*) android_content_AssetManager_getResourceEntryName },
{ "loadResourceValue","(ILandroid/util/TypedValue;Z)I",
{ "loadResourceValue","(ISLandroid/util/TypedValue;Z)I",
(void*) android_content_AssetManager_loadResourceValue },
{ "loadResourceBagValue","(IILandroid/util/TypedValue;Z)I",
(void*) android_content_AssetManager_loadResourceBagValue },

View File

@@ -1771,12 +1771,14 @@ public:
*
* @return ssize_t Either a >= 0 table index or a negative error code.
*/
ssize_t getResource(uint32_t resID, Res_value* outValue, bool mayBeBag=false,
uint32_t* outSpecFlags=NULL, ResTable_config* outConfig=NULL) const;
ssize_t getResource(uint32_t resID, Res_value* outValue, bool mayBeBag = false,
uint16_t density = 0,
uint32_t* outSpecFlags = NULL,
ResTable_config* outConfig = NULL) const;
inline ssize_t getResource(const ResTable_ref& res, Res_value* outValue,
uint32_t* outSpecFlags=NULL) const {
return getResource(res.ident, outValue, false, outSpecFlags, NULL);
return getResource(res.ident, outValue, false, 0, outSpecFlags, NULL);
}
ssize_t resolveReference(Res_value* inOutValue,

View File

@@ -1896,7 +1896,7 @@ bool ResTable::getResourceName(uint32_t resID, resource_name* outName) const
return false;
}
ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag,
ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag, uint16_t density,
uint32_t* outSpecFlags, ResTable_config* outConfig) const
{
if (mError != NO_ERROR) {
@@ -1926,7 +1926,7 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag
memset(&bestItem, 0, sizeof(bestItem)); // make the compiler shut up
if (outSpecFlags != NULL) *outSpecFlags = 0;
// Look through all resource packages, starting with the most
// recently added.
const PackageGroup* const grp = mPackageGroups[p];
@@ -1934,6 +1934,22 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag
LOGW("Bad identifier when getting value for resource number 0x%08x", resID);
return BAD_INDEX;
}
// Allow overriding density
const ResTable_config* desiredConfig = &mParams;
ResTable_config* overrideConfig = NULL;
if (density > 0) {
overrideConfig = (ResTable_config*) malloc(sizeof(ResTable_config));
if (overrideConfig == NULL) {
LOGE("Couldn't malloc ResTable_config for overrides: %s", strerror(errno));
return BAD_INDEX;
}
memcpy(overrideConfig, &mParams, sizeof(ResTable_config));
overrideConfig->density = density;
desiredConfig = overrideConfig;
}
ssize_t rc = BAD_INDEX;
size_t ip = grp->packages.size();
while (ip > 0) {
ip--;
@@ -1943,12 +1959,13 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag
const ResTable_type* type;
const ResTable_entry* entry;
const Type* typeClass;
ssize_t offset = getEntry(package, t, e, &mParams, &type, &entry, &typeClass);
ssize_t offset = getEntry(package, t, e, desiredConfig, &type, &entry, &typeClass);
if (offset <= 0) {
if (offset < 0) {
LOGW("Failure getting entry for 0x%08x (t=%d e=%d) in package %zd (error %d)\n",
resID, t, e, ip, (int)offset);
return offset;
rc = offset;
goto out;
}
continue;
}
@@ -1963,13 +1980,14 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag
TABLE_NOISY(aout << "Resource type data: "
<< HexDump(type, dtohl(type->header.size)) << endl);
if ((size_t)offset > (dtohl(type->header.size)-sizeof(Res_value))) {
LOGW("ResTable_item at %d is beyond type chunk data %d",
(int)offset, dtohl(type->header.size));
return BAD_TYPE;
rc = BAD_TYPE;
goto out;
}
const Res_value* item =
(const Res_value*)(((const uint8_t*)type) + offset);
ResTable_config thisConfig;
@@ -2011,10 +2029,16 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag
outValue->data, &len)).string()
: "",
outValue->data));
return bestPackage->header->index;
rc = bestPackage->header->index;
goto out;
}
return BAD_VALUE;
out:
if (overrideConfig != NULL) {
free(overrideConfig);
}
return rc;
}
ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex,
@@ -2027,7 +2051,7 @@ ssize_t ResTable::resolveReference(Res_value* value, ssize_t blockIndex,
if (outLastRef) *outLastRef = value->data;
uint32_t lastRef = value->data;
uint32_t newFlags = 0;
const ssize_t newIndex = getResource(value->data, value, true, &newFlags,
const ssize_t newIndex = getResource(value->data, value, true, 0, &newFlags,
outConfig);
if (newIndex == BAD_INDEX) {
return BAD_INDEX;