Subversion Repositories Scribus

Compare Revisions

Regard whitespace Rev 5978 → Rev 5979

/branches/Version13x/Scribus/scribus/fonts/scface_ttf.cpp
0,0 → 1,210
/*
For general Scribus (>=1.3.2) copyright and licensing information please refer
to the COPYING file provided with the program. Following this notice may exist
a copyright and/or license notice that predates the release of Scribus 1.3.2
for which a new license (GPL+exception) is in place.
*/
 
#include <qfile.h>
#include <qstring.h>
#include <qobject.h>
 
#include <sys/types.h>
 
#include "fonts/scface_ttf.h"
#include "fonts/scfontmetrics.h"
#include "util.h"
#include "scconfig.h"
 
 
 
namespace {
uint word(QByteArray const & bb, uint pos)
{
unsigned char * pp = reinterpret_cast<unsigned char*>(bb.data()) + pos;
return pp[0] << 24 | pp[1] << 16 | pp[2] << 8 | pp[3];
}
uint word16(QByteArray const & bb, uint pos)
{
unsigned char * pp = reinterpret_cast<unsigned char*>(bb.data()) + pos;
return pp[0] << 8 | pp[1];
}
QString tag(QByteArray const & bb, uint pos)
{
char buf[5] = "1234";
buf[0] = bb.data()[pos];
buf[1] = bb.data()[pos+1];
buf[2] = bb.data()[pos+2];
buf[3] = bb.data()[pos+3];
return buf;
}
bool copy(QByteArray & dst, uint to, QByteArray & src, uint from, uint len)
{
if (!dst.data())
return false;
if (!src.data())
return false;
if (to + len > dst.size())
return false;
if (from + len > src.size())
return false;
memcpy(dst.data() + to, src.data() + from, len);
return true;
}
} //namespace
 
 
void ScFace_ttf::RawData(QByteArray & bb) {
if (formatCode == ScFace::TTCF) {
QByteArray coll;
FtFace::RawData(coll);
// access table for faceIndex
if (faceIndex >= static_cast<int>(word(coll, 8)))
{
bb.resize(0);
return;
}
static const uint OFFSET_TABLE_LEN = 12;
static const uint TDIR_ENTRY_LEN = 16;
uint faceOffset = word(coll, 12 + 4 * faceIndex);
uint nTables = word16(coll, faceOffset + 4);
sDebug(QObject::tr("extracting face %1 from font %2 (offset=%3, nTables=%4)").arg(faceIndex).arg(fontFile).arg(faceOffset).arg(nTables));
uint headerLength = OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * nTables;
uint tableLengths = 0;
// sum table lengths incl padding
for (uint i=0; i < nTables; ++i)
{
tableLengths += word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12);
tableLengths = (tableLengths+3) & ~3;
}
bb.resize(headerLength + tableLengths);
if (! bb.data())
return;
// write header
sDebug(QObject::tr("memcpy header: %1 %2 %3").arg(0).arg(faceOffset).arg(headerLength));
if (!copy(bb, 0, coll, faceOffset, headerLength))
return;
 
uint pos = headerLength;
for (uint i=0; i < nTables; ++i)
{
uint tableSize = word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 12);
uint tableStart = word(coll, faceOffset + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8);
sDebug(QObject::tr("table '%1'").arg(tag(coll, tableStart)));
sDebug(QObject::tr("memcpy table: %1 %2 %3").arg(pos).arg(tableStart).arg(tableSize));
if (!copy(bb, pos, coll, tableStart, tableSize)) break;
// write new offset to table entry
sDebug(QObject::tr("memcpy offset: %1 %2 %3").arg(OFFSET_TABLE_LEN + TDIR_ENTRY_LEN*i + 8).arg(pos).arg(4));
memcpy(bb.data() + OFFSET_TABLE_LEN + TDIR_ENTRY_LEN * i + 8, &pos, 4);
pos += tableSize;
// pad
while ((pos & 3) != 0)
bb.data()[pos++] = '\0';
}
}
else if (formatCode == ScFace::TYPE42) {
FtFace::RawData(bb);
}
else {
FtFace::RawData(bb);
}
}
 
bool ScFace_ttf::EmbedFont(QString &str)
{
if (formatCode == ScFace::TYPE42) {
//easy:
QByteArray bb;
FtFace::RawData(bb);
str += bb;
return true;
}
QString tmp4;
QString tmp2 = "";
QString tmp3 = "";
int counter = 0;
char *buf[50];
FT_ULong charcode;
FT_UInt gindex;
FT_Face face = ftFace();
if (!face) {
return false;
}
const FT_Stream fts = face->stream;
if (ftIOFunc(fts, 0L, NULL, 0)) {
return(false);
}
str+="%!PS-TrueTypeFont\n";
str+="11 dict begin\n";
str+="/FontName /" + psName + " def\n";
str+="/Encoding /ISOLatin1Encoding where {pop ISOLatin1Encoding} {StandardEncoding} ifelse def\n";
str+="/PaintType 0 def\n/FontMatrix [1 0 0 1 0 0] def\n";
str+="/FontBBox ["+FontBBox+"] def\n";
str+="/FontType 42 def\n";
str+="/FontInfo 8 dict dup begin\n";
str+="/FamilyName (" + psName + ") def\n";
str+="end readonly def\n";
unsigned char *tmp = new unsigned char[65535];
int length;
char linebuf[80];
str += "/sfnts [";
int poso=0;
do {
int posi=0;
length= fts->size - fts->pos;
if (length > 65534) {
length = 65534;
}
if (!ftIOFunc(fts, 0L, tmp, length))
{
str+="\n<\n";
for (int j = 0; j < length; j++)
{
unsigned char u=tmp[posi];
linebuf[poso]=((u >> 4) & 15) + '0';
if(u>0x9f) linebuf[poso]+='a'-':';
++poso;
u&=15; linebuf[poso]=u + '0';
if(u>0x9) linebuf[poso]+='a'-':';
++posi;
++poso;
if (poso > 70)
{
linebuf[poso++]='\n';
linebuf[poso++]=0;
str += linebuf;
poso = 0;
}
}
linebuf[poso++]=0;
str += linebuf;
poso = 0;
str += "00\n>";
}
else {
sDebug(QObject::tr("Font %1 is broken (read stream), no embedding").arg(fontFile).arg(gindex));
str += "\n] def\n";
status = QMAX(status,ScFace::BROKENGLYPHS);
return false;
}
} while (length==65534);
str += "\n] def\n";
delete tmp;
gindex = 0;
charcode = FT_Get_First_Char(face, &gindex );
while (gindex != 0)
{
FT_Get_Glyph_Name(face, gindex, buf, 50);
tmp2 += "/"+QString(reinterpret_cast<char*>(buf))+" "+tmp3.setNum(gindex)+" def\n";
charcode = FT_Get_Next_Char(face, charcode, &gindex );
counter++;
}
tmp4.setNum(counter);
str += "/CharStrings " + tmp4 + " dict dup begin\n"+tmp2;
str += "end readonly def\n";
str += "FontName currentdict end definefont pop\n";
return(true);
}
 
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: Version13x/Scribus/scribus/fonts/scfontmetrics.cpp
===================================================================
--- Version13x/Scribus/scribus/fonts/scfontmetrics.cpp (nonexistent)
+++ Version13x/Scribus/scribus/fonts/scfontmetrics.cpp (revision 5979)
@@ -0,0 +1,612 @@
+/*
+For general Scribus (>=1.3.2) copyright and licensing information please refer
+to the COPYING file provided with the program. Following this notice may exist
+a copyright and/or license notice that predates the release of Scribus 1.3.2
+for which a new license (GPL+exception) is in place.
+*/
+#include <qpainter.h>
+#include <qcolor.h>
+#include <qwmatrix.h>
+#include <qpixmap.h>
+#include <qstringlist.h>
+#include <qmap.h>
+#include <qregexp.h>
+
+#include "scribusdoc.h"
+#include "scfonts.h"
+#include "style.h"
+#include "scfontmetrics.h"
+#include "scpainter.h"
+#include "fpoint.h"
+#include "fpointarray.h"
+#include "page.h"
+#include "util.h"
+
+// this code contains a set of font related functions
+// that don't really fit within ScFonts.
+
+static FPoint firstP;
+static bool FirstM;
+static QMap<FT_ULong, QString> adobeGlyphNames;
+static const char* table[] = {
+//#include "glyphnames.txt.q"
+ NULL};
+
+// private functions
+static void readAdobeGlyphNames();
+static QString adobeGlyphName(FT_ULong charcode);
+static int traceMoveto( FT_Vector *to, FPointArray *composite );
+static int traceLineto( FT_Vector *to, FPointArray *composite );
+static int traceQuadraticBezier( FT_Vector *control, FT_Vector *to, FPointArray *composite );
+static int traceCubicBezier( FT_Vector *p, FT_Vector *q, FT_Vector *to, FPointArray *composite );
+
+FT_Outline_Funcs OutlineMethods =
+ {
+ (FT_Outline_MoveTo_Func) traceMoveto,
+ (FT_Outline_LineTo_Func) traceLineto,
+ (FT_Outline_ConicTo_Func) traceQuadraticBezier,
+ (FT_Outline_CubicTo_Func) traceCubicBezier,
+ 0,
+ 0
+ };
+
+
+const double FTSCALE = 64.0;
+
+
+int setBestEncoding(FT_Face face)
+{
+ FT_ULong charcode;
+ FT_UInt gindex;
+ bool foundEncoding = false;
+ int countUniCode = 0;
+ int chmapUniCode = -1;
+ int chmapCustom = -1;
+ int retVal = 0;
+ //FT_CharMap defaultEncoding = face->charmap;
+// int defaultchmap=face->charmap ? FT_Get_Charmap_Index(face->charmap) : 0;
+// Since the above function is only available in FreeType 2.1.10 its replaced by
+// the following line, assuming that the default charmap has the index 0
+ int defaultchmap = 0;
+ for(int u = 0; u < face->num_charmaps; u++)
+ {
+ if (face->charmaps[u]->encoding == FT_ENCODING_UNICODE )
+ {
+ FT_Set_Charmap(face, face->charmaps[u]);
+ chmapUniCode = u;
+ gindex = 0;
+ charcode = FT_Get_First_Char( face, &gindex );
+ while ( gindex != 0 )
+ {
+ countUniCode++;
+ charcode = FT_Get_Next_Char( face, charcode, &gindex );
+ }
+ }
+ if (face->charmaps[u]->encoding == FT_ENCODING_ADOBE_CUSTOM)
+ {
+ chmapCustom = u;
+ foundEncoding = true;
+ retVal = 1;
+ break;
+ }
+ else if (face->charmaps[u]->encoding == FT_ENCODING_MS_SYMBOL)
+ {
+ chmapCustom = u;
+ foundEncoding = true;
+ retVal = 2;
+ break;
+ }
+ }
+ int mapToSet=defaultchmap;
+ if (chmapUniCode>0 && countUniCode >= face->num_glyphs-1)
+ {
+ mapToSet=chmapUniCode;
+ //FT_Set_Charmap(face, face->charmaps[chmapUniCode]);
+ retVal = 0;
+ }
+ else
+ if (foundEncoding)
+ {
+ mapToSet=chmapCustom;
+ //FT_Set_Charmap(face, face->charmaps[chmapCustom]);
+ }
+ else
+ {
+ mapToSet=defaultchmap;
+ //FT_Set_Charmap(face, defaultEncoding);
+ retVal = 0;
+ }
+
+ //Fixes #2199, missing glyphs from 1.2.1->1.2.2
+ //If the currently wanted character map is not already Unicode...
+ //if (FT_Get_Charmap_Index(face->charmap)!=chmapUniCode)
+ if (mapToSet!=chmapUniCode)
+ {
+ //Change map so we can count the chars in it
+ FT_Set_Charmap(face, face->charmaps[mapToSet]);
+ //Count the characters in the current map
+ gindex = 0;
+ int countCurrMap=0;
+ charcode = FT_Get_First_Char( face, &gindex );
+ while ( gindex != 0 )
+ {
+ countCurrMap++;
+ charcode = FT_Get_Next_Char( face, charcode, &gindex );
+ }
+ //If the last Unicode map we found before has more characters,
+ //then set it to be the current map.
+ if (countUniCode>countCurrMap)
+ {
+ mapToSet=chmapUniCode;
+ //FT_Set_Charmap(face, face->charmaps[chmapUniCode]);
+ retVal = 0;
+ }
+ }
+// if (face->charmap == NULL || mapToSet!=FT_Get_Charmap_Index(face->charmap))
+ FT_Set_Charmap(face, face->charmaps[mapToSet]);
+ return retVal;
+}
+
+FPointArray traceGlyph(FT_Face face, FT_UInt glyphIndex, int chs, double *x, double *y, bool *err)
+{
+ bool error = false;
+ //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);
+ FirstM = true;
+ error = FT_Set_Char_Size( face, 0, chs*6400, 72, 72 );
+ if (error)
+ {
+ *err = error;
+ return pts2;
+ }
+ if (glyphIndex == 0)
+ {
+ *err = true;
+ return pts2;
+ }
+ double uniEM = static_cast<double>(face->units_per_EM);
+ error = FT_Load_Glyph( face, glyphIndex, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP );
+ if (error)
+ {
+ *err = error;
+ return pts2;
+ }
+ error = FT_Outline_Decompose(&face->glyph->outline, &OutlineMethods, reinterpret_cast<void*>(&pts));
+ if (error)
+ {
+ *err = error;
+ return pts2;
+ }
+ *x = face->glyph->metrics.horiBearingX / 6400.0;
+ *y = face->glyph->metrics.horiBearingY / 6400.0;
+ QWMatrix ma;
+ ma.scale(0.01, -0.01);
+ pts.map(ma);
+ pts.translate(0, chs);
+ pts2.putPoints(0, pts.size()-2, pts, 0);
+
+ return pts2;
+}
+
+
+FPointArray traceChar(FT_Face face, uint chr, int chs, double *x, double *y, bool *err)
+{
+ bool error = false;
+ FT_UInt glyphIndex;
+ error = FT_Set_Char_Size( face, 0, chs*64, 72, 72 );
+ if (error)
+ {
+ *err = error;
+ return FPointArray();
+ }
+ glyphIndex = FT_Get_Char_Index(face, chr);
+ return traceGlyph(face, glyphIndex, chs, x, y, err);
+}
+
+
+QPixmap FontSample(ScFace * fnt, int s, QString ts, QColor back, bool force)
+{
+ FT_Face face;
+ FT_Library library;
+ double x, y, ymax;
+ bool error;
+ int pen_x;
+ FPoint gp;
+ error = FT_Init_FreeType( &library );
+ error = FT_New_Face( library, QFile::encodeName(fnt->fontFilePath()), fnt->faceIndex(), &face );
+ int encode = setBestEncoding(face);
+ double uniEM = static_cast<double>(face->units_per_EM);
+ int h = qRound(face->height / uniEM) * s + 1;
+ double a = static_cast<double>(face->descender) / uniEM * s + 1;
+ int w = qRound((face->bbox.xMax - face->bbox.xMin) / uniEM) * s * (ts.length()+1);
+ if (w < 1)
+ w = s * (ts.length()+1);
+ if (h < 1)
+ h = s;
+ QPixmap pm(w, h);
+ pm.fill();
+ pen_x = 0;
+ ymax = 0.0;
+ ScPainter *p = new ScPainter(&pm, pm.width(), pm.height());
+ p->setFillMode(1);
+ p->setLineWidth(0.0);
+ p->setBrush(back);
+ p->drawRect(0.0, 0.0, static_cast<double>(w), static_cast<double>(h));
+ p->setBrush(Qt::black);
+ FPointArray gly;
+ uint dv;
+ dv = ts[0].unicode();
+ error = false;
+ gly = traceChar(face, dv, s, &x, &y, &error);
+ if (((encode != 0) || (error)) && (!force))
+ {
+ error = false;
+ FT_ULong charcode;
+ FT_UInt gindex;
+ gindex = 0;
+ charcode = FT_Get_First_Char(face, &gindex );
+ for (uint n = 0; n < ts.length(); ++n)
+ {
+ gly = traceChar(face, charcode, s, &x, &y, &error);
+ if (error)
+ break;
+ if (gly.size() > 3)
+ {
+ gly.translate(static_cast<double>(pen_x) / FTSCALE, a);
+ gp = getMaxClipF(&gly);
+ ymax = QMAX(ymax, gp.y());
+ p->setupPolygon(&gly);
+ p->fillPath();
+ }
+ pen_x += face->glyph->advance.x;
+ charcode = FT_Get_Next_Char(face, charcode, &gindex );
+ if (gindex == 0)
+ break;
+ }
+ }
+ else
+ {
+ for (uint n = 0; n < ts.length(); ++n)
+ {
+ dv = ts[n].unicode();
+ error = false;
+ gly = traceChar(face, dv, s, &x, &y, &error);
+ if (gly.size() > 3)
+ {
+ gly.translate(static_cast<double>(pen_x) / FTSCALE, a);
+ gp = getMaxClipF(&gly);
+ ymax = QMAX(ymax, gp.y());
+ p->setupPolygon(&gly);
+ p->fillPath();
+ }
+ pen_x += face->glyph->advance.x;
+ }
+ }
+ p->end();
+ pm.resize(QMIN(qRound(gp.x()), w), QMIN(qRound(ymax), h));
+ delete p;
+ FT_Done_FreeType( library );
+ return pm;
+}
+
+/** Same as FontSample() with \n strings support added.
+09/26/2004 petr vanek
+
+QPixmap fontSamples(ScFace * fnt, int s, QString ts, QColor back)
+{
+ QStringList lines = QStringList::split("\n", ts);
+ QPixmap ret(640, 480);
+ QPixmap sample;
+ QPainter *painter = new QPainter(&ret);
+ int y = 0;
+ int x = 0;
+ ret.fill(back);
+ for ( QStringList::Iterator it = lines.begin(); it != lines.end(); ++it )
+ {
+ sample = FontSample(fnt, s, *it, back);
+ if (!sample.isNull())
+ painter->drawPixmap(0, y, sample, 0, 0);
+ y = y + sample.height();
+ if (x < sample.width())
+ x = sample.width();
+ } // for
+ delete(painter);
+ QPixmap final(x, y);
+ if ((x != 0) && (y != 0))
+ {
+ QPainter *fpainter = new QPainter(&final);
+ fpainter->drawPixmap(0, 0, ret, 0, 0, x, y);
+ delete(fpainter);
+ }
+ return final;
+}
+*/
+
+bool GlyNames(FT_Face face, QMap<QChar, std::pair<uint, QString> >& GList)
+{
+ bool error;
+ char buf[50];
+ FT_ULong charcode;
+ FT_UInt gindex;
+ setBestEncoding(face);
+ gindex = 0;
+ charcode = FT_Get_First_Char(face, &gindex );
+ const bool hasPSNames = FT_HAS_GLYPH_NAMES(face);
+ if (adobeGlyphNames.empty())
+ readAdobeGlyphNames();
+ while (gindex != 0)
+ {
+ bool notfound = true;
+ if (hasPSNames)
+ notfound = FT_Get_Glyph_Name(face, gindex, &buf, 50);
+
+ // just in case FT gives empty string or ".notdef"
+ // no valid glyphname except ".notdef" starts with '.'
+ if (notfound || buf[0] == '\0' || buf[0] == '.')
+ GList.insert(QChar(static_cast<uint>(charcode)), std::make_pair(gindex,adobeGlyphName(charcode)));
+ else
+ GList.insert(QChar(static_cast<uint>(charcode)), std::make_pair(gindex,QString(reinterpret_cast<char*>(buf))));
+
+ charcode = FT_Get_Next_Char(face, charcode, &gindex );
+ }
+ return true;
+}
+/*
+bool GlyIndex(ScFace * fnt, QMap<uint, PDFlib::GlNamInd> *GListInd)
+{
+ struct PDFlib::GlNamInd gln;
+ bool error;
+ char buf[50];
+ FT_Library library;
+ FT_Face face;
+ FT_ULong charcode;
+ FT_UInt gindex;
+ uint counter1 = 32;
+ uint counter2 = 0;
+ error = FT_Init_FreeType(&library);
+ error = FT_New_Face(library, QFile::encodeName(fnt->fontFilePath()), fnt->faceIndex(), &face);
+ setBestEncoding(face);
+ gindex = 0;
+ charcode = FT_Get_First_Char(face, &gindex );
+ const bool hasPSNames = FT_HAS_GLYPH_NAMES(face);
+ if (adobeGlyphNames.empty())
+ readAdobeGlyphNames();
+ while (gindex != 0)
+ {
+ bool notfound = true;
+ if (hasPSNames)
+ notfound = FT_Get_Glyph_Name(face, gindex, buf, 50);
+
+ // just in case FT gives empty string or ".notdef"
+ // no valid glyphname except ".notdef" starts with '.'
+ if (notfound || buf[0] == '\0' || buf[0] == '.')
+ gln.Name = "/" + adobeGlyphName(charcode);
+ else
+ gln.Name = "/" + QString(buf);
+
+ gln.Code = counter1 + counter2;
+ GListInd->insert(charcode, gln);
+ charcode = FT_Get_Next_Char(face, charcode, &gindex );
+ counter1++;
+ if (counter1 > 255)
+ {
+ counter1 = 32;
+ counter2 += 0x100;
+ }
+ }
+ FT_Done_FreeType( library );
+ return true;
+}
+*/
+
+static int traceMoveto( FT_Vector *to, FPointArray *composite )
+{
+ double tox = ( to->x / FTSCALE );
+ double toy = ( to->y / FTSCALE );
+ if (!FirstM)
+ {
+ composite->addPoint(firstP);
+ composite->addPoint(firstP);
+ composite->setMarker();
+ }
+ else
+ FirstM = false;
+ composite->addPoint(tox, toy);
+ composite->addPoint(tox, toy);
+ firstP.setXY(tox, toy);
+ return 0;
+}
+
+static int traceLineto( FT_Vector *to, FPointArray *composite )
+{
+ double tox = ( to->x / FTSCALE );
+ double toy = ( to->y / FTSCALE );
+ if ( !composite->hasLastQuadPoint(tox, toy, tox, toy, tox, toy, tox, toy))
+ composite->addQuadPoint(tox, toy, tox, toy, tox, toy, tox, toy);
+ return 0;
+}
+
+static int traceQuadraticBezier( FT_Vector *control, FT_Vector *to, FPointArray *composite )
+{
+ double x1 = ( control->x / FTSCALE );
+ double y1 = ( control->y / FTSCALE );
+ double x2 = ( to->x / FTSCALE );
+ double y2 = ( to->y / FTSCALE );
+ if ( !composite->hasLastQuadPoint(x2, y2, x1, y1, x2, y2, x2, y2))
+ composite->addQuadPoint(x2, y2, x1, y1, x2, y2, x2, y2);
+ return 0;
+}
+
+static int traceCubicBezier( FT_Vector *p, FT_Vector *q, FT_Vector *to, FPointArray *composite )
+{
+ double x1 = ( p->x / FTSCALE );
+ double y1 = ( p->y / FTSCALE );
+ double x2 = ( q->x / FTSCALE );
+ double y2 = ( q->y / FTSCALE );
+ double x3 = ( to->x / FTSCALE );
+ double y3 = ( to->y / FTSCALE );
+ if ( !composite->hasLastQuadPoint(x3, y3, x2, y2, x3, y3, x3, y3) )
+ {
+ composite->setPoint(composite->size()-1, FPoint(x1, y1));
+ composite->addQuadPoint(x3, y3, x2, y2, x3, y3, x3, y3);
+ }
+ return 0;
+}
+
+/// init the Adobe Glyph List
+void readAdobeGlyphNames() {
+ adobeGlyphNames.clear();
+ QRegExp pattern("(\\w*);([0-9A-Fa-f]{4})");
+ for (uint i=0; table[i]; ++i) {
+ if (pattern.search(table[i]) >= 0) {
+ FT_ULong unicode = pattern.cap(2).toULong(0, 16);
+ qDebug("%s", QString("reading glyph name %1 fo unicode %2(%3)").arg(pattern.cap(1)).arg(unicode).arg(pattern.cap(2)).ascii());
+ adobeGlyphNames.insert(unicode, pattern.cap(1));
+ }
+ }
+}
+
+
+/// if in AGL, use that name, else use "uni1234" or "u12345"
+QString adobeGlyphName(FT_ULong charcode) {
+ static const char HEX[] = "0123456789ABCDEF";
+ QString result;
+ if (adobeGlyphNames.contains(charcode))
+ return adobeGlyphNames[charcode];
+ else if (charcode < 0x10000) {
+ result = QString("uni") + HEX[charcode>>12 & 0xF]
+ + HEX[charcode>> 8 & 0xF]
+ + HEX[charcode>> 4 & 0xF]
+ + HEX[charcode & 0xF];
+ }
+ else {
+ result = QString("u");
+ for (int i= 28; i >= 0; i-=4) {
+ if (charcode & (0xF << i))
+ result += HEX[charcode >> i & 0xF];
+ }
+ }
+ return result;
+}
+
+/*
+double Cwidth(ScribusDoc *, ScFace* scFace, QString ch, int Size, QString ch2)
+{
+ double width;
+ FT_Vector delta;
+ FT_Face face;
+ uint c1 = ch.at(0).unicode();
+ uint c2 = ch2.at(0).unicode();
+ double size10=Size/10.0;
+ if (scFace->canRender(ch[0]))
+ {
+ width = scFace->charWidth(ch[0])*size10;
+ face = scFace->ftFace();
+ /\****
+ Ok, this looks like a regression between Freetype 2.1.9 -> 2.1.10.
+ Ignoring the value of FT_HAS_KERNING for now -- AV
+ ****\/
+ if (true || FT_HAS_KERNING(face) )
+ {
+ uint cl = FT_Get_Char_Index(face, c1);
+ uint cr = FT_Get_Char_Index(face, c2);
+ FT_Error error = FT_Get_Kerning(face, cl, cr, FT_KERNING_UNSCALED, &delta);
+ if (error) {
+ qDebug(QString("Error %2 when accessing kerning pair for font %1").arg(scFace->scName()).arg(error));
+ }
+ else {
+ double uniEM = static_cast<double>(face->units_per_EM);
+ width += delta.x / uniEM * size10;
+ }
+ }
+ else {
+ qDebug(QString("Font %1 has no kerning pairs (according to Freetype)").arg(scFace->scName()));
+ }
+ return width;
+ }
+ else
+ return size10;
+}
+
+double RealCWidth(ScribusDoc *, ScFace* scFace, QString ch, int Size)
+{
+ double w, ww;
+ uint c1 = ch.at(0).unicode();
+ FT_Face face;
+ if (scFace->canRender(ch.at(0)))
+ {
+ face = scFace->ftFace();
+ uint cl = FT_Get_Char_Index(face, c1);
+ int error = FT_Load_Glyph(face, cl, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
+ if (!error) {
+ double uniEM = static_cast<double>(face->units_per_EM);
+ w = (face->glyph->metrics.width + fabs((double)face->glyph->metrics.horiBearingX)) / uniEM * (Size / 10.0);
+ ww = face->glyph->metrics.horiAdvance / uniEM * (Size / 10.0);
+ return QMAX(ww, w);
+ }
+ else
+ sDebug(QString("internal error: missing glyph: %1 (char %2) error=%3").arg(c1).arg(ch).arg(error));
+
+ }
+ return static_cast<double>(Size / 10.0);
+}
+
+double RealCHeight(ScribusDoc *, ScFace* scFace, QString ch, int Size)
+{
+ double w;
+ uint c1 = ch.at(0).unicode();
+ FT_Face face;
+ if (scFace->canRender(ch.at(0)))
+ {
+ face = scFace->ftFace();
+ uint cl = FT_Get_Char_Index(face, c1);
+ int error = FT_Load_Glyph(face, cl, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
+ if (!error) {
+ double uniEM = static_cast<double>(face->units_per_EM);
+ w = face->glyph->metrics.height / uniEM * (Size / 10.0);
+ }
+ else {
+ sDebug(QString("internal error: missing glyph: %1 (char %2) error=%3").arg(c1).arg(ch).arg(error));
+ w = Size / 10.0;
+ }
+ return w;
+ }
+ else
+ return static_cast<double>(Size / 10.0);
+}
+
+double RealCAscent(ScribusDoc *, ScFace* scFace, QString ch, int Size)
+{
+ double w;
+ uint c1 = ch.at(0).unicode();
+ FT_Face face;
+ if (scFace->canRender(ch.at(0)))
+ {
+ face = scFace->ftFace();
+ uint cl = FT_Get_Char_Index(face, c1);
+ int error = FT_Load_Glyph(face, cl, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
+ if (! error) {
+ double uniEM = static_cast<double>(face->units_per_EM);
+ w = face->glyph->metrics.horiBearingY / uniEM * (Size / 10.0);
+ }
+ else {
+ sDebug(QString("internal error: missing glyph: %1 (char %2) error=%3").arg(c1).arg(ch).arg(error));
+ w = Size / 10.0;
+ }
+ return w;
+ }
+ else
+ return static_cast<double>(Size / 10.0);
+}
+
+double RealFHeight(ScribusDoc *, ScFace* scFace, int Size)
+{
+ FT_Face face = scFace->ftFace();
+ double uniEM = static_cast<double>(face->units_per_EM);
+ return face->height / uniEM * (Size / 10.0);
+}
+*/
\ No newline at end of file
/Version13x/Scribus/scribus/fonts/scfontmetrics.cpp
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: Version13x/Scribus/scribus/fonts/scface.cpp
===================================================================
--- Version13x/Scribus/scribus/fonts/scface.cpp (nonexistent)
+++ Version13x/Scribus/scribus/fonts/scface.cpp (revision 5979)
@@ -0,0 +1,280 @@
+
+
+#include "scribusapi.h"
+#include "fonts/scface.h"
+
+
+double ScFace::ScFaceData::glyphKerning(uint gl1, uint gl2, double sz) const
+{
+ return 0.0;
+}
+
+
+bool ScFace::ScFaceData::glyphNames(QMap<QChar, std::pair<uint, QString> >& gList) const
+{
+ return false;
+}
+
+
+QMap<QString,QString> ScFace::ScFaceData::fontDictionary(double sz) const
+{
+ return QMap<QString, QString>();
+}
+
+GlyphMetrics ScFace::ScFaceData::glyphBBox(uint gl, double sz) const
+{
+ GlyphMetrics res;
+ res.width = sz;
+ res.ascent = sz;
+ res.descent = 0;
+ return res;
+}
+
+
+double ScFace::ScFaceData::glyphWidth(uint gl, double size) const
+{
+ if (! m_glyphWidth.contains(gl)) {
+ loadGlyph(gl);
+ }
+ return m_glyphWidth[gl] * size;
+}
+
+
+FPointArray ScFace::ScFaceData::glyphOutline(uint gl, double sz) const
+{
+ if (! m_glyphWidth.contains(gl)) {
+ loadGlyph(gl);
+ }
+ FPointArray res = m_glyphOutline[gl].Outlines.copy();
+ if (sz != 1.0)
+ res.scale(sz, sz);
+ return res;
+}
+
+
+FPoint ScFace::ScFaceData::glyphOrigin(uint gl, double sz) const
+{
+ if (! m_glyphWidth.contains(gl)) {
+ loadGlyph(gl);
+ }
+ const struct GlyphData & res(m_glyphOutline[gl]);
+ return FPoint(res.x, res.y) * sz;
+}
+
+
+/*****
+ ScFace lifecycle: unchecked -> loaded -> glyphs checked
+ | \-> broken glyphs
+ \-> broken
+ usable() == ! broken
+ embeddable() == glyphs_checked
+
+ canRender(unicode) -> CharMap cache? -> loadChar/Glyph -> !broken
+ Glyphs: width status
+ -1000 unkown
+ -2000 broken
+ >= 0 ok, outline valid
+ CharMap: unicode -> glyph index
+ uint[256][256]
+ unicode ignores: < 32, ...
+ unicode emulate: spaces, hyphen, ligatures?, diacritics?
+ *****/
+
+ScFace::ScFace()
+{
+ m = new ScFaceData();
+ m->refs = 1;
+ m->usage = 0;
+
+ m->status = ScFace::NULLFACE;
+ m->typeCode = ScFace::UNKNOWN_TYPE;
+ m->formatCode = ScFace::UNKNOWN_FORMAT;
+
+ m->scName = "";
+ m->family = "";
+ m->style = "";
+ m->variant = "";
+ m->psName = "";
+ m->fontFile = "(None)";
+ m->faceIndex = -1;
+ m->forDocument = "";
+ m->usable = false;
+ m->embedPs = false;
+ m->subset = false;
+ m->maxGlyph = 0;
+ m->cachedStatus = ScFace::UNKNOWN;
+}
+
+
+ScFace::ScFace(ScFaceData* data)
+{
+ m = data;
+ m->refs = 1;
+ m->cachedStatus = ScFace::UNKNOWN;
+}
+
+ScFace::ScFace(const ScFace& other)
+{
+ m = other.m;
+ ++(m->refs);
+}
+
+ScFace::~ScFace()
+{
+ if ( m && --(m->refs) == 0 ) {
+ m->unload();
+ delete m;
+ m = 0;
+ }
+}
+
+
+ScFace& ScFace::operator=(const ScFace& other)
+{
+ ++(other.m->refs);
+ if ( m && --(m->refs) == 0 ) {
+ m->unload();
+ delete m;
+ }
+ m = other.m;
+}
+
+
+/** two ScFaces are equal if they either are both NULLFACEs or they
+agree on family, style, variant and fontpath
+*/
+bool ScFace::operator==(const ScFace& other) const
+{
+ return ( (isNone() && other.isNone() )
+ || (m == other.m)
+ || (m->family == other.m->family
+ && m->style == other.m->style
+ && m->variant == other.m->variant
+ && m->fontFile == other.m->fontFile
+ && m-> faceIndex == other.m->faceIndex) );
+}
+
+
+const ScFace& ScFace::none()
+{
+ static ScFace NONE;
+ return NONE;
+}
+
+
+void ScFace::increaseUsage() const
+{
+ m->usage++;
+}
+
+
+void ScFace::decreaseUsage() const
+{
+ if (m->usage == 1)
+ unload();
+ m->usage--;
+}
+
+
+void ScFace::unload() const
+{
+ if (m->status >= ScFace::LOADED && usable()) {
+ m->unload();
+ }
+ // clear caches
+ m->m_glyphWidth.clear();
+ m->m_glyphOutline.clear();
+ m->m_cMap.clear();
+ m->status = ScFace::UNKNOWN;
+}
+
+
+uint ScFace::char2CMap(QChar ch) const
+{
+ if (m->status == ScFace::UNKNOWN) {
+ m->load();
+ }
+ return m->char2CMap(ch);
+}
+
+
+bool ScFace::canRender(QChar ch) const
+{
+ if (!usable())
+ return false;
+ else if (ch.unicode() < 32) {
+ return ch.unicode() == 28 || ch.unicode() == 13 || ch.unicode() == 9;
+ }
+ else {
+ uint gl = char2CMap(ch); // calls load()
+ if (gl != 0) {
+ m->loadGlyph(gl);
+ return ! m->m_glyphOutline[gl].broken;
+ }
+ else {
+ return false;
+ }
+ }
+}
+
+
+double ScFace::charWidth(QChar ch, double size, QChar ch2) const
+{
+ if (!canRender(ch)) // calls loadGlyph()
+ return size;
+ else if (ch.unicode() == 28 || ch.unicode() == 13 || ch.unicode() == 9)
+ return ch.unicode() == 9 ? 1.0 : 0.0;
+ else {
+ uint gl1 = char2CMap(ch);
+ uint gl2 = ch2.unicode() != 32 ? char2CMap(ch2) : 0;
+ double width = glyphWidth(gl1, size);
+ if (gl2 != 0)
+ width += glyphKerning(gl1, gl2, size);
+// qDebug(QString("scface::glyphkerning: %1_%2 = %3 (%4, %5)").arg(ch).arg(ch2).arg(glyphKerning(gl1, gl2,size)).arg(gl1).arg(gl2));
+ return width;
+ }
+}
+
+
+bool ScFace::EmbedFont(QString &str)
+{
+ if (m->status == ScFace::UNKNOWN) {
+ m->load();
+ }
+ return m->EmbedFont(str);
+}
+
+
+bool ScFace::glyphNames(QMap<QChar, std::pair<uint, QString> >& gList)
+{
+ if (m->status == ScFace::UNKNOWN) {
+ m->load();
+ }
+ return m->glyphNames(gList);
+}
+
+
+void ScFace::RawData(QByteArray & bb)
+{
+ if (m->status == ScFace::UNKNOWN) {
+ m->load();
+ }
+ m->RawData(bb);
+}
+
+void ScFace::checkAllGlyphs()
+{
+ if (m->status == ScFace::UNKNOWN) {
+ m->load();
+ }
+ if (m->status != ScFace::LOADED) {
+ return;
+ }
+ for (uint gl=0; gl <= m->maxGlyph; ++gl) {
+ if (! m->m_glyphWidth.contains(gl)) {
+ m->loadGlyph(gl);
+ m->m_glyphWidth.remove(gl);
+ m->m_glyphOutline.remove(gl);
+ }
+ }
+}
/Version13x/Scribus/scribus/fonts/scface.cpp
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: Version13x/Scribus/scribus/fonts/scface_ps.cpp
===================================================================
/Version13x/Scribus/scribus/fonts/scface_ps.cpp
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: Version13x/Scribus/scribus/fonts/scface_ttf.h
===================================================================
--- Version13x/Scribus/scribus/fonts/scface_ttf.h (nonexistent)
+++ Version13x/Scribus/scribus/fonts/scface_ttf.h (revision 5979)
@@ -0,0 +1,31 @@
+/*
+For general Scribus (>=1.3.2) copyright and licensing information please refer
+to the COPYING file provided with the program. Following this notice may exist
+a copyright and/or license notice that predates the release of Scribus 1.3.2
+for which a new license (GPL+exception) is in place.
+*/
+#ifndef SCFACE_TTF_H
+#define SCFACE_TTF_H
+
+#include "scribusapi.h"
+#include "fonts/ftface.h"
+
+/*
+ Class ScFace_ttf
+ Subclass of ScFace, specifically for TrueType fonts.
+ Implements: RealName() and EmbedFont().
+*/
+
+class SCRIBUS_API ScFace_ttf : public FtFace
+{
+public:
+ ScFace_ttf(QString fam, QString sty, QString alt, QString scname, QString psname, QString path, int face)
+ : FtFace(fam, sty, alt, scname, psname, path, face )
+ {
+ formatCode = ScFace::SFNT;
+ }
+ bool EmbedFont(QString &str);
+ void RawData(QByteArray & bb);
+};
+
+#endif
/Version13x/Scribus/scribus/fonts/scface_ttf.h
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: Version13x/Scribus/scribus/fonts/scfontmetrics.h
===================================================================
--- Version13x/Scribus/scribus/fonts/scfontmetrics.h (nonexistent)
+++ Version13x/Scribus/scribus/fonts/scfontmetrics.h (revision 5979)
@@ -0,0 +1,36 @@
+/*
+For general Scribus (>=1.3.2) copyright and licensing information please refer
+to the COPYING file provided with the program. Following this notice may exist
+a copyright and/or license notice that predates the release of Scribus 1.3.2
+for which a new license (GPL+exception) is in place.
+*/
+
+#ifndef SCFONTMETRICS_H
+#define SCFONTMETRICS_H
+
+#include <utility>
+#include <qglobal.h>
+#include <qstring.h>
+#include <qcolor.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_OUTLINE_H
+#include FT_GLYPH_H
+
+#include "scribusapi.h"
+#include "fpoint.h"
+#include "fpointarray.h"
+
+class ScFace;
+class Scribusdoc;
+
+int SCRIBUS_API setBestEncoding(FT_Face face);
+FPointArray SCRIBUS_API traceChar(FT_Face face, uint chr, int chs, double *x, double *y, bool *err);
+FPointArray SCRIBUS_API traceGlyph(FT_Face face, uint chr, int chs, double *x, double *y, bool *err);
+QPixmap SCRIBUS_API FontSample(const ScFace& fnt, int s, QString ts, QColor back, bool force = false);
+//QPixmap SCRIBUS_API fontSamples(const ScFace& fnt, int s, QString ts, QColor back);
+bool SCRIBUS_API GlyNames(FT_Face face, QMap<QChar, std::pair<uint, QString> >& GList);
+//bool SCRIBUS_API GlyIndex(ScFace * fnt, QMap<uint, PDFlib::GlNamInd> *GListInd);
+
+#endif
/Version13x/Scribus/scribus/fonts/scfontmetrics.h
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: Version13x/Scribus/scribus/fonts/scface.h
===================================================================
--- Version13x/Scribus/scribus/fonts/scface.h (nonexistent)
+++ Version13x/Scribus/scribus/fonts/scface.h (revision 5979)
@@ -0,0 +1,340 @@
+#ifndef SC_FACE_H
+#define SC_FACE_H
+
+/* ScFace responsibilities:
+
+font storage: type, format, filepath, index, document-local, substitute, etc.
+usage: use, embed, subset, ...
+face info: family, effect, alternative, flags, charset
+encoding: CMap2String, glyphnames,
+metrics: cwidth, bearing, bbox, "real" widths, paths
+opentype: apply features, script support (-)
+embedding: fontdictionary, rawdata, embedPS, embedPDF, subsetPS, subsetPDF
+virtual: dispatch to constituents, handle embedding (-)
+*/
+
+#include <qstring.h>
+#include <qvector.h>
+#include <qmap.h>
+#include <qarray.h>
+#include <utility>
+
+#include "fpointarray.h"
+
+
+
+struct GlyphMetrics {
+ double width;
+ double ascent;
+ double descent;
+};
+
+
+
+/*! \brief Base Class ScFace : This is a total rewrite of the old Foi class.
+
+It uses a shared private implementation which must be a subclass of ScFontData.
+ScFace objects are quite small and can be handled like value objects. Reference
+counting ensures that the shared data is freed when the last ScFace object is
+destructed.
+
+ScFaceData has caches for face and glyph data. load() fills those caches for
+face data, loadGlyph() fills the cache for glyphs. caches are always filled by
+need, so you can call unload() any time (well, better not multithreaded...)
+without producing errors. the increaseUsage() and decreaseUsage() keep track
+of at how many places a face is used and automatically unload when the count
+reaches zero.
+Other data is recalculated on demand. The implementation can choose to do its
+own caching for this data.
+
+ScFace uses a sophisticated lifecycle which controls the state of initialisation
+and the performed checks. the normal lilecycle goes:
+
+UNKNOWN --load()--> LOADED --checkAllGlyphs()--> CHECKED
+
+If the face can not be loaded, the status changes to BROKEN.
+If only some glyphs can not be loaded, the status changes to
+BROKENGLYPHS. These fonts can still be used and subsetted(outlined),
+but not embedded.
+
+ScFace constructors are only accessible to the ScFonts class which does
+some checking before creating a new ScFace. These checks are recorded
+in a cache and only reexecuted if the font file changes.
+The field 'cachedStatus' allows load() to switch directly to one of the
+states BROKEN, CHECKED or BROKENGLYPHS if this state was reached during a
+previous run of Scribus.
+*/
+class SCRIBUS_API ScFace
+{
+public:
+ enum Status { UNKNOWN, LOADED, CHECKED, BROKENGLYPHS, BROKEN, NULLFACE };
+ enum FontType { TYPE0, TYPE1, TYPE3, TTF, CFF, OTF, UNKNOWN_TYPE };
+ enum FontFormat { PFA, PFB, TYPE2, TYPE42,
+ // handled by freetype: PFB_MAC, DFONT, HQX, MACBIN,
+ SFNT, TTCF, UNKNOWN_FORMAT };
+
+ struct GlyphData {
+ FPointArray Outlines;
+ double x;
+ double y;
+ bool broken;
+ GlyphData() : Outlines(), x(0), y(0), broken(true) {}
+ };
+
+
+ /// see accessors for ScFace for docs
+ struct ScFaceData {
+ /// controls destruction
+ mutable int refs;
+ /// controls load()
+ mutable int usage;
+
+ QString scName;
+ QString fontFile;
+ int faceIndex;
+ QString psName;
+ QString family;
+ QString style;
+ QString variant;
+
+ QString forDocument;
+
+ mutable ScFace::Status status;
+ ScFace::FontType typeCode;
+ ScFace::FontFormat formatCode;
+
+ bool usable;
+ bool embedPs;
+ bool subset;
+
+ bool isStroked;
+ bool isFixedPitch;
+ bool hasNames;
+ uint maxGlyph;
+
+ virtual ~ScFaceData() { };
+protected:
+
+ friend class ScFace;
+ Status cachedStatus;
+
+ // caches
+ mutable QMap<uint,double> m_glyphWidth;
+ mutable QMap<uint,GlyphData> m_glyphOutline;
+ mutable QMap<uint, uint> m_cMap;
+
+ // fill caches & members
+
+ virtual void load() const
+ {
+ m_glyphWidth.clear();
+ m_glyphOutline.clear();
+ m_cMap.clear();
+
+ status = QMAX(cachedStatus, ScFace::LOADED);
+ }
+
+ virtual void unload() const
+ {
+ m_glyphWidth.clear();
+ m_glyphOutline.clear();
+ m_cMap.clear();
+
+ status = ScFace::UNKNOWN;
+ }
+
+ virtual void loadGlyph(uint gl) const {}
+
+ // dummy implementations
+ virtual double ascent(double sz) const { return sz; }
+ virtual double descent(double sz) const { return 0.0; }
+ virtual double xHeight(double sz) const { return sz; }
+ virtual double capHeight(double sz) const { return sz; }
+ virtual double height(double sz) const { return sz; }
+ virtual double strikeoutPos(double sz) const { return sz / 2; }
+ virtual double underlinePos(double sz) const { return -1.0; }
+ virtual double strokeWidth(double sz) const { return 0.1; }
+ virtual double maxAdvanceWidth(double sz) const { return sz; }
+ virtual uint char2CMap(QChar ch) const { return 0; }
+ virtual double glyphKerning(uint gl1, uint gl2, double sz) const;
+ virtual QMap<QString,QString> fontDictionary(double sz=1.0) const;
+ virtual GlyphMetrics glyphBBox(uint gl, double sz) const;
+ virtual bool EmbedFont(QString &str) const { return false; }
+ virtual void RawData(QByteArray & bb) const {}
+ virtual bool glyphNames(QMap<QChar, std::pair<uint, QString> >& gList) const;
+
+ // these use the cache:
+ virtual double glyphWidth(uint gl, double sz) const;
+ virtual FPointArray glyphOutline(uint gl, double sz) const;
+ virtual FPoint glyphOrigin (uint gl, double sz) const;
+
+ };
+
+
+
+ ScFace();
+ ScFace(const ScFace& other);
+ ~ScFace();
+
+ /// used as a null object
+ static const ScFace& none();
+
+ /// test for null object
+ bool isNone() const { return m->status == NULLFACE; }
+
+ ScFace& operator=(const ScFace& other);
+ /** two ScFaces are equal if they either are both NULLFACEs or they
+ agree on family, style, variant and fontpath
+ */
+ bool operator==(const ScFace& other) const ;
+ bool operator!=(const ScFace& other) const { return ! (*this == other); }
+
+
+ bool EmbedFont(QString &str);
+ void RawData(QByteArray & bb);
+ bool glyphNames(QMap<QChar, std::pair<uint, QString> >& gList);
+
+ /// prevent unloading of face data
+ void increaseUsage() const;
+
+ /// unload face data if not used any more
+ void decreaseUsage() const;
+
+ /// unload face data. It will be reloaded on need
+ void unload() const;
+
+ /// the name Scribus uses for this font
+ QString scName() const { return m->scName; }
+
+ /// the name PostScript uses for this font
+ QString psName() const { return m->psName; }
+
+ /// the physical location of the fontfile
+ QString fontPath() const { return m->faceIndex >= 0 ? QString("%1(%2)").arg(m->fontFile).arg(m->faceIndex+1) : m->fontFile; }
+
+ /// the file path of the fontfile
+ QString fontFilePath() const { return m->fontFile; }
+
+ /// if the fontfile contains more than one face, the index, else -1
+ int faceIndex() const { return m->faceIndex; }
+
+ /// path name of the document this face is local to
+ QString localForDocument() const { return m->forDocument; }
+
+ /// font type, eg. Type1 or TTF
+ FontType type() const { return m->typeCode; }
+
+ /// font format, which might be a little more complicated
+ FontFormat format()const { return m->formatCode; }
+
+ /// test if this face can be used in documents
+ bool usable() const { return m->usable && !isNone(); }
+
+ /// test if this face can be embedded in PS/PDF
+ bool embedPs() const { return m->embedPs && m->status < BROKENGLYPHS; }
+
+ /// test if this face can be embedded as outlines in PS/PDF
+ bool subset() const { return m->subset && m->status < BROKEN; }
+
+ void usable(bool flag) { m->usable = flag; }
+ void embedPs(bool flag) { m->embedPs = flag; }
+ void subset(bool flag) { m->subset = flag; }
+
+ /// deprecated? tells if the face has PS names
+ bool hasNames() const { return m->hasNames; }
+
+ /// tells if this font is an outline font
+ bool isStroked() const { return m->isStroked; }
+
+ /// tells if this font is a fixed pitch font
+ bool isFixedPitch()const { return m->isFixedPitch; }
+
+ /// tells if this is an OTF/CFF font
+ bool isOTF() const { return m->typeCode == OTF; }
+
+ /// returns the highest glyph index in this face
+ uint maxGlyph() const { return m->maxGlyph; }
+
+ /// returns the font family as seen by Scribus
+ QString family() const { return m->family; }
+
+ /// returns the font style as seen by Scribus (eg. bold, Italic)
+ QString style() const { return m->style; }
+
+ /// returns an additional discriminating String for this face
+ QString variant() const { return m->variant; }
+
+ // font metrics
+ double ascent(double sz=1.0) const { return m->ascent(sz); }
+ double descent(double sz=1.0) const { return m->descent(sz); }
+ double xHeight(double sz=1.0) const { return m->xHeight(sz); }
+ double capHeight(double sz=1.0) const { return m->capHeight(sz); }
+ double height(double sz=1.0) const { return m->height(sz); }
+ double strikeoutPos(double sz=1.0) const { return m->strikeoutPos(sz); }
+ double underlinePos(double sz=1.0) const { return m->underlinePos(sz); }
+ double strokeWidth(double sz=1.0) const { return m->strokeWidth(sz); }
+ double maxAdvanceWidth(double sz=1.0) const { return m->maxAdvanceWidth(sz); }
+
+ /// deprecated
+ QString stemV(double sz=1.0) const { return fontDictionary(sz)["/StemV"]; }
+
+ /// deprecated
+ QString italicAngle(double sz=1.0) const { return fontDictionary(sz)["/ItalicAngle"]; }
+
+ /// deprecated
+ QString fontBBox(double sz=1.0) const { return fontDictionary(sz)["/FontBBox"]; }
+
+ /// returns a map of values used for font dictionaries in PS/PDF
+ QMap<QString,QString> fontDictionary(double sz=1.0) const { return m->fontDictionary(sz); }
+ // glyph interface
+
+ /// returns the glyphs normal advance width at size 'sz'
+ double glyphWidth(uint gl, double sz=1.0) const { return m->glyphWidth(gl, sz); }
+
+ /// returns the glyph kerning between 'gl1' and 'gl2' at size 'sz'
+ double glyphKerning(uint gl1, uint gl2, double sz=1.0) const { return m->glyphKerning(gl1, gl2, sz); }
+
+ /// returns the glyphs bounding box at size 'sz', ie. the area where this glyph will produce marks
+ GlyphMetrics glyphBBox(uint gl, double sz=1.0) const { return m->glyphBBox(gl, sz); }
+
+ /// returns the glyph's outline as a cubic Bezier path
+ FPointArray glyphOutline(uint gl, double sz=1.0) const { return m->glyphOutline(gl, sz); }
+
+ /// returns the glyph's origin FIXME: what's that exactly?
+ FPoint glyphOrigin(uint gl, double sz=1.0) const { return m->glyphOrigin(gl, sz); }
+
+ // char interface
+
+ /// test if the face can render this char
+ bool canRender(QChar ch) const;
+
+ /// translate unicode to glyph index
+ uint char2CMap(QChar ch) const;
+
+ /// returns the combined glyph width and kerning for 'ch' if followed by 'ch2'
+ double charWidth(QChar ch, double sz=1.0, QChar ch2 = QChar(32)) const;
+
+ /// deprecated, see glyphBBox()
+ double realCharWidth(QChar ch, double sz=1.0) const { return glyphBBox(char2CMap(ch),sz).width; }
+
+ /// deprecated, see glyphBBox()
+ double realCharHeight(QChar ch, double sz=1.0) const { GlyphMetrics gm=glyphBBox(char2CMap(ch),sz); return gm.ascent + gm.descent; }
+
+ /// deprecated, see glyphBBox()
+ double realCharAscent(QChar ch, double sz=1.0) const { return glyphBBox(char2CMap(ch),sz).ascent; }
+
+ /// deprecated, see glyphBBox()
+ double realCharDescent(QChar ch, double sz=1.0) const { return glyphBBox(char2CMap(ch),sz).descent; }
+
+private:
+
+ friend class SCFonts;
+
+ ScFace(ScFaceData* md);
+ ScFaceData* m;
+
+ void initFaceData();
+ void checkAllGlyphs();
+};
+
+#endif
/Version13x/Scribus/scribus/fonts/scface.h
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: Version13x/Scribus/scribus/fonts/scface_ps.h
===================================================================
--- Version13x/Scribus/scribus/fonts/scface_ps.h (nonexistent)
+++ Version13x/Scribus/scribus/fonts/scface_ps.h (revision 5979)
@@ -0,0 +1,235 @@
+/*
+ For general Scribus (>=1.3.2) copyright and licensing information please refer
+ to the COPYING file provided with the program. Following this notice may exist
+ a copyright and/or license notice that predates the release of Scribus 1.3.2
+ for which a new license (GPL+exception) is in place.
+ */
+#ifndef SCFACE_PS_H
+#define SCFACE_PS_H
+
+#include <qstring.h>
+#include <qstrlist.h>
+#include <qstringlist.h>
+#include <qdict.h>
+#include <qfont.h>
+#include <qmap.h>
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_OUTLINE_H
+#include FT_GLYPH_H
+
+#include "scribusapi.h"
+#include "fpointarray.h"
+#include "scconfig.h"
+
+
+/*
+ Class ScFace_postscript
+ Subclass of ScFace, for PostScript fonts that could possibly have a .afm file
+ associated with them for metrics information.
+*/
+
+class ScFace_postscript : public FtFace
+{
+ public:
+ ScFace_postscript(QString fam, QString sty, QString alt, QString scname, QString psname, QString path, int face) :
+ FtFace(fam,sty,alt,scname,psname,path,face)
+ {
+ isFixedPitch = false;
+ typeCode = ScFace::TYPE1;
+ }
+
+ virtual void load() // routine by Franz Schmid - modified by Alastair M. Robinson
+ {
+ ScFaceData::load();
+ bool error;
+ FT_Face face = ftFace();
+ if (!face)
+ {
+ usable = false;
+ qDebug(QObject::tr("Font %1 is broken (no Face), discarding it").arg(fontFile));
+ return;
+ }
+ QString afnm = fontFile.left(fontFile.length()-3);
+ QFile afm(afnm+"afm");
+ if(!(afm.exists()))
+ {
+ afm.setName(afnm+"Afm");
+ }
+ if(!(afm.exists()))
+ {
+ afm.setName(afnm+"AFM");
+ }
+ if(!(afm.exists()))
+ {
+ afm.setName(afnm+"pfm");
+ }
+ if(!(afm.exists()))
+ {
+ afm.setName(afnm+"Pfm");
+ }
+ if(!(afm.exists())) {
+ afm.setName(afnm+"PFM");
+ }
+ if (afm.exists())
+ error = FT_Attach_File(face, afm.name());
+// Ascent = tmp.setNum(face->ascender);
+// Descender = tmp.setNum(face->descender);
+// CapHeight = Ascent;
+// ItalicAngle = "0";
+// StdVW = "1";
+// FontBBox = tmp.setNum(face->bbox.xMin)+" "+tmp2.setNum(face->bbox.yMin)+" "+tmp3.setNum(face->bbox.xMax)+" "+tmp4.setNum(face->bbox.yMax);
+/*
+ setBestEncoding(face);
+ gindex = 0;
+ charcode = FT_Get_First_Char( face, &gindex );
+ int goodGlyph = 0;
+ int invalidGlyph = 0;
+ while ( gindex != 0 )
+ {
+ error = FT_Load_Glyph( face, gindex, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP );
+ if (error)
+ {
+ ++invalidGlyph;
+ sDebug(QObject::tr("Font %1 has broken glyph %2 (charcode %3)").arg(fontPath()).arg(gindex).arg(charcode));
+ charcode = FT_Get_Next_Char( face, charcode, &gindex );
+ continue;
+ }
+ ++goodGlyph;
+ double ww = face->glyph->metrics.horiAdvance / uniEM;
+ if (face->glyph->format == FT_GLYPH_FORMAT_PLOTTER)
+ isStroked = true;
+ error = false;
+ outlines = traceChar(face, charcode, 10, &x, &y, &error);
+ if (!error)
+ {
+ CharWidth.insert(charcode, ww);
+ GRec.Outlines = outlines.copy();
+ GRec.x = x;
+ GRec.y = y;
+ GlyphArray.insert(charcode, GRec);
+ }
+ charcode = FT_Get_Next_Char( face, charcode, &gindex );
+ }
+ */
+ }
+};
+
+/*
+ Class ScFace_pfb
+ Subclass of ScFace, specifically for Adobe type 1 .pfb fonts.
+ Implements: RealName() and EmbedFont().
+*/
+
+class ScFace_pfb : public ScFace_postscript
+{
+ public:
+ ScFace_pfb(QString fam, QString sty, QString alt, QString scname, QString psname, QString path, int face) :
+ ScFace_postscript(fam,sty,alt,scname,psname,path,face)
+ {
+ formatCode = ScFace::PFB;
+ }
+
+ virtual bool EmbedFont(QString &str)
+ {
+ QByteArray bb;
+ RawData(bb);
+ QString tmp2 = "";
+ if ((bb.size() > 2) && (bb[0] == char(0x80)) && (static_cast<int>(bb[1]) == 1))
+ {
+ QString tmp3="";
+ QString tmp4 = "";
+ uint posi,cxxc=0;
+ for (posi = 6; posi < bb.size(); ++posi)
+ {
+ if ((bb[posi] == char(0x80)) && (posi+1 < bb.size()) && (static_cast<int>(bb[posi+1]) == 2))
+ break;
+ str += bb[posi];
+ }
+ uint ulen;
+ if (posi+6 < bb.size())
+ {
+ ulen = bb[posi+2] & 0xff;
+ ulen |= (bb[posi+3] << 8) & 0xff00;
+ ulen |= (bb[posi+4] << 16) & 0xff0000;
+ ulen |= (bb[posi+5] << 24) & 0xff000000;
+ posi += 6;
+ if (posi + ulen > bb.size())
+ ulen = bb.size() - posi - 1;
+ char linebuf[80];
+ cxxc=0;
+ for (uint j = 0; j < ulen; ++j)
+ {
+ unsigned char u=bb[posi];
+ linebuf[cxxc]=((u >> 4) & 15) + '0';
+ if(u>0x9f) linebuf[cxxc]+='a'-':';
+ ++cxxc;
+ u&=15; linebuf[cxxc]=u + '0';
+ if(u>0x9) linebuf[cxxc]+='a'-':';
+ ++posi;
+ ++cxxc;
+ if (cxxc > 72)
+ {
+ linebuf[cxxc++]='\n';
+ linebuf[cxxc++]=0;
+ str += linebuf;
+ cxxc = 0;
+ }
+ }
+ linebuf[cxxc]=0;
+ str += linebuf;
+ str += "\n";
+ }
+ posi += 6;
+ for (uint j = posi; j < bb.size(); ++j)
+ {
+ if ((bb[j] == static_cast<char>(0x80)) && (j+1 < bb.size()) && (static_cast<int>(bb[j+1]) == 3))
+ break;
+ if(bb[j]=='\r')
+ str+="\n";
+ else
+ str += bb[j];
+ }
+ str += "\n";
+ cxxc = 0;
+ return true;
+ }
+ else
+ {
+ qDebug(QObject::tr("Font %1 cannot be read, no embedding").arg(fontFile));
+ return false;
+ }
+ }
+};
+
+/*
+ Class ScFace_pfa
+ Subclass of ScFace, specifically for Adobe type 1 and type 3 .pfa fonts.
+ Implements: RealName() and EmbedFont().
+*/
+
+class ScFace_pfa : public ScFace_postscript
+{
+ public:
+ ScFace_pfa(QString fam, QString sty, QString alt, QString scname, QString psname, QString path, int face) :
+ ScFace_postscript(fam,sty,alt,scname,psname,path,face)
+ {
+ formatCode = ScFace::PFA;
+ }
+ virtual bool EmbedFont(QString &str)
+ {
+ QByteArray bb;
+ RawData(bb);
+ if (bb.size() > 2 && bb[0] == '%' && bb[1] == '!')
+ {
+ // this is ok since bb will not contain '\0'
+ str.append(bb);
+ return true;
+ }
+ return false;
+ }
+};
+
+
+#endif
/Version13x/Scribus/scribus/fonts/scface_ps.h
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property
Index: Version13x/Scribus/scribus/fonts/CMakeLists.txt
===================================================================
--- Version13x/Scribus/scribus/fonts/CMakeLists.txt (nonexistent)
+++ Version13x/Scribus/scribus/fonts/CMakeLists.txt (revision 5979)
@@ -0,0 +1,16 @@
+INCLUDE_DIRECTORIES(
+${CMAKE_SOURCE_DIR}
+${CMAKE_SOURCE_DIR}/scribus
+)
+
+
+SET(SCRIBUS_FONTS_LIB_SOURCES
+scface.cpp
+ftface.cpp
+scface_ps.cpp
+scface_ttf.cpp
+scfontmetrics.cpp
+)
+
+SET(SCRIBUS_FONTS_LIB "scribus_fonts_lib")
+ADD_LIBRARY(${SCRIBUS_FONTS_LIB} STATIC ${SCRIBUS_FONTS_LIB_SOURCES})
/Version13x/Scribus/scribus/fonts/CMakeLists.txt
Property changes:
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Author Date Id Revision
\ No newline at end of property