FontInstance.cpp revision c8589a6c7367d09fa756755cef0dd448c7328a71
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * FontInstance.cpp
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * testICU
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Authors:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * fred
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * bulia byak <buliabyak@users.sf.net>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define PANGO_ENABLE_ENGINE
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef HAVE_CONFIG_H
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster# include "config.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <ft2build.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include FT_OUTLINE_H
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include FT_BBOX_H
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include FT_TRUETYPE_TAGS_H
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include FT_TRUETYPE_TABLES_H
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <pango/pangoft2.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <2geom/pathvector.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include <2geom/path-sink.h>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "libnrtype/font-glyph.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "libnrtype/font-instance.h"
c3299845f8822f637c7ff3455a52bcf249597158Sachiko Wallace#include "livarot/Path.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#include "util/unordered-containers.h"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstruct font_style_hash : public std::unary_function<font_style, size_t> {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster size_t operator()(font_style const &x) const;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster};
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstruct font_style_equal : public std::binary_function<font_style, font_style, bool> {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster bool operator()(font_style const &a, font_style const &b) const;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster};
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic const double STROKE_WIDTH_THREASHOLD = 0.01;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
f6d3e8d6653f14cfd38ebbbeac75a12a8536f0c7James Phillpotts
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostersize_t font_style_hash::operator()(const font_style &x) const {
f6d3e8d6653f14cfd38ebbbeac75a12a8536f0c7James Phillpotts int h = 0;
669362f1b4a40a59cfe461728c8765dbdf63159fPhill Cunnington int n = static_cast<int>(floor(100 * x.stroke_width));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h *= 12186;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h += n;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n = (x.vertical) ? 1:0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h *= 12186;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h += n;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( x.stroke_width >= STROKE_WIDTH_THREASHOLD ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n = x.stroke_cap * 10 + x.stroke_join + static_cast<int>(x.stroke_miter_limit * 100);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h *= 12186;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h += n;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( x.nbDash > 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n = x.nbDash;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h *= 12186;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h += n;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n = static_cast<int>(floor(100 * x.dash_offset));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h *= 12186;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h += n;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (int i = 0; i < x.nbDash; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n = static_cast<int>(floor(100 * x.dashes[i]));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h *= 12186;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster h += n;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return h;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterbool font_style_equal::operator()(const font_style &a,const font_style &b) const {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster bool same = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (int i = 0; (i < 6) && same; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster same = ( static_cast<int>(100 * a.transform[i]) == static_cast<int>(100 * b.transform[i]) );
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster same &= ( a.vertical == b.vertical )
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster && ( a.stroke_width > STROKE_WIDTH_THREASHOLD ) == ( b.stroke_width > STROKE_WIDTH_THREASHOLD );
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( same && ( a.stroke_width > STROKE_WIDTH_THREASHOLD ) ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster same = ( a.stroke_cap == b.stroke_cap )
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster && ( a.stroke_join == b.stroke_join )
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster && ( static_cast<int>(a.stroke_miter_limit * 100) == static_cast<int>(b.stroke_miter_limit * 100) )
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster && ( a.nbDash == b.nbDash );
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( same && ( a.nbDash > 0 ) ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster same = ( static_cast<int>(floor(100 * a.dash_offset)) == static_cast<int>(floor(100 * b.dash_offset)) );
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (int i = 0; (i < a.nbDash) && same; i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster same = ( static_cast<int>(floor(100 * a.dashes[i])) == static_cast<int>(floor(100 * b.dashes[i])) );
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return same;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifndef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Outline extraction
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstruct FT2GeomData {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FT2GeomData(Geom::PathBuilder &b, double s)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster : builder(b)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster , last(0, 0)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster , scale(s)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::PathBuilder &builder;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point last;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster double scale;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster};
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster// Note: Freetype 2.2.1 redefined function signatures for functions to be placed in an
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster// FT_Outline_Funcs structure. This is needed to keep backwards compatibility with the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster// 2.1.x series.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* *** BEGIN #if HACK *** */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#if FREETYPE_MAJOR == 2 && FREETYPE_MINOR >= 2
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertypedef FT_Vector const FREETYPE_VECTOR;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostertypedef FT_Vector FREETYPE_VECTOR;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster// outline as returned by freetype -> livarot Path
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster// see nr-type-ft2.cpp for the freetype -> artBPath on which this code is based
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int ft2_move_to(FREETYPE_VECTOR *to, void * i_user)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FT2GeomData *user = (FT2GeomData*)i_user;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point p(to->x, to->y);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // printf("m t=%f %f\n",p[0],p[1]);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster user->builder.moveTo(p * user->scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster user->last = p;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int ft2_line_to(FREETYPE_VECTOR *to, void *i_user)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FT2GeomData *user = (FT2GeomData*)i_user;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point p(to->x, to->y);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // printf("l t=%f %f\n",p[0],p[1]);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster user->builder.lineTo(p * user->scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster user->last = p;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int ft2_conic_to(FREETYPE_VECTOR *control, FREETYPE_VECTOR *to, void *i_user)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FT2GeomData *user = (FT2GeomData*)i_user;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point p(to->x, to->y), c(control->x, control->y);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster user->builder.quadTo(c * user->scale, p * user->scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // printf("b c=%f %f t=%f %f\n",c[0],c[1],p[0],p[1]);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster user->last = p;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic int ft2_cubic_to(FREETYPE_VECTOR *control1, FREETYPE_VECTOR *control2, FREETYPE_VECTOR *to, void *i_user)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FT2GeomData *user = (FT2GeomData*)i_user;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point p(to->x, to->y);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point c1(control1->x, control1->y);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point c2(control2->x, control2->y);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // printf("c c1=%f %f c2=%f %f t=%f %f\n",c1[0],c1[1],c2[0],c2[1],p[0],p[1]);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //user->theP->CubicTo(p,3*(c1-user->last),3*(p-c2));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster user->builder.curveTo(c1 * user->scale, c2 * user->scale, p * user->scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster user->last = p;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/* *** END #if HACK *** */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterfont_instance::font_instance(void) :
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pFont(0),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster descr(0),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster refCount(0),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster daddy(0),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster nbGlyph(0),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster maxGlyph(0),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster glyphs(0),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster theFace(0)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //printf("font instance born\n");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterfont_instance::~font_instance(void)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( daddy ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster daddy->UnrefFace(this);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster daddy = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //printf("font instance death\n");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( pFont ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FreeTheFace();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster g_object_unref(pFont);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pFont = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( descr ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pango_font_description_free(descr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster descr = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // if ( theFace ) FT_Done_Face(theFace); // owned by pFont. don't touch
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster theFace = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (int i=0;i<nbGlyph;i++) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( glyphs[i].pathvector ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster delete glyphs[i].pathvector;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( glyphs ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster free(glyphs);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster glyphs = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster nbGlyph = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster maxGlyph = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostervoid font_instance::Ref(void)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster refCount++;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //char *tc=pango_font_description_to_string(descr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //printf("font %x %s ref'd %i\n",this,tc,refCount);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //free(tc);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostervoid font_instance::Unref(void)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster refCount--;
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts //char *tc=pango_font_description_to_string(descr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //printf("font %x %s unref'd %i\n",this,tc,refCount);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //free(tc);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( refCount <= 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster delete this;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterunsigned int font_instance::Name(gchar *str, unsigned int size)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return Attribute("name", str, size);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterunsigned int font_instance::Family(gchar *str, unsigned int size)
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return Attribute("family", str, size);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterunsigned int font_instance::PSName(gchar *str, unsigned int size)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return Attribute("psname", str, size);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterunsigned int font_instance::Attribute(const gchar *key, gchar *str, unsigned int size)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( descr == NULL ) {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts if ( size > 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster str[0]=0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char* res=NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster bool free_res=false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( strcmp(key,"name") == 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PangoFontDescription* td=pango_font_description_copy(descr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pango_font_description_unset_fields (td, PANGO_FONT_MASK_SIZE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=pango_font_description_to_string (td);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pango_font_description_free(td);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster free_res=true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( strcmp(key,"psname") == 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifndef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res = (char *) FT_Get_Postscript_Name (theFace); // that's the main method, seems to always work
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster free_res=false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (res == NULL) { // a very limited workaround, only bold, italic, and oblique will work
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PangoStyle style=pango_font_description_get_style(descr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster bool i = (style == PANGO_STYLE_ITALIC);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster bool o = (style == PANGO_STYLE_OBLIQUE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PangoWeight weight=pango_font_description_get_weight(descr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster bool b = (weight >= PANGO_WEIGHT_BOLD);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res = g_strdup_printf ("%s%s%s%s",
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster sp_font_description_get_family(descr),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster (b || i || o) ? "-" : "",
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster (b) ? "Bold" : "",
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster (i) ? "Italic" : ((o) ? "Oblique" : "") );
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster free_res = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( strcmp(key,"family") == 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)sp_font_description_get_family(descr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster free_res=false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( strcmp(key,"style") == 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PangoStyle v=pango_font_description_get_style(descr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( v == PANGO_STYLE_ITALIC ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"italic";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( v == PANGO_STYLE_OBLIQUE ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"oblique";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"normal";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster free_res=false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( strcmp(key,"weight") == 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PangoWeight v=pango_font_description_get_weight(descr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( v <= PANGO_WEIGHT_THIN ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"100";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( v <= PANGO_WEIGHT_ULTRALIGHT ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"200";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( v <= PANGO_WEIGHT_LIGHT ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"300";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( v <= PANGO_WEIGHT_BOOK ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"380";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( v <= PANGO_WEIGHT_NORMAL ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"normal";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( v <= PANGO_WEIGHT_MEDIUM ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"500";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( v <= PANGO_WEIGHT_SEMIBOLD ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"600";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( v <= PANGO_WEIGHT_BOLD ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"bold";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( v <= PANGO_WEIGHT_ULTRABOLD ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"800";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else { // HEAVY NB: Pango defines ULTRAHEAVY = 1000 but not CSS2
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"900";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster free_res=false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( strcmp(key,"stretch") == 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PangoStretch v=pango_font_description_get_stretch(descr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( v <= PANGO_STRETCH_EXTRA_CONDENSED ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"extra-condensed";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( v <= PANGO_STRETCH_CONDENSED ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res=(char*)"condensed";
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts } else if ( v <= PANGO_STRETCH_SEMI_CONDENSED ) {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts res=(char*)"semi-condensed";
f6d3e8d6653f14cfd38ebbbeac75a12a8536f0c7James Phillpotts } else if ( v <= PANGO_STRETCH_NORMAL ) {
f6d3e8d6653f14cfd38ebbbeac75a12a8536f0c7James Phillpotts res=(char*)"normal";
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts } else if ( v <= PANGO_STRETCH_SEMI_EXPANDED ) {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts res=(char*)"semi-expanded";
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts } else if ( v <= PANGO_STRETCH_EXPANDED ) {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts res=(char*)"expanded";
a2b64c9e3378d4d0127e550f5d19286f37d42011James Phillpotts } else {
a2b64c9e3378d4d0127e550f5d19286f37d42011James Phillpotts res=(char*)"extra-expanded";
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts }
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts free_res=false;
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts } else if ( strcmp(key,"variant") == 0 ) {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts PangoVariant v=pango_font_description_get_variant(descr);
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts if ( v == PANGO_VARIANT_SMALL_CAPS ) {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts res=(char*)"small-caps";
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts } else {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts res=(char*)"normal";
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts }
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts free_res=false;
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts } else {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts res = NULL;
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts free_res=false;
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts }
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts if ( res == NULL ) {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts if ( size > 0 ) {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts str[0] = 0;
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts }
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts return 0;
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts }
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts if (res) {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts unsigned int len=strlen(res);
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts unsigned int rlen=(size-1<len)?size-1:len;
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts if ( str ) {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts if ( rlen > 0 ) {
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts memcpy(str, res, rlen);
d135fba117a27e6d0de2f5518a274bba4c0a38efJames Phillpotts }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( size > 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster str[rlen] = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (free_res) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster g_free(res);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return len;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostervoid font_instance::InitTheFace()
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (theFace == NULL && pFont != NULL) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( !theFace ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LOGFONT *lf=pango_win32_font_logfont(pFont);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster g_assert(lf != NULL);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster theFace=pango_win32_font_cache_load(daddy->pangoFontCache,lf);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster g_free(lf);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster XFORM identity = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SetWorldTransform(daddy->hScreenDC, &identity);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SetGraphicsMode(daddy->hScreenDC, GM_COMPATIBLE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SelectObject(daddy->hScreenDC,theFace);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster theFace=pango_fc_font_lock_face(PANGO_FC_FONT(pFont));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( theFace ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FT_Select_Charmap(theFace,ft_encoding_unicode) && FT_Select_Charmap(theFace,ft_encoding_symbol);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostervoid font_instance::FreeTheFace()
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster SelectObject(daddy->hScreenDC,GetStockObject(SYSTEM_FONT));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pango_win32_font_cache_unload(daddy->pangoFontCache,theFace);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pango_fc_font_unlock_face(PANGO_FC_FONT(pFont));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster theFace=NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostervoid font_instance::InstallFace(PangoFont* iFace)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( !iFace ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pFont=iFace;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster iFace = NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster InitTheFace();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( pFont && IsOutlineFont() == false ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FreeTheFace();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( pFont ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster g_object_unref(pFont);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pFont=NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterbool font_instance::IsOutlineFont(void)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( pFont == NULL ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster InitTheFace();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster TEXTMETRIC tm;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return GetTextMetrics(daddy->hScreenDC,&tm) && tm.tmPitchAndFamily&(TMPF_TRUETYPE|TMPF_DEVICE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return FT_IS_SCALABLE(theFace);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterint font_instance::MapUnicodeChar(gunichar c)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int res = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( pFont ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res = pango_win32_font_get_glyph_index(pFont, c);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster theFace = pango_fc_font_lock_face(PANGO_FC_FONT(pFont));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( c > 0xf0000 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res = CLAMP(c, 0xf0000, 0x1fffff) - 0xf0000;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster res = FT_Get_Char_Index(theFace, c);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pango_fc_font_unlock_face(PANGO_FC_FONT(pFont));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return res;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterstatic inline Geom::Point pointfx_to_nrpoint(const POINTFX &p, double scale)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return Geom::Point(*(long*)&p.x / 65536.0 * scale,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *(long*)&p.y / 65536.0 * scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fostervoid font_instance::LoadGlyph(int glyph_id)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( pFont == NULL ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster InitTheFace();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifndef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( !FT_IS_SCALABLE(theFace) ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return; // bitmap font
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::PathBuilder path_builder;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( nbGlyph >= maxGlyph ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster maxGlyph=2*nbGlyph+1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster font_glyph n_g;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.pathvector=NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.h_advance = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.v_advance = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.h_width = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.v_width = 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster bool doAdd=false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifndef GGO_UNHINTED // For compatibility with old SDKs.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#define GGO_UNHINTED 0x0100
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster OUTLINETEXTMETRIC otm;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster GetOutlineTextMetrics(daddy->hScreenDC, sizeof(otm), &otm);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster GLYPHMETRICS metrics;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DWORD bufferSize=GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster double scale=1.0/daddy->fontSize;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.h_advance=metrics.gmCellIncX*scale;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.v_advance=otm.otmTextMetrics.tmHeight*scale;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.h_width=metrics.gmBlackBoxX*scale;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.v_width=metrics.gmBlackBoxY*scale;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( bufferSize == GDI_ERROR) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // shit happened
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else if ( bufferSize == 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // character has no visual representation, but is valid (eg whitespace)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster doAdd=true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster char *buffer = new char[bufferSize];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer, &identity) <= 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // shit happened
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // Platform SDK is rubbish, read KB87115 instead
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DWORD polyOffset=0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while ( polyOffset < bufferSize ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer+polyOffset);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (polyOffset+polyHeader->cb > bufferSize) break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (polyHeader->dwType == TT_POLYGON_TYPE) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster path_builder.moveTo(pointfx_to_nrpoint(polyHeader->pfxStart, scale));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DWORD curveOffset=polyOffset+sizeof(TTPOLYGONHEADER);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while ( curveOffset < polyOffset+polyHeader->cb ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster TTPOLYCURVE const *polyCurve=(TTPOLYCURVE const *)(buffer+curveOffset);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster POINTFX const *p=polyCurve->apfx;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster POINTFX const *endp=p+polyCurve->cpfx;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster switch (polyCurve->wType) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster case TT_PRIM_LINE:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while ( p != endp )
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster path_builder.lineTo(pointfx_to_nrpoint(*p++, scale));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster case TT_PRIM_QSPLINE:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster g_assert(polyCurve->cpfx >= 2);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // The list of points specifies one or more control points and ends with the end point.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // The intermediate points (on the curve) are the points between the control points.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point this_control = pointfx_to_nrpoint(*p++, scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while ( p+1 != endp ) { // Process all "midpoints" (all points except the last)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point new_control = pointfx_to_nrpoint(*p++, scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster path_builder.quadTo(this_control, (new_control+this_control)/2);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster this_control = new_control;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point end = pointfx_to_nrpoint(*p++, scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster path_builder.quadTo(this_control, end);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster case 3: // TT_PRIM_CSPLINE
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster g_assert(polyCurve->cpfx % 3 == 0);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster while ( p != endp ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster path_builder.curveTo(pointfx_to_nrpoint(p[0], scale),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pointfx_to_nrpoint(p[1], scale),
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster pointfx_to_nrpoint(p[2], scale));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster p += 3;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster break;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster curveOffset += sizeof(TTPOLYCURVE)+sizeof(POINTFX)*(polyCurve->cpfx-1);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster polyOffset += polyHeader->cb;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster doAdd=true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster delete [] buffer;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // shit happened
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( FT_HAS_HORIZONTAL(theFace) ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.h_advance=((double)theFace->glyph->metrics.horiAdvance)/((double)theFace->units_per_EM);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.h_width=((double)theFace->glyph->metrics.width)/((double)theFace->units_per_EM);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( FT_HAS_VERTICAL(theFace) ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.v_advance=((double)theFace->glyph->metrics.vertAdvance)/((double)theFace->units_per_EM);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.v_width=((double)theFace->glyph->metrics.height)/((double)theFace->units_per_EM);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.v_width=n_g.v_advance=((double)theFace->height)/((double)theFace->units_per_EM);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( theFace->glyph->format == ft_glyph_format_outline ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FT_Outline_Funcs ft2_outline_funcs = {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ft2_move_to,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ft2_line_to,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ft2_conic_to,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ft2_cubic_to,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster 0, 0
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster };
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FT2GeomData user(path_builder, 1.0/((double)theFace->units_per_EM));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &user);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster doAdd=true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster path_builder.flush();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( doAdd ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::PathVector pv = path_builder.peek();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // close all paths
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (Geom::PathVector::iterator i = pv.begin(); i != pv.end(); ++i) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster i->close();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( !pv.empty() ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.pathvector = new Geom::PathVector(pv);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::OptRect bounds = bounds_exact(*n_g.pathvector);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (bounds) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.bbox[0] = bounds->left();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.bbox[1] = bounds->top();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.bbox[2] = bounds->right();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster n_g.bbox[3] = bounds->bottom();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster glyphs[nbGlyph]=n_g;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster id_to_no[glyph_id]=nbGlyph;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster nbGlyph++;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterbool font_instance::FontMetrics(double &ascent,double &descent,double &leading)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( pFont == NULL ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster InitTheFace();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( theFace == NULL ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster OUTLINETEXTMETRIC otm;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( !GetOutlineTextMetrics(daddy->hScreenDC,sizeof(otm),&otm) ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster double scale=1.0/daddy->fontSize;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ascent=fabs(otm.otmAscent*scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster descent=fabs(otm.otmDescent*scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster leading=fabs(otm.otmLineGap*scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //otmSubscriptSize, otmSubscriptOffset, otmSuperscriptSize, otmSuperscriptOffset,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( theFace->units_per_EM == 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false; // bitmap font
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ascent=fabs(((double)theFace->ascender)/((double)theFace->units_per_EM));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster descent=fabs(((double)theFace->descender)/((double)theFace->units_per_EM));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster leading=fabs(((double)theFace->height)/((double)theFace->units_per_EM));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster leading-=ascent+descent;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterbool font_instance::FontDecoration(
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster double &underline_position, double &underline_thickness,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster double &linethrough_position, double &linethrough_thickness
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster){
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( pFont == NULL ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster InitTheFace();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( theFace == NULL ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster OUTLINETEXTMETRIC otm;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( !GetOutlineTextMetrics(daddy->hScreenDC,sizeof(otm),&otm) ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster double scale=1.0/daddy->fontSize;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster underline_position = fabs(otm.otmUnderscorePosition *scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster underline_thickness = fabs(otm.otmUnderscoreSize *scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster linethrough_position = fabs(otm.otmStrikeoutPosition *scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster linethrough_thickness = fabs(otm.otmStrikeoutSize *scale);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( theFace->units_per_EM == 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false; // bitmap font
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster underline_position = fabs(((double)theFace->underline_position )/((double)theFace->units_per_EM));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster underline_thickness = fabs(((double)theFace->underline_thickness)/((double)theFace->units_per_EM));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // there is no specific linethrough information, mock it up from other font fields
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster linethrough_position = fabs(((double)theFace->ascender / 3.0 )/((double)theFace->units_per_EM));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster linethrough_thickness = fabs(((double)theFace->underline_thickness)/((double)theFace->units_per_EM));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterbool font_instance::FontSlope(double &run, double &rise)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster run = 0.0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rise = 1.0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( pFont == NULL ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster InitTheFace();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( theFace == NULL ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#ifdef USE_PANGO_WIN32
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster OUTLINETEXTMETRIC otm;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( !GetOutlineTextMetrics(daddy->hScreenDC,sizeof(otm),&otm) ) return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster run=otm.otmsCharSlopeRun;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rise=otm.otmsCharSlopeRise;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#else
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( !FT_IS_SCALABLE(theFace) ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false; // bitmap font
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster TT_HoriHeader *hhea = (TT_HoriHeader*)FT_Get_Sfnt_Table(theFace, ft_sfnt_hhea);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (hhea == NULL) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster run = hhea->caret_Slope_Run;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster rise = hhea->caret_Slope_Rise;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster#endif
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterGeom::OptRect font_instance::BBox(int glyph_id)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int no = -1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LoadGlyph(glyph_id);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // didn't load
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster no = id_to_no[glyph_id];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster no = id_to_no[glyph_id];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( no < 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return Geom::OptRect();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point rmin(glyphs[no].bbox[0],glyphs[no].bbox[1]);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Geom::Point rmax(glyphs[no].bbox[2],glyphs[no].bbox[3]);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return Geom::Rect(rmin, rmax);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan FosterGeom::PathVector* font_instance::PathVector(int glyph_id)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int no = -1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LoadGlyph(glyph_id);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // didn't load
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster no = id_to_no[glyph_id];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster no = id_to_no[glyph_id];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( no < 0 ) return NULL;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return glyphs[no].pathvector;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterdouble font_instance::Advance(int glyph_id,bool vertical)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster{
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int no = -1;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster LoadGlyph(glyph_id);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // didn't load
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster no=id_to_no[glyph_id];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster no = id_to_no[glyph_id];
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( no >= 0 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( vertical ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return glyphs[no].v_advance;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster } else {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return glyphs[no].h_advance;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return 0;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/*
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Local Variables:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster mode:c++
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster c-file-style:"stroustrup"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster indent-tabs-mode:nil
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster fill-column:99
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster End:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster