View Issue Details

IDProjectCategoryView StatusLast Update
0001055ScribusFontspublic2005-04-16 09:03
ReporterZhang Weiwu Assigned Tofschmid  
PrioritynormalSeverityfeatureReproducibilityalways
Status closedResolutionfixed 
PlatformunixOSFreeBSDOS Version4.10
Product Version1.2 
Fixed in Version1.3.0cvs 
Summary0001055: Scribus is extremely CPU and memory hungry when processing documents with large fonts
DescriptionThis 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 InformationYou 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.
TagsNo tags attached.
Patch

Relationships

related to 0001046 closed scribus crash when exporting PDF 

Activities

plinnell

2004-09-10 14:46

viewer   ~0002354

I have changed this to a feature request, as we do not officially support CJK yet, though we really would like to.

TomK32

2005-03-25 05:44

reporter   ~0003967

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;
 }
 
fpoints.diff (16,181 bytes)   

avox

2005-04-10 19:47

administrator   ~0004225

Last edited: 2005-04-10 19:49

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)

Issue History

Date Modified Username Field Change
2004-09-10 09:39 Zhang Weiwu New Issue
2004-09-10 14:46 plinnell Note Added: 0002354
2004-09-10 14:46 plinnell Severity major => feature
2004-09-10 14:46 plinnell Status new => feedback
2004-09-10 14:46 plinnell Category General => Fonts
2004-09-24 17:38 plinnell 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