[Pkg-javascript-commits] [pdf.js] 28/72: Use binary search in getVisibleElements()
David Prévot
taffit at moszumanska.debian.org
Wed Mar 18 20:15:57 UTC 2015
This is an automated email from the git hooks/post-receive script.
taffit pushed a commit to branch master
in repository pdf.js.
commit a78bb6b946840a7095bce29af69a3f1c54781de8
Author: fkaelberer <l_l at gmx-topmail.de>
Date: Fri Dec 26 17:43:13 2014 +0100
Use binary search in getVisibleElements()
---
test/unit/ui_utils_spec.js | 37 ++++++++++++++++++++++
test/unit/unit_test.html | 2 ++
web/ui_utils.js | 78 ++++++++++++++++++++++++++++++++++++----------
3 files changed, 100 insertions(+), 17 deletions(-)
diff --git a/test/unit/ui_utils_spec.js b/test/unit/ui_utils_spec.js
new file mode 100644
index 0000000..757aef2
--- /dev/null
+++ b/test/unit/ui_utils_spec.js
@@ -0,0 +1,37 @@
+/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
+/* globals expect, it, describe, binarySearchFirstItem */
+
+'use strict';
+
+describe('ui_utils', function() {
+
+ describe('binary search', function() {
+ function isTrue(boolean) {
+ return boolean;
+ }
+ function isGreater3(number) {
+ return number > 3;
+ }
+
+ it('empty array', function() {
+ expect(binarySearchFirstItem([], isTrue)).toEqual(0);
+ });
+ it('single boolean entry', function() {
+ expect(binarySearchFirstItem([false], isTrue)).toEqual(1);
+ expect(binarySearchFirstItem([true], isTrue)).toEqual(0);
+ });
+ it('three boolean entries', function() {
+ expect(binarySearchFirstItem([true, true, true], isTrue)).toEqual(0);
+ expect(binarySearchFirstItem([false, true, true], isTrue)).toEqual(1);
+ expect(binarySearchFirstItem([false, false, true], isTrue)).toEqual(2);
+ expect(binarySearchFirstItem([false, false, false], isTrue)).toEqual(3);
+ });
+ it('three numeric entries', function() {
+ expect(binarySearchFirstItem([0, 1, 2], isGreater3)).toEqual(3);
+ expect(binarySearchFirstItem([2, 3, 4], isGreater3)).toEqual(2);
+ expect(binarySearchFirstItem([4, 5, 6], isGreater3)).toEqual(0);
+ });
+ });
+});
+
diff --git a/test/unit/unit_test.html b/test/unit/unit_test.html
index c8f59fc..9b43e01 100644
--- a/test/unit/unit_test.html
+++ b/test/unit/unit_test.html
@@ -40,6 +40,7 @@
<script src="../../src/core/worker.js"></script>
<script src="../../src/display/metadata.js"></script>
<script src="../../src/core/jpg.js"></script>
+ <script src="../../web/ui_utils.js"></script>
<script>PDFJS.workerSrc = '../../src/worker_loader.js';</script>
<!-- include spec files here... -->
@@ -52,6 +53,7 @@
<script src="parser_spec.js"></script>
<script src="api_spec.js"></script>
<script src="metadata_spec.js"></script>
+ <script src="ui_utils_spec.js"></script>
<script src="util_spec.js"></script>
<script src="cmap_spec.js"></script>
<script>
diff --git a/web/ui_utils.js b/web/ui_utils.js
index 00eb25e..7e798e3 100644
--- a/web/ui_utils.js
+++ b/web/ui_utils.js
@@ -160,13 +160,10 @@ function watchScroll(viewAreaElement, callback) {
var currentY = viewAreaElement.scrollTop;
var lastY = state.lastY;
- if (currentY > lastY) {
- state.down = true;
- } else if (currentY < lastY) {
- state.down = false;
+ if (currentY !== lastY) {
+ state.down = currentY > lastY;
}
state.lastY = currentY;
- // else do nothing and use previous value
callback(state);
});
};
@@ -183,36 +180,83 @@ function watchScroll(viewAreaElement, callback) {
}
/**
+ * Use binary search to find the index of the first item in a given array which
+ * passes a given condition. The items are expected to be sorted in the sense
+ * that if the condition is true for one item in the array, then it is also true
+ * for all following items.
+ *
+ * @returns {Number} Index of the first array element to pass the test,
+ * or |items.length| if no such element exists.
+ */
+function binarySearchFirstItem(items, condition) {
+ var minIndex = 0;
+ var maxIndex = items.length - 1;
+
+ if (items.length === 0 || !condition(items[maxIndex])) {
+ return items.length;
+ }
+ if (condition(items[minIndex])) {
+ return minIndex;
+ }
+
+ while (minIndex < maxIndex) {
+ var currentIndex = (minIndex + maxIndex) >> 1;
+ var currentItem = items[currentIndex];
+ if (condition(currentItem)) {
+ maxIndex = currentIndex;
+ } else {
+ minIndex = currentIndex + 1;
+ }
+ }
+ return minIndex; /* === maxIndex */
+}
+
+/**
* Generic helper to find out what elements are visible within a scroll pane.
*/
function getVisibleElements(scrollEl, views, sortByVisibility) {
var top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight;
var left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth;
- var visible = [], view;
+ function isElementBottomBelowViewTop(view) {
+ var element = view.div;
+ var elementBottom =
+ element.offsetTop + element.clientTop + element.clientHeight;
+ return elementBottom > top;
+ }
+
+ var visible = [], view, element;
var currentHeight, viewHeight, hiddenHeight, percentHeight;
var currentWidth, viewWidth;
- for (var i = 0, ii = views.length; i < ii; ++i) {
+ var firstVisibleElementInd = (views.length === 0) ? 0 :
+ binarySearchFirstItem(views, isElementBottomBelowViewTop);
+
+ for (var i = firstVisibleElementInd, ii = views.length; i < ii; i++) {
view = views[i];
- currentHeight = view.div.offsetTop + view.div.clientTop;
- viewHeight = view.div.clientHeight;
- if ((currentHeight + viewHeight) < top) {
- continue;
- }
+ element = view.div;
+ currentHeight = element.offsetTop + element.clientTop;
+ viewHeight = element.clientHeight;
+
if (currentHeight > bottom) {
break;
}
- currentWidth = view.div.offsetLeft + view.div.clientLeft;
- viewWidth = view.div.clientWidth;
- if ((currentWidth + viewWidth) < left || currentWidth > right) {
+
+ currentWidth = element.offsetLeft + element.clientLeft;
+ viewWidth = element.clientWidth;
+ if (currentWidth + viewWidth < left || currentWidth > right) {
continue;
}
hiddenHeight = Math.max(0, top - currentHeight) +
Math.max(0, currentHeight + viewHeight - bottom);
percentHeight = ((viewHeight - hiddenHeight) * 100 / viewHeight) | 0;
- visible.push({ id: view.id, x: currentWidth, y: currentHeight,
- view: view, percent: percentHeight });
+ visible.push({
+ id: view.id,
+ x: currentWidth,
+ y: currentHeight,
+ view: view,
+ percent: percentHeight
+ });
}
var first = visible[0];
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/pdf.js.git
More information about the Pkg-javascript-commits
mailing list