Prima
view release on metacpan or search on metacpan
class/Drawable/shape.c view on Meta::CPAN
#include "apricot.h"
#include "guts.h"
#include "Drawable.h"
#include "Application.h"
#include "Drawable_private.h"
#ifdef WITH_FRIBIDI
#include <fribidi/fribidi.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
static void*
warn_malloc(ssize_t size)
{
void * ret;
if (!(ret = malloc(size))) {
warn("Drawable.text_shape: not enough memory");
return NULL;
}
return ret;
}
static uint32_t*
sv2uint32( SV * text, unsigned int * size, unsigned int * flags)
{
STRLEN dlen;
register char * src;
uint32_t *ret;
src = SvPV(text, dlen);
if (prima_is_utf8_sv(text)) {
*flags |= toUTF8;
*size = prima_utf8_length(src, dlen);
} else {
*size = dlen;
}
if (!(ret = ( uint32_t*) warn_malloc(sizeof(uint32_t) * (*size))))
return NULL;
if (*flags & toUTF8 ) {
uint32_t *dst = ret;
while ( dlen > 0 && dst - ret < *size) {
STRLEN charlen;
UV uv;
uv = prima_utf8_uvchr(src, dlen, &charlen);
if ( uv > 0x10FFFF ) uv = 0x10FFFF;
*(dst++) = uv;
if ( charlen == 0 ) break;
src += charlen;
dlen -= charlen;
}
*size = dst - ret;
} else {
register int i = *size;
register uint32_t *dst = ret;
while (i-- > 0) *(dst++) = *((unsigned char*) src++);
}
return ret;
}
/*
Iterator for individual shaper runs. Each run has same direction
and its indexes are increasing/decreasing monotonically. The latter is
to avoid situations where text A<PDF>B is being sent to shaper as single run AB
which might ligate.
*/
typedef struct {
unsigned int i, vis_len;
} BidiRunRec, *PBidiRunRec;
static void
run_init(PBidiRunRec r, int visual_length)
{
r->i = 0;
r->vis_len = visual_length;
}
static int
run_next(PTextShapeRec t, PBidiRunRec r)
{
int rtl, font, start = r->i;
if ( r->i >= r->vis_len ) return 0;
rtl = t->analysis[r->i];
font = t->fonts ? t->fonts[r->i] : 0;
for ( ; r->i < r->vis_len + 1; r->i++) {
if (
r->i >= r->vis_len || /* eol */
(t-> analysis[r->i] != rtl) || /* rtl != ltr */
(t->fonts && font != t->fonts[r->i])
) {
return r->i - start;
}
}
return 0;
}
#define INVERT(_type,_start,_end) \
{ \
register _type *s = _start, *e = _end;\
while ( s < e ) { \
class/Drawable/shape.c view on Meta::CPAN
if ( t.len == 0 ) {
return_zero = true;
goto EXIT;
}
if ( level != tsBytes ) {
if (!(t.analysis = warn_malloc(t.len)))
goto EXIT;
if (!(t.v2l = warn_malloc(sizeof(uint16_t) * t.len)))
goto EXIT;
}
/* MSDN, on ScriptShape: A reasonable value is (1.5 * cChars + 16) */
t.n_glyphs_max = t.len * 2 + 16;
#define ALLOC(id,n,type) { \
sv_##id = prima_array_new( t.n_glyphs_max * n * sizeof(uint16_t)); \
t.id = (type*) prima_array_get_storage(sv_##id); \
}
ALLOC(glyphs,1,uint16_t);
ALLOC(indexes,1,uint16_t);
if ( shaper_type == tsFull || force_advances) {
ALLOC(positions,2,int16_t);
ALLOC(advances,1,uint16_t);
} else {
sv_positions = sv_advances = NULL_SV;
t.positions = NULL;
t.advances = NULL;
}
if ( polyfont ) {
ALLOC(fonts,1,uint16_t);
bzero(t.fonts, sizeof(uint16_t) * t.n_glyphs_max);
} else {
sv_fonts = NULL_SV;
t.fonts = NULL;
}
#undef ALLOC
if ( level == tsBytes ) {
int i;
uint16_t * indexes;
if ( !system_shaper(self, &t))
goto EXIT;
for ( i = 0, indexes = t.indexes; i < t.n_glyphs; i++)
*(indexes++) = i;
} else {
if ( !shape_unicode(self, &t,
system_shaper, shaper_type < tsFull,
(level < tsFull) ? false : (shaper_type < tsFull), reorder)
) goto EXIT;
}
if ( skip_if_simple ) {
Bool is_simple = true;
for ( i = 0; i < t.n_glyphs; i++) {
if ( i != t.indexes[i] ) {
is_simple = false;
break;
}
}
if ( is_simple && !(t.flags & toUTF8))
for ( i = 0; i < t.len; i++) {
if (t.text[i] > 0x7f) {
is_simple = false;
break;
}
}
if ( is_simple ) {
return_zero = true;
goto EXIT;
}
}
if (gp_enter) gpLEAVE;
/* encode direction */
if ( level != tsBytes ) {
for ( i = 0; i < t.n_glyphs; i++) {
if ( t.analysis[ t.indexes[i] ] & 1 )
t.indexes[i] |= toRTL;
}
}
/* add an extra index as text length */
t.indexes[t.n_glyphs] = t.len;
free(t.v2l );
free(t.analysis );
free(t.text);
t.v2l = NULL;
t.analysis = NULL;
t.text = NULL;
if (sv_fonts != NULL_SV) {
int i, non_zero = 0;
for ( i = 0; i < t.n_glyphs; i++) {
if ( t.fonts[i] != 0 ) {
non_zero = 1;
break;
}
}
if (!non_zero) {
sv_free(sv_fonts);
sv_fonts = NULL_SV;
}
}
#define BIND(x,n,d,letter) { \
prima_array_truncate(x, (t.n_glyphs * n + d) * sizeof(uint16_t)); \
x = sv_2mortal(prima_array_tie( x, sizeof(uint16_t), letter)); \
}
BIND(sv_glyphs, 1, 0, "S");
BIND(sv_indexes, 1, 1, "S");
if ( sv_positions != NULL_SV ) BIND(sv_positions, 2, 0, "s");
if ( sv_advances != NULL_SV ) BIND(sv_advances, 1, 0, "S");
if ( sv_fonts != NULL_SV ) BIND(sv_fonts, 1, 0, "S");
#undef BIND
return newSVsv(call_perl(self, "new_glyph_obj", "<SSSSS",
sv_glyphs, sv_indexes, sv_advances, sv_positions, sv_fonts
));
( run in 2.162 seconds using v1.01-cache-2.11-cpan-a49fcb8fa48 )