diff --git a/src/calibre/ebooks/oeb/display/cfi.coffee b/src/calibre/ebooks/oeb/display/cfi.coffee index c455810c1f..02862263c1 100644 --- a/src/calibre/ebooks/oeb/display/cfi.coffee +++ b/src/calibre/ebooks/oeb/display/cfi.coffee @@ -4,6 +4,7 @@ ### Copyright 2011, Kovid Goyal Released under the GPLv3 License + Based on code originally written by Peter Sorotkin (epubcfi.js) ### # log = (error) -> @@ -271,6 +272,67 @@ class CanonicalFragmentIdentifier this.encode(doc, target, offset, tail) # }}} + point: (cfi, doc=window?.document) -> # {{{ + r = this.decode(cfi, doc) + if not r + return null + node = r.node + ndoc = node.ownerDocument + if not ndoc + log("CFI node has no owner document: #{ cfi } #{ node }") + return null + + nwin = ndoc.defaultView + x = null + y = null + + if typeof(r.offset) == "number" + # Character offset + range = ndoc.createRange() + if r.forward + try_list = [{start:0, end:0, a:0.5}, {start:0, end:1, a:1}, {start:-1, end:0, a:0}] + else + try_list = [{start:0, end:0, a:0.5}, {start:-1, end:0, a:0}, {start:0, end:1, a:1}] + k = 0 + a = null + rects = null + node_len = node.nodeValue.length + until rects or rects.length or k >= try_list.length + t = try_list[k++] + start_offset = r.offset + t.start + end_offset = r.offset + t.end + a = t.a + if start_offset < 0 or end_offset >= node_len + continue + range.setStart(node, start_offset) + range.setEnd(node, end_offset) + rects = range.getClientRects() + + if not rects or not rects.length + log("Could not find caret position: rects: #{ rects } offset: #{ r.offset }") + return null + + rect = rects[0] + x = (a*rect.left + (1-a)*rect.right) + y = (rect.top + rect.bottom)/2 + else + x = node.offsetLeft - nwin.scrollX + y = node.offsetTop - nwin.scrollY + if typeof(r.x) == "number" and node.offsetWidth + x += (r.x*node.offsetWidth)/100 + y += (r.y*node.offsetHeight)/100 + + until ndoc == doc + node = nwin.frameElement + ndoc = node.ownerDocument + nwin = ndoc.defaultView + x += node.offsetLeft - nwin.scrollX + y += node.offsetTop - nwin.scrollY + + {x:x, y:y, node:r.node, time:r.time} + + # }}} + if window? window.cfi = new CanonicalFragmentIdentifier() else if process?