Sync to trunk.

This commit is contained in:
John Schember 2009-06-11 06:09:07 -04:00
commit f334cd786e
5 changed files with 387 additions and 91 deletions

View File

@ -61,8 +61,9 @@ def roman(num):
def fmt_sidx(i, fmt='%.2f', use_roman=False): def fmt_sidx(i, fmt='%.2f', use_roman=False):
if i is None: if i is None or i == '':
i = 1 i = 1
i = float(i)
if int(i) == float(i): if int(i) == float(i):
return roman(int(i)) if use_roman else '%d'%int(i) return roman(int(i)) if use_roman else '%d'%int(i)
try: try:

View File

@ -88,6 +88,7 @@ def encode(data):
DECINT_FORWARD = 0 DECINT_FORWARD = 0
DECINT_BACKWARD = 1 DECINT_BACKWARD = 1
def decint(value, direction): def decint(value, direction):
# Encode vwi
bytes = [] bytes = []
while True: while True:
b = value & 0x7f b = value & 0x7f
@ -324,6 +325,8 @@ class MobiWriter(object):
self._imagemax = imagemax or OTHER_MAX_IMAGE_SIZE self._imagemax = imagemax or OTHER_MAX_IMAGE_SIZE
self._prefer_author_sort = prefer_author_sort self._prefer_author_sort = prefer_author_sort
self._primary_index_record = None self._primary_index_record = None
self._HTMLRecords = []
self._tbSequence = ""
@classmethod @classmethod
def generate(cls, opts): def generate(cls, opts):
@ -358,7 +361,8 @@ class MobiWriter(object):
def _generate_content(self): def _generate_content(self):
self._map_image_names() self._map_image_names()
self._generate_text() self._generate_text()
if INDEXING and not self.opts.no_mobi_index: #if INDEXING and not self.opts.no_mobi_index:
if INDEXING :
try: try:
self._generate_index() self._generate_index()
except: except:
@ -403,6 +407,130 @@ class MobiWriter(object):
text.seek(npos) text.seek(npos)
return data, overlap return data, overlap
def _build_HTMLRecords_Data_List(self):
# Assemble a HTMLRecordData instance for each HTML record
numberOfHTMLRecords = ( self._content_length // RECORD_SIZE ) + 1
# Create a list of HTMLRecordData class instances
x = numberOfHTMLRecords
while x:
self._HTMLRecords.append(HTMLRecordData())
x -= 1
toc = self._oeb.toc
myIndex = 0
myEndingRecord = 0
entries = list(toc.iter())[1:]
# borrowed from _generate_indxt
for i, child in enumerate(entries):
if not child.title or not child.title.strip():
continue
h = child.href
if h not in self._id_offsets:
self._oeb.log.warning('Could not find TOC entry:', child.title)
continue
offset = self._id_offsets[h]
length = None
for sibling in entries[i+1:]:
h2 = sibling.href
if h2 in self._id_offsets:
offset2 = self._id_offsets[h2]
if offset2 > offset:
length = offset2 - offset
break
if length is None:
length = self._content_length - offset
# Calculate the HTML record for this entry
myStartingRecord = offset // RECORD_SIZE
# If no one has taken the openingNode slot, it must be us
if self._HTMLRecords[myStartingRecord].openingNode == -1 :
self._HTMLRecords[myStartingRecord].openingNode = myIndex
# Bump the node count for this HTML record
# Special case if we're the first so we get a true node count
if self._HTMLRecords[myStartingRecord].currentSectionNodeCount == -1:
self._HTMLRecords[myStartingRecord].currentSectionNodeCount = 1
else:
self._HTMLRecords[myStartingRecord].currentSectionNodeCount += 1
# Calculate the ending HTMLRecord of this entry
myEndingRecord = (offset + length) // RECORD_SIZE
# Tell the future HTML records about us
if myEndingRecord > myStartingRecord :
interimSpanRecord = myStartingRecord + 1
while interimSpanRecord <= myEndingRecord :
self._HTMLRecords[interimSpanRecord].continuingNode = myIndex
self._HTMLRecords[interimSpanRecord].currentSectionNodeCount = 1
interimSpanRecord += 1
ctoc_offset = self._ctoc_map[child]
last_name = "%04d" % myIndex
myIndex += 1
'''
# Dump the accumulated HTML Record Data
x = 0
while x < len(self._HTMLRecords):
self._HTMLRecords[x].dumpData(x, self._oeb)
x += 1
'''
def _build_TBS_Book(self, nrecords, lastrecord):
# Variables for trailing byte sequence
tbsType = 0x00
tbSequence = ""
#print "_build_TBS_Book: nrecords = %d, lastrecord = %d" % (nrecords, lastrecord)
# Generate TBS for type 0x002 - mobi_book
if nrecords == 0 :
# First HTML record is a special case
if self._HTMLRecords[nrecords].currentSectionNodeCount == 1 :
tbsType = 2
else :
tbsType = 6
tbSequence = decint(tbsType, DECINT_BACKWARD)
tbSequence += decint(0x00, DECINT_BACKWARD)
# Don't write a nodecount for opening type 2 record
if tbsType != 2 :
tbSequence += chr(self._HTMLRecords[nrecords].currentSectionNodeCount)
tbSequence += decint(len(tbSequence) + 1, DECINT_BACKWARD)
else :
# Determine tbsType for HTMLRecords > 0
if nrecords == lastrecord and self._HTMLRecords[nrecords].currentSectionNodeCount == 1 :
# Ending record with singleton node
tbsType = 2
elif self._HTMLRecords[nrecords].continuingNode > 0 and self._HTMLRecords[nrecords].openingNode == -1 :
# This is a span-only record
tbsType = 3
# Zero out the nodeCount with a pre-formed vwi
self._HTMLRecords[nrecords].currentSectionNodeCount = 0x80
else :
tbsType = 6
# Shift the openingNode index << 3
shiftedNCXEntry = self._HTMLRecords[nrecords].continuingNode << 3
# Add the TBS type
shiftedNCXEntry |= tbsType
# Assemble the TBS
tbSequence = decint(shiftedNCXEntry, DECINT_BACKWARD)
tbSequence += decint(0x00, DECINT_BACKWARD)
# Don't write a nodecount for terminating type 2 record
if tbsType != 2 :
tbSequence += chr(self._HTMLRecords[nrecords].currentSectionNodeCount)
tbSequence += decint(len(tbSequence) + 1, DECINT_BACKWARD)
# print "record %d: tbsType %d" % (nrecords, tbsType)
self._tbSequence = tbSequence
def _generate_text(self): def _generate_text(self):
self._oeb.logger.info('Serializing markup content...') self._oeb.logger.info('Serializing markup content...')
serializer = Serializer(self._oeb, self._images) serializer = Serializer(self._oeb, self._images)
@ -414,10 +542,25 @@ class MobiWriter(object):
text = StringIO(text) text = StringIO(text)
buf = [] buf = []
nrecords = 0 nrecords = 0
lastrecord = (self._content_length // RECORD_SIZE )
offset = 0 offset = 0
if self._compression != UNCOMPRESSED: if self._compression != UNCOMPRESSED:
self._oeb.logger.info('Compressing markup content...') self._oeb.logger.info('Compressing markup content...')
data, overlap = self._read_text_record(text) data, overlap = self._read_text_record(text)
# GR borrowed this from generate_index
# We seem to need it before calling self._build_HTMLRecords_Data_List()
ctoc = self._generate_ctoc()
# Build the HTMLRecords list so we can assemble the trailing bytes sequences in the following while loop
toc = self._oeb.toc
entries = list(toc.iter())[1:]
hasNCXEntries = True if len(entries) else False
if hasNCXEntries :
self._build_HTMLRecords_Data_List()
while len(data) > 0: while len(data) > 0:
if self._compression == PALMDOC: if self._compression == PALMDOC:
data = compress_doc(data) data = compress_doc(data)
@ -428,24 +571,59 @@ class MobiWriter(object):
nextra = 0 nextra = 0
pbreak = 0 pbreak = 0
running = offset running = offset
while breaks and (breaks[0] - offset) < RECORD_SIZE:
pbreak = (breaks.pop(0) - running) >> 3 # Write Trailing Byte Sequence
encoded = decint(pbreak, DECINT_FORWARD) if INDEXING and hasNCXEntries :
record.write(encoded) # Dispatch to different TBS generators based upon publication type
running += pbreak << 3 booktype = 0x101 if self.opts.mobi_periodical else 0x002
nextra += len(encoded) if booktype == 0x002 :
lsize = 1 self._build_TBS_Book(nrecords, lastrecord)
while True: #elif booktype == flatPeriodical :
size = decint(nextra + lsize, DECINT_BACKWARD) # tbSequence = self._build_TBS_FlatPeriodicalTBS()
if len(size) == lsize: #elif booktype == structuredPeriodical :
break # tbSequence = self._build_TBS_StructuredPeriodicalTBS()
lsize += 1 else :
record.write(size) raise NotImplementedError('Indexing for periodicals not implemented')
# Dump the current HTML Record Data / TBS
# GR diagnostics
if False :
self._HTMLRecords[nrecords].dumpData(nrecords, self._oeb)
outstr = ''
for eachbyte in self._tbSequence:
outstr += '0x%02X ' % ord(eachbyte)
self._oeb.logger.info(' Trailing Byte Sequence: %s\n' % outstr)
# Write the sequence
record.write(self._tbSequence)
else :
# Marshall's original code
while breaks and (breaks[0] - offset) < RECORD_SIZE:
# .pop returns item, removes it from list
pbreak = (breaks.pop(0) - running) >> 3
self._oeb.logger.info('pbreak = 0x%X' % pbreak )
encoded = decint(pbreak, DECINT_FORWARD)
record.write(encoded)
running += pbreak << 3
nextra += len(encoded)
lsize = 1
while True:
size = decint(nextra + lsize, DECINT_BACKWARD)
if len(size) == lsize:
break
lsize += 1
# Writing vwi length byte here
record.write(size)
self._records.append(record.getvalue()) self._records.append(record.getvalue())
buf.append(self._records[-1]) buf.append(self._records[-1])
nrecords += 1 nrecords += 1
offset += RECORD_SIZE offset += RECORD_SIZE
data, overlap = self._read_text_record(text) data, overlap = self._read_text_record(text)
if INDEXING: if INDEXING:
extra = sum(map(len, buf))%4 extra = sum(map(len, buf))%4
if extra == 0: if extra == 0:
@ -455,6 +633,7 @@ class MobiWriter(object):
self._text_nrecords = nrecords self._text_nrecords = nrecords
def _generate_indxt(self, ctoc): def _generate_indxt(self, ctoc):
if self.opts.mobi_periodical: if self.opts.mobi_periodical:
raise NotImplementedError('Indexing for periodicals not implemented') raise NotImplementedError('Indexing for periodicals not implemented')
toc = self._oeb.toc toc = self._oeb.toc
@ -471,7 +650,7 @@ class MobiWriter(object):
pos = 0xc0 + indxt.tell() pos = 0xc0 + indxt.tell()
indices.write(pack('>H', pos)) indices.write(pack('>H', pos))
name = "%4d"%count name = "%04d"%count
indxt.write(chr(len(name)) + name) indxt.write(chr(len(name)) + name)
indxt.write(INDXT['chapter']) indxt.write(INDXT['chapter'])
indxt.write(decint(offset, DECINT_FORWARD)) indxt.write(decint(offset, DECINT_FORWARD))
@ -502,7 +681,7 @@ class MobiWriter(object):
add_node(child, offset, length, c) add_node(child, offset, length, c)
ctoc_offset = self._ctoc_map[child] ctoc_offset = self._ctoc_map[child]
last_name = "%4d"%c last_name = "%04d"%c
c += 1 c += 1
return align_block(indxt.getvalue()), c, \ return align_block(indxt.getvalue()), c, \
@ -510,7 +689,7 @@ class MobiWriter(object):
def _generate_index(self): def _generate_index(self):
self._oeb.log('Generating index...') self._oeb.log('Generating primary index...')
self._primary_index_record = None self._primary_index_record = None
ctoc = self._generate_ctoc() ctoc = self._generate_ctoc()
indxt, indxt_count, indices, last_name = \ indxt, indxt_count, indices, last_name = \
@ -519,6 +698,8 @@ class MobiWriter(object):
self._oeb.log.warn('Input document has no TOC. No index generated.') self._oeb.log.warn('Input document has no TOC. No index generated.')
return return
# GR: indx0 => INDX0[0]
# indx1 => INDX1[0]
indx1 = StringIO() indx1 = StringIO()
indx1.write('INDX'+pack('>I', 0xc0)) # header length indx1.write('INDX'+pack('>I', 0xc0)) # header length
@ -575,7 +756,9 @@ class MobiWriter(object):
header.write(pack('>I', 1)) header.write(pack('>I', 1))
# 0x1c - 0x1f : Text encoding ? # 0x1c - 0x1f : Text encoding ?
header.write(pack('>I', 650001)) # header.write(pack('>I', 650001))
# GR: This needs to be either 0xFDE9 or 0x4E4
header.write(pack('>I', 0xFDE9))
# 0x20 - 0x23 : Language code? # 0x20 - 0x23 : Language code?
header.write(iana2mobi(str(self._oeb.metadata.language[0]))) header.write(iana2mobi(str(self._oeb.metadata.language[0])))
@ -615,56 +798,58 @@ class MobiWriter(object):
self._primary_index_record = len(self._records) self._primary_index_record = len(self._records)
self._records.extend([indx0, indx1, ctoc]) self._records.extend([indx0, indx1, ctoc])
# Write secondary index records # Turn this off for now
tagx = TAGX['secondary_'+\ if False:
('periodical' if self.opts.mobi_periodical else 'book')] # Write secondary index records
tagx_len = 8 + len(tagx) tagx = TAGX['secondary_'+\
('periodical' if self.opts.mobi_periodical else 'book')]
tagx_len = 8 + len(tagx)
indx0 = StringIO() indx0 = StringIO()
indx0.write('INDX'+pack('>I', 0xc0)+'\0'*8) indx0.write('INDX'+pack('>I', 0xc0)+'\0'*8)
indx0.write(pack('>I', 0x02)) indx0.write(pack('>I', 0x02))
indx0.write(pack('>I', 0xc0+tagx_len+4)) indx0.write(pack('>I', 0xc0+tagx_len+4))
indx0.write(pack('>I', 1)) indx0.write(pack('>I', 1))
indx0.write(pack('>I', 65001)) indx0.write(pack('>I', 65001))
indx0.write('\xff'*4) indx0.write('\xff'*4)
indx0.write(pack('>I', 1)) indx0.write(pack('>I', 1))
indx0.write('\0'*4) indx0.write('\0'*4)
indx0.write('\0'*136) indx0.write('\0'*136)
indx0.write(pack('>I', 0xc0)) indx0.write(pack('>I', 0xc0))
indx0.write('\0'*8) indx0.write('\0'*8)
indx0.write('TAGX'+pack('>I', tagx_len)+tagx) indx0.write('TAGX'+pack('>I', tagx_len)+tagx)
if self.opts.mobi_periodical: if self.opts.mobi_periodical:
raise NotImplementedError raise NotImplementedError
else: else:
indx0.write('\0'*3 + '\x01' + 'IDXT' + '\0\xd4\0\0') indx0.write('\0'*3 + '\x01' + 'IDXT' + '\0\xd4\0\0')
indx1 = StringIO() indx1 = StringIO()
indx1.write('INDX' + pack('>I', 0xc0) + '\0'*4) indx1.write('INDX' + pack('>I', 0xc0) + '\0'*4)
indx1.write(pack('>I', 1)) indx1.write(pack('>I', 1))
extra = 0xf0 if self.opts.mobi_periodical else 4 extra = 0xf0 if self.opts.mobi_periodical else 4
indx1.write('\0'*4 + pack('>I', 0xc0+extra)) indx1.write('\0'*4 + pack('>I', 0xc0+extra))
num = 4 if self.opts.mobi_periodical else 1 num = 4 if self.opts.mobi_periodical else 1
indx1.write(pack('>I', num)) indx1.write(pack('>I', num))
indx1.write('\xff'*8) indx1.write('\xff'*8)
indx1.write('\0'*(0xc0-indx1.tell())) indx1.write('\0'*(0xc0-indx1.tell()))
if self.opts.mobi_periodical: if self.opts.mobi_periodical:
raise NotImplementedError raise NotImplementedError
else: else:
indx1.write('\0\x01\x80\0') indx1.write('\0\x01\x80\0')
indx1.write('IDXT') indx1.write('IDXT')
if self.opts.mobi_periodical: if self.opts.mobi_periodical:
raise NotImplementedError raise NotImplementedError
else: else:
indx1.write('\0\xc0\0\0') indx1.write('\0\xc0\0\0')
indx0, indx1 = indx0.getvalue(), indx1.getvalue() indx0, indx1 = indx0.getvalue(), indx1.getvalue()
self._records.extend((indx0, indx1)) self._records.extend((indx0, indx1))
if self.opts.verbose > 3: if self.opts.verbose > 3:
from tempfile import mkdtemp from tempfile import mkdtemp
import os import os
t = mkdtemp() t = mkdtemp()
for i, n in enumerate(['sindx1', 'sindx0', 'ctoc', 'indx0', 'indx1']): for i, n in enumerate(['sindx1', 'sindx0', 'ctoc', 'indx0', 'indx1']):
open(os.path.join(t, n+'.bin'), 'wb').write(self._records[-(i+1)]) open(os.path.join(t, n+'.bin'), 'wb').write(self._records[-(i+1)])
self._oeb.log.debug('Index records dumped to', t) self._oeb.log.debug('Index records dumped to', t)
@ -714,16 +899,22 @@ class MobiWriter(object):
self._first_image_record = len(self._records)-1 self._first_image_record = len(self._records)-1
def _generate_end_records(self): def _generate_end_records(self):
self._flis_number = len(self._records) if True:
self._records.append( self._flis_number = len(self._records)
'FLIS\0\0\0\x08\0\x41\0\0\0\0\0\0\xff\xff\xff\xff\0\x01\0\x03\0\0\0\x03\0\0\0\x01'+ self._records.append('\xE9\x8E\x0D\x0A')
'\xff'*4)
fcis = 'FCIS\x00\x00\x00\x14\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00' else:
fcis += pack('>I', self._text_length) # This adds the binary blobs of FLIS and FCIS, which don't seem to be necessary
fcis += '\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x08\x00\x01\x00\x01\x00\x00\x00\x00' self._flis_number = len(self._records)
self._fcis_number = len(self._records) self._records.append(
self._records.append(fcis) 'FLIS\0\0\0\x08\0\x41\0\0\0\0\0\0\xff\xff\xff\xff\0\x01\0\x03\0\0\0\x03\0\0\0\x01'+
self._records.append('\xE9\x8E\x0D\x0A') '\xff'*4)
fcis = 'FCIS\x00\x00\x00\x14\x00\x00\x00\x10\x00\x00\x00\x01\x00\x00\x00\x00'
fcis += pack('>I', self._text_length)
fcis += '\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x08\x00\x01\x00\x01\x00\x00\x00\x00'
self._fcis_number = len(self._records)
self._records.append(fcis)
self._records.append('\xE9\x8E\x0D\x0A')
def _generate_record0(self): def _generate_record0(self):
metadata = self._oeb.metadata metadata = self._oeb.metadata
@ -760,9 +951,14 @@ class MobiWriter(object):
# 0x18 - 0x1f : Unknown # 0x18 - 0x1f : Unknown
record0.write('\xff' * 8) record0.write('\xff' * 8)
# 0x20 - 0x23 : Secondary index record # 0x20 - 0x23 : Secondary index record
record0.write(pack('>I', 0xffffffff if self._primary_index_record is # Turned off as it seems unnecessary
None else self._primary_index_record+3)) if True:
record0.write(pack('>I', 0xffffffff))
else:
record0.write(pack('>I', 0xffffffff if self._primary_index_record is
None else self._primary_index_record+3))
# 0x24 - 0x3f : Unknown # 0x24 - 0x3f : Unknown
record0.write('\xff' * 28) record0.write('\xff' * 28)
@ -819,16 +1015,33 @@ class MobiWriter(object):
record0.write('\0\0\0\x01') record0.write('\0\0\0\x01')
# 0xb8 - 0xbb : FCIS record number # 0xb8 - 0xbb : FCIS record number
record0.write(pack('>I', self._fcis_number)) # Turned off, these are optional and not understood yet
if True:
# 0xb8 - 0xbb : FCIS record number
record0.write(pack('>I', 0xffffffff))
# 0xbc - 0xbf : Unknown (FCIS record count?) # 0xbc - 0xbf : Unknown (FCIS record count?)
record0.write(pack('>I', 1)) record0.write(pack('>I', 0xffffffff))
# 0xc0 - 0xc3 : FLIS record number # 0xc0 - 0xc3 : FLIS record number
record0.write(pack('>I', self._flis_number)) record0.write(pack('>I', 0xffffffff))
# 0xc4 - 0xc7 : Unknown (FLIS record count?) # 0xc4 - 0xc7 : Unknown (FLIS record count?)
record0.write(pack('>I', 1)) record0.write(pack('>I', 1))
else:
# Write these if FCIS/FLIS turned on
# 0xb8 - 0xbb : FCIS record number
record0.write(pack('>I', self._fcis_number))
# 0xbc - 0xbf : Unknown (FCIS record count?)
record0.write(pack('>I', 1))
# 0xc0 - 0xc3 : FLIS record number
record0.write(pack('>I', self._flis_number))
# 0xc4 - 0xc7 : Unknown (FLIS record count?)
record0.write(pack('>I', 1))
# 0xc8 - 0xcf : Unknown # 0xc8 - 0xcf : Unknown
record0.write('\0'*8) record0.write('\0'*8)
@ -839,9 +1052,14 @@ class MobiWriter(object):
# 0xe0 - 0xe3 : Extra record data # 0xe0 - 0xe3 : Extra record data
# The '5' is a bitmask of extra record data at the end: # The '5' is a bitmask of extra record data at the end:
# - 0x1: <extra multibyte bytes><size> (?) # - 0x1: <extra multibyte bytes><size> (?)
# - 0x2: <indexing description of this HTML record><size> GR
# - 0x4: <uncrossable breaks><size> # - 0x4: <uncrossable breaks><size>
# Of course, the formats aren't quite the same. # Of course, the formats aren't quite the same.
record0.write(pack('>I', 5)) # GR: Use 2 for indexed files
if INDEXING :
record0.write(pack('>I', 2))
else:
record0.write(pack('>I', 5))
# 0xe4 - 0xe7 : Primary index record # 0xe4 - 0xe7 : Primary index record
record0.write(pack('>I', 0xffffffff if self._primary_index_record is record0.write(pack('>I', 0xffffffff if self._primary_index_record is
@ -891,11 +1109,14 @@ class MobiWriter(object):
if index is not None: if index is not None:
exth.write(pack('>III', 0xca, 0x0c, index - 1)) exth.write(pack('>III', 0xca, 0x0c, index - 1))
nrecs += 1 nrecs += 1
if INDEXING:
# Not sure what these are, but not needed for indexing
if False :
# Write unknown EXTH records as 0s # Write unknown EXTH records as 0s
for code, size in [(204,4), (205,4), (206,4), (207,4), (300,40)]: for code, size in [(204,4), (205,4), (206,4), (207,4), (300,40)]:
exth.write(pack('>II', code, 8+size)+'\0'*size) exth.write(pack('>II', code, 8+size)+'\0'*size)
nrecs += 1 nrecs += 1
exth = exth.getvalue() exth = exth.getvalue()
trail = len(exth) % 4 trail = len(exth) % 4
pad = '\0' * (4 - trail) # Always pad w/ at least 1 byte pad = '\0' * (4 - trail) # Always pad w/ at least 1 byte
@ -935,3 +1156,73 @@ class MobiWriter(object):
self._write(record) self._write(record)
class HTMLRecordData(object):
def __init__(self):
self._continuingNode = -1
self._continuingNodeParent = -1
self._openingNode = -1
self._openingNodeParent = -1
self._currentSectionNodeCount = -1
self._nextSectionNumber = -1
self._nextSectionOpeningNode = -1
self._nextSectionNodeCount = -1
def getContinuingNode(self):
return self._continuingNode
def setContinuingNode(self, value):
self._continuingNode = value
continuingNode = property(getContinuingNode, setContinuingNode, None, None)
def getContinuingNodeParent(self):
return self._continuingNodeParent
def setContinuingNodeParent(self, value):
self._continuingNodeParent = value
continuingNodeParent = property(getContinuingNodeParent, setContinuingNodeParent, None, None)
def getOpeningNode(self):
return self._openingNode
def setOpeningNode(self, value):
self._openingNode = value
openingNode = property(getOpeningNode, setOpeningNode, None, None)
def getOpeningNodeParent(self):
return self._openingNodeParent
def setOpeningNodeParent(self, value):
self._openingNodeParent = value
openingNodeParent = property(getOpeningNodeParent, setOpeningNodeParent, None, None)
def getCurrentSectionNodeCount(self):
return self._currentSectionNodeCount
def setCurrentSectionNodeCount(self, value):
self._currentSectionNodeCount = value
currentSectionNodeCount = property(getCurrentSectionNodeCount, setCurrentSectionNodeCount, None, None)
def getNextSectionNumber(self):
return self._nextSectionNumber
def setNextSectionNumber(self, value):
self._nextSectionNumber = value
nextSectionNumber = property(getNextSectionNumber, setNextSectionNumber, None, None)
def getNextSectionOpeningNode(self):
return self._nextSectionOpeningNode
def setNextSectionOpeningNode(self, value):
self._nextSectionOpeningNode = value
nextSectionOpeningNode = property(getNextSectionOpeningNode, setNextSectionOpeningNode, None, None)
def getNextSectionNodeCount(self):
return self._nextSectionNodeCount
def setNextSectionNodeCount(self, value):
self._nextSectionNodeCount = value
nextSectionNodeCount = property(getNextSectionNodeCount, setNextSectionNodeCount, None, None)
def dumpData(self, recordNumber, oeb):
oeb.logger.info( "--- Summary of HTML Record 0x%x [%d] indexing ---" % (recordNumber, recordNumber) )
oeb.logger.info( " continuingNode: %03d" % self.continuingNode )
oeb.logger.info( " continuingNodeParent: %03d" % self.continuingNodeParent )
oeb.logger.info( " openingNode: %03d" % self.openingNode )
oeb.logger.info( " openingNodeParent: %03d" % self.openingNodeParent )
oeb.logger.info( " currentSectionNodeCount: %03d" % self.currentSectionNodeCount )
oeb.logger.info( " nextSectionNumber: %03d" % self.nextSectionNumber )
oeb.logger.info( " nextSectionOpeningNode: %03d" % self.nextSectionOpeningNode )
oeb.logger.info( " nextSectionNodeCount: %03d" % self.nextSectionNodeCount )

View File

@ -279,7 +279,7 @@ class Stylizer(object):
class Style(object): class Style(object):
UNIT_RE = re.compile(r'^(-*[0-9]*[.]?[0-9]*)\s*(%|em|px|mm|cm|in|pt|pc)$') UNIT_RE = re.compile(r'^(-*[0-9]*[.]?[0-9]*)\s*(%|em|ex|en|px|mm|cm|in|pt|pc)$')
def __init__(self, element, stylizer): def __init__(self, element, stylizer):
self._element = element self._element = element
@ -362,6 +362,11 @@ class Style(object):
elif unit == 'em': elif unit == 'em':
font = font or self.fontSize font = font or self.fontSize
result = value * font result = value * font
elif unit in ('ex', 'en'):
# This is a hack for ex since we have no way to know
# the x-height of the font
font = font or self.fontSize
result = value * font * 0.5
elif unit == 'pc': elif unit == 'pc':
result = value * 12.0 result = value * 12.0
elif unit == 'mm': elif unit == 'mm':

View File

@ -23,7 +23,6 @@ entry_points = {
'calibre-server = calibre.library.server:main', 'calibre-server = calibre.library.server:main',
'lrf2lrs = calibre.ebooks.lrf.lrfparser:main', 'lrf2lrs = calibre.ebooks.lrf.lrfparser:main',
'lrs2lrf = calibre.ebooks.lrf.lrs.convert_from:main', 'lrs2lrf = calibre.ebooks.lrf.lrs.convert_from:main',
'isbndb = calibre.ebooks.metadata.isbndb:main',
'librarything = calibre.ebooks.metadata.library_thing:main', 'librarything = calibre.ebooks.metadata.library_thing:main',
'calibre-debug = calibre.debug:main', 'calibre-debug = calibre.debug:main',
'calibredb = calibre.library.cli:main', 'calibredb = calibre.library.cli:main',

View File

@ -11,12 +11,12 @@ from math import ceil
from threading import Thread, RLock from threading import Thread, RLock
from Queue import Queue, Empty from Queue import Queue, Empty
from multiprocessing.connection import Listener from multiprocessing.connection import Listener
from multiprocessing import cpu_count
from collections import deque from collections import deque
from binascii import hexlify from binascii import hexlify
from calibre.utils.ipc.launch import Worker from calibre.utils.ipc.launch import Worker
from calibre.utils.ipc.worker import PARALLEL_FUNCS from calibre.utils.ipc.worker import PARALLEL_FUNCS
from calibre import detect_ncpus as cpu_count
_counter = 0 _counter = 0