View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0001055 | Scribus | Fonts | public | 2004-09-10 09:39 | 2005-04-16 09:03 |
Reporter | Zhang Weiwu | Assigned To | fschmid | ||
Priority | normal | Severity | feature | Reproducibility | always |
Status | closed | Resolution | fixed | ||
Platform | unix | OS | FreeBSD | OS Version | 4.10 |
Product Version | 1.2 | ||||
Fixed in Version | 1.3.0cvs | ||||
Summary | 0001055: Scribus is extremely CPU and memory hungry when processing documents with large fonts | ||||
Description | This is especially the case with CJK users. It's very frequently that a CJK font's size is over 10MB. top(1) said when CJK fonts is installed on the system (in my case, two Chinese fonts), scribus starts at large memory usage (in my case, 496MB), and loads very slow (my case: 4 minutes to start the app on PIII 600MHz). This is not the case when the developer test with their CJK fonts. Many developers would have installed fonts from arphic font package to test CJK capacity, but in productional environment the fonts in that package is likely not enough. AR PL Kai GB fonts contain only about 7,000 most frequently used Chinese ideographs, but there are actually more than 70,000 ideograph in Chinese, Korean and Japanese langauge, some users may love to use a wide-coverage font like Arial Unicode MS. The default Windows fonts contains about 20,000 Chinese ideographs, I did a test to install 3 default Windows (win2k simplified chinese version) fonts on X, launch scribus, it runs a while and quit for swap space used up, even no document is opened at all. Remove these fonts solves the problem. | ||||
Additional Information | You can obtain two extended arphic fonts (opensource) from ftp://debian.linux.org.tw/pub/3Anoppix/people/arne/ which can be used for test. Each of the two fonts contains around 20,000 ideographs, a very common number amone commercial fonts in China. | ||||
Tags | No tags attached. | ||||
Patch | |||||
related to | 0001046 | closed | scribus crash when exporting PDF |
|
I have changed this to a feature request, as we do not officially support CJK yet, though we really would like to. |
|
I found the problem, a check if the font is allready used is missing in AddFont(). I'm sure the devs will add it soon to CVS. |
2005-04-10 19:43
|
fpoints.diff (16,181 bytes)
Index: scribus/fpoint.cpp =================================================================== RCS file: /cvs/Scribus/scribus/fpoint.cpp,v retrieving revision 1.3 diff -u -p -r1.3 fpoint.cpp --- scribus/fpoint.cpp 16 Oct 2003 22:32:08 -0000 1.3 +++ scribus/fpoint.cpp 10 Apr 2005 21:10:23 -0000 @@ -17,16 +17,23 @@ #include "fpoint.h" -FPoint::FPoint(double x, double y) +FPoint::FPoint(double x, double y) : xp(x), yp(y) +{ +} + +FPoint::FPoint(QPoint p) : xp(p.x()), yp(p.y()) { - xp = x; - yp = y; } -FPoint::FPoint(QPoint p) +FPoint::FPoint(const FPoint & p) : xp(p.xp), yp(p.yp) { - xp = p.x(); - yp = p.y(); +} + +FPoint & FPoint::operator=(const FPoint & p) +{ + xp = p.xp; + yp = p.yp; + return *this; } double FPoint::x() Index: scribus/fpoint.h =================================================================== RCS file: /cvs/Scribus/scribus/fpoint.h,v retrieving revision 1.4.2.2 diff -u -p -r1.4.2.2 fpoint.h --- scribus/fpoint.h 22 Feb 2005 10:50:25 -0000 1.4.2.2 +++ scribus/fpoint.h 10 Apr 2005 21:10:23 -0000 @@ -29,7 +29,9 @@ public: FPoint() {}; FPoint(double x, double y); FPoint(QPoint p); - ~FPoint() {}; + FPoint(const FPoint & p); +// ~FPoint() {}; + FPoint & operator=(const FPoint & rhs); double x(); double y(); void setX(double x); @@ -43,6 +45,7 @@ public: friend inline const FPoint operator*( const FPoint &, const double & ); friend inline const FPoint operator*( const double &, const FPoint & ); friend inline const double operator*( const FPoint &a, const FPoint &b ); + friend class FPointArray; private: double xp; Index: scribus/fpointarray.cpp =================================================================== RCS file: /cvs/Scribus/scribus/fpointarray.cpp,v retrieving revision 1.5.2.4 diff -u -p -r1.5.2.4 fpointarray.cpp --- scribus/fpointarray.cpp 17 Mar 2005 23:19:32 -0000 1.5.2.4 +++ scribus/fpointarray.cpp 10 Apr 2005 21:10:23 -0000 @@ -21,20 +21,80 @@ using namespace std; +FPointArray FPointArray::copy() const +{ + FPointArray tmp; + tmp.duplicate(*this); + tmp.count = count; + tmp.capacity = capacity; +// qDebug(QString("copy(): count=%1 capacity=%2 size=%3").arg(tmp.count).arg(tmp.capacity).arg(tmp. QMemArray<FPoint>::size())); + return tmp; +} + + +FPointArray & FPointArray::operator=( const FPointArray &a ) +{ + assign( a ); + count = a.count; + capacity = a.capacity; +// qDebug(QString("operator=(): count=%1 capacity=%2 size=%3").arg(count).arg(capacity).arg(QMemArray<FPoint>::size())); + return *this; +} + + +/* optimized for speed: + * never shrink + * when growing, try to double size + * if capacity permits, just increase count + */ +bool FPointArray::resize(uint newCount) +{ + if (newCount <= capacity) { + if (newCount < 0) { + qDebug(QString("resize(): newcount=%1 this=%2").arg(newCount).arg(reinterpret_cast<long>(this), 0, 16)); + count = 0; + } + else + count = newCount; + return true; + } + else if (newCount <= 2*capacity && QMemArray<FPoint>::resize(2*capacity)) { + capacity *= 2; + count = newCount; + return true; + } + else if (QMemArray<FPoint>::resize(newCount)) { + capacity = newCount; + count = newCount; + return true; + } + else { + qDebug(QString("failed resize(): count=%1 capacity=%2 newCount=%3").arg(count).arg(capacity).arg(newCount)); + return false; + } +} + +uint FPointArray::size() const +{ + return count; +} + void FPointArray::setPoint(uint i, double x, double y) { - QMemArray<FPoint>::at( i ) = FPoint( x, y ); + FPoint *p = & QMemArray<FPoint>::at( i ); + p->xp = x; + p->yp = y; } void FPointArray::setPoint(uint i, FPoint p) { - setPoint(i, p.x(), p.y()); + setPoint(i, p.xp, p.yp); } bool FPointArray::setPoints( int nPoints, double firstx, double firsty, ... ) { va_list ap; - if ( !resize(nPoints) ) + if ( !FPointArray::resize(nPoints) ) return false; setPoint( 0, firstx, firsty ); int i = 1; @@ -54,9 +114,9 @@ bool FPointArray::setPoints( int nPoints bool FPointArray::putPoints( int index, int nPoints, double firstx, double firsty, ... ) { va_list ap; - if ( index + nPoints > static_cast<int>(size()) ) + if ( index + nPoints > static_cast<int>(count) ) { - if ( !resize(index + nPoints) ) + if ( !FPointArray::resize(index + nPoints) ) return false; } if ( nPoints <= 0 ) @@ -78,18 +138,20 @@ bool FPointArray::putPoints( int index, bool FPointArray::putPoints( int index, int nPoints, const FPointArray & from, int fromIndex ) { - if ( index + nPoints > static_cast<int>(size()) ) + if ( index + nPoints > static_cast<int>(count) ) { // extend array - if ( !resize(index + nPoints) ) + if ( !FPointArray::resize(index + nPoints) ) return false; } if ( nPoints <= 0 ) return true; - int n = 0; - while( n < nPoints ) + Iterator p = begin(); + p += index; + ConstIterator q = from.begin(); + q += fromIndex; + while( --nPoints >= 0 ) { - setPoint( index+n, from[fromIndex+n] ); - n++; + *p++ = *q++; } return true; } @@ -117,112 +179,111 @@ QPoint FPointArray::pointQ(uint i) void FPointArray::translate( double dx, double dy ) { - FPoint *p = data(); - int i = size(); FPoint pt( dx, dy ); - while ( i-- ) - { + Iterator pend = begin(); + pend += count; + for (Iterator p = begin(); p != pend; p++) + { if (p->x() < 900000) - *p += pt; - p++; - } + *p += pt; + } } FPoint FPointArray::WidthHeight() { - if ( isEmpty() ) + qDebug(QString("WidthHeight(): count=%1 capacity=%2 size=%3").arg(count).arg(capacity).arg(QMemArray<FPoint>::size())); + if ( count == 0 ) return FPoint( 0.0, 0.0 ); // null rectangle - FPoint *pd = data(); + Iterator pd = begin(); + Iterator pend = begin(); + pend += count; double minx, maxx, miny, maxy; - minx = maxx = pd->x(); - miny = maxy = pd->y(); - pd++; - for ( int i=1; i < static_cast<int>(size()); ++i ) + minx = maxx = pd->xp; + miny = maxy = pd->yp; + for ( ++pd; pd != pend; ++pd ) { // find min+max x and y - if (pd->x() > 900000) + if (pd->xp > 900000) { - pd++; continue; } - if ( pd->x() < minx ) - minx = pd->x(); + if ( pd->xp < minx ) + minx = pd->xp; else - if ( pd->x() > maxx ) - maxx = pd->x(); + if ( pd->xp > maxx ) + maxx = pd->xp; if ( pd->y() < miny ) - miny = pd->y(); + miny = pd->yp; else - if ( pd->y() > maxy ) - maxy = pd->y(); - pd++; + if ( pd->yp > maxy ) + maxy = pd->yp; } return FPoint(maxx - minx,maxy - miny); } void FPointArray::map( QWMatrix m ) { - FPoint *p = data(); + const double m11 = m.m11(); + const double m12 = m.m12(); + const double m21 = m.m21(); + const double m22 = m.m22(); + const double dx = m.dx(); + const double dy = m.dy(); double mx, my; - int i = size(); - while ( i-- ) + Iterator pend = begin(); + pend += count; + for (Iterator p = begin(); p != pend; p++) { - if (p->x() > 900000) + if (p->xp > 900000) { - mx = p->x(); - my = p->y(); + mx = p->xp; + my = p->yp; } else { - mx = m.m11() * p->x() + m.m21() * p->y() + m.dx(); - my = m.m22() * p->y() + m.m12() * p->x() + m.dy(); + mx = m11 * p->xp + m21 * p->yp + dx; + my = m22 * p->yp + m12 * p->xp + dy; } - *p = FPoint(mx, my); - p++; + p->xp = mx; + p->yp = my; } } void FPointArray::setMarker() { - addPoint(999999.0, 999999.0); - addPoint(999999.0, 999999.0); - addPoint(999999.0, 999999.0); - addPoint(999999.0, 999999.0); + addQuadPoint(999999.0, 999999.0, + 999999.0, 999999.0, + 999999.0, 999999.0, + 999999.0, 999999.0); } void FPointArray::addPoint(double x, double y) { - resize(size()+1); - setPoint(size()-1, FPoint(x, y)); + FPointArray::resize(count+1); + setPoint(count-1, x, y); } void FPointArray::addPoint(FPoint p) { - resize(size()+1); - setPoint(size()-1, p.x(), p.y()); + FPointArray::resize(count+1); + setPoint(count-1, p); } void FPointArray::addQuadPoint(double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4) { - resize(size()+1); - setPoint(size()-1, FPoint(x1, y1)); - resize(size()+1); - setPoint(size()-1, FPoint(x2, y2)); - resize(size()+1); - setPoint(size()-1, FPoint(x3, y3)); - resize(size()+1); - setPoint(size()-1, FPoint(x4, y4)); + FPointArray::resize(count+4); + setPoint(count-4, x1, y1); + setPoint(count-3, x2, y2); + setPoint(count-2, x3, y3); + setPoint(count-1, x4, y4); } void FPointArray::addQuadPoint(FPoint p1, FPoint p2, FPoint p3, FPoint p4) { - resize(size()+1); - setPoint(size()-1, p1.x(), p1.y()); - resize(size()+1); - setPoint(size()-1, p2.x(), p2.y()); - resize(size()+1); - setPoint(size()-1, p3.x(), p3.y()); - resize(size()+1); - setPoint(size()-1, p4.x(), p4.y()); + FPointArray::resize(count+4); + setPoint(count-4, p1); + setPoint(count-3, p2); + setPoint(count-2, p3); + setPoint(count-1, p4); } double FPointArray::lenPathSeg(int seg) Index: scribus/fpointarray.h =================================================================== RCS file: /cvs/Scribus/scribus/fpointarray.h,v retrieving revision 1.4.2.2 diff -u -p -r1.4.2.2 fpointarray.h --- scribus/fpointarray.h 22 Feb 2005 10:50:25 -0000 1.4.2.2 +++ scribus/fpointarray.h 10 Apr 2005 21:10:23 -0000 @@ -27,11 +27,14 @@ *@author Franz Schmid */ -class FPointArray : public QMemArray<FPoint> +class FPointArray : private QMemArray<FPoint> { public: - FPointArray() {}; - FPointArray(int size) : QMemArray<FPoint>(size) {}; + FPointArray() : count(0), capacity(0) {}; + FPointArray(int size) : QMemArray<FPoint>(size), count(size), capacity(size) {}; + FPointArray(const FPointArray &a) : QMemArray<FPoint>(a), count(a.count), capacity(a.capacity) {}; + uint size() const; + bool resize(uint newCount); void setPoint(uint i, double x, double y); void setPoint(uint i, FPoint p); bool setPoints( int nPoints, double firstx, double firsty, ... ); @@ -43,8 +46,8 @@ public: void translate( double dx, double dy ); FPoint WidthHeight(); void map(QWMatrix m); - FPointArray &operator=( const FPointArray &a ) { return (FPointArray&)assign( a ); } - FPointArray copy() const { FPointArray tmp; return *((FPointArray*)&tmp.duplicate(*this)); } + FPointArray &operator=( const FPointArray &a ); + FPointArray copy() const; void setMarker(); void addPoint(double x, double y); void addPoint(FPoint p); @@ -55,6 +58,9 @@ public: void pointTangentNormalAt( int seg, double t, FPoint* p, FPoint* tn, FPoint* n ); void pointDerivativesAt( int seg, double t, FPoint* p, FPoint* d1, FPoint* d2 ); ~FPointArray() {}; +private: + uint count; + uint capacity; }; #endif Index: scribus/pageitem.cpp =================================================================== RCS file: /cvs/Scribus/scribus/pageitem.cpp,v retrieving revision 1.121.2.102 diff -u -p -r1.121.2.102 pageitem.cpp --- scribus/pageitem.cpp 10 Apr 2005 13:38:38 -0000 1.121.2.102 +++ scribus/pageitem.cpp 10 Apr 2005 21:10:27 -0000 @@ -2047,16 +2047,16 @@ void PageItem::DrawObj_PathText(ScPainte dx = wide / 2.0; CurX += dx; ext = false; - while ( (seg < PoLine.count()-3) && (CurX > fsx + segLen)) + while ( (seg < PoLine.size()-3) && (CurX > fsx + segLen)) { fsx += segLen; seg += 4; - if (seg > PoLine.count()-3) + if (seg > PoLine.size()-3) break; segLen = PoLine.lenPathSeg(seg); ext = true; } - if (seg > PoLine.count()-3) + if (seg > PoLine.size()-3) break; if (CurX > fsx + segLen) break; @@ -2076,7 +2076,7 @@ void PageItem::DrawObj_PathText(ScPainte } else { - if( seg < PoLine.count()-3 ) + if( seg < PoLine.size()-3 ) { if (CurX > fsx + segLen) break; @@ -2364,7 +2364,10 @@ void PageItem::DrawZeichenS(ScPainter *p QWMatrix chma, chma2, chma3, chma4, chma5; chma.scale(csi, csi); chma5.scale(p->zoomFactor(), p->zoomFactor()); +//qDebug(QString("DrawZeichenS(): before count=%1 capacity=%2").arg(hl->ZFo->GlyphArray[chr].Outlines.size()).arg(reinterpret_cast<QMemArray<FPoint>*>(&hl->ZFo->GlyphArray[chr].Outlines)->size())); + FPointArray gly = hl->ZFo->GlyphArray[chr].Outlines.copy(); +//qDebug(QString("DrawZeichenS(): after count=%1 capacity=%2").arg(gly.size()).arg(reinterpret_cast<QMemArray<FPoint>*>(&gly)->size())); if (gly.size() > 3) { chma2.scale(hl->scale / 100.0, 1); Index: scribus/scribusview.cpp =================================================================== RCS file: /cvs/Scribus/scribus/scribusview.cpp,v retrieving revision 1.76.2.155 diff -u -p -r1.76.2.155 scribusview.cpp --- scribus/scribusview.cpp 10 Apr 2005 13:38:38 -0000 1.76.2.155 +++ scribus/scribusview.cpp 10 Apr 2005 21:10:39 -0000 @@ -1423,7 +1427,7 @@ void ScribusView::contentsMouseReleaseEv Clip = b->ContourLine; else Clip = b->PoLine; - for (uint a = 0; a < Clip.count(); ++a) + for (uint a = 0; a < Clip.size(); ++a) { if (Clip.point(a).x() > 900000) continue; Index: scribus/util.cpp =================================================================== RCS file: /cvs/Scribus/scribus/util.cpp,v retrieving revision 1.52.2.54 diff -u -p -r1.52.2.54 util.cpp --- scribus/util.cpp 3 Apr 2005 07:21:29 -0000 1.52.2.54 +++ scribus/util.cpp 10 Apr 2005 21:10:46 -0000 @@ -1165,10 +1166,10 @@ static void parseRessourceData( QDataStr } else { - clip2.addPoint(FPoint(frac4 * header.width, frac3 * header.height)); - clip2.addPoint(FPoint(frac2 * header.width, frac1 * header.height)); - clip2.addPoint(FPoint(frac4 * header.width, frac3 * header.height)); - clip2.addPoint(FPoint(frac6 * header.width, frac5 * header.height)); + clip2.addPoint(frac4 * header.width, frac3 * header.height); + clip2.addPoint(frac2 * header.width, frac1 * header.height); + clip2.addPoint(frac4 * header.width, frac3 * header.height); + clip2.addPoint(frac6 * header.width, frac5 * header.height); } pathOpen = true; first = false; @@ -2489,7 +2490,7 @@ FPointArray RegularPolygonF(double w, do double di = factor; double mx = 0; double my = 0; - FPointArray pts = FPointArray(); + FPointArray pts; for (uint x = 0; x < cx; ++x) { sc = seg * x + 180.0 + rota; @@ -3014,8 +3085,8 @@ int traceMoveto( FT_Vector *to, FPointAr } else FirstM = false; - composite->addPoint(FPoint(tox, toy)); - composite->addPoint(FPoint(tox, toy)); + composite->addPoint(tox, toy); + composite->addPoint(tox, toy); firstP = FPoint(tox, toy); return 0; } @@ -3037,10 +3108,10 @@ int traceLineto( FT_Vector *to, FPointAr if ((b1 == n1) && (b2 == n2) && (b3 == n3) && (b4 == n4)) return 0; } - composite->addPoint(FPoint(tox, toy)); - composite->addPoint(FPoint(tox, toy)); - composite->addPoint(FPoint(tox, toy)); - composite->addPoint(FPoint(tox, toy)); + composite->addQuadPoint(tox, toy, + tox, toy, + tox, toy, + tox, toy); return 0; } @@ -3063,10 +3134,10 @@ int traceQuadraticBezier( FT_Vector *con if ((b1 == n1) && (b2 == n2) && (b3 == n3) && (b4 == n4)) return 0; } - composite->addPoint(FPoint(x2, y2)); - composite->addPoint(FPoint(x1, y1)); - composite->addPoint(FPoint(x2, y2)); - composite->addPoint(FPoint(x2, y2)); + composite->addQuadPoint(x2, y2, + x1, y1, + x2, y2, + x2, y2); return 0; } @@ -3092,10 +3163,10 @@ int traceCubicBezier( FT_Vector *p, FT_V return 0; } composite->setPoint(composite->size()-1, FPoint(x1, y1)); - composite->addPoint(FPoint(x3, y3)); - composite->addPoint(FPoint(x2, y2)); - composite->addPoint(FPoint(x3, y3)); - composite->addPoint(FPoint(x3, y3)); + composite->addQuadPoint(x3, y3, + x2, y2, + x3, y3, + x3, y3); return 0; } @@ -3113,7 +3184,9 @@ FPointArray traceChar(FT_Face face, uint { bool error = false; FT_UInt glyphIndex; - FPointArray pts, pts2; + //AV: not threadsave, but tracechar is only used in ReadMetrics() and fontSample() + static FPointArray pts; + FPointArray pts2; pts.resize(0); pts2.resize(0); firstP = FPoint(0,0); @@ -3149,6 +3222,7 @@ FPointArray traceChar(FT_Face face, uint pts.map(ma); pts.translate(0, chs); pts2.putPoints(0, pts.size()-2, pts, 0); + return pts2; } |
|
Uploaded fpoints.diff (for cvs 1.3.0) This patch includes optimizations for the fpointarray structure which is used when reading font metrics. Should speed up ReadMetrics() by factor 2 Memory usage should stay about the same (not tested) |
Date Modified | Username | Field | Change |
---|---|---|---|
2004-09-10 09:39 | Zhang Weiwu | New Issue | |
2004-09-10 14:46 |
|
Note Added: 0002354 | |
2004-09-10 14:46 |
|
Severity | major => feature |
2004-09-10 14:46 |
|
Status | new => feedback |
2004-09-10 14:46 |
|
Category | General => Fonts |
2004-09-24 17:38 |
|
Relationship added | related to 0001046 |
2005-03-25 05:44 | TomK32 | Note Added: 0003967 | |
2005-04-10 19:43 | avox | File Added: fpoints.diff | |
2005-04-10 19:47 | avox | Note Added: 0004225 | |
2005-04-10 19:49 | avox | Note Edited: 0004225 | |
2005-04-10 21:40 | cbradney | Summary | scribus is extermely CPU and memory hungary when processing documents with large fonts => Scribus is extermely CPU and memory hungry when processing documents with large fonts |
2005-04-10 21:42 | cbradney | Summary | Scribus is extermely CPU and memory hungry when processing documents with large fonts => Scribus is extremely CPU and memory hungry when processing documents with large fonts |
2005-04-12 09:54 | fschmid | Status | feedback => resolved |
2005-04-12 09:54 | fschmid | Fixed in Version | => 1.3.0cvs |
2005-04-12 09:54 | fschmid | Resolution | open => fixed |
2005-04-12 09:54 | fschmid | Assigned To | => fschmid |
2005-04-16 09:03 | cbradney | Status | resolved => closed |