mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Proper CFI calculation for paged mode
This commit is contained in:
parent
ce3fba7161
commit
89724d321d
@ -572,6 +572,44 @@ class CanonicalFragmentIdentifier
|
|||||||
null
|
null
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
at_point: (ox, oy) ->
|
||||||
|
# The CFI at the specified point. Different to at() in that this method
|
||||||
|
# returns null if there is an error, and also calculates a point from
|
||||||
|
# the CFI and returns null if the calculated point is far from the
|
||||||
|
# original point.
|
||||||
|
|
||||||
|
dist = (p1, p2) ->
|
||||||
|
Math.sqrt(Math.pow(p1[0]-p2[0], 2), Math.pow(p1[1]-p2[1], 2))
|
||||||
|
|
||||||
|
try
|
||||||
|
cfi = window.cfi.at(ox, oy)
|
||||||
|
point = window.cfi.point(cfi)
|
||||||
|
catch err
|
||||||
|
cfi = null
|
||||||
|
|
||||||
|
|
||||||
|
if cfi
|
||||||
|
if point.range != null
|
||||||
|
r = point.range
|
||||||
|
rect = r.getClientRects()[0]
|
||||||
|
|
||||||
|
x = (point.a*rect.left + (1-point.a)*rect.right)
|
||||||
|
y = (rect.top + rect.bottom)/2
|
||||||
|
[x, y] = viewport_to_document(x, y, r.startContainer.ownerDocument)
|
||||||
|
else
|
||||||
|
node = point.node
|
||||||
|
r = node.getBoundingClientRect()
|
||||||
|
[x, y] = viewport_to_document(r.left, r.top, node.ownerDocument)
|
||||||
|
if typeof(point.x) == 'number' and node.offsetWidth
|
||||||
|
x += (point.x*node.offsetWidth)/100
|
||||||
|
if typeof(point.y) == 'number' and node.offsetHeight
|
||||||
|
y += (point.y*node.offsetHeight)/100
|
||||||
|
|
||||||
|
if dist(viewport_to_document(ox, oy), [x, y]) > 50
|
||||||
|
cfi = null
|
||||||
|
|
||||||
|
return cfi
|
||||||
|
|
||||||
at_current: () -> # {{{
|
at_current: () -> # {{{
|
||||||
[winx, winy] = window_scroll_pos()
|
[winx, winy] = window_scroll_pos()
|
||||||
[winw, winh] = [window.innerWidth, window.innerHeight]
|
[winw, winh] = [window.innerWidth, window.innerHeight]
|
||||||
@ -585,44 +623,12 @@ class CanonicalFragmentIdentifier
|
|||||||
minx = max(-winx, -winw)
|
minx = max(-winx, -winw)
|
||||||
maxx = winw
|
maxx = winw
|
||||||
|
|
||||||
dist = (p1, p2) ->
|
x_loop = (cury) =>
|
||||||
Math.sqrt(Math.pow(p1[0]-p2[0], 2), Math.pow(p1[1]-p2[1], 2))
|
|
||||||
|
|
||||||
get_cfi = (ox, oy) ->
|
|
||||||
try
|
|
||||||
cfi = window.cfi.at(ox, oy)
|
|
||||||
point = window.cfi.point(cfi)
|
|
||||||
catch err
|
|
||||||
cfi = null
|
|
||||||
|
|
||||||
if cfi
|
|
||||||
if point.range != null
|
|
||||||
r = point.range
|
|
||||||
rect = r.getClientRects()[0]
|
|
||||||
|
|
||||||
x = (point.a*rect.left + (1-point.a)*rect.right)
|
|
||||||
y = (rect.top + rect.bottom)/2
|
|
||||||
[x, y] = viewport_to_document(x, y, r.startContainer.ownerDocument)
|
|
||||||
else
|
|
||||||
node = point.node
|
|
||||||
r = node.getBoundingClientRect()
|
|
||||||
[x, y] = viewport_to_document(r.left, r.top, node.ownerDocument)
|
|
||||||
if typeof(point.x) == 'number' and node.offsetWidth
|
|
||||||
x += (point.x*node.offsetWidth)/100
|
|
||||||
if typeof(point.y) == 'number' and node.offsetHeight
|
|
||||||
y += (point.y*node.offsetHeight)/100
|
|
||||||
|
|
||||||
if dist(viewport_to_document(ox, oy), [x, y]) > 50
|
|
||||||
cfi = null
|
|
||||||
|
|
||||||
return cfi
|
|
||||||
|
|
||||||
x_loop = (cury) ->
|
|
||||||
for direction in [-1, 1]
|
for direction in [-1, 1]
|
||||||
delta = deltax * direction
|
delta = deltax * direction
|
||||||
curx = 0
|
curx = 0
|
||||||
until (direction < 0 and curx < minx) or (direction > 0 and curx > maxx)
|
until (direction < 0 and curx < minx) or (direction > 0 and curx > maxx)
|
||||||
cfi = get_cfi(curx, cury)
|
cfi = this.at_point(curx, cury)
|
||||||
if cfi
|
if cfi
|
||||||
return cfi
|
return cfi
|
||||||
curx += delta
|
curx += delta
|
||||||
|
@ -67,6 +67,8 @@ class PagedDisplay
|
|||||||
###
|
###
|
||||||
|
|
||||||
constructor: () ->
|
constructor: () ->
|
||||||
|
if not this instanceof arguments.callee
|
||||||
|
throw new Error('PagedDisplay constructor called as function')
|
||||||
this.set_geometry()
|
this.set_geometry()
|
||||||
this.page_width = 0
|
this.page_width = 0
|
||||||
this.screen_width = 0
|
this.screen_width = 0
|
||||||
@ -213,11 +215,11 @@ class PagedDisplay
|
|||||||
# most column in the viewport is the column containing the start of the
|
# most column in the viewport is the column containing the start of the
|
||||||
# element and that the scroll position is at the start of the column.
|
# element and that the scroll position is at the start of the column.
|
||||||
elem = document.getElementById(name)
|
elem = document.getElementById(name)
|
||||||
if !elem
|
if not elem
|
||||||
elems = document.getElementsByName(name)
|
elems = document.getElementsByName(name)
|
||||||
if elems
|
if elems
|
||||||
elem = elems[0]
|
elem = elems[0]
|
||||||
if !elem
|
if not elem
|
||||||
return
|
return
|
||||||
elem.scrollIntoView()
|
elem.scrollIntoView()
|
||||||
if this.in_paged_mode
|
if this.in_paged_mode
|
||||||
@ -249,12 +251,48 @@ class PagedDisplay
|
|||||||
window.scrollTo(0, y)
|
window.scrollTo(0, y)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
current_cfi: () ->
|
||||||
|
# The Conformal Fragment Identifier at the current position, returns
|
||||||
|
# null if it could not be calculated. Requires the cfi.coffee library.
|
||||||
|
ans = null
|
||||||
|
if not window.cfi?
|
||||||
|
return ans
|
||||||
|
if this.in_paged_mode
|
||||||
|
c = this.current_column_location()
|
||||||
|
for x in [c, c-this.page_width, c+this.page_width]
|
||||||
|
# Try the current column, the previous column and the next
|
||||||
|
# column. Each column is tried from top to bottom.
|
||||||
|
[left, right] = [x, x + this.page_width]
|
||||||
|
if left < 0 or right > document.body.scrollWidth
|
||||||
|
continue
|
||||||
|
deltax = Math.floor(this.page_width/25)
|
||||||
|
deltay = Math.floor(window.innerHeight/25)
|
||||||
|
cury = this.margin_top
|
||||||
|
until cury >= (window.innerHeight - this.margin_bottom)
|
||||||
|
curx = left + this.current_margin_side
|
||||||
|
until curx >= (right - this.current_margin_side)
|
||||||
|
cfi = window.cfi.at_point(curx-window.pageXOffset, cury-window.pageYOffset)
|
||||||
|
if cfi
|
||||||
|
log('Viewport cfi:', cfi)
|
||||||
|
return cfi
|
||||||
|
curx += deltax
|
||||||
|
cury += deltay
|
||||||
|
else
|
||||||
|
try
|
||||||
|
ans = window.cfi.at_current()
|
||||||
|
if not ans
|
||||||
|
ans = null
|
||||||
|
catch err
|
||||||
|
log(err)
|
||||||
|
if ans
|
||||||
|
log('Viewport cfi:', ans)
|
||||||
|
return ans
|
||||||
|
|
||||||
if window?
|
if window?
|
||||||
window.paged_display = new PagedDisplay()
|
window.paged_display = new PagedDisplay()
|
||||||
|
|
||||||
# TODO:
|
# TODO:
|
||||||
# css pagebreak rules
|
# css pagebreak rules
|
||||||
# CFI and bookmarks
|
|
||||||
# Go to reference positions
|
# Go to reference positions
|
||||||
# Indexing
|
# Indexing
|
||||||
# Resizing of images
|
# Resizing of images
|
||||||
|
@ -19,13 +19,10 @@ class PagePosition(object):
|
|||||||
ans = None
|
ans = None
|
||||||
res = self.document.mainFrame().evaluateJavaScript('''
|
res = self.document.mainFrame().evaluateJavaScript('''
|
||||||
ans = 'undefined';
|
ans = 'undefined';
|
||||||
try {
|
if (window.paged_display) {
|
||||||
ans = window.cfi.at_current();
|
ans = window.paged_display.current_cfi();
|
||||||
if (!ans) ans = 'undefined';
|
if (!ans) ans = 'undefined';
|
||||||
} catch (err) {
|
|
||||||
window.console.log(err);
|
|
||||||
}
|
}
|
||||||
window.console.log("Viewport cfi: " + ans);
|
|
||||||
ans;
|
ans;
|
||||||
''')
|
''')
|
||||||
if res.isValid() and not res.isNull() and res.type() == res.String:
|
if res.isValid() and not res.isNull() and res.type() == res.String:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user