/*
 * This file was generated automatically by ExtUtils::ParseXS version 3.35 from the
 * contents of FreeType.xs. Do not edit this file, edit FreeType.xs instead.
 *
 *    ANY CHANGES MADE HERE WILL BE LOST!
 *
 */

#line 1 "FreeType.xs"
/* Perl binding for the FreeType font rendering library.
 *
 * Copyright 2004, Geoff Richards.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the same terms as Perl itself.
 */

#ifdef __cplusplus
extern "C" {
#endif
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#ifdef __cplusplus
}
#endif

#include <ft2build.h>
#include FT_SFNT_NAMES_H
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_OUTLINE_H
#include FT_BBOX_H
#include FT_TYPE1_TABLES_H

#undef assert
#include <assert.h>

/* utf8_to_uvchr is deprecated in 5.16, but
 * utf8_to_uvchr_buf is not available before 5.16
 * If I need to get fancier, I should look at Dumper.xs
 * in Data::Dumper
 */
#if PERL_VERSION <= 15 && ! defined(utf8_to_uvchr_buf)
#define utf8_to_uvchr_buf(s, send, p_length) (utf8_to_uvchr(s, p_length))
#endif

/* Macro for testing whether we have at least a certain version of
 * Freetype available.  */
#define QEFFT2_FT_AT_LEAST(major, minor, patch) \
    FREETYPE_MAJOR > major || \
        (FREETYPE_MAJOR == major && \
            (FREETYPE_MINOR > minor || \
                (FREETYPE_MINOR == minor && FREETYPE_PATCH >= patch)))

/* Define the newer names for constants in terms of the old names if we're
 * compiling against an old version of the library.  These uppercase
 * constants, which are defined in enums, were added in Freetype 2.1.3.  */
#if !(QEFFT2_FT_AT_LEAST(2,1,3))
#define FT_GLYPH_FORMAT_NONE ft_glyph_format_none
#define FT_GLYPH_FORMAT_COMPOSITE ft_glyph_format_composite
#define FT_GLYPH_FORMAT_BITMAP ft_glyph_format_bitmap
#define FT_GLYPH_FORMAT_OUTLINE ft_glyph_format_outline
#define FT_GLYPH_FORMAT_PLOTTER ft_glyph_format_plotter
#define FT_RENDER_MODE_NORMAL ft_render_mode_normal
#define FT_RENDER_MODE_MONO ft_render_mode_mono
#define FT_PIXEL_MODE_NONE ft_pixel_mode_none
#define FT_PIXEL_MODE_MONO ft_pixel_mode_mono
#define FT_PIXEL_MODE_GRAY ft_pixel_mode_grays
#define FT_PIXEL_MODE_GRAY2 ft_pixel_mode_pal2
#define FT_PIXEL_MODE_GRAY4 ft_pixel_mode_pal4
#define FT_KERNING_DEFAULT ft_kerning_default
#define FT_KERNING_UNFITTED ft_kerning_unfitted
#define FT_KERNING_UNSCALED ft_kerning_unscaled
#endif

#define QEF_BUF_SZ 256

/* Scary macrology follows, stolen from fterrors.h
 * This stuff sets up a table mapping error codes to descriptive strings.
 * I find the whole idea of 'callback macros' rather distasteful though.
 */
#undef __FTERRORS_H__
#define FT_ERRORDEF( e, v, s )  { e, s },
#define FT_ERROR_START_LIST {
#define FT_ERROR_END_LIST { 0, 0 } };
struct QefFT2_Errstr_
{
  int num;
  const char *message;
};
typedef struct QefFT2_Errstr_ QefFT2_Errstr;
QefFT2_Errstr qefft2_errstr[] = /* rest filled in by the header */
#include FT_ERRORS_H

#define ftnum_to_nv(num) newSVnv((double) (num) / 1.0)

struct QefFT2_Glyph_
{
    SV *face_sv;
    FT_ULong char_code;     /* 0 if not yet known */
    bool has_char_code;
    FT_UInt index;
    char *name;
};
struct QefFT2_Face_Extra_
{
    SV *library_sv;
    FT_UInt loaded_glyph_idx;
    FT_Int32 glyph_load_flags;
    FT_Glyph glyph_ft;
    int slot_valid;
};
typedef struct QefFT2_Face_Extra_ QefFT2_Face_Extra;

struct QefFT2_Outline_Decompose_Extra_
{
    SV *move_to;
    SV *line_to;
    SV *conic_to;
    SV *cubic_to;
    double curx, cury;
};

typedef FT_Library Font_FreeType;
typedef FT_Face Font_FreeType_Face;
typedef FT_CharMap Font_FreeType_CharMap;
typedef FT_BBox* Font_FreeType_BoundingBox;
typedef FT_SfntName* Font_FreeType_NamedInfo;
typedef struct QefFT2_Glyph_ * Font_FreeType_Glyph;


/* Table of FreeType constants, for exporting into Perl.  */
#define QEFFT2_CONSTANT(symbol) { #symbol, symbol },
struct QefFT2_Uv_Const_
{
    char *name;
    UV value;
};
typedef struct QefFT2_Uv_Const_ QefFT2_Uv_Const;
const static QefFT2_Uv_Const qefft2_uv_const[] =
{
    QEFFT2_CONSTANT(FT_LOAD_DEFAULT)
    QEFFT2_CONSTANT(FT_LOAD_NO_SCALE)
    QEFFT2_CONSTANT(FT_LOAD_NO_HINTING)
    QEFFT2_CONSTANT(FT_LOAD_NO_BITMAP)
    QEFFT2_CONSTANT(FT_LOAD_VERTICAL_LAYOUT)
    QEFFT2_CONSTANT(FT_LOAD_FORCE_AUTOHINT)
    QEFFT2_CONSTANT(FT_LOAD_CROP_BITMAP)
    QEFFT2_CONSTANT(FT_LOAD_PEDANTIC)
    QEFFT2_CONSTANT(FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)
    /* FT_LOAD_NO_RECURSE - for internal use only*/
    QEFFT2_CONSTANT(FT_LOAD_IGNORE_TRANSFORM)
    QEFFT2_CONSTANT(FT_LOAD_LINEAR_DESIGN)
#if QEFFT2_FT_AT_LEAST(2,1,3)
    QEFFT2_CONSTANT(FT_LOAD_NO_AUTOHINT)
#endif
#if QEFFT2_FT_AT_LEAST(2,6,1)
    QEFFT2_CONSTANT(FT_LOAD_COMPUTE_METRICS)
#endif
    QEFFT2_CONSTANT(FT_RENDER_MODE_NORMAL)
#if QEFFT2_FT_AT_LEAST(2,1,4)
    QEFFT2_CONSTANT(FT_RENDER_MODE_LIGHT)
#endif
    QEFFT2_CONSTANT(FT_RENDER_MODE_MONO)
#if QEFFT2_FT_AT_LEAST(2,1,3)
    QEFFT2_CONSTANT(FT_RENDER_MODE_LCD)
    QEFFT2_CONSTANT(FT_RENDER_MODE_LCD_V)
#endif
    QEFFT2_CONSTANT(FT_KERNING_DEFAULT)
    QEFFT2_CONSTANT(FT_KERNING_UNFITTED)
    QEFFT2_CONSTANT(FT_KERNING_UNSCALED)

    QEFFT2_CONSTANT(FT_ENCODING_NONE)
    QEFFT2_CONSTANT(FT_ENCODING_UNICODE)
    QEFFT2_CONSTANT(FT_ENCODING_MS_SYMBOL)
    QEFFT2_CONSTANT(FT_ENCODING_SJIS)
    QEFFT2_CONSTANT(FT_ENCODING_GB2312)
    QEFFT2_CONSTANT(FT_ENCODING_BIG5)
    QEFFT2_CONSTANT(FT_ENCODING_WANSUNG)
    QEFFT2_CONSTANT(FT_ENCODING_JOHAB)
    QEFFT2_CONSTANT(FT_ENCODING_ADOBE_LATIN_1)
    QEFFT2_CONSTANT(FT_ENCODING_ADOBE_STANDARD)
    QEFFT2_CONSTANT(FT_ENCODING_ADOBE_EXPERT)
    QEFFT2_CONSTANT(FT_ENCODING_ADOBE_CUSTOM)
    QEFFT2_CONSTANT(FT_ENCODING_APPLE_ROMAN)
    QEFFT2_CONSTANT(FT_ENCODING_OLD_LATIN_2)
    QEFFT2_CONSTANT(FT_ENCODING_MS_SJIS)
    QEFFT2_CONSTANT(FT_ENCODING_MS_GB2312)
    QEFFT2_CONSTANT(FT_ENCODING_MS_BIG5)
    QEFFT2_CONSTANT(FT_ENCODING_MS_WANSUNG)
    QEFFT2_CONSTANT(FT_ENCODING_MS_JOHAB)
};

static void
errchk (FT_Error err, const char *desc)
{
    QefFT2_Errstr *errmap;

    if (err == 0)
        return;

    errmap = qefft2_errstr;
    while (errmap->message) {
        if (errmap->num == err) {
            croak("error %s: %s", desc, errmap->message);
        }
        ++errmap;
    }

    croak("error %s: unknown error code", desc);
}

static SV *
make_glyph (SV *face_sv, FT_ULong char_code, bool has_cc, FT_UInt index)
{
    Font_FreeType_Glyph glyph;
    SV *sv;
    Newx(glyph, 1, struct QefFT2_Glyph_);

    glyph->face_sv = face_sv;
    SvREFCNT_inc(face_sv);

    glyph->char_code = char_code;
    glyph->has_char_code = has_cc;
    glyph->index = index;
    glyph->name = 0;

    sv = newSV(0);
    sv_setref_pv(sv, "Font::FreeType::Glyph", (void *) glyph);
    return sv;
}

static FT_GlyphSlot
ensure_glyph_loaded (FT_Face face, Font_FreeType_Glyph glyph)
{
    QefFT2_Face_Extra *extra = face->generic.data;

    if (extra->loaded_glyph_idx != glyph->index || !extra->slot_valid) {
        if (extra->glyph_ft) {
            FT_Done_Glyph(extra->glyph_ft);
            extra->glyph_ft = 0;
        }
        errchk(FT_Load_Glyph(face, glyph->index, extra->glyph_load_flags),
               "loading freetype glyph");
        extra->loaded_glyph_idx = glyph->index;
        extra->slot_valid = 1;
    }

    return face->glyph;
}

static bool
ensure_outline_loaded (FT_Face face, Font_FreeType_Glyph glyph)
{
    QefFT2_Face_Extra *extra;
    ensure_glyph_loaded(face, glyph);

    extra = face->generic.data;
    if (!extra->glyph_ft)
        errchk(FT_Get_Glyph(face->glyph, &extra->glyph_ft),
               "getting glyph object from freetype");

    return extra->glyph_ft->format == FT_GLYPH_FORMAT_OUTLINE;
}

/* Macros to help the outline event handlers call Perl code */
#define QEFFT2_CALL_PREP  dSP; ENTER; SAVETMPS; PUSHMARK(SP);
#define QEFFT2_NUM(num)  ((double) (num) / 64.0)
#define QEFFT2_PUSH_NUM(num)  XPUSHs(sv_2mortal(newSVnv((double) num / 64.0)));
#define QEFFT2_PUSH_DNUM(num)  XPUSHs(sv_2mortal(newSVnv(num)));
#define QEFFT2_CALL(code)  PUTBACK; call_sv(code, G_DISCARD);
#define QEFFT2_CALL_TIDY  FREETMPS; LEAVE;

static int
handle_move_to (const FT_Vector *to, void *data)
{
    struct QefFT2_Outline_Decompose_Extra_ *extra = data;
    double x = QEFFT2_NUM(to->x), y = QEFFT2_NUM(to->y);

    QEFFT2_CALL_PREP
    QEFFT2_PUSH_DNUM(x)
    QEFFT2_PUSH_DNUM(y)
    QEFFT2_CALL(extra->move_to)
    QEFFT2_CALL_TIDY

    extra->curx = x;
    extra->cury = y;
    return 0;
}

static int
handle_line_to (const FT_Vector *to, void *data)
{
    struct QefFT2_Outline_Decompose_Extra_ *extra = data;
    double x = QEFFT2_NUM(to->x), y = QEFFT2_NUM(to->y);

    QEFFT2_CALL_PREP
    QEFFT2_PUSH_DNUM(x)
    QEFFT2_PUSH_DNUM(y)
    QEFFT2_CALL(extra->line_to)
    QEFFT2_CALL_TIDY

    extra->curx = x;
    extra->cury = y;
    return 0;
}

static int
handle_conic_to (const FT_Vector *control, const FT_Vector *to, void *data)
{
    struct QefFT2_Outline_Decompose_Extra_ *extra = data;
    double x = QEFFT2_NUM(to->x), y = QEFFT2_NUM(to->y);
    double cx = QEFFT2_NUM(control->x), cy = QEFFT2_NUM(control->y);

    QEFFT2_CALL_PREP
    QEFFT2_PUSH_DNUM(x)
    QEFFT2_PUSH_DNUM(y)

    /* If there's no conic callback, simulate an equivalent cubic one */
    if (extra->conic_to) {
        QEFFT2_PUSH_DNUM(cx)
        QEFFT2_PUSH_DNUM(cy)
        QEFFT2_CALL(extra->conic_to)
    }
    else {
        QEFFT2_PUSH_DNUM((extra->curx + 2 * cx) / 3)
        QEFFT2_PUSH_DNUM((extra->cury + 2 * cy) / 3)
        QEFFT2_PUSH_DNUM((2 * cx + x) / 3)
        QEFFT2_PUSH_DNUM((2 * cy + y) / 3)
        QEFFT2_CALL(extra->cubic_to)
    }

    QEFFT2_CALL_TIDY

    extra->curx = x;
    extra->cury = y;
    return 0;
}

static int
handle_cubic_to (const FT_Vector *control1, const FT_Vector *control2, const FT_Vector *to,
                 void *data)
{
    struct QefFT2_Outline_Decompose_Extra_ *extra = data;
    double x = QEFFT2_NUM(to->x), y = QEFFT2_NUM(to->y);

    QEFFT2_CALL_PREP
    QEFFT2_PUSH_DNUM(x)
    QEFFT2_PUSH_DNUM(y)
    QEFFT2_PUSH_NUM(control1->x)
    QEFFT2_PUSH_NUM(control1->y)
    QEFFT2_PUSH_NUM(control2->x)
    QEFFT2_PUSH_NUM(control2->y)
    QEFFT2_CALL(extra->cubic_to)
    QEFFT2_CALL_TIDY

    extra->curx = x;
    extra->cury = y;
    return 0;
}

#line 364 "FreeType.c"
#ifndef PERL_UNUSED_VAR
#  define PERL_UNUSED_VAR(var) if (0) var = var
#endif

#ifndef dVAR
#  define dVAR		dNOOP
#endif


/* This stuff is not part of the API! You have been warned. */
#ifndef PERL_VERSION_DECIMAL
#  define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s)
#endif
#ifndef PERL_DECIMAL_VERSION
#  define PERL_DECIMAL_VERSION \
	  PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION)
#endif
#ifndef PERL_VERSION_GE
#  define PERL_VERSION_GE(r,v,s) \
	  (PERL_DECIMAL_VERSION >= PERL_VERSION_DECIMAL(r,v,s))
#endif
#ifndef PERL_VERSION_LE
#  define PERL_VERSION_LE(r,v,s) \
	  (PERL_DECIMAL_VERSION <= PERL_VERSION_DECIMAL(r,v,s))
#endif

/* XS_INTERNAL is the explicit static-linkage variant of the default
 * XS macro.
 *
 * XS_EXTERNAL is the same as XS_INTERNAL except it does not include
 * "STATIC", ie. it exports XSUB symbols. You probably don't want that
 * for anything but the BOOT XSUB.
 *
 * See XSUB.h in core!
 */


/* TODO: This might be compatible further back than 5.10.0. */
#if PERL_VERSION_GE(5, 10, 0) && PERL_VERSION_LE(5, 15, 1)
#  undef XS_EXTERNAL
#  undef XS_INTERNAL
#  if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)
#    define XS_EXTERNAL(name) __declspec(dllexport) XSPROTO(name)
#    define XS_INTERNAL(name) STATIC XSPROTO(name)
#  endif
#  if defined(__SYMBIAN32__)
#    define XS_EXTERNAL(name) EXPORT_C XSPROTO(name)
#    define XS_INTERNAL(name) EXPORT_C STATIC XSPROTO(name)
#  endif
#  ifndef XS_EXTERNAL
#    if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus)
#      define XS_EXTERNAL(name) void name(pTHX_ CV* cv __attribute__unused__)
#      define XS_INTERNAL(name) STATIC void name(pTHX_ CV* cv __attribute__unused__)
#    else
#      ifdef __cplusplus
#        define XS_EXTERNAL(name) extern "C" XSPROTO(name)
#        define XS_INTERNAL(name) static XSPROTO(name)
#      else
#        define XS_EXTERNAL(name) XSPROTO(name)
#        define XS_INTERNAL(name) STATIC XSPROTO(name)
#      endif
#    endif
#  endif
#endif

/* perl >= 5.10.0 && perl <= 5.15.1 */


/* The XS_EXTERNAL macro is used for functions that must not be static
 * like the boot XSUB of a module. If perl didn't have an XS_EXTERNAL
 * macro defined, the best we can do is assume XS is the same.
 * Dito for XS_INTERNAL.
 */
#ifndef XS_EXTERNAL
#  define XS_EXTERNAL(name) XS(name)
#endif
#ifndef XS_INTERNAL
#  define XS_INTERNAL(name) XS(name)
#endif

/* Now, finally, after all this mess, we want an ExtUtils::ParseXS
 * internal macro that we're free to redefine for varying linkage due
 * to the EXPORT_XSUB_SYMBOLS XS keyword. This is internal, use
 * XS_EXTERNAL(name) or XS_INTERNAL(name) in your code if you need to!
 */

#undef XS_EUPXS
#if defined(PERL_EUPXS_ALWAYS_EXPORT)
#  define XS_EUPXS(name) XS_EXTERNAL(name)
#else
   /* default to internal */
#  define XS_EUPXS(name) XS_INTERNAL(name)
#endif

#ifndef PERL_ARGS_ASSERT_CROAK_XS_USAGE
#define PERL_ARGS_ASSERT_CROAK_XS_USAGE assert(cv); assert(params)

/* prototype to pass -Wmissing-prototypes */
STATIC void
S_croak_xs_usage(const CV *const cv, const char *const params);

STATIC void
S_croak_xs_usage(const CV *const cv, const char *const params)
{
    const GV *const gv = CvGV(cv);

    PERL_ARGS_ASSERT_CROAK_XS_USAGE;

    if (gv) {
        const char *const gvname = GvNAME(gv);
        const HV *const stash = GvSTASH(gv);
        const char *const hvname = stash ? HvNAME(stash) : NULL;

        if (hvname)
	    Perl_croak_nocontext("Usage: %s::%s(%s)", hvname, gvname, params);
        else
	    Perl_croak_nocontext("Usage: %s(%s)", gvname, params);
    } else {
        /* Pants. I don't think that it should be possible to get here. */
	Perl_croak_nocontext("Usage: CODE(0x%" UVxf ")(%s)", PTR2UV(cv), params);
    }
}
#undef  PERL_ARGS_ASSERT_CROAK_XS_USAGE

#define croak_xs_usage        S_croak_xs_usage

#endif

/* NOTE: the prototype of newXSproto() is different in versions of perls,
 * so we define a portable version of newXSproto()
 */
#ifdef newXS_flags
#define newXSproto_portable(name, c_impl, file, proto) newXS_flags(name, c_impl, file, proto, 0)
#else
#define newXSproto_portable(name, c_impl, file, proto) (PL_Sv=(SV*)newXS(name, c_impl, file), sv_setpv(PL_Sv, proto), (CV*)PL_Sv)
#endif /* !defined(newXS_flags) */

#if PERL_VERSION_LE(5, 21, 5)
#  define newXS_deffile(a,b) Perl_newXS(aTHX_ a,b,file)
#else
#  define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b)
#endif

#line 508 "FreeType.c"

XS_EUPXS(XS_Font__FreeType_qefft2_import); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType_qefft2_import)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "target_pkg");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
#line 362 "FreeType.xs"
        HV *stash;
        size_t i;
#line 522 "FreeType.c"
	const char *	target_pkg = (const char *)SvPV_nolen(ST(0))
;
#line 365 "FreeType.xs"
        stash = gv_stashpv(target_pkg, 0);
        if (!stash)
            croak("the package I'm importing into doesn't seem to exist");
        for (i = 0; i < sizeof(qefft2_uv_const) / sizeof(QefFT2_Uv_Const); ++i) {
            const char* name = qefft2_uv_const[i].name;
            if ( !hv_exists(stash, name, strlen(name)) )
                 newCONSTSUB(stash, name,  newSVuv(qefft2_uv_const[i].value));
        }
#line 534 "FreeType.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Font__FreeType_new); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType_new)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "void");
    {
	Font_FreeType	RETVAL;
#line 378 "FreeType.xs"
        errchk(FT_Init_FreeType(&RETVAL),
               "opening freetype library");
#line 552 "FreeType.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
    sv_setref_pv(RETVALSV, "Font::FreeType", (void*)RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "library");
    {
	Font_FreeType	library;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        library = (Font_FreeType) tmp;
    }
    else
        croak("library is not of type Font::FreeType")
;
#line 387 "FreeType.xs"
        if (FT_Done_FreeType(library))
            warn("error closing freetype library");
#line 585 "FreeType.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Font__FreeType_version); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType_version)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "library");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
#line 394 "FreeType.xs"
        FT_Int major, minor, patch;
#line 602 "FreeType.c"
	Font_FreeType	library;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        library = (Font_FreeType) tmp;
    }
    else
        croak("library is not of type Font::FreeType")
;
#line 396 "FreeType.xs"
        major = minor = patch = -1;
        FT_Library_Version(library, &major, &minor, &patch);
        assert(major != -1);
        assert(minor != -1);
        assert(patch != -1);
        if (GIMME_V != G_ARRAY)
            PUSHs(sv_2mortal(newSVpvf("%d.%d.%d",
                                      (int) major, (int) minor, (int) patch)));
        else {
            EXTEND(SP, 3);
            PUSHs(sv_2mortal(newSViv(major)));
            PUSHs(sv_2mortal(newSViv(minor)));
            PUSHs(sv_2mortal(newSViv(patch)));
        }
#line 629 "FreeType.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Font__FreeType_qefft2_face); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType_qefft2_face)
{
    dVAR; dXSARGS;
    if (items != 4)
       croak_xs_usage(cv,  "library, filename, faceidx, glyph_load_flags");
    {
#line 415 "FreeType.xs"
        SV *library_sv;
        QefFT2_Face_Extra *extra;
#line 646 "FreeType.c"
	Font_FreeType_Face	RETVAL;
	Font_FreeType	library;
	const char *	filename = (const char *)SvPV_nolen(ST(1))
;
	int	faceidx = (int)SvIV(ST(2))
;
	FT_Int32    glyph_load_flags = (FT_Int32) SvIV(ST(3))
;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        library = (Font_FreeType) tmp;
    }
    else
        croak("library is not of type Font::FreeType")
;
#line 418 "FreeType.xs"
        errchk(FT_New_Face(library, filename, faceidx, &RETVAL),
               "opening font face");
        library_sv = SvRV(ST(0));
        SvREFCNT_inc(library_sv);
        Newx(extra, 1, QefFT2_Face_Extra);
        extra->library_sv = library_sv;
        extra->loaded_glyph_idx = 0;
        extra->slot_valid = 0;
        extra->glyph_load_flags = glyph_load_flags;
        extra->glyph_ft = 0;
        RETVAL->generic.data = (void *) extra;
        /*
        set active charmap if we don't have one;  caused by regression:
        https://git.savannah.gnu.org/cgit/freetype/freetype2.git/commit/?id=79e3789f81e14266578e71196ce71ecf5381d142
        http://lists.nongnu.org/archive/html/freetype/2017-10/msg00006.html
        */
#if (QEFFT2_FT_AT_LEAST(2,8,1))
        if (!RETVAL->charmap && RETVAL->num_charmaps) {
            RETVAL->charmap = RETVAL->charmaps[0];
        }
#endif

#line 688 "FreeType.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
    sv_setref_pv(RETVALSV, "Font::FreeType::Face", (void*)RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_load_flags); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_load_flags)
{
    dVAR; dXSARGS;
    if (items < 1 || items > 2)
       croak_xs_usage(cv,  "face, val= NO_INIT");
    {
#line 450 "FreeType.xs"
        QefFT2_Face_Extra *extra;
#line 709 "FreeType.c"
	FT_Int32	RETVAL;
	dXSTARG;
	Font_FreeType_Face	face;
	FT_Int32	val;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;

	if (items >= 2) {
    val = (FT_Int32) SvIV(ST(1))
;
	}
#line 452 "FreeType.xs"
        extra = face->generic.data;
        if( items > 1 )
        {
            extra->slot_valid = 0;
            extra->glyph_load_flags = val;
        }
        RETVAL = extra->glyph_load_flags;
#line 737 "FreeType.c"
	XSprePUSH; PUSHi((IV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
#line 466 "FreeType.xs"
        QefFT2_Face_Extra *extra;
#line 753 "FreeType.c"
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 468 "FreeType.xs"
        assert(face->generic.data);
        extra = face->generic.data;
        if (FT_Done_Face(face))
            warn("error destroying freetype face");
        SvREFCNT_dec(extra->library_sv);
        Safefree(extra);
#line 772 "FreeType.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Font__FreeType__Face_number_of_faces); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_number_of_faces)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	long	RETVAL;
	dXSTARG;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 479 "FreeType.xs"
        RETVAL = face->num_faces;
#line 800 "FreeType.c"
	XSprePUSH; PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_current_face_index); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_current_face_index)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	long	RETVAL;
	dXSTARG;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 487 "FreeType.xs"
        RETVAL = face->face_index;
#line 829 "FreeType.c"
	XSprePUSH; PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_postscript_name); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_postscript_name)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
#line 495 "FreeType.xs"
        const char *ps_name;
#line 845 "FreeType.c"
	SV *	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 497 "FreeType.xs"
        ps_name = FT_Get_Postscript_Name(face);
        if (ps_name)
            RETVAL = newSVpv(ps_name, 0);
        else
            RETVAL = &PL_sv_undef;
#line 864 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_family_name); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_family_name)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	const char *	RETVAL;
	dXSTARG;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 509 "FreeType.xs"
        RETVAL = face->family_name;
#line 894 "FreeType.c"
	sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_style_name); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_style_name)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	SV *	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 517 "FreeType.xs"
        if (face->style_name)
            RETVAL = newSVpv(face->style_name, 0);
        else
            RETVAL = &PL_sv_undef;
#line 925 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_is_scalable); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_is_scalable)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	bool	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 528 "FreeType.xs"
        RETVAL = FT_IS_SCALABLE(face) ? 1 : 0;
#line 954 "FreeType.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_is_fixed_width); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_is_fixed_width)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	bool	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 536 "FreeType.xs"
        RETVAL = FT_IS_FIXED_WIDTH(face) ? 1 : 0;
#line 982 "FreeType.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_is_sfnt); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_is_sfnt)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	bool	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 544 "FreeType.xs"
        RETVAL = FT_IS_SFNT(face) ? 1 : 0;
#line 1010 "FreeType.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_has_horizontal_metrics); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_has_horizontal_metrics)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	bool	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 552 "FreeType.xs"
        RETVAL = FT_HAS_HORIZONTAL(face) ? 1 : 0;
#line 1038 "FreeType.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_has_vertical_metrics); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_has_vertical_metrics)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	bool	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 560 "FreeType.xs"
        RETVAL = FT_HAS_VERTICAL(face) ? 1 : 0;
#line 1066 "FreeType.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_has_kerning); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_has_kerning)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	bool	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 568 "FreeType.xs"
        RETVAL = FT_HAS_KERNING(face) ? 1 : 0;
#line 1094 "FreeType.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_has_glyph_names); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_has_glyph_names)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	bool	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 576 "FreeType.xs"
        RETVAL = FT_HAS_GLYPH_NAMES(face) ? 1 : 0;
#line 1122 "FreeType.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_has_reliable_glyph_names); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_has_reliable_glyph_names)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	bool	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 584 "FreeType.xs"
        /* The FT_Has_PS_Glyph_Names function was added in version 2.1.1.  */
#if QEFFT2_FT_AT_LEAST(2,1,1)
        RETVAL = FT_HAS_GLYPH_NAMES(face) && FT_Has_PS_Glyph_Names(face);
#else
        RETVAL = 0;
#endif
#line 1155 "FreeType.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_is_italic); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_is_italic)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	bool	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 597 "FreeType.xs"
        RETVAL = face->style_flags & FT_STYLE_FLAG_ITALIC ? 1 : 0;
#line 1183 "FreeType.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_is_bold); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_is_bold)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	bool	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 605 "FreeType.xs"
        RETVAL = face->style_flags & FT_STYLE_FLAG_BOLD ? 1 : 0;
#line 1211 "FreeType.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_number_of_glyphs); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_number_of_glyphs)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	long	RETVAL;
	dXSTARG;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 613 "FreeType.xs"
        RETVAL = face->num_glyphs;
#line 1240 "FreeType.c"
	XSprePUSH; PUSHi((IV)RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_units_per_em); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_units_per_em)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	SV *	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 621 "FreeType.xs"
        RETVAL = FT_IS_SCALABLE(face) ? newSVuv((UV) face->units_per_EM)
                                      : &PL_sv_undef;
#line 1269 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_attach_file); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_attach_file)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "face, filename");
    {
	Font_FreeType_Face	face;
	const char *	filename = (const char *)SvPV_nolen(ST(1))
;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 630 "FreeType.xs"
        errchk(FT_Attach_File(face, filename),
               "attaching file to freetype face");
#line 1300 "FreeType.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Font__FreeType__Face_set_char_size); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_set_char_size)
{
    dVAR; dXSARGS;
    if (items != 5)
       croak_xs_usage(cv,  "face, width, height, x_res, y_res");
    {
	Font_FreeType_Face	face;
	FT_F26Dot6    width = (FT_F26Dot6) floor(SvNV(ST(1)) * 64.0 + 0.5)
;
	FT_F26Dot6    height = (FT_F26Dot6) floor(SvNV(ST(2)) * 64.0 + 0.5)
;
	FT_UInt    x_res = (FT_UInt) SvUV(ST(3))
;
	FT_UInt    y_res = (FT_UInt) SvUV(ST(4))
;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 637 "FreeType.xs"
        errchk(FT_Set_Char_Size(face, width, height, x_res, y_res),
               "setting char size of freetype face");
        ((QefFT2_Face_Extra *) face->generic.data)->slot_valid = 0;
#line 1336 "FreeType.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Font__FreeType__Face_set_pixel_size); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_set_pixel_size)
{
    dVAR; dXSARGS;
    if (items != 3)
       croak_xs_usage(cv,  "face, width, height");
    {
	Font_FreeType_Face	face;
	FT_UInt    width = (FT_UInt) SvUV(ST(1))
;
	FT_UInt    height = (FT_UInt) SvUV(ST(2))
;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 645 "FreeType.xs"
        errchk(FT_Set_Pixel_Sizes(face, width, height),
               "setting pixel size of freetype face");
        ((QefFT2_Face_Extra *) face->generic.data)->slot_valid = 0;
#line 1368 "FreeType.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Font__FreeType__Face_height); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_height)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	SV *	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 653 "FreeType.xs"
        RETVAL = FT_IS_SCALABLE(face) ? newSViv(face->height)
                                      : &PL_sv_undef;
#line 1396 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_fixed_sizes); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_fixed_sizes)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
#line 662 "FreeType.xs"
        int i;
        FT_Bitmap_Size *size;
        HV *hash;
        double pt = 0.0, ppem;
#line 1418 "FreeType.c"
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 667 "FreeType.xs"
        if (GIMME_V != G_ARRAY) {
            PUSHs(sv_2mortal(newSViv((int) face->num_fixed_sizes)));
        }
        else {
            EXTEND(SP, face->num_fixed_sizes);
            for (i = 0; i < face->num_fixed_sizes; ++i) {
                size = &face->available_sizes[i];
                hash = newHV();
                if (size->height)
                    hv_store(hash, "height", 6, newSVuv(size->height), 0);
                if (size->width)
                    hv_store(hash, "width", 5, newSVuv(size->width), 0);
                /* The 'size', 'x_ppem', and 'y_ppem' fields were only added
                 * to the FT_Bitmap_Size structure in version 2.1.5.  */
#if QEFFT2_FT_AT_LEAST(2,1,5)
                if (size->size) {
                    pt = size->size / 64.0;
                    hv_store(hash, "size", 4, newSVnv(pt), 0);
                }
                if (size->x_ppem) {
                    ppem = size->x_ppem / 64.0;
                    hv_store(hash, "x_res_ppem", 10, newSVnv(ppem), 0);
                    if (size->size)
                        hv_store(hash, "x_res_dpi", 9,
                                 newSVnv((72 * ppem) / pt), 0);
                }
                if (size->y_ppem) {
                    ppem = size->y_ppem / 64.0;
                    hv_store(hash, "y_res_ppem", 10, newSVnv(ppem), 0);
                    if (size->size)
                        hv_store(hash, "y_res_dpi", 9,
                                 newSVnv((72 * ppem) / pt), 0);
                }
#endif
                PUSHs(sv_2mortal(newRV_inc((SV *) hash)));
            }
        }
#line 1468 "FreeType.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Font__FreeType__Face_ascender); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_ascender)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	SV *	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 709 "FreeType.xs"
        RETVAL = FT_IS_SCALABLE(face) ? newSViv(face->ascender)
                                      : &PL_sv_undef;
#line 1497 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_descender); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_descender)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	SV *	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 718 "FreeType.xs"
        RETVAL = FT_IS_SCALABLE(face) ? newSViv(face->descender)
                                      : &PL_sv_undef;
#line 1527 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_underline_position); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_underline_position)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	SV *	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 727 "FreeType.xs"
        /* TODO - can I get this in scaled coords? */
        RETVAL = FT_IS_SCALABLE(face) ? newSViv(face->underline_position)
                                      : &PL_sv_undef;
#line 1558 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_underline_thickness); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_underline_thickness)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	SV *	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 737 "FreeType.xs"
        /* TODO - can I get this in scaled coords? */
        RETVAL = FT_IS_SCALABLE(face) ? newSViv(face->underline_thickness)
                                      : &PL_sv_undef;
#line 1589 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_charmap); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_charmap)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	Font_FreeType_CharMap	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 747 "FreeType.xs"
        RETVAL = face->charmap;
#line 1618 "FreeType.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
    sv_setref_pv(RETVALSV, "Font::FreeType::CharMap", (void*)RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_charmaps); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_charmaps)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
#line 754 "FreeType.xs"
        AV* array;
        int i;
        Font_FreeType_CharMap* ptr;
#line 1641 "FreeType.c"
	AV *	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 758 "FreeType.xs"
        array = newAV();
        ptr = face->charmaps;
        for(i = 0; i < face->num_charmaps; i++) {
            SV *sv = newSV(0);
            sv_setref_pv(sv, "Font::FreeType::CharMap", (void *) *ptr++);
            av_push(array, sv);
        }
        RETVAL = array;
#line 1663 "FreeType.c"
	{
	    SV * RETVALSV;
	    RETVALSV = newRV((SV*)RETVAL);
	    RETVALSV = sv_2mortal(RETVALSV);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_bounding_box); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_bounding_box)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
	Font_FreeType_BoundingBox	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 772 "FreeType.xs"
        if (!FT_IS_SCALABLE(face)) {
            XSRETURN_UNDEF;
        } else {
            RETVAL = &face->bbox;
        }
#line 1700 "FreeType.c"
	{
	    SV * RETVALSV;
	    RETVALSV = sv_newmortal();
    sv_setref_pv(RETVALSV, "Font::FreeType::BoundingBox", (void*)RETVAL);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_namedinfos); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_namedinfos)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "face");
    {
#line 783 "FreeType.xs"
        AV* array;
        int i;
#line 1722 "FreeType.c"
	AV *	RETVAL;
	Font_FreeType_Face	face;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 786 "FreeType.xs"
        if (!FT_IS_SCALABLE(face)) {
            XSRETURN_UNDEF;
        } else {
            array = newAV();
            int count = FT_Get_Sfnt_Name_Count(face);
            for(i = 0; i < count; i++) {
                SV *sv = newSV(0);
                FT_SfntName* sfnt;
                Newx(sfnt, 1, FT_SfntName);
                errchk(FT_Get_Sfnt_Name(face, i, sfnt),
                       "loading sfnt structure");
                sv_setref_pv(sv, "Font::FreeType::NamedInfo", (void *) sfnt);
                av_push(array, sv);
            }
            RETVAL = array;
        }
#line 1752 "FreeType.c"
	{
	    SV * RETVALSV;
	    RETVALSV = newRV((SV*)RETVAL);
	    RETVALSV = sv_2mortal(RETVALSV);
	    ST(0) = RETVALSV;
	}
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_kerning); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_kerning)
{
    dVAR; dXSARGS;
    if (items < 3 || items > 4)
       croak_xs_usage(cv,  "face, left_glyph_idx, right_glyph_idx, kern_mode= FT_KERNING_DEFAULT");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
#line 808 "FreeType.xs"
        FT_Vector kerning;
#line 1775 "FreeType.c"
	Font_FreeType_Face	face;
	FT_UInt    left_glyph_idx = (FT_UInt) SvUV(ST(1))
;
	FT_UInt    right_glyph_idx = (FT_UInt) SvUV(ST(2))
;
	UV	kern_mode;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;

	if (items < 4)
	    kern_mode = FT_KERNING_DEFAULT;
	else {
	    kern_mode = (UV)SvUV(ST(3))
;
	}
#line 810 "FreeType.xs"
        errchk(FT_Get_Kerning(face, left_glyph_idx, right_glyph_idx, kern_mode,
                              &kerning),
               "getting kerning from freetype face");
        if (GIMME_V != G_ARRAY) {
            PUSHs(sv_2mortal(newSVnv((double) kerning.x / 64.0)));
        }
        else {
            EXTEND(SP, 2);
            PUSHs(sv_2mortal(newSVnv((double) kerning.x / 64.0)));
            PUSHs(sv_2mortal(newSVnv((double) kerning.y / 64.0)));
        }
#line 1811 "FreeType.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Font__FreeType__Face_glyph_from_char_code); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_glyph_from_char_code)
{
    dVAR; dXSARGS;
    if (items < 2 || items > 3)
       croak_xs_usage(cv,  "face, char_code, fallback= 0");
    {
#line 826 "FreeType.xs"
        FT_UInt glyph_idx;
#line 1827 "FreeType.c"
	SV *	RETVAL;
	Font_FreeType_Face	face;
	FT_ULong    char_code = (FT_ULong) SvUV(ST(1))
;
	int	fallback;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;

	if (items < 3)
	    fallback = 0;
	else {
	    fallback = (int)SvIV(ST(2))
;
	}
#line 828 "FreeType.xs"
        glyph_idx = FT_Get_Char_Index(face, char_code);
        if (glyph_idx || fallback)
            RETVAL = make_glyph(SvRV(ST(0)), char_code, 1, glyph_idx);
        else
            RETVAL = &PL_sv_undef;
#line 1856 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_glyph_from_char); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_glyph_from_char)
{
    dVAR; dXSARGS;
    if (items < 2 || items > 3)
       croak_xs_usage(cv,  "face, sv, fallback= 0");
    {
#line 840 "FreeType.xs"
        FT_UInt glyph_idx;
        const U8 *str;
        STRLEN len;
        UV char_code;
#line 1876 "FreeType.c"
	SV *	RETVAL;
	Font_FreeType_Face	face;
	SV *	sv = ST(1)
;
	int	fallback;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;

	if (items < 3)
	    fallback = 0;
	else {
	    fallback = (int)SvIV(ST(2))
;
	}
#line 845 "FreeType.xs"
        if (!SvPOK(sv))
            croak("argument must be a string containing a character");
        str = (const U8*)SvPV(sv, len);
        if (!len)
            croak("string has no characters");
        if (!UTF8_IS_INVARIANT(*str)) {
            STRLEN s_len;
            char_code = utf8_to_uvchr_buf(str, str + len, &s_len);
            if (len != s_len) {
                croak("malformed string (looks as UTF-8, but isn't it)");
            }
        } else {
            char_code = *str;
        }
        glyph_idx = FT_Get_Char_Index(face, char_code);
        fallback = SvOK(ST(2)) ? SvIV(ST(2)) : 0;
        if (glyph_idx || fallback)
            RETVAL = make_glyph(SvRV(ST(0)), char_code, 1, glyph_idx);
        else
            RETVAL = &PL_sv_undef;
#line 1920 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_get_name_index); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_get_name_index)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "face, sv");
    {
#line 871 "FreeType.xs"
        char *name;
#line 1937 "FreeType.c"
	FT_UInt	RETVAL;
	dXSTARG;
	Font_FreeType_Face	face;
	SV *	sv = ST(1)
;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 873 "FreeType.xs"
        name = SvPV_nolen(sv);
        RETVAL = FT_Get_Name_Index(face, name);
#line 1956 "FreeType.c"
	XSprePUSH; PUSHu((UV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_glyph_from_index); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_glyph_from_index)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "face, ix");
    {
	SV *	RETVAL;
	Font_FreeType_Face	face;
	FT_UInt    ix = (FT_UInt) SvUV(ST(1))
;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 881 "FreeType.xs"
        RETVAL = make_glyph(SvRV(ST(0)), 0, 0, ix);
#line 1986 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_glyph_from_name); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_glyph_from_name)
{
    dVAR; dXSARGS;
    if (items < 2 || items > 3)
       croak_xs_usage(cv,  "face, sv, fallback= 0");
    {
#line 888 "FreeType.xs"
        char *name;
        FT_UInt ix;
#line 2004 "FreeType.c"
	SV *	RETVAL;
	Font_FreeType_Face	face;
	SV *	sv = ST(1)
;
	int	fallback;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;

	if (items < 3)
	    fallback = 0;
	else {
	    fallback = (int)SvIV(ST(2))
;
	}
#line 891 "FreeType.xs"
        name = SvPV_nolen(sv);
        ix = FT_Get_Name_Index(face, name);
        if (ix || fallback || !strcmp(name, ".notdef"))
            RETVAL = make_glyph(SvRV(ST(0)), 0, 0, ix);
        else
            RETVAL = &PL_sv_undef;
#line 2034 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Face_foreach_char); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_foreach_char)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "face, code");
    {
#line 903 "FreeType.xs"
        FT_ULong char_code;
        FT_UInt glyph_idx;
#line 2052 "FreeType.c"
	Font_FreeType_Face	face;
	SV *	code = ST(1)
;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 906 "FreeType.xs"
        char_code = FT_Get_First_Char(face, &glyph_idx);
        while (glyph_idx) {
            dSP;
            ENTER;
            SAVETMPS;

            PUSHMARK(SP);
            SAVESPTR(DEFSV);
            DEFSV = sv_2mortal(make_glyph(SvRV(ST(0)), char_code, 1, glyph_idx));
            PUTBACK;

            call_sv(code, G_VOID | G_DISCARD);

            FREETMPS;
            LEAVE;

            char_code = FT_Get_Next_Char(face, char_code, &glyph_idx);
        }
#line 2085 "FreeType.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Font__FreeType__Face_foreach_glyph); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Face_foreach_glyph)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "face, code");
    {
#line 929 "FreeType.xs"
        FT_UInt glyph_idx;
#line 2100 "FreeType.c"
	Font_FreeType_Face	face;
	SV *	code = ST(1)
;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Face"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        face = (Font_FreeType_Face) tmp;
    }
    else
        croak("face is not of type Font::FreeType::Face")
;
#line 931 "FreeType.xs"
        for (glyph_idx  = 0 ; glyph_idx < face->num_glyphs ; glyph_idx++) {
            dSP;
            ENTER;
            SAVETMPS;

            PUSHMARK(SP);
            SAVESPTR(DEFSV);
            DEFSV = sv_2mortal(make_glyph(SvRV(ST(0)), 0, 0, glyph_idx));
            PUTBACK;

            call_sv(code, G_VOID | G_DISCARD);

            FREETMPS;
            LEAVE;
        }
#line 2130 "FreeType.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Font__FreeType__Glyph_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
#line 954 "FreeType.xs"
        FT_Face face;
        QefFT2_Face_Extra *extra;
#line 2146 "FreeType.c"
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 957 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        extra = face->generic.data;
        if (extra->glyph_ft) {
            FT_Done_Glyph(extra->glyph_ft);
            extra->glyph_ft = 0;
        }
        assert(glyph->face_sv);
        SvREFCNT_dec(glyph->face_sv);
        Safefree(glyph->name);
        Safefree(glyph);
#line 2169 "FreeType.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Font__FreeType__Glyph_char_code); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_char_code)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
#line 972 "FreeType.xs"
        FT_Face face;
        FT_ULong char_code;
        FT_UInt glyph_idx;
#line 2186 "FreeType.c"
	SV *	RETVAL;
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 976 "FreeType.xs"
        if (glyph->has_char_code) {
            RETVAL = newSVuv((UV) glyph->char_code);
        }
        else {
            /* Unfortunately, the only way I know of finding the character
             * code given a glyph index is to hunt through all the
             * glyphs.  Some glyphs might not have codes in the current
             * charmap, in which case undef is returned. */
            RETVAL = &PL_sv_undef;
            face = (FT_Face) SvIV(glyph->face_sv);
            char_code = FT_Get_First_Char(face, &glyph_idx);
            while (glyph_idx) {
                if (glyph_idx == glyph->index) {
                    glyph->char_code = char_code;
                    RETVAL = newSVuv((UV) glyph->char_code);
                    break;
                }
                char_code = FT_Get_Next_Char(face, char_code, &glyph_idx);
            }
        }
#line 2220 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Glyph_index); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_index)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
	FT_UInt	RETVAL;
	dXSTARG;
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 1003 "FreeType.xs"
        RETVAL = glyph->index;
#line 2250 "FreeType.c"
	XSprePUSH; PUSHu((UV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Glyph_name); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_name)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
#line 1011 "FreeType.xs"
        FT_Face face;
        char *buf;
        int bufsz;
        STRLEN len;
#line 2269 "FreeType.c"
	SV *	RETVAL;
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 1016 "FreeType.xs"
        if (glyph->name)
            RETVAL = newSVpv(glyph->name, 0);
        else {
            face = (FT_Face) SvIV(glyph->face_sv);
            if (!FT_HAS_GLYPH_NAMES(face))
                RETVAL = &PL_sv_undef;
            else {
                /* The loop repeatedly expands the buffer if it looks like
                 * the glyph name might be longer than the space available.  */
                bufsz = QEF_BUF_SZ;
                Newx(buf, bufsz, char);
                while (1) {
                    errchk(FT_Get_Glyph_Name(face, glyph->index, buf, bufsz),
                           "getting freetype glyph name");
                    len = strlen(buf);
                    if (len == bufsz - 1) {
                        bufsz = bufsz * 2;
                        Renew(buf, bufsz, char);
                    }
                    else
                        break;
                }

                glyph->name = buf;
                RETVAL = newSVpv(buf, len);
            }
        }
#line 2310 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Glyph_width); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_width)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
#line 1050 "FreeType.xs"
        FT_Face face;
#line 2327 "FreeType.c"
	FT_F26Dot6	RETVAL;
	dXSTARG;
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 1052 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        RETVAL = ensure_glyph_loaded(face, glyph)->metrics.width;
#line 2344 "FreeType.c"
	XSprePUSH; PUSHn((double) RETVAL / 64.0);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Glyph_height); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_height)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
#line 1061 "FreeType.xs"
        FT_Face face;
#line 2360 "FreeType.c"
	FT_F26Dot6	RETVAL;
	dXSTARG;
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 1063 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        RETVAL = ensure_glyph_loaded(face, glyph)->metrics.height;
#line 2377 "FreeType.c"
	XSprePUSH; PUSHn((double) RETVAL / 64.0);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Glyph_left_bearing); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_left_bearing)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
#line 1072 "FreeType.xs"
        FT_Face face;
#line 2393 "FreeType.c"
	FT_F26Dot6	RETVAL;
	dXSTARG;
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 1074 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        RETVAL = ensure_glyph_loaded(face, glyph)->metrics.horiBearingX;
#line 2410 "FreeType.c"
	XSprePUSH; PUSHn((double) RETVAL / 64.0);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Glyph_right_bearing); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_right_bearing)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
#line 1083 "FreeType.xs"
        FT_Face face;
        const FT_Glyph_Metrics *metrics;
#line 2427 "FreeType.c"
	FT_F26Dot6	RETVAL;
	dXSTARG;
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 1086 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        metrics = &ensure_glyph_loaded(face, glyph)->metrics;
        RETVAL = metrics->horiAdvance - metrics->horiBearingX - metrics->width;
#line 2445 "FreeType.c"
	XSprePUSH; PUSHn((double) RETVAL / 64.0);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Glyph_horizontal_advance); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_horizontal_advance)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
#line 1096 "FreeType.xs"
        FT_Face face;
#line 2461 "FreeType.c"
	FT_F26Dot6	RETVAL;
	dXSTARG;
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 1098 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        RETVAL = ensure_glyph_loaded(face, glyph)->metrics.horiAdvance;
#line 2478 "FreeType.c"
	XSprePUSH; PUSHn((double) RETVAL / 64.0);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Glyph_vertical_advance); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_vertical_advance)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
#line 1107 "FreeType.xs"
        FT_Face face;
#line 2494 "FreeType.c"
	FT_F26Dot6	RETVAL;
	dXSTARG;
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 1109 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        RETVAL = ensure_glyph_loaded(face, glyph)->metrics.vertAdvance;
#line 2511 "FreeType.c"
	XSprePUSH; PUSHn((double) RETVAL / 64.0);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Glyph_load); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_load)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
#line 1118 "FreeType.xs"
        FT_Face face;
#line 2527 "FreeType.c"
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 1120 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        ensure_glyph_loaded(face, glyph);
#line 2542 "FreeType.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Font__FreeType__Glyph_has_outline); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_has_outline)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    {
#line 1127 "FreeType.xs"
        FT_Face face;
#line 2557 "FreeType.c"
	bool	RETVAL;
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 1129 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        RETVAL = ensure_outline_loaded(face, glyph);
#line 2573 "FreeType.c"
	ST(0) = boolSV(RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__Glyph_outline_bbox); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_outline_bbox)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "glyph");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
#line 1138 "FreeType.xs"
        FT_Face face;
        QefFT2_Face_Extra *extra;
        FT_OutlineGlyph outline_glyph;
        FT_BBox bbox;
#line 2594 "FreeType.c"
	Font_FreeType_Glyph	glyph;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;
#line 1143 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        if (!ensure_outline_loaded(face, glyph))
            croak("glyph %lu does not have an outline",
                  (unsigned long) glyph->char_code);
        extra = face->generic.data;
        outline_glyph = (FT_OutlineGlyph) extra->glyph_ft;
        errchk(FT_Outline_Get_BBox(&outline_glyph->outline, &bbox),
               "getting glyph outline bounding box");
        EXTEND(SP, 4);
        PUSHs(sv_2mortal(newSVnv((double) bbox.xMin / 64.0)));
        PUSHs(sv_2mortal(newSVnv((double) bbox.yMin / 64.0)));
        PUSHs(sv_2mortal(newSVnv((double) bbox.xMax / 64.0)));
        PUSHs(sv_2mortal(newSVnv((double) bbox.yMax / 64.0)));
#line 2620 "FreeType.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Font__FreeType__Glyph_outline_decompose_); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_outline_decompose_)
{
    dVAR; dXSARGS;
    if (items != 2)
       croak_xs_usage(cv,  "glyph, args");
    {
#line 1161 "FreeType.xs"
        FT_Face face;
        QefFT2_Face_Extra *extra;
        FT_OutlineGlyph outline_glyph;
        FT_Outline_Funcs handlers;
        struct QefFT2_Outline_Decompose_Extra_ decompose_extra;
        STRLEN len;
        HE *he;
        const char *key;
        SV *sv;
#line 2644 "FreeType.c"
	Font_FreeType_Glyph	glyph;
	HV *	args;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;

	if (SvROK(ST(1)) && SvTYPE(SvRV(ST(1)))==SVt_PVHV)
	    args = (HV*)SvRV(ST(1));
	else
	    Perl_croak(aTHX_ "args is not a hash reference")
;
#line 1171 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        if (!ensure_outline_loaded(face, glyph))
            croak("glyph %lu does not have an outline",
                  (unsigned long) glyph->char_code);
        extra = face->generic.data;

        decompose_extra.move_to = 0;
        decompose_extra.line_to = 0;
        decompose_extra.conic_to = 0;
        decompose_extra.cubic_to = 0;
        hv_iterinit(args);
        while ((he = hv_iternext(args))) {
            key = HePV(he, len);
            sv = HeVAL(he);
            if (!strcmp(key, "move_to"))
                decompose_extra.move_to = sv;
            else if (!strcmp(key, "line_to"))
                decompose_extra.line_to = sv;
            else if (!strcmp(key, "conic_to"))
                decompose_extra.conic_to = sv;
            else if (!strcmp(key, "cubic_to"))
                decompose_extra.cubic_to = sv;
            else
                croak("hash key '%s' not the name of a known event", key);
        }

        if (!decompose_extra.move_to)
            croak("callback handler 'move_to' argument required");
        if (!decompose_extra.line_to)
            croak("callback handler 'line_to' argument required");
        if (!decompose_extra.cubic_to)
            croak("callback handler 'cubic_to' argument required");

        handlers.move_to = handle_move_to;
        handlers.line_to = handle_line_to;
        handlers.conic_to = handle_conic_to;
        handlers.cubic_to = handle_cubic_to;
        handlers.shift = 0;
        handlers.delta = 0;
        outline_glyph = (FT_OutlineGlyph) extra->glyph_ft;
        errchk(FT_Outline_Decompose(&outline_glyph->outline, &handlers,
                                    &decompose_extra),
               "decomposing FreeType outline");
#line 2707 "FreeType.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Font__FreeType__Glyph_bitmap); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__Glyph_bitmap)
{
    dVAR; dXSARGS;
    if (items < 1 || items > 2)
       croak_xs_usage(cv,  "glyph, render_mode= FT_RENDER_MODE_NORMAL");
    PERL_UNUSED_VAR(ax); /* -Wall */
    SP -= items;
    {
#line 1219 "FreeType.xs"
        FT_Face face;
        FT_GlyphSlot glyph_ft;
        FT_Bitmap *bitmap;
        unsigned char *buf;
        int i, j;
        int bits = 0;
        AV *rows;
        unsigned char *row_buf;
#line 2731 "FreeType.c"
	Font_FreeType_Glyph	glyph;
	UV	render_mode;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::Glyph"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        glyph = (Font_FreeType_Glyph) tmp;
    }
    else
        croak("glyph is not of type Font::FreeType::Glyph")
;

	if (items < 2)
	    render_mode = FT_RENDER_MODE_NORMAL;
	else {
	    render_mode = (UV)SvUV(ST(1))
;
	}
#line 1228 "FreeType.xs"
        face = (FT_Face) SvIV(glyph->face_sv);
        /* XXX: For some reason I can't work out how to load the bitmap and
         * then load the outline later, but it works the other way round.
         * To ensure that a glyph object can be used for both, in either order,
         * I load the outline first even if it's not needed.  There's probably
         * a better way of doing this.  I'll ask on the mailing list.  */
        ensure_outline_loaded(face, glyph);
        glyph_ft = face->glyph;
        if (glyph_ft->format != FT_GLYPH_FORMAT_BITMAP) {
            errchk(FT_Render_Glyph(glyph_ft, render_mode), "rendering glyph");
        }
        bitmap = &glyph_ft->bitmap;
        assert(bitmap);

        rows = newAV();
        av_extend(rows, bitmap->rows - 1);
        buf = bitmap->buffer;
        Newx(row_buf, bitmap->width, unsigned char);

        if (bitmap->pixel_mode == FT_PIXEL_MODE_MONO) {
            for (i = 0; i < bitmap->rows; ++i) {
                for (j = 0; j < bitmap->width; ++j) {
                    if (j % 8 == 0)
                        bits = buf[j / 8];
                    row_buf[j] = bits & 0x80 ? 0xFF : 0x00;
                    bits <<= 1;
                }
                /* Not bothering to check that value was actually stored */
                av_store(rows, i, newSVpvn(row_buf, bitmap->width));
                buf += bitmap->pitch;
            }
        }
        else if (bitmap->pixel_mode == FT_PIXEL_MODE_GRAY) {
            for (i = 0; i < bitmap->rows; ++i) {
                for (j = 0; j < bitmap->width; ++j) {
                    row_buf[j] = buf[j];
                }
                /* Not bothering to check that value was actually stored */
                av_store(rows, i, newSVpvn(row_buf, bitmap->width));
                buf += bitmap->pitch;
            }
        }
        else {
            Safefree(row_buf);
            SvREFCNT_dec(rows);
            croak("unsupported pixel mode %d", (int) bitmap->pixel_mode);
        }

        Safefree(row_buf);
        EXTEND(SP, 3);
        PUSHs(sv_2mortal(newRV_inc((SV *) rows)));
        PUSHs(sv_2mortal(newSViv(glyph_ft->bitmap_left)));
        PUSHs(sv_2mortal(newSViv(glyph_ft->bitmap_top)));
#line 2805 "FreeType.c"
	PUTBACK;
	return;
    }
}


XS_EUPXS(XS_Font__FreeType__CharMap_encoding); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__CharMap_encoding)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "charmap");
    {
	FT_Encoding	RETVAL;
	dXSTARG;
	Font_FreeType_CharMap	charmap;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::CharMap"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        charmap = (Font_FreeType_CharMap) tmp;
    }
    else
        croak("charmap is not of type Font::FreeType::CharMap")
;
#line 1288 "FreeType.xs"
        RETVAL = charmap->encoding;
#line 2834 "FreeType.c"
	XSprePUSH; PUSHu((UV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__CharMap_platform_id); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__CharMap_platform_id)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "charmap");
    {
	FT_UShort	RETVAL;
	dXSTARG;
	Font_FreeType_CharMap	charmap;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::CharMap"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        charmap = (Font_FreeType_CharMap) tmp;
    }
    else
        croak("charmap is not of type Font::FreeType::CharMap")
;
#line 1295 "FreeType.xs"
        RETVAL = charmap->platform_id;
#line 2863 "FreeType.c"
	XSprePUSH; PUSHu((UV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__CharMap_encoding_id); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__CharMap_encoding_id)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "charmap");
    {
	FT_UShort	RETVAL;
	dXSTARG;
	Font_FreeType_CharMap	charmap;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::CharMap"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        charmap = (Font_FreeType_CharMap) tmp;
    }
    else
        croak("charmap is not of type Font::FreeType::CharMap")
;
#line 1302 "FreeType.xs"
        RETVAL = charmap->encoding_id;
#line 2892 "FreeType.c"
	XSprePUSH; PUSHu((UV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__NamedInfo_DESTROY); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__NamedInfo_DESTROY)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "info");
    {
	Font_FreeType_NamedInfo	info;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::NamedInfo"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        info = (Font_FreeType_NamedInfo) tmp;
    }
    else
        croak("info is not of type Font::FreeType::NamedInfo")
;
#line 1311 "FreeType.xs"
        Safefree(info);
#line 2919 "FreeType.c"
    }
    XSRETURN_EMPTY;
}


XS_EUPXS(XS_Font__FreeType__NamedInfo_platform_id); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__NamedInfo_platform_id)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "info");
    {
	FT_UShort	RETVAL;
	dXSTARG;
	Font_FreeType_NamedInfo	info;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::NamedInfo"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        info = (Font_FreeType_NamedInfo) tmp;
    }
    else
        croak("info is not of type Font::FreeType::NamedInfo")
;
#line 1316 "FreeType.xs"
        RETVAL = info->platform_id;
#line 2947 "FreeType.c"
	XSprePUSH; PUSHu((UV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__NamedInfo_encoding_id); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__NamedInfo_encoding_id)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "info");
    {
	FT_UShort	RETVAL;
	dXSTARG;
	Font_FreeType_NamedInfo	info;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::NamedInfo"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        info = (Font_FreeType_NamedInfo) tmp;
    }
    else
        croak("info is not of type Font::FreeType::NamedInfo")
;
#line 1323 "FreeType.xs"
        RETVAL = info->encoding_id;
#line 2976 "FreeType.c"
	XSprePUSH; PUSHu((UV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__NamedInfo_language_id); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__NamedInfo_language_id)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "info");
    {
	FT_UShort	RETVAL;
	dXSTARG;
	Font_FreeType_NamedInfo	info;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::NamedInfo"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        info = (Font_FreeType_NamedInfo) tmp;
    }
    else
        croak("info is not of type Font::FreeType::NamedInfo")
;
#line 1330 "FreeType.xs"
        RETVAL = info->language_id;
#line 3005 "FreeType.c"
	XSprePUSH; PUSHu((UV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__NamedInfo_name_id); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__NamedInfo_name_id)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "info");
    {
	FT_UShort	RETVAL;
	dXSTARG;
	Font_FreeType_NamedInfo	info;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::NamedInfo"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        info = (Font_FreeType_NamedInfo) tmp;
    }
    else
        croak("info is not of type Font::FreeType::NamedInfo")
;
#line 1337 "FreeType.xs"
        RETVAL = info->name_id;
#line 3034 "FreeType.c"
	XSprePUSH; PUSHu((UV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__NamedInfo_string); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__NamedInfo_string)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "info");
    {
	SV *	RETVAL;
	Font_FreeType_NamedInfo	info;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::NamedInfo"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        info = (Font_FreeType_NamedInfo) tmp;
    }
    else
        croak("info is not of type Font::FreeType::NamedInfo")
;
#line 1344 "FreeType.xs"
        RETVAL = newSVpvn(info->string, info->string_len);
#line 3062 "FreeType.c"
	RETVAL = sv_2mortal(RETVAL);
	ST(0) = RETVAL;
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__BoundingBox_x_min); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__BoundingBox_x_min)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "bb");
    {
	FT_Pos	RETVAL;
	dXSTARG;
	Font_FreeType_BoundingBox	bb;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::BoundingBox"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        bb = (Font_FreeType_BoundingBox) tmp;
    }
    else
        croak("bb is not of type Font::FreeType::BoundingBox")
;
#line 1353 "FreeType.xs"
        RETVAL = bb->xMin;
#line 3092 "FreeType.c"
	XSprePUSH; PUSHi((IV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__BoundingBox_y_min); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__BoundingBox_y_min)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "bb");
    {
	FT_Pos	RETVAL;
	dXSTARG;
	Font_FreeType_BoundingBox	bb;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::BoundingBox"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        bb = (Font_FreeType_BoundingBox) tmp;
    }
    else
        croak("bb is not of type Font::FreeType::BoundingBox")
;
#line 1360 "FreeType.xs"
        RETVAL = bb->yMin;
#line 3121 "FreeType.c"
	XSprePUSH; PUSHi((IV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__BoundingBox_x_max); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__BoundingBox_x_max)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "bb");
    {
	FT_Pos	RETVAL;
	dXSTARG;
	Font_FreeType_BoundingBox	bb;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::BoundingBox"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        bb = (Font_FreeType_BoundingBox) tmp;
    }
    else
        croak("bb is not of type Font::FreeType::BoundingBox")
;
#line 1367 "FreeType.xs"
        RETVAL = bb->xMax;
#line 3150 "FreeType.c"
	XSprePUSH; PUSHi((IV) RETVAL);
    }
    XSRETURN(1);
}


XS_EUPXS(XS_Font__FreeType__BoundingBox_y_max); /* prototype to pass -Wmissing-prototypes */
XS_EUPXS(XS_Font__FreeType__BoundingBox_y_max)
{
    dVAR; dXSARGS;
    if (items != 1)
       croak_xs_usage(cv,  "bb");
    {
	FT_Pos	RETVAL;
	dXSTARG;
	Font_FreeType_BoundingBox	bb;

    if (sv_isobject(ST(0)) &&
        sv_derived_from(ST(0), "Font::FreeType::BoundingBox"))
    {
        IV tmp = SvIV((SV*)SvRV(ST(0)));
        bb = (Font_FreeType_BoundingBox) tmp;
    }
    else
        croak("bb is not of type Font::FreeType::BoundingBox")
;
#line 1374 "FreeType.xs"
        RETVAL = bb->yMax;
#line 3179 "FreeType.c"
	XSprePUSH; PUSHi((IV) RETVAL);
    }
    XSRETURN(1);
}

#ifdef __cplusplus
extern "C"
#endif
XS_EXTERNAL(boot_Font__FreeType); /* prototype to pass -Wmissing-prototypes */
XS_EXTERNAL(boot_Font__FreeType)
{
#if PERL_VERSION_LE(5, 21, 5)
    dVAR; dXSARGS;
#else
    dVAR; dXSBOOTARGSXSAPIVERCHK;
#endif
#if (PERL_REVISION == 5 && PERL_VERSION < 9)
    char* file = __FILE__;
#else
    const char* file = __FILE__;
#endif

    PERL_UNUSED_VAR(file);

    PERL_UNUSED_VAR(cv); /* -W */
    PERL_UNUSED_VAR(items); /* -W */
#if PERL_VERSION_LE(5, 21, 5)
    XS_VERSION_BOOTCHECK;
#  ifdef XS_APIVERSION_BOOTCHECK
    XS_APIVERSION_BOOTCHECK;
#  endif
#endif

        newXS_deffile("Font::FreeType::qefft2_import", XS_Font__FreeType_qefft2_import);
        newXS_deffile("Font::FreeType::new", XS_Font__FreeType_new);
        newXS_deffile("Font::FreeType::DESTROY", XS_Font__FreeType_DESTROY);
        newXS_deffile("Font::FreeType::version", XS_Font__FreeType_version);
        newXS_deffile("Font::FreeType::qefft2_face", XS_Font__FreeType_qefft2_face);
        newXS_deffile("Font::FreeType::Face::load_flags", XS_Font__FreeType__Face_load_flags);
        newXS_deffile("Font::FreeType::Face::DESTROY", XS_Font__FreeType__Face_DESTROY);
        newXS_deffile("Font::FreeType::Face::number_of_faces", XS_Font__FreeType__Face_number_of_faces);
        newXS_deffile("Font::FreeType::Face::current_face_index", XS_Font__FreeType__Face_current_face_index);
        newXS_deffile("Font::FreeType::Face::postscript_name", XS_Font__FreeType__Face_postscript_name);
        newXS_deffile("Font::FreeType::Face::family_name", XS_Font__FreeType__Face_family_name);
        newXS_deffile("Font::FreeType::Face::style_name", XS_Font__FreeType__Face_style_name);
        newXS_deffile("Font::FreeType::Face::is_scalable", XS_Font__FreeType__Face_is_scalable);
        newXS_deffile("Font::FreeType::Face::is_fixed_width", XS_Font__FreeType__Face_is_fixed_width);
        newXS_deffile("Font::FreeType::Face::is_sfnt", XS_Font__FreeType__Face_is_sfnt);
        newXS_deffile("Font::FreeType::Face::has_horizontal_metrics", XS_Font__FreeType__Face_has_horizontal_metrics);
        newXS_deffile("Font::FreeType::Face::has_vertical_metrics", XS_Font__FreeType__Face_has_vertical_metrics);
        newXS_deffile("Font::FreeType::Face::has_kerning", XS_Font__FreeType__Face_has_kerning);
        newXS_deffile("Font::FreeType::Face::has_glyph_names", XS_Font__FreeType__Face_has_glyph_names);
        newXS_deffile("Font::FreeType::Face::has_reliable_glyph_names", XS_Font__FreeType__Face_has_reliable_glyph_names);
        newXS_deffile("Font::FreeType::Face::is_italic", XS_Font__FreeType__Face_is_italic);
        newXS_deffile("Font::FreeType::Face::is_bold", XS_Font__FreeType__Face_is_bold);
        newXS_deffile("Font::FreeType::Face::number_of_glyphs", XS_Font__FreeType__Face_number_of_glyphs);
        newXS_deffile("Font::FreeType::Face::units_per_em", XS_Font__FreeType__Face_units_per_em);
        newXS_deffile("Font::FreeType::Face::attach_file", XS_Font__FreeType__Face_attach_file);
        newXS_deffile("Font::FreeType::Face::set_char_size", XS_Font__FreeType__Face_set_char_size);
        newXS_deffile("Font::FreeType::Face::set_pixel_size", XS_Font__FreeType__Face_set_pixel_size);
        newXS_deffile("Font::FreeType::Face::height", XS_Font__FreeType__Face_height);
        newXS_deffile("Font::FreeType::Face::fixed_sizes", XS_Font__FreeType__Face_fixed_sizes);
        newXS_deffile("Font::FreeType::Face::ascender", XS_Font__FreeType__Face_ascender);
        newXS_deffile("Font::FreeType::Face::descender", XS_Font__FreeType__Face_descender);
        newXS_deffile("Font::FreeType::Face::underline_position", XS_Font__FreeType__Face_underline_position);
        newXS_deffile("Font::FreeType::Face::underline_thickness", XS_Font__FreeType__Face_underline_thickness);
        newXS_deffile("Font::FreeType::Face::charmap", XS_Font__FreeType__Face_charmap);
        newXS_deffile("Font::FreeType::Face::charmaps", XS_Font__FreeType__Face_charmaps);
        newXS_deffile("Font::FreeType::Face::bounding_box", XS_Font__FreeType__Face_bounding_box);
        newXS_deffile("Font::FreeType::Face::namedinfos", XS_Font__FreeType__Face_namedinfos);
        newXS_deffile("Font::FreeType::Face::kerning", XS_Font__FreeType__Face_kerning);
        newXS_deffile("Font::FreeType::Face::glyph_from_char_code", XS_Font__FreeType__Face_glyph_from_char_code);
        newXS_deffile("Font::FreeType::Face::glyph_from_char", XS_Font__FreeType__Face_glyph_from_char);
        newXS_deffile("Font::FreeType::Face::get_name_index", XS_Font__FreeType__Face_get_name_index);
        newXS_deffile("Font::FreeType::Face::glyph_from_index", XS_Font__FreeType__Face_glyph_from_index);
        newXS_deffile("Font::FreeType::Face::glyph_from_name", XS_Font__FreeType__Face_glyph_from_name);
        newXS_deffile("Font::FreeType::Face::foreach_char", XS_Font__FreeType__Face_foreach_char);
        newXS_deffile("Font::FreeType::Face::foreach_glyph", XS_Font__FreeType__Face_foreach_glyph);
        newXS_deffile("Font::FreeType::Glyph::DESTROY", XS_Font__FreeType__Glyph_DESTROY);
        newXS_deffile("Font::FreeType::Glyph::char_code", XS_Font__FreeType__Glyph_char_code);
        newXS_deffile("Font::FreeType::Glyph::index", XS_Font__FreeType__Glyph_index);
        newXS_deffile("Font::FreeType::Glyph::name", XS_Font__FreeType__Glyph_name);
        newXS_deffile("Font::FreeType::Glyph::width", XS_Font__FreeType__Glyph_width);
        newXS_deffile("Font::FreeType::Glyph::height", XS_Font__FreeType__Glyph_height);
        newXS_deffile("Font::FreeType::Glyph::left_bearing", XS_Font__FreeType__Glyph_left_bearing);
        newXS_deffile("Font::FreeType::Glyph::right_bearing", XS_Font__FreeType__Glyph_right_bearing);
        newXS_deffile("Font::FreeType::Glyph::horizontal_advance", XS_Font__FreeType__Glyph_horizontal_advance);
        newXS_deffile("Font::FreeType::Glyph::vertical_advance", XS_Font__FreeType__Glyph_vertical_advance);
        newXS_deffile("Font::FreeType::Glyph::load", XS_Font__FreeType__Glyph_load);
        newXS_deffile("Font::FreeType::Glyph::has_outline", XS_Font__FreeType__Glyph_has_outline);
        newXS_deffile("Font::FreeType::Glyph::outline_bbox", XS_Font__FreeType__Glyph_outline_bbox);
        newXS_deffile("Font::FreeType::Glyph::outline_decompose_", XS_Font__FreeType__Glyph_outline_decompose_);
        newXS_deffile("Font::FreeType::Glyph::bitmap", XS_Font__FreeType__Glyph_bitmap);
        newXS_deffile("Font::FreeType::CharMap::encoding", XS_Font__FreeType__CharMap_encoding);
        newXS_deffile("Font::FreeType::CharMap::platform_id", XS_Font__FreeType__CharMap_platform_id);
        newXS_deffile("Font::FreeType::CharMap::encoding_id", XS_Font__FreeType__CharMap_encoding_id);
        newXS_deffile("Font::FreeType::NamedInfo::DESTROY", XS_Font__FreeType__NamedInfo_DESTROY);
        newXS_deffile("Font::FreeType::NamedInfo::platform_id", XS_Font__FreeType__NamedInfo_platform_id);
        newXS_deffile("Font::FreeType::NamedInfo::encoding_id", XS_Font__FreeType__NamedInfo_encoding_id);
        newXS_deffile("Font::FreeType::NamedInfo::language_id", XS_Font__FreeType__NamedInfo_language_id);
        newXS_deffile("Font::FreeType::NamedInfo::name_id", XS_Font__FreeType__NamedInfo_name_id);
        newXS_deffile("Font::FreeType::NamedInfo::string", XS_Font__FreeType__NamedInfo_string);
        newXS_deffile("Font::FreeType::BoundingBox::x_min", XS_Font__FreeType__BoundingBox_x_min);
        newXS_deffile("Font::FreeType::BoundingBox::y_min", XS_Font__FreeType__BoundingBox_y_min);
        newXS_deffile("Font::FreeType::BoundingBox::x_max", XS_Font__FreeType__BoundingBox_x_max);
        newXS_deffile("Font::FreeType::BoundingBox::y_max", XS_Font__FreeType__BoundingBox_y_max);
#if PERL_VERSION_LE(5, 21, 5)
#  if PERL_VERSION_GE(5, 9, 0)
    if (PL_unitcheckav)
        call_list(PL_scopestack_ix, PL_unitcheckav);
#  endif
    XSRETURN_YES;
#else
    Perl_xs_boot_epilog(aTHX_ ax);
#endif
}

