/usr/include/scribus/fonts/scface.h is in scribus-dev 1.4.6+dfsg-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 | /*
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 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>
//#include <QVector>
#include <QMap>
//#include <QArray>
#include <utility>
#include "fpointarray.h"
struct GlyphMetrics {
qreal width;
qreal ascent;
qreal 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 };
static const uint CONTROL_GLYPHS = 2000000000; // 2 billion
struct GlyphData {
FPointArray Outlines;
qreal x;
qreal y;
qreal bbox_width;
qreal bbox_ascent;
qreal bbox_descent;
bool broken;
GlyphData() : Outlines(), x(0), y(0), bbox_width(1), bbox_ascent(1), bbox_descent(0), broken(true) {}
};
/// see accessors for ScFace for docs
class ScFaceData {
public:
/// 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;
ScFaceData();
virtual ~ScFaceData() { };
protected:
friend class ScFace;
Status cachedStatus;
// caches
mutable QMap<uint,qreal> 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 qreal ascent(qreal sz) const { return sz; }
virtual QString pdfAscentAsString() const { return "0" ; }
virtual QString pdfDescentAsString() const { return "0"; }
virtual QString pdfCapHeightAsString() const { return "0"; }
virtual QString pdfFontBBoxAsString() const { return "0 0 0 0"; }
virtual QString ItalicAngleAsString() const { return "0"; }
virtual qreal descent(qreal /*sz*/) const { return 0.0; }
virtual qreal xHeight(qreal sz) const { return sz; }
virtual qreal capHeight(qreal sz) const { return sz; }
virtual qreal height(qreal sz) const { return sz; }
virtual qreal strikeoutPos(qreal sz) const { return sz / 2; }
virtual qreal underlinePos(qreal /*sz*/) const { return -1.0; }
virtual qreal strokeWidth(qreal /*sz*/) const { return 0.1; }
virtual qreal maxAdvanceWidth(qreal sz) const { return sz; }
virtual uint char2CMap(QChar /*ch*/) const { return 0; }
virtual qreal glyphKerning(uint gl1, uint gl2, qreal sz) const;
virtual QMap<QString,QString> fontDictionary(qreal sz=1.0) const;
virtual GlyphMetrics glyphBBox(uint gl, qreal sz) const;
virtual bool EmbedFont(QString &/*str*/) const { return false; }
virtual void RawData(QByteArray & /*bb*/) const {}
virtual bool glyphNames(QMap<uint, std::pair<QChar, QString> >& gList) const;
// these use the cache:
virtual qreal glyphWidth(uint gl, qreal sz) const;
virtual FPointArray glyphOutline(uint gl, qreal sz) const;
virtual FPoint glyphOrigin (uint gl, qreal sz) const;
virtual bool isSymbolic() const { return false; }
};
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; }
/// test if font is a symbolic font
bool isSymbolic() const;
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<uint, std::pair<QChar, 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 replacedName.isEmpty() ? m->scName : replacedName; }
/// the name of the font which was used for replacement
QString replacementName() const { return m->scName; }
/// the name of the font which was used for replacement
QString replacementForDoc() const { return replacedInDoc; }
/// check if this is a replacement font
bool isReplacement() const { return !replacedName.isEmpty(); }
/// makes a repalcement font for font "name" using this fonts data
ScFace mkReplacementFor(QString name, QString doc) {
ScFace result(m);
result.replacedName = name;
result.replacedInDoc = doc;
return result;
}
void chReplacementTo(ScFace& other, QString doc) {
QString oldName = replacedName;
(*this) = other;
replacedName = oldName;
replacedInDoc = doc;
}
/// 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
QString pdfAscentAsString() const;
QString pdfDescentAsString() const;
QString pdfCapHeightAsString() const;
QString pdfFontBBoxAsString() const;
QString italicAngleAsString() const;
qreal ascent(qreal sz=1.0) const;
qreal descent(qreal sz=1.0) const;
qreal xHeight(qreal sz=1.0) const;
qreal capHeight(qreal sz=1.0) const;
qreal height(qreal sz=1.0) const;
qreal strikeoutPos(qreal sz=1.0) const;
qreal underlinePos(qreal sz=1.0) const;
qreal strokeWidth(qreal sz=1.0) const;
qreal maxAdvanceWidth(qreal sz=1.0) const;
/// deprecated
QString stemV(qreal sz=1.0) const { return fontDictionary(sz)["/StemV"]; }
/// deprecated
QString italicAngle(qreal sz=1.0) const { return fontDictionary(sz)["/ItalicAngle"]; }
/// deprecated
QString fontBBox(qreal sz=1.0) const { return fontDictionary(sz)["/FontBBox"]; }
/// returns a map of values used for font dictionaries in PS/PDF
QMap<QString,QString> fontDictionary(qreal sz=1.0) const { return m->fontDictionary(sz); }
// glyph interface
/// returns the glyphs normal advance width at size 'sz'
qreal glyphWidth(uint gl, qreal sz=1.0) const { return m->glyphWidth(gl, sz); }
/// returns the glyph kerning between 'gl1' and 'gl2' at size 'sz'
qreal glyphKerning(uint gl1, uint gl2, qreal sz=1.0) const { return qMax(gl1,gl2) < CONTROL_GLYPHS ? m->glyphKerning(gl1, gl2, sz) : 0; }
/// returns the glyphs bounding box at size 'sz', ie. the area where this glyph will produce marks
GlyphMetrics glyphBBox(uint gl, qreal sz=1.0) const { return m->glyphBBox(gl, sz); }
/// returns the glyph's outline as a cubic Bezier path
FPointArray glyphOutline(uint gl, qreal sz=1.0) const { return m->glyphOutline(gl, sz); }
/// returns the glyph's origin FIXME: what's that exactly?
FPoint glyphOrigin(uint gl, qreal 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'
qreal charWidth(QChar ch, qreal sz=1.0, QChar ch2 = QChar(0)) const;
/// deprecated, see glyphBBox()
qreal realCharWidth(QChar ch, qreal sz=1.0) const { return glyphBBox(char2CMap(ch),sz).width; }
/// deprecated, see glyphBBox()
qreal realCharHeight(QChar ch, qreal sz=1.0) const { GlyphMetrics gm=glyphBBox(char2CMap(ch),sz); return gm.ascent + gm.descent; }
/// deprecated, see glyphBBox()
qreal realCharAscent(QChar ch, qreal sz=1.0) const { return glyphBBox(char2CMap(ch),sz).ascent; }
/// deprecated, see glyphBBox()
qreal realCharDescent(QChar ch, qreal sz=1.0) const { return glyphBBox(char2CMap(ch),sz).descent; }
private:
friend class SCFonts;
ScFace(ScFaceData* md);
ScFaceData* m;
QString replacedName;
QString replacedInDoc;
void initFaceData();
void checkAllGlyphs();
uint emulateGlyph(QChar c) const;
};
#endif
|