Subversion Repositories Scribus

Compare Revisions

No changes between 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
+native
\ No newline at end of property
Added: svn:keywords
+Author Date Id Revision
\ No newline at end of property
/branches/Version13x/Scribus/scribus/fonts/scfontmetrics.cpp
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);
}
*/
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Author Date Id Revision
\ No newline at end of property
/branches/Version13x/Scribus/scribus/fonts/scface.cpp
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);
}
}
}
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Author Date Id Revision
\ No newline at end of property
/branches/Version13x/Scribus/scribus/fonts/scface_ps.cpp
___________________________________________________________________
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
/branches/Version13x/Scribus/scribus/fonts/scface_ttf.h
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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Author Date Id Revision
\ No newline at end of property
/branches/Version13x/Scribus/scribus/fonts/scfontmetrics.h
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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Author Date Id Revision
\ No newline at end of property
/branches/Version13x/Scribus/scribus/fonts/scface.h
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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Author Date Id Revision
\ No newline at end of property
/branches/Version13x/Scribus/scribus/fonts/scface_ps.h
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
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Author Date Id Revision
\ No newline at end of property
/branches/Version13x/Scribus/scribus/fonts/CMakeLists.txt
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})
Property changes:
Added: svn:eol-style
+native
\ No newline at end of property
Added: svn:keywords
+Author Date Id Revision
\ No newline at end of property