Esempio n. 1
0
void read_tile_samples(KVS &store, int uid, std::string full_channel_name, TileIndex requested_index, TileIndex client_tile_index, std::vector<DataSample<T> > &samples, bool &binned)
{
  Channel ch(store, uid, full_channel_name);
  Tile tile;
  TileIndex actual_index;
  bool success = ch.read_tile_or_closest_ancestor(requested_index, actual_index, tile);

  if (!success) {
    log_f("gettile: no tile found for %s", requested_index.to_string().c_str());
  } else {
    log_f("gettile: requested %s: found %s", requested_index.to_string().c_str(), actual_index.to_string().c_str());
    for (unsigned i = 0; i < tile.get_samples<T>().size(); i++) {
      DataSample<T> &sample=tile.get_samples<T>()[i];
      if (client_tile_index.contains_time(sample.time)) samples.push_back(sample);
    }
  }

  if (samples.size() <= 512) {
    binned = false;
  } else {
    // Bin
    binned = true;
    std::vector<DataAccumulator<T> > bins(512);
    for (unsigned i = 0; i < samples.size(); i++) {
      DataSample<T> &sample=samples[i];
      bins[(int)floor(client_tile_index.position(sample.time)*512)] += sample;
    }
    samples.clear();
    for (unsigned i = 0; i < bins.size(); i++) {
      if (bins[i].weight > 0) samples.push_back(bins[i].get_sample());
    }
  }
}
Esempio n. 2
0
void TestItemMarkerTiler::testIndices()
{
    const int maxLevel = TileIndex::MaxLevel;

    for (int l = 0; l<=maxLevel; ++l)
    {
        const TileIndex tileIndex = TileIndex::fromCoordinates(coord_1_2, l);
        QVERIFY(tileIndex.level() == l);
    }
}
Esempio n. 3
0
void Channel::move_root_upwards(TileIndex new_root_index, TileIndex old_root_index) {
  Tile old_root_tile;
  Tile empty_tile;
  assert(read_tile(old_root_index, old_root_tile));
  TileIndex ti = old_root_index;
  while (ti != new_root_index) {
    write_tile(ti.sibling(), empty_tile);
    write_tile(ti.parent(), old_root_tile);
    ti = ti.parent();
  }
}
Esempio n. 4
0
TileIndex TileIndex::fromIntList(const QIntList& intList)
{
    TileIndex result;

    for (int i = 0; i < intList.count(); ++i)
    {
        result.appendLinearIndex(intList.at(i));
    }

    return result;
}
Esempio n. 5
0
IntRect TileGrid::rectForTileIndex(const TileIndex& tileIndex) const
{
    // FIXME: calculating the scaled size here should match with the rest of calculated sizes where we use the combination of
    // enclosingIntRect, expandedIntSize (floor vs ceil).
    // However enclosing this size could reveal gap on root layer's background. see RenderView::backgroundRect()
    IntSize tileSize = m_controller.tileSize();
    IntRect rect(tileIndex.x() * tileSize.width(), tileIndex.y() * tileSize.height(), tileSize.width(), tileSize.height());
    IntRect scaledBounds(m_controller.bounds());
    scaledBounds.scale(m_scale);
    rect.intersect(scaledBounds);
    return rect;
}
Esempio n. 6
0
TileIndex TileIndex::mid(const int first, const int len) const
{
    GEOIFACE_ASSERT(first+(len-1) <= m_indicesCount);
    TileIndex result;

    for (int i = first; i < first+len; ++i)
    {
        result.appendLinearIndex(m_indices[i]);
    }

    return result;
}
Esempio n. 7
0
bool TileIndex::indicesEqual(const TileIndex& a, const TileIndex& b, const int upToLevel)
{
    GEOIFACE_ASSERT(a.level() >= upToLevel);
    GEOIFACE_ASSERT(b.level() >= upToLevel);

    for (int i = 0; i <= upToLevel; ++i)
    {
        if (a.linearIndex(i)!=b.linearIndex(i))
        {
            return false;
        }
    }

    return true;
}
Esempio n. 8
0
bool Channel::read_tile(TileIndex ti, Tile &tile) const {
  std::string binary;
  if (!m_kvs.get(tile_key(ti), binary)) return false;
  total_tiles_read++;
  tile.from_binary(binary);
  if (verbosity) log_f("Channel: read_tile %s %s: %s", 
                       descriptor().c_str(), ti.to_string().c_str(), tile.summary().c_str());
  return true;
}
Esempio n. 9
0
void Channel::write_tile(TileIndex ti, const Tile &tile) {
  std::string binary;
  tile.to_binary(binary);
  //assert(binary.size() <= m_max_tile_size);
  m_kvs.set(tile_key(ti), binary);
  total_tiles_written++;
  if (verbosity) log_f("Channel: write_tile %s %s: %s", 
                       descriptor().c_str(), ti.to_string().c_str(), tile.summary().c_str());
}
Esempio n. 10
0
void Channel::create_parent_tile_from_children(TileIndex parent_index, Tile &parent, Tile children[]) {
  // Subsample the children to create the parent
  // when do we want to show original values?
  // when do we want to do a real low-pass filter?
  // do we need to filter more than just the child tiles? e.g. gaussian beyond the tile border
  if (verbosity) log_f("Channel: creating parent %s from children %s, %s",
                       parent_index.to_string().c_str(),
                       parent_index.left_child().to_string().c_str(),
                       parent_index.right_child().to_string().c_str());

  combine_samples(BT_CHANNEL_DOUBLE_SAMPLES, parent_index, parent.double_samples, children[0].double_samples, children[1].double_samples);
  if (children[0].double_samples.size() + children[1].double_samples.size()) assert(parent.double_samples.size());

  combine_samples(BT_CHANNEL_STRING_SAMPLES, parent_index, parent.string_samples, children[0].string_samples, children[1].string_samples);
  if (children[0].string_samples.size() + children[1].string_samples.size()) assert(parent.string_samples.size());

  parent.ranges = children[0].ranges;
  parent.ranges.add(children[1].ranges);
}
Esempio n. 11
0
void combine_samples(unsigned int n_samples,
                     TileIndex parent_index,
                     std::vector<DataSample<T> > &parent,
                     const std::vector<DataSample<T> > &left_child,
                     const std::vector<DataSample<T> > &right_child)
{
  std::vector<DataAccumulator<T> > bins(n_samples);

  const std::vector<DataSample<T> > *children[2];
  children[0]=&left_child; children[1]=&right_child;

  int n=0;
  for (unsigned j = 0; j < 2; j++) {
    const std::vector<DataSample<T> > &child = *children[j];
    for (unsigned i = 0; i < child.size(); i++) {
      // Version 1: bin samples into correct bin
      // Version 2: try gaussian or lanczos(1) or 1/4 3/4 3/4 1/4
      
      const DataSample<T> &sample = child[i];
      assert(parent_index.contains_time(sample.time));
      unsigned bin = (unsigned) floor(parent_index.position(sample.time) * n_samples);
      assert(bin < n_samples);
      n++;
      bins[bin] += sample;
      assert(bins[bin].weight>0);
    }
  }

  n = 0;
  int m=0;
  parent.clear();
  for (unsigned i = 0; i < bins.size(); i++) {
    if (bins[i].weight > 0) {
      parent.push_back(bins[i].get_sample());
      assert(parent.size());
      n++;
    } else {
      m++;
    }
  }
  if (left_child.size() || right_child.size()) assert(parent.size());
}
Esempio n. 12
0
IntRect TileGrid::extent() const
{
    TileIndex topLeft;
    TileIndex bottomRight;
    getTileIndexRangeForRect(m_primaryTileCoverageRect, topLeft, bottomRight);

    // Return index of top, left tile and the number of tiles across and down.
    return IntRect(topLeft.x(), topLeft.y(), bottomRight.x() - topLeft.x() + 1, bottomRight.y() - topLeft.y() + 1);
}
Esempio n. 13
0
TileIndex Channel::split_tile_if_needed(TileIndex ti, Tile &tile) {
  TileIndex new_root_index = TileIndex::null();
  if (tile.binary_length() <= m_max_tile_size) return new_root_index;
  Tile children[2];
  TileIndex child_indexes[2];
  if (verbosity) log_f("split_tile_if_needed: splitting tile %s", ti.to_string().c_str());

  // If we're splitting an "all" tile, it means that until now the channel has only had one tile's worth of
  // data, and that a proper root tile location couldn't be selected.  Select a new root tile now.
  if (ti.is_nonnegative_all()) {
    // TODO: this breaks if all samples are at one time
    ti = new_root_index = TileIndex::index_containing(Range(tile.first_sample_time(), tile.last_sample_time()));
    if (verbosity) log_f("split_tile_if_needed: Moving root tile to %s", ti.to_string().c_str());
  }
  
  child_indexes[0]= ti.left_child();
  child_indexes[1]= ti.right_child();

  double split_time = ti.right_child().start_time();
  split_samples(tile.double_samples, split_time, children[0], children[1]);
  split_samples(tile.string_samples, split_time, children[0], children[1]);

  for (int i = 0; i < 2; i++) {
    assert(!has_tile(child_indexes[i]));
    assert(split_tile_if_needed(child_indexes[i], children[i]) == TileIndex::null());
    write_tile(child_indexes[i], children[i]);
  }
  create_parent_tile_from_children(ti, tile, children);
  return new_root_index;
}
Esempio n. 14
0
bool Channel::read_tile_or_closest_ancestor(TileIndex ti, TileIndex &ret_index, Tile &ret) const {
  Locker lock(*this);  // Lock self and hold lock until exiting this method
  ChannelInfo info;
  bool success = read_info(info);
  if (!success) {
    if (verbosity) log_f("read_tile_or_closest_ancestor: can't read info");
    return false;
  }
  TileIndex root = info.nonnegative_root_tile_index;

  if (ti.is_ancestor_of(root)) {
    ret_index = root;
  } else {
    if (ti != root && !root.is_ancestor_of(ti)) {
      // Tile isn't under root
      return false;
    }
    
    assert(tile_exists(root));
    ret_index = root;
    while (ret_index != ti) {
      TileIndex child = ti.start_time() < ret_index.left_child().end_time() ? ret_index.left_child() : ret_index.right_child();
      if (!tile_exists(child)) break;
      ret_index = child;
    }
  }
  // ret_index now holds closest ancestor to ti (or ti itself if it exists)  
    
  assert(read_tile(ret_index, ret));
  return true;
}
Esempio n. 15
0
void TileGrid::setNeedsDisplayInRect(const IntRect& rect)
{
    if (m_tiles.isEmpty())
        return;

    FloatRect scaledRect(rect);
    scaledRect.scale(m_scale);
    IntRect repaintRectInTileCoords(enclosingIntRect(scaledRect));

    IntSize tileSize = m_controller.tileSize();

    // For small invalidations, lookup the covered tiles.
    if (repaintRectInTileCoords.height() < 2 * tileSize.height() && repaintRectInTileCoords.width() < 2 * tileSize.width()) {
        TileIndex topLeft;
        TileIndex bottomRight;
        getTileIndexRangeForRect(repaintRectInTileCoords, topLeft, bottomRight);

        for (int y = topLeft.y(); y <= bottomRight.y(); ++y) {
            for (int x = topLeft.x(); x <= bottomRight.x(); ++x) {
                TileIndex tileIndex(x, y);

                TileMap::iterator it = m_tiles.find(tileIndex);
                if (it != m_tiles.end())
                    setTileNeedsDisplayInRect(tileIndex, it->value, repaintRectInTileCoords, m_primaryTileCoverageRect);
            }
        }
        return;
    }

    for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it)
        setTileNeedsDisplayInRect(it->key, it->value, repaintRectInTileCoords, m_primaryTileCoverageRect);
}
Esempio n. 16
0
void Channel::read_bottommost_tiles_in_range(Range times,
                                             bool (*callback)(const Tile &t, Range times)) const {
  ChannelInfo info;
  bool success = read_info(info);
  if (!success) return;
  if (!info.times.intersects(times)) return;

  double time = times.min;
  TileIndex ti = TileIndex::null();
  while (time < times.max) {
    if (ti.is_null()) {
      ti = find_lowest_child_overlapping_time(info.nonnegative_root_tile_index, times.min);
    } else {
      ti = find_lowest_successive_tile(info.nonnegative_root_tile_index, ti);
    }
    if (ti.is_null() || ti.start_time() >= times.max) break;

    Tile t;
    assert(read_tile(ti, t));
    if (!(*callback)(t, times)) break;
  }
}
Esempio n. 17
0
void Channel::read_data(std::vector<DataSample<double> > &data, double begin, double end) const {
  double time = begin;
  data.clear();

  Locker lock(*this);  // Lock self and hold lock until exiting this method

  ChannelInfo info;
  bool success = read_info(info);
  if (!success) {
    // Channel doesn't yet exist;  no data
    if (verbosity) log_f("read_data: can't read info");
    return;
  }
  bool first_tile = true;

  while (time < end) {
    TileIndex ti = find_lowest_child_overlapping_time(info.nonnegative_root_tile_index, time);
    if (ti.is_null()) {
      // No tiles; no more data
      if (verbosity) log_f("read_data: can't read tile");
      return;
    }

    Tile tile;
    assert(read_tile(ti, tile));
    unsigned i = 0;
    if (first_tile) {
      // Skip any samples before requested time
      for (; i < tile.double_samples.size() && tile.double_samples[i].time < begin; i++);
    }

    for (; i < tile.double_samples.size() && tile.double_samples[i].time < end; i++) {
      data.push_back(tile.double_samples[i]);
    }
    time = ti.end_time();
  }
}
Esempio n. 18
0
   Project(Display *display, Player *player)
      : NewWorldScreen(display, player)
      , bitmaps("data")
      , motion()
      , tile_index()
   {
      level = new Level();
      current_map = new Map();
      level->maps.push_back(current_map);

      tile_index.load_from_atlas(bitmaps["spritesheet.png"], 21, 21, 2, 2, 1, 1);
      current_map->tile_layers.push_back(TileLayer(&tile_index, 60, 60));

      // fill our map with random tiles
      for (unsigned x=0; x<current_map->tile_layers.back().width; x++)
         for (unsigned y=0; y<current_map->tile_layers.back().height; y++)
            current_map->tile_layers.back().set_tile(x, y, random_int(0, 200));
   }
Esempio n. 19
0
TileIndex Channel::find_child_overlapping_time(TileIndex ti, double t, int desired_level) const {
  assert(!ti.is_null());
  // Start at root tile and move downwards

  while (ti.level > desired_level) {
    // Select correct child
    TileIndex child = t < ti.left_child().end_time() ? ti.left_child() : ti.right_child();
    
    if (child.is_null() || !tile_exists(child)) break;
    ti = child;
  }

  return ti;
}
Esempio n. 20
0
TileIndex Channel::find_successive_tile(TileIndex root, TileIndex ti, int desired_level) const {
  // Move upwards until parent has a different end time
  while (1) {
    if (ti.parent().is_null()) return TileIndex::null();
    if (ti.parent().end_time() != ti.end_time()) break;
    ti = ti.parent();
    if (ti.level >= root.level) {
      // No more underneath the root
      return TileIndex::null();
    }
  }
  // We are now the left child of our parent;  skip to the right child
  ti = ti.sibling();

  return find_child_overlapping_time(ti, ti.start_time(), desired_level);
}
Esempio n. 21
0
void TileGrid::getTileIndexRangeForRect(const IntRect& rect, TileIndex& topLeft, TileIndex& bottomRight) const
{
    IntRect clampedRect = m_controller.bounds();
    clampedRect.scale(m_scale);
    clampedRect.intersect(rect);

    auto tileSize = m_controller.tileSize();
    if (clampedRect.x() >= 0)
        topLeft.setX(clampedRect.x() / tileSize.width());
    else
        topLeft.setX(floorf((float)clampedRect.x() / tileSize.width()));

    if (clampedRect.y() >= 0)
        topLeft.setY(clampedRect.y() / tileSize.height());
    else
        topLeft.setY(floorf((float)clampedRect.y() / tileSize.height()));

    int bottomXRatio = ceil((float)clampedRect.maxX() / tileSize.width());
    bottomRight.setX(std::max(bottomXRatio - 1, 0));

    int bottomYRatio = ceil((float)clampedRect.maxY() / tileSize.height());
    bottomRight.setY(std::max(bottomYRatio - 1, 0));
}
Esempio n. 22
0
TileIndex TileIndex::fromCoordinates(const GeoIface::GeoCoordinates& coordinate, const int getLevel)
{
    GEOIFACE_ASSERT(getLevel<=MaxLevel);

    if (!coordinate.hasCoordinates())
        return TileIndex();

    qreal tileLatBL     = -90.0;
    qreal tileLonBL     = -180.0;
    qreal tileLatHeight = 180.0;
    qreal tileLonWidth  = 360.0;

    TileIndex resultIndex;

    for (int l = 0; l <= getLevel; ++l)
    {
        // how many tiles at this level?
        const qreal latDivisor = TileIndex::Tiling;
        const qreal lonDivisor = TileIndex::Tiling;

        const qreal dLat       = tileLatHeight / latDivisor;
        const qreal dLon       = tileLonWidth / lonDivisor;

        int latIndex           = int( (coordinate.lat() - tileLatBL ) / dLat );
        int lonIndex           = int( (coordinate.lon() - tileLonBL ) / dLon );

        // protect against invalid indices due to rounding errors
        bool haveRoundingErrors = false;

        if (latIndex < 0)
        {
            haveRoundingErrors = true;
            latIndex           = 0;
        }

        if (lonIndex < 0)
        {
            haveRoundingErrors = true;
            lonIndex           = 0;
        }

        if (latIndex >= latDivisor)
        {
            haveRoundingErrors = true;
            latIndex           = latDivisor-1;
        }

        if (lonIndex >= lonDivisor)
        {
            haveRoundingErrors = true;
            lonIndex           = lonDivisor-1;
        }

        if (haveRoundingErrors)
        {
//             qCDebug(DIGIKAM_GEOIFACE_LOG) << QString::fromLatin1("Rounding errors at level %1!").arg(l);
        }

        resultIndex.appendLatLonIndex(latIndex, lonIndex);

        // update the start position for the next tile:
        // TODO: rounding errors
        tileLatBL     += latIndex*dLat;
        tileLonBL     += lonIndex*dLon;
        tileLatHeight /= latDivisor;
        tileLonWidth  /= lonDivisor;
    }

    return resultIndex;
}
Esempio n. 23
0
void Channel::add_data_internal(const std::vector<DataSample<T> > &data, DataRanges *channel_ranges) {
  if (!data.size()) return;
  // Sanity check
  if (data[0].time < 0) throw std::runtime_error("Unimplemented feature: adding data with negative time");
  for (unsigned i = 0; i < data.size()-1; i++) {
    if (data[i].time > data[i+1].time) throw std::runtime_error("Attempt to add data that is not sorted by ascending time");
  }

  //	regenerate = empty set
  Locker lock(*this);  // Lock self and hold lock until exiting this method
  std::set<TileIndex> to_regenerate;

  ChannelInfo info;
  bool success = read_info(info);
  if (!success) {
    // New channel
    info.magic = ChannelInfo::MAGIC;
    info.version = 0x00010000;
    info.times = Range(data[0].time, data.back().time);
    info.nonnegative_root_tile_index = TileIndex::nonnegative_all();
    create_tile(TileIndex::nonnegative_all());
    info.negative_root_tile_index = TileIndex::null();
  } else {
    info.times.add(Range(data[0].time, data.back().time));
    // If we're not the all-tile, see if we need to move the root upwards
    if (info.nonnegative_root_tile_index != TileIndex::nonnegative_all()) {
      TileIndex new_nonnegative_root_tile_index = TileIndex::index_containing(info.times);
      if (new_nonnegative_root_tile_index.level > info.nonnegative_root_tile_index.level) {
	// Root index changed.  Confirm new root is parent or more distant ancestor of old root
	assert(new_nonnegative_root_tile_index.is_ancestor_of(info.nonnegative_root_tile_index));
	// Trigger regeneration from old root's parent, up through new root
	to_regenerate.insert(info.nonnegative_root_tile_index.parent());
	move_root_upwards(new_nonnegative_root_tile_index, info.nonnegative_root_tile_index);
	info.nonnegative_root_tile_index = new_nonnegative_root_tile_index;
      }
    }
  }

  unsigned i=0;

  while (i < data.size()) {
    TileIndex ti= find_lowest_child_overlapping_time(info.nonnegative_root_tile_index, data[i].time);
    assert(!ti.is_null());

    Tile tile;
    assert(read_tile(ti, tile));
    const DataSample<T> *begin = &data[i];
    while (i < data.size() && ti.contains_time(data[i].time)) i++;
    const DataSample<T> *end = &data[i];
    tile.insert_samples(begin, end);
    
    TileIndex new_root = split_tile_if_needed(ti, tile);
    if (new_root != TileIndex::null()) {
      assert(ti == TileIndex::nonnegative_all());
      if (verbosity) log_f("Channel: %s changing root from %s to %s",
                           descriptor().c_str(), ti.to_string().c_str(),
                           new_root.to_string().c_str());
      info.nonnegative_root_tile_index = new_root;
      delete_tile(ti); // Delete old root
      ti = new_root;
    }
    write_tile(ti, tile);
    if (ti == info.nonnegative_root_tile_index && channel_ranges) { *channel_ranges = tile.ranges; }
    if (ti != info.nonnegative_root_tile_index) to_regenerate.insert(ti.parent());
  }
  
  // Regenerate from lowest level to highest
  while (!to_regenerate.empty()) {
    TileIndex ti = *to_regenerate.begin();
    to_regenerate.erase(to_regenerate.begin());
    Tile regenerated, children[2];
    assert(read_tile(ti.left_child(), children[0]));
    assert(read_tile(ti.right_child(), children[1]));
    create_parent_tile_from_children(ti, regenerated, children);
    write_tile(ti, regenerated);
    if (ti == info.nonnegative_root_tile_index && channel_ranges) { *channel_ranges = regenerated.ranges; }
    if (ti != info.nonnegative_root_tile_index) to_regenerate.insert(ti.parent());
  }
  write_info(info);
}
Esempio n. 24
0
void TileGrid::revalidateTiles(TileValidationPolicy validationPolicy)
{
    FloatRect coverageRect = m_controller.coverageRect();
    IntRect bounds = m_controller.bounds();

    if (coverageRect.isEmpty() || bounds.isEmpty())
        return;

    FloatRect scaledRect(coverageRect);
    scaledRect.scale(m_scale);
    IntRect coverageRectInTileCoords(enclosingIntRect(scaledRect));

    TileCohort currCohort = nextTileCohort();
    unsigned tilesInCohort = 0;

    double minimumRevalidationTimerDuration = std::numeric_limits<double>::max();
    bool needsTileRevalidation = false;

    // Move tiles newly outside the coverage rect into the cohort map.
    for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it) {
        TileInfo& tileInfo = it->value;
        TileIndex tileIndex = it->key;

        PlatformCALayer* tileLayer = tileInfo.layer.get();
        IntRect tileRect = rectForTileIndex(tileIndex);
        if (tileRect.intersects(coverageRectInTileCoords)) {
            tileInfo.cohort = VisibleTileCohort;
            if (tileInfo.hasStaleContent) {
                // FIXME: store a dirty region per layer?
                tileLayer->setNeedsDisplay();
                tileInfo.hasStaleContent = false;
            }
        } else {
            // Add to the currentCohort if not already in one.
            if (tileInfo.cohort == VisibleTileCohort) {
                tileInfo.cohort = currCohort;
                ++tilesInCohort;

                if (m_controller.unparentsOffscreenTiles())
                    tileLayer->removeFromSuperlayer();
            } else if (m_controller.unparentsOffscreenTiles() && m_controller.shouldAggressivelyRetainTiles() && tileLayer->superlayer()) {
                // Aggressive tile retention means we'll never remove cohorts, but we need to make sure they're unparented.
                // We can't immediately unparent cohorts comprised of secondary tiles that never touch the primary coverage rect,
                // because that would defeat the usefulness of prepopulateRect(); instead, age prepopulated tiles out as if they were being removed.
                for (auto& cohort : m_cohortList) {
                    if (cohort.cohort != tileInfo.cohort)
                        continue;
                    double timeUntilCohortExpires = cohort.timeUntilExpiration();
                    if (timeUntilCohortExpires > 0) {
                        minimumRevalidationTimerDuration = std::min(minimumRevalidationTimerDuration, timeUntilCohortExpires);
                        needsTileRevalidation = true;
                    } else
                        tileLayer->removeFromSuperlayer();
                    break;
                }
            }
        }
    }

    if (needsTileRevalidation)
        m_controller.scheduleTileRevalidation(minimumRevalidationTimerDuration);

    if (tilesInCohort)
        startedNewCohort(currCohort);

    if (!m_controller.shouldAggressivelyRetainTiles()) {
        if (m_controller.shouldTemporarilyRetainTileCohorts())
            scheduleCohortRemoval();
        else if (tilesInCohort)
            removeTilesInCohort(currCohort);
    }

    // Ensure primary tile coverage tiles.
    m_primaryTileCoverageRect = ensureTilesForRect(coverageRect, CoverageType::PrimaryTiles);

    if (validationPolicy & PruneSecondaryTiles) {
        removeAllSecondaryTiles();
        m_cohortList.clear();
    } else {
        for (auto& secondaryCoverageRect : m_secondaryTileCoverageRects) {
            FloatRect secondaryRectInLayerCoordinates(secondaryCoverageRect);
            secondaryRectInLayerCoordinates.scale(1 / m_scale);
            ensureTilesForRect(secondaryRectInLayerCoordinates, CoverageType::SecondaryTiles);
        }
        m_secondaryTileCoverageRects.clear();
    }

    if (m_controller.unparentsOffscreenTiles() && (validationPolicy & UnparentAllTiles)) {
        for (TileMap::iterator it = m_tiles.begin(), end = m_tiles.end(); it != end; ++it)
            it->value.layer->removeFromSuperlayer();
    }

    auto boundsAtLastRevalidate = m_controller.boundsAtLastRevalidate();
    if (boundsAtLastRevalidate != bounds) {
        // If there are margin tiles and the bounds have grown taller or wider, then the tiles that used to
        // be bottom or right margin tiles need to be invalidated.
        if (m_controller.hasMargins()) {
            if (bounds.width() > boundsAtLastRevalidate.width() || bounds.height() > boundsAtLastRevalidate.height()) {
                IntRect boundsWithoutMargin = m_controller.boundsWithoutMargin();
                IntRect oldBoundsWithoutMargin = m_controller.boundsAtLastRevalidateWithoutMargin();

                if (bounds.height() > boundsAtLastRevalidate.height()) {
                    IntRect formerBottomMarginRect = IntRect(oldBoundsWithoutMargin.x(), oldBoundsWithoutMargin.height(),
                                                     oldBoundsWithoutMargin.width(), boundsWithoutMargin.height() - oldBoundsWithoutMargin.height());
                    setNeedsDisplayInRect(formerBottomMarginRect);
                }

                if (bounds.width() > boundsAtLastRevalidate.width()) {
                    IntRect formerRightMarginRect = IntRect(oldBoundsWithoutMargin.width(), oldBoundsWithoutMargin.y(),
                                                            boundsWithoutMargin.width() - oldBoundsWithoutMargin.width(), oldBoundsWithoutMargin.height());
                    setNeedsDisplayInRect(formerRightMarginRect);
                }
            }
        }

        FloatRect scaledBounds(bounds);
        scaledBounds.scale(m_scale);
        IntRect boundsInTileCoords(enclosingIntRect(scaledBounds));

        TileIndex topLeftForBounds;
        TileIndex bottomRightForBounds;
        getTileIndexRangeForRect(boundsInTileCoords, topLeftForBounds, bottomRightForBounds);

        Vector<TileIndex> tilesToRemove;
        for (auto& index : m_tiles.keys()) {
            if (index.y() < topLeftForBounds.y() || index.y() > bottomRightForBounds.y() || index.x() < topLeftForBounds.x() || index.x() > bottomRightForBounds.x())
                tilesToRemove.append(index);
        }
        removeTiles(tilesToRemove);
    }

    m_controller.didRevalidateTiles();
}
Esempio n. 25
0
bool Channel::delete_tile(TileIndex ti) {
  return m_kvs.del(tile_key(ti));
  if (verbosity) log_f("Channel: delete_tile %s %s", 
                       descriptor().c_str(), ti.to_string().c_str());
}
Esempio n. 26
0
IntRect TileGrid::ensureTilesForRect(const FloatRect& rect, CoverageType newTileType)
{
    if (m_controller.unparentsOffscreenTiles() && !m_controller.isInWindow())
        return IntRect();

    FloatRect scaledRect(rect);
    scaledRect.scale(m_scale);
    IntRect rectInTileCoords(enclosingIntRect(scaledRect));

    TileIndex topLeft;
    TileIndex bottomRight;
    getTileIndexRangeForRect(rectInTileCoords, topLeft, bottomRight);

    TileCohort currCohort = nextTileCohort();
    unsigned tilesInCohort = 0;

    IntRect coverageRect;

    for (int y = topLeft.y(); y <= bottomRight.y(); ++y) {
        for (int x = topLeft.x(); x <= bottomRight.x(); ++x) {
            TileIndex tileIndex(x, y);

            IntRect tileRect = rectForTileIndex(tileIndex);
            TileInfo& tileInfo = m_tiles.add(tileIndex, TileInfo()).iterator->value;

            coverageRect.unite(tileRect);

            bool shouldChangeTileLayerFrame = false;

            if (!tileInfo.layer) {
                tileInfo.layer = m_controller.createTileLayer(tileRect, *this);
                ASSERT(!m_tileRepaintCounts.contains(tileInfo.layer.get()));
            } else {
                // We already have a layer for this tile. Ensure that its size is correct.
                FloatSize tileLayerSize(tileInfo.layer->bounds().size());
                shouldChangeTileLayerFrame = tileLayerSize != FloatSize(tileRect.size());

                if (shouldChangeTileLayerFrame) {
                    tileInfo.layer->setBounds(FloatRect(FloatPoint(), tileRect.size()));
                    tileInfo.layer->setPosition(tileRect.location());
                    tileInfo.layer->setNeedsDisplay();
                }
            }

            if (newTileType == CoverageType::SecondaryTiles && !tileRect.intersects(m_primaryTileCoverageRect)) {
                tileInfo.cohort = currCohort;
                ++tilesInCohort;
            }

            bool shouldParentTileLayer = (!m_controller.unparentsOffscreenTiles() || m_controller.isInWindow()) && !tileInfo.layer->superlayer();

            if (shouldParentTileLayer)
                m_containerLayer.get().appendSublayer(*tileInfo.layer);
        }
    }

    if (tilesInCohort)
        startedNewCohort(currCohort);

    return coverageRect;
}
Esempio n. 27
0
std::string Channel::dump_tile_summaries_internal(TileIndex ti, int level) const {
  Tile tile;
  if (!read_tile(ti, tile)) return "";
  std::string ret = string_printf("%*s%d.%d: %zd samples\n", level, "", ti.level, ti.offset, tile.double_samples.size());
  return ret + dump_tile_summaries_internal(ti.left_child(), level+1) + dump_tile_summaries_internal(ti.right_child(), level+1);
}