loleaflet/src/layer/tile/CalcTileLayer.js |  152 ++++++++++++++++++++++++++++--
 1 file changed, 142 insertions(+), 10 deletions(-)

New commits:
commit 7c8b5ff12fb270c10e33c537a6d131007f6e87ec
Author:     Dennis Francis <dennis.fran...@collabora.com>
AuthorDate: Thu May 14 22:49:30 2020 +0530
Commit:     Dennis Francis <dennis.fran...@collabora.com>
CommitDate: Sun Jul 5 09:56:54 2020 +0200

    add table outline query interfaces
    
    Change-Id: Ibd26592e321af1dca5ee7ff369e58b1f51dc480b
    Reviewed-on: https://gerrit.libreoffice.org/c/online/+/97942
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Dennis Francis <dennis.fran...@collabora.com>

diff --git a/loleaflet/src/layer/tile/CalcTileLayer.js 
b/loleaflet/src/layer/tile/CalcTileLayer.js
index b3b7c7037..974c1daae 100644
--- a/loleaflet/src/layer/tile/CalcTileLayer.js
+++ b/loleaflet/src/layer/tile/CalcTileLayer.js
@@ -841,7 +841,7 @@ L.SheetDimension = L.Class.extend({
                this._sizes = new L.SpanList();
                this._hidden = new L.BoolSpanList();
                this._filtered = new L.BoolSpanList();
-               this._groups = new L.DimensionOutlines();
+               this._outlines = new L.DimensionOutlines();
 
                // This is used to store the span-list of sizes
                // with hidden/filtered elements set to zero size.
@@ -876,7 +876,7 @@ L.SheetDimension = L.Class.extend({
                }
 
                if (jsonObject.hasOwnProperty('groups')) {
-                       thisLoadOK = this._groups.load(jsonObject.groups);
+                       thisLoadOK = this._outlines.load(jsonObject.groups);
                        loadsOK = loadsOK && thisLoadOK;
                }
 
@@ -939,25 +939,27 @@ L.SheetDimension = L.Class.extend({
                });
        },
 
-       getElementData: function (index) {
+       // returns the element pos/size in css pixels by default.
+       getElementData: function (index, useDevicePixels) {
                var span = this._visibleSizes.getSpanDataByIndex(index);
                if (span === undefined) {
                        return undefined;
                }
 
-               return this._getElementDataFromSpanByIndex(index, span);
+               return this._getElementDataFromSpanByIndex(index, span, 
useDevicePixels);
        },
 
-       _getElementDataFromSpanByIndex: function (index, span) {
+       // returns element pos/size in css pixels by default.
+       _getElementDataFromSpanByIndex: function (index, span, useDevicePixels) 
{
                if (span === undefined || index < span.start || span.end < 
index) {
                        return undefined;
                }
 
                var numSizes = span.end - index + 1;
-               // all in css pixels.
+               var pixelScale = useDevicePixels ? this._devPixelsPerCssPixel : 
1;
                return {
-                       startpos: (span.data.posdevpx - span.data.sizedev * 
numSizes) / this._devPixelsPerCssPixel,
-                       size: span.data.sizedev / this._devPixelsPerCssPixel
+                       startpos: (span.data.posdevpx - span.data.sizedev * 
numSizes) / pixelScale,
+                       size: span.data.sizedev / pixelScale
                };
        },
 
@@ -1432,16 +1434,19 @@ L.DimensionOutlines = L.Class.extend({
 
                                var olineEntry = {
                                        start: parseInt(entrySplits[0]),
-                                       size: parseInt(entrySplits[1]),
+                                       end: parseInt(entrySplits[1]), // this 
is size.
                                        hidden: parseInt(entrySplits[2]),
                                        visible: parseInt(entrySplits[3])
                                };
 
-                               if (isNaN(olineEntry.start) || 
isNaN(olineEntry.size) ||
+                               if (isNaN(olineEntry.start) || 
isNaN(olineEntry.end) ||
                                        isNaN(olineEntry.hidden) || 
isNaN(olineEntry.visible)) {
                                        return false;
                                }
 
+                               // correct the 'end' attribute.
+                               olineEntry.end += (olineEntry.start - 1);
+
                                collections.push(olineEntry);
                        }
 
@@ -1450,5 +1455,132 @@ L.DimensionOutlines = L.Class.extend({
 
                this._outlines = outlines;
                return true;
+       },
+
+       getLevels: function () {
+               return this._outlines.length;
+       },
+
+       // Calls 'callback' for all groups in all levels that have an 
intersection with the inclusive element range [start, end].
+       // 'callback' is called with these parameters : (levelIdx, groupIdx, 
groupStart, groupEnd, groupHidden).
+       forEachGroupInRange: function (start, end, callback) {
+
+               if (start === undefined || end === undefined || callback === 
undefined) {
+                       return;
+               }
+
+               if (!this._outlines.length || start > end) {
+                       return;
+               }
+
+               // Search direction provider for binarySearch().
+               // Here we want to find the first group after or intersects 
elementIdx.
+               // return value : 0 for match, -1 for "try previous entries", 
+1 for "try next entries".
+               var directionProvider = function (elementIdx, prevGroup, 
curGroup/*, nextGroup*/) {
+
+                       var direction = (elementIdx < curGroup.start) ? -1 :
+                               (curGroup.end < elementIdx) ? 1 : 0;
+
+                       if (direction >= 0) {
+                               return direction;
+                       }
+
+                       // If curGroup is the first one, or elementidx is after 
prevGroup's end, then it is a match.
+                       if (!prevGroup || (prevGroup.end < elementIdx)) {
+                               return 0;
+                       }
+
+                       return -1;
+               };
+
+               for (var levelIdx = this._outlines.length - 1; levelIdx >= 0; 
--levelIdx) {
+
+                       var groupsInLevel = this._outlines[levelIdx];
+                       // Find the first group after or that intersects 
'start'.
+                       var startGroupIdx = binarySearch(groupsInLevel, start, 
directionProvider);
+                       if (startGroupIdx == -1) {
+                               // All groups at this level are before 'start'.
+                               continue;
+                       }
+
+                       var startGroup = groupsInLevel[startGroupIdx];
+                       if (end < startGroup.start) {
+                               // No group at this level intersects the range 
[start, end].
+                               continue;
+                       }
+
+                       for (var groupIdx = startGroupIdx; groupIdx < 
groupsInLevel.length; ++groupIdx) {
+                               var group = groupsInLevel[groupIdx];
+                               if (end < group.start) {
+                                       continue;
+                               }
+
+                               callback(levelIdx, groupIdx, group.start,
+                                       group.end, group.hidden);
+                       }
+               }
        }
 });
+
+
+// Does binary search on array for key, possibly using a custom direction 
provider.
+// Of course, this assumes that the array is sorted (w.r.t to the semantics of
+// the directionProvider when it is provided).
+// It returns the index of the match if successful else returns -1.
+//
+// directionProvider will be provided the following parameters :
+// (key, previousArrayElement, currentArrayElement, nextArrayElement)
+// previousArrayElement and nextArrayElement can be undefined when
+// currentArrayElement is the first or the last element of the array
+// respectively. This function should return:
+//   0: for a match(to stop search),
+//   1: to try searching upper half,
+//  -1: to try searching lower half
+
+function binarySearch(array, key, directionProvider) {
+
+       if (array === undefined || !array.length) {
+               return -1;
+       }
+
+       if (directionProvider === undefined) {
+               directionProvider = function (key, testvalue) {
+                       return (key === testvalue) ? 0 :
+                               (key < testvalue) ? -1 : 1;
+               };
+       }
+
+       var start = 0;
+       var end = array.length - 1;
+
+       // Bound checks and early exit.
+       var startDir = directionProvider(key, undefined, array[0], array[1]);
+       if (startDir <= 0) {
+               return startDir;
+       }
+
+       var endDir = directionProvider(key, array[end - 1], array[end]);
+       if (endDir >= 0) {
+               return endDir ? -1 : end;
+       }
+
+       var mid = -1;
+       while (start <= end) {
+               mid = Math.round((start + end) / 2);
+               var direction = directionProvider(key, array[mid-1],
+                       array[mid], array[mid+1]);
+
+               if (direction == 0) {
+                       break;
+               }
+
+               if (direction == -1) {
+                       end = mid - 1;
+               }
+               else {
+                       start = mid + 1;
+               }
+       }
+
+       return (start > end) ? -1 : mid;
+}
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to