Logo Search packages:      
Sourcecode: passepartout version File versions  Download package

freetype.cc

///
// Copyright (C) 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING
///
#include "freetype.hh"
#include "util/stringutil.h"
#include "util/warning.h"
#include <cassert>
#include FT_TRUETYPE_TABLES_H

FT_Library font::FTMetrics::library = 0;

namespace {
  void fterr(int err) {
    if(err)
      /// \todo readable error messages
      throw std::runtime_error("FT error " + tostr(err));
  }
}

namespace {
  /// convert from signed 16.16 fixed point (not tested much)
  double from_fixed(FT_Fixed a) {
    return double(a) / (1 << 16);
  }
}

font::FTMetrics::FTMetrics(const std::string &filename)
  : face(0), exHeight(1), capHeight(1), italicAngle(0)
{
  if(!library)
    fterr(FT_Init_FreeType(&library));

  fterr(FT_New_Face(library, filename.c_str(), 0, &face));
  TT_PCLT *pclt = static_cast<TT_PCLT*>(FT_Get_Sfnt_Table(face, ft_sfnt_pclt));
  if(pclt) {
    exHeight = float(pclt->xHeight) / face->units_per_EM;
    capHeight = float(pclt->CapHeight) / face->units_per_EM;
  }
  TT_Postscript *post =
    static_cast<TT_Postscript*>(FT_Get_Sfnt_Table(face, ft_sfnt_post));
  if(post) {
    italicAngle = from_fixed(post->italicAngle);
  }
}

font::FTMetrics::~FTMetrics() {
  int error = FT_Done_Face(face);
  if(error)
    std::cerr << "Error " << error << " when releasing typeface" << std::endl;
}

00052 std::string font::FTMetrics::getName() const {
  std::string name(face->family_name);
  if(face->style_name) {
    name += " ";
    name += face->style_name;
  }
  return name;
}

00061 std::string font::FTMetrics::getPostscriptName() const {
  const char *name = FT_Get_Postscript_Name(face);
  return name ? name : "";
}

00066 float font::FTMetrics::getWidth(const Glib::ustring &str) const {
  float w = 0;
  for(Glib::ustring::const_iterator i = str.begin(); i != str.end(); i++) {
    FT_UInt glyph_index = FT_Get_Char_Index(face, *i);
    // FT_LOAD_NO_SCALE gives metrics in "designer" units (the
    // unscaled internal font units)
    int err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE);
    if(!err)
      w += face->glyph->metrics.horiAdvance;
    else {
      w += 0.625; // reasonable default?
      verbose << "Glyph #" << glyph_index << " not found" << std::endl;
    }
  }
  return w / face->units_per_EM;
}

00083 float font::FTMetrics::getAscender()  const {
  return float(face->ascender) / face->units_per_EM;
}

00087 float font::FTMetrics::getDescender() const {
  return -float(face->descender) / face->units_per_EM;
}

00091 float font::FTMetrics::getExHeight() const { return exHeight; }

00093 float font::FTMetrics::getCapHeight() const { return capHeight; }

00095 float font::FTMetrics::getUnderlinePos() const {
  return float(face->underline_position) / face->units_per_EM;
}

00099 float font::FTMetrics::getUnderlineThickness() const {
  return float(face->underline_thickness) / face->units_per_EM;
}

00103 float font::FTMetrics::getItalicAngle() const { return italicAngle; }

00105 std::string font::FTMetrics::nameOfGlyph(unsigned int glyph_index) const {
  const int buffer_size = 30;
  char buffer[buffer_size];
  if(!FT_Get_Glyph_Name(face, glyph_index, &buffer, buffer_size))
    return buffer;
  return "";
}

00113 std::string font::FTMetrics::getGlyphName(const Glib::ustring &chars) const {
  if(chars.length() != 1)
    return "";
  return nameOfGlyph(get_glyph_index(chars[0]));
}

unsigned int font::FTMetrics::get_glyph_index(gunichar c) const {
  return FT_Get_Char_Index(face, c);
}

namespace {
  /// wub16 == "write unsigned bigendian 16-bit"
  std::ostream& wub16(std::ostream &out, unsigned int x) {
    x &= 0xFFFF;
    unsigned char l = x & 0xFF;
    unsigned char h = x >> 8;
    out << h << l;
    return out;
  }
}

void font::FTMetrics::write_CIDToGIDMap(std::ostream &out) const {
  for(int i = 0; i < 0xffff; i++)
    // 16 bit indices, high-order byte first
    wub16(out, get_glyph_index(i));
  out << std::flush;
}

00141 int font::FTMetrics::getBBox(int idx) const {
  assert(0 <= idx && idx < 4);
  int tmp;
  switch(idx) {
  case 0: tmp = face->bbox.xMin; break;
  case 1: tmp = face->bbox.yMin; break;
  case 2: tmp = face->bbox.xMax; break;
  case 3: tmp = face->bbox.yMax; break;
  default: break;
  }
  // convert to postscript font units (em/1000)
  return (1000 * tmp) / int(face->units_per_EM);
}

#ifdef FREETYPE_STANDALONE

#include <iostream>

int main(int argc, char **argv) {
  using namespace std;
  try {
    using namespace font;
    FTMetrics fnt(argv[1]);
    cout << fnt.getWidth("Hej hej, Monika!") << endl;
    cout << fnt.getAscender() << endl;
    cout << fnt.getDescender() << endl;
    cout << fnt.getGlyphName("C") << endl;
  }
  catch(const exception &e) {
    cerr << e.what() << endl;
  }
}

#endif

Generated by  Doxygen 1.6.0   Back to index