File: IntersectionObservation.cpp

package info (click to toggle)
chromium-browser 57.0.2987.98-1~deb8u1
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 2,637,852 kB
  • ctags: 2,544,394
  • sloc: cpp: 12,815,961; ansic: 3,676,222; python: 1,147,112; asm: 526,608; java: 523,212; xml: 286,794; perl: 92,654; sh: 86,408; objc: 73,271; makefile: 27,698; cs: 18,487; yacc: 13,031; tcl: 12,957; pascal: 4,875; ml: 4,716; lex: 3,904; sql: 3,862; ruby: 1,982; lisp: 1,508; php: 1,368; exp: 404; awk: 325; csh: 117; jsp: 39; sed: 37
file content (90 lines) | stat: -rw-r--r-- 3,431 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "core/dom/IntersectionObservation.h"

#include "core/dom/ElementRareData.h"
#include "core/dom/IntersectionObserver.h"
#include "core/layout/IntersectionGeometry.h"

namespace blink {

IntersectionObservation::IntersectionObservation(IntersectionObserver& observer,
                                                 Element& target,
                                                 bool shouldReportRootBounds)
    : m_observer(observer),
      m_target(&target),
      m_shouldReportRootBounds(shouldReportRootBounds),
      m_lastThresholdIndex(0) {}

void IntersectionObservation::computeIntersectionObservations(
    DOMHighResTimeStamp timestamp) {
  DCHECK(observer());
  if (!m_target)
    return;
  Vector<Length> rootMargin(4);
  rootMargin[0] = m_observer->topMargin();
  rootMargin[1] = m_observer->rightMargin();
  rootMargin[2] = m_observer->bottomMargin();
  rootMargin[3] = m_observer->leftMargin();
  IntersectionGeometry geometry(m_observer->root(), *target(), rootMargin,
                                m_shouldReportRootBounds);
  geometry.computeGeometry();

  // Some corner cases for threshold index:
  //   - If target rect is zero area, because it has zero width and/or zero
  //     height,
  //     only two states are recognized:
  //     - 0 means not intersecting.
  //     - 1 means intersecting.
  //     No other threshold crossings are possible.
  //   - Otherwise:
  //     - If root and target do not intersect, the threshold index is 0.
  //     - If root and target intersect but the intersection has zero-area
  //       (i.e., they have a coincident edge or corner), we consider the
  //       intersection to have "crossed" a zero threshold, but not crossed
  //       any non-zero threshold.
  unsigned newThresholdIndex;
  float newVisibleRatio;
  if (geometry.doesIntersect()) {
    if (geometry.targetRect().isEmpty()) {
      newVisibleRatio = 1;
    } else {
      float intersectionArea =
          geometry.intersectionRect().size().width().toFloat() *
          geometry.intersectionRect().size().height().toFloat();
      float targetArea = geometry.targetRect().size().width().toFloat() *
                         geometry.targetRect().size().height().toFloat();
      newVisibleRatio = intersectionArea / targetArea;
    }
    newThresholdIndex = observer()->firstThresholdGreaterThan(newVisibleRatio);
  } else {
    newVisibleRatio = 0;
    newThresholdIndex = 0;
  }
  if (m_lastThresholdIndex != newThresholdIndex) {
    IntRect snappedRootBounds = geometry.rootIntRect();
    IntRect* rootBoundsPointer =
        m_shouldReportRootBounds ? &snappedRootBounds : nullptr;
    IntersectionObserverEntry* newEntry = new IntersectionObserverEntry(
        timestamp, newVisibleRatio, geometry.targetIntRect(), rootBoundsPointer,
        geometry.intersectionIntRect(), target());
    observer()->enqueueIntersectionObserverEntry(*newEntry);
    setLastThresholdIndex(newThresholdIndex);
  }
}

void IntersectionObservation::disconnect() {
  DCHECK(observer());
  if (m_target)
    target()->ensureIntersectionObserverData().removeObservation(*observer());
  m_observer.clear();
}

DEFINE_TRACE(IntersectionObservation) {
  visitor->trace(m_observer);
  visitor->trace(m_target);
}

}  // namespace blink