00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "util_math.h"
00025 #include <QBitmap>
00026 #include <QFile>
00027 #include <QFileInfo>
00028 #include <QDir>
00029 #include <QCheckBox>
00030 #include <QWidget>
00031 #include <QPixmap>
00032 #include <QList>
00033 #include <QByteArray>
00034 #include <QPolygon>
00035 #include <QImageReader>
00036
00037 #include <algorithm>
00038 #include "scconfig.h"
00039
00040 #include "commonstrings.h"
00041 #include <QProcess>
00042 #include "scmessagebox.h"
00043 #include "scpixmapcache.h"
00044 #include "scpaths.h"
00045
00046 extern "C"
00047 {
00048 #define XMD_H // shut JPEGlib up
00049 #if defined(Q_OS_UNIXWARE)
00050 # define HAVE_BOOLEAN // libjpeg under Unixware seems to need this
00051 #endif
00052 #include <jpeglib.h>
00053 #include <jerror.h>
00054 #undef HAVE_STDLIB_H
00055 #ifdef const
00056 # undef const // remove crazy C hackery in jconfig.h
00057 #endif
00058 }
00059
00060 #include "pageitem.h"
00061 #include "scribus.h"
00062 #include "scribusdoc.h"
00063 #include "scribusview.h"
00064
00065
00066
00067
00068
00069 #include <zlib.h>
00070
00071
00072 using namespace std;
00073
00074
00075
00076 uint getDouble(QString in, bool raw)
00077 {
00078 QByteArray bb(4, ' ');
00079 if (raw)
00080 {
00081
00082
00083
00084
00085
00086 bb = bb.insert(3, in.at(0));
00087 bb = bb.insert(2, in.at(1));
00088 bb = bb.insert(1, in.at(2));
00089 bb = bb.insert(0, in.at(3));
00090 }
00091 else
00092 {
00093
00094
00095
00096
00097
00098 bb = bb.insert(0, in.at(0));
00099 bb = bb.insert(1, in.at(1));
00100 bb = bb.insert(2, in.at(2));
00101 bb = bb.insert(3, in.at(3));
00102 }
00103 uint ret;
00104 ret = bb[0] & 0xff;
00105 ret |= (bb[1] << 8) & 0xff00;
00106 ret |= (bb[2] << 16) & 0xff0000;
00107 ret |= (bb[3] << 24) & 0xff000000;
00108 return ret;
00109 }
00110
00111 QPolygon RegularPolygon(double w, double h, uint c, bool star, double factor, double rota)
00112 {
00113 uint cx = star ? c * 2 : c;
00114 double seg = 360.0 / cx;
00115 double sc = rota + 180.0;
00116 double di = factor;
00117 int mx = 0;
00118 int my = 0;
00119 QPolygon pts(cx);
00120 for (uint x = 0; x < cx; ++x)
00121 {
00122 sc = seg * x + 180.0 + rota;
00123 if (star)
00124 {
00125 double wf = x % 2 == 0 ? w / 2.0 : w / 2.0 * di;
00126 double hf = x % 2 == 0 ? h / 2.0 : h / 2.0 * di;
00127 mx = qRound(sin(sc / 180.0 * M_PI) * (wf) + (w/2.0));
00128 my = qRound(cos(sc / 180.0 * M_PI) * (hf) + (h/2.0));
00129 }
00130 else
00131 {
00132 mx = qRound(sin(sc / 180.0 * M_PI) * (w/2.0) + (w/2.0));
00133 my = qRound(cos(sc / 180.0 * M_PI) * (h/2.0) + (h/2.0));
00134 }
00135 pts.setPoint(x, mx, my);
00136 }
00137 return pts;
00138 }
00139
00140 FPointArray RegularPolygonF(double w, double h, uint c, bool star, double factor, double rota)
00141 {
00142 uint cx = star ? c * 2 : c;
00143 double seg = 360.0 / cx;
00144 double sc = rota + 180.0;
00145 double di = factor;
00146 double mx = 0;
00147 double my = 0;
00148 FPointArray pts(cx);
00149 for (uint x = 0; x < cx; ++x)
00150 {
00151 sc = seg * x + 180.0 + rota;
00152 if (star)
00153 {
00154 double wf = x % 2 == 0 ? w / 2.0 : w / 2.0 * di;
00155 double hf = x % 2 == 0 ? h / 2.0 : h / 2.0 * di;
00156 mx = sin(sc / 180.0 * M_PI) * (wf) + (w/2.0);
00157 my = cos(sc / 180.0 * M_PI) * (hf) + (h/2.0);
00158 }
00159 else
00160 {
00161 mx = sin(sc / 180.0 * M_PI) * (w/2.0) + (w/2.0);
00162 my = cos(sc / 180.0 * M_PI) * (h/2.0) + (h/2.0);
00163 }
00164 pts.setPoint(x, mx, my);
00165 }
00166 return pts;
00167 }
00168
00169 QList<QPainterPath> decomposePath(QPainterPath &path)
00170 {
00171 QList<QPainterPath> ret;
00172 ret.clear();
00173 QPainterPath part;
00174 part = QPainterPath();
00175 bool first = true;
00176 for (int i = 0; i < path.elementCount(); ++i)
00177 {
00178 const QPainterPath::Element &elm = path.elementAt(i);
00179 if ((first) && (elm.type != QPainterPath::MoveToElement))
00180 part.moveTo(elm.x, elm.y);
00181 switch (elm.type)
00182 {
00183 case QPainterPath::MoveToElement:
00184 if (!first)
00185 {
00186 ret.append(part);
00187 part = QPainterPath();
00188 }
00189 first = false;
00190 part.moveTo(elm.x, elm.y);
00191 break;
00192 case QPainterPath::LineToElement:
00193 part.lineTo(elm.x, elm.y);
00194 break;
00195 case QPainterPath::CurveToElement:
00196 part.cubicTo(elm.x, elm.y, path.elementAt(i+1).x, path.elementAt(i+1).y, path.elementAt(i+2).x, path.elementAt(i+2).y );
00197 break;
00198 default:
00199 break;
00200 }
00201 }
00202 if (!part.isEmpty())
00203 ret.append(part);
00204 return ret;
00205 }
00206
00207
00208
00209 FPoint projectPointOnLine(FPoint p, QPointF lineStart, QPointF lineEnd)
00210 {
00211 if (lineStart == lineEnd)
00212 return FPoint(lineStart.x(), lineStart.y());
00213
00214
00215 p -= FPoint(lineStart.x(), lineStart.y());
00216 lineEnd -= lineStart;
00217
00218 double lineLengthSquare = lineEnd.x() * lineEnd.x() + lineEnd.y() * lineEnd.y();
00219 double partOfLine = p.x() * lineEnd.x() + p.y() * lineEnd.y() / lineLengthSquare;
00220
00221 return FPoint(lineStart.x() + partOfLine * lineEnd.x(), lineStart.y() + partOfLine * lineEnd.y());
00222 }
00223
00224
00225 QPolygon FlattenPath(const FPointArray& ina, QList<uint> &Segs)
00226 {
00227 QPolygon cli, outa;
00228 Segs.clear();
00229 if (ina.size() > 3)
00230 {
00231 for (uint poi=0; poi<ina.size()-3; poi += 4)
00232 {
00233 if (ina.point(poi).x() > 900000)
00234 {
00235
00236 Segs.append(outa.size());
00237 continue;
00238 }
00239 FPoint a1 = ina.point(poi);
00240 FPoint a2 = ina.point(poi+1);
00241 FPoint a3 = ina.point(poi+3);
00242 FPoint a4 = ina.point(poi+2);
00243 QPainterPath Bez;
00244 Bez.moveTo(a1.x(), a1.y());
00245 Bez.cubicTo(a2.x(), a2.y(), a3.x(), a3.y(), a4.x(), a4.y());
00246 cli = Bez.toFillPolygon().toPolygon();
00247 if (cli.size() > 1)
00248 outa.putPoints(outa.size(), cli.size()-2, cli);
00249 else
00250 outa << QPoint(qRound(a4.x()), qRound(a4.y()));
00251 }
00252
00253
00254 }
00255 return outa;
00256 }
00257
00258 FPoint getMaxClipF(FPointArray* Clip)
00259 {
00260 FPoint np, rp;
00261 double mx = 0;
00262 double my = 0;
00263 uint clipSize=Clip->size();
00264 for (uint c = 0; c < clipSize; ++c)
00265 {
00266 np = Clip->point(c);
00267 if (np.x() > 900000)
00268 continue;
00269 if (np.x() > mx)
00270 mx = np.x();
00271 if (np.y() > my)
00272 my = np.y();
00273 }
00274 rp.setXY(mx, my);
00275 return rp;
00276 }
00277
00278 FPoint getMinClipF(FPointArray* Clip)
00279 {
00280 FPoint np, rp;
00281 double mx = 99999;
00282 double my = 99999;
00283 uint clipSize=Clip->size();
00284 for (uint c = 0; c < clipSize; ++c)
00285 {
00286 np = Clip->point(c);
00287 if (np.x() > 900000)
00288 continue;
00289 if (np.x() < mx)
00290 mx = np.x();
00291 if (np.y() < my)
00292 my = np.y();
00293 }
00294 rp.setXY(mx, my);
00295 return rp;
00296 }
00297
00298
00299 bool compareDouble(double a, double b)
00300 {
00301 if(a > -21473 && b > -21473 && a < 21474 && b < 21474)
00302 {
00303 long al = static_cast<long>(10000 * a);
00304 long bl = static_cast<long>(10000 * b);
00305 return al == bl;
00306 }
00307 return a == b;
00308 }
00309
00310
00311 double constrainAngle(double angle, double constrain)
00312 {
00313 double newAngle=angle;
00314 double constrainTo=constrain;
00315 if (newAngle<0.0)
00316 newAngle+=360.0;
00317 newAngle=qRound(angle/constrainTo)*constrainTo;
00318 if (newAngle==360.0)
00319 newAngle=0.0;
00320 return newAngle;
00321 }
00322
00323 double getRotationFromMatrix(QMatrix& matrix, double def)
00324 {
00325 double value = def;
00326 double norm = sqrt(fabs(matrix.det()));
00327 if (norm > 0.0000001)
00328 {
00329 double m11 = matrix.m11() / norm;
00330 double m12 = matrix.m12() / norm;
00331 double m21 = matrix.m21() / norm;
00332 double m22 = matrix.m22() / norm;
00333 if (fabs(m11) <= 1.0 && fabs(m12) <= 1.0 && fabs(m21) <= 1.0 && fabs(m22) <= 1.0)
00334 {
00335 QMatrix mat(m11, m12, m21, m22, 0, 0);
00336 if (abs(mat.det()-1.0) < 0.00001 && (mat.m12() == -mat.m21()))
00337 {
00338 double ac = acos(mat.m11());
00339 value = (mat.m21() >= 0.0) ? ac : (-ac);
00340 }
00341 }
00342 }
00343 return value;
00344 }
00345