From 47d455dd55be855e4cc691c32f687f723d9247ee Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdegraphics@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kviewshell/renderedDocumentPage.cpp | 375 ++++++++++++++++++++++++++++++++++++ 1 file changed, 375 insertions(+) create mode 100644 kviewshell/renderedDocumentPage.cpp (limited to 'kviewshell/renderedDocumentPage.cpp') diff --git a/kviewshell/renderedDocumentPage.cpp b/kviewshell/renderedDocumentPage.cpp new file mode 100644 index 00000000..c5f0d361 --- /dev/null +++ b/kviewshell/renderedDocumentPage.cpp @@ -0,0 +1,375 @@ +// +// Class: RenderedDocumentPage +// +// Widget for displaying TeX DVI files. +// Part of KDVI- A previewer for TeX DVI files. +// +// (C) 2004 Stefan Kebekus. Distributed under the GPL. + +#include + +#include + +#include "renderedDocumentPage.h" +#include "hyperlink.h" +#include "selection.h" +#include "textBox.h" + + +RenderedDocumentPage::RenderedDocumentPage() +{ + textBoxList.reserve(250); + pageNr = 0; + isEmpty = true; + pageText = QString::null; +} + + +RenderedDocumentPage::~RenderedDocumentPage() +{ + ; +} + + +void RenderedDocumentPage::setPageNumber(const PageNumber& pnr) +{ + pageNr = pnr; + clear(); +} + + +void RenderedDocumentPage::clear() +{ +#ifdef DEBUG_DOCUMENTPAGE + kdDebug(1223) << "RenderedDocumentPage::clear() called for page #" << pageNumber << endl; +#endif + + textBoxList.clear(); + hyperLinkList.clear(); + pageText = QString::null; + + isEmpty = true; +} + + +QRegion RenderedDocumentPage::selectedRegion(const TextSelection& selection) +{ + if (selection.isEmpty() || selection.getPageNumber() != pageNr) + return QRegion(); + + int startIndex = selection.getSelectedTextStart(); + int endIndex = selection.getSelectedTextEnd(); + + QValueVector wordBox; + + QRect currentWordBox; + //unsigned int currentBaseline = 0; + + // Merge character boxes into boxes containing complete words. + // Note: A word in this context is defined as a string of boxes + // with the same baseline. + for (int i = startIndex; i <= endIndex; i++) + { + if (i == 0) + { + // start first word + currentWordBox = textBoxList[i].box; + //currentBaseline = textBoxList[i].baseline; + continue; + } + + /*if (currentBaseline == textBoxList[i].baseline) + { + currentWordBox = currentWordBox.unite(textBoxList[i].box); + } + else*/ + { + // start next word + wordBox.push_back(currentWordBox); + currentWordBox = textBoxList[i].box; + //currentBaseline = textBoxList[i].baseline; + } + } + // we still need to store the last word + wordBox.push_back(currentWordBox); + + QValueVector lineBox; + + // Merge word boxes into boxes containing whole lines. + // We start a new line if we encounter a wordbox which does not + // vertically overlap which the current lineBox. + QRect currentLineBox; + + for (unsigned int i = 0; i < wordBox.size(); i++) + { + if (!currentLineBox.isValid()) + { + // start first line + currentLineBox = wordBox[i]; + continue; + } + + // check if there is vertical overlap + if (wordBox[i].top() <= currentLineBox.bottom() && wordBox[i].bottom() >= currentLineBox.top()) + { + // the word belongs to the current line + currentLineBox = currentLineBox.unite(wordBox[i]); + } + else + { + // start next line + //kdDebug() << "push line (" << currentLineBox.top() << ", " << currentLineBox.bottom() << ")" << endl; + lineBox.push_back(currentLineBox); + currentLineBox = wordBox[i]; + } + } + // we still need to store the last line + //kdDebug() << "push line (" << currentLineBox.top() << ", " << currentLineBox.bottom() << ")" << endl; + lineBox.push_back(currentLineBox); + + //kdDebug() << "Number of lineboxes = " << lineBox.size() << endl; + + // Now we increase the height of the lines if necessary to obtain a connected region + // for our selection. + for (unsigned int i = 0; i < lineBox.size() - 1; i++) + { + if (lineBox[i+1].top() >= lineBox[i].bottom()) + { + int midPoint = (lineBox[i].bottom() + lineBox[i+1].top()) / 2; + + lineBox[i].setBottom(midPoint); + lineBox[i+1].setTop(midPoint+1); + } + } + + // Add the lineboxes to a Region + QRegion selectedRegion; + for (unsigned int i = 0; i < lineBox.size(); i++) + { + selectedRegion += QRegion(lineBox[i]); + } + + return selectedRegion; +} + + +TextSelection RenderedDocumentPage::select(const QRect& selectedRectangle) +{ + int selectedTextStart = -1; + int selectedTextEnd = -1; + + // Find the smallest and biggest index for which the corresponding + // textBoxList entry intersects the selected rectangle. + for (unsigned int i=0; i::Iterator i = textBoxList.begin(); i != textBoxList.end(); i++) + { + pageText = pageText + i->text; + } + } + + // Create empty selection; + TextSelection selection; + + // If the page contains no searchable text + if (pageText.isNull()) + return selection; + + // Compute the corresponding pageText index + unsigned int subIndex = 0; + for (int i = 0; i < index; i++) + { + subIndex += textBoxList[i].text.length(); + } + + int textIndex = pageText.find(str, subIndex, caseSensitive); + + if (textIndex == -1) + return selection; + + // Because a single Hyperlink structure can possible store more then + // one character we now have to search for the Indices in the + // textBoxList Vector which corresponds to the found index in the + // String pageText. FIXME: It would be faster to search directly in + // the textBoxList. + int counter = 0; + int startIndex = 0; + while (counter < textIndex) + { + counter += textBoxList[startIndex].text.length(); + // If the string we searched for starts in the middle of some text element we better return a + // selection that it somewhat bigger. + if (counter > textIndex) + break; + + startIndex++; + + // safety check + if (startIndex >= (int)textBoxList.size()) + return selection; + } + + // Search for the end index. + // TODO: This algorithm is not entirely correct if str does not start exactly at the beginning of some text element. + counter = 0; + int endIndex = startIndex; + while (counter < (int)str.length()) + { + counter += textBoxList[endIndex].text.length(); + if (counter >= (int)str.length()) + break; + + endIndex++; + + // safety check + if (endIndex >= (int)textBoxList.size()) + return selection; + } + + // Set the selection + selection.set(pageNr, startIndex, endIndex, str); + return selection; +} + + +TextSelection RenderedDocumentPage::findRev(const QString& str, int index, bool caseSensitive) +{ + // Negative index means we start the search at the end of the text. + if (index < 0) + { + index = textBoxList.size(); + } + + if (pageText.isNull()) + { + // Create the pageText by joining all entries of textBoxList. + for (QValueVector::Iterator i = textBoxList.begin(); i != textBoxList.end(); i++) + { + pageText = pageText + i->text; + } + } + + // Create empty selection; + TextSelection selection; + + // If the page contains no searchable text + if (pageText.isNull()) + return selection; + + // Compute the corresponding pageText index + unsigned int subIndex = 0; + for (int i = 0; i < index; i++) + { + subIndex += textBoxList[i].text.length(); + } + + int textIndex = pageText.findRev(str, subIndex, caseSensitive); + + if (textIndex == -1) + return selection; + + // Because a single Hyperlink structure can possible store more then + // one character we now have to search for the Indices in the + // textBoxList Vector which corresponds to the found index in the + // String pageText. FIXME: It would be faster to search directly in + // the textBoxList. + int counter = 0; + int startIndex = 0; + while (counter < textIndex) + { + counter += textBoxList[startIndex].text.length(); + // If the string we searched for starts in the middle of some text element we better return a + // selection that it somewhat bigger. + if (counter > textIndex) + break; + + startIndex++; + + // safety check + if (startIndex >= (int)textBoxList.size()) + return selection; + } + + // Search for the end index. + // TODO: This algorithm is not entirely correct if str does not start exactly at the beginning of some text element. + counter = 0; + int endIndex = startIndex; + while (counter < (int)str.length()) + { + counter += textBoxList[endIndex].text.length(); + if (counter >= (int)str.length()) + break; + + endIndex++; + + // safety check + if (endIndex >= (int)textBoxList.size()) + return selection; + } + + // Set the selection + selection.set(pageNr, startIndex, endIndex, str); + return selection; +} + +#include "renderedDocumentPage.moc" + -- cgit v1.2.3