Merge "Add path to get different DPI drawables"
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user