//AtomicInteger hitCount = new AtomicInteger(0); //AtomicInteger missCount = new AtomicInteger(0); //AtomicInteger sameCount = new AtomicInteger(0); public override RenderStyle[] matchElement(GeometryType geometryType, TagSet tags, int zoomLevel) { /* list of items in cache */ RenderStyleItem ris = null; /* the item matching tags and zoomlevel */ RenderStyleItem ri = null; int type = geometryType.nativeInt; if (type < 1 || type > 3) { log.debug("invalid geometry type for RenderTheme " + geometryType.name()); return(null); } RenderStyleCache cache = mStyleCache[type - 1]; /* NOTE: maximum zoom level supported is 32 */ int zoomMask = 1 << zoomLevel; lock (cache) { if ((cache.prevItem == null) || (cache.prevItem.zoom & zoomMask) == 0) { /* previous instructions zoom does not match */ cache.cacheKey.set(tags, null); } else { /* compare if tags match previous instructions */ if (cache.cacheKey.set(tags, cache.prevItem.key)) { ri = cache.prevItem; //log.debug(hitCount + "/" + sameCount.incrementAndGet() // + "/" + missCount + "same hit " + tags); } } if (ri == null) { /* get instruction for current cacheKey */ ris = cache.RenderInstructions; for (ri = ris; ri != null; ri = ri.next) { if ((ri.zoom & zoomMask) != 0) { /* cache hit */ //log.debug(hitCount.incrementAndGet() // + "/" + sameCount + "/" + missCount // + " cache hit " + tags); break; } } } if (ri == null) { /* cache miss */ //missCount.incrementAndGet(); IList <RenderStyle> matches = cache.instructionList; matches.Clear(); foreach (Rule rule in mRules) { rule.matchElement(cache.matchType, cache.cacheKey.mTags, zoomMask, matches); } int size = matches.Count; if (size > 1) { for (int i = 0; i < size - 1; i++) { RenderStyle r = matches[i]; for (int j = i + 1; j < size; j++) { if (matches[j] == r) { //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: log.debug("fix duplicate instruction! " + Arrays.deepToString(cache.cacheKey.mTags) + " zoom:" + zoomLevel + " " + r.GetType().FullName); matches.RemoveAt(j--); size--; } } } } /* check if same instructions are used in another level */ for (ri = ris; ri != null; ri = ri.next) { if (size == 0) { if (ri.list != null) { continue; } /* both matchinglists are empty */ break; } if (ri.list == null) { continue; } if (ri.list.Length != size) { continue; } int i = 0; foreach (RenderStyle r in ri.list) { if (r != matches[i]) { break; } i++; } if (i == size) /* both matching lists contain the same items */ { break; } } if (ri != null) { /* we found a same matchting list on another zoomlevel add * this zoom level to the existing RenderInstructionItem. */ ri.zoom |= zoomMask; //log.debug(zoomLevel + " same instructions " + size + " " // + Arrays.deepToString(tags)); } else { //log.debug(zoomLevel + " new instructions " + size + " " // + Arrays.deepToString(tags)); ri = new RenderStyleItem(this); ri.zoom = zoomMask; if (size > 0) { ri.list = new RenderStyle[size]; matches.toArray(ri.list); } /* attach this list to the one found for MatchingKey */ if (ris != null) { ri.next = ris.next; ri.key = ris.key; ris.next = ri; } else { ri.key = new MatchingCacheKey(cache.cacheKey); cache.cache.put(ri.key, ri); } } } cache.prevItem = ri; } return(ri.list); }