Per-view ZLTextParagraphCursorCache and ZLTextElementPool

This commit is contained in:
Slava Monich 2015-05-27 00:08:27 +03:00
parent 8653f9512d
commit 7565921037
11 changed files with 89 additions and 68 deletions

View file

@ -28,7 +28,7 @@
#include "ZLTextLineInfo.h"
#include "ZLTextSelectionModel.h"
ZLTextArea::ZLTextArea(ZLPaintContext &context, const Properties &properties) : myContext(context), myProperties(properties), myWidth(0), myHeight(0) {
ZLTextArea::ZLTextArea(ZLPaintContext &context, const Properties &properties, ZLTextParagraphCursorCache *cache) : myContext(context), myProperties(properties), myWidth(0), myHeight(0), myParagraphCursorCache(cache) {
}
ZLTextArea::~ZLTextArea() {
@ -52,7 +52,7 @@ void ZLTextArea::setModel(shared_ptr<ZLTextModel> model) {
} else {
myMirroredContext.reset();
}
myStartCursor = ZLTextParagraphCursor::cursor(*model);
myStartCursor = myParagraphCursorCache->cursor(*model, 0);
myEndCursor = 0;
}

View file

@ -27,6 +27,7 @@
#include <ZLTextParagraphCursor.h>
#include <ZLTextRectangle.h>
#include <ZLTextModel.h>
class ZLPaintContext;
class ZLMirroredPaintContext;
@ -53,7 +54,7 @@ public:
};
public:
ZLTextArea(ZLPaintContext &context, const Properties &properties);
ZLTextArea(ZLPaintContext &context, const Properties &properties, ZLTextParagraphCursorCache *cache);
~ZLTextArea();
public:
@ -124,6 +125,7 @@ private:
ZLTextTreeNodeMap myTreeNodeMap;
shared_ptr<ZLTextSelectionModel> mySelectionModel;
ZLTextParagraphCursorCache* myParagraphCursorCache;
friend class ZLTextAreaController;
friend class ZLTextSelectionModel;

View file

@ -22,7 +22,7 @@
#include "ZLTextAreaStyle.h"
#include "ZLTextLineInfo.h"
ZLTextAreaController::ZLTextAreaController(ZLPaintContext &context, const ZLTextArea::Properties &properties) : myArea(context, properties), myPaintState(NOTHING_TO_PAINT) {
ZLTextAreaController::ZLTextAreaController(ZLPaintContext &context, const ZLTextArea::Properties &properties, ZLTextParagraphCursorCache *cache) : myArea(context, properties, cache), myParagraphCursorCache(cache), myPaintState(NOTHING_TO_PAINT) {
}
ZLTextAreaController::~ZLTextAreaController() {
@ -38,7 +38,7 @@ void ZLTextAreaController::clear() {
myArea.clear();
myPaintState = NOTHING_TO_PAINT;
ZLTextParagraphCursorCache::clear();
myParagraphCursorCache->clear();
}
ZLTextWordCursor ZLTextAreaController::findStart(const ZLTextWordCursor &end, SizeUnit unit, int size) {
@ -229,7 +229,7 @@ void ZLTextAreaController::rebuildPaintInfo(bool strong) {
myArea.myLineInfos.clear();
if (strong) {
ZLTextParagraphCursorCache::clear();
myParagraphCursorCache->clear();
myArea.myLineInfoCache.clear();
}

View file

@ -41,7 +41,7 @@ public:
};
public:
ZLTextAreaController(ZLPaintContext &context, const ZLTextArea::Properties &properties);
ZLTextAreaController(ZLPaintContext &context, const ZLTextArea::Properties &properties, ZLTextParagraphCursorCache *cache);
~ZLTextAreaController();
const ZLTextArea &area() const;
@ -77,6 +77,7 @@ private:
private:
ZLTextArea myArea;
ZLTextParagraphCursorCache *myParagraphCursorCache;
enum {
NOTHING_TO_PAINT,

View file

@ -22,7 +22,7 @@
#include <linebreak.h>
#include <ZLImage.h>
#include <ZLTextModel.h>
#include <ZLTextParagraph.h>
#include "ZLTextParagraphCursor.h"
@ -32,6 +32,7 @@
ZLTextParagraphCursor::Builder::Builder(ZLTextParagraphCursor &cursor) :
myParagraph(*cursor.myModel[cursor.myIndex]),
myElements(cursor.myElements),
myTextElementPool(cursor.myElements.elementPool()),
myLanguage(cursor.myModel.language()),
myBaseBidiLevel(cursor.myModel.isRtl() ? 1 : 0) {
const int paragraphIndex = cursor.myIndex;
@ -52,16 +53,16 @@ ZLTextParagraphCursor::Builder::Builder(ZLTextParagraphCursor &cursor) :
void ZLTextParagraphCursor::Builder::updateBidiLevel(FriBidiLevel bidiLevel) {
while (myCurrentBidiLevel > bidiLevel) {
--myCurrentBidiLevel;
myElements.push_back(ZLTextElementPool::Pool.EndReversedSequenceElement);
myElements.push_back(myTextElementPool.EndReversedSequenceElement);
}
while (myCurrentBidiLevel < bidiLevel) {
++myCurrentBidiLevel;
myElements.push_back(ZLTextElementPool::Pool.StartReversedSequenceElement);
myElements.push_back(myTextElementPool.StartReversedSequenceElement);
}
}
void ZLTextParagraphCursor::Builder::addWord(const char *ptr, int offset, int len) {
ZLTextWord *word = ZLTextElementPool::Pool.getWord(ptr, len, offset, myCurrentBidiLevel);
ZLTextWord *word = myTextElementPool.getWord(ptr, len, offset, myCurrentBidiLevel);
for (std::vector<ZLTextMark>::const_iterator mit = myFirstMark; mit != myLastMark; ++mit) {
ZLTextMark mark = *mit;
if ((mark.Offset < offset + len) && (mark.Offset + mark.Length > offset)) {
@ -86,7 +87,7 @@ void ZLTextParagraphCursor::Builder::fill() {
break;
case ZLTextParagraphEntry::CONTROL_ENTRY:
case ZLTextParagraphEntry::HYPERLINK_CONTROL_ENTRY:
myElements.push_back(ZLTextElementPool::Pool.getControlElement(it.entry()));
myElements.push_back(myTextElementPool.getControlElement(it.entry()));
break;
case ZLTextParagraphEntry::IMAGE_ENTRY:
{
@ -173,14 +174,14 @@ void ZLTextParagraphCursor::Builder::processTextEntry(const ZLTextEntry &textEnt
switch (spaceState) {
case SPACE:
if ((myBreaksTable[ptr - start - 1] == LINEBREAK_NOBREAK) || (previousCh == '-')) {
myElements.push_back(ZLTextElementPool::Pool.NBHSpaceElement);
myElements.push_back(myTextElementPool.NBHSpaceElement);
} else {
myElements.push_back(ZLTextElementPool::Pool.HSpaceElement);
myElements.push_back(myTextElementPool.HSpaceElement);
}
wordStart = ptr;
break;
case NON_BREAKABLE_SPACE:
myElements.push_back(ZLTextElementPool::Pool.NBHSpaceElement);
myElements.push_back(myTextElementPool.NBHSpaceElement);
wordStart = ptr;
break;
case NO_SPACE:
@ -198,10 +199,10 @@ void ZLTextParagraphCursor::Builder::processTextEntry(const ZLTextEntry &textEnt
}
switch (spaceState) {
case SPACE:
myElements.push_back(ZLTextElementPool::Pool.HSpaceElement);
myElements.push_back(myTextElementPool.HSpaceElement);
break;
case NON_BREAKABLE_SPACE:
myElements.push_back(ZLTextElementPool::Pool.NBHSpaceElement);
myElements.push_back(myTextElementPool.NBHSpaceElement);
break;
case NO_SPACE:
addWord(wordStart, myOffset + (wordStart - start), end - wordStart);

View file

@ -47,6 +47,7 @@ private:
private:
const ZLTextParagraph &myParagraph;
ZLTextElementVector &myElements;
ZLTextElementPool &myTextElementPool;
std::vector<ZLTextMark>::const_iterator myFirstMark;
std::vector<ZLTextMark>::const_iterator myLastMark;

View file

@ -20,24 +20,20 @@
#include <algorithm>
#include <ZLTextParagraph.h>
#include <ZLTextModel.h>
#include "ZLTextParagraphCursor.h"
#include "ZLTextWord.h"
#include "ZLTextParagraphBuilder.h"
ZLTextElementPool ZLTextElementPool::Pool;
std::map<const ZLTextParagraph*, weak_ptr<ZLTextParagraphCursor> > ZLTextParagraphCursorCache::ourCache;
ZLTextParagraphCursorPtr ZLTextParagraphCursorCache::ourLastAdded;
ZLTextElementVector::~ZLTextElementVector() {
for (ZLTextElementVector::const_iterator it = begin(); it != end(); ++it) {
switch ((*it)->kind()) {
case ZLTextElement::WORD_ELEMENT:
ZLTextElementPool::Pool.storeWord((ZLTextWord*)*it);
myTextElementPool->storeWord((ZLTextWord*)*it);
break;
case ZLTextElement::CONTROL_ELEMENT:
ZLTextElementPool::Pool.storeControlElement((ZLTextControlElement*)*it);
myTextElementPool->storeControlElement((ZLTextControlElement*)*it);
break;
case ZLTextElement::IMAGE_ELEMENT:
case ZLTextElement::FORCED_CONTROL_ELEMENT:
@ -77,20 +73,27 @@ ZLTextElementPool::~ZLTextElementPool() {
delete EndReversedSequenceElement;
}
ZLTextParagraphCursorPtr ZLTextParagraphCursor::cursor(const ZLTextModel &model, size_t index) {
ZLTextParagraphCursorPtr result = ZLTextParagraphCursorCache::get(model[index]);
ZLTextParagraphCursorPtr ZLTextParagraphCursorCache::cursor(const ZLTextModel &model, size_t index) {
const ZLTextParagraph *paragraph = model[index];
ZLTextParagraphCursorPtr result = get(paragraph);
if (result.isNull()) {
if (model.kind() == ZLTextModel::TREE_MODEL) {
result = new ZLTextTreeParagraphCursor((const ZLTextTreeModel&)model, index);
result = new ZLTextTreeParagraphCursor((const ZLTextTreeModel&)model, index, this);
} else {
result = new ZLTextPlainParagraphCursor((const ZLTextPlainModel&)model, index);
result = new ZLTextPlainParagraphCursor(model, index, this);
}
ZLTextParagraphCursorCache::put(model[index], result);
put(paragraph, result);
}
return result;
}
ZLTextParagraphCursor::ZLTextParagraphCursor(const ZLTextModel &model, size_t index) : myModel(model) {
ZLTextPlainParagraphCursor::ZLTextPlainParagraphCursor(const ZLTextModel &model, size_t index, ZLTextParagraphCursorCache *cache) : ZLTextParagraphCursor(model, index, cache) {
}
ZLTextTreeParagraphCursor::ZLTextTreeParagraphCursor(const ZLTextTreeModel &model, size_t index, ZLTextParagraphCursorCache *cache) : ZLTextParagraphCursor(model, index, cache) {
}
ZLTextParagraphCursor::ZLTextParagraphCursor(const ZLTextModel &model, size_t index, ZLTextParagraphCursorCache *cache) : myModel(model), myElements(cache->elementPool()), myParagraphCursorCache(cache) {
myIndex = std::min(index, myModel.paragraphsNumber() - 1);
fill();
}
@ -99,7 +102,7 @@ ZLTextParagraphCursor::~ZLTextParagraphCursor() {
}
ZLTextParagraphCursorPtr ZLTextPlainParagraphCursor::previous() const {
return isFirst() ? 0 : cursor(myModel, myIndex - 1);
return isFirst() ? 0 : myParagraphCursorCache->cursor(myModel, myIndex - 1);
}
ZLTextParagraphCursorPtr ZLTextTreeParagraphCursor::previous() const {
@ -121,11 +124,11 @@ ZLTextParagraphCursorPtr ZLTextTreeParagraphCursor::previous() const {
--index;
}
}
return cursor(myModel, index);
return myParagraphCursorCache->cursor(myModel, index);
}
ZLTextParagraphCursorPtr ZLTextPlainParagraphCursor::next() const {
return isLast() ? 0 : cursor(myModel, myIndex + 1);
return isLast() ? 0 : myParagraphCursorCache->cursor(myModel, myIndex + 1);
}
ZLTextParagraphCursorPtr ZLTextTreeParagraphCursor::next() const {
@ -134,7 +137,7 @@ ZLTextParagraphCursorPtr ZLTextTreeParagraphCursor::next() const {
}
const ZLTextTreeParagraph *current = (const ZLTextTreeParagraph*)myModel[myIndex];
if (!current->children().empty() && current->isOpen()) {
return cursor(myModel, myIndex + 1);
return myParagraphCursorCache->cursor(myModel, myIndex + 1);
}
const ZLTextTreeParagraph *parent = current->parent();
@ -147,7 +150,7 @@ ZLTextParagraphCursorPtr ZLTextTreeParagraphCursor::next() const {
while (((const ZLTextTreeParagraph*)myModel[index])->parent() != parent) {
++index;
}
return cursor(myModel, index);
return myParagraphCursorCache->cursor(myModel, index);
}
return 0;
}
@ -185,6 +188,10 @@ bool ZLTextTreeParagraphCursor::isLast() const {
return true;
}
const ZLTextParagraph &ZLTextParagraphCursor::paragraph() const {
return *myModel[myIndex];
}
bool ZLTextParagraphCursor::isEndOfSection() const {
return myModel[myIndex]->kind() == ZLTextParagraph::END_OF_SECTION_PARAGRAPH;
}
@ -207,7 +214,7 @@ ZLTextMark ZLTextWordCursor::position() const {
void ZLTextParagraphCursor::processControlParagraph(const ZLTextParagraph &paragraph) {
for (ZLTextParagraph::Iterator it = paragraph; !it.isEnd(); it.next()) {
myElements.push_back(ZLTextElementPool::Pool.getControlElement(it.entry()));
myElements.push_back(elementPool()->getControlElement(it.entry()));
}
}
@ -223,15 +230,15 @@ void ZLTextParagraphCursor::fill() {
}
case ZLTextParagraph::EMPTY_LINE_PARAGRAPH:
processControlParagraph(paragraph);
myElements.push_back(ZLTextElementPool::Pool.EmptyLineElement);
myElements.push_back(elementPool()->EmptyLineElement);
break;
case ZLTextParagraph::BEFORE_SKIP_PARAGRAPH:
processControlParagraph(paragraph);
myElements.push_back(ZLTextElementPool::Pool.BeforeParagraphElement);
myElements.push_back(elementPool()->BeforeParagraphElement);
break;
case ZLTextParagraph::AFTER_SKIP_PARAGRAPH:
processControlParagraph(paragraph);
myElements.push_back(ZLTextElementPool::Pool.AfterParagraphElement);
myElements.push_back(elementPool()->AfterParagraphElement);
break;
case ZLTextParagraph::END_OF_SECTION_PARAGRAPH:
case ZLTextParagraph::END_OF_TEXT_PARAGRAPH:
@ -316,7 +323,7 @@ const ZLTextWordCursor &ZLTextWordCursor::operator = (ZLTextParagraphCursorPtr p
void ZLTextWordCursor::moveToParagraph(int paragraphIndex) {
if (!isNull() && (paragraphIndex != (int)myParagraphCursor->index())) {
myParagraphCursor = ZLTextParagraphCursor::cursor(myParagraphCursor->myModel, paragraphIndex);
myParagraphCursor = myParagraphCursor->cursor(paragraphIndex);
moveToParagraphStart();
}
}

View file

@ -27,26 +27,32 @@
#include <shared_ptr.h>
#include <allocator.h>
#include <ZLTextModel.h>
#include <ZLTextMark.h>
#include "ZLTextElement.h"
#include "ZLTextWord.h"
class ZLTextParagraph;
class ZLTextElementPool;
class ZLTextParagraphCursorCache;
class ZLTextTreeModel;
class ZLTextModel;
class ZLTextElementVector : public std::vector<ZLTextElement*> {
public:
ZLTextElementVector();
ZLTextElementVector(ZLTextElementPool *pool);
~ZLTextElementVector();
ZLTextElementPool &elementPool() const { return *myTextElementPool; }
private:
ZLTextElementPool *myTextElementPool;
};
class ZLTextElementPool {
public:
static ZLTextElementPool Pool;
private:
ZLTextElementPool();
~ZLTextElementPool();
@ -78,10 +84,9 @@ private:
class Builder;
protected:
ZLTextParagraphCursor(const ZLTextModel &model, size_t index);
ZLTextParagraphCursor(const ZLTextModel &model, size_t index, ZLTextParagraphCursorCache* cache);
public:
static ZLTextParagraphCursorPtr cursor(const ZLTextModel &model, size_t index = 0);
virtual ~ZLTextParagraphCursor();
bool isFirst() const;
@ -96,6 +101,8 @@ public:
const ZLTextElement &operator [] (size_t index) const;
const ZLTextParagraph &paragraph() const;
ZLTextElementPool *elementPool() const;
ZLTextParagraphCursorPtr cursor(size_t index);
private:
void processControlParagraph(const ZLTextParagraph &paragraph);
@ -113,6 +120,7 @@ protected:
const ZLTextModel &myModel;
size_t myIndex;
ZLTextElementVector myElements;
ZLTextParagraphCursorCache *myParagraphCursorCache;
friend class ZLTextWordCursor;
};
@ -120,19 +128,21 @@ friend class ZLTextWordCursor;
class ZLTextParagraphCursorCache {
public:
static void put(const ZLTextParagraph *paragraph, ZLTextParagraphCursorPtr cursor);
static ZLTextParagraphCursorPtr get(const ZLTextParagraph *paragraph);
ZLTextParagraphCursorCache() {}
~ZLTextParagraphCursorCache() {}
static void clear();
static void cleanup();
void clear();
void cleanup();
void put(const ZLTextParagraph *paragraph, ZLTextParagraphCursorPtr cursor);
ZLTextParagraphCursorPtr get(const ZLTextParagraph *paragraph);
ZLTextParagraphCursorPtr cursor(const ZLTextModel &model, size_t index);
ZLTextElementPool *elementPool() { return &ourElementPool; }
private:
static std::map<const ZLTextParagraph*, weak_ptr<ZLTextParagraphCursor> > ourCache;
static ZLTextParagraphCursorPtr ourLastAdded;
private:
// Instance creation is disabled
ZLTextParagraphCursorCache();
std::map<const ZLTextParagraph*, weak_ptr<ZLTextParagraphCursor> > ourCache;
ZLTextParagraphCursorPtr ourLastAdded;
ZLTextElementPool ourElementPool;
};
class ZLTextWordCursor {
@ -179,7 +189,7 @@ private:
class ZLTextPlainParagraphCursor : public ZLTextParagraphCursor {
private:
ZLTextPlainParagraphCursor(const ZLTextModel &model, size_t index);
ZLTextPlainParagraphCursor(const ZLTextModel &model, size_t index, ZLTextParagraphCursorCache* cache);
public:
~ZLTextPlainParagraphCursor();
@ -188,13 +198,13 @@ public:
ZLTextParagraphCursorPtr next() const;
bool isLast() const;
friend class ZLTextParagraphCursor;
friend class ZLTextParagraphCursorCache;
};
class ZLTextTreeParagraphCursor : public ZLTextParagraphCursor {
private:
ZLTextTreeParagraphCursor(const ZLTextTreeModel &model, size_t index);
ZLTextTreeParagraphCursor(const ZLTextTreeModel &model, size_t index, ZLTextParagraphCursorCache* cache);
public:
~ZLTextTreeParagraphCursor();
@ -203,10 +213,10 @@ public:
ZLTextParagraphCursorPtr next() const;
bool isLast() const;
friend class ZLTextParagraphCursor;
friend class ZLTextParagraphCursorCache;
};
inline ZLTextElementVector::ZLTextElementVector() {}
inline ZLTextElementVector::ZLTextElementVector(ZLTextElementPool *pool) : myTextElementPool(pool) {}
inline ZLTextWord *ZLTextElementPool::getWord(const char *data, unsigned short length, size_t paragraphOffset, unsigned char bidiLevel) {
return new (myWordAllocator.allocate()) ZLTextWord(data, length, paragraphOffset, bidiLevel);
@ -225,8 +235,9 @@ inline void ZLTextElementPool::storeControlElement(ZLTextControlElement *element
inline size_t ZLTextParagraphCursor::index() const { return myIndex; }
inline const ZLTextElement &ZLTextParagraphCursor::operator [] (size_t index) const { return *myElements[index]; }
inline const ZLTextParagraph &ZLTextParagraphCursor::paragraph() const { return *myModel[myIndex]; }
inline size_t ZLTextParagraphCursor::paragraphLength() const { return myElements.size(); }
inline ZLTextElementPool *ZLTextParagraphCursor::elementPool() const { return myParagraphCursorCache->elementPool(); }
inline ZLTextParagraphCursorPtr ZLTextParagraphCursor::cursor(size_t index) { return myParagraphCursorCache->cursor(myModel, index); }
inline ZLTextWordCursor::ZLTextWordCursor() : myElementIndex(0), myCharIndex(0) {}
inline ZLTextWordCursor::ZLTextWordCursor(const ZLTextWordCursor &cursor) : myParagraphCursor(cursor.myParagraphCursor), myElementIndex(cursor.myElementIndex), myCharIndex(cursor.myCharIndex) {}
@ -268,10 +279,7 @@ inline const ZLTextParagraphCursor &ZLTextWordCursor::paragraphCursor() const {
inline void ZLTextWordCursor::nextWord() { ++myElementIndex; myCharIndex = 0; }
inline void ZLTextWordCursor::previousWord() { --myElementIndex; myCharIndex = 0; }
inline ZLTextPlainParagraphCursor::ZLTextPlainParagraphCursor(const ZLTextModel &model, size_t index) : ZLTextParagraphCursor(model, index) {}
inline ZLTextPlainParagraphCursor::~ZLTextPlainParagraphCursor() {}
inline ZLTextTreeParagraphCursor::ZLTextTreeParagraphCursor(const ZLTextTreeModel &model, size_t index) : ZLTextParagraphCursor(model, index) {}
inline ZLTextTreeParagraphCursor::~ZLTextTreeParagraphCursor() {}
#endif /* __ZLTEXTPARAGRAPHCURSOR_H__ */

View file

@ -42,7 +42,7 @@ const ZLTypeId &ZLTextView::typeId() const {
ZLTextView::ZLTextView(ZLPaintContext &context) :
ZLView(context),
myTextAreaController(context, *this),
myTextAreaController(context, *this, &myParagraphCursorCache),
myTreeStateIsFrozen(false),
myDoUpdateScrollbar(false),
myDoubleClickInfo(*this) {

View file

@ -127,6 +127,7 @@ private:
void stopSelectionScrolling();
private:
ZLTextParagraphCursorCache myParagraphCursorCache;
ZLTextAreaController myTextAreaController;
std::vector<size_t> myTextSize;

View file

@ -59,5 +59,5 @@ void ZLTextView::paint() {
}
}
ZLTextParagraphCursorCache::cleanup();
myParagraphCursorCache.cleanup();
}