From bcb8fa49128c6a76354ac6fd5e0322394c5ba0f1 Mon Sep 17 00:00:00 2001 From: poire-z Date: Mon, 29 Jun 2020 21:31:25 +0200 Subject: [PATCH] globalHash: exclude some settings on initial loading If not yet rendered (initial loading with XML parsing), we can ignore some global flags that have not yet produced any effect, so they can possibly be updated between loading and rendering without trigerring a drop of all the styles and rend methods set up in the XML loading phase. This is mostly only needed for TextLangMan::getHash(), as the lang can be set by frontend code after the loading phase, once the book language is known from its metadata, before the rendering that will use the language set. With KOReader, this should speed up a book first load where its language is not yet known, and is different from the default or fallback typography language. --- crengine/include/lvtinydom.h | 8 +++---- crengine/src/lvtinydom.cpp | 45 +++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/crengine/include/lvtinydom.h b/crengine/include/lvtinydom.h index 9784ffc0e..1f9b905b9 100644 --- a/crengine/include/lvtinydom.h +++ b/crengine/include/lvtinydom.h @@ -107,7 +107,7 @@ extern int gDOMVersionRequested; #define DEF_UNUSED_SPACE_THRESHOLD_PERCENT 5 #define DEF_MAX_ADDED_LETTER_SPACING_PERCENT 0 -#define NODE_DISPLAY_STYLE_HASH_UNITIALIZED 0xFFFFFFFF +#define NODE_DISPLAY_STYLE_HASH_UNINITIALIZED 0xFFFFFFFF // To be used for 'direction' in ldomNode->elementFromPoint(lvPoint pt, int direction) // and ldomDocument->createXPointer(lvPoint pt, int direction...) as a way to @@ -518,7 +518,7 @@ class tinyNodeCollection bool saveStylesData(); bool loadStylesData(); bool updateLoadedStyles( bool enabled ); - lUInt32 calcStyleHash(); + lUInt32 calcStyleHash(bool already_rendered); bool saveNodeData(); bool saveNodeData( lUInt16 type, ldomNode ** list, int nodecount ); bool loadNodeData(); @@ -645,7 +645,7 @@ class tinyNodeCollection /// is built (and cached) DOM possibly invalid (can happen when some nodes have changed display style) bool isBuiltDomStale() { - return _nodeDisplayStyleHashInitial != NODE_DISPLAY_STYLE_HASH_UNITIALIZED && + return _nodeDisplayStyleHashInitial != NODE_DISPLAY_STYLE_HASH_UNINITIALIZED && _nodeDisplayStyleHash != _nodeDisplayStyleHashInitial; } void setNodeStylesInvalidIfLoading() { @@ -1328,7 +1328,7 @@ class lxmlDocBase : public tinyNodeCollection bool deserialize( SerialBuf & buf ); DocFileHeader() : render_dx(0), render_dy(0), render_docflags(0), render_style_hash(0), stylesheet_hash(0), - node_displaystyle_hash(NODE_DISPLAY_STYLE_HASH_UNITIALIZED) + node_displaystyle_hash(NODE_DISPLAY_STYLE_HASH_UNINITIALIZED) { } }; diff --git a/crengine/src/lvtinydom.cpp b/crengine/src/lvtinydom.cpp index ecd4d7b3a..aa77ed603 100644 --- a/crengine/src/lvtinydom.cpp +++ b/crengine/src/lvtinydom.cpp @@ -375,7 +375,7 @@ static lUInt32 calcHash(const lUInt8 * s, int len) { return XXH32(s,len,0); } -lUInt32 calcGlobalSettingsHash(int documentId) +lUInt32 calcGlobalSettingsHash(int documentId, bool already_rendered) { lUInt32 hash = FORMATTING_VERSION_ID; // if ( fontMan->getKerning() ) @@ -383,7 +383,7 @@ lUInt32 calcGlobalSettingsHash(int documentId) hash = hash * 31 + (int)fontMan->GetKerningMode(); hash = hash * 31 + fontMan->GetFontListHash(documentId); // Hinting mode change does not need to trigger a re-render, as since - // we use FT_LOAD_TARGET_LIGHT, hinting has not effect on the x-axis + // we use FT_LOAD_TARGET_LIGHT, hinting has no effect on the x-axis // and should not change glyph advances, so it should not change line // layout and paragraphs' heights. We just need to _renderedBlockCache.clear() // when hinting mode is changed to reformat paragraphs. @@ -392,14 +392,27 @@ lUInt32 calcGlobalSettingsHash(int documentId) hash = hash * 75 + 2384761; if ( gFlgFloatingPunctuationEnabled ) hash = hash * 75 + 1761; - hash = hash * 31 + TextLangMan::getHash(); - hash = hash * 31 + HyphMan::getLeftHyphenMin(); - hash = hash * 31 + HyphMan::getRightHyphenMin(); - hash = hash * 31 + HyphMan::getTrustSoftHyphens(); hash = hash * 31 + gRenderDPI; hash = hash * 31 + gRenderBlockRenderingFlags; hash = hash * 31 + gRootFontSize; hash = hash * 31 + gInterlineScaleFactor; + // If not yet rendered (initial loading with XML parsing), we can + // ignore some global flags that have not yet produced any effect, + // so they can possibly be updated between loading and rendering + // without trigerring a drop of all the styles and rend methods + // set up in the XML loading phase. This is mostly only needed + // for TextLangMan::getHash(), as the lang can be set by frontend + // code after the loading phase, once the book language is known + // from its metadata, before the rendering that will use the + // language set. (We could ignore some of the other settings + // above if we ever need to reset them in between these phases; + // just be certain they are really not used in the first phase.) + if ( already_rendered ) { + hash = hash * 31 + TextLangMan::getHash(); + hash = hash * 31 + HyphMan::getLeftHyphenMin(); + hash = hash * 31 + HyphMan::getRightHyphenMin(); + hash = hash * 31 + HyphMan::getTrustSoftHyphens(); + } return hash; } @@ -1941,8 +1954,8 @@ tinyNodeCollection::tinyNodeCollection() , _unusedSpaceThresholdPercent(DEF_UNUSED_SPACE_THRESHOLD_PERCENT) , _maxAddedLetterSpacingPercent(DEF_MAX_ADDED_LETTER_SPACING_PERCENT) , _nodeStyleHash(0) -, _nodeDisplayStyleHash(NODE_DISPLAY_STYLE_HASH_UNITIALIZED) -, _nodeDisplayStyleHashInitial(NODE_DISPLAY_STYLE_HASH_UNITIALIZED) +, _nodeDisplayStyleHash(NODE_DISPLAY_STYLE_HASH_UNINITIALIZED) +, _nodeDisplayStyleHashInitial(NODE_DISPLAY_STYLE_HASH_UNINITIALIZED) , _nodeStylesInvalidIfLoading(false) , _boxingWishedButPreventedByCache(false) #endif @@ -1981,8 +1994,8 @@ tinyNodeCollection::tinyNodeCollection( tinyNodeCollection & v ) , _unusedSpaceThresholdPercent(DEF_UNUSED_SPACE_THRESHOLD_PERCENT) , _maxAddedLetterSpacingPercent(DEF_MAX_ADDED_LETTER_SPACING_PERCENT) , _nodeStyleHash(0) -, _nodeDisplayStyleHash(NODE_DISPLAY_STYLE_HASH_UNITIALIZED) -, _nodeDisplayStyleHashInitial(NODE_DISPLAY_STYLE_HASH_UNITIALIZED) +, _nodeDisplayStyleHash(NODE_DISPLAY_STYLE_HASH_UNINITIALIZED) +, _nodeDisplayStyleHashInitial(NODE_DISPLAY_STYLE_HASH_UNINITIALIZED) , _nodeStylesInvalidIfLoading(false) , _boxingWishedButPreventedByCache(false) #endif @@ -4501,7 +4514,7 @@ bool ldomDocument::render( LVRendPageList * pages, LVDocViewCallback * callback, bool was_just_rendered_from_cache = _just_rendered_from_cache; // cleared by checkRenderContext() if ( !checkRenderContext() ) { - if ( _nodeDisplayStyleHashInitial == NODE_DISPLAY_STYLE_HASH_UNITIALIZED ) { // happen when just loaded + if ( _nodeDisplayStyleHashInitial == NODE_DISPLAY_STYLE_HASH_UNINITIALIZED ) { // happen when just loaded // For knowing/debugging cases when node styles set up during loading // is invalid (should happen now only when EPUB has embedded fonts // or some pseudoclass like :last-child has been met). @@ -4600,7 +4613,7 @@ bool ldomDocument::render( LVRendPageList * pages, LVDocViewCallback * callback, pages->serialize( _pagesData ); _renderedBlockCache.restoreSize(); // Restore original cache size - if ( _nodeDisplayStyleHashInitial == NODE_DISPLAY_STYLE_HASH_UNITIALIZED ) { + if ( _nodeDisplayStyleHashInitial == NODE_DISPLAY_STYLE_HASH_UNINITIALIZED ) { // If _nodeDisplayStyleHashInitial has not been initialized from its // former value from the cache file, we use the one computed (just // above in updateRenderContext()) after the first full rendering @@ -13690,12 +13703,12 @@ bool tinyNodeCollection::loadStylesData() return !stylebuf.error(); } -lUInt32 tinyNodeCollection::calcStyleHash() +lUInt32 tinyNodeCollection::calcStyleHash(bool already_rendered) { CRLog::debug("calcStyleHash start"); // int maxlog = 20; lUInt32 res = 0; //_elemCount; - lUInt32 globalHash = calcGlobalSettingsHash(getFontContextDocIndex()); + lUInt32 globalHash = calcGlobalSettingsHash(getFontContextDocIndex(), already_rendered); lUInt32 docFlags = getDocFlags(); //CRLog::info("Calculating style hash... elemCount=%d, globalHash=%08x, docFlags=%08x", _elemCount, globalHash, docFlags); if (_nodeStyleHash) { @@ -14424,7 +14437,7 @@ void ldomDocument::updateRenderContext() int dx = _page_width; int dy = _page_height; _nodeStyleHash = 0; // force recalculation by calcStyleHash() - lUInt32 styleHash = calcStyleHash(); + lUInt32 styleHash = calcStyleHash(_rendered); lUInt32 stylesheetHash = (((_stylesheet.getHash() * 31) + calcHash(_def_style))*31 + calcHash(_def_font)); //calcStyleHash( getRootNode(), styleHash ); _hdr.render_style_hash = styleHash; @@ -14452,7 +14465,7 @@ bool ldomDocument::checkRenderContext() } int dx = _page_width; int dy = _page_height; - lUInt32 styleHash = calcStyleHash(); + lUInt32 styleHash = calcStyleHash(_rendered); lUInt32 stylesheetHash = (((_stylesheet.getHash() * 31) + calcHash(_def_style))*31 + calcHash(_def_font)); //calcStyleHash( getRootNode(), styleHash ); if ( styleHash != _hdr.render_style_hash ) {