示例#1
0
  /**
   * Matches a way with the given parameters against this RenderTheme.
   *
   * @param renderCallback the callback implementation which will be executed on each match.
   * @param tags the tags of the way.
   * @param zoomLevel the zoom level at which the way should be matched.
   * @param closed way is Closed
   * @param render ...
   * @return currently processed render instructions
   */
  public RenderInstruction[] matchWay(
      IRenderCallback renderCallback, Tag[] tags, byte zoomLevel, boolean closed, boolean render) {

    // list of renderinsctruction items in cache
    RenderInstructionItem ris = null;

    RenderInstructionItem prevInstructions = null;

    // the item matching tags and zoomlevel
    RenderInstructionItem ri = null;

    // temporary matching instructions list
    List<RenderInstruction> matches;

    LRUCache<MatchingCacheKey, RenderInstructionItem> matchingCache;
    MatchingCacheKey cacheKey;

    if (closed) matchingCache = mAreaCache;
    else matchingCache = mWayCache;

    int zoomMask = 1 << zoomLevel;

    synchronized (matchingCache) {
      if (closed) {
        cacheKey = mAreaCacheKey;
        matches = mAreaInstructionList;
        prevInstructions = mPrevAreaItem;
      } else {
        cacheKey = mWayCacheKey;
        matches = mWayInstructionList;
        prevInstructions = mPrevWayItem;
      }

      if (prevInstructions == null || (prevInstructions.zoom & zoomMask) == 0) {
        // previous instructions zoom does not match
        cacheKey.set(tags, null);
      } else {
        // compare if tags match previous instructions
        if (cacheKey.set(tags, prevInstructions.key)) {
          // Log.d(TAG, "same as previous " +
          // Arrays.deepToString(tags));
          ri = prevInstructions;
        }
      }

      if (ri == null) {
        ris = matchingCache.get(cacheKey);

        for (ri = ris; ri != null; ri = ri.next)
          if ((ri.zoom & zoomMask) != 0)
            // cache hit
            break;
      }

      if (ri == null) {
        // cache miss
        // Log.d(TAG, missCnt++ + " / " + hitCnt + " Cache Miss");

        int c = (closed ? Closed.YES : Closed.NO);
        // List<RenderInstruction> matches = mMatchingList;
        matches.clear();

        for (int i = 0, n = mRulesList.size(); i < n; ++i)
          mRulesList.get(i).matchWay(renderCallback, tags, zoomLevel, c, matches);

        int size = matches.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;
          for (RenderInstruction r : ri.list) {
            if (r != matches.get(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
          ri.zoom |= zoomMask;
          // Log.d(TAG,
          // zoomLevel + " same instructions " + size + " "
          // + Arrays.deepToString(tags));

        } else {
          // Log.d(TAG,
          // zoomLevel + " new instructions " + size + " "
          // + Arrays.deepToString(tags));

          ri = new RenderInstructionItem();
          ri.zoom = zoomMask;

          if (size > 0) {
            ri.list = new RenderInstruction[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(cacheKey);
            matchingCache.put(ri.key, ri);
          }
        }
      }
      if (closed) mPrevAreaItem = ri;
      else mPrevWayItem = ri;
    }

    if (render && ri.list != null) {
      for (int i = 0, n = ri.list.length; i < n; i++) ri.list[i].renderWay(renderCallback, tags);
    }

    return ri.list;
  }
示例#2
0
  /**
   * @param renderCallback ...
   * @param tags ...
   * @param zoomLevel ...
   * @return ...
   */
  public RenderInstruction[] matchNode(IRenderCallback renderCallback, Tag[] tags, byte zoomLevel) {

    // list of renderinsctruction items in cache
    RenderInstructionItem ris = null;

    // the item matching tags and zoomlevel
    RenderInstructionItem ri = null;

    synchronized (mNodesCache) {
      int zoomMask = 1 << zoomLevel;

      MatchingCacheKey cacheKey = mNodeCacheKey;
      if (mPrevNodeItem == null || (mPrevNodeItem.zoom & zoomMask) == 0) {
        // previous instructions zoom does not match
        cacheKey.set(tags, null);
      } else {
        // compare if tags match previous instructions
        if (cacheKey.set(tags, mPrevNodeItem.key)) ri = mPrevNodeItem;
      }

      if (ri == null) {
        boolean found = mNodesCache.containsKey(cacheKey);

        if (found) {
          ris = mNodesCache.get(cacheKey);

          for (ri = ris; ri != null; ri = ri.next)
            if ((ri.zoom & zoomMask) != 0)
              // cache hit
              break;
        }
      }

      if (ri == null) {
        // cache miss
        List<RenderInstruction> matches = mNodeInstructionList;
        matches.clear();
        for (int i = 0, n = mRulesList.size(); i < n; ++i)
          mRulesList.get(i).matchNode(renderCallback, tags, zoomLevel, matches);

        int size = matches.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;
          for (RenderInstruction r : ri.list) {
            if (r != matches.get(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
          ri.zoom |= zoomMask;
        } else {

          ri = new RenderInstructionItem();
          ri.zoom = zoomMask;

          if (size > 0) {
            ri.list = new RenderInstruction[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(cacheKey);
            mNodesCache.put(ri.key, ri);
          }
        }
      }
    }

    if (ri.list != null) render(renderCallback, ri.list, tags);

    mPrevNodeItem = ri;

    return ri.list;
  }