Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Background images enhancements, fix FB2 footnotes alignment #353

Merged
merged 8 commits into from
Jul 5, 2020
26 changes: 17 additions & 9 deletions crengine/include/hyphman.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ class HyphDictionary
public:
HyphDictionary( HyphDictType type, lString16 title, lString16 id, lString16 filename )
: _type(type), _title(title), _id( id ), _filename( filename ) { }
HyphDictType getType() { return _type; }
lString16 getTitle() { return _title; }
lString16 getId() { return _id; }
lString16 getFilename() { return _filename; }
HyphDictType getType() const { return _type; }
lString16 getTitle() const { return _title; }
lString16 getId() const { return _id; }
lString16 getFilename() const { return _filename; }
bool activate();
virtual lUInt32 getHash() { return getTitle().getHash(); }
virtual lUInt32 getHash() const { return getTitle().getHash(); }
virtual ~HyphDictionary() { }
};

Expand All @@ -98,7 +98,7 @@ class HyphDictionaryList
HyphDictionary * get( int index ) { return (index>=0 && index<+_list.length()) ? _list[index] : NULL; }
HyphDictionaryList() { addDefault(); }
bool open(lString16 hyphDirectory, bool clear = true);
HyphDictionary * find( lString16 id );
HyphDictionary * find( const lString16& id );
bool activate( lString16 id );
};

Expand All @@ -109,12 +109,18 @@ class HyphDictionaryList
// the document if the book does not contain any language tag, and
// we end up going with it anyway.

class HyphDictionary;
class HyphDictionaryList;
class TexHyph;
class AlgoHyph;
class SoftHyphensHyph;

class HyphDataLoader
{
public:
HyphDataLoader() {}
virtual ~HyphDataLoader() {}
virtual LVStreamRef loadData(lString16 id) = 0;
};

/// hyphenation manager
class HyphMan
{
Expand All @@ -127,15 +133,17 @@ class HyphMan
// static HyphDictionary * _selectedDictionary;
static HyphDictionaryList * _dictList; // available hyph dict files (+ none/algo/softhyphens)
static LVHashTable<lString16, HyphMethod*> _loaded_hyph_methods; // methods with loaded dictionaries
static HyphDataLoader* _dataLoader;
static int _LeftHyphenMin;
static int _RightHyphenMin;
static int _TrustSoftHyphens;
public:
static void uninit();
static bool initDictionaries(lString16 dir, bool clear = true);
static HyphDictionaryList * getDictList() { return _dictList; }
static bool addDictionaryItem(HyphDictionary* dict);
static void setDataLoader(HyphDataLoader* loader);
static bool activateDictionary( lString16 id ) { return _dictList->activate(id); }
static bool activateDictionaryFromStream( LVStreamRef stream ); // used by CoolReader on Android
static HyphDictionary * getSelectedDictionary(); // was: { return _selectedDictionary; }
static int getLeftHyphenMin() { return _LeftHyphenMin; }
static int getRightHyphenMin() { return _RightHyphenMin; }
Expand Down
1 change: 0 additions & 1 deletion crengine/include/lvstyles.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,6 @@ enum lvdom_element_render_method
erm_block, ///< render as block element (render as containing other elements)
erm_final, ///< final element: render the whole it's content as single render block
erm_inline, ///< inline element
erm_runin, ///< run-in (used as a solution to inline FB2 footnotes)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a Norse mythological bird named something like Runin — I can't quite think of the name right now. I didn't immediately realize it said run-in. :-)

Copy link
Member

@NiLuJe NiLuJe Jul 5, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Muninn, (one of) Odin's raven (Memory, IIRC).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

erm_table, ///< table element: render as table
erm_table_row_group, ///< table row group
erm_table_header_group, ///< table header group
Expand Down
105 changes: 50 additions & 55 deletions crengine/src/hyphman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ int HyphMan::_LeftHyphenMin = HYPH_DEFAULT_HYPHEN_MIN;
int HyphMan::_RightHyphenMin = HYPH_DEFAULT_HYPHEN_MIN;
int HyphMan::_TrustSoftHyphens = HYPH_DEFAULT_TRUST_SOFT_HYPHENS;
LVHashTable<lString16, HyphMethod*> HyphMan::_loaded_hyph_methods(16);
HyphDataLoader* HyphMan::_dataLoader = NULL;


// Obsolete: now fetched from TextLangMan main lang TextLangCfg
// HyphDictionary * HyphMan::_selectedDictionary = NULL;
Expand Down Expand Up @@ -140,6 +142,28 @@ typedef struct {
} hyph_index_item_t;
#pragma pack(pop)

class HyphDataLoaderFromFile: public HyphDataLoader
{
public:
HyphDataLoaderFromFile() : HyphDataLoader() {}
virtual ~HyphDataLoaderFromFile() {}
virtual LVStreamRef loadData(lString16 id) {
HyphDictionaryList* dictList = HyphMan::getDictList();
HyphDictionary * p = dictList->find(id);
if ( !p )
return LVStreamRef();
if ( p->getType() == HDT_NONE ||
p->getType() == HDT_ALGORITHM ||
p->getType() == HDT_SOFTHYPHENS ||
( p->getType() != HDT_DICT_ALAN && p->getType() != HDT_DICT_TEX) )
return LVStreamRef();
lString16 filename = p->getFilename();
return LVOpenFileStream( filename.c_str(), LVOM_READ );
}
};



void HyphMan::uninit()
{
// Avoid existing frontend code to have to call it:
Expand All @@ -154,6 +178,9 @@ void HyphMan::uninit()
if ( _dictList )
delete _dictList;
_dictList = NULL;
if ( _dataLoader )
delete _dataLoader;
_dataLoader = NULL;
/* Obsolete:
_selectedDictionary = NULL;
if ( HyphMan::_method != &ALGO_HYPH && HyphMan::_method != &NO_HYPH && HyphMan::_method != &SOFTHYPHENS_HYPH )
Expand All @@ -162,60 +189,14 @@ void HyphMan::uninit()
*/
}

bool HyphMan::activateDictionaryFromStream( LVStreamRef stream )
{
if ( stream.isNull() )
return false;
/* Obsolete:
CRLog::trace("remove old hyphenation method");
if ( HyphMan::_method != &NO_HYPH && HyphMan::_method != &ALGO_HYPH && HyphMan::_method != &SOFTHYPHENS_HYPH && HyphMan::_method ) {
delete HyphMan::_method;
HyphMan::_method = &NO_HYPH;
}
*/
CRLog::trace("creating new TexHyph method");
TexHyph * method = new TexHyph(HYPH_DICT_ID_DICTIONARY);
CRLog::trace("loading from file");
if ( !method->load( stream ) ) {
CRLog::error("HyphMan::activateDictionaryFromStream: Cannot open hyphenation dictionary from stream" );
delete method;
return false;
}
if (method->largest_overflowed_word)
printf("CRE WARNING: hyph dict from stream: some hyphenation patterns were too long and have been ignored: increase MAX_PATTERN_SIZE from %d to %d\n", MAX_PATTERN_SIZE, method->largest_overflowed_word);
CRLog::debug("Dictionary is loaded successfully. Activating.");

// Replace any previously dict loaded from stream
HyphMethod * prev_method;
if ( _loaded_hyph_methods.get(HYPH_DICT_ID_DICTIONARY, prev_method) ) {
delete prev_method;
_loaded_hyph_methods.remove(HYPH_DICT_ID_DICTIONARY);
}
_loaded_hyph_methods.set(HYPH_DICT_ID_DICTIONARY, method);

if (!_dictList)
_dictList = new HyphDictionaryList();
/* Obsolete:
HyphMan::_method = method;
*/
if ( HyphMan::_dictList->find(lString16(HYPH_DICT_ID_DICTIONARY))==NULL ) {
HyphDictionary * dict = new HyphDictionary( HDT_DICT_ALAN, cs16("Dictionary"), lString16(HYPH_DICT_ID_DICTIONARY), lString16::empty_str );
HyphMan::_dictList->add(dict);
/* Obsolete:
HyphMan::_selectedDictionary = dict;
*/
}
TextLangMan::setMainLangFromHyphDict( HYPH_DICT_ID_DICTIONARY );
CRLog::trace("Activation is done");
return true;
}

bool HyphMan::initDictionaries(lString16 dir, bool clear)
{
if (clear && _dictList)
delete _dictList;
if (clear || !_dictList)
_dictList = new HyphDictionaryList();
if (NULL == _dataLoader)
_dataLoader = new HyphDataLoaderFromFile;
if (_dictList->open(dir, clear)) {
if ( !_dictList->activate( lString16(DEF_HYPHENATION_DICT) ) )
_dictList->activate( lString16(HYPH_DICT_ID_ALGORITHM) );
Expand All @@ -226,6 +207,21 @@ bool HyphMan::initDictionaries(lString16 dir, bool clear)
}
}

// for android
bool HyphMan::addDictionaryItem(HyphDictionary* dict)
{
if (_dictList->find(dict->getId()))
return false;
_dictList->add(dict);
return true;
}

void HyphMan::setDataLoader(HyphDataLoader* loader) {
if (_dataLoader)
delete _dataLoader;
_dataLoader = loader;
}

bool HyphMan::setLeftHyphenMin( int left_hyphen_min ) {
if (left_hyphen_min >= HYPH_MIN_HYPHEN_MIN && left_hyphen_min <= HYPH_MAX_HYPHEN_MIN) {
HyphMan::_LeftHyphenMin = left_hyphen_min;
Expand Down Expand Up @@ -269,7 +265,7 @@ HyphDictionary * HyphMan::getSelectedDictionary() {
}

HyphMethod * HyphMan::getHyphMethodForDictionary( lString16 id, int leftHyphenMin, int rightHyphenMin ) {
if ( id.empty() )
if ( id.empty() || NULL == _dataLoader)
return &NO_HYPH;
HyphDictionary * p = _dictList->find(id);
if ( !p || p->getType() == HDT_NONE )
Expand All @@ -285,21 +281,20 @@ HyphMethod * HyphMan::getHyphMethodForDictionary( lString16 id, int leftHyphenMi
// printf("getHyphMethodForDictionary reusing cached %s\n", UnicodeToUtf8(p->getFilename()).c_str());
return method;
}
lString16 filename = p->getFilename();
LVStreamRef stream = LVOpenFileStream( filename.c_str(), LVOM_READ );
LVStreamRef stream = _dataLoader->loadData(id);
if ( stream.isNull() ) {
CRLog::error("Cannot open hyphenation dictionary %s", UnicodeToUtf8(filename).c_str() );
CRLog::error("Cannot open hyphenation dictionary %s", UnicodeToUtf8(id).c_str() );
return &NO_HYPH;
}
TexHyph * newmethod = new TexHyph(id, leftHyphenMin, rightHyphenMin);
if ( !newmethod->load( stream ) ) {
CRLog::error("Cannot open hyphenation dictionary %s", UnicodeToUtf8(filename).c_str() );
CRLog::error("Cannot open hyphenation dictionary %s", UnicodeToUtf8(id).c_str() );
delete newmethod;
return &NO_HYPH;
}
// printf("CRE: loaded hyphenation dict %s\n", UnicodeToUtf8(id).c_str());
if ( newmethod->largest_overflowed_word )
printf("CRE WARNING: %s: some hyphenation patterns were too long and have been ignored: increase MAX_PATTERN_SIZE from %d to %d\n", UnicodeToUtf8(filename).c_str(), MAX_PATTERN_SIZE, newmethod->largest_overflowed_word);
printf("CRE WARNING: %s: some hyphenation patterns were too long and have been ignored: increase MAX_PATTERN_SIZE from %d to %d\n", UnicodeToUtf8(id).c_str(), MAX_PATTERN_SIZE, newmethod->largest_overflowed_word);
_loaded_hyph_methods.set(id, newmethod);
return newmethod;
}
Expand Down Expand Up @@ -382,7 +377,7 @@ void HyphDictionaryList::addDefault()

}

HyphDictionary * HyphDictionaryList::find( lString16 id )
HyphDictionary * HyphDictionaryList::find( const lString16& id )
{
for ( int i=0; i<_list.length(); i++ ) {
if ( _list[i]->getId() == id )
Expand Down
4 changes: 0 additions & 4 deletions crengine/src/lvdocview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6100,7 +6100,6 @@ void LVDocView::propsUpdateDefaults(CRPropRef props) {
props->setIntDef(PROP_STATUS_FONT_SIZE, fs);
lString16 hyph = props->getStringDef(PROP_HYPHENATION_DICT,
DEF_HYPHENATION_DICT);
#if !defined(ANDROID)
HyphDictionaryList * dictlist = HyphMan::getDictList();
if (dictlist) {
if (dictlist->find(hyph))
Expand All @@ -6109,7 +6108,6 @@ void LVDocView::propsUpdateDefaults(CRPropRef props) {
props->setStringDef(PROP_HYPHENATION_DICT, lString16(
HYPH_DICT_ID_ALGORITHM));
}
#endif
props->setIntDef(PROP_STATUS_LINE, 0);
props->setIntDef(PROP_SHOW_TITLE, 1);
props->setIntDef(PROP_SHOW_TIME, 1);
Expand Down Expand Up @@ -6373,7 +6371,6 @@ CRPropRef LVDocView::propsApply(CRPropRef props) {
fontSize = MAX_STATUS_FONT_SIZE;
setStatusFontSize(fontSize);//cr_font_sizes
value = lString16::itoa(fontSize);
#if !defined(ANDROID)
} else if (name == PROP_HYPHENATION_DICT) {
// hyphenation dictionary
lString16 id = props->getStringDef(PROP_HYPHENATION_DICT,
Expand Down Expand Up @@ -6408,7 +6405,6 @@ CRPropRef LVDocView::propsApply(CRPropRef props) {
HyphMan::setTrustSoftHyphens(trustSoftHyphens);
REQUEST_RENDER("propsApply hyphenation trust_soft_hyphens")
}
#endif
} else if (name == PROP_TEXTLANG_MAIN_LANG) {
lString16 lang = props->getStringDef(PROP_TEXTLANG_MAIN_LANG, TEXTLANG_DEFAULT_MAIN_LANG);
if ( lang != TextLangMan::getMainLang() ) {
Expand Down
1 change: 0 additions & 1 deletion crengine/src/lvrend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,6 @@ class CCRTable {
}
break;
case erm_inline:
case erm_runin:
// do nothing
break;
}
Expand Down
18 changes: 8 additions & 10 deletions crengine/src/lvtinydom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3975,7 +3975,7 @@ static void writeNodeEx( LVStream * stream, ldomNode * node, lString16Collection
rm = erm_final;
}
}
if ( (rm != erm_inline && rm != erm_runin) || node->isBoxingInlineBox()) {
if ( rm != erm_inline || node->isBoxingInlineBox()) {
doNewLineBeforeStartTag = true;
doNewLineAfterStartTag = true;
// doNewLineBeforeEndTag = false; // done by child elements
Expand Down Expand Up @@ -4113,7 +4113,6 @@ static void writeNodeEx( LVStream * stream, ldomNode * node, lString16Collection
case erm_block: *stream << "B"; break;
case erm_final: *stream << "F"; break;
case erm_inline: *stream << "i"; break;
case erm_runin: *stream << "r"; break;
case erm_table: *stream << "T"; break;
case erm_table_row_group: *stream << "TRG"; break;
case erm_table_header_group: *stream << "THG"; break;
Expand Down Expand Up @@ -4969,7 +4968,7 @@ static bool isInlineNode( ldomNode * node )
//int d = node->getStyle()->display;
//return ( d==css_d_inline || d==css_d_run_in );
int m = node->getRendMethod();
return m==erm_inline || m==erm_runin;
return m == erm_inline;
}

static bool isFloatingNode( ldomNode * node )
Expand Down Expand Up @@ -5429,7 +5428,7 @@ static void detectChildTypes( ldomNode * parent, bool & hasBlockItems, bool & ha
int m = node->getRendMethod();
if ( d==css_d_none || m==erm_invisible )
continue;
if ( m==erm_inline || m==erm_runin) { //d==css_d_inline || d==css_d_run_in
if ( m==erm_inline ) { //d==css_d_inline || d==css_d_run_in
hasInline = true;
} else {
hasBlockItems = true;
Expand Down Expand Up @@ -5801,7 +5800,7 @@ bool ldomNode::isEmbeddedBlockBoxingInlineBox(bool inline_box_checks_done) const
if ( hasAttribute( attr_T ) ) { // T="EmbeddedBlock"
// (no other possible value yet, no need to compare strings)
int cm = getChildNode(0)->getRendMethod();
if ( cm == erm_inline || cm == erm_runin || cm == erm_invisible || cm == erm_killed )
if ( cm == erm_inline || cm == erm_invisible || cm == erm_killed )
return false; // child has been reset to inline
return true;
}
Expand Down Expand Up @@ -5901,7 +5900,7 @@ void ldomNode::initNodeRendMethod()
if ( !child->isElement() ) // text node
continue;
int cm = child->getRendMethod();
if ( cm == erm_inline || cm == erm_runin ) {
if ( cm == erm_inline ) {
has_inline_nodes = true; // We won't be able to make it erm_block
continue;
}
Expand Down Expand Up @@ -5945,7 +5944,7 @@ void ldomNode::initNodeRendMethod()
if ( !child->isElement() ) // text node
continue;
int cm = child->getRendMethod();
if ( cm == erm_inline || cm == erm_runin || cm == erm_invisible || cm == erm_killed )
if ( cm == erm_inline || cm == erm_invisible || cm == erm_killed )
continue;
if ( !isNotBoxWrappingNode( child ) )
continue;
Expand Down Expand Up @@ -6007,7 +6006,7 @@ void ldomNode::initNodeRendMethod()
// runin
//CRLog::trace("switch all children elements of <%s> to inline", LCSTR(getNodeName()));
recurseElements( resetRendMethodToInline );
setRendMethod(erm_runin);
setRendMethod(erm_inline);
} else if ( d==css_d_list_item_legacy ) {
// list item (no more used, obsolete rendering method)
setRendMethod(erm_final);
Expand Down Expand Up @@ -6214,7 +6213,7 @@ void ldomNode::initNodeRendMethod()
inBetweenTextNode = prev;
prev = getChildNode(i-2);
}
if ( prev->isElement() && prev->getRendMethod()==erm_runin ) {
if ( prev->isElement() && prev->getStyle()->display == css_d_run_in ) {
bool do_autoboxing = true;
int run_in_idx = inBetweenTextNode ? i-2 : i-1;
int block_idx = i;
Expand Down Expand Up @@ -11516,7 +11515,6 @@ ldomNode * ldomXPointerEx::getThisBlockNode()
return NULL;
lvdom_element_render_method rm = node->getRendMethod();
switch ( rm ) {
case erm_runin: // treat as separate block
case erm_block:
case erm_final:
case erm_table:
Expand Down