mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Code to merge W arrays
This commit is contained in:
parent
d994cf7895
commit
d304e08ec1
@ -112,6 +112,8 @@ def find_tests(which_tests=None):
|
|||||||
a(find_tests())
|
a(find_tests())
|
||||||
from calibre.ebooks.metadata.html import find_tests
|
from calibre.ebooks.metadata.html import find_tests
|
||||||
a(find_tests())
|
a(find_tests())
|
||||||
|
from calibre.ebooks.pdf.test_html_writer import find_tests
|
||||||
|
a(find_tests())
|
||||||
if ok('misc'):
|
if ok('misc'):
|
||||||
from calibre.ebooks.metadata.tag_mapper import find_tests
|
from calibre.ebooks.metadata.tag_mapper import find_tests
|
||||||
a(find_tests())
|
a(find_tests())
|
||||||
|
@ -520,13 +520,54 @@ def add_pagenum_toc(root, toc, opts, page_number_display_map):
|
|||||||
|
|
||||||
class Range(object):
|
class Range(object):
|
||||||
|
|
||||||
__slots__ = ('first', 'last', 'width')
|
__slots__ = ('first', 'last', 'widths', 'sort_order')
|
||||||
|
|
||||||
def __init__(self, first, last, width):
|
def __init__(self, first, last, widths):
|
||||||
self.first, self.last, self.width = first, last, width
|
self.first, self.last, self.widths = first, last, widths
|
||||||
# Sort by first with larger ranges coming before smaller ones
|
# Sort by first with larger ranges coming before smaller ones
|
||||||
self.sort_order = self.first, -self.last
|
self.sort_order = self.first, -self.last
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '({}, {}, {})'.format(self.first, self.last, self.widths)
|
||||||
|
|
||||||
|
def merge(self, r):
|
||||||
|
if r.last <= self.last:
|
||||||
|
return # is a subset
|
||||||
|
if r.first > self.last:
|
||||||
|
if r.first == self.last + 1 and self.has_single_width == r.has_single_width:
|
||||||
|
if self.has_single_width:
|
||||||
|
if r.widths[0] == self.widths[0]:
|
||||||
|
self.last = r.last
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.last = r.last
|
||||||
|
delta = self.last - self.first + 1 - len(self.widths)
|
||||||
|
self.widths.extend(r.widths[-delta:])
|
||||||
|
return
|
||||||
|
return r
|
||||||
|
if self.has_single_width != r.has_single_width:
|
||||||
|
# make r disjoint
|
||||||
|
delta = self.last + 1 - r.first
|
||||||
|
r.first = self.last + 1
|
||||||
|
if len(r.widths) > 1:
|
||||||
|
del r.widths[:delta]
|
||||||
|
return r if r.widths else None
|
||||||
|
# subsume r into self
|
||||||
|
self.last = r.last
|
||||||
|
if not self.has_single_width:
|
||||||
|
delta = self.last - self.first + 1 - len(self.widths)
|
||||||
|
self.widths.extend(r.widths[-delta:])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def as_item(self):
|
||||||
|
if self.has_single_width:
|
||||||
|
return self.first, self.last, self.widths[0]
|
||||||
|
return self.first, self.widths
|
||||||
|
|
||||||
|
@property
|
||||||
|
def has_single_width(self):
|
||||||
|
return len(self.widths) == 1
|
||||||
|
|
||||||
|
|
||||||
def merge_w_arrays(arrays):
|
def merge_w_arrays(arrays):
|
||||||
ranges = []
|
ranges = []
|
||||||
@ -536,10 +577,10 @@ def merge_w_arrays(arrays):
|
|||||||
elem = w[i]
|
elem = w[i]
|
||||||
next_elem = w[i+1]
|
next_elem = w[i+1]
|
||||||
if isinstance(next_elem, list):
|
if isinstance(next_elem, list):
|
||||||
ranges.extend(Range(elem + c, elem + c, w) for c, w in enumerate(next_elem))
|
ranges.append(Range(elem, elem + len(next_elem) - 1, next_elem))
|
||||||
i += 2
|
i += 2
|
||||||
elif i + 2 < len(w):
|
elif i + 2 < len(w):
|
||||||
ranges.append(Range(elem, next_elem, w[i+2]))
|
ranges.append(Range(elem, next_elem, [w[i+2]]))
|
||||||
i += 3
|
i += 3
|
||||||
else:
|
else:
|
||||||
break
|
break
|
||||||
@ -552,7 +593,10 @@ def merge_w_arrays(arrays):
|
|||||||
merged_ranges.append(left_over)
|
merged_ranges.append(left_over)
|
||||||
if not merged_ranges:
|
if not merged_ranges:
|
||||||
return []
|
return []
|
||||||
# combine consecutive single value ranges
|
ans = []
|
||||||
|
for r in merged_ranges:
|
||||||
|
ans.extend(r.as_item)
|
||||||
|
return ans
|
||||||
|
|
||||||
|
|
||||||
def merge_font(fonts):
|
def merge_font(fonts):
|
||||||
|
41
src/calibre/ebooks/pdf/test_html_writer.py
Normal file
41
src/calibre/ebooks/pdf/test_html_writer.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPL v3 Copyright: 2019, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function, unicode_literals
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from .html_writer import merge_w_arrays
|
||||||
|
|
||||||
|
|
||||||
|
class TestPDFWriter(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_merge_w_arrays(self):
|
||||||
|
self.assertEqual(merge_w_arrays(( # merge neighbor arrays
|
||||||
|
[1, 3, 0.1], [3, [0.1, 0.2]])), [1, 3, 0.1, 4, 4, 0.2])
|
||||||
|
self.assertEqual(merge_w_arrays(( # merge neighbor ranges
|
||||||
|
[1, 5, 0.1], [6, 8, 0.1])), [1, 8, 0.1])
|
||||||
|
self.assertEqual(merge_w_arrays(( # merge neighbor ranges
|
||||||
|
[1, 5, 0.1], [6, 8, 0.2])), [1, 5, 0.1, 6, 8, 0.2])
|
||||||
|
|
||||||
|
self.assertEqual(merge_w_arrays(( # disjoin overlap
|
||||||
|
[1, 4, 0.1], [3, [0.1, 0.1, 0.2, 0.3]])), [1, 4, 0.1, 5, [0.2, 0.3]])
|
||||||
|
self.assertEqual(merge_w_arrays(( # disjoin overlap
|
||||||
|
[1, [0.1, 0.2]], [2, 4, 0.2])), [1, [0.1, 0.2], 3, 4, 0.2])
|
||||||
|
|
||||||
|
self.assertEqual(merge_w_arrays(( # split overlapping arrays
|
||||||
|
[1, [0.1, 0.2, 0.3]], [3, 5, 0.3])), [1, [0.1, 0.2, 0.3], 4, 5, 0.3])
|
||||||
|
self.assertEqual(merge_w_arrays(( # merge overlapping ranges, using first width
|
||||||
|
[1, 5, 0.1], [2, 4, 0.2])), [1, 5, 0.1])
|
||||||
|
self.assertEqual(merge_w_arrays(( # merge overlapping arrays
|
||||||
|
[1, [0.1, 0.1]], [3, [0.2, 0.2]])), [1, [0.1, 0.1, 0.2, 0.2]])
|
||||||
|
|
||||||
|
self.assertEqual(merge_w_arrays((
|
||||||
|
[1, 10, 99, 20, [1, 2, 3, 4]],
|
||||||
|
[3, 10, 99, 11, 13, 77, 19, [77, 1]])),
|
||||||
|
[1, 10, 99, 11, 13, 77, 19, [77, 1, 2, 3, 4]]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def find_tests():
|
||||||
|
return unittest.defaultTestLoader.loadTestsFromTestCase(TestPDFWriter)
|
Loading…
x
Reference in New Issue
Block a user