filters

fstring.cpp

00001 /*
00002  * Copyright (c) 2002-2003 Nicolas HADACEK (hadacek@kde.org)
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008 
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013 
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018  */
00019 
00020 #include "fstring.h"
00021 
00022 #include <kglobal.h>
00023 #include <kdebug.h>
00024 
00025 #include "data.h"
00026 #include "transform.h"
00027 
00028 
00029 namespace PDFImport {
00030 
00031 //-----------------------------------------------------------------------------
00032 QDomElement Tabulator::createElement(Data &data) const
00033 {
00034     QDomElement element = data.createElement("TABULATOR");
00035     element.setAttribute("type", alignment);
00036     element.setAttribute("ptpos", pos);
00037     element.setAttribute("filling", filling);
00038     if ( alignment==Character )
00039         element.setAttribute("alignchar", QString(alignmentChar));
00040     return element;
00041 }
00042 
00043 //-----------------------------------------------------------------------------
00044 Paragraph::Paragraph()
00045     : type(Body), firstIndent(0), leftIndent(0), align(AlignLeft)
00046 {}
00047 
00048 Paragraph::Paragraph(TextLine *first, uint nbLines)
00049     :  type(Body), firstIndent(0), leftIndent(0), align(AlignLeft)
00050 {
00051     // fill line list
00052     TextLine *line = first;
00053     for (uint i=0; i<nbLines; i++) {
00054         Q_ASSERT( line!=0 );
00055         _lines.append(line);
00056         line = line->next;
00057     }
00058 
00059     // compute rectangle
00060     QValueList<TextLine *>::const_iterator it;
00061     for (it = _lines.begin(); it!=_lines.end(); ++it)
00062         for (TextBlock *block = (*it)->blocks; block; block = block->next) {
00063             DRect br(block->xMin, block->xMax, block->yMin, block->yMax);
00064             _rect.unite(br);
00065         }
00066 }
00067 
00068 int Paragraph::findTab(double xMin, const TextLine *line) const
00069 {
00070     double epsilon = 0.1 * (line->yMax - line->yMin);
00071     double dx = xMin - (isFirst(line) ? firstIndent : leftIndent);
00072     if ( fabs(dx)<epsilon ) return -2;
00073     for (uint i=0; i<tabs.size(); i++)
00074         if ( fabs(xMin-tabs[i].pos)<epsilon ) return i;
00075     return -1;
00076 }
00077 
00078 uint Paragraph::findNbTabs(uint i, double prevXMax) const
00079 {
00080     uint k = 0;
00081     for (; k<tabs.size(); k++)
00082         if ( tabs[k].pos>prevXMax ) break;
00083     if ( k>i ) return 0;
00084     return i-k+1;
00085 }
00086 
00087 int Paragraph::charFromEnd(uint dec, uint &bi) const
00088 {
00089     uint k = 0;
00090     for (uint i=blocks.size(); i>0; i--) {
00091         for (uint j=blocks[i-1].text.length(); j>0; j--) {
00092             if ( k==dec ) {
00093                 bi = i-1;
00094                 return j-1;
00095             }
00096             k++;
00097         }
00098     }
00099     return -1;
00100 }
00101 
00102 //-----------------------------------------------------------------------------
00103 String::String(GfxState *state, double x0, double y0,
00104                double fontSize, uint frameIndex)
00105     : TextString(state, x0, y0, fontSize), link(0), _frameIndex(frameIndex)
00106 {
00107     _font = Font(state, fontSize);
00108 }
00109 
00110 void String::addChar(GfxState *state, double x, double y,
00111                      double dx, double dy, Unicode u)
00112 {
00113     Unicode res[MaxLigatureLength];
00114     uint nb = checkLigature(u, res);
00115     QString sdebug;
00116     if ( nb>1 ) sdebug = "found ligature ";
00117     double ddx = dx / nb;
00118     for (uint i=0; i<nb; i++) {
00119         TextString::addChar(state, x + ddx*i, y, ddx, dy, res[i]);
00120         if ( nb>1 ) sdebug += QChar(res[i]);
00121     }
00122     if ( nb>1 ) kdDebug(30516) << sdebug << endl;
00123     else checkCombination(this);
00124 }
00125 
00126 bool String::checkCombination(TextString *str)
00127 {
00128     if ( len<1 || str->len<1 ) return false;
00129     if ( str==this && len<2 ) return false;
00130 
00131     struct CharData {
00132         int i;
00133         DRect r;
00134         Unicode u;
00135     };
00136     CharData letter, accent;
00137     letter.i = (str==this ? len-1 : 0);
00138     letter.u = str->text[letter.i];
00139     accent.i = (str==this ? len-2 : len-1);
00140     accent.u = text[accent.i];
00141     Unicode res = checkCombi(letter.u, accent.u);
00142     if ( res==0 ) return false;
00143 
00144     letter.r.setLeft(letter.i==0 ? str->xMin : str->xRight[letter.i-1]);
00145     letter.r.setRight(str->xRight[letter.i]);
00146     letter.r.setTop(str->yMin);
00147     letter.r.setBottom(str->yMax);
00148     accent.r.setLeft(accent.i==0 ? xMin : xRight[accent.i-1]);
00149     accent.r.setRight(xRight[accent.i]);
00150     accent.r.setTop(yMin);
00151     accent.r.setBottom(yMax);
00152     bool ok = ( more(accent.r.left(), letter.r.left(), 0.005)
00153                 && less(accent.r.right(), letter.r.right(), 0.005) );
00154     // #### above/below detection is not right !!!
00155 //    bool above = more(accent.r.bottom, letter.r.top);
00156 //    bool below = more(accent.r.top, letter.r.bottom);
00157 //    kdDebug(30516) << "found combi " << QString(QChar(res))
00158 //                   << " accent: " << accent.r.toString() << endl;
00159 //    kdDebug(30516) << "letter: " << letter.r.toString()
00160 //                   << endl;
00161     // #### FIXME we should check for above or below accent !!!
00162     if ( !ok ) return false;
00163 //    if (below) {
00164         // #### TODO
00165 //        kdDebug(30516) << "accent below !" << endl;
00166 //        return false;
00167 //    } else if ( !above ) {
00168 //        kdDebug(30516) << "accent inside letter ??" << endl;
00169 //        return false;
00170 //    }
00171 //    kdDebug(30516) << "combi ok" << endl;
00172 
00173     // replace accent by accented letter
00174     text[accent.i] = res;
00175     xMax = letter.r.right();
00176     if ( accent.i==0 ) xMin = letter.r.left();
00177     else xRight[accent.i-1] = letter.r.left();
00178     yMin = kMin(yMin, str->yMin);
00179     yMax = kMax(yMax, str->yMax);
00180 
00181     // append remaining string
00182     if ( str==this ) {
00183         len--;
00184         for (int k=letter.i+1; k<str->len; k++) {
00185             xRight[k-1] = xRight[k];
00186             text[k-1] = text[k];
00187         }
00188     } else {
00189         for (int k=letter.i+1; k<str->len; k++)
00190         TextString::addChar(0, str->xRight[k-1], 0,
00191                             str->xRight[k] - str->xRight[k-1], 0,
00192                             str->text[k]);
00193         str->len = 0;
00194     }
00195 
00196     return true;
00197 }
00198 
00199 } // namespace
KDE Home | KDE Accessibility Home | Description of Access Keys