FontInstance.cpp revision db6a2351857d96bbd67e5d07a4b2540c876cbd6b
/*
* testICU
*
* Authors:
* fred
* bulia byak <buliabyak@users.sf.net>
*
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifndef PANGO_ENABLE_ENGINE
#define PANGO_ENABLE_ENGINE
#endif
#include <ft2build.h>
#include FT_OUTLINE_H
#include FT_BBOX_H
#include FT_TRUETYPE_TAGS_H
#include FT_TRUETYPE_TABLES_H
#include FT_GLYPH_H
#include <pango/pangoft2.h>
#include "libnrtype/font-glyph.h"
#include "libnrtype/font-instance.h"
#include "util/unordered-containers.h"
size_t operator()(font_style const &x) const;
};
bool operator()(font_style const &a, font_style const &b) const;
};
static const double STROKE_WIDTH_THREASHOLD = 0.01;
int h = 0;
h *= 12186;
h += n;
n = (x.vertical) ? 1:0;
h *= 12186;
h += n;
if ( x.stroke_width >= STROKE_WIDTH_THREASHOLD ) {
h *= 12186;
h += n;
if ( x.nbDash > 0 ) {
n = x.nbDash;
h *= 12186;
h += n;
h *= 12186;
h += n;
for (int i = 0; i < x.nbDash; i++) {
h *= 12186;
h += n;
}
}
}
return h;
}
bool same = true;
for (int i = 0; (i < 6) && same; i++) {
}
&& ( a.stroke_join == b.stroke_join )
same = ( static_cast<int>(floor(100 * a.dash_offset)) == static_cast<int>(floor(100 * b.dash_offset)) );
same = ( static_cast<int>(floor(100 * a.dashes[i])) == static_cast<int>(floor(100 * b.dashes[i])) );
}
}
}
return same;
}
#ifndef USE_PANGO_WIN32
/*
* Outline extraction
*/
struct FT2GeomData {
: builder(b)
, last(0, 0)
, scale(s)
{}
double scale;
};
// Note: Freetype 2.2.1 redefined function signatures for functions to be placed in an
// FT_Outline_Funcs structure. This is needed to keep backwards compatibility with the
// 2.1.x series.
/* *** BEGIN #if HACK *** */
typedef FT_Vector const FREETYPE_VECTOR;
#else
typedef FT_Vector FREETYPE_VECTOR;
#endif
// outline as returned by freetype -> livarot Path
// see nr-type-ft2.cpp for the freetype -> artBPath on which this code is based
{
// printf("m t=%f %f\n",p[0],p[1]);
return 0;
}
{
// printf("l t=%f %f\n",p[0],p[1]);
return 0;
}
{
// printf("b c=%f %f t=%f %f\n",c[0],c[1],p[0],p[1]);
return 0;
}
static int ft2_cubic_to(FREETYPE_VECTOR *control1, FREETYPE_VECTOR *control2, FREETYPE_VECTOR *to, void *i_user)
{
// printf("c c1=%f %f c2=%f %f t=%f %f\n",c1[0],c1[1],c2[0],c2[1],p[0],p[1]);
//user->theP->CubicTo(p,3*(c1-user->last),3*(p-c2));
return 0;
}
#endif
/* *** END #if HACK *** */
/*
*
*/
font_instance::font_instance(void) :
pFont(0),
descr(0),
refCount(0),
parent(0),
nbGlyph(0),
maxGlyph(0),
glyphs(0),
theFace(0)
{
//printf("font instance born\n");
_xheight = 0.5;
// Default baseline values, alphabetic is reference
}
font_instance::~font_instance(void)
{
if ( parent ) {
parent = 0;
}
//printf("font instance death\n");
if ( pFont ) {
FreeTheFace();
pFont = 0;
}
if ( descr ) {
descr = 0;
}
// if ( theFace ) FT_Done_Face(theFace); // owned by pFont. don't touch
theFace = 0;
for (int i=0;i<nbGlyph;i++) {
if ( glyphs[i].pathvector ) {
delete glyphs[i].pathvector;
}
}
if ( glyphs ) {
glyphs = 0;
}
nbGlyph = 0;
maxGlyph = 0;
}
void font_instance::Ref(void)
{
refCount++;
//char *tc=pango_font_description_to_string(descr);
//printf("font %x %s ref'd %i\n",this,tc,refCount);
//free(tc);
}
void font_instance::Unref(void)
{
refCount--;
//char *tc=pango_font_description_to_string(descr);
//printf("font %x %s unref'd %i\n",this,tc,refCount);
//free(tc);
if ( refCount <= 0 ) {
delete this;
}
}
void font_instance::InitTheFace()
{
#ifdef USE_PANGO_WIN32
if ( !theFace ) {
}
#else
if ( theFace ) {
}
#endif
}
}
void font_instance::FreeTheFace()
{
#ifdef USE_PANGO_WIN32
#else
#endif
}
{
if ( !iFace ) {
return;
}
InitTheFace();
if ( pFont && IsOutlineFont() == false ) {
FreeTheFace();
if ( pFont ) {
}
}
}
bool font_instance::IsOutlineFont(void)
{
return false;
}
InitTheFace();
#ifdef USE_PANGO_WIN32
#else
return FT_IS_SCALABLE(theFace);
#endif
}
{
int res = 0;
if ( pFont ) {
#ifdef USE_PANGO_WIN32
#else
if ( c > 0xf0000 ) {
} else {
}
#endif
}
return res;
}
#ifdef USE_PANGO_WIN32
{
*(long*)&p.y / 65536.0 * scale);
}
#endif
{
return;
}
InitTheFace();
#ifndef USE_PANGO_WIN32
if ( !FT_IS_SCALABLE(theFace) ) {
return; // bitmap font
}
#endif
}
bool doAdd=false;
#ifdef USE_PANGO_WIN32
#ifndef GGO_UNHINTED // For compatibility with old SDKs.
#define GGO_UNHINTED 0x0100
#endif
DWORD bufferSize=GetGlyphOutline (parent->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity);
if ( bufferSize == GDI_ERROR) {
// shit happened
} else if ( bufferSize == 0) {
// character has no visual representation, but is valid (eg whitespace)
doAdd=true;
} else {
char *buffer = new char[bufferSize];
if ( GetGlyphOutline (parent->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer, &identity) <= 0 ) {
// shit happened
} else {
// Platform SDK is rubbish, read KB87115 instead
DWORD polyOffset=0;
while ( polyOffset < bufferSize ) {
case TT_PRIM_LINE:
while ( p != endp )
break;
case TT_PRIM_QSPLINE:
{
// The list of points specifies one or more control points and ends with the end point.
// The intermediate points (on the curve) are the points between the control points.
}
}
break;
case 3: // TT_PRIM_CSPLINE
while ( p != endp ) {
p += 3;
}
break;
}
}
}
}
doAdd=true;
}
delete [] buffer;
}
#else
// shit happened
} else {
if ( FT_HAS_HORIZONTAL(theFace) ) {
} else {
n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM);
}
if ( FT_HAS_VERTICAL(theFace) ) {
} else {
// CSS3 Writing modes dictates that if vertical font metrics are missing we must
// synthisize them. No method is specified. The SVG 1.1 spec suggests using the em
// height (which is not theFace->height as that includes leading). The em height
// is ascender + descender (descender positive). Note: The "Requirements for
// Japanese Text Layout" W3C document says that Japanese kanji should be "set
// solid" which implies that vertical (and horizontal) advance should be 1em.
}
0, 0
};
}
doAdd=true;
}
#endif
if ( doAdd ) {
// close all paths
i->close();
}
if (bounds) {
}
}
nbGlyph++;
}
} else {
}
}
{
return false;
}
InitTheFace();
return false;
}
return true;
}
double &linethrough_position, double &linethrough_thickness)
{
return false;
}
InitTheFace();
return false;
}
#ifdef USE_PANGO_WIN32
return false;
}
#else
if ( theFace->units_per_EM == 0 ) {
return false; // bitmap font
}
// there is no specific linethrough information, mock it up from other font fields
linethrough_thickness = fabs(((double)theFace->underline_thickness)/((double)theFace->units_per_EM));
#endif
return true;
}
{
run = 0.0;
rise = 1.0;
return false;
}
InitTheFace();
return false;
}
#ifdef USE_PANGO_WIN32
#else
if ( !FT_IS_SCALABLE(theFace) ) {
return false; // bitmap font
}
return false;
}
#endif
return true;
}
{
int no = -1;
// didn't load
} else {
}
} else {
}
if ( no < 0 ) {
} else {
}
}
{
int no = -1;
// didn't load
} else {
}
} else {
}
}
{
int no = -1;
// didn't load
} else {
}
} else {
}
if ( no >= 0 ) {
if ( vertical ) {
} else {
}
}
return 0;
}
// Internal function to find baselines
void font_instance::FindFontMetrics() {
// CSS2 recommends using the OS/2 values sTypoAscender and sTypoDescender for the Typographic
// ascender and descender values:
// http://www.w3.org/TR/CSS2/visudet.html#sTypoAscender
// On Windows, the typographic ascender and descender are taken from the otmMacAscent and
// otmMacDescent values:
// The otmAscent and otmDescent values are the maxiumum ascent and maxiumum descent of all the
// glyphs in a font.
if ( theFace ) {
#ifdef USE_PANGO_WIN32
// In CSS em size is ascent + descent... which should be 1. If not,
// adjust so it is.
if( em > 0 ) {
}
// May not be necessary but if OS/2 table missing or not version 2 or higher,
// xheight might be zero.
if( _xheight == 0.0 ) {
_xheight = 0.5;
}
// Baselines defined relative to alphabetic.
int retval;
// Better math baseline:
// Try center of minus sign
retval = GetGlyphOutline (parent->hScreenDC, 0x2212, GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity);
// If no minus sign, try hyphen
if( retval <= 0 )
retval = GetGlyphOutline (parent->hScreenDC, '-', GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity);
if( retval > 0 ) {
}
// Find hanging baseline... assume it is at top of 'म'.
retval = GetGlyphOutline (parent->hScreenDC, 0x092E, GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity);
if( retval > 0 ) {
}
}
#else
if( os2 ) {
} else {
}
// In CSS em size is ascent + descent... which should be 1. If not,
// adjust so it is.
if( em > 0 ) {
}
// x-height
// Only os/2 version 2 and above have sxHeight, 0xffff marks "old Mac fonts" without table
} else {
// Measure 'x' height in font. Recommended option by XSL standard if no sxHeight.
if( index != 0 ) {
} else {
// No 'x' in font!
_xheight = 0.5;
}
}
// Baselines defined relative to alphabetic.
// Better math baseline:
// Try center of minus sign
// If no minus sign, try hyphen
if( index == 0 )
if( index != 0 ) {
// std::cout << "Math baseline: - bbox: y_min: " << acbox.yMin
// << " y_max: " << acbox.yMax
// << " math: " << math << std::endl;
}
// Find hanging baseline... assume it is at top of 'म'.
if( index != 0 ) {
// std::cout << "Hanging baseline: प: " << hanging << std::endl;
}
}
#endif
// const gchar *family = pango_font_description_get_family(descr);
// std::cout << "Font: " << (family?family:"null") << std::endl;
// std::cout << " ascent: " << _ascent << std::endl;
// std::cout << " descent: " << _descent << std::endl;
// std::cout << " x-height: " << _xheight << std::endl;
// std::cout << " max ascent: " << _ascent_max << std::endl;
// std::cout << " max descent: " << _descent_max << std::endl;
// std::cout << " Baselines:" << std::endl;
// std::cout << " alphabetic: " << _baselines[ SP_CSS_BASELINE_ALPHABETIC ] << std::endl;
// std::cout << " ideographic: " << _baselines[ SP_CSS_BASELINE_IDEOGRAPHIC ] << std::endl;
// std::cout << " hanging: " << _baselines[ SP_CSS_BASELINE_HANGING ] << std::endl;
// std::cout << " math: " << _baselines[ SP_CSS_BASELINE_MATHEMATICAL ] << std::endl;
// std::cout << " central: " << _baselines[ SP_CSS_BASELINE_CENTRAL ] << std::endl;
// std::cout << " middle: " << _baselines[ SP_CSS_BASELINE_MIDDLE ] << std::endl;
// std::cout << " text_before: " << _baselines[ SP_CSS_BASELINE_TEXT_BEFORE_EDGE ] << std::endl;
// std::cout << " text_after: " << _baselines[ SP_CSS_BASELINE_TEXT_AFTER_EDGE ] << std::endl;
}
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :