Exemplo n.º 1
0
bool
AssetManagerGlue::retrieveAttributes(XmlParser& xmlParser, const NativeArray<int>& attrs,
				     NativeArray<int>* outValues, NativeArray<int>* outIndices)
{
	const ResTable& res(getResources());
	ResTable_config config;
	Res_value value;

	const size_t NI = attrs.length();
	const size_t NV = outValues->length();
	SkASSERT(NV >= (NI * STYLE_NUM_ENTRIES));

	// int* src = attrs;
	// int* baseDest = outValues;
	// int* dest = baseDest;

	int indicesIdx = 0;
	bool haveIndices = false;
	if (outIndices != NULL) {
		if (outIndices->length() > NI)
			haveIndices = true;
        }

	// Now lock down the resource object and start pulling stuff from it.
	res.lock();

	// Retrieve the XML attributes, if requested.
	const size_t NX = xmlParser.getAttributeCount();
	size_t ix=0;
	uint32_t curXmlAttr = xmlParser.getAttributeNameResID(ix);

	static const ssize_t kXmlBlock = 0x10000000;

	// Now iterate through all of the attributes that the client has requested,
	// filling in each with whatever data we can find.
	size_t offset = 0;
	ssize_t block = 0;
	uint32_t typeSetFlags;
	for (size_t ii=0; ii<NI; ii++) {
		const uint32_t curIdent = attrs[ii];

		// Try to find a value for this attribute...
		value.dataType = Res_value::TYPE_NULL;
		value.data = 0;
		typeSetFlags = 0;
		config.density = 0;

		// Skip through XML attributes until the end or the next possible match.
		while (ix < NX && curIdent > curXmlAttr) {
			ix++;
			curXmlAttr = xmlParser.getAttributeNameResID(ix);
		}
		// Retrieve the current XML attribute if it matches, and step to next.
		if (ix < NX && curIdent == curXmlAttr) {
			block = kXmlBlock;
			xmlParser.getAttributeValue(ix, &value);
			ix++;
			curXmlAttr = xmlParser.getAttributeNameResID(ix);
		}

		//printf("Attribute 0x%08x: type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
		uint32_t resid = 0;
		if (value.dataType != Res_value::TYPE_NULL) {
			// Take care of resolving the found resource to its final value.
			//printf("Resolving attribute reference\n");
			ssize_t newBlock = res.resolveReference(&value, block, &resid,
								&typeSetFlags, &config);
#if THROW_ON_BAD_ID
			if (newBlock == BAD_INDEX) {
				jniThrowException(env, "java/lang/IllegalStateException", "Bad resource!");
				return JNI_FALSE;
			}
#endif
			if (newBlock >= 0) block = newBlock;
		}

		// Deal with the special @null value -- it turns back to TYPE_NULL.
		if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
			value.dataType = Res_value::TYPE_NULL;
		}

		//printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);

		// Write the final value back to Java.
		outValues->set(offset+STYLE_TYPE, value.dataType);
		outValues->set(offset+STYLE_DATA, value.data);
		// FIXME: This is a pointer!
		// dest[STYLE_ASSET_COOKIE] = block != kXmlBlock ? res.getTableCookie(block) : NULL;
		if (block != kXmlBlock) {
			void* cookie = res.getTableCookie(block);
			DEBUG_STYLES(LOGI("COOKIE: %p - %x", cookie, (int)(long)cookie));
			SkASSERT((int)(long)cookie == (long)cookie);
			outValues->set(offset+STYLE_ASSET_COOKIE, (int)(long)cookie);
		} else {
			outValues->set(offset+STYLE_ASSET_COOKIE, -1);
		}
		outValues->set(offset+STYLE_RESOURCE_ID, resid);
		outValues->set(offset+STYLE_CHANGING_CONFIGURATIONS, typeSetFlags);
		outValues->set(offset+STYLE_DENSITY, config.density);

		if (haveIndices && value.dataType != Res_value::TYPE_NULL) {
			indicesIdx++;
			outIndices->set(indicesIdx, ii);
		}

		offset += STYLE_NUM_ENTRIES;
	}

	res.unlock();

	if (haveIndices)
		outIndices->set(0, indicesIdx);

	return true;
}