Font-FreeType
view release on metacpan or search on metacpan
FreeType.xs view on Meta::CPAN
/* 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;
FreeType.xs view on Meta::CPAN
}
++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)
( run in 1.189 second using v1.01-cache-2.11-cpan-483215c6ad5 )