• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kviewshell

renderedDocumentPage.cpp

Go to the documentation of this file.
00001 //
00002 // Class: RenderedDocumentPage
00003 //
00004 // Widget for displaying TeX DVI files.
00005 // Part of KDVI- A previewer for TeX DVI files.
00006 //
00007 // (C) 2004 Stefan Kebekus. Distributed under the GPL.
00008 
00009 #include <config.h>
00010 
00011 #include <kdebug.h>
00012 
00013 #include "renderedDocumentPage.h"
00014 #include "hyperlink.h"
00015 #include "selection.h"
00016 #include "textBox.h"
00017 
00018 
00019 RenderedDocumentPage::RenderedDocumentPage()
00020 {
00021   textBoxList.reserve(250);
00022   pageNr = 0;
00023   isEmpty = true;
00024   pageText = QString::null;
00025 }
00026 
00027 
00028 RenderedDocumentPage::~RenderedDocumentPage()
00029 {
00030   ;
00031 }
00032 
00033 
00034 void RenderedDocumentPage::setPageNumber(const PageNumber& pnr)
00035 {
00036   pageNr = pnr;
00037   clear();
00038 }
00039 
00040 
00041 void RenderedDocumentPage::clear()
00042 {
00043 #ifdef DEBUG_DOCUMENTPAGE
00044   kdDebug(1223) << "RenderedDocumentPage::clear() called for page #" << pageNumber << endl;
00045 #endif
00046 
00047   textBoxList.clear();
00048   hyperLinkList.clear();
00049   pageText = QString::null;
00050 
00051   isEmpty = true;
00052 }
00053 
00054 
00055 QRegion RenderedDocumentPage::selectedRegion(const TextSelection& selection)
00056 {
00057   if (selection.isEmpty() || selection.getPageNumber() != pageNr)
00058     return QRegion();
00059 
00060   int startIndex = selection.getSelectedTextStart();
00061   int endIndex = selection.getSelectedTextEnd();
00062 
00063   QValueVector<QRect> wordBox;
00064 
00065   QRect currentWordBox;
00066   //unsigned int currentBaseline = 0;
00067 
00068   // Merge character boxes into boxes containing complete words.
00069   // Note: A word in this context is defined as a string of boxes
00070   // with the same baseline.
00071   for (int i = startIndex; i <= endIndex; i++)
00072   {
00073     if (i == 0)
00074     {
00075       // start first word
00076       currentWordBox = textBoxList[i].box;
00077       //currentBaseline = textBoxList[i].baseline;
00078       continue;
00079     }
00080 
00081     /*if (currentBaseline == textBoxList[i].baseline)
00082     {
00083       currentWordBox = currentWordBox.unite(textBoxList[i].box);
00084     }
00085     else*/
00086     {
00087       // start next word
00088       wordBox.push_back(currentWordBox);
00089       currentWordBox = textBoxList[i].box;
00090       //currentBaseline = textBoxList[i].baseline;
00091     }
00092   }
00093   // we still need to store the last word
00094   wordBox.push_back(currentWordBox);
00095 
00096   QValueVector<QRect> lineBox;
00097 
00098   // Merge word boxes into boxes containing whole lines.
00099   // We start a new line if we encounter a wordbox which does not
00100   // vertically overlap which the current lineBox.
00101   QRect currentLineBox;
00102 
00103   for (unsigned int i = 0; i < wordBox.size(); i++)
00104   {
00105     if (!currentLineBox.isValid())
00106     {
00107       // start first line
00108       currentLineBox = wordBox[i];
00109       continue;
00110     }
00111 
00112     // check if there is vertical overlap
00113     if (wordBox[i].top() <= currentLineBox.bottom() && wordBox[i].bottom() >= currentLineBox.top())
00114     {
00115       // the word belongs to the current line
00116       currentLineBox = currentLineBox.unite(wordBox[i]);
00117     }
00118     else
00119     {
00120       // start next line
00121       //kdDebug() << "push line (" << currentLineBox.top() << ", " << currentLineBox.bottom() << ")" << endl;
00122       lineBox.push_back(currentLineBox);
00123       currentLineBox = wordBox[i];
00124     }
00125   }
00126   // we still need to store the last line
00127   //kdDebug() << "push line (" << currentLineBox.top() << ", " << currentLineBox.bottom() << ")" << endl;
00128   lineBox.push_back(currentLineBox);
00129 
00130   //kdDebug() << "Number of lineboxes = " << lineBox.size() << endl;
00131 
00132   // Now we increase the height of the lines if necessary to obtain a connected region
00133   // for our selection.
00134   for (unsigned int i = 0; i < lineBox.size() - 1; i++)
00135   {
00136       if (lineBox[i+1].top() >= lineBox[i].bottom())
00137       {
00138         int midPoint = (lineBox[i].bottom() + lineBox[i+1].top()) / 2;
00139 
00140         lineBox[i].setBottom(midPoint);
00141         lineBox[i+1].setTop(midPoint+1);
00142       }
00143   }
00144 
00145   // Add the lineboxes to a Region
00146   QRegion selectedRegion;
00147   for (unsigned int i = 0; i < lineBox.size(); i++)
00148   {
00149     selectedRegion += QRegion(lineBox[i]);
00150   }
00151 
00152   return selectedRegion;
00153 }
00154 
00155 
00156 TextSelection RenderedDocumentPage::select(const QRect& selectedRectangle)
00157 {
00158   int selectedTextStart = -1;
00159   int selectedTextEnd   = -1;
00160 
00161   // Find the smallest and biggest index for which the corresponding
00162   // textBoxList entry intersects the selected rectangle.
00163   for (unsigned int i=0; i<textBoxList.size(); i++)
00164   {
00165     if (selectedRectangle.intersects(textBoxList[i].box))
00166     {
00167       if (selectedTextStart == -1)
00168         selectedTextStart = i;
00169       selectedTextEnd = i;
00170     }
00171   }
00172 
00173   TextSelection selection;
00174 
00175   QString selectedText;
00176 
00177   if (selectedTextStart != -1)
00178   {
00179     for (int i = selectedTextStart; (i <= selectedTextEnd) && (i < (int)textBoxList.size()); i++)
00180     {
00181       selectedText += textBoxList[i].text;
00182     }
00183     selection.set(pageNr, selectedTextStart, selectedTextEnd, selectedText);
00184     return selection;
00185   }
00186   // return empty selection
00187   return selection;
00188 }
00189 
00190 TextSelection RenderedDocumentPage::select(const QPoint& point)
00191 {
00192   int selectedTextStart = -1;
00193   int selectedTextEnd   = -1;
00194 
00195   for (unsigned int i=0; i<textBoxList.size(); i++)
00196   {
00197     if (textBoxList[i].box.contains(point))
00198     {
00199       selectedTextStart = i;
00200       selectedTextEnd = i;
00201       break;
00202     }
00203   }
00204 
00205   TextSelection selection;
00206 
00207   QString selectedText;
00208 
00209   if (selectedTextStart != -1)
00210   {
00211     selectedText = textBoxList[selectedTextStart].text;
00212     selection.set(pageNr, selectedTextStart, selectedTextEnd, selectedText);
00213     return selection;
00214   }
00215   // return empty selection
00216   return selection;
00217 }
00218 
00219 TextSelection RenderedDocumentPage::find(const QString& str, int index, bool caseSensitive)
00220 {
00221   if (pageText.isNull())
00222   {
00223     // Create the pageText by joining all entries of textBoxList.
00224     for (QValueVector<TextBox>::Iterator i = textBoxList.begin(); i != textBoxList.end(); i++)
00225     {
00226       pageText = pageText + i->text;
00227     }
00228   }
00229 
00230   // Create empty selection;
00231   TextSelection selection;
00232 
00233   // If the page contains no searchable text
00234   if (pageText.isNull())
00235     return selection;
00236 
00237   // Compute the corresponding pageText index
00238   unsigned int subIndex = 0;
00239   for (int i = 0; i < index; i++)
00240   {
00241     subIndex += textBoxList[i].text.length();
00242   }
00243 
00244   int textIndex = pageText.find(str, subIndex, caseSensitive);
00245 
00246   if (textIndex == -1)
00247     return selection;
00248 
00249   // Because a single Hyperlink structure can possible store more then
00250   // one character we now have to search for the Indices in the
00251   // textBoxList Vector which corresponds to the found index in the
00252   // String pageText.  FIXME: It would be faster to search directly in
00253   // the textBoxList.
00254   int counter = 0;
00255   int startIndex = 0;
00256   while (counter < textIndex)
00257   {
00258     counter += textBoxList[startIndex].text.length();
00259     // If the string we searched for starts in the middle of some text element we better return a
00260     // selection that it somewhat bigger.
00261     if (counter > textIndex)
00262       break;
00263 
00264     startIndex++;
00265 
00266     // safety check
00267     if (startIndex >= (int)textBoxList.size())
00268       return selection;
00269   }
00270 
00271   // Search for the end index.
00272   // TODO: This algorithm is not entirely correct if str does not start exactly at the beginning of some text element.
00273   counter = 0;
00274   int endIndex = startIndex;
00275   while (counter < (int)str.length())
00276   {
00277     counter += textBoxList[endIndex].text.length();
00278     if (counter >= (int)str.length())
00279       break;
00280 
00281     endIndex++;
00282 
00283     // safety check
00284     if (endIndex >= (int)textBoxList.size())
00285       return selection;
00286   }
00287 
00288   // Set the selection
00289   selection.set(pageNr, startIndex, endIndex, str);
00290   return selection;
00291 }
00292 
00293 
00294 TextSelection RenderedDocumentPage::findRev(const QString& str, int index, bool caseSensitive)
00295 {
00296   // Negative index means we start the search at the end of the text.
00297   if (index < 0)
00298   {
00299     index = textBoxList.size();
00300   }
00301 
00302   if (pageText.isNull())
00303   {
00304     // Create the pageText by joining all entries of textBoxList.
00305     for (QValueVector<TextBox>::Iterator i = textBoxList.begin(); i != textBoxList.end(); i++)
00306     {
00307       pageText = pageText + i->text;
00308     }
00309   }
00310 
00311   // Create empty selection;
00312   TextSelection selection;
00313 
00314   // If the page contains no searchable text
00315   if (pageText.isNull())
00316     return selection;
00317 
00318   // Compute the corresponding pageText index
00319   unsigned int subIndex = 0;
00320   for (int i = 0; i < index; i++)
00321   {
00322     subIndex += textBoxList[i].text.length();
00323   }
00324 
00325   int textIndex = pageText.findRev(str, subIndex, caseSensitive);
00326 
00327   if (textIndex == -1)
00328     return selection;
00329 
00330   // Because a single Hyperlink structure can possible store more then
00331   // one character we now have to search for the Indices in the
00332   // textBoxList Vector which corresponds to the found index in the
00333   // String pageText.  FIXME: It would be faster to search directly in
00334   // the textBoxList.
00335   int counter = 0;
00336   int startIndex = 0;
00337   while (counter < textIndex)
00338   {
00339     counter += textBoxList[startIndex].text.length();
00340     // If the string we searched for starts in the middle of some text element we better return a
00341     // selection that it somewhat bigger.
00342     if (counter > textIndex)
00343       break;
00344 
00345     startIndex++;
00346 
00347     // safety check
00348     if (startIndex >= (int)textBoxList.size())
00349       return selection;
00350   }
00351 
00352   // Search for the end index.
00353   // TODO: This algorithm is not entirely correct if str does not start exactly at the beginning of some text element.
00354   counter = 0;
00355   int endIndex = startIndex;
00356   while (counter < (int)str.length())
00357   {
00358     counter += textBoxList[endIndex].text.length();
00359     if (counter >= (int)str.length())
00360       break;
00361 
00362     endIndex++;
00363 
00364     // safety check
00365     if (endIndex >= (int)textBoxList.size())
00366       return selection;
00367   }
00368 
00369   // Set the selection
00370   selection.set(pageNr, startIndex, endIndex, str);
00371   return selection;
00372 }
00373 
00374 #include "renderedDocumentPage.moc"
00375 

kviewshell

Skip menu "kviewshell"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

API Reference

Skip menu "API Reference"
  • kviewshell
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal