/contrib/media/updf/fitz/base_error.c |
---|
0,0 → 1,159 |
#include "fitz.h" |
enum { LINE_LEN = 160, LINE_COUNT = 25 }; |
static char warn_message[LINE_LEN] = ""; |
static int warn_count = 0; |
void fz_flush_warnings(void) |
{ |
if (warn_count > 1) |
fprintf(stderr, "warning: ... repeated %d times ...\n", warn_count); |
warn_message[0] = 0; |
warn_count = 0; |
} |
void fz_warn(char *fmt, ...) |
{ |
va_list ap; |
char buf[LINE_LEN]; |
va_start(ap, fmt); |
vsnprintf(buf, sizeof buf, fmt, ap); |
va_end(ap); |
if (!strcmp(buf, warn_message)) |
{ |
warn_count++; |
} |
else |
{ |
fz_flush_warnings(); |
fprintf(stderr, "warning: %s\n", buf); |
fz_strlcpy(warn_message, buf, sizeof warn_message); |
warn_count = 1; |
} |
} |
static char error_message[LINE_COUNT][LINE_LEN]; |
static int error_count = 0; |
static void |
fz_emit_error(char what, char *location, char *message) |
{ |
fz_flush_warnings(); |
fprintf(stderr, "%c %s%s\n", what, location, message); |
if (error_count < LINE_COUNT) |
{ |
fz_strlcpy(error_message[error_count], location, LINE_LEN); |
fz_strlcat(error_message[error_count], message, LINE_LEN); |
error_count++; |
} |
} |
int |
fz_get_error_count(void) |
{ |
return error_count; |
} |
char * |
fz_get_error_line(int n) |
{ |
return error_message[n]; |
} |
fz_error |
fz_throw_imp(const char *file, int line, const char *func, char *fmt, ...) |
{ |
va_list ap; |
char one[LINE_LEN], two[LINE_LEN]; |
error_count = 0; |
snprintf(one, sizeof one, "%s:%d: %s(): ", file, line, func); |
va_start(ap, fmt); |
vsnprintf(two, sizeof two, fmt, ap); |
va_end(ap); |
fz_emit_error('+', one, two); |
return -1; |
} |
fz_error |
fz_rethrow_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) |
{ |
va_list ap; |
char one[LINE_LEN], two[LINE_LEN]; |
snprintf(one, sizeof one, "%s:%d: %s(): ", file, line, func); |
va_start(ap, fmt); |
vsnprintf(two, sizeof two, fmt, ap); |
va_end(ap); |
fz_emit_error('|', one, two); |
return cause; |
} |
void |
fz_catch_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) |
{ |
va_list ap; |
char one[LINE_LEN], two[LINE_LEN]; |
snprintf(one, sizeof one, "%s:%d: %s(): ", file, line, func); |
va_start(ap, fmt); |
vsnprintf(two, sizeof two, fmt, ap); |
va_end(ap); |
fz_emit_error('\\', one, two); |
} |
fz_error |
fz_throw_impx(char *fmt, ...) |
{ |
va_list ap; |
char buf[LINE_LEN]; |
error_count = 0; |
va_start(ap, fmt); |
vsnprintf(buf, sizeof buf, fmt, ap); |
va_end(ap); |
fz_emit_error('+', "", buf); |
return -1; |
} |
fz_error |
fz_rethrow_impx(fz_error cause, char *fmt, ...) |
{ |
va_list ap; |
char buf[LINE_LEN]; |
va_start(ap, fmt); |
vsnprintf(buf, sizeof buf, fmt, ap); |
va_end(ap); |
fz_emit_error('|', "", buf); |
return cause; |
} |
void |
fz_catch_impx(fz_error cause, char *fmt, ...) |
{ |
va_list ap; |
char buf[LINE_LEN]; |
va_start(ap, fmt); |
vsnprintf(buf, sizeof buf, fmt, ap); |
va_end(ap); |
fz_emit_error('\\', "", buf); |
} |
/contrib/media/updf/fitz/base_geometry.c |
---|
0,0 → 1,268 |
#include "fitz.h" |
#define MAX4(a,b,c,d) MAX(MAX(a,b), MAX(c,d)) |
#define MIN4(a,b,c,d) MIN(MIN(a,b), MIN(c,d)) |
/* Matrices, points and affine transformations */ |
const fz_matrix fz_identity = { 1, 0, 0, 1, 0, 0 }; |
fz_matrix |
fz_concat(fz_matrix one, fz_matrix two) |
{ |
fz_matrix dst; |
dst.a = one.a * two.a + one.b * two.c; |
dst.b = one.a * two.b + one.b * two.d; |
dst.c = one.c * two.a + one.d * two.c; |
dst.d = one.c * two.b + one.d * two.d; |
dst.e = one.e * two.a + one.f * two.c + two.e; |
dst.f = one.e * two.b + one.f * two.d + two.f; |
return dst; |
} |
fz_matrix |
fz_scale(float sx, float sy) |
{ |
fz_matrix m; |
m.a = sx; m.b = 0; |
m.c = 0; m.d = sy; |
m.e = 0; m.f = 0; |
return m; |
} |
fz_matrix |
fz_shear(float h, float v) |
{ |
fz_matrix m; |
m.a = 1; m.b = v; |
m.c = h; m.d = 1; |
m.e = 0; m.f = 0; |
return m; |
} |
fz_matrix |
fz_rotate(float theta) |
{ |
fz_matrix m; |
float s; |
float c; |
while (theta < 0) |
theta += 360; |
while (theta >= 360) |
theta -= 360; |
if (fabsf(0 - theta) < FLT_EPSILON) |
{ |
s = 0; |
c = 1; |
} |
else if (fabsf(90.0f - theta) < FLT_EPSILON) |
{ |
s = 1; |
c = 0; |
} |
else if (fabsf(180.0f - theta) < FLT_EPSILON) |
{ |
s = 0; |
c = -1; |
} |
else if (fabsf(270.0f - theta) < FLT_EPSILON) |
{ |
s = -1; |
c = 0; |
} |
else |
{ |
s = sinf(theta * (float)M_PI / 180); |
c = cosf(theta * (float)M_PI / 180); |
} |
m.a = c; m.b = s; |
m.c = -s; m.d = c; |
m.e = 0; m.f = 0; |
return m; |
} |
fz_matrix |
fz_translate(float tx, float ty) |
{ |
fz_matrix m; |
m.a = 1; m.b = 0; |
m.c = 0; m.d = 1; |
m.e = tx; m.f = ty; |
return m; |
} |
fz_matrix |
fz_invert_matrix(fz_matrix src) |
{ |
fz_matrix dst; |
float rdet = 1 / (src.a * src.d - src.b * src.c); |
dst.a = src.d * rdet; |
dst.b = -src.b * rdet; |
dst.c = -src.c * rdet; |
dst.d = src.a * rdet; |
dst.e = -src.e * dst.a - src.f * dst.c; |
dst.f = -src.e * dst.b - src.f * dst.d; |
return dst; |
} |
int |
fz_is_rectilinear(fz_matrix m) |
{ |
return (fabsf(m.b) < FLT_EPSILON && fabsf(m.c) < FLT_EPSILON) || |
(fabsf(m.a) < FLT_EPSILON && fabsf(m.d) < FLT_EPSILON); |
} |
float |
fz_matrix_expansion(fz_matrix m) |
{ |
return sqrtf(fabsf(m.a * m.d - m.b * m.c)); |
} |
fz_point |
fz_transform_point(fz_matrix m, fz_point p) |
{ |
fz_point t; |
t.x = p.x * m.a + p.y * m.c + m.e; |
t.y = p.x * m.b + p.y * m.d + m.f; |
return t; |
} |
fz_point |
fz_transform_vector(fz_matrix m, fz_point p) |
{ |
fz_point t; |
t.x = p.x * m.a + p.y * m.c; |
t.y = p.x * m.b + p.y * m.d; |
return t; |
} |
/* Rectangles and bounding boxes */ |
const fz_rect fz_infinite_rect = { 1, 1, -1, -1 }; |
const fz_rect fz_empty_rect = { 0, 0, 0, 0 }; |
const fz_rect fz_unit_rect = { 0, 0, 1, 1 }; |
const fz_bbox fz_infinite_bbox = { 1, 1, -1, -1 }; |
const fz_bbox fz_empty_bbox = { 0, 0, 0, 0 }; |
const fz_bbox fz_unit_bbox = { 0, 0, 1, 1 }; |
fz_bbox |
fz_round_rect(fz_rect f) |
{ |
fz_bbox i; |
i.x0 = floorf(f.x0 + 0.001f); /* adjust by 0.001 to compensate for precision errors */ |
i.y0 = floorf(f.y0 + 0.001f); |
i.x1 = ceilf(f.x1 - 0.001f); |
i.y1 = ceilf(f.y1 - 0.001f); |
return i; |
} |
fz_rect |
fz_intersect_rect(fz_rect a, fz_rect b) |
{ |
fz_rect r; |
if (fz_is_infinite_rect(a)) return b; |
if (fz_is_infinite_rect(b)) return a; |
if (fz_is_empty_rect(a)) return fz_empty_rect; |
if (fz_is_empty_rect(b)) return fz_empty_rect; |
r.x0 = MAX(a.x0, b.x0); |
r.y0 = MAX(a.y0, b.y0); |
r.x1 = MIN(a.x1, b.x1); |
r.y1 = MIN(a.y1, b.y1); |
return (r.x1 < r.x0 || r.y1 < r.y0) ? fz_empty_rect : r; |
} |
fz_rect |
fz_union_rect(fz_rect a, fz_rect b) |
{ |
fz_rect r; |
if (fz_is_infinite_rect(a)) return a; |
if (fz_is_infinite_rect(b)) return b; |
if (fz_is_empty_rect(a)) return b; |
if (fz_is_empty_rect(b)) return a; |
r.x0 = MIN(a.x0, b.x0); |
r.y0 = MIN(a.y0, b.y0); |
r.x1 = MAX(a.x1, b.x1); |
r.y1 = MAX(a.y1, b.y1); |
return r; |
} |
fz_bbox |
fz_intersect_bbox(fz_bbox a, fz_bbox b) |
{ |
fz_bbox r; |
if (fz_is_infinite_rect(a)) return b; |
if (fz_is_infinite_rect(b)) return a; |
if (fz_is_empty_rect(a)) return fz_empty_bbox; |
if (fz_is_empty_rect(b)) return fz_empty_bbox; |
r.x0 = MAX(a.x0, b.x0); |
r.y0 = MAX(a.y0, b.y0); |
r.x1 = MIN(a.x1, b.x1); |
r.y1 = MIN(a.y1, b.y1); |
return (r.x1 < r.x0 || r.y1 < r.y0) ? fz_empty_bbox : r; |
} |
fz_bbox |
fz_union_bbox(fz_bbox a, fz_bbox b) |
{ |
fz_bbox r; |
if (fz_is_infinite_rect(a)) return a; |
if (fz_is_infinite_rect(b)) return b; |
if (fz_is_empty_rect(a)) return b; |
if (fz_is_empty_rect(b)) return a; |
r.x0 = MIN(a.x0, b.x0); |
r.y0 = MIN(a.y0, b.y0); |
r.x1 = MAX(a.x1, b.x1); |
r.y1 = MAX(a.y1, b.y1); |
return r; |
} |
fz_rect |
fz_transform_rect(fz_matrix m, fz_rect r) |
{ |
fz_point s, t, u, v; |
if (fz_is_infinite_rect(r)) |
return r; |
s.x = r.x0; s.y = r.y0; |
t.x = r.x0; t.y = r.y1; |
u.x = r.x1; u.y = r.y1; |
v.x = r.x1; v.y = r.y0; |
s = fz_transform_point(m, s); |
t = fz_transform_point(m, t); |
u = fz_transform_point(m, u); |
v = fz_transform_point(m, v); |
r.x0 = MIN4(s.x, t.x, u.x, v.x); |
r.y0 = MIN4(s.y, t.y, u.y, v.y); |
r.x1 = MAX4(s.x, t.x, u.x, v.x); |
r.y1 = MAX4(s.y, t.y, u.y, v.y); |
return r; |
} |
fz_bbox |
fz_transform_bbox(fz_matrix m, fz_bbox b) |
{ |
fz_point s, t, u, v; |
if (fz_is_infinite_bbox(b)) |
return b; |
s.x = b.x0; s.y = b.y0; |
t.x = b.x0; t.y = b.y1; |
u.x = b.x1; u.y = b.y1; |
v.x = b.x1; v.y = b.y0; |
s = fz_transform_point(m, s); |
t = fz_transform_point(m, t); |
u = fz_transform_point(m, u); |
v = fz_transform_point(m, v); |
b.x0 = MIN4(s.x, t.x, u.x, v.x); |
b.y0 = MIN4(s.y, t.y, u.y, v.y); |
b.x1 = MAX4(s.x, t.x, u.x, v.x); |
b.y1 = MAX4(s.y, t.y, u.y, v.y); |
return b; |
} |
/contrib/media/updf/fitz/base_getopt.c |
---|
0,0 → 1,66 |
/* |
* This is a version of the public domain getopt implementation by |
* Henry Spencer originally posted to net.sources. |
* |
* This file is in the public domain. |
*/ |
#include <stdio.h> |
#include <string.h> |
#define getopt fz_getopt |
#define optarg fz_optarg |
#define optind fz_optind |
char *optarg; /* Global argument pointer. */ |
int optind = 0; /* Global argv index. */ |
static char *scan = NULL; /* Private scan pointer. */ |
int |
getopt(int argc, char *argv[], char *optstring) |
{ |
char c; |
char *place; |
optarg = NULL; |
if (scan == NULL || *scan == '\0') { |
if (optind == 0) |
optind++; |
if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') |
return EOF; |
if (argv[optind][1] == '-' && argv[optind][2] == '\0') { |
optind++; |
return EOF; |
} |
scan = argv[optind]+1; |
optind++; |
} |
c = *scan++; |
place = strchr(optstring, c); |
if (place == NULL || c == ':') { |
fprintf(stderr, "%s: unknown option -%c\n", argv[0], c); |
return '?'; |
} |
place++; |
if (*place == ':') { |
if (*scan != '\0') { |
optarg = scan; |
scan = NULL; |
} else if( optind < argc ) { |
optarg = argv[optind]; |
optind++; |
} else { |
fprintf(stderr, "%s: option requires argument -%c\n", argv[0], c); |
return ':'; |
} |
} |
return c; |
} |
/contrib/media/updf/fitz/base_hash.c |
---|
0,0 → 1,241 |
#include "fitz.h" |
/* |
Simple hashtable with open adressing linear probe. |
Unlike text book examples, removing entries works |
correctly in this implementation, so it wont start |
exhibiting bad behaviour if entries are inserted |
and removed frequently. |
*/ |
enum { MAX_KEY_LEN = 48 }; |
typedef struct fz_hash_entry_s fz_hash_entry; |
struct fz_hash_entry_s |
{ |
unsigned char key[MAX_KEY_LEN]; |
void *val; |
}; |
struct fz_hash_table_s |
{ |
int keylen; |
int size; |
int load; |
fz_hash_entry *ents; |
}; |
static unsigned hash(unsigned char *s, int len) |
{ |
unsigned val = 0; |
int i; |
for (i = 0; i < len; i++) |
{ |
val += s[i]; |
val += (val << 10); |
val ^= (val >> 6); |
} |
val += (val << 3); |
val ^= (val >> 11); |
val += (val << 15); |
return val; |
} |
fz_hash_table * |
fz_new_hash_table(int initialsize, int keylen) |
{ |
fz_hash_table *table; |
assert(keylen <= MAX_KEY_LEN); |
table = fz_malloc(sizeof(fz_hash_table)); |
table->keylen = keylen; |
table->size = initialsize; |
table->load = 0; |
table->ents = fz_calloc(table->size, sizeof(fz_hash_entry)); |
memset(table->ents, 0, sizeof(fz_hash_entry) * table->size); |
return table; |
} |
void |
fz_empty_hash(fz_hash_table *table) |
{ |
table->load = 0; |
memset(table->ents, 0, sizeof(fz_hash_entry) * table->size); |
} |
int |
fz_hash_len(fz_hash_table *table) |
{ |
return table->size; |
} |
void * |
fz_hash_get_key(fz_hash_table *table, int idx) |
{ |
return table->ents[idx].key; |
} |
void * |
fz_hash_get_val(fz_hash_table *table, int idx) |
{ |
return table->ents[idx].val; |
} |
void |
fz_free_hash(fz_hash_table *table) |
{ |
fz_free(table->ents); |
fz_free(table); |
} |
static void |
fz_resize_hash(fz_hash_table *table, int newsize) |
{ |
fz_hash_entry *oldents = table->ents; |
int oldsize = table->size; |
int oldload = table->load; |
int i; |
if (newsize < oldload * 8 / 10) |
{ |
fz_throw("assert: resize hash too small"); |
return; |
} |
table->ents = fz_calloc(newsize, sizeof(fz_hash_entry)); |
memset(table->ents, 0, sizeof(fz_hash_entry) * newsize); |
table->size = newsize; |
table->load = 0; |
for (i = 0; i < oldsize; i++) |
{ |
if (oldents[i].val) |
{ |
fz_hash_insert(table, oldents[i].key, oldents[i].val); |
} |
} |
fz_free(oldents); |
} |
void * |
fz_hash_find(fz_hash_table *table, void *key) |
{ |
fz_hash_entry *ents = table->ents; |
unsigned size = table->size; |
unsigned pos = hash(key, table->keylen) % size; |
while (1) |
{ |
if (!ents[pos].val) |
return NULL; |
if (memcmp(key, ents[pos].key, table->keylen) == 0) |
return ents[pos].val; |
pos = (pos + 1) % size; |
} |
} |
void |
fz_hash_insert(fz_hash_table *table, void *key, void *val) |
{ |
fz_hash_entry *ents; |
unsigned size; |
unsigned pos; |
if (table->load > table->size * 8 / 10) |
{ |
fz_resize_hash(table, table->size * 2); |
} |
ents = table->ents; |
size = table->size; |
pos = hash(key, table->keylen) % size; |
while (1) |
{ |
if (!ents[pos].val) |
{ |
memcpy(ents[pos].key, key, table->keylen); |
ents[pos].val = val; |
table->load ++; |
return; |
} |
if (memcmp(key, ents[pos].key, table->keylen) == 0) |
fz_warn("assert: overwrite hash slot"); |
pos = (pos + 1) % size; |
} |
} |
void |
fz_hash_remove(fz_hash_table *table, void *key) |
{ |
fz_hash_entry *ents = table->ents; |
unsigned size = table->size; |
unsigned pos = hash(key, table->keylen) % size; |
unsigned hole, look, code; |
while (1) |
{ |
if (!ents[pos].val) |
{ |
fz_warn("assert: remove inexistant hash entry"); |
return; |
} |
if (memcmp(key, ents[pos].key, table->keylen) == 0) |
{ |
ents[pos].val = NULL; |
hole = pos; |
look = (hole + 1) % size; |
while (ents[look].val) |
{ |
code = hash(ents[look].key, table->keylen) % size; |
if ((code <= hole && hole < look) || |
(look < code && code <= hole) || |
(hole < look && look < code)) |
{ |
ents[hole] = ents[look]; |
ents[look].val = NULL; |
hole = look; |
} |
look = (look + 1) % size; |
} |
table->load --; |
return; |
} |
pos = (pos + 1) % size; |
} |
} |
void |
fz_debug_hash(fz_hash_table *table) |
{ |
int i, k; |
printf("cache load %d / %d\n", table->load, table->size); |
for (i = 0; i < table->size; i++) |
{ |
if (!table->ents[i].val) |
printf("table % 4d: empty\n", i); |
else |
{ |
printf("table % 4d: key=", i); |
for (k = 0; k < MAX_KEY_LEN; k++) |
printf("%02x", ((char*)table->ents[i].key)[k]); |
printf(" val=$%p\n", table->ents[i].val); |
} |
} |
} |
/contrib/media/updf/fitz/base_memory.c |
---|
0,0 → 1,77 |
#include "fitz.h" |
void * |
fz_malloc(int size) |
{ |
void *p = malloc(size); |
if (!p) |
{ |
fprintf(stderr, "fatal error: out of memory\n"); |
abort(); |
} |
return p; |
} |
void * |
fz_calloc(int count, int size) |
{ |
void *p; |
if (count == 0 || size == 0) |
return 0; |
if (count < 0 || size < 0 || count > INT_MAX / size) |
{ |
fprintf(stderr, "fatal error: out of memory (integer overflow)\n"); |
abort(); |
} |
p = malloc(count * size); |
if (!p) |
{ |
fprintf(stderr, "fatal error: out of memory\n"); |
abort(); |
} |
return p; |
} |
void * |
fz_realloc(void *p, int count, int size) |
{ |
void *np; |
if (count == 0 || size == 0) |
{ |
fz_free(p); |
return 0; |
} |
if (count < 0 || size < 0 || count > INT_MAX / size) |
{ |
fprintf(stderr, "fatal error: out of memory (integer overflow)\n"); |
abort(); |
} |
np = realloc(p, count * size); |
if (np == NULL) |
{ |
fprintf(stderr, "fatal error: out of memory\n"); |
abort(); |
} |
return np; |
} |
void |
fz_free(void *p) |
{ |
free(p); |
} |
char * |
fz_strdup(char *s) |
{ |
int len = strlen(s) + 1; |
char *ns = fz_malloc(len); |
memcpy(ns, s, len); |
return ns; |
} |
/contrib/media/updf/fitz/base_object.c |
---|
0,0 → 1,802 |
#include "fitz.h" |
typedef enum fz_objkind_e |
{ |
FZ_NULL, |
FZ_BOOL, |
FZ_INT, |
FZ_REAL, |
FZ_STRING, |
FZ_NAME, |
FZ_ARRAY, |
FZ_DICT, |
FZ_INDIRECT |
} fz_objkind; |
struct keyval |
{ |
fz_obj *k; |
fz_obj *v; |
}; |
struct fz_obj_s |
{ |
int refs; |
fz_objkind kind; |
union |
{ |
int b; |
int i; |
float f; |
struct { |
unsigned short len; |
char buf[1]; |
} s; |
char n[1]; |
struct { |
int len; |
int cap; |
fz_obj **items; |
} a; |
struct { |
char sorted; |
int len; |
int cap; |
struct keyval *items; |
} d; |
struct { |
int num; |
int gen; |
struct pdf_xref_s *xref; |
} r; |
} u; |
}; |
static fz_obj *fz_resolve_indirect_null(fz_obj *ref) |
{ |
return ref; |
} |
fz_obj* (*fz_resolve_indirect)(fz_obj*) = fz_resolve_indirect_null; |
fz_obj * |
fz_new_null(void) |
{ |
fz_obj *obj = fz_malloc(sizeof(fz_obj)); |
obj->refs = 1; |
obj->kind = FZ_NULL; |
return obj; |
} |
fz_obj * |
fz_new_bool(int b) |
{ |
fz_obj *obj = fz_malloc(sizeof(fz_obj)); |
obj->refs = 1; |
obj->kind = FZ_BOOL; |
obj->u.b = b; |
return obj; |
} |
fz_obj * |
fz_new_int(int i) |
{ |
fz_obj *obj = fz_malloc(sizeof(fz_obj)); |
obj->refs = 1; |
obj->kind = FZ_INT; |
obj->u.i = i; |
return obj; |
} |
fz_obj * |
fz_new_real(float f) |
{ |
fz_obj *obj = fz_malloc(sizeof(fz_obj)); |
obj->refs = 1; |
obj->kind = FZ_REAL; |
obj->u.f = f; |
return obj; |
} |
fz_obj * |
fz_new_string(char *str, int len) |
{ |
fz_obj *obj = fz_malloc(offsetof(fz_obj, u.s.buf) + len + 1); |
obj->refs = 1; |
obj->kind = FZ_STRING; |
obj->u.s.len = len; |
memcpy(obj->u.s.buf, str, len); |
obj->u.s.buf[len] = '\0'; |
return obj; |
} |
fz_obj * |
fz_new_name(char *str) |
{ |
fz_obj *obj = fz_malloc(offsetof(fz_obj, u.n) + strlen(str) + 1); |
obj->refs = 1; |
obj->kind = FZ_NAME; |
strcpy(obj->u.n, str); |
return obj; |
} |
fz_obj * |
fz_new_indirect(int num, int gen, void *xref) |
{ |
fz_obj *obj = fz_malloc(sizeof(fz_obj)); |
obj->refs = 1; |
obj->kind = FZ_INDIRECT; |
obj->u.r.num = num; |
obj->u.r.gen = gen; |
obj->u.r.xref = xref; |
return obj; |
} |
fz_obj * |
fz_keep_obj(fz_obj *obj) |
{ |
assert(obj != NULL); |
obj->refs ++; |
return obj; |
} |
int fz_is_indirect(fz_obj *obj) |
{ |
return obj ? obj->kind == FZ_INDIRECT : 0; |
} |
int fz_is_null(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
return obj ? obj->kind == FZ_NULL : 0; |
} |
int fz_is_bool(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
return obj ? obj->kind == FZ_BOOL : 0; |
} |
int fz_is_int(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
return obj ? obj->kind == FZ_INT : 0; |
} |
int fz_is_real(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
return obj ? obj->kind == FZ_REAL : 0; |
} |
int fz_is_string(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
return obj ? obj->kind == FZ_STRING : 0; |
} |
int fz_is_name(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
return obj ? obj->kind == FZ_NAME : 0; |
} |
int fz_is_array(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
return obj ? obj->kind == FZ_ARRAY : 0; |
} |
int fz_is_dict(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
return obj ? obj->kind == FZ_DICT : 0; |
} |
int fz_to_bool(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
if (fz_is_bool(obj)) |
return obj->u.b; |
return 0; |
} |
int fz_to_int(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
if (fz_is_int(obj)) |
return obj->u.i; |
if (fz_is_real(obj)) |
return obj->u.f; |
return 0; |
} |
float fz_to_real(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
if (fz_is_real(obj)) |
return obj->u.f; |
if (fz_is_int(obj)) |
return obj->u.i; |
return 0; |
} |
char *fz_to_name(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
if (fz_is_name(obj)) |
return obj->u.n; |
return ""; |
} |
char *fz_to_str_buf(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
if (fz_is_string(obj)) |
return obj->u.s.buf; |
return ""; |
} |
int fz_to_str_len(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
if (fz_is_string(obj)) |
return obj->u.s.len; |
return 0; |
} |
/* for use by pdf_crypt_obj_imp to decrypt AES string in place */ |
void fz_set_str_len(fz_obj *obj, int newlen) |
{ |
obj = fz_resolve_indirect(obj); |
if (fz_is_string(obj)) |
if (newlen < obj->u.s.len) |
obj->u.s.len = newlen; |
} |
int fz_to_num(fz_obj *obj) |
{ |
if (fz_is_indirect(obj)) |
return obj->u.r.num; |
return 0; |
} |
int fz_to_gen(fz_obj *obj) |
{ |
if (fz_is_indirect(obj)) |
return obj->u.r.gen; |
return 0; |
} |
void *fz_get_indirect_xref(fz_obj *obj) |
{ |
if (fz_is_indirect(obj)) |
return obj->u.r.xref; |
return NULL; |
} |
int |
fz_objcmp(fz_obj *a, fz_obj *b) |
{ |
int i; |
if (a == b) |
return 0; |
if (!a || !b) |
return 1; |
if (a->kind != b->kind) |
return 1; |
switch (a->kind) |
{ |
case FZ_NULL: |
return 0; |
case FZ_BOOL: |
return a->u.b - b->u.b; |
case FZ_INT: |
return a->u.i - b->u.i; |
case FZ_REAL: |
if (a->u.f < b->u.f) |
return -1; |
if (a->u.f > b->u.f) |
return 1; |
return 0; |
case FZ_STRING: |
if (a->u.s.len < b->u.s.len) |
{ |
if (memcmp(a->u.s.buf, b->u.s.buf, a->u.s.len) <= 0) |
return -1; |
return 1; |
} |
if (a->u.s.len > b->u.s.len) |
{ |
if (memcmp(a->u.s.buf, b->u.s.buf, b->u.s.len) >= 0) |
return 1; |
return -1; |
} |
return memcmp(a->u.s.buf, b->u.s.buf, a->u.s.len); |
case FZ_NAME: |
return strcmp(a->u.n, b->u.n); |
case FZ_INDIRECT: |
if (a->u.r.num == b->u.r.num) |
return a->u.r.gen - b->u.r.gen; |
return a->u.r.num - b->u.r.num; |
case FZ_ARRAY: |
if (a->u.a.len != b->u.a.len) |
return a->u.a.len - b->u.a.len; |
for (i = 0; i < a->u.a.len; i++) |
if (fz_objcmp(a->u.a.items[i], b->u.a.items[i])) |
return 1; |
return 0; |
case FZ_DICT: |
if (a->u.d.len != b->u.d.len) |
return a->u.d.len - b->u.d.len; |
for (i = 0; i < a->u.d.len; i++) |
{ |
if (fz_objcmp(a->u.d.items[i].k, b->u.d.items[i].k)) |
return 1; |
if (fz_objcmp(a->u.d.items[i].v, b->u.d.items[i].v)) |
return 1; |
} |
return 0; |
} |
return 1; |
} |
static char * |
fz_objkindstr(fz_obj *obj) |
{ |
if (obj == NULL) |
return "<NULL>"; |
switch (obj->kind) |
{ |
case FZ_NULL: return "null"; |
case FZ_BOOL: return "boolean"; |
case FZ_INT: return "integer"; |
case FZ_REAL: return "real"; |
case FZ_STRING: return "string"; |
case FZ_NAME: return "name"; |
case FZ_ARRAY: return "array"; |
case FZ_DICT: return "dictionary"; |
case FZ_INDIRECT: return "reference"; |
} |
return "<unknown>"; |
} |
fz_obj * |
fz_new_array(int initialcap) |
{ |
fz_obj *obj; |
int i; |
obj = fz_malloc(sizeof(fz_obj)); |
obj->refs = 1; |
obj->kind = FZ_ARRAY; |
obj->u.a.len = 0; |
obj->u.a.cap = initialcap > 1 ? initialcap : 6; |
obj->u.a.items = fz_calloc(obj->u.a.cap, sizeof(fz_obj*)); |
for (i = 0; i < obj->u.a.cap; i++) |
obj->u.a.items[i] = NULL; |
return obj; |
} |
fz_obj * |
fz_copy_array(fz_obj *obj) |
{ |
fz_obj *new; |
int i; |
if (fz_is_indirect(obj) || !fz_is_array(obj)) |
fz_warn("assert: not an array (%s)", fz_objkindstr(obj)); |
new = fz_new_array(fz_array_len(obj)); |
for (i = 0; i < fz_array_len(obj); i++) |
fz_array_push(new, fz_array_get(obj, i)); |
return new; |
} |
int |
fz_array_len(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
if (!fz_is_array(obj)) |
return 0; |
return obj->u.a.len; |
} |
fz_obj * |
fz_array_get(fz_obj *obj, int i) |
{ |
obj = fz_resolve_indirect(obj); |
if (!fz_is_array(obj)) |
return NULL; |
if (i < 0 || i >= obj->u.a.len) |
return NULL; |
return obj->u.a.items[i]; |
} |
void |
fz_array_put(fz_obj *obj, int i, fz_obj *item) |
{ |
obj = fz_resolve_indirect(obj); |
if (!fz_is_array(obj)) |
fz_warn("assert: not an array (%s)", fz_objkindstr(obj)); |
else if (i < 0) |
fz_warn("assert: index %d < 0", i); |
else if (i >= obj->u.a.len) |
fz_warn("assert: index %d > length %d", i, obj->u.a.len); |
else |
{ |
if (obj->u.a.items[i]) |
fz_drop_obj(obj->u.a.items[i]); |
obj->u.a.items[i] = fz_keep_obj(item); |
} |
} |
void |
fz_array_push(fz_obj *obj, fz_obj *item) |
{ |
obj = fz_resolve_indirect(obj); |
if (!fz_is_array(obj)) |
fz_warn("assert: not an array (%s)", fz_objkindstr(obj)); |
else |
{ |
if (obj->u.a.len + 1 > obj->u.a.cap) |
{ |
int i; |
obj->u.a.cap = (obj->u.a.cap * 3) / 2; |
obj->u.a.items = fz_realloc(obj->u.a.items, obj->u.a.cap, sizeof(fz_obj*)); |
for (i = obj->u.a.len ; i < obj->u.a.cap; i++) |
obj->u.a.items[i] = NULL; |
} |
obj->u.a.items[obj->u.a.len] = fz_keep_obj(item); |
obj->u.a.len++; |
} |
} |
void |
fz_array_insert(fz_obj *obj, fz_obj *item) |
{ |
obj = fz_resolve_indirect(obj); |
if (!fz_is_array(obj)) |
fz_warn("assert: not an array (%s)", fz_objkindstr(obj)); |
else |
{ |
if (obj->u.a.len + 1 > obj->u.a.cap) |
{ |
int i; |
obj->u.a.cap = (obj->u.a.cap * 3) / 2; |
obj->u.a.items = fz_realloc(obj->u.a.items, obj->u.a.cap, sizeof(fz_obj*)); |
for (i = obj->u.a.len ; i < obj->u.a.cap; i++) |
obj->u.a.items[i] = NULL; |
} |
memmove(obj->u.a.items + 1, obj->u.a.items, obj->u.a.len * sizeof(fz_obj*)); |
obj->u.a.items[0] = fz_keep_obj(item); |
obj->u.a.len++; |
} |
} |
/* dicts may only have names as keys! */ |
static int keyvalcmp(const void *ap, const void *bp) |
{ |
const struct keyval *a = ap; |
const struct keyval *b = bp; |
return strcmp(fz_to_name(a->k), fz_to_name(b->k)); |
} |
fz_obj * |
fz_new_dict(int initialcap) |
{ |
fz_obj *obj; |
int i; |
obj = fz_malloc(sizeof(fz_obj)); |
obj->refs = 1; |
obj->kind = FZ_DICT; |
obj->u.d.sorted = 1; |
obj->u.d.len = 0; |
obj->u.d.cap = initialcap > 1 ? initialcap : 10; |
obj->u.d.items = fz_calloc(obj->u.d.cap, sizeof(struct keyval)); |
for (i = 0; i < obj->u.d.cap; i++) |
{ |
obj->u.d.items[i].k = NULL; |
obj->u.d.items[i].v = NULL; |
} |
return obj; |
} |
fz_obj * |
fz_copy_dict(fz_obj *obj) |
{ |
fz_obj *new; |
int i; |
if (fz_is_indirect(obj) || !fz_is_dict(obj)) |
fz_throw("assert: not a dict (%s)", fz_objkindstr(obj)); |
new = fz_new_dict(fz_dict_len(obj)); |
for (i = 0; i < fz_dict_len(obj); i++) |
fz_dict_put(new, fz_dict_get_key(obj, i), fz_dict_get_val(obj, i)); |
return new; |
} |
int |
fz_dict_len(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
if (!fz_is_dict(obj)) |
return 0; |
return obj->u.d.len; |
} |
fz_obj * |
fz_dict_get_key(fz_obj *obj, int i) |
{ |
obj = fz_resolve_indirect(obj); |
if (!fz_is_dict(obj)) |
return NULL; |
if (i < 0 || i >= obj->u.d.len) |
return NULL; |
return obj->u.d.items[i].k; |
} |
fz_obj * |
fz_dict_get_val(fz_obj *obj, int i) |
{ |
obj = fz_resolve_indirect(obj); |
if (!fz_is_dict(obj)) |
return NULL; |
if (i < 0 || i >= obj->u.d.len) |
return NULL; |
return obj->u.d.items[i].v; |
} |
static int |
fz_dict_finds(fz_obj *obj, char *key) |
{ |
if (obj->u.d.sorted) |
{ |
int l = 0; |
int r = obj->u.d.len - 1; |
while (l <= r) |
{ |
int m = (l + r) >> 1; |
int c = -strcmp(fz_to_name(obj->u.d.items[m].k), key); |
if (c < 0) |
r = m - 1; |
else if (c > 0) |
l = m + 1; |
else |
return m; |
} |
} |
else |
{ |
int i; |
for (i = 0; i < obj->u.d.len; i++) |
if (strcmp(fz_to_name(obj->u.d.items[i].k), key) == 0) |
return i; |
} |
return -1; |
} |
fz_obj * |
fz_dict_gets(fz_obj *obj, char *key) |
{ |
int i; |
obj = fz_resolve_indirect(obj); |
if (!fz_is_dict(obj)) |
return NULL; |
i = fz_dict_finds(obj, key); |
if (i >= 0) |
return obj->u.d.items[i].v; |
return NULL; |
} |
fz_obj * |
fz_dict_get(fz_obj *obj, fz_obj *key) |
{ |
if (fz_is_name(key)) |
return fz_dict_gets(obj, fz_to_name(key)); |
return NULL; |
} |
fz_obj * |
fz_dict_getsa(fz_obj *obj, char *key, char *abbrev) |
{ |
fz_obj *v; |
v = fz_dict_gets(obj, key); |
if (v) |
return v; |
return fz_dict_gets(obj, abbrev); |
} |
void |
fz_dict_put(fz_obj *obj, fz_obj *key, fz_obj *val) |
{ |
char *s; |
int i; |
obj = fz_resolve_indirect(obj); |
if (!fz_is_dict(obj)) |
{ |
fz_warn("assert: not a dict (%s)", fz_objkindstr(obj)); |
return; |
} |
if (fz_is_name(key)) |
s = fz_to_name(key); |
else |
{ |
fz_warn("assert: key is not a name (%s)", fz_objkindstr(obj)); |
return; |
} |
if (!val) |
{ |
fz_warn("assert: val does not exist for key (%s)", s); |
return; |
} |
i = fz_dict_finds(obj, s); |
if (i >= 0) |
{ |
fz_drop_obj(obj->u.d.items[i].v); |
obj->u.d.items[i].v = fz_keep_obj(val); |
return; |
} |
if (obj->u.d.len + 1 > obj->u.d.cap) |
{ |
obj->u.d.cap = (obj->u.d.cap * 3) / 2; |
obj->u.d.items = fz_realloc(obj->u.d.items, obj->u.d.cap, sizeof(struct keyval)); |
for (i = obj->u.d.len; i < obj->u.d.cap; i++) |
{ |
obj->u.d.items[i].k = NULL; |
obj->u.d.items[i].v = NULL; |
} |
} |
/* borked! */ |
if (obj->u.d.len) |
if (strcmp(fz_to_name(obj->u.d.items[obj->u.d.len - 1].k), s) > 0) |
obj->u.d.sorted = 0; |
obj->u.d.items[obj->u.d.len].k = fz_keep_obj(key); |
obj->u.d.items[obj->u.d.len].v = fz_keep_obj(val); |
obj->u.d.len ++; |
} |
void |
fz_dict_puts(fz_obj *obj, char *key, fz_obj *val) |
{ |
fz_obj *keyobj = fz_new_name(key); |
fz_dict_put(obj, keyobj, val); |
fz_drop_obj(keyobj); |
} |
void |
fz_dict_dels(fz_obj *obj, char *key) |
{ |
obj = fz_resolve_indirect(obj); |
if (!fz_is_dict(obj)) |
fz_warn("assert: not a dict (%s)", fz_objkindstr(obj)); |
else |
{ |
int i = fz_dict_finds(obj, key); |
if (i >= 0) |
{ |
fz_drop_obj(obj->u.d.items[i].k); |
fz_drop_obj(obj->u.d.items[i].v); |
obj->u.d.sorted = 0; |
obj->u.d.items[i] = obj->u.d.items[obj->u.d.len-1]; |
obj->u.d.len --; |
} |
} |
} |
void |
fz_dict_del(fz_obj *obj, fz_obj *key) |
{ |
if (fz_is_name(key)) |
fz_dict_dels(obj, fz_to_name(key)); |
else |
fz_warn("assert: key is not a name (%s)", fz_objkindstr(obj)); |
} |
void |
fz_sort_dict(fz_obj *obj) |
{ |
obj = fz_resolve_indirect(obj); |
if (!fz_is_dict(obj)) |
return; |
if (!obj->u.d.sorted) |
{ |
qsort(obj->u.d.items, obj->u.d.len, sizeof(struct keyval), keyvalcmp); |
obj->u.d.sorted = 1; |
} |
} |
static void |
fz_free_array(fz_obj *obj) |
{ |
int i; |
for (i = 0; i < obj->u.a.len; i++) |
if (obj->u.a.items[i]) |
fz_drop_obj(obj->u.a.items[i]); |
fz_free(obj->u.a.items); |
fz_free(obj); |
} |
static void |
fz_free_dict(fz_obj *obj) |
{ |
int i; |
for (i = 0; i < obj->u.d.len; i++) { |
if (obj->u.d.items[i].k) |
fz_drop_obj(obj->u.d.items[i].k); |
if (obj->u.d.items[i].v) |
fz_drop_obj(obj->u.d.items[i].v); |
} |
fz_free(obj->u.d.items); |
fz_free(obj); |
} |
void |
fz_drop_obj(fz_obj *obj) |
{ |
assert(obj != NULL); |
if (--obj->refs == 0) |
{ |
if (obj->kind == FZ_ARRAY) |
fz_free_array(obj); |
else if (obj->kind == FZ_DICT) |
fz_free_dict(obj); |
else |
fz_free(obj); |
} |
} |
/contrib/media/updf/fitz/base_string.c |
---|
0,0 → 1,265 |
#include "fitz.h" |
int |
fz_is_big_endian(void) |
{ |
static const int one = 1; |
return *(char*)&one == 0; |
} |
char * |
fz_strsep(char **stringp, const char *delim) |
{ |
char *ret = *stringp; |
if (ret == NULL) return NULL; |
if ((*stringp = strpbrk(*stringp, delim)) != NULL) |
*((*stringp)++) = '\0'; |
return ret; |
} |
int |
fz_strlcpy(char *dst, const char *src, int siz) |
{ |
register char *d = dst; |
register const char *s = src; |
register int n = siz; |
/* Copy as many bytes as will fit */ |
if (n != 0 && --n != 0) { |
do { |
if ((*d++ = *s++) == 0) |
break; |
} while (--n != 0); |
} |
/* Not enough room in dst, add NUL and traverse rest of src */ |
if (n == 0) { |
if (siz != 0) |
*d = '\0'; /* NUL-terminate dst */ |
while (*s++) |
; |
} |
return(s - src - 1); /* count does not include NUL */ |
} |
int |
fz_strlcat(char *dst, const char *src, int siz) |
{ |
register char *d = dst; |
register const char *s = src; |
register int n = siz; |
int dlen; |
/* Find the end of dst and adjust bytes left but don't go past end */ |
while (*d != '\0' && n-- != 0) |
d++; |
dlen = d - dst; |
n = siz - dlen; |
if (n == 0) |
return dlen + strlen(s); |
while (*s != '\0') { |
if (n != 1) { |
*d++ = *s; |
n--; |
} |
s++; |
} |
*d = '\0'; |
return dlen + (s - src); /* count does not include NUL */ |
} |
enum |
{ |
UTFmax = 4, /* maximum bytes per rune */ |
Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */ |
Runeself = 0x80, /* rune and UTF sequences are the same (<) */ |
Runeerror = 0xFFFD, /* decoding error in UTF */ |
Runemax = 0x10FFFF, /* maximum rune value */ |
}; |
enum |
{ |
Bit1 = 7, |
Bitx = 6, |
Bit2 = 5, |
Bit3 = 4, |
Bit4 = 3, |
Bit5 = 2, |
T1 = ((1<<(Bit1+1))-1) ^ 0xFF, /* 0000 0000 */ |
Tx = ((1<<(Bitx+1))-1) ^ 0xFF, /* 1000 0000 */ |
T2 = ((1<<(Bit2+1))-1) ^ 0xFF, /* 1100 0000 */ |
T3 = ((1<<(Bit3+1))-1) ^ 0xFF, /* 1110 0000 */ |
T4 = ((1<<(Bit4+1))-1) ^ 0xFF, /* 1111 0000 */ |
T5 = ((1<<(Bit5+1))-1) ^ 0xFF, /* 1111 1000 */ |
Rune1 = (1<<(Bit1+0*Bitx))-1, /* 0000 0000 0111 1111 */ |
Rune2 = (1<<(Bit2+1*Bitx))-1, /* 0000 0111 1111 1111 */ |
Rune3 = (1<<(Bit3+2*Bitx))-1, /* 1111 1111 1111 1111 */ |
Rune4 = (1<<(Bit4+3*Bitx))-1, /* 0001 1111 1111 1111 1111 1111 */ |
Maskx = (1<<Bitx)-1, /* 0011 1111 */ |
Testx = Maskx ^ 0xFF, /* 1100 0000 */ |
Bad = Runeerror, |
}; |
int |
chartorune(int *rune, char *str) |
{ |
int c, c1, c2, c3; |
long l; |
/* |
* one character sequence |
* 00000-0007F => T1 |
*/ |
c = *(unsigned char*)str; |
if(c < Tx) { |
*rune = c; |
return 1; |
} |
/* |
* two character sequence |
* 0080-07FF => T2 Tx |
*/ |
c1 = *(unsigned char*)(str+1) ^ Tx; |
if(c1 & Testx) |
goto bad; |
if(c < T3) { |
if(c < T2) |
goto bad; |
l = ((c << Bitx) | c1) & Rune2; |
if(l <= Rune1) |
goto bad; |
*rune = l; |
return 2; |
} |
/* |
* three character sequence |
* 0800-FFFF => T3 Tx Tx |
*/ |
c2 = *(unsigned char*)(str+2) ^ Tx; |
if(c2 & Testx) |
goto bad; |
if(c < T4) { |
l = ((((c << Bitx) | c1) << Bitx) | c2) & Rune3; |
if(l <= Rune2) |
goto bad; |
*rune = l; |
return 3; |
} |
/* |
* four character sequence (21-bit value) |
* 10000-1FFFFF => T4 Tx Tx Tx |
*/ |
c3 = *(unsigned char*)(str+3) ^ Tx; |
if (c3 & Testx) |
goto bad; |
if (c < T5) { |
l = ((((((c << Bitx) | c1) << Bitx) | c2) << Bitx) | c3) & Rune4; |
if (l <= Rune3) |
goto bad; |
*rune = l; |
return 4; |
} |
/* |
* Support for 5-byte or longer UTF-8 would go here, but |
* since we don't have that, we'll just fall through to bad. |
*/ |
/* |
* bad decoding |
*/ |
bad: |
*rune = Bad; |
return 1; |
} |
int |
runetochar(char *str, int *rune) |
{ |
/* Runes are signed, so convert to unsigned for range check. */ |
unsigned long c; |
/* |
* one character sequence |
* 00000-0007F => 00-7F |
*/ |
c = *rune; |
if(c <= Rune1) { |
str[0] = c; |
return 1; |
} |
/* |
* two character sequence |
* 0080-07FF => T2 Tx |
*/ |
if(c <= Rune2) { |
str[0] = T2 | (c >> 1*Bitx); |
str[1] = Tx | (c & Maskx); |
return 2; |
} |
/* |
* If the Rune is out of range, convert it to the error rune. |
* Do this test here because the error rune encodes to three bytes. |
* Doing it earlier would duplicate work, since an out of range |
* Rune wouldn't have fit in one or two bytes. |
*/ |
if (c > Runemax) |
c = Runeerror; |
/* |
* three character sequence |
* 0800-FFFF => T3 Tx Tx |
*/ |
if (c <= Rune3) { |
str[0] = T3 | (c >> 2*Bitx); |
str[1] = Tx | ((c >> 1*Bitx) & Maskx); |
str[2] = Tx | (c & Maskx); |
return 3; |
} |
/* |
* four character sequence (21-bit value) |
* 10000-1FFFFF => T4 Tx Tx Tx |
*/ |
str[0] = T4 | (c >> 3*Bitx); |
str[1] = Tx | ((c >> 2*Bitx) & Maskx); |
str[2] = Tx | ((c >> 1*Bitx) & Maskx); |
str[3] = Tx | (c & Maskx); |
return 4; |
} |
int |
runelen(int c) |
{ |
char str[10]; |
return runetochar(str, &c); |
} |
float fz_atof(const char *s) |
{ |
double d; |
/* The errno voodoo here checks for us reading numbers that are too |
* big to fit into a double. The checks for FLT_MAX ensure that we |
* don't read a number that's OK as a double and then become invalid |
* as we convert to a float. */ |
errno = 0; |
d = strtod(s, NULL); |
if (errno == ERANGE || d > FLT_MAX || d < -FLT_MAX) { |
/* Return 1.0, as it's a small known value that won't cause a |
* divide by 0. */ |
return 1.0; |
} |
return (float)d; |
} |
/contrib/media/updf/fitz/base_time.c |
---|
0,0 → 1,42 |
#ifdef _WIN32 |
#include <time.h> |
#include <winsock2.h> |
#include <windows.h> |
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) |
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 |
#else |
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL |
#endif |
struct timeval; |
int gettimeofday(struct timeval *tv, struct timezone *tz) |
{ |
FILETIME ft; |
unsigned __int64 tmpres = 0; |
if (tv) |
{ |
GetSystemTimeAsFileTime(&ft); |
tmpres |= ft.dwHighDateTime; |
tmpres <<= 32; |
tmpres |= ft.dwLowDateTime; |
tmpres /= 10; /*convert into microseconds*/ |
/*converting file time to unix epoch*/ |
tmpres -= DELTA_EPOCH_IN_MICROSECS; |
tv->tv_sec = (long)(tmpres / 1000000UL); |
tv->tv_usec = (long)(tmpres % 1000000UL); |
} |
return 0; |
} |
#else |
void fz_gettimeofday_dummy() { } |
#endif |
/contrib/media/updf/fitz/crypt_aes.c |
---|
0,0 → 1,565 |
/* |
* FIPS-197 compliant AES implementation |
* |
* Copyright (C) 2006-2007 Christophe Devine |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* * Redistributions of source code _must_ retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* * Redistributions in binary form may or may not reproduce the above |
* copyright notice, this list of conditions and the following |
* disclaimer in the documentation and/or other materials provided |
* with the distribution. |
* * Neither the name of XySSL nor the names of its contributors may be |
* used to endorse or promote products derived from this software |
* without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED |
* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
/* |
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen. |
* |
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf |
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf |
*/ |
#include "fitz.h" |
#define aes_context fz_aes |
/* AES block cipher implementation from XYSSL */ |
/* |
* 32-bit integer manipulation macros (little endian) |
*/ |
#ifndef GET_ULONG_LE |
#define GET_ULONG_LE(n,b,i) \ |
{ \ |
(n) = ( (unsigned long) (b)[(i)] ) \ |
| ( (unsigned long) (b)[(i) + 1] << 8 ) \ |
| ( (unsigned long) (b)[(i) + 2] << 16 ) \ |
| ( (unsigned long) (b)[(i) + 3] << 24 ); \ |
} |
#endif |
#ifndef PUT_ULONG_LE |
#define PUT_ULONG_LE(n,b,i) \ |
{ \ |
(b)[(i) ] = (unsigned char) ( (n) ); \ |
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ |
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ |
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ |
} |
#endif |
/* |
* Forward S-box & tables |
*/ |
static unsigned char FSb[256]; |
static unsigned long FT0[256]; |
static unsigned long FT1[256]; |
static unsigned long FT2[256]; |
static unsigned long FT3[256]; |
/* |
* Reverse S-box & tables |
*/ |
static unsigned char RSb[256]; |
static unsigned long RT0[256]; |
static unsigned long RT1[256]; |
static unsigned long RT2[256]; |
static unsigned long RT3[256]; |
/* |
* Round constants |
*/ |
static unsigned long RCON[10]; |
/* |
* Tables generation code |
*/ |
#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) |
#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) |
#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) |
static int aes_init_done = 0; |
static void aes_gen_tables( void ) |
{ |
int i, x, y, z; |
int pow[256]; |
int log[256]; |
/* |
* compute pow and log tables over GF(2^8) |
*/ |
for( i = 0, x = 1; i < 256; i++ ) |
{ |
pow[i] = x; |
log[x] = i; |
x = ( x ^ XTIME( x ) ) & 0xFF; |
} |
/* |
* calculate the round constants |
*/ |
for( i = 0, x = 1; i < 10; i++ ) |
{ |
RCON[i] = (unsigned long) x; |
x = XTIME( x ) & 0xFF; |
} |
/* |
* generate the forward and reverse S-boxes |
*/ |
FSb[0x00] = 0x63; |
RSb[0x63] = 0x00; |
for( i = 1; i < 256; i++ ) |
{ |
x = pow[255 - log[i]]; |
y = x; y = ( (y << 1) | (y >> 7) ) & 0xFF; |
x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; |
x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; |
x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; |
x ^= y ^ 0x63; |
FSb[i] = (unsigned char) x; |
RSb[x] = (unsigned char) i; |
} |
/* |
* generate the forward and reverse tables |
*/ |
for( i = 0; i < 256; i++ ) |
{ |
x = FSb[i]; |
y = XTIME( x ) & 0xFF; |
z = ( y ^ x ) & 0xFF; |
FT0[i] = ( (unsigned long) y ) ^ |
( (unsigned long) x << 8 ) ^ |
( (unsigned long) x << 16 ) ^ |
( (unsigned long) z << 24 ); |
FT1[i] = ROTL8( FT0[i] ); |
FT2[i] = ROTL8( FT1[i] ); |
FT3[i] = ROTL8( FT2[i] ); |
x = RSb[i]; |
RT0[i] = ( (unsigned long) MUL( 0x0E, x ) ) ^ |
( (unsigned long) MUL( 0x09, x ) << 8 ) ^ |
( (unsigned long) MUL( 0x0D, x ) << 16 ) ^ |
( (unsigned long) MUL( 0x0B, x ) << 24 ); |
RT1[i] = ROTL8( RT0[i] ); |
RT2[i] = ROTL8( RT1[i] ); |
RT3[i] = ROTL8( RT2[i] ); |
} |
} |
/* |
* AES key schedule (encryption) |
*/ |
void aes_setkey_enc( aes_context *ctx, const unsigned char *key, int keysize ) |
{ |
int i; |
unsigned long *RK; |
#if !defined(XYSSL_AES_ROM_TABLES) |
if( aes_init_done == 0 ) |
{ |
aes_gen_tables(); |
aes_init_done = 1; |
} |
#endif |
switch( keysize ) |
{ |
case 128: ctx->nr = 10; break; |
case 192: ctx->nr = 12; break; |
case 256: ctx->nr = 14; break; |
default : return; |
} |
#if defined(PADLOCK_ALIGN16) |
ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); |
#else |
ctx->rk = RK = ctx->buf; |
#endif |
for( i = 0; i < (keysize >> 5); i++ ) |
{ |
GET_ULONG_LE( RK[i], key, i << 2 ); |
} |
switch( ctx->nr ) |
{ |
case 10: |
for( i = 0; i < 10; i++, RK += 4 ) |
{ |
RK[4] = RK[0] ^ RCON[i] ^ |
( FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ |
( FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ |
( FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ |
( FSb[ ( RK[3] ) & 0xFF ] << 24 ); |
RK[5] = RK[1] ^ RK[4]; |
RK[6] = RK[2] ^ RK[5]; |
RK[7] = RK[3] ^ RK[6]; |
} |
break; |
case 12: |
for( i = 0; i < 8; i++, RK += 6 ) |
{ |
RK[6] = RK[0] ^ RCON[i] ^ |
( FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ |
( FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ |
( FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ |
( FSb[ ( RK[5] ) & 0xFF ] << 24 ); |
RK[7] = RK[1] ^ RK[6]; |
RK[8] = RK[2] ^ RK[7]; |
RK[9] = RK[3] ^ RK[8]; |
RK[10] = RK[4] ^ RK[9]; |
RK[11] = RK[5] ^ RK[10]; |
} |
break; |
case 14: |
for( i = 0; i < 7; i++, RK += 8 ) |
{ |
RK[8] = RK[0] ^ RCON[i] ^ |
( FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ |
( FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ |
( FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ |
( FSb[ ( RK[7] ) & 0xFF ] << 24 ); |
RK[9] = RK[1] ^ RK[8]; |
RK[10] = RK[2] ^ RK[9]; |
RK[11] = RK[3] ^ RK[10]; |
RK[12] = RK[4] ^ |
( FSb[ ( RK[11] ) & 0xFF ] ) ^ |
( FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ |
( FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ |
( FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); |
RK[13] = RK[5] ^ RK[12]; |
RK[14] = RK[6] ^ RK[13]; |
RK[15] = RK[7] ^ RK[14]; |
} |
break; |
default: |
break; |
} |
} |
/* |
* AES key schedule (decryption) |
*/ |
void aes_setkey_dec( aes_context *ctx, const unsigned char *key, int keysize ) |
{ |
int i, j; |
aes_context cty; |
unsigned long *RK; |
unsigned long *SK; |
switch( keysize ) |
{ |
case 128: ctx->nr = 10; break; |
case 192: ctx->nr = 12; break; |
case 256: ctx->nr = 14; break; |
default : return; |
} |
#if defined(PADLOCK_ALIGN16) |
ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); |
#else |
ctx->rk = RK = ctx->buf; |
#endif |
aes_setkey_enc( &cty, key, keysize ); |
SK = cty.rk + cty.nr * 4; |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) |
{ |
for( j = 0; j < 4; j++, SK++ ) |
{ |
*RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ |
RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ |
RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ |
RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; |
} |
} |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
*RK++ = *SK++; |
memset( &cty, 0, sizeof( aes_context ) ); |
} |
#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ |
{ \ |
X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ |
FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ |
FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ |
FT3[ ( Y3 >> 24 ) & 0xFF ]; \ |
\ |
X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ |
FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ |
FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ |
FT3[ ( Y0 >> 24 ) & 0xFF ]; \ |
\ |
X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ |
FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ |
FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ |
FT3[ ( Y1 >> 24 ) & 0xFF ]; \ |
\ |
X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ |
FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ |
FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ |
FT3[ ( Y2 >> 24 ) & 0xFF ]; \ |
} |
#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ |
{ \ |
X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ |
RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ |
RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ |
RT3[ ( Y1 >> 24 ) & 0xFF ]; \ |
\ |
X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ |
RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ |
RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ |
RT3[ ( Y2 >> 24 ) & 0xFF ]; \ |
\ |
X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ |
RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ |
RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ |
RT3[ ( Y3 >> 24 ) & 0xFF ]; \ |
\ |
X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ |
RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ |
RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ |
RT3[ ( Y0 >> 24 ) & 0xFF ]; \ |
} |
/* |
* AES-ECB block encryption/decryption |
*/ |
void aes_crypt_ecb( aes_context *ctx, |
int mode, |
const unsigned char input[16], |
unsigned char output[16] ) |
{ |
int i; |
unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; |
#if defined(XYSSL_PADLOCK_C) && defined(XYSSL_HAVE_X86) |
if( padlock_supports( PADLOCK_ACE ) ) |
{ |
if( padlock_xcryptecb( ctx, mode, input, output ) == 0 ) |
return; |
} |
#endif |
RK = ctx->rk; |
GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++; |
GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++; |
GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++; |
GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++; |
if( mode == AES_DECRYPT ) |
{ |
for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) |
{ |
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); |
AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); |
} |
AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); |
X0 = *RK++ ^ ( RSb[ ( Y0 ) & 0xFF ] ) ^ |
( RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ |
( RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ |
( RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); |
X1 = *RK++ ^ ( RSb[ ( Y1 ) & 0xFF ] ) ^ |
( RSb[ ( Y0 >>8 ) & 0xFF ] << 8 ) ^ |
( RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ |
( RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); |
X2 = *RK++ ^ ( RSb[ ( Y2 ) & 0xFF ] ) ^ |
( RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ |
( RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ |
( RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); |
X3 = *RK++ ^ ( RSb[ ( Y3 ) & 0xFF ] ) ^ |
( RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ |
( RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ |
( RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); |
} |
else /* AES_ENCRYPT */ |
{ |
for( i = (ctx->nr >> 1) - 1; i > 0; i-- ) |
{ |
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); |
AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); |
} |
AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); |
X0 = *RK++ ^ ( FSb[ ( Y0 ) & 0xFF ] ) ^ |
( FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ |
( FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ |
( FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); |
X1 = *RK++ ^ ( FSb[ ( Y1 ) & 0xFF ] ) ^ |
( FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ |
( FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ |
( FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); |
X2 = *RK++ ^ ( FSb[ ( Y2 ) & 0xFF ] ) ^ |
( FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ |
( FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ |
( FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); |
X3 = *RK++ ^ ( FSb[ ( Y3 ) & 0xFF ] ) ^ |
( FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ |
( FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ |
( FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); |
} |
PUT_ULONG_LE( X0, output, 0 ); |
PUT_ULONG_LE( X1, output, 4 ); |
PUT_ULONG_LE( X2, output, 8 ); |
PUT_ULONG_LE( X3, output, 12 ); |
} |
/* |
* AES-CBC buffer encryption/decryption |
*/ |
void aes_crypt_cbc( aes_context *ctx, |
int mode, |
int length, |
unsigned char iv[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int i; |
unsigned char temp[16]; |
#if defined(XYSSL_PADLOCK_C) && defined(XYSSL_HAVE_X86) |
if( padlock_supports( PADLOCK_ACE ) ) |
{ |
if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) |
return; |
} |
#endif |
if( mode == AES_DECRYPT ) |
{ |
while( length > 0 ) |
{ |
memcpy( temp, input, 16 ); |
aes_crypt_ecb( ctx, mode, input, output ); |
for( i = 0; i < 16; i++ ) |
output[i] = (unsigned char)( output[i] ^ iv[i] ); |
memcpy( iv, temp, 16 ); |
input += 16; |
output += 16; |
length -= 16; |
} |
} |
else |
{ |
while( length > 0 ) |
{ |
for( i = 0; i < 16; i++ ) |
output[i] = (unsigned char)( input[i] ^ iv[i] ); |
aes_crypt_ecb( ctx, mode, output, output ); |
memcpy( iv, output, 16 ); |
input += 16; |
output += 16; |
length -= 16; |
} |
} |
} |
/* |
* AES-CFB buffer encryption/decryption |
*/ |
void aes_crypt_cfb( aes_context *ctx, |
int mode, |
int length, |
int *iv_off, |
unsigned char iv[16], |
const unsigned char *input, |
unsigned char *output ) |
{ |
int c, n = *iv_off; |
if( mode == AES_DECRYPT ) |
{ |
while( length-- ) |
{ |
if( n == 0 ) |
aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); |
c = *input++; |
*output++ = (unsigned char)( c ^ iv[n] ); |
iv[n] = (unsigned char) c; |
n = (n + 1) & 0x0F; |
} |
} |
else |
{ |
while( length-- ) |
{ |
if( n == 0 ) |
aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); |
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); |
n = (n + 1) & 0x0F; |
} |
} |
*iv_off = n; |
} |
/contrib/media/updf/fitz/crypt_arc4.c |
---|
0,0 → 1,98 |
/* This code illustrates a sample implementation |
* of the Arcfour algorithm |
* Copyright (c) April 29, 1997 Kalle Kaukonen. |
* All Rights Reserved. |
* |
* Redistribution and use in source and binary forms, with or |
* without modification, are permitted provided that this copyright |
* notice and disclaimer are retained. |
* |
* THIS SOFTWARE IS PROVIDED BY KALLE KAUKONEN AND CONTRIBUTORS ``AS |
* IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KALLE |
* KAUKONEN OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include "fitz.h" |
void |
fz_arc4_init(fz_arc4 *arc4, const unsigned char *key, const unsigned keylen) |
{ |
unsigned int t, u; |
unsigned int keyindex; |
unsigned int stateindex; |
unsigned char *state; |
unsigned int counter; |
state = arc4->state; |
arc4->x = 0; |
arc4->y = 0; |
for (counter = 0; counter < 256; counter++) |
{ |
state[counter] = counter; |
} |
keyindex = 0; |
stateindex = 0; |
for (counter = 0; counter < 256; counter++) |
{ |
t = state[counter]; |
stateindex = (stateindex + key[keyindex] + t) & 0xff; |
u = state[stateindex]; |
state[stateindex] = t; |
state[counter] = u; |
if (++keyindex >= keylen) |
{ |
keyindex = 0; |
} |
} |
} |
static unsigned char |
fz_arc4_next(fz_arc4 *arc4) |
{ |
unsigned int x; |
unsigned int y; |
unsigned int sx, sy; |
unsigned char *state; |
state = arc4->state; |
x = (arc4->x + 1) & 0xff; |
sx = state[x]; |
y = (sx + arc4->y) & 0xff; |
sy = state[y]; |
arc4->x = x; |
arc4->y = y; |
state[y] = sx; |
state[x] = sy; |
return state[(sx + sy) & 0xff]; |
} |
void |
fz_arc4_encrypt(fz_arc4 *arc4, unsigned char *dest, const unsigned char *src, const unsigned len) |
{ |
unsigned int i; |
for (i = 0; i < len; i++) |
{ |
unsigned char x; |
x = fz_arc4_next(arc4); |
dest[i] = src[i] ^ x; |
} |
} |
/contrib/media/updf/fitz/crypt_md5.c |
---|
0,0 → 1,272 |
/* |
MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm |
Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. |
All rights reserved. |
License to copy and use this software is granted provided that it |
is identified as the "RSA Data Security, Inc. MD5 Message-Digest |
Algorithm" in all material mentioning or referencing this software |
or this function. |
License is also granted to make and use derivative works provided |
that such works are identified as "derived from the RSA Data |
Security, Inc. MD5 Message-Digest Algorithm" in all material |
mentioning or referencing the derived work. |
RSA Data Security, Inc. makes no representations concerning either |
the merchantability of this software or the suitability of this |
software for any particular purpose. It is provided "as is" |
without express or implied warranty of any kind. |
These notices must be retained in any copies of any part of this |
documentation and/or software. |
*/ |
#include "fitz.h" |
/* Constants for MD5Transform routine */ |
enum |
{ |
S11 = 7, S12 = 12, S13 = 17, S14 = 22, |
S21 = 5, S22 = 9, S23 = 14, S24 = 20, |
S31 = 4, S32 = 11, S33 = 16, S34 = 23, |
S41 = 6, S42 = 10, S43 = 15, S44 = 21 |
}; |
static void encode(unsigned char *, const unsigned int *, const unsigned); |
static void decode(unsigned int *, const unsigned char *, const unsigned); |
static void transform(unsigned int state[4], const unsigned char block[64]); |
static unsigned char padding[64] = |
{ |
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 |
}; |
/* F, G, H and I are basic MD5 functions */ |
#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) |
#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) |
#define H(x, y, z) ((x) ^ (y) ^ (z)) |
#define I(x, y, z) ((y) ^ ((x) | (~z))) |
/* ROTATE rotates x left n bits */ |
#define ROTATE(x, n) (((x) << (n)) | ((x) >> (32-(n)))) |
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. |
* Rotation is separate from addition to prevent recomputation. |
*/ |
#define FF(a, b, c, d, x, s, ac) { \ |
(a) += F ((b), (c), (d)) + (x) + (unsigned int)(ac); \ |
(a) = ROTATE ((a), (s)); \ |
(a) += (b); \ |
} |
#define GG(a, b, c, d, x, s, ac) { \ |
(a) += G ((b), (c), (d)) + (x) + (unsigned int)(ac); \ |
(a) = ROTATE ((a), (s)); \ |
(a) += (b); \ |
} |
#define HH(a, b, c, d, x, s, ac) { \ |
(a) += H ((b), (c), (d)) + (x) + (unsigned int)(ac); \ |
(a) = ROTATE ((a), (s)); \ |
(a) += (b); \ |
} |
#define II(a, b, c, d, x, s, ac) { \ |
(a) += I ((b), (c), (d)) + (x) + (unsigned int)(ac); \ |
(a) = ROTATE ((a), (s)); \ |
(a) += (b); \ |
} |
static void encode(unsigned char *output, const unsigned int *input, const unsigned len) |
{ |
unsigned i, j; |
for (i = 0, j = 0; j < len; i++, j += 4) |
{ |
output[j] = (unsigned char)(input[i] & 0xff); |
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff); |
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff); |
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff); |
} |
} |
static void decode(unsigned int *output, const unsigned char *input, const unsigned len) |
{ |
unsigned i, j; |
for (i = 0, j = 0; j < len; i++, j += 4) |
{ |
output[i] = ((unsigned int)input[j]) | |
(((unsigned int)input[j+1]) << 8) | |
(((unsigned int)input[j+2]) << 16) | |
(((unsigned int)input[j+3]) << 24); |
} |
} |
static void transform(unsigned int state[4], const unsigned char block[64]) |
{ |
unsigned int a = state[0]; |
unsigned int b = state[1]; |
unsigned int c = state[2]; |
unsigned int d = state[3]; |
unsigned int x[16]; |
decode(x, block, 64); |
/* Round 1 */ |
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ |
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ |
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ |
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ |
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ |
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ |
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ |
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ |
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ |
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ |
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ |
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ |
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ |
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ |
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ |
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ |
/* Round 2 */ |
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ |
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ |
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ |
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ |
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ |
GG (d, a, b, c, x[10], S22, 0x02441453); /* 22 */ |
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ |
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ |
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ |
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ |
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ |
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ |
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ |
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ |
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ |
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ |
/* Round 3 */ |
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ |
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ |
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ |
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ |
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ |
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ |
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ |
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ |
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ |
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ |
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ |
HH (b, c, d, a, x[ 6], S34, 0x04881d05); /* 44 */ |
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ |
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ |
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ |
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ |
/* Round 4 */ |
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ |
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ |
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ |
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ |
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ |
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ |
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ |
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ |
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ |
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ |
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ |
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ |
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ |
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ |
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ |
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ |
state[0] += a; |
state[1] += b; |
state[2] += c; |
state[3] += d; |
/* Zeroize sensitive information */ |
memset(x, 0, sizeof (x)); |
} |
/* MD5 initialization. Begins an MD5 operation, writing a new context. */ |
void fz_md5_init(fz_md5 *context) |
{ |
context->count[0] = context->count[1] = 0; |
/* Load magic initialization constants */ |
context->state[0] = 0x67452301; |
context->state[1] = 0xefcdab89; |
context->state[2] = 0x98badcfe; |
context->state[3] = 0x10325476; |
} |
/* MD5 block update operation. Continues an MD5 message-digest operation, |
* processing another message block, and updating the context. |
*/ |
void fz_md5_update(fz_md5 *context, const unsigned char *input, const unsigned inlen) |
{ |
unsigned i, index, partlen; |
/* Compute number of bytes mod 64 */ |
index = (unsigned)((context->count[0] >> 3) & 0x3F); |
/* Update number of bits */ |
context->count[0] += (unsigned int) inlen << 3; |
if (context->count[0] < (unsigned int) inlen << 3) |
context->count[1] ++; |
context->count[1] += (unsigned int) inlen >> 29; |
partlen = 64 - index; |
/* Transform as many times as possible. */ |
if (inlen >= partlen) |
{ |
memcpy(context->buffer + index, input, partlen); |
transform(context->state, context->buffer); |
for (i = partlen; i + 63 < inlen; i += 64) |
transform(context->state, input + i); |
index = 0; |
} |
else |
{ |
i = 0; |
} |
/* Buffer remaining input */ |
memcpy(context->buffer + index, input + i, inlen - i); |
} |
/* MD5 finalization. Ends an MD5 message-digest operation, writing the |
* the message digest and zeroizing the context. |
*/ |
void fz_md5_final(fz_md5 *context, unsigned char digest[16]) |
{ |
unsigned char bits[8]; |
unsigned index, padlen; |
/* Save number of bits */ |
encode(bits, context->count, 8); |
/* Pad out to 56 mod 64 */ |
index = (unsigned)((context->count[0] >> 3) & 0x3f); |
padlen = index < 56 ? 56 - index : 120 - index; |
fz_md5_update(context, padding, padlen); |
/* Append length (before padding) */ |
fz_md5_update(context, bits, 8); |
/* Store state in digest */ |
encode(digest, context->state, 16); |
/* Zeroize sensitive information */ |
memset(context, 0, sizeof(fz_md5)); |
} |
/contrib/media/updf/fitz/crypt_sha2.c |
---|
0,0 → 1,182 |
/* |
This code is based on the code found from 7-Zip, which has a modified |
version of the SHA-256 found from Crypto++ <http://www.cryptopp.com/>. |
The code was modified a little to fit into liblzma and fitz. |
This file has been put into the public domain. |
You can do whatever you want with this file. |
*/ |
#include "fitz.h" |
static inline int isbigendian(void) |
{ |
static const int one = 1; |
return *(char*)&one == 0; |
} |
static inline unsigned int bswap32(unsigned int num) |
{ |
if (!isbigendian()) |
{ |
return ( (((num) << 24)) |
| (((num) << 8) & 0x00FF0000) |
| (((num) >> 8) & 0x0000FF00) |
| (((num) >> 24)) ); |
} |
return num; |
} |
/* At least on x86, GCC is able to optimize this to a rotate instruction. */ |
#define rotr_32(num, amount) ((num) >> (amount) | (num) << (32 - (amount))) |
#define blk0(i) (W[i] = data[i]) |
#define blk2(i) (W[i & 15] += s1(W[(i - 2) & 15]) + W[(i - 7) & 15] \ |
+ s0(W[(i - 15) & 15])) |
#define Ch(x, y, z) (z ^ (x & (y ^ z))) |
#define Maj(x, y, z) ((x & y) | (z & (x | y))) |
#define a(i) T[(0 - i) & 7] |
#define b(i) T[(1 - i) & 7] |
#define c(i) T[(2 - i) & 7] |
#define d(i) T[(3 - i) & 7] |
#define e(i) T[(4 - i) & 7] |
#define f(i) T[(5 - i) & 7] |
#define g(i) T[(6 - i) & 7] |
#define h(i) T[(7 - i) & 7] |
#define R(i) \ |
h(i) += S1(e(i)) + Ch(e(i), f(i), g(i)) + SHA256_K[i + j] \ |
+ (j ? blk2(i) : blk0(i)); \ |
d(i) += h(i); \ |
h(i) += S0(a(i)) + Maj(a(i), b(i), c(i)) |
#define S0(x) (rotr_32(x, 2) ^ rotr_32(x, 13) ^ rotr_32(x, 22)) |
#define S1(x) (rotr_32(x, 6) ^ rotr_32(x, 11) ^ rotr_32(x, 25)) |
#define s0(x) (rotr_32(x, 7) ^ rotr_32(x, 18) ^ (x >> 3)) |
#define s1(x) (rotr_32(x, 17) ^ rotr_32(x, 19) ^ (x >> 10)) |
static const unsigned int SHA256_K[64] = { |
0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, |
0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, |
0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, |
0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, |
0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, |
0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, |
0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, |
0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, |
0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, |
0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, |
0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, |
0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, |
0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, |
0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, |
0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, |
0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, |
}; |
static void |
transform(unsigned int state[8], const unsigned int data_xe[16]) |
{ |
unsigned int data[16]; |
unsigned int W[16]; |
unsigned int T[8]; |
unsigned int j; |
/* ensure big-endian integers */ |
for (j = 0; j < 16; j++) |
data[j] = bswap32(data_xe[j]); |
/* Copy state[] to working vars. */ |
memcpy(T, state, sizeof(T)); |
/* 64 operations, partially loop unrolled */ |
for (j = 0; j < 64; j += 16) { |
R( 0); R( 1); R( 2); R( 3); |
R( 4); R( 5); R( 6); R( 7); |
R( 8); R( 9); R(10); R(11); |
R(12); R(13); R(14); R(15); |
} |
/* Add the working vars back into state[]. */ |
state[0] += a(0); |
state[1] += b(0); |
state[2] += c(0); |
state[3] += d(0); |
state[4] += e(0); |
state[5] += f(0); |
state[6] += g(0); |
state[7] += h(0); |
} |
void fz_sha256_init(fz_sha256 *context) |
{ |
context->count[0] = context->count[1] = 0; |
context->state[0] = 0x6A09E667; |
context->state[1] = 0xBB67AE85; |
context->state[2] = 0x3C6EF372; |
context->state[3] = 0xA54FF53A; |
context->state[4] = 0x510E527F; |
context->state[5] = 0x9B05688C; |
context->state[6] = 0x1F83D9AB; |
context->state[7] = 0x5BE0CD19; |
} |
void fz_sha256_update(fz_sha256 *context, const unsigned char *input, unsigned int inlen) |
{ |
/* Copy the input data into a properly aligned temporary buffer. |
* This way we can be called with arbitrarily sized buffers |
* (no need to be multiple of 64 bytes), and the code works also |
* on architectures that don't allow unaligned memory access. */ |
while (inlen > 0) |
{ |
const unsigned int copy_start = context->count[0] & 0x3F; |
unsigned int copy_size = 64 - copy_start; |
if (copy_size > inlen) |
copy_size = inlen; |
memcpy(context->buffer.u8 + copy_start, input, copy_size); |
input += copy_size; |
inlen -= copy_size; |
context->count[0] += copy_size; |
/* carry overflow from low to high */ |
if (context->count[0] < copy_size) |
context->count[1]++; |
if ((context->count[0] & 0x3F) == 0) |
transform(context->state, context->buffer.u32); |
} |
} |
void fz_sha256_final(fz_sha256 *context, unsigned char digest[32]) |
{ |
/* Add padding as described in RFC 3174 (it describes SHA-1 but |
* the same padding style is used for SHA-256 too). */ |
unsigned int j = context->count[0] & 0x3F; |
context->buffer.u8[j++] = 0x80; |
while (j != 56) |
{ |
if (j == 64) |
{ |
transform(context->state, context->buffer.u32); |
j = 0; |
} |
context->buffer.u8[j++] = 0x00; |
} |
/* Convert the message size from bytes to bits. */ |
context->count[1] = (context->count[1] << 3) + (context->count[0] >> 29); |
context->count[0] = context->count[0] << 3; |
context->buffer.u32[14] = bswap32(context->count[1]); |
context->buffer.u32[15] = bswap32(context->count[0]); |
transform(context->state, context->buffer.u32); |
for (j = 0; j < 8; j++) |
((unsigned int *)digest)[j] = bswap32(context->state[j]); |
memset(context, 0, sizeof(fz_sha256)); |
} |
/contrib/media/updf/fitz/dev_bbox.c |
---|
0,0 → 1,82 |
#include "fitz.h" |
/* TODO: add clip stack and use to intersect bboxes */ |
static void |
fz_bbox_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_bbox *result = user; |
fz_bbox bbox = fz_round_rect(fz_bound_path(path, NULL, ctm)); |
*result = fz_union_bbox(*result, bbox); |
} |
static void |
fz_bbox_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_bbox *result = user; |
fz_bbox bbox = fz_round_rect(fz_bound_path(path, stroke, ctm)); |
*result = fz_union_bbox(*result, bbox); |
} |
static void |
fz_bbox_fill_text(void *user, fz_text *text, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_bbox *result = user; |
fz_bbox bbox = fz_round_rect(fz_bound_text(text, ctm)); |
*result = fz_union_bbox(*result, bbox); |
} |
static void |
fz_bbox_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_bbox *result = user; |
fz_bbox bbox = fz_round_rect(fz_bound_text(text, ctm)); |
*result = fz_union_bbox(*result, bbox); |
} |
static void |
fz_bbox_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) |
{ |
fz_bbox *result = user; |
fz_bbox bbox = fz_round_rect(fz_bound_shade(shade, ctm)); |
*result = fz_union_bbox(*result, bbox); |
} |
static void |
fz_bbox_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) |
{ |
fz_bbox *result = user; |
fz_bbox bbox = fz_round_rect(fz_transform_rect(ctm, fz_unit_rect)); |
*result = fz_union_bbox(*result, bbox); |
} |
static void |
fz_bbox_fill_image_mask(void *user, fz_pixmap *image, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_bbox_fill_image(user, image, ctm, alpha); |
} |
fz_device * |
fz_new_bbox_device(fz_bbox *result) |
{ |
fz_device *dev; |
dev = fz_new_device(result); |
dev->fill_path = fz_bbox_fill_path; |
dev->stroke_path = fz_bbox_stroke_path; |
dev->fill_text = fz_bbox_fill_text; |
dev->stroke_text = fz_bbox_stroke_text; |
dev->fill_shade = fz_bbox_fill_shade; |
dev->fill_image = fz_bbox_fill_image; |
dev->fill_image_mask = fz_bbox_fill_image_mask; |
*result = fz_empty_bbox; |
return dev; |
} |
/contrib/media/updf/fitz/dev_list.c |
---|
0,0 → 1,660 |
#include "fitz.h" |
typedef struct fz_display_node_s fz_display_node; |
#define STACK_SIZE 96 |
typedef enum fz_display_command_e |
{ |
FZ_CMD_FILL_PATH, |
FZ_CMD_STROKE_PATH, |
FZ_CMD_CLIP_PATH, |
FZ_CMD_CLIP_STROKE_PATH, |
FZ_CMD_FILL_TEXT, |
FZ_CMD_STROKE_TEXT, |
FZ_CMD_CLIP_TEXT, |
FZ_CMD_CLIP_STROKE_TEXT, |
FZ_CMD_IGNORE_TEXT, |
FZ_CMD_FILL_SHADE, |
FZ_CMD_FILL_IMAGE, |
FZ_CMD_FILL_IMAGE_MASK, |
FZ_CMD_CLIP_IMAGE_MASK, |
FZ_CMD_POP_CLIP, |
FZ_CMD_BEGIN_MASK, |
FZ_CMD_END_MASK, |
FZ_CMD_BEGIN_GROUP, |
FZ_CMD_END_GROUP, |
FZ_CMD_BEGIN_TILE, |
FZ_CMD_END_TILE |
} fz_display_command; |
struct fz_display_node_s |
{ |
fz_display_command cmd; |
fz_display_node *next; |
fz_rect rect; |
union { |
fz_path *path; |
fz_text *text; |
fz_shade *shade; |
fz_pixmap *image; |
int blendmode; |
} item; |
fz_stroke_state *stroke; |
int flag; /* even_odd, accumulate, isolated/knockout... */ |
fz_matrix ctm; |
fz_colorspace *colorspace; |
float alpha; |
float color[FZ_MAX_COLORS]; |
}; |
struct fz_display_list_s |
{ |
fz_display_node *first; |
fz_display_node *last; |
int top; |
struct { |
fz_rect *update; |
fz_rect rect; |
} stack[STACK_SIZE]; |
int tiled; |
}; |
enum { ISOLATED = 1, KNOCKOUT = 2 }; |
static fz_display_node * |
fz_new_display_node(fz_display_command cmd, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_display_node *node; |
int i; |
node = fz_malloc(sizeof(fz_display_node)); |
node->cmd = cmd; |
node->next = NULL; |
node->rect = fz_empty_rect; |
node->item.path = NULL; |
node->stroke = NULL; |
node->flag = 0; |
node->ctm = ctm; |
if (colorspace) |
{ |
node->colorspace = fz_keep_colorspace(colorspace); |
if (color) |
{ |
for (i = 0; i < node->colorspace->n; i++) |
node->color[i] = color[i]; |
} |
} |
else |
{ |
node->colorspace = NULL; |
} |
node->alpha = alpha; |
return node; |
} |
static fz_stroke_state * |
fz_clone_stroke_state(fz_stroke_state *stroke) |
{ |
fz_stroke_state *newstroke = fz_malloc(sizeof(fz_stroke_state)); |
*newstroke = *stroke; |
return newstroke; |
} |
static void |
fz_append_display_node(fz_display_list *list, fz_display_node *node) |
{ |
switch (node->cmd) |
{ |
case FZ_CMD_CLIP_PATH: |
case FZ_CMD_CLIP_STROKE_PATH: |
case FZ_CMD_CLIP_IMAGE_MASK: |
if (list->top < STACK_SIZE) |
{ |
list->stack[list->top].update = &node->rect; |
list->stack[list->top].rect = fz_empty_rect; |
} |
list->top++; |
break; |
case FZ_CMD_END_MASK: |
case FZ_CMD_CLIP_TEXT: |
case FZ_CMD_CLIP_STROKE_TEXT: |
if (list->top < STACK_SIZE) |
{ |
list->stack[list->top].update = NULL; |
list->stack[list->top].rect = fz_empty_rect; |
} |
list->top++; |
break; |
case FZ_CMD_BEGIN_TILE: |
list->tiled++; |
if (list->top > 0 && list->top < STACK_SIZE) |
{ |
list->stack[list->top-1].rect = fz_infinite_rect; |
} |
break; |
case FZ_CMD_END_TILE: |
list->tiled--; |
break; |
case FZ_CMD_END_GROUP: |
break; |
case FZ_CMD_POP_CLIP: |
if (list->top > STACK_SIZE) |
{ |
list->top--; |
node->rect = fz_infinite_rect; |
} |
else if (list->top > 0) |
{ |
fz_rect *update; |
list->top--; |
update = list->stack[list->top].update; |
if (list->tiled == 0) |
{ |
if (update != NULL) |
{ |
*update = fz_intersect_rect(*update, list->stack[list->top].rect); |
node->rect = *update; |
} |
else |
node->rect = list->stack[list->top].rect; |
} |
else |
node->rect = fz_infinite_rect; |
} |
/* fallthrough */ |
default: |
if (list->top > 0 && list->tiled == 0 && list->top <= STACK_SIZE) |
list->stack[list->top-1].rect = fz_union_rect(list->stack[list->top-1].rect, node->rect); |
break; |
} |
if (!list->first) |
{ |
list->first = node; |
list->last = node; |
} |
else |
{ |
list->last->next = node; |
list->last = node; |
} |
} |
static void |
fz_free_display_node(fz_display_node *node) |
{ |
switch (node->cmd) |
{ |
case FZ_CMD_FILL_PATH: |
case FZ_CMD_STROKE_PATH: |
case FZ_CMD_CLIP_PATH: |
case FZ_CMD_CLIP_STROKE_PATH: |
fz_free_path(node->item.path); |
break; |
case FZ_CMD_FILL_TEXT: |
case FZ_CMD_STROKE_TEXT: |
case FZ_CMD_CLIP_TEXT: |
case FZ_CMD_CLIP_STROKE_TEXT: |
case FZ_CMD_IGNORE_TEXT: |
fz_free_text(node->item.text); |
break; |
case FZ_CMD_FILL_SHADE: |
fz_drop_shade(node->item.shade); |
break; |
case FZ_CMD_FILL_IMAGE: |
case FZ_CMD_FILL_IMAGE_MASK: |
case FZ_CMD_CLIP_IMAGE_MASK: |
fz_drop_pixmap(node->item.image); |
break; |
case FZ_CMD_POP_CLIP: |
case FZ_CMD_BEGIN_MASK: |
case FZ_CMD_END_MASK: |
case FZ_CMD_BEGIN_GROUP: |
case FZ_CMD_END_GROUP: |
case FZ_CMD_BEGIN_TILE: |
case FZ_CMD_END_TILE: |
break; |
} |
if (node->stroke) |
fz_free(node->stroke); |
if (node->colorspace) |
fz_drop_colorspace(node->colorspace); |
fz_free(node); |
} |
static void |
fz_list_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_FILL_PATH, ctm, colorspace, color, alpha); |
node->rect = fz_bound_path(path, NULL, ctm); |
node->item.path = fz_clone_path(path); |
node->flag = even_odd; |
fz_append_display_node(user, node); |
} |
static void |
fz_list_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_STROKE_PATH, ctm, colorspace, color, alpha); |
node->rect = fz_bound_path(path, stroke, ctm); |
node->item.path = fz_clone_path(path); |
node->stroke = fz_clone_stroke_state(stroke); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_clip_path(void *user, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_CLIP_PATH, ctm, NULL, NULL, 0); |
node->rect = fz_bound_path(path, NULL, ctm); |
if (rect != NULL) |
node->rect = fz_intersect_rect(node->rect, *rect); |
node->item.path = fz_clone_path(path); |
node->flag = even_odd; |
fz_append_display_node(user, node); |
} |
static void |
fz_list_clip_stroke_path(void *user, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_CLIP_STROKE_PATH, ctm, NULL, NULL, 0); |
node->rect = fz_bound_path(path, stroke, ctm); |
if (rect != NULL) |
node->rect = fz_intersect_rect(node->rect, *rect); |
node->item.path = fz_clone_path(path); |
node->stroke = fz_clone_stroke_state(stroke); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_fill_text(void *user, fz_text *text, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_FILL_TEXT, ctm, colorspace, color, alpha); |
node->rect = fz_bound_text(text, ctm); |
node->item.text = fz_clone_text(text); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_STROKE_TEXT, ctm, colorspace, color, alpha); |
node->rect = fz_bound_text(text, ctm); |
node->item.text = fz_clone_text(text); |
node->stroke = fz_clone_stroke_state(stroke); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_CLIP_TEXT, ctm, NULL, NULL, 0); |
node->rect = fz_bound_text(text, ctm); |
node->item.text = fz_clone_text(text); |
node->flag = accumulate; |
/* when accumulating, be conservative about culling */ |
if (accumulate) |
node->rect = fz_infinite_rect; |
fz_append_display_node(user, node); |
} |
static void |
fz_list_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_CLIP_STROKE_TEXT, ctm, NULL, NULL, 0); |
node->rect = fz_bound_text(text, ctm); |
node->item.text = fz_clone_text(text); |
node->stroke = fz_clone_stroke_state(stroke); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_ignore_text(void *user, fz_text *text, fz_matrix ctm) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_IGNORE_TEXT, ctm, NULL, NULL, 0); |
node->rect = fz_bound_text(text, ctm); |
node->item.text = fz_clone_text(text); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_pop_clip(void *user) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_POP_CLIP, fz_identity, NULL, NULL, 0); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_FILL_SHADE, ctm, NULL, NULL, alpha); |
node->rect = fz_bound_shade(shade, ctm); |
node->item.shade = fz_keep_shade(shade); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_FILL_IMAGE, ctm, NULL, NULL, alpha); |
node->rect = fz_transform_rect(ctm, fz_unit_rect); |
node->item.image = fz_keep_pixmap(image); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_fill_image_mask(void *user, fz_pixmap *image, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_FILL_IMAGE_MASK, ctm, colorspace, color, alpha); |
node->rect = fz_transform_rect(ctm, fz_unit_rect); |
node->item.image = fz_keep_pixmap(image); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_CLIP_IMAGE_MASK, ctm, NULL, NULL, 0); |
node->rect = fz_transform_rect(ctm, fz_unit_rect); |
if (rect != NULL) |
node->rect = fz_intersect_rect(node->rect, *rect); |
node->item.image = fz_keep_pixmap(image); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_begin_mask(void *user, fz_rect rect, int luminosity, fz_colorspace *colorspace, float *color) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_BEGIN_MASK, fz_identity, colorspace, color, 0); |
node->rect = rect; |
node->flag = luminosity; |
fz_append_display_node(user, node); |
} |
static void |
fz_list_end_mask(void *user) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_END_MASK, fz_identity, NULL, NULL, 0); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_begin_group(void *user, fz_rect rect, int isolated, int knockout, int blendmode, float alpha) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_BEGIN_GROUP, fz_identity, NULL, NULL, alpha); |
node->rect = rect; |
node->item.blendmode = blendmode; |
node->flag |= isolated ? ISOLATED : 0; |
node->flag |= knockout ? KNOCKOUT : 0; |
fz_append_display_node(user, node); |
} |
static void |
fz_list_end_group(void *user) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_END_GROUP, fz_identity, NULL, NULL, 0); |
fz_append_display_node(user, node); |
} |
static void |
fz_list_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_BEGIN_TILE, ctm, NULL, NULL, 0); |
node->rect = area; |
node->color[0] = xstep; |
node->color[1] = ystep; |
node->color[2] = view.x0; |
node->color[3] = view.y0; |
node->color[4] = view.x1; |
node->color[5] = view.y1; |
fz_append_display_node(user, node); |
} |
static void |
fz_list_end_tile(void *user) |
{ |
fz_display_node *node; |
node = fz_new_display_node(FZ_CMD_END_TILE, fz_identity, NULL, NULL, 0); |
fz_append_display_node(user, node); |
} |
fz_device * |
fz_new_list_device(fz_display_list *list) |
{ |
fz_device *dev = fz_new_device(list); |
dev->fill_path = fz_list_fill_path; |
dev->stroke_path = fz_list_stroke_path; |
dev->clip_path = fz_list_clip_path; |
dev->clip_stroke_path = fz_list_clip_stroke_path; |
dev->fill_text = fz_list_fill_text; |
dev->stroke_text = fz_list_stroke_text; |
dev->clip_text = fz_list_clip_text; |
dev->clip_stroke_text = fz_list_clip_stroke_text; |
dev->ignore_text = fz_list_ignore_text; |
dev->fill_shade = fz_list_fill_shade; |
dev->fill_image = fz_list_fill_image; |
dev->fill_image_mask = fz_list_fill_image_mask; |
dev->clip_image_mask = fz_list_clip_image_mask; |
dev->pop_clip = fz_list_pop_clip; |
dev->begin_mask = fz_list_begin_mask; |
dev->end_mask = fz_list_end_mask; |
dev->begin_group = fz_list_begin_group; |
dev->end_group = fz_list_end_group; |
dev->begin_tile = fz_list_begin_tile; |
dev->end_tile = fz_list_end_tile; |
return dev; |
} |
fz_display_list * |
fz_new_display_list(void) |
{ |
fz_display_list *list = fz_malloc(sizeof(fz_display_list)); |
list->first = NULL; |
list->last = NULL; |
list->top = 0; |
list->tiled = 0; |
return list; |
} |
void |
fz_free_display_list(fz_display_list *list) |
{ |
fz_display_node *node = list->first; |
while (node) |
{ |
fz_display_node *next = node->next; |
fz_free_display_node(node); |
node = next; |
} |
fz_free(list); |
} |
void |
fz_execute_display_list(fz_display_list *list, fz_device *dev, fz_matrix top_ctm, fz_bbox scissor) |
{ |
fz_display_node *node; |
fz_matrix ctm; |
fz_rect rect; |
fz_bbox bbox; |
int clipped = 0; |
int tiled = 0; |
int empty; |
if (!fz_is_infinite_bbox(scissor)) |
{ |
/* add some fuzz at the edges, as especially glyph rects |
* are sometimes not actually completely bounding the glyph */ |
scissor.x0 -= 20; scissor.y0 -= 20; |
scissor.x1 += 20; scissor.y1 += 20; |
} |
for (node = list->first; node; node = node->next) |
{ |
/* cull objects to draw using a quick visibility test */ |
if (tiled || node->cmd == FZ_CMD_BEGIN_TILE || node->cmd == FZ_CMD_END_TILE) |
{ |
empty = 0; |
} |
else |
{ |
bbox = fz_round_rect(fz_transform_rect(top_ctm, node->rect)); |
bbox = fz_intersect_bbox(bbox, scissor); |
empty = fz_is_empty_bbox(bbox); |
} |
if (clipped || empty) |
{ |
switch (node->cmd) |
{ |
case FZ_CMD_CLIP_PATH: |
case FZ_CMD_CLIP_STROKE_PATH: |
case FZ_CMD_CLIP_TEXT: |
case FZ_CMD_CLIP_STROKE_TEXT: |
case FZ_CMD_CLIP_IMAGE_MASK: |
case FZ_CMD_BEGIN_MASK: |
case FZ_CMD_BEGIN_GROUP: |
clipped++; |
continue; |
case FZ_CMD_POP_CLIP: |
case FZ_CMD_END_GROUP: |
if (!clipped) |
goto visible; |
clipped--; |
continue; |
case FZ_CMD_END_MASK: |
if (!clipped) |
goto visible; |
continue; |
default: |
continue; |
} |
} |
visible: |
ctm = fz_concat(node->ctm, top_ctm); |
switch (node->cmd) |
{ |
case FZ_CMD_FILL_PATH: |
fz_fill_path(dev, node->item.path, node->flag, ctm, |
node->colorspace, node->color, node->alpha); |
break; |
case FZ_CMD_STROKE_PATH: |
fz_stroke_path(dev, node->item.path, node->stroke, ctm, |
node->colorspace, node->color, node->alpha); |
break; |
case FZ_CMD_CLIP_PATH: |
{ |
fz_rect trect = fz_transform_rect(top_ctm, node->rect); |
fz_clip_path(dev, node->item.path, &trect, node->flag, ctm); |
break; |
} |
case FZ_CMD_CLIP_STROKE_PATH: |
{ |
fz_rect trect = fz_transform_rect(top_ctm, node->rect); |
fz_clip_stroke_path(dev, node->item.path, &trect, node->stroke, ctm); |
break; |
} |
case FZ_CMD_FILL_TEXT: |
fz_fill_text(dev, node->item.text, ctm, |
node->colorspace, node->color, node->alpha); |
break; |
case FZ_CMD_STROKE_TEXT: |
fz_stroke_text(dev, node->item.text, node->stroke, ctm, |
node->colorspace, node->color, node->alpha); |
break; |
case FZ_CMD_CLIP_TEXT: |
fz_clip_text(dev, node->item.text, ctm, node->flag); |
break; |
case FZ_CMD_CLIP_STROKE_TEXT: |
fz_clip_stroke_text(dev, node->item.text, node->stroke, ctm); |
break; |
case FZ_CMD_IGNORE_TEXT: |
fz_ignore_text(dev, node->item.text, ctm); |
break; |
case FZ_CMD_FILL_SHADE: |
fz_fill_shade(dev, node->item.shade, ctm, node->alpha); |
break; |
case FZ_CMD_FILL_IMAGE: |
fz_fill_image(dev, node->item.image, ctm, node->alpha); |
break; |
case FZ_CMD_FILL_IMAGE_MASK: |
fz_fill_image_mask(dev, node->item.image, ctm, |
node->colorspace, node->color, node->alpha); |
break; |
case FZ_CMD_CLIP_IMAGE_MASK: |
{ |
fz_rect trect = fz_transform_rect(top_ctm, node->rect); |
fz_clip_image_mask(dev, node->item.image, &trect, ctm); |
break; |
} |
case FZ_CMD_POP_CLIP: |
fz_pop_clip(dev); |
break; |
case FZ_CMD_BEGIN_MASK: |
rect = fz_transform_rect(top_ctm, node->rect); |
fz_begin_mask(dev, rect, node->flag, node->colorspace, node->color); |
break; |
case FZ_CMD_END_MASK: |
fz_end_mask(dev); |
break; |
case FZ_CMD_BEGIN_GROUP: |
rect = fz_transform_rect(top_ctm, node->rect); |
fz_begin_group(dev, rect, |
(node->flag & ISOLATED) != 0, (node->flag & KNOCKOUT) != 0, |
node->item.blendmode, node->alpha); |
break; |
case FZ_CMD_END_GROUP: |
fz_end_group(dev); |
break; |
case FZ_CMD_BEGIN_TILE: |
tiled++; |
rect.x0 = node->color[2]; |
rect.y0 = node->color[3]; |
rect.x1 = node->color[4]; |
rect.y1 = node->color[5]; |
fz_begin_tile(dev, node->rect, rect, |
node->color[0], node->color[1], ctm); |
break; |
case FZ_CMD_END_TILE: |
tiled--; |
fz_end_tile(dev); |
break; |
} |
} |
} |
/contrib/media/updf/fitz/dev_null.c |
---|
0,0 → 1,165 |
#include "fitz.h" |
fz_device * |
fz_new_device(void *user) |
{ |
fz_device *dev = fz_malloc(sizeof(fz_device)); |
memset(dev, 0, sizeof(fz_device)); |
dev->hints = 0; |
dev->flags = 0; |
dev->user = user; |
return dev; |
} |
void |
fz_free_device(fz_device *dev) |
{ |
if (dev->free_user) |
dev->free_user(dev->user); |
fz_free(dev); |
} |
void |
fz_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
if (dev->fill_path) |
dev->fill_path(dev->user, path, even_odd, ctm, colorspace, color, alpha); |
} |
void |
fz_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
if (dev->stroke_path) |
dev->stroke_path(dev->user, path, stroke, ctm, colorspace, color, alpha); |
} |
void |
fz_clip_path(fz_device *dev, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) |
{ |
if (dev->clip_path) |
dev->clip_path(dev->user, path, rect, even_odd, ctm); |
} |
void |
fz_clip_stroke_path(fz_device *dev, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) |
{ |
if (dev->clip_stroke_path) |
dev->clip_stroke_path(dev->user, path, rect, stroke, ctm); |
} |
void |
fz_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
if (dev->fill_text) |
dev->fill_text(dev->user, text, ctm, colorspace, color, alpha); |
} |
void |
fz_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
if (dev->stroke_text) |
dev->stroke_text(dev->user, text, stroke, ctm, colorspace, color, alpha); |
} |
void |
fz_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate) |
{ |
if (dev->clip_text) |
dev->clip_text(dev->user, text, ctm, accumulate); |
} |
void |
fz_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) |
{ |
if (dev->clip_stroke_text) |
dev->clip_stroke_text(dev->user, text, stroke, ctm); |
} |
void |
fz_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm) |
{ |
if (dev->ignore_text) |
dev->ignore_text(dev->user, text, ctm); |
} |
void |
fz_pop_clip(fz_device *dev) |
{ |
if (dev->pop_clip) |
dev->pop_clip(dev->user); |
} |
void |
fz_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha) |
{ |
if (dev->fill_shade) |
dev->fill_shade(dev->user, shade, ctm, alpha); |
} |
void |
fz_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha) |
{ |
if (dev->fill_image) |
dev->fill_image(dev->user, image, ctm, alpha); |
} |
void |
fz_fill_image_mask(fz_device *dev, fz_pixmap *image, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
if (dev->fill_image_mask) |
dev->fill_image_mask(dev->user, image, ctm, colorspace, color, alpha); |
} |
void |
fz_clip_image_mask(fz_device *dev, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) |
{ |
if (dev->clip_image_mask) |
dev->clip_image_mask(dev->user, image, rect, ctm); |
} |
void |
fz_begin_mask(fz_device *dev, fz_rect area, int luminosity, fz_colorspace *colorspace, float *bc) |
{ |
if (dev->begin_mask) |
dev->begin_mask(dev->user, area, luminosity, colorspace, bc); |
} |
void |
fz_end_mask(fz_device *dev) |
{ |
if (dev->end_mask) |
dev->end_mask(dev->user); |
} |
void |
fz_begin_group(fz_device *dev, fz_rect area, int isolated, int knockout, int blendmode, float alpha) |
{ |
if (dev->begin_group) |
dev->begin_group(dev->user, area, isolated, knockout, blendmode, alpha); |
} |
void |
fz_end_group(fz_device *dev) |
{ |
if (dev->end_group) |
dev->end_group(dev->user); |
} |
void |
fz_begin_tile(fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) |
{ |
if (dev->begin_tile) |
dev->begin_tile(dev->user, area, view, xstep, ystep, ctm); |
} |
void |
fz_end_tile(fz_device *dev) |
{ |
if (dev->end_tile) |
dev->end_tile(dev->user); |
} |
/contrib/media/updf/fitz/dev_text.c |
---|
0,0 → 1,418 |
#include "fitz.h" |
#define LINE_DIST 0.9f |
#define SPACE_DIST 0.2f |
#include <ft2build.h> |
#include FT_FREETYPE_H |
#include FT_ADVANCES_H |
typedef struct fz_text_device_s fz_text_device; |
struct fz_text_device_s |
{ |
fz_point point; |
fz_text_span *head; |
fz_text_span *span; |
}; |
fz_text_span * |
fz_new_text_span(void) |
{ |
fz_text_span *span; |
span = fz_malloc(sizeof(fz_text_span)); |
span->font = NULL; |
span->wmode = 0; |
span->size = 0; |
span->len = 0; |
span->cap = 0; |
span->text = NULL; |
span->next = NULL; |
span->eol = 0; |
return span; |
} |
void |
fz_free_text_span(fz_text_span *span) |
{ |
if (span->font) |
fz_drop_font(span->font); |
if (span->next) |
fz_free_text_span(span->next); |
fz_free(span->text); |
fz_free(span); |
} |
static void |
fz_add_text_char_imp(fz_text_span *span, int c, fz_bbox bbox) |
{ |
if (span->len + 1 >= span->cap) |
{ |
span->cap = span->cap > 1 ? (span->cap * 3) / 2 : 80; |
span->text = fz_realloc(span->text, span->cap, sizeof(fz_text_char)); |
} |
span->text[span->len].c = c; |
span->text[span->len].bbox = bbox; |
span->len ++; |
} |
static fz_bbox |
fz_split_bbox(fz_bbox bbox, int i, int n) |
{ |
float w = (float)(bbox.x1 - bbox.x0) / n; |
float x0 = bbox.x0; |
bbox.x0 = x0 + i * w; |
bbox.x1 = x0 + (i + 1) * w; |
return bbox; |
} |
static void |
fz_add_text_char(fz_text_span **last, fz_font *font, float size, int wmode, int c, fz_bbox bbox) |
{ |
fz_text_span *span = *last; |
if (!span->font) |
{ |
span->font = fz_keep_font(font); |
span->size = size; |
} |
if ((span->font != font || span->size != size || span->wmode != wmode) && c != 32) |
{ |
span = fz_new_text_span(); |
span->font = fz_keep_font(font); |
span->size = size; |
span->wmode = wmode; |
(*last)->next = span; |
*last = span; |
} |
switch (c) |
{ |
case -1: /* ignore when one unicode character maps to multiple glyphs */ |
break; |
case 0xFB00: /* ff */ |
fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 0, 2)); |
fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 1, 2)); |
break; |
case 0xFB01: /* fi */ |
fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 0, 2)); |
fz_add_text_char_imp(span, 'i', fz_split_bbox(bbox, 1, 2)); |
break; |
case 0xFB02: /* fl */ |
fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 0, 2)); |
fz_add_text_char_imp(span, 'l', fz_split_bbox(bbox, 1, 2)); |
break; |
case 0xFB03: /* ffi */ |
fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 0, 3)); |
fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 1, 3)); |
fz_add_text_char_imp(span, 'i', fz_split_bbox(bbox, 2, 3)); |
break; |
case 0xFB04: /* ffl */ |
fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 0, 3)); |
fz_add_text_char_imp(span, 'f', fz_split_bbox(bbox, 1, 3)); |
fz_add_text_char_imp(span, 'l', fz_split_bbox(bbox, 2, 3)); |
break; |
case 0xFB05: /* long st */ |
case 0xFB06: /* st */ |
fz_add_text_char_imp(span, 's', fz_split_bbox(bbox, 0, 2)); |
fz_add_text_char_imp(span, 't', fz_split_bbox(bbox, 1, 2)); |
break; |
default: |
fz_add_text_char_imp(span, c, bbox); |
break; |
} |
} |
static void |
fz_divide_text_chars(fz_text_span **last, int n, fz_bbox bbox) |
{ |
fz_text_span *span = *last; |
int i, x; |
x = span->len - n; |
if (x >= 0) |
for (i = 0; i < n; i++) |
span->text[x + i].bbox = fz_split_bbox(bbox, i, n); |
} |
static void |
fz_add_text_newline(fz_text_span **last, fz_font *font, float size, int wmode) |
{ |
fz_text_span *span; |
span = fz_new_text_span(); |
span->font = fz_keep_font(font); |
span->size = size; |
span->wmode = wmode; |
(*last)->eol = 1; |
(*last)->next = span; |
*last = span; |
} |
void |
fz_debug_text_span_xml(fz_text_span *span) |
{ |
char buf[10]; |
int c, n, k, i; |
printf("<span font=\"%s\" size=\"%g\" wmode=\"%d\" eol=\"%d\">\n", |
span->font ? span->font->name : "NULL", span->size, span->wmode, span->eol); |
for (i = 0; i < span->len; i++) |
{ |
printf("\t<char ucs=\""); |
c = span->text[i].c; |
if (c < 128) |
putchar(c); |
else |
{ |
n = runetochar(buf, &c); |
for (k = 0; k < n; k++) |
putchar(buf[k]); |
} |
printf("\" bbox=\"%d %d %d %d\" />\n", |
span->text[i].bbox.x0, |
span->text[i].bbox.y0, |
span->text[i].bbox.x1, |
span->text[i].bbox.y1); |
} |
printf("</span>\n"); |
if (span->next) |
fz_debug_text_span_xml(span->next); |
} |
void |
fz_debug_text_span(fz_text_span *span) |
{ |
char buf[10]; |
int c, n, k, i; |
for (i = 0; i < span->len; i++) |
{ |
c = span->text[i].c; |
if (c < 128) |
putchar(c); |
else |
{ |
n = runetochar(buf, &c); |
for (k = 0; k < n; k++) |
putchar(buf[k]); |
} |
} |
if (span->eol) |
putchar('\n'); |
if (span->next) |
fz_debug_text_span(span->next); |
} |
static void |
fz_text_extract_span(fz_text_span **last, fz_text *text, fz_matrix ctm, fz_point *pen) |
{ |
fz_font *font = text->font; |
FT_Face face = font->ft_face; |
fz_matrix tm = text->trm; |
fz_matrix trm; |
float size; |
float adv; |
fz_rect rect; |
fz_point dir, ndir; |
fz_point delta, ndelta; |
float dist, dot; |
float ascender = 1; |
float descender = 0; |
int multi; |
int i, err; |
if (text->len == 0) |
return; |
if (font->ft_face) |
{ |
err = FT_Set_Char_Size(font->ft_face, 64, 64, 72, 72); |
if (err) |
fz_warn("freetype set character size: %s", ft_error_string(err)); |
ascender = (float)face->ascender / face->units_per_EM; |
descender = (float)face->descender / face->units_per_EM; |
} |
rect = fz_empty_rect; |
if (text->wmode == 0) |
{ |
dir.x = 1; |
dir.y = 0; |
} |
else |
{ |
dir.x = 0; |
dir.y = 1; |
} |
tm.e = 0; |
tm.f = 0; |
trm = fz_concat(tm, ctm); |
dir = fz_transform_vector(trm, dir); |
dist = sqrtf(dir.x * dir.x + dir.y * dir.y); |
ndir.x = dir.x / dist; |
ndir.y = dir.y / dist; |
size = fz_matrix_expansion(trm); |
multi = 1; |
for (i = 0; i < text->len; i++) |
{ |
if (text->items[i].gid < 0) |
{ |
fz_add_text_char(last, font, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); |
multi ++; |
fz_divide_text_chars(last, multi, fz_round_rect(rect)); |
continue; |
} |
multi = 1; |
/* Calculate new pen location and delta */ |
tm.e = text->items[i].x; |
tm.f = text->items[i].y; |
trm = fz_concat(tm, ctm); |
delta.x = pen->x - trm.e; |
delta.y = pen->y - trm.f; |
if (pen->x == -1 && pen->y == -1) |
delta.x = delta.y = 0; |
dist = sqrtf(delta.x * delta.x + delta.y * delta.y); |
/* Add space and newlines based on pen movement */ |
if (dist > 0) |
{ |
ndelta.x = delta.x / dist; |
ndelta.y = delta.y / dist; |
dot = ndelta.x * ndir.x + ndelta.y * ndir.y; |
if (dist > size * LINE_DIST) |
{ |
fz_add_text_newline(last, font, size, text->wmode); |
} |
else if (fabsf(dot) > 0.95f && dist > size * SPACE_DIST) |
{ |
if ((*last)->len > 0 && (*last)->text[(*last)->len - 1].c != ' ') |
{ |
fz_rect spacerect; |
spacerect.x0 = -0.2f; |
spacerect.y0 = 0; |
spacerect.x1 = 0; |
spacerect.y1 = 1; |
spacerect = fz_transform_rect(trm, spacerect); |
fz_add_text_char(last, font, size, text->wmode, ' ', fz_round_rect(spacerect)); |
} |
} |
} |
/* Calculate bounding box and new pen position based on font metrics */ |
if (font->ft_face) |
{ |
FT_Fixed ftadv = 0; |
int mask = FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING | FT_LOAD_IGNORE_TRANSFORM; |
/* TODO: freetype returns broken vertical metrics */ |
/* if (text->wmode) mask |= FT_LOAD_VERTICAL_LAYOUT; */ |
FT_Get_Advance(font->ft_face, text->items[i].gid, mask, &ftadv); |
adv = ftadv / 65536.0f; |
rect.x0 = 0; |
rect.y0 = descender; |
rect.x1 = adv; |
rect.y1 = ascender; |
} |
else |
{ |
adv = font->t3widths[text->items[i].gid]; |
rect.x0 = 0; |
rect.y0 = descender; |
rect.x1 = adv; |
rect.y1 = ascender; |
} |
rect = fz_transform_rect(trm, rect); |
pen->x = trm.e + dir.x * adv; |
pen->y = trm.f + dir.y * adv; |
fz_add_text_char(last, font, size, text->wmode, text->items[i].ucs, fz_round_rect(rect)); |
} |
} |
static void |
fz_text_fill_text(void *user, fz_text *text, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_text_device *tdev = user; |
fz_text_extract_span(&tdev->span, text, ctm, &tdev->point); |
} |
static void |
fz_text_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
fz_text_device *tdev = user; |
fz_text_extract_span(&tdev->span, text, ctm, &tdev->point); |
} |
static void |
fz_text_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate) |
{ |
fz_text_device *tdev = user; |
fz_text_extract_span(&tdev->span, text, ctm, &tdev->point); |
} |
static void |
fz_text_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) |
{ |
fz_text_device *tdev = user; |
fz_text_extract_span(&tdev->span, text, ctm, &tdev->point); |
} |
static void |
fz_text_ignore_text(void *user, fz_text *text, fz_matrix ctm) |
{ |
fz_text_device *tdev = user; |
fz_text_extract_span(&tdev->span, text, ctm, &tdev->point); |
} |
static void |
fz_text_free_user(void *user) |
{ |
fz_text_device *tdev = user; |
tdev->span->eol = 1; |
/* TODO: unicode NFC normalization */ |
/* TODO: bidi logical reordering */ |
fz_free(tdev); |
} |
fz_device * |
fz_new_text_device(fz_text_span *root) |
{ |
fz_device *dev; |
fz_text_device *tdev = fz_malloc(sizeof(fz_text_device)); |
tdev->head = root; |
tdev->span = root; |
tdev->point.x = -1; |
tdev->point.y = -1; |
dev = fz_new_device(tdev); |
dev->hints = FZ_IGNORE_IMAGE | FZ_IGNORE_SHADE; |
dev->free_user = fz_text_free_user; |
dev->fill_text = fz_text_fill_text; |
dev->stroke_text = fz_text_stroke_text; |
dev->clip_text = fz_text_clip_text; |
dev->clip_stroke_text = fz_text_clip_stroke_text; |
dev->ignore_text = fz_text_ignore_text; |
return dev; |
} |
/contrib/media/updf/fitz/dev_trace.c |
---|
0,0 → 1,305 |
#include "fitz.h" |
static void |
fz_trace_matrix(fz_matrix ctm) |
{ |
printf("matrix=\"%g %g %g %g %g %g\" ", |
ctm.a, ctm.b, ctm.c, ctm.d, ctm.e, ctm.f); |
} |
static void |
fz_trace_color(fz_colorspace *colorspace, float *color, float alpha) |
{ |
int i; |
printf("colorspace=\"%s\" color=\"", colorspace->name); |
for (i = 0; i < colorspace->n; i++) |
printf("%s%g", i == 0 ? "" : " ", color[i]); |
printf("\" "); |
if (alpha < 1) |
printf("alpha=\"%g\" ", alpha); |
} |
static void |
fz_trace_path(fz_path *path, int indent) |
{ |
float x, y; |
int i = 0; |
int n; |
while (i < path->len) |
{ |
for (n = 0; n < indent; n++) |
putchar(' '); |
switch (path->items[i++].k) |
{ |
case FZ_MOVETO: |
x = path->items[i++].v; |
y = path->items[i++].v; |
printf("<moveto x=\"%g\" y=\"%g\" />\n", x, y); |
break; |
case FZ_LINETO: |
x = path->items[i++].v; |
y = path->items[i++].v; |
printf("<lineto x=\"%g\" y=\"%g\" />\n", x, y); |
break; |
case FZ_CURVETO: |
x = path->items[i++].v; |
y = path->items[i++].v; |
printf("<curveto x1=\"%g\" y1=\"%g\" ", x, y); |
x = path->items[i++].v; |
y = path->items[i++].v; |
printf("x2=\"%g\" y2=\"%g\" ", x, y); |
x = path->items[i++].v; |
y = path->items[i++].v; |
printf("x3=\"%g\" y3=\"%g\" />\n", x, y); |
break; |
case FZ_CLOSE_PATH: |
printf("<closepath />\n"); |
break; |
} |
} |
} |
static void |
fz_trace_fill_path(void *user, fz_path *path, int even_odd, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
printf("<fill_path "); |
if (even_odd) |
printf("winding=\"eofill\" "); |
else |
printf("winding=\"nonzero\" "); |
fz_trace_color(colorspace, color, alpha); |
fz_trace_matrix(ctm); |
printf(">\n"); |
fz_trace_path(path, 0); |
printf("</fill_path>\n"); |
} |
static void |
fz_trace_stroke_path(void *user, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
int i; |
printf("<stroke_path "); |
printf("linewidth=\"%g\" ", stroke->linewidth); |
printf("miterlimit=\"%g\" ", stroke->miterlimit); |
printf("linecap=\"%d,%d,%d\" ", stroke->start_cap, stroke->dash_cap, stroke->end_cap); |
printf("linejoin=\"%d\" ", stroke->linejoin); |
if (stroke->dash_len) |
{ |
printf("dash_phase=\"%g\" dash=\"", stroke->dash_phase); |
for (i = 0; i < stroke->dash_len; i++) |
printf("%g ", stroke->dash_list[i]); |
printf("\""); |
} |
fz_trace_color(colorspace, color, alpha); |
fz_trace_matrix(ctm); |
printf(">\n"); |
fz_trace_path(path, 0); |
printf("</stroke_path>\n"); |
} |
static void |
fz_trace_clip_path(void *user, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm) |
{ |
printf("<clip_path "); |
if (even_odd) |
printf("winding=\"eofill\" "); |
else |
printf("winding=\"nonzero\" "); |
fz_trace_matrix(ctm); |
printf("contentbbox=\"%g %g %g %g\">\n", |
rect->x0, rect->y0, rect->x1, rect->y1); |
fz_trace_path(path, 0); |
printf("</clip_path>\n"); |
} |
static void |
fz_trace_clip_stroke_path(void *user, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm) |
{ |
printf("<clip_stroke_path "); |
fz_trace_matrix(ctm); |
printf(">\n"); |
fz_trace_path(path, 0); |
printf("</clip_stroke_path>\n"); |
} |
static void |
fz_trace_fill_text(void *user, fz_text *text, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
printf("<fill_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode); |
fz_trace_color(colorspace, color, alpha); |
fz_trace_matrix(fz_concat(ctm, text->trm)); |
printf(">\n"); |
fz_debug_text(text, 0); |
printf("</fill_text>\n"); |
} |
static void |
fz_trace_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
printf("<stroke_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode); |
fz_trace_color(colorspace, color, alpha); |
fz_trace_matrix(fz_concat(ctm, text->trm)); |
printf(">\n"); |
fz_debug_text(text, 0); |
printf("</stroke_text>\n"); |
} |
static void |
fz_trace_clip_text(void *user, fz_text *text, fz_matrix ctm, int accumulate) |
{ |
printf("<clip_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode); |
printf("accumulate=\"%d\" ", accumulate); |
fz_trace_matrix(fz_concat(ctm, text->trm)); |
printf(">\n"); |
fz_debug_text(text, 0); |
printf("</clip_text>\n"); |
} |
static void |
fz_trace_clip_stroke_text(void *user, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm) |
{ |
printf("<clip_stroke_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode); |
fz_trace_matrix(fz_concat(ctm, text->trm)); |
printf(">\n"); |
fz_debug_text(text, 0); |
printf("</clip_stroke_text>\n"); |
} |
static void |
fz_trace_ignore_text(void *user, fz_text *text, fz_matrix ctm) |
{ |
printf("<ignore_text font=\"%s\" wmode=\"%d\" ", text->font->name, text->wmode); |
fz_trace_matrix(fz_concat(ctm, text->trm)); |
printf(">\n"); |
fz_debug_text(text, 0); |
printf("</ignore_text>\n"); |
} |
static void |
fz_trace_fill_image(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) |
{ |
printf("<fill_image alpha=\"%g\" ", alpha); |
fz_trace_matrix(ctm); |
printf("/>\n"); |
} |
static void |
fz_trace_fill_shade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) |
{ |
printf("<fill_shade alpha=\"%g\" ", alpha); |
fz_trace_matrix(ctm); |
printf("/>\n"); |
} |
static void |
fz_trace_fill_image_mask(void *user, fz_pixmap *image, fz_matrix ctm, |
fz_colorspace *colorspace, float *color, float alpha) |
{ |
printf("<fill_image_mask "); |
fz_trace_matrix(ctm); |
fz_trace_color(colorspace, color, alpha); |
printf("/>\n"); |
} |
static void |
fz_trace_clip_image_mask(void *user, fz_pixmap *image, fz_rect *rect, fz_matrix ctm) |
{ |
printf("<clip_image_mask "); |
fz_trace_matrix(ctm); |
printf("/>\n"); |
} |
static void |
fz_trace_pop_clip(void *user) |
{ |
printf("<pop_clip />\n"); |
} |
static void |
fz_trace_begin_mask(void *user, fz_rect bbox, int luminosity, fz_colorspace *colorspace, float *color) |
{ |
printf("<mask bbox=\"%g %g %g %g\" s=\"%s\" ", |
bbox.x0, bbox.y0, bbox.x1, bbox.y1, |
luminosity ? "luminosity" : "alpha"); |
// fz_trace_color(colorspace, color, 1); |
printf(">\n"); |
} |
static void |
fz_trace_end_mask(void *user) |
{ |
printf("</mask>\n"); |
} |
static void |
fz_trace_begin_group(void *user, fz_rect bbox, int isolated, int knockout, int blendmode, float alpha) |
{ |
printf("<group bbox=\"%g %g %g %g\" isolated=\"%d\" knockout=\"%d\" blendmode=\"%s\" alpha=\"%g\">\n", |
bbox.x0, bbox.y0, bbox.x1, bbox.y1, |
isolated, knockout, fz_blendmode_name(blendmode), alpha); |
} |
static void |
fz_trace_end_group(void *user) |
{ |
printf("</group>\n"); |
} |
static void |
fz_trace_begin_tile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) |
{ |
printf("<tile "); |
printf("area=\"%g %g %g %g\" ", area.x0, area.y0, area.x1, area.y1); |
printf("view=\"%g %g %g %g\" ", view.x0, view.y0, view.x1, view.y1); |
printf("xstep=\"%g\" ystep=\"%g\" ", xstep, ystep); |
fz_trace_matrix(ctm); |
printf(">\n"); |
} |
static void |
fz_trace_end_tile(void *user) |
{ |
printf("</tile>\n"); |
} |
fz_device *fz_new_trace_device(void) |
{ |
fz_device *dev = fz_new_device(NULL); |
dev->fill_path = fz_trace_fill_path; |
dev->stroke_path = fz_trace_stroke_path; |
dev->clip_path = fz_trace_clip_path; |
dev->clip_stroke_path = fz_trace_clip_stroke_path; |
dev->fill_text = fz_trace_fill_text; |
dev->stroke_text = fz_trace_stroke_text; |
dev->clip_text = fz_trace_clip_text; |
dev->clip_stroke_text = fz_trace_clip_stroke_text; |
dev->ignore_text = fz_trace_ignore_text; |
dev->fill_shade = fz_trace_fill_shade; |
dev->fill_image = fz_trace_fill_image; |
dev->fill_image_mask = fz_trace_fill_image_mask; |
dev->clip_image_mask = fz_trace_clip_image_mask; |
dev->pop_clip = fz_trace_pop_clip; |
dev->begin_mask = fz_trace_begin_mask; |
dev->end_mask = fz_trace_end_mask; |
dev->begin_group = fz_trace_begin_group; |
dev->end_group = fz_trace_end_group; |
dev->begin_tile = fz_trace_begin_tile; |
dev->end_tile = fz_trace_end_tile; |
return dev; |
} |
/contrib/media/updf/fitz/filt_basic.c |
---|
0,0 → 1,504 |
#include "fitz.h" |
/* Pretend we have a filter that just copies data forever */ |
fz_stream * |
fz_open_copy(fz_stream *chain) |
{ |
return fz_keep_stream(chain); |
} |
/* Null filter copies a specified amount of data */ |
struct null_filter |
{ |
fz_stream *chain; |
int remain; |
}; |
static int |
read_null(fz_stream *stm, unsigned char *buf, int len) |
{ |
struct null_filter *state = stm->state; |
int amount = MIN(len, state->remain); |
int n = fz_read(state->chain, buf, amount); |
if (n < 0) |
return fz_rethrow(n, "read error in null filter"); |
state->remain -= n; |
return n; |
} |
static void |
close_null(fz_stream *stm) |
{ |
struct null_filter *state = stm->state; |
fz_close(state->chain); |
fz_free(state); |
} |
fz_stream * |
fz_open_null(fz_stream *chain, int len) |
{ |
struct null_filter *state; |
state = fz_malloc(sizeof(struct null_filter)); |
state->chain = chain; |
state->remain = len; |
return fz_new_stream(state, read_null, close_null); |
} |
/* ASCII Hex Decode */ |
typedef struct fz_ahxd_s fz_ahxd; |
struct fz_ahxd_s |
{ |
fz_stream *chain; |
int eod; |
}; |
static inline int iswhite(int a) |
{ |
switch (a) { |
case '\n': case '\r': case '\t': case ' ': |
case '\0': case '\f': case '\b': case 0177: |
return 1; |
} |
return 0; |
} |
static inline int ishex(int a) |
{ |
return (a >= 'A' && a <= 'F') || |
(a >= 'a' && a <= 'f') || |
(a >= '0' && a <= '9'); |
} |
static inline int unhex(int a) |
{ |
if (a >= 'A' && a <= 'F') return a - 'A' + 0xA; |
if (a >= 'a' && a <= 'f') return a - 'a' + 0xA; |
if (a >= '0' && a <= '9') return a - '0'; |
return 0; |
} |
static int |
read_ahxd(fz_stream *stm, unsigned char *buf, int len) |
{ |
fz_ahxd *state = stm->state; |
unsigned char *p = buf; |
unsigned char *ep = buf + len; |
int a, b, c, odd; |
odd = 0; |
while (p < ep) |
{ |
if (state->eod) |
return p - buf; |
c = fz_read_byte(state->chain); |
if (c < 0) |
return p - buf; |
if (ishex(c)) |
{ |
if (!odd) |
{ |
a = unhex(c); |
odd = 1; |
} |
else |
{ |
b = unhex(c); |
*p++ = (a << 4) | b; |
odd = 0; |
} |
} |
else if (c == '>') |
{ |
if (odd) |
*p++ = (a << 4); |
state->eod = 1; |
} |
else if (!iswhite(c)) |
{ |
return fz_throw("bad data in ahxd: '%c'", c); |
} |
} |
return p - buf; |
} |
static void |
close_ahxd(fz_stream *stm) |
{ |
fz_ahxd *state = stm->state; |
fz_close(state->chain); |
fz_free(state); |
} |
fz_stream * |
fz_open_ahxd(fz_stream *chain) |
{ |
fz_ahxd *state; |
state = fz_malloc(sizeof(fz_ahxd)); |
state->chain = chain; |
state->eod = 0; |
return fz_new_stream(state, read_ahxd, close_ahxd); |
} |
/* ASCII 85 Decode */ |
typedef struct fz_a85d_s fz_a85d; |
struct fz_a85d_s |
{ |
fz_stream *chain; |
unsigned char bp[4]; |
unsigned char *rp, *wp; |
int eod; |
}; |
static int |
read_a85d(fz_stream *stm, unsigned char *buf, int len) |
{ |
fz_a85d *state = stm->state; |
unsigned char *p = buf; |
unsigned char *ep = buf + len; |
int count = 0; |
int word = 0; |
int c; |
while (state->rp < state->wp && p < ep) |
*p++ = *state->rp++; |
while (p < ep) |
{ |
if (state->eod) |
return p - buf; |
c = fz_read_byte(state->chain); |
if (c < 0) |
return p - buf; |
if (c >= '!' && c <= 'u') |
{ |
if (count == 4) |
{ |
word = word * 85 + (c - '!'); |
state->bp[0] = (word >> 24) & 0xff; |
state->bp[1] = (word >> 16) & 0xff; |
state->bp[2] = (word >> 8) & 0xff; |
state->bp[3] = (word) & 0xff; |
state->rp = state->bp; |
state->wp = state->bp + 4; |
word = 0; |
count = 0; |
} |
else |
{ |
word = word * 85 + (c - '!'); |
count ++; |
} |
} |
else if (c == 'z' && count == 0) |
{ |
state->bp[0] = 0; |
state->bp[1] = 0; |
state->bp[2] = 0; |
state->bp[3] = 0; |
state->rp = state->bp; |
state->wp = state->bp + 4; |
} |
else if (c == '~') |
{ |
c = fz_read_byte(state->chain); |
if (c != '>') |
fz_warn("bad eod marker in a85d"); |
switch (count) { |
case 0: |
break; |
case 1: |
return fz_throw("partial final byte in a85d"); |
case 2: |
word = word * (85 * 85 * 85) + 0xffffff; |
state->bp[0] = word >> 24; |
state->rp = state->bp; |
state->wp = state->bp + 1; |
break; |
case 3: |
word = word * (85 * 85) + 0xffff; |
state->bp[0] = word >> 24; |
state->bp[1] = word >> 16; |
state->rp = state->bp; |
state->wp = state->bp + 2; |
break; |
case 4: |
word = word * 85 + 0xff; |
state->bp[0] = word >> 24; |
state->bp[1] = word >> 16; |
state->bp[2] = word >> 8; |
state->rp = state->bp; |
state->wp = state->bp + 3; |
break; |
} |
state->eod = 1; |
} |
else if (!iswhite(c)) |
{ |
return fz_throw("bad data in a85d: '%c'", c); |
} |
while (state->rp < state->wp && p < ep) |
*p++ = *state->rp++; |
} |
return p - buf; |
} |
static void |
close_a85d(fz_stream *stm) |
{ |
fz_a85d *state = stm->state; |
fz_close(state->chain); |
fz_free(state); |
} |
fz_stream * |
fz_open_a85d(fz_stream *chain) |
{ |
fz_a85d *state; |
state = fz_malloc(sizeof(fz_a85d)); |
state->chain = chain; |
state->rp = state->bp; |
state->wp = state->bp; |
state->eod = 0; |
return fz_new_stream(state, read_a85d, close_a85d); |
} |
/* Run Length Decode */ |
typedef struct fz_rld_s fz_rld; |
struct fz_rld_s |
{ |
fz_stream *chain; |
int run, n, c; |
}; |
static int |
read_rld(fz_stream *stm, unsigned char *buf, int len) |
{ |
fz_rld *state = stm->state; |
unsigned char *p = buf; |
unsigned char *ep = buf + len; |
while (p < ep) |
{ |
if (state->run == 128) |
return p - buf; |
if (state->n == 0) |
{ |
state->run = fz_read_byte(state->chain); |
if (state->run < 0) |
state->run = 128; |
if (state->run < 128) |
state->n = state->run + 1; |
if (state->run > 128) |
{ |
state->n = 257 - state->run; |
state->c = fz_read_byte(state->chain); |
if (state->c < 0) |
return fz_throw("premature end of data in run length decode"); |
} |
} |
if (state->run < 128) |
{ |
while (p < ep && state->n) |
{ |
int c = fz_read_byte(state->chain); |
if (c < 0) |
return fz_throw("premature end of data in run length decode"); |
*p++ = c; |
state->n--; |
} |
} |
if (state->run > 128) |
{ |
while (p < ep && state->n) |
{ |
*p++ = state->c; |
state->n--; |
} |
} |
} |
return p - buf; |
} |
static void |
close_rld(fz_stream *stm) |
{ |
fz_rld *state = stm->state; |
fz_close(state->chain); |
fz_free(state); |
} |
fz_stream * |
fz_open_rld(fz_stream *chain) |
{ |
fz_rld *state; |
state = fz_malloc(sizeof(fz_rld)); |
state->chain = chain; |
state->run = 0; |
state->n = 0; |
state->c = 0; |
return fz_new_stream(state, read_rld, close_rld); |
} |
/* RC4 Filter */ |
typedef struct fz_arc4c_s fz_arc4c; |
struct fz_arc4c_s |
{ |
fz_stream *chain; |
fz_arc4 arc4; |
}; |
static int |
read_arc4(fz_stream *stm, unsigned char *buf, int len) |
{ |
fz_arc4c *state = stm->state; |
int n; |
n = fz_read(state->chain, buf, len); |
if (n < 0) |
return fz_rethrow(n, "read error in arc4 filter"); |
fz_arc4_encrypt(&state->arc4, buf, buf, n); |
return n; |
} |
static void |
close_arc4(fz_stream *stm) |
{ |
fz_arc4c *state = stm->state; |
fz_close(state->chain); |
fz_free(state); |
} |
fz_stream * |
fz_open_arc4(fz_stream *chain, unsigned char *key, unsigned keylen) |
{ |
fz_arc4c *state; |
state = fz_malloc(sizeof(fz_arc4c)); |
state->chain = chain; |
fz_arc4_init(&state->arc4, key, keylen); |
return fz_new_stream(state, read_arc4, close_arc4); |
} |
/* AES Filter */ |
typedef struct fz_aesd_s fz_aesd; |
struct fz_aesd_s |
{ |
fz_stream *chain; |
fz_aes aes; |
unsigned char iv[16]; |
int ivcount; |
unsigned char bp[16]; |
unsigned char *rp, *wp; |
}; |
static int |
read_aesd(fz_stream *stm, unsigned char *buf, int len) |
{ |
fz_aesd *state = stm->state; |
unsigned char *p = buf; |
unsigned char *ep = buf + len; |
while (state->ivcount < 16) |
{ |
int c = fz_read_byte(state->chain); |
if (c < 0) |
return fz_throw("premature end in aes filter"); |
state->iv[state->ivcount++] = c; |
} |
while (state->rp < state->wp && p < ep) |
*p++ = *state->rp++; |
while (p < ep) |
{ |
int n = fz_read(state->chain, state->bp, 16); |
if (n < 0) |
return fz_rethrow(n, "read error in aes filter"); |
else if (n == 0) |
return p - buf; |
else if (n < 16) |
return fz_throw("partial block in aes filter"); |
aes_crypt_cbc(&state->aes, AES_DECRYPT, 16, state->iv, state->bp, state->bp); |
state->rp = state->bp; |
state->wp = state->bp + 16; |
/* strip padding at end of file */ |
if (fz_is_eof(state->chain)) |
{ |
int pad = state->bp[15]; |
if (pad < 1 || pad > 16) |
return fz_throw("aes padding out of range: %d", pad); |
state->wp -= pad; |
} |
while (state->rp < state->wp && p < ep) |
*p++ = *state->rp++; |
} |
return p - buf; |
} |
static void |
close_aesd(fz_stream *stm) |
{ |
fz_aesd *state = stm->state; |
fz_close(state->chain); |
fz_free(state); |
} |
fz_stream * |
fz_open_aesd(fz_stream *chain, unsigned char *key, unsigned keylen) |
{ |
fz_aesd *state; |
state = fz_malloc(sizeof(fz_aesd)); |
state->chain = chain; |
aes_setkey_dec(&state->aes, key, keylen * 8); |
state->ivcount = 0; |
state->rp = state->bp; |
state->wp = state->bp; |
return fz_new_stream(state, read_aesd, close_aesd); |
} |
/contrib/media/updf/fitz/filt_dctd.c |
---|
0,0 → 1,221 |
#include "fitz.h" |
#include <jpeglib.h> |
#include <setjmp.h> |
typedef struct fz_dctd_s fz_dctd; |
struct fz_dctd_s |
{ |
fz_stream *chain; |
int color_transform; |
int init; |
int stride; |
unsigned char *scanline; |
unsigned char *rp, *wp; |
struct jpeg_decompress_struct cinfo; |
struct jpeg_source_mgr srcmgr; |
struct jpeg_error_mgr errmgr; |
jmp_buf jb; |
char msg[JMSG_LENGTH_MAX]; |
}; |
static void error_exit(j_common_ptr cinfo) |
{ |
fz_dctd *state = cinfo->client_data; |
cinfo->err->format_message(cinfo, state->msg); |
longjmp(state->jb, 1); |
} |
static void init_source(j_decompress_ptr cinfo) |
{ |
/* nothing to do */ |
} |
static void term_source(j_decompress_ptr cinfo) |
{ |
/* nothing to do */ |
} |
static boolean fill_input_buffer(j_decompress_ptr cinfo) |
{ |
struct jpeg_source_mgr *src = cinfo->src; |
fz_dctd *state = cinfo->client_data; |
fz_stream *chain = state->chain; |
chain->rp = chain->wp; |
fz_fill_buffer(chain); |
src->next_input_byte = chain->rp; |
src->bytes_in_buffer = chain->wp - chain->rp; |
if (src->bytes_in_buffer == 0) |
{ |
static unsigned char eoi[2] = { 0xFF, JPEG_EOI }; |
fz_warn("premature end of file in jpeg"); |
src->next_input_byte = eoi; |
src->bytes_in_buffer = 2; |
} |
return 1; |
} |
static void skip_input_data(j_decompress_ptr cinfo, long num_bytes) |
{ |
struct jpeg_source_mgr *src = cinfo->src; |
if (num_bytes > 0) |
{ |
while ((size_t)num_bytes > src->bytes_in_buffer) |
{ |
num_bytes -= src->bytes_in_buffer; |
(void) src->fill_input_buffer(cinfo); |
} |
src->next_input_byte += num_bytes; |
src->bytes_in_buffer -= num_bytes; |
} |
} |
static int |
read_dctd(fz_stream *stm, unsigned char *buf, int len) |
{ |
fz_dctd *state = stm->state; |
j_decompress_ptr cinfo = &state->cinfo; |
unsigned char *p = buf; |
unsigned char *ep = buf + len; |
if (setjmp(state->jb)) |
{ |
if (cinfo->src) |
state->chain->rp = state->chain->wp - cinfo->src->bytes_in_buffer; |
return fz_throw("jpeg error: %s", state->msg); |
} |
if (!state->init) |
{ |
cinfo->client_data = state; |
cinfo->err = &state->errmgr; |
jpeg_std_error(cinfo->err); |
cinfo->err->error_exit = error_exit; |
jpeg_create_decompress(cinfo); |
cinfo->src = &state->srcmgr; |
cinfo->src->init_source = init_source; |
cinfo->src->fill_input_buffer = fill_input_buffer; |
cinfo->src->skip_input_data = skip_input_data; |
cinfo->src->resync_to_restart = jpeg_resync_to_restart; |
cinfo->src->term_source = term_source; |
cinfo->src->next_input_byte = state->chain->rp; |
cinfo->src->bytes_in_buffer = state->chain->wp - state->chain->rp; |
jpeg_read_header(cinfo, 1); |
/* speed up jpeg decoding a bit */ |
cinfo->dct_method = JDCT_FASTEST; |
cinfo->do_fancy_upsampling = FALSE; |
/* default value if ColorTransform is not set */ |
if (state->color_transform == -1) |
{ |
if (state->cinfo.num_components == 3) |
state->color_transform = 1; |
else |
state->color_transform = 0; |
} |
if (cinfo->saw_Adobe_marker) |
state->color_transform = cinfo->Adobe_transform; |
/* Guess the input colorspace, and set output colorspace accordingly */ |
switch (cinfo->num_components) |
{ |
case 3: |
if (state->color_transform) |
cinfo->jpeg_color_space = JCS_YCbCr; |
else |
cinfo->jpeg_color_space = JCS_RGB; |
break; |
case 4: |
if (state->color_transform) |
cinfo->jpeg_color_space = JCS_YCCK; |
else |
cinfo->jpeg_color_space = JCS_CMYK; |
break; |
} |
jpeg_start_decompress(cinfo); |
state->stride = cinfo->output_width * cinfo->output_components; |
state->scanline = fz_malloc(state->stride); |
state->rp = state->scanline; |
state->wp = state->scanline; |
state->init = 1; |
} |
while (state->rp < state->wp && p < ep) |
*p++ = *state->rp++; |
while (p < ep) |
{ |
if (cinfo->output_scanline == cinfo->output_height) |
break; |
if (p + state->stride <= ep) |
{ |
jpeg_read_scanlines(cinfo, &p, 1); |
p += state->stride; |
} |
else |
{ |
jpeg_read_scanlines(cinfo, &state->scanline, 1); |
state->rp = state->scanline; |
state->wp = state->scanline + state->stride; |
} |
while (state->rp < state->wp && p < ep) |
*p++ = *state->rp++; |
} |
return p - buf; |
} |
static void |
close_dctd(fz_stream *stm) |
{ |
fz_dctd *state = stm->state; |
if (setjmp(state->jb)) |
{ |
state->chain->rp = state->chain->wp - state->cinfo.src->bytes_in_buffer; |
fz_warn("jpeg error: %s", state->msg); |
goto skip; |
} |
if (state->init) |
jpeg_finish_decompress(&state->cinfo); |
skip: |
state->chain->rp = state->chain->wp - state->cinfo.src->bytes_in_buffer; |
jpeg_destroy_decompress(&state->cinfo); |
fz_free(state->scanline); |
fz_close(state->chain); |
fz_free(state); |
} |
fz_stream * |
fz_open_dctd(fz_stream *chain, fz_obj *params) |
{ |
fz_dctd *state; |
fz_obj *obj; |
state = fz_malloc(sizeof(fz_dctd)); |
memset(state, 0, sizeof(fz_dctd)); |
state->chain = chain; |
state->color_transform = -1; /* unset */ |
state->init = 0; |
obj = fz_dict_gets(params, "ColorTransform"); |
if (obj) |
state->color_transform = fz_to_int(obj); |
return fz_new_stream(state, read_dctd, close_dctd); |
} |
/contrib/media/updf/fitz/filt_faxd.c |
---|
0,0 → 1,731 |
#include "fitz.h" |
/* Fax G3/G4 decoder */ |
/* TODO: uncompressed */ |
/* |
<raph> the first 2^(initialbits) entries map bit patterns to decodes |
<raph> let's say initial_bits is 8 for the sake of example |
<raph> and that the code is 1001 |
<raph> that means that entries 0x90 .. 0x9f have the entry { val, 4 } |
<raph> because those are all the bytes that start with the code |
<raph> and the 4 is the length of the code |
... if (n_bits > initial_bits) ... |
<raph> anyway, in that case, it basically points to a mini table |
<raph> the n_bits is the maximum length of all codes beginning with that byte |
<raph> so 2^(n_bits - initial_bits) is the size of the mini-table |
<raph> peter came up with this, and it makes sense |
*/ |
typedef struct cfd_node_s cfd_node; |
struct cfd_node_s |
{ |
short val; |
short nbits; |
}; |
enum |
{ |
cfd_white_initial_bits = 8, |
cfd_black_initial_bits = 7, |
cfd_2d_initial_bits = 7, |
cfd_uncompressed_initial_bits = 6 /* must be 6 */ |
}; |
/* non-run codes in tables */ |
enum |
{ |
ERROR = -1, |
ZEROS = -2, /* EOL follows, possibly with more padding first */ |
UNCOMPRESSED = -3 |
}; |
/* semantic codes for cf_2d_decode */ |
enum |
{ |
P = -4, |
H = -5, |
VR3 = 0, |
VR2 = 1, |
VR1 = 2, |
V0 = 3, |
VL1 = 4, |
VL2 = 5, |
VL3 = 6 |
}; |
/* White decoding table. */ |
const cfd_node cf_white_decode[] = { |
{256,12},{272,12},{29,8},{30,8},{45,8},{46,8},{22,7},{22,7}, |
{23,7},{23,7},{47,8},{48,8},{13,6},{13,6},{13,6},{13,6},{20,7}, |
{20,7},{33,8},{34,8},{35,8},{36,8},{37,8},{38,8},{19,7},{19,7}, |
{31,8},{32,8},{1,6},{1,6},{1,6},{1,6},{12,6},{12,6},{12,6},{12,6}, |
{53,8},{54,8},{26,7},{26,7},{39,8},{40,8},{41,8},{42,8},{43,8}, |
{44,8},{21,7},{21,7},{28,7},{28,7},{61,8},{62,8},{63,8},{0,8}, |
{320,8},{384,8},{10,5},{10,5},{10,5},{10,5},{10,5},{10,5},{10,5}, |
{10,5},{11,5},{11,5},{11,5},{11,5},{11,5},{11,5},{11,5},{11,5}, |
{27,7},{27,7},{59,8},{60,8},{288,9},{290,9},{18,7},{18,7},{24,7}, |
{24,7},{49,8},{50,8},{51,8},{52,8},{25,7},{25,7},{55,8},{56,8}, |
{57,8},{58,8},{192,6},{192,6},{192,6},{192,6},{1664,6},{1664,6}, |
{1664,6},{1664,6},{448,8},{512,8},{292,9},{640,8},{576,8},{294,9}, |
{296,9},{298,9},{300,9},{302,9},{256,7},{256,7},{2,4},{2,4},{2,4}, |
{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4},{2,4}, |
{2,4},{2,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4}, |
{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{3,4},{128,5},{128,5},{128,5}, |
{128,5},{128,5},{128,5},{128,5},{128,5},{8,5},{8,5},{8,5},{8,5}, |
{8,5},{8,5},{8,5},{8,5},{9,5},{9,5},{9,5},{9,5},{9,5},{9,5},{9,5}, |
{9,5},{16,6},{16,6},{16,6},{16,6},{17,6},{17,6},{17,6},{17,6}, |
{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4},{4,4}, |
{4,4},{4,4},{4,4},{4,4},{4,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4}, |
{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4}, |
{14,6},{14,6},{14,6},{14,6},{15,6},{15,6},{15,6},{15,6},{64,5}, |
{64,5},{64,5},{64,5},{64,5},{64,5},{64,5},{64,5},{6,4},{6,4}, |
{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4},{6,4}, |
{6,4},{6,4},{6,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4}, |
{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{7,4},{-2,3},{-2,3}, |
{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}, |
{-1,0},{-1,0},{-1,0},{-1,0},{-3,4},{1792,3},{1792,3},{1984,4}, |
{2048,4},{2112,4},{2176,4},{2240,4},{2304,4},{1856,3},{1856,3}, |
{1920,3},{1920,3},{2368,4},{2432,4},{2496,4},{2560,4},{1472,1}, |
{1536,1},{1600,1},{1728,1},{704,1},{768,1},{832,1},{896,1}, |
{960,1},{1024,1},{1088,1},{1152,1},{1216,1},{1280,1},{1344,1}, |
{1408,1} |
}; |
/* Black decoding table. */ |
const cfd_node cf_black_decode[] = { |
{128,12},{160,13},{224,12},{256,12},{10,7},{11,7},{288,12},{12,7}, |
{9,6},{9,6},{8,6},{8,6},{7,5},{7,5},{7,5},{7,5},{6,4},{6,4},{6,4}, |
{6,4},{6,4},{6,4},{6,4},{6,4},{5,4},{5,4},{5,4},{5,4},{5,4},{5,4}, |
{5,4},{5,4},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3}, |
{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{1,3},{4,3},{4,3},{4,3},{4,3}, |
{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3}, |
{4,3},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2}, |
{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2}, |
{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2},{3,2}, |
{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2}, |
{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2}, |
{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2},{2,2}, |
{-2,4},{-2,4},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}, |
{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-3,5},{1792,4}, |
{1792,4},{1984,5},{2048,5},{2112,5},{2176,5},{2240,5},{2304,5}, |
{1856,4},{1856,4},{1920,4},{1920,4},{2368,5},{2432,5},{2496,5}, |
{2560,5},{18,3},{18,3},{18,3},{18,3},{18,3},{18,3},{18,3},{18,3}, |
{52,5},{52,5},{640,6},{704,6},{768,6},{832,6},{55,5},{55,5}, |
{56,5},{56,5},{1280,6},{1344,6},{1408,6},{1472,6},{59,5},{59,5}, |
{60,5},{60,5},{1536,6},{1600,6},{24,4},{24,4},{24,4},{24,4}, |
{25,4},{25,4},{25,4},{25,4},{1664,6},{1728,6},{320,5},{320,5}, |
{384,5},{384,5},{448,5},{448,5},{512,6},{576,6},{53,5},{53,5}, |
{54,5},{54,5},{896,6},{960,6},{1024,6},{1088,6},{1152,6},{1216,6}, |
{64,3},{64,3},{64,3},{64,3},{64,3},{64,3},{64,3},{64,3},{13,1}, |
{13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{13,1}, |
{13,1},{13,1},{13,1},{13,1},{13,1},{13,1},{23,4},{23,4},{50,5}, |
{51,5},{44,5},{45,5},{46,5},{47,5},{57,5},{58,5},{61,5},{256,5}, |
{16,3},{16,3},{16,3},{16,3},{17,3},{17,3},{17,3},{17,3},{48,5}, |
{49,5},{62,5},{63,5},{30,5},{31,5},{32,5},{33,5},{40,5},{41,5}, |
{22,4},{22,4},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1}, |
{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1},{14,1}, |
{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{15,2},{128,5}, |
{192,5},{26,5},{27,5},{28,5},{29,5},{19,4},{19,4},{20,4},{20,4}, |
{34,5},{35,5},{36,5},{37,5},{38,5},{39,5},{21,4},{21,4},{42,5}, |
{43,5},{0,3},{0,3},{0,3},{0,3} |
}; |
/* 2-D decoding table. */ |
const cfd_node cf_2d_decode[] = { |
{128,11},{144,10},{6,7},{0,7},{5,6},{5,6},{1,6},{1,6},{-4,4}, |
{-4,4},{-4,4},{-4,4},{-4,4},{-4,4},{-4,4},{-4,4},{-5,3},{-5,3}, |
{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{-5,3}, |
{-5,3},{-5,3},{-5,3},{-5,3},{-5,3},{4,3},{4,3},{4,3},{4,3},{4,3}, |
{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3},{4,3}, |
{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{2,3}, |
{2,3},{2,3},{2,3},{2,3},{2,3},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1},{3,1}, |
{3,1},{3,1},{3,1},{-2,4},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}, |
{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0}, |
{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-1,0},{-3,3} |
}; |
/* Uncompresssed decoding table. */ |
const cfd_node cf_uncompressed_decode[] = { |
{64,12},{5,6},{4,5},{4,5},{3,4},{3,4},{3,4},{3,4},{2,3},{2,3}, |
{2,3},{2,3},{2,3},{2,3},{2,3},{2,3},{1,2},{1,2},{1,2},{1,2},{1,2}, |
{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2}, |
{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1}, |
{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1}, |
{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1},{0,1}, |
{-1,0},{-1,0},{8,6},{9,6},{6,5},{6,5},{7,5},{7,5},{4,4},{4,4}, |
{4,4},{4,4},{5,4},{5,4},{5,4},{5,4},{2,3},{2,3},{2,3},{2,3},{2,3}, |
{2,3},{2,3},{2,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3},{3,3}, |
{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2},{0,2}, |
{0,2},{0,2},{0,2},{0,2},{0,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2}, |
{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2},{1,2} |
}; |
/* bit magic */ |
static inline int getbit(const unsigned char *buf, int x) |
{ |
return ( buf[x >> 3] >> ( 7 - (x & 7) ) ) & 1; |
} |
static int |
find_changing(const unsigned char *line, int x, int w) |
{ |
int a, b; |
if (!line) |
return w; |
if (x == -1) |
{ |
a = 0; |
x = 0; |
} |
else |
{ |
a = getbit(line, x); |
x++; |
} |
while (x < w) |
{ |
b = getbit(line, x); |
if (a != b) |
break; |
x++; |
} |
return x; |
} |
static int |
find_changing_color(const unsigned char *line, int x, int w, int color) |
{ |
if (!line) |
return w; |
x = find_changing(line, x, w); |
if (x < w && getbit(line, x) != color) |
x = find_changing(line, x, w); |
return x; |
} |
static const unsigned char lm[8] = { |
0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01 |
}; |
static const unsigned char rm[8] = { |
0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE |
}; |
static inline void setbits(unsigned char *line, int x0, int x1) |
{ |
int a0, a1, b0, b1, a; |
a0 = x0 >> 3; |
a1 = x1 >> 3; |
b0 = x0 & 7; |
b1 = x1 & 7; |
if (a0 == a1) |
{ |
if (b1) |
line[a0] |= lm[b0] & rm[b1]; |
} |
else |
{ |
line[a0] |= lm[b0]; |
for (a = a0 + 1; a < a1; a++) |
line[a] = 0xFF; |
if (b1) |
line[a1] |= rm[b1]; |
} |
} |
typedef struct fz_faxd_s fz_faxd; |
enum |
{ |
STATE_NORMAL, /* neutral state, waiting for any code */ |
STATE_MAKEUP, /* got a 1d makeup code, waiting for terminating code */ |
STATE_EOL, /* at eol, needs output buffer space */ |
STATE_H1, STATE_H2, /* in H part 1 and 2 (both makeup and terminating codes) */ |
STATE_DONE /* all done */ |
}; |
struct fz_faxd_s |
{ |
fz_stream *chain; |
int k; |
int end_of_line; |
int encoded_byte_align; |
int columns; |
int rows; |
int end_of_block; |
int black_is_1; |
int stride; |
int ridx; |
int bidx; |
unsigned int word; |
int stage; |
int a, c, dim, eolc; |
unsigned char *ref; |
unsigned char *dst; |
unsigned char *rp, *wp; |
}; |
static inline void eat_bits(fz_faxd *fax, int nbits) |
{ |
fax->word <<= nbits; |
fax->bidx += nbits; |
} |
static int |
fill_bits(fz_faxd *fax) |
{ |
while (fax->bidx >= 8) |
{ |
int c = fz_read_byte(fax->chain); |
if (c == EOF) |
return EOF; |
fax->bidx -= 8; |
fax->word |= c << fax->bidx; |
} |
return 0; |
} |
static int |
get_code(fz_faxd *fax, const cfd_node *table, int initialbits) |
{ |
unsigned int word = fax->word; |
int tidx = word >> (32 - initialbits); |
int val = table[tidx].val; |
int nbits = table[tidx].nbits; |
if (nbits > initialbits) |
{ |
int mask = (1 << (32 - initialbits)) - 1; |
tidx = val + ((word & mask) >> (32 - nbits)); |
val = table[tidx].val; |
nbits = initialbits + table[tidx].nbits; |
} |
eat_bits(fax, nbits); |
return val; |
} |
/* decode one 1d code */ |
static fz_error |
dec1d(fz_faxd *fax) |
{ |
int code; |
if (fax->a == -1) |
fax->a = 0; |
if (fax->c) |
code = get_code(fax, cf_black_decode, cfd_black_initial_bits); |
else |
code = get_code(fax, cf_white_decode, cfd_white_initial_bits); |
if (code == UNCOMPRESSED) |
return fz_throw("uncompressed data in faxd"); |
if (code < 0) |
return fz_throw("negative code in 1d faxd"); |
if (fax->a + code > fax->columns) |
return fz_throw("overflow in 1d faxd"); |
if (fax->c) |
setbits(fax->dst, fax->a, fax->a + code); |
fax->a += code; |
if (code < 64) |
{ |
fax->c = !fax->c; |
fax->stage = STATE_NORMAL; |
} |
else |
fax->stage = STATE_MAKEUP; |
return fz_okay; |
} |
/* decode one 2d code */ |
static fz_error |
dec2d(fz_faxd *fax) |
{ |
int code, b1, b2; |
if (fax->stage == STATE_H1 || fax->stage == STATE_H2) |
{ |
if (fax->a == -1) |
fax->a = 0; |
if (fax->c) |
code = get_code(fax, cf_black_decode, cfd_black_initial_bits); |
else |
code = get_code(fax, cf_white_decode, cfd_white_initial_bits); |
if (code == UNCOMPRESSED) |
return fz_throw("uncompressed data in faxd"); |
if (code < 0) |
return fz_throw("negative code in 2d faxd"); |
if (fax->a + code > fax->columns) |
return fz_throw("overflow in 2d faxd"); |
if (fax->c) |
setbits(fax->dst, fax->a, fax->a + code); |
fax->a += code; |
if (code < 64) |
{ |
fax->c = !fax->c; |
if (fax->stage == STATE_H1) |
fax->stage = STATE_H2; |
else if (fax->stage == STATE_H2) |
fax->stage = STATE_NORMAL; |
} |
return fz_okay; |
} |
code = get_code(fax, cf_2d_decode, cfd_2d_initial_bits); |
switch (code) |
{ |
case H: |
fax->stage = STATE_H1; |
break; |
case P: |
b1 = find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
if (b1 >= fax->columns) |
b2 = fax->columns; |
else |
b2 = find_changing(fax->ref, b1, fax->columns); |
if (fax->c) setbits(fax->dst, fax->a, b2); |
fax->a = b2; |
break; |
case V0: |
b1 = find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
if (fax->c) setbits(fax->dst, fax->a, b1); |
fax->a = b1; |
fax->c = !fax->c; |
break; |
case VR1: |
b1 = 1 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
if (b1 >= fax->columns) b1 = fax->columns; |
if (fax->c) setbits(fax->dst, fax->a, b1); |
fax->a = b1; |
fax->c = !fax->c; |
break; |
case VR2: |
b1 = 2 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
if (b1 >= fax->columns) b1 = fax->columns; |
if (fax->c) setbits(fax->dst, fax->a, b1); |
fax->a = b1; |
fax->c = !fax->c; |
break; |
case VR3: |
b1 = 3 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
if (b1 >= fax->columns) b1 = fax->columns; |
if (fax->c) setbits(fax->dst, fax->a, b1); |
fax->a = b1; |
fax->c = !fax->c; |
break; |
case VL1: |
b1 = -1 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
if (b1 < 0) b1 = 0; |
if (fax->c) setbits(fax->dst, fax->a, b1); |
fax->a = b1; |
fax->c = !fax->c; |
break; |
case VL2: |
b1 = -2 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
if (b1 < 0) b1 = 0; |
if (fax->c) setbits(fax->dst, fax->a, b1); |
fax->a = b1; |
fax->c = !fax->c; |
break; |
case VL3: |
b1 = -3 + find_changing_color(fax->ref, fax->a, fax->columns, !fax->c); |
if (b1 < 0) b1 = 0; |
if (fax->c) setbits(fax->dst, fax->a, b1); |
fax->a = b1; |
fax->c = !fax->c; |
break; |
case UNCOMPRESSED: |
return fz_throw("uncompressed data in faxd"); |
case ERROR: |
return fz_throw("invalid code in 2d faxd"); |
default: |
return fz_throw("invalid code in 2d faxd (%d)", code); |
} |
return 0; |
} |
static int |
read_faxd(fz_stream *stm, unsigned char *buf, int len) |
{ |
fz_faxd *fax = stm->state; |
unsigned char *p = buf; |
unsigned char *ep = buf + len; |
unsigned char *tmp; |
fz_error error; |
if (fax->stage == STATE_DONE) |
return 0; |
if (fax->stage == STATE_EOL) |
goto eol; |
loop: |
if (fill_bits(fax)) |
{ |
if (fax->bidx > 31) |
{ |
if (fax->a > 0) |
goto eol; |
goto rtc; |
} |
} |
if ((fax->word >> (32 - 12)) == 0) |
{ |
eat_bits(fax, 1); |
goto loop; |
} |
if ((fax->word >> (32 - 12)) == 1) |
{ |
eat_bits(fax, 12); |
fax->eolc ++; |
if (fax->k > 0) |
{ |
if (fax->a == -1) |
fax->a = 0; |
if ((fax->word >> (32 - 1)) == 1) |
fax->dim = 1; |
else |
fax->dim = 2; |
eat_bits(fax, 1); |
} |
} |
else if (fax->k > 0 && fax->a == -1) |
{ |
fax->a = 0; |
if ((fax->word >> (32 - 1)) == 1) |
fax->dim = 1; |
else |
fax->dim = 2; |
eat_bits(fax, 1); |
} |
else if (fax->dim == 1) |
{ |
fax->eolc = 0; |
error = dec1d(fax); |
if (error) |
return fz_rethrow(error, "cannot decode 1d code"); |
} |
else if (fax->dim == 2) |
{ |
fax->eolc = 0; |
error = dec2d(fax); |
if (error) |
return fz_rethrow(error, "cannot decode 2d code"); |
} |
/* no eol check after makeup codes nor in the middle of an H code */ |
if (fax->stage == STATE_MAKEUP || fax->stage == STATE_H1 || fax->stage == STATE_H2) |
goto loop; |
/* check for eol conditions */ |
if (fax->eolc || fax->a >= fax->columns) |
{ |
if (fax->a > 0) |
goto eol; |
if (fax->eolc == (fax->k < 0 ? 2 : 6)) |
goto rtc; |
} |
goto loop; |
eol: |
fax->stage = STATE_EOL; |
if (fax->black_is_1) |
{ |
while (fax->rp < fax->wp && p < ep) |
*p++ = *fax->rp++; |
} |
else |
{ |
while (fax->rp < fax->wp && p < ep) |
*p++ = *fax->rp++ ^ 0xff; |
} |
if (fax->rp < fax->wp) |
return p - buf; |
tmp = fax->ref; |
fax->ref = fax->dst; |
fax->dst = tmp; |
memset(fax->dst, 0, fax->stride); |
fax->rp = fax->dst; |
fax->wp = fax->dst + fax->stride; |
fax->stage = STATE_NORMAL; |
fax->c = 0; |
fax->a = -1; |
fax->ridx ++; |
if (!fax->end_of_block && fax->rows) |
{ |
if (fax->ridx >= fax->rows) |
goto rtc; |
} |
/* we have not read dim from eol, make a guess */ |
if (fax->k > 0 && !fax->eolc && fax->a == -1) |
{ |
if (fax->ridx % fax->k == 0) |
fax->dim = 1; |
else |
fax->dim = 2; |
} |
/* if end_of_line & encoded_byte_align, EOLs are *not* optional */ |
if (fax->encoded_byte_align) |
{ |
if (fax->end_of_line) |
eat_bits(fax, (12 - fax->bidx) & 7); |
else |
eat_bits(fax, (8 - fax->bidx) & 7); |
} |
/* no more space in output, don't decode the next row yet */ |
if (p == buf + len) |
return p - buf; |
goto loop; |
rtc: |
fax->stage = STATE_DONE; |
return p - buf; |
} |
static void |
close_faxd(fz_stream *stm) |
{ |
fz_faxd *fax = stm->state; |
int i; |
/* if we read any extra bytes, try to put them back */ |
i = (32 - fax->bidx) / 8; |
while (i--) |
fz_unread_byte(fax->chain); |
fz_close(fax->chain); |
fz_free(fax->ref); |
fz_free(fax->dst); |
fz_free(fax); |
} |
fz_stream * |
fz_open_faxd(fz_stream *chain, fz_obj *params) |
{ |
fz_faxd *fax; |
fz_obj *obj; |
fax = fz_malloc(sizeof(fz_faxd)); |
fax->chain = chain; |
fax->ref = NULL; |
fax->dst = NULL; |
fax->k = 0; |
fax->end_of_line = 0; |
fax->encoded_byte_align = 0; |
fax->columns = 1728; |
fax->rows = 0; |
fax->end_of_block = 1; |
fax->black_is_1 = 0; |
obj = fz_dict_gets(params, "K"); |
if (obj) fax->k = fz_to_int(obj); |
obj = fz_dict_gets(params, "EndOfLine"); |
if (obj) fax->end_of_line = fz_to_bool(obj); |
obj = fz_dict_gets(params, "EncodedByteAlign"); |
if (obj) fax->encoded_byte_align = fz_to_bool(obj); |
obj = fz_dict_gets(params, "Columns"); |
if (obj) fax->columns = fz_to_int(obj); |
obj = fz_dict_gets(params, "Rows"); |
if (obj) fax->rows = fz_to_int(obj); |
obj = fz_dict_gets(params, "EndOfBlock"); |
if (obj) fax->end_of_block = fz_to_bool(obj); |
obj = fz_dict_gets(params, "BlackIs1"); |
if (obj) fax->black_is_1 = fz_to_bool(obj); |
fax->stride = ((fax->columns - 1) >> 3) + 1; |
fax->ridx = 0; |
fax->bidx = 32; |
fax->word = 0; |
fax->stage = STATE_NORMAL; |
fax->a = -1; |
fax->c = 0; |
fax->dim = fax->k < 0 ? 2 : 1; |
fax->eolc = 0; |
fax->ref = fz_malloc(fax->stride); |
fax->dst = fz_malloc(fax->stride); |
fax->rp = fax->dst; |
fax->wp = fax->dst + fax->stride; |
memset(fax->ref, 0, fax->stride); |
memset(fax->dst, 0, fax->stride); |
return fz_new_stream(fax, read_faxd, close_faxd); |
} |
/contrib/media/updf/fitz/filt_flate.c |
---|
0,0 → 1,103 |
#include "fitz.h" |
#include <zlib.h> |
typedef struct fz_flate_s fz_flate; |
struct fz_flate_s |
{ |
fz_stream *chain; |
z_stream z; |
}; |
static void *zalloc(void *opaque, unsigned int items, unsigned int size) |
{ |
return fz_calloc(items, size); |
} |
static void zfree(void *opaque, void *ptr) |
{ |
fz_free(ptr); |
} |
static int |
read_flated(fz_stream *stm, unsigned char *outbuf, int outlen) |
{ |
fz_flate *state = stm->state; |
fz_stream *chain = state->chain; |
z_streamp zp = &state->z; |
int code; |
zp->next_out = outbuf; |
zp->avail_out = outlen; |
while (zp->avail_out > 0) |
{ |
if (chain->rp == chain->wp) |
fz_fill_buffer(chain); |
zp->next_in = chain->rp; |
zp->avail_in = chain->wp - chain->rp; |
code = inflate(zp, Z_SYNC_FLUSH); |
chain->rp = chain->wp - zp->avail_in; |
if (code == Z_STREAM_END) |
{ |
return outlen - zp->avail_out; |
} |
else if (code == Z_BUF_ERROR) |
{ |
fz_warn("premature end of data in flate filter"); |
return outlen - zp->avail_out; |
} |
else if (code == Z_DATA_ERROR && zp->avail_in == 0) |
{ |
fz_warn("ignoring zlib error: %s", zp->msg); |
return outlen - zp->avail_out; |
} |
else if (code != Z_OK) |
{ |
return fz_throw("zlib error: %s", zp->msg); |
} |
} |
return outlen - zp->avail_out; |
} |
static void |
close_flated(fz_stream *stm) |
{ |
fz_flate *state = stm->state; |
int code; |
code = inflateEnd(&state->z); |
if (code != Z_OK) |
fz_warn("zlib error: inflateEnd: %s", state->z.msg); |
fz_close(state->chain); |
fz_free(state); |
} |
fz_stream * |
fz_open_flated(fz_stream *chain) |
{ |
fz_flate *state; |
int code; |
state = fz_malloc(sizeof(fz_flate)); |
state->chain = chain; |
state->z.zalloc = zalloc; |
state->z.zfree = zfree; |
state->z.opaque = NULL; |
state->z.next_in = NULL; |
state->z.avail_in = 0; |
code = inflateInit(&state->z); |
if (code != Z_OK) |
fz_warn("zlib error: inflateInit: %s", state->z.msg); |
return fz_new_stream(state, read_flated, close_flated); |
} |
/contrib/media/updf/fitz/filt_jbig2d.c |
---|
0,0 → 1,103 |
#include "fitz.h" |
#ifdef _WIN32 /* Microsoft Visual C++ */ |
typedef signed char int8_t; |
typedef short int int16_t; |
typedef int int32_t; |
typedef __int64 int64_t; |
typedef unsigned char uint8_t; |
typedef unsigned short int uint16_t; |
typedef unsigned int uint32_t; |
#else |
#include <inttypes.h> |
#endif |
#include <jbig2.h> |
typedef struct fz_jbig2d_s fz_jbig2d; |
struct fz_jbig2d_s |
{ |
fz_stream *chain; |
Jbig2Ctx *ctx; |
Jbig2GlobalCtx *gctx; |
Jbig2Image *page; |
int idx; |
}; |
static void |
close_jbig2d(fz_stream *stm) |
{ |
fz_jbig2d *state = stm->state; |
if (state->page) |
jbig2_release_page(state->ctx, state->page); |
if (state->gctx) |
jbig2_global_ctx_free(state->gctx); |
jbig2_ctx_free(state->ctx); |
fz_close(state->chain); |
fz_free(state); |
} |
static int |
read_jbig2d(fz_stream *stm, unsigned char *buf, int len) |
{ |
fz_jbig2d *state = stm->state; |
unsigned char tmp[4096]; |
unsigned char *p = buf; |
unsigned char *ep = buf + len; |
unsigned char *s; |
int x, w, n; |
if (!state->page) |
{ |
while (1) |
{ |
n = fz_read(state->chain, tmp, sizeof tmp); |
if (n < 0) |
return fz_rethrow(n, "read error in jbig2 filter"); |
if (n == 0) |
break; |
jbig2_data_in(state->ctx, tmp, n); |
} |
jbig2_complete_page(state->ctx); |
state->page = jbig2_page_out(state->ctx); |
if (!state->page) |
return fz_throw("jbig2_page_out failed"); |
} |
s = state->page->data; |
w = state->page->height * state->page->stride; |
x = state->idx; |
while (p < ep && x < w) |
*p++ = s[x++] ^ 0xff; |
state->idx = x; |
return p - buf; |
} |
fz_stream * |
fz_open_jbig2d(fz_stream *chain, fz_buffer *globals) |
{ |
fz_jbig2d *state; |
state = fz_malloc(sizeof(fz_jbig2d)); |
state->chain = chain; |
state->ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, NULL, NULL, NULL); |
state->gctx = NULL; |
state->page = NULL; |
state->idx = 0; |
if (globals) |
{ |
jbig2_data_in(state->ctx, globals->data, globals->len); |
state->gctx = jbig2_make_global_ctx(state->ctx); |
state->ctx = jbig2_ctx_new(NULL, JBIG2_OPTIONS_EMBEDDED, state->gctx, NULL, NULL); |
} |
return fz_new_stream(state, read_jbig2d, close_jbig2d); |
} |
/contrib/media/updf/fitz/filt_jpxd.c |
---|
0,0 → 1,153 |
#include "fitz.h" |
#define OPJ_STATIC |
#include <openjpeg.h> |
static void fz_opj_error_callback(const char *msg, void *client_data) |
{ |
fprintf(stderr, "openjpeg error: %s", msg); |
} |
static void fz_opj_warning_callback(const char *msg, void *client_data) |
{ |
fprintf(stderr, "openjpeg warning: %s", msg); |
} |
static void fz_opj_info_callback(const char *msg, void *client_data) |
{ |
/* fprintf(stderr, "openjpeg info: %s", msg); */ |
} |
fz_error |
fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace *defcs) |
{ |
fz_pixmap *img; |
opj_event_mgr_t evtmgr; |
opj_dparameters_t params; |
opj_dinfo_t *info; |
opj_cio_t *cio; |
opj_image_t *jpx; |
fz_colorspace *colorspace; |
unsigned char *p; |
int format; |
int a, n, w, h, depth, sgnd; |
int x, y, k, v; |
if (size < 2) |
return fz_throw("not enough data to determine image format"); |
/* Check for SOC marker -- if found we have a bare J2K stream */ |
if (data[0] == 0xFF && data[1] == 0x4F) |
format = CODEC_J2K; |
else |
format = CODEC_JP2; |
memset(&evtmgr, 0, sizeof(evtmgr)); |
evtmgr.error_handler = fz_opj_error_callback; |
evtmgr.warning_handler = fz_opj_warning_callback; |
evtmgr.info_handler = fz_opj_info_callback; |
opj_set_default_decoder_parameters(¶ms); |
info = opj_create_decompress(format); |
opj_set_event_mgr((opj_common_ptr)info, &evtmgr, stderr); |
opj_setup_decoder(info, ¶ms); |
cio = opj_cio_open((opj_common_ptr)info, data, size); |
jpx = opj_decode(info, cio); |
opj_cio_close(cio); |
opj_destroy_decompress(info); |
if (!jpx) |
return fz_throw("opj_decode failed"); |
for (k = 1; k < jpx->numcomps; k++) |
{ |
if (jpx->comps[k].w != jpx->comps[0].w) |
return fz_throw("image components have different width"); |
if (jpx->comps[k].h != jpx->comps[0].h) |
return fz_throw("image components have different height"); |
if (jpx->comps[k].prec != jpx->comps[0].prec) |
return fz_throw("image components have different precision"); |
} |
n = jpx->numcomps; |
w = jpx->comps[0].w; |
h = jpx->comps[0].h; |
depth = jpx->comps[0].prec; |
sgnd = jpx->comps[0].sgnd; |
if (jpx->color_space == CLRSPC_SRGB && n == 4) { n = 3; a = 1; } |
else if (jpx->color_space == CLRSPC_SYCC && n == 4) { n = 3; a = 1; } |
else if (n == 2) { n = 1; a = 1; } |
else if (n > 4) { n = 4; a = 1; } |
else { a = 0; } |
if (defcs) |
{ |
if (defcs->n == n) |
{ |
colorspace = defcs; |
} |
else |
{ |
fz_warn("jpx file and dict colorspaces do not match"); |
defcs = NULL; |
} |
} |
if (!defcs) |
{ |
switch (n) |
{ |
case 1: colorspace = fz_device_gray; break; |
case 3: colorspace = fz_device_rgb; break; |
case 4: colorspace = fz_device_cmyk; break; |
} |
} |
img = fz_new_pixmap_with_limit(colorspace, w, h); |
if (!img) |
{ |
opj_image_destroy(jpx); |
return fz_throw("out of memory"); |
} |
p = img->samples; |
for (y = 0; y < h; y++) |
{ |
for (x = 0; x < w; x++) |
{ |
for (k = 0; k < n + a; k++) |
{ |
v = jpx->comps[k].data[y * w + x]; |
if (sgnd) |
v = v + (1 << (depth - 1)); |
if (depth > 8) |
v = v >> (depth - 8); |
*p++ = v; |
} |
if (!a) |
*p++ = 255; |
} |
} |
if (a) |
{ |
if (n == 4) |
{ |
fz_pixmap *tmp = fz_new_pixmap(fz_device_rgb, w, h); |
fz_convert_pixmap(img, tmp); |
fz_drop_pixmap(img); |
img = tmp; |
} |
fz_premultiply_pixmap(img); |
} |
opj_image_destroy(jpx); |
*imgp = img; |
return fz_okay; |
} |
/contrib/media/updf/fitz/filt_lzwd.c |
---|
0,0 → 1,206 |
#include "fitz.h" |
/* TODO: error checking */ |
enum |
{ |
MIN_BITS = 9, |
MAX_BITS = 12, |
NUM_CODES = (1 << MAX_BITS), |
LZW_CLEAR = 256, |
LZW_EOD = 257, |
LZW_FIRST = 258, |
MAX_LENGTH = 4097 |
}; |
typedef struct lzw_code_s lzw_code; |
struct lzw_code_s |
{ |
int prev; /* prev code (in string) */ |
unsigned short length; /* string len, including this token */ |
unsigned char value; /* data value */ |
unsigned char first_char; /* first token of string */ |
}; |
typedef struct fz_lzwd_s fz_lzwd; |
struct fz_lzwd_s |
{ |
fz_stream *chain; |
int eod; |
int early_change; |
int code_bits; /* num bits/code */ |
int code; /* current code */ |
int old_code; /* previously recognized code */ |
int next_code; /* next free entry */ |
lzw_code table[NUM_CODES]; |
unsigned char bp[MAX_LENGTH]; |
unsigned char *rp, *wp; |
}; |
static int |
read_lzwd(fz_stream *stm, unsigned char *buf, int len) |
{ |
fz_lzwd *lzw = stm->state; |
lzw_code *table = lzw->table; |
unsigned char *p = buf; |
unsigned char *ep = buf + len; |
unsigned char *s; |
int codelen; |
int code_bits = lzw->code_bits; |
int code = lzw->code; |
int old_code = lzw->old_code; |
int next_code = lzw->next_code; |
while (lzw->rp < lzw->wp && p < ep) |
*p++ = *lzw->rp++; |
while (p < ep) |
{ |
if (lzw->eod) |
return 0; |
code = fz_read_bits(lzw->chain, code_bits); |
if (fz_is_eof_bits(lzw->chain)) |
{ |
lzw->eod = 1; |
break; |
} |
if (code == LZW_EOD) |
{ |
lzw->eod = 1; |
break; |
} |
if (code == LZW_CLEAR) |
{ |
code_bits = MIN_BITS; |
next_code = LZW_FIRST; |
old_code = -1; |
continue; |
} |
/* if stream starts without a clear code, old_code is undefined... */ |
if (old_code == -1) |
{ |
old_code = code; |
} |
else |
{ |
/* add new entry to the code table */ |
table[next_code].prev = old_code; |
table[next_code].first_char = table[old_code].first_char; |
table[next_code].length = table[old_code].length + 1; |
if (code < next_code) |
table[next_code].value = table[code].first_char; |
else if (code == next_code) |
table[next_code].value = table[next_code].first_char; |
else |
fz_warn("out of range code encountered in lzw decode"); |
next_code ++; |
if (next_code > (1 << code_bits) - lzw->early_change - 1) |
{ |
code_bits ++; |
if (code_bits > MAX_BITS) |
code_bits = MAX_BITS; /* FIXME */ |
} |
old_code = code; |
} |
/* code maps to a string, copy to output (in reverse...) */ |
if (code > 255) |
{ |
codelen = table[code].length; |
lzw->rp = lzw->bp; |
lzw->wp = lzw->bp + codelen; |
assert(codelen < MAX_LENGTH); |
s = lzw->wp; |
do { |
*(--s) = table[code].value; |
code = table[code].prev; |
} while (code >= 0 && s > lzw->bp); |
} |
/* ... or just a single character */ |
else |
{ |
lzw->bp[0] = code; |
lzw->rp = lzw->bp; |
lzw->wp = lzw->bp + 1; |
} |
/* copy to output */ |
while (lzw->rp < lzw->wp && p < ep) |
*p++ = *lzw->rp++; |
} |
lzw->code_bits = code_bits; |
lzw->code = code; |
lzw->old_code = old_code; |
lzw->next_code = next_code; |
return p - buf; |
} |
static void |
close_lzwd(fz_stream *stm) |
{ |
fz_lzwd *lzw = stm->state; |
fz_close(lzw->chain); |
fz_free(lzw); |
} |
fz_stream * |
fz_open_lzwd(fz_stream *chain, fz_obj *params) |
{ |
fz_lzwd *lzw; |
fz_obj *obj; |
int i; |
lzw = fz_malloc(sizeof(fz_lzwd)); |
lzw->chain = chain; |
lzw->eod = 0; |
lzw->early_change = 1; |
obj = fz_dict_gets(params, "EarlyChange"); |
if (obj) |
lzw->early_change = !!fz_to_int(obj); |
for (i = 0; i < 256; i++) |
{ |
lzw->table[i].value = i; |
lzw->table[i].first_char = i; |
lzw->table[i].length = 1; |
lzw->table[i].prev = -1; |
} |
for (i = 256; i < NUM_CODES; i++) |
{ |
lzw->table[i].value = 0; |
lzw->table[i].first_char = 0; |
lzw->table[i].length = 0; |
lzw->table[i].prev = -1; |
} |
lzw->code_bits = MIN_BITS; |
lzw->code = -1; |
lzw->next_code = LZW_FIRST; |
lzw->old_code = -1; |
lzw->rp = lzw->bp; |
lzw->wp = lzw->bp; |
return fz_new_stream(lzw, read_lzwd, close_lzwd); |
} |
/contrib/media/updf/fitz/filt_predict.c |
---|
0,0 → 1,243 |
#include "fitz.h" |
/* TODO: check if this works with 16bpp images */ |
enum { MAXC = 32 }; |
typedef struct fz_predict_s fz_predict; |
struct fz_predict_s |
{ |
fz_stream *chain; |
int predictor; |
int columns; |
int colors; |
int bpc; |
int stride; |
int bpp; |
unsigned char *in; |
unsigned char *out; |
unsigned char *ref; |
unsigned char *rp, *wp; |
}; |
static inline int getcomponent(unsigned char *line, int x, int bpc) |
{ |
switch (bpc) |
{ |
case 1: return (line[x >> 3] >> ( 7 - (x & 7) ) ) & 1; |
case 2: return (line[x >> 2] >> ( ( 3 - (x & 3) ) << 1 ) ) & 3; |
case 4: return (line[x >> 1] >> ( ( 1 - (x & 1) ) << 2 ) ) & 15; |
case 8: return line[x]; |
} |
return 0; |
} |
static inline void putcomponent(unsigned char *buf, int x, int bpc, int value) |
{ |
switch (bpc) |
{ |
case 1: buf[x >> 3] |= value << (7 - (x & 7)); break; |
case 2: buf[x >> 2] |= value << ((3 - (x & 3)) << 1); break; |
case 4: buf[x >> 1] |= value << ((1 - (x & 1)) << 2); break; |
case 8: buf[x] = value; break; |
} |
} |
static inline int paeth(int a, int b, int c) |
{ |
/* The definitions of ac and bc are correct, not a typo. */ |
int ac = b - c, bc = a - c, abcc = ac + bc; |
int pa = ABS(ac); |
int pb = ABS(bc); |
int pc = ABS(abcc); |
return pa <= pb && pa <= pc ? a : pb <= pc ? b : c; |
} |
static void |
fz_predict_tiff(fz_predict *state, unsigned char *out, unsigned char *in, int len) |
{ |
int left[MAXC]; |
int i, k; |
for (k = 0; k < state->colors; k++) |
left[k] = 0; |
for (i = 0; i < state->columns; i++) |
{ |
for (k = 0; k < state->colors; k++) |
{ |
int a = getcomponent(in, i * state->colors + k, state->bpc); |
int b = a + left[k]; |
int c = b % (1 << state->bpc); |
putcomponent(out, i * state->colors + k, state->bpc, c); |
left[k] = c; |
} |
} |
} |
static void |
fz_predict_png(fz_predict *state, unsigned char *out, unsigned char *in, int len, int predictor) |
{ |
int bpp = state->bpp; |
int i; |
unsigned char *ref = state->ref; |
switch (predictor) |
{ |
case 0: |
memcpy(out, in, len); |
break; |
case 1: |
for (i = bpp; i > 0; i--) |
{ |
*out++ = *in++; |
} |
for (i = len - bpp; i > 0; i--) |
{ |
*out = *in++ + out[-bpp]; |
out++; |
} |
break; |
case 2: |
for (i = bpp; i > 0; i--) |
{ |
*out++ = *in++ + *ref++; |
} |
for (i = len - bpp; i > 0; i--) |
{ |
*out++ = *in++ + *ref++; |
} |
break; |
case 3: |
for (i = bpp; i > 0; i--) |
{ |
*out++ = *in++ + (*ref++) / 2; |
} |
for (i = len - bpp; i > 0; i--) |
{ |
*out = *in++ + (out[-bpp] + *ref++) / 2; |
out++; |
} |
break; |
case 4: |
for (i = bpp; i > 0; i--) |
{ |
*out++ = *in++ + paeth(0, *ref++, 0); |
} |
for (i = len - bpp; i > 0; i --) |
{ |
*out = *in++ + paeth(out[-bpp], *ref, ref[-bpp]); |
ref++; |
out++; |
} |
break; |
} |
} |
static int |
read_predict(fz_stream *stm, unsigned char *buf, int len) |
{ |
fz_predict *state = stm->state; |
unsigned char *p = buf; |
unsigned char *ep = buf + len; |
int ispng = state->predictor >= 10; |
int n; |
while (state->rp < state->wp && p < ep) |
*p++ = *state->rp++; |
while (p < ep) |
{ |
n = fz_read(state->chain, state->in, state->stride + ispng); |
if (n < 0) |
return fz_rethrow(n, "read error in prediction filter"); |
if (n == 0) |
return p - buf; |
if (state->predictor == 1) |
memcpy(state->out, state->in, n); |
else if (state->predictor == 2) |
fz_predict_tiff(state, state->out, state->in, n); |
else |
{ |
fz_predict_png(state, state->out, state->in + 1, n - 1, state->in[0]); |
memcpy(state->ref, state->out, state->stride); |
} |
state->rp = state->out; |
state->wp = state->out + n - ispng; |
while (state->rp < state->wp && p < ep) |
*p++ = *state->rp++; |
} |
return p - buf; |
} |
static void |
close_predict(fz_stream *stm) |
{ |
fz_predict *state = stm->state; |
fz_close(state->chain); |
fz_free(state->in); |
fz_free(state->out); |
fz_free(state->ref); |
fz_free(state); |
} |
fz_stream * |
fz_open_predict(fz_stream *chain, fz_obj *params) |
{ |
fz_predict *state; |
fz_obj *obj; |
state = fz_malloc(sizeof(fz_predict)); |
state->chain = chain; |
state->predictor = 1; |
state->columns = 1; |
state->colors = 1; |
state->bpc = 8; |
obj = fz_dict_gets(params, "Predictor"); |
if (obj) |
state->predictor = fz_to_int(obj); |
if (state->predictor != 1 && state->predictor != 2 && |
state->predictor != 10 && state->predictor != 11 && |
state->predictor != 12 && state->predictor != 13 && |
state->predictor != 14 && state->predictor != 15) |
{ |
fz_warn("invalid predictor: %d", state->predictor); |
state->predictor = 1; |
} |
obj = fz_dict_gets(params, "Columns"); |
if (obj) |
state->columns = fz_to_int(obj); |
obj = fz_dict_gets(params, "Colors"); |
if (obj) |
state->colors = fz_to_int(obj); |
obj = fz_dict_gets(params, "BitsPerComponent"); |
if (obj) |
state->bpc = fz_to_int(obj); |
state->stride = (state->bpc * state->colors * state->columns + 7) / 8; |
state->bpp = (state->bpc * state->colors + 7) / 8; |
state->in = fz_malloc(state->stride + 1); |
state->out = fz_malloc(state->stride); |
state->ref = fz_malloc(state->stride); |
state->rp = state->out; |
state->wp = state->out; |
memset(state->ref, 0, state->stride); |
return fz_new_stream(state, read_predict, close_predict); |
} |
/contrib/media/updf/fitz/fitz.h |
---|
0,0 → 1,1120 |
#ifndef _FITZ_H_ |
#define _FITZ_H_ |
/* |
* Include the standard libc headers. |
*/ |
#include <stdio.h> |
#include <stdlib.h> |
#include <stddef.h> |
#include <stdarg.h> |
#include <string.h> |
#include <math.h> |
#include <assert.h> |
#include <errno.h> |
#include <limits.h> /* INT_MAX & co */ |
#include <float.h> /* FLT_EPSILON */ |
#include <fcntl.h> /* O_RDONLY & co */ |
#define nelem(x) (sizeof(x)/sizeof((x)[0])) |
#define ABS(x) ( (x) < 0 ? -(x) : (x) ) |
#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) |
#define MAX(a,b) ( (a) > (b) ? (a) : (b) ) |
#define CLAMP(x,a,b) ( (x) > (b) ? (b) : ( (x) < (a) ? (a) : (x) ) ) |
/* |
* Some differences in libc can be smoothed over |
*/ |
#ifdef _MSC_VER /* Microsoft Visual C */ |
#pragma warning( disable: 4244 ) /* conversion from X to Y, possible loss of data */ |
#pragma warning( disable: 4996 ) /* The POSIX name for this item is deprecated */ |
#pragma warning( disable: 4996 ) /* This function or variable may be unsafe */ |
#include <io.h> |
int gettimeofday(struct timeval *tv, struct timezone *tz); |
#define snprintf _snprintf |
#define strtoll _strtoi64 |
#else /* Unix or close enough */ |
#include <unistd.h> |
#ifndef O_BINARY |
#define O_BINARY 0 |
#endif |
#endif |
#ifndef M_PI |
#define M_PI 3.14159265358979323846 |
#endif |
#ifndef M_SQRT2 |
#define M_SQRT2 1.41421356237309504880 |
#endif |
/* |
* Variadic macros, inline and restrict keywords |
*/ |
#if __STDC_VERSION__ == 199901L /* C99 */ |
#define fz_throw(...) fz_throw_imp(__FILE__, __LINE__, __func__, __VA_ARGS__) |
#define fz_rethrow(cause, ...) fz_rethrow_imp(__FILE__, __LINE__, __func__, cause, __VA_ARGS__) |
#define fz_catch(cause, ...) fz_catch_imp(__FILE__, __LINE__, __func__, cause, __VA_ARGS__) |
#elif _MSC_VER >= 1500 /* MSVC 9 or newer */ |
#define inline __inline |
#define restrict __restrict |
#define fz_throw(...) fz_throw_imp(__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__) |
#define fz_rethrow(cause, ...) fz_rethrow_imp(__FILE__, __LINE__, __FUNCTION__, cause, __VA_ARGS__) |
#define fz_catch(cause, ...) fz_catch_imp(__FILE__, __LINE__, __FUNCTION__, cause, __VA_ARGS__) |
#elif __GNUC__ >= 3 /* GCC 3 or newer */ |
#define inline __inline |
#define restrict __restrict |
#define fz_throw(fmt...) fz_throw_imp(__FILE__, __LINE__, __FUNCTION__, fmt) |
#define fz_rethrow(cause, fmt...) fz_rethrow_imp(__FILE__, __LINE__, __FUNCTION__, cause, fmt) |
#define fz_catch(cause, fmt...) fz_catch_imp(__FILE__, __LINE__, __FUNCTION__, cause, fmt) |
#else /* Unknown or ancient */ |
#define inline |
#define restrict |
#define fz_throw fz_throw_impx |
#define fz_rethrow fz_rethrow_impx |
#define fz_catch fz_catch_impx |
#endif |
/* |
* GCC can do type checking of printf strings |
*/ |
#ifndef __printflike |
#if __GNUC__ > 2 || __GNUC__ == 2 && __GNUC_MINOR__ >= 7 |
#define __printflike(fmtarg, firstvararg) \ |
__attribute__((__format__ (__printf__, fmtarg, firstvararg))) |
#else |
#define __printflike(fmtarg, firstvararg) |
#endif |
#endif |
/* |
* Error handling |
*/ |
typedef int fz_error; |
#define fz_okay ((fz_error)0) |
void fz_warn(char *fmt, ...) __printflike(1, 2); |
void fz_flush_warnings(void); |
fz_error fz_throw_imp(const char *file, int line, const char *func, char *fmt, ...) __printflike(4, 5); |
fz_error fz_rethrow_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) __printflike(5, 6); |
void fz_catch_imp(const char *file, int line, const char *func, fz_error cause, char *fmt, ...) __printflike(5, 6); |
fz_error fz_throw_impx(char *fmt, ...) __printflike(1, 2); |
fz_error fz_rethrow_impx(fz_error cause, char *fmt, ...) __printflike(2, 3); |
void fz_catch_impx(fz_error cause, char *fmt, ...) __printflike(2, 3); |
/* extract the last error stack trace */ |
int fz_get_error_count(void); |
char *fz_get_error_line(int n); |
/* |
* Basic runtime and utility functions |
*/ |
/* memory allocation */ |
void *fz_malloc(int size); |
void *fz_calloc(int count, int size); |
void *fz_realloc(void *p, int count, int size); |
void fz_free(void *p); |
char *fz_strdup(char *s); |
/* runtime (hah!) test for endian-ness */ |
int fz_is_big_endian(void); |
/* safe string functions */ |
char *fz_strsep(char **stringp, const char *delim); |
int fz_strlcpy(char *dst, const char *src, int n); |
int fz_strlcat(char *dst, const char *src, int n); |
/* Range checking atof */ |
float fz_atof(const char *s); |
/* utf-8 encoding and decoding */ |
int chartorune(int *rune, char *str); |
int runetochar(char *str, int *rune); |
int runelen(int c); |
/* getopt */ |
extern int fz_getopt(int nargc, char * const *nargv, const char *ostr); |
extern int fz_optind; |
extern char *fz_optarg; |
/* |
* Generic hash-table with fixed-length keys. |
*/ |
typedef struct fz_hash_table_s fz_hash_table; |
fz_hash_table *fz_new_hash_table(int initialsize, int keylen); |
void fz_debug_hash(fz_hash_table *table); |
void fz_empty_hash(fz_hash_table *table); |
void fz_free_hash(fz_hash_table *table); |
void *fz_hash_find(fz_hash_table *table, void *key); |
void fz_hash_insert(fz_hash_table *table, void *key, void *val); |
void fz_hash_remove(fz_hash_table *table, void *key); |
int fz_hash_len(fz_hash_table *table); |
void *fz_hash_get_key(fz_hash_table *table, int idx); |
void *fz_hash_get_val(fz_hash_table *table, int idx); |
/* |
* Math and geometry |
*/ |
/* Multiply scaled two integers in the 0..255 range */ |
static inline int fz_mul255(int a, int b) |
{ |
/* see Jim Blinn's book "Dirty Pixels" for how this works */ |
int x = a * b + 128; |
x += x >> 8; |
return x >> 8; |
} |
/* Expand a value A from the 0...255 range to the 0..256 range */ |
#define FZ_EXPAND(A) ((A)+((A)>>7)) |
/* Combine values A (in any range) and B (in the 0..256 range), |
* to give a single value in the same range as A was. */ |
#define FZ_COMBINE(A,B) (((A)*(B))>>8) |
/* Combine values A and C (in the same (any) range) and B and D (in the |
* 0..256 range), to give a single value in the same range as A and C were. */ |
#define FZ_COMBINE2(A,B,C,D) (FZ_COMBINE((A), (B)) + FZ_COMBINE((C), (D))) |
/* Blend SRC and DST (in the same range) together according to |
* AMOUNT (in the 0...256 range). */ |
#define FZ_BLEND(SRC, DST, AMOUNT) ((((SRC)-(DST))*(AMOUNT) + ((DST)<<8))>>8) |
typedef struct fz_matrix_s fz_matrix; |
typedef struct fz_point_s fz_point; |
typedef struct fz_rect_s fz_rect; |
typedef struct fz_bbox_s fz_bbox; |
extern const fz_rect fz_unit_rect; |
extern const fz_rect fz_empty_rect; |
extern const fz_rect fz_infinite_rect; |
extern const fz_bbox fz_unit_bbox; |
extern const fz_bbox fz_empty_bbox; |
extern const fz_bbox fz_infinite_bbox; |
#define fz_is_empty_rect(r) ((r).x0 == (r).x1) |
#define fz_is_infinite_rect(r) ((r).x0 > (r).x1) |
#define fz_is_empty_bbox(b) ((b).x0 == (b).x1) |
#define fz_is_infinite_bbox(b) ((b).x0 > (b).x1) |
struct fz_matrix_s |
{ |
float a, b, c, d, e, f; |
}; |
struct fz_point_s |
{ |
float x, y; |
}; |
struct fz_rect_s |
{ |
float x0, y0; |
float x1, y1; |
}; |
struct fz_bbox_s |
{ |
int x0, y0; |
int x1, y1; |
}; |
extern const fz_matrix fz_identity; |
fz_matrix fz_concat(fz_matrix one, fz_matrix two); |
fz_matrix fz_scale(float sx, float sy); |
fz_matrix fz_shear(float sx, float sy); |
fz_matrix fz_rotate(float theta); |
fz_matrix fz_translate(float tx, float ty); |
fz_matrix fz_invert_matrix(fz_matrix m); |
int fz_is_rectilinear(fz_matrix m); |
float fz_matrix_expansion(fz_matrix m); |
fz_bbox fz_round_rect(fz_rect r); |
fz_bbox fz_intersect_bbox(fz_bbox a, fz_bbox b); |
fz_rect fz_intersect_rect(fz_rect a, fz_rect b); |
fz_bbox fz_union_bbox(fz_bbox a, fz_bbox b); |
fz_rect fz_union_rect(fz_rect a, fz_rect b); |
fz_point fz_transform_point(fz_matrix m, fz_point p); |
fz_point fz_transform_vector(fz_matrix m, fz_point p); |
fz_rect fz_transform_rect(fz_matrix m, fz_rect r); |
fz_bbox fz_transform_bbox(fz_matrix m, fz_bbox b); |
/* |
* Basic crypto functions. |
* Independent of the rest of fitz. |
* For further encapsulation in filters, or not. |
*/ |
/* md5 digests */ |
typedef struct fz_md5_s fz_md5; |
struct fz_md5_s |
{ |
unsigned int state[4]; |
unsigned int count[2]; |
unsigned char buffer[64]; |
}; |
void fz_md5_init(fz_md5 *state); |
void fz_md5_update(fz_md5 *state, const unsigned char *input, unsigned inlen); |
void fz_md5_final(fz_md5 *state, unsigned char digest[16]); |
/* sha-256 digests */ |
typedef struct fz_sha256_s fz_sha256; |
struct fz_sha256_s |
{ |
unsigned int state[8]; |
unsigned int count[2]; |
union { |
unsigned char u8[64]; |
unsigned int u32[16]; |
} buffer; |
}; |
void fz_sha256_init(fz_sha256 *state); |
void fz_sha256_update(fz_sha256 *state, const unsigned char *input, unsigned int inlen); |
void fz_sha256_final(fz_sha256 *state, unsigned char digest[32]); |
/* arc4 crypto */ |
typedef struct fz_arc4_s fz_arc4; |
struct fz_arc4_s |
{ |
unsigned x; |
unsigned y; |
unsigned char state[256]; |
}; |
void fz_arc4_init(fz_arc4 *state, const unsigned char *key, unsigned len); |
void fz_arc4_encrypt(fz_arc4 *state, unsigned char *dest, const unsigned char *src, unsigned len); |
/* AES block cipher implementation from XYSSL */ |
typedef struct fz_aes_s fz_aes; |
#define AES_DECRYPT 0 |
#define AES_ENCRYPT 1 |
struct fz_aes_s |
{ |
int nr; /* number of rounds */ |
unsigned long *rk; /* AES round keys */ |
unsigned long buf[68]; /* unaligned data */ |
}; |
void aes_setkey_enc( fz_aes *ctx, const unsigned char *key, int keysize ); |
void aes_setkey_dec( fz_aes *ctx, const unsigned char *key, int keysize ); |
void aes_crypt_cbc( fz_aes *ctx, int mode, int length, |
unsigned char iv[16], |
const unsigned char *input, |
unsigned char *output ); |
/* |
* Dynamic objects. |
* The same type of objects as found in PDF and PostScript. |
* Used by the filters and the mupdf parser. |
*/ |
typedef struct fz_obj_s fz_obj; |
extern fz_obj* (*fz_resolve_indirect)(fz_obj*); |
fz_obj *fz_new_null(void); |
fz_obj *fz_new_bool(int b); |
fz_obj *fz_new_int(int i); |
fz_obj *fz_new_real(float f); |
fz_obj *fz_new_name(char *str); |
fz_obj *fz_new_string(char *str, int len); |
fz_obj *fz_new_indirect(int num, int gen, void *xref); |
fz_obj *fz_new_array(int initialcap); |
fz_obj *fz_new_dict(int initialcap); |
fz_obj *fz_copy_array(fz_obj *array); |
fz_obj *fz_copy_dict(fz_obj *dict); |
fz_obj *fz_keep_obj(fz_obj *obj); |
void fz_drop_obj(fz_obj *obj); |
/* type queries */ |
int fz_is_null(fz_obj *obj); |
int fz_is_bool(fz_obj *obj); |
int fz_is_int(fz_obj *obj); |
int fz_is_real(fz_obj *obj); |
int fz_is_name(fz_obj *obj); |
int fz_is_string(fz_obj *obj); |
int fz_is_array(fz_obj *obj); |
int fz_is_dict(fz_obj *obj); |
int fz_is_indirect(fz_obj *obj); |
int fz_objcmp(fz_obj *a, fz_obj *b); |
/* safe, silent failure, no error reporting */ |
int fz_to_bool(fz_obj *obj); |
int fz_to_int(fz_obj *obj); |
float fz_to_real(fz_obj *obj); |
char *fz_to_name(fz_obj *obj); |
char *fz_to_str_buf(fz_obj *obj); |
int fz_to_str_len(fz_obj *obj); |
int fz_to_num(fz_obj *obj); |
int fz_to_gen(fz_obj *obj); |
int fz_array_len(fz_obj *array); |
fz_obj *fz_array_get(fz_obj *array, int i); |
void fz_array_put(fz_obj *array, int i, fz_obj *obj); |
void fz_array_push(fz_obj *array, fz_obj *obj); |
void fz_array_insert(fz_obj *array, fz_obj *obj); |
int fz_dict_len(fz_obj *dict); |
fz_obj *fz_dict_get_key(fz_obj *dict, int idx); |
fz_obj *fz_dict_get_val(fz_obj *dict, int idx); |
fz_obj *fz_dict_get(fz_obj *dict, fz_obj *key); |
fz_obj *fz_dict_gets(fz_obj *dict, char *key); |
fz_obj *fz_dict_getsa(fz_obj *dict, char *key, char *abbrev); |
void fz_dict_put(fz_obj *dict, fz_obj *key, fz_obj *val); |
void fz_dict_puts(fz_obj *dict, char *key, fz_obj *val); |
void fz_dict_del(fz_obj *dict, fz_obj *key); |
void fz_dict_dels(fz_obj *dict, char *key); |
void fz_sort_dict(fz_obj *dict); |
int fz_fprint_obj(FILE *fp, fz_obj *obj, int tight); |
void fz_debug_obj(fz_obj *obj); |
void fz_debug_ref(fz_obj *obj); |
void fz_set_str_len(fz_obj *obj, int newlen); /* private */ |
void *fz_get_indirect_xref(fz_obj *obj); /* private */ |
/* |
* Data buffers. |
*/ |
typedef struct fz_buffer_s fz_buffer; |
struct fz_buffer_s |
{ |
int refs; |
unsigned char *data; |
int cap, len; |
}; |
fz_buffer *fz_new_buffer(int size); |
fz_buffer *fz_keep_buffer(fz_buffer *buf); |
void fz_drop_buffer(fz_buffer *buf); |
void fz_resize_buffer(fz_buffer *buf, int size); |
void fz_grow_buffer(fz_buffer *buf); |
/* |
* Buffered reader. |
* Only the data between rp and wp is valid data. |
*/ |
typedef struct fz_stream_s fz_stream; |
struct fz_stream_s |
{ |
int refs; |
int error; |
int eof; |
int pos; |
int avail; |
int bits; |
unsigned char *bp, *rp, *wp, *ep; |
void *state; |
int (*read)(fz_stream *stm, unsigned char *buf, int len); |
void (*close)(fz_stream *stm); |
void (*seek)(fz_stream *stm, int offset, int whence); |
unsigned char buf[4096]; |
}; |
fz_stream *fz_open_fd(int file); |
fz_stream *fz_open_file(const char *filename); |
fz_stream *fz_open_file_w(const wchar_t *filename); /* only on win32 */ |
fz_stream *fz_open_buffer(fz_buffer *buf); |
fz_stream *fz_open_memory(unsigned char *data, int len); |
void fz_close(fz_stream *stm); |
fz_stream *fz_new_stream(void*, int(*)(fz_stream*, unsigned char*, int), void(*)(fz_stream *)); |
fz_stream *fz_keep_stream(fz_stream *stm); |
void fz_fill_buffer(fz_stream *stm); |
int fz_tell(fz_stream *stm); |
void fz_seek(fz_stream *stm, int offset, int whence); |
int fz_read(fz_stream *stm, unsigned char *buf, int len); |
void fz_read_line(fz_stream *stm, char *buf, int max); |
fz_error fz_read_all(fz_buffer **bufp, fz_stream *stm, int initial); |
static inline int fz_read_byte(fz_stream *stm) |
{ |
if (stm->rp == stm->wp) |
{ |
fz_fill_buffer(stm); |
return stm->rp < stm->wp ? *stm->rp++ : EOF; |
} |
return *stm->rp++; |
} |
static inline int fz_peek_byte(fz_stream *stm) |
{ |
if (stm->rp == stm->wp) |
{ |
fz_fill_buffer(stm); |
return stm->rp < stm->wp ? *stm->rp : EOF; |
} |
return *stm->rp; |
} |
static inline void fz_unread_byte(fz_stream *stm) |
{ |
if (stm->rp > stm->bp) |
stm->rp--; |
} |
static inline int fz_is_eof(fz_stream *stm) |
{ |
if (stm->rp == stm->wp) |
{ |
if (stm->eof) |
return 1; |
return fz_peek_byte(stm) == EOF; |
} |
return 0; |
} |
static inline unsigned int fz_read_bits(fz_stream *stm, int n) |
{ |
unsigned int x; |
if (n <= stm->avail) |
{ |
stm->avail -= n; |
x = (stm->bits >> stm->avail) & ((1 << n) - 1); |
} |
else |
{ |
x = stm->bits & ((1 << stm->avail) - 1); |
n -= stm->avail; |
stm->avail = 0; |
while (n > 8) |
{ |
x = (x << 8) | fz_read_byte(stm); |
n -= 8; |
} |
if (n > 0) |
{ |
stm->bits = fz_read_byte(stm); |
stm->avail = 8 - n; |
x = (x << n) | (stm->bits >> stm->avail); |
} |
} |
return x; |
} |
static inline void fz_sync_bits(fz_stream *stm) |
{ |
stm->avail = 0; |
} |
static inline int fz_is_eof_bits(fz_stream *stm) |
{ |
return fz_is_eof(stm) && (stm->avail == 0 || stm->bits == EOF); |
} |
/* |
* Data filters. |
*/ |
fz_stream *fz_open_copy(fz_stream *chain); |
fz_stream *fz_open_null(fz_stream *chain, int len); |
fz_stream *fz_open_arc4(fz_stream *chain, unsigned char *key, unsigned keylen); |
fz_stream *fz_open_aesd(fz_stream *chain, unsigned char *key, unsigned keylen); |
fz_stream *fz_open_a85d(fz_stream *chain); |
fz_stream *fz_open_ahxd(fz_stream *chain); |
fz_stream *fz_open_rld(fz_stream *chain); |
fz_stream *fz_open_dctd(fz_stream *chain, fz_obj *param); |
fz_stream *fz_open_faxd(fz_stream *chain, fz_obj *param); |
fz_stream *fz_open_flated(fz_stream *chain); |
fz_stream *fz_open_lzwd(fz_stream *chain, fz_obj *param); |
fz_stream *fz_open_predict(fz_stream *chain, fz_obj *param); |
fz_stream *fz_open_jbig2d(fz_stream *chain, fz_buffer *global); |
/* |
* Resources and other graphics related objects. |
*/ |
enum { FZ_MAX_COLORS = 32 }; |
int fz_find_blendmode(char *name); |
char *fz_blendmode_name(int blendmode); |
/* |
* Pixmaps have n components per pixel. the last is always alpha. |
* premultiplied alpha when rendering, but non-premultiplied for colorspace |
* conversions and rescaling. |
*/ |
typedef struct fz_pixmap_s fz_pixmap; |
typedef struct fz_colorspace_s fz_colorspace; |
struct fz_pixmap_s |
{ |
int refs; |
int x, y, w, h, n; |
fz_pixmap *mask; /* explicit soft/image mask */ |
int interpolate; |
int xres, yres; |
fz_colorspace *colorspace; |
unsigned char *samples; |
int free_samples; |
}; |
/* will return NULL if soft limit is exceeded */ |
fz_pixmap *fz_new_pixmap_with_limit(fz_colorspace *colorspace, int w, int h); |
fz_pixmap *fz_new_pixmap_with_data(fz_colorspace *colorspace, int w, int h, unsigned char *samples); |
fz_pixmap *fz_new_pixmap_with_rect(fz_colorspace *, fz_bbox bbox); |
fz_pixmap *fz_new_pixmap_with_rect_and_data(fz_colorspace *, fz_bbox bbox, unsigned char *samples); |
fz_pixmap *fz_new_pixmap(fz_colorspace *, int w, int h); |
fz_pixmap *fz_keep_pixmap(fz_pixmap *pix); |
void fz_drop_pixmap(fz_pixmap *pix); |
void fz_clear_pixmap(fz_pixmap *pix); |
void fz_clear_pixmap_with_color(fz_pixmap *pix, int value); |
void fz_clear_pixmap_rect_with_color(fz_pixmap *pix, int value, fz_bbox r); |
void fz_copy_pixmap_rect(fz_pixmap *dest, fz_pixmap *src, fz_bbox r); |
void fz_premultiply_pixmap(fz_pixmap *pix); |
fz_pixmap *fz_alpha_from_gray(fz_pixmap *gray, int luminosity); |
fz_bbox fz_bound_pixmap(fz_pixmap *pix); |
void fz_invert_pixmap(fz_pixmap *pix); |
void fz_gamma_pixmap(fz_pixmap *pix, float gamma); |
fz_pixmap *fz_scale_pixmap(fz_pixmap *src, float x, float y, float w, float h); |
fz_pixmap *fz_scale_pixmap_gridfit(fz_pixmap *src, float x, float y, float w, float h, int gridfit); |
fz_error fz_write_pnm(fz_pixmap *pixmap, char *filename); |
fz_error fz_write_pam(fz_pixmap *pixmap, char *filename, int savealpha); |
fz_error fz_write_png(fz_pixmap *pixmap, char *filename, int savealpha); |
fz_error fz_load_jpx_image(fz_pixmap **imgp, unsigned char *data, int size, fz_colorspace *dcs); |
/* |
* Bitmaps have 1 component per bit. Only used for creating halftoned versions |
* of contone buffers, and saving out. Samples are stored msb first, akin to |
* pbms. |
*/ |
typedef struct fz_bitmap_s fz_bitmap; |
struct fz_bitmap_s |
{ |
int refs; |
int w, h, stride, n; |
unsigned char *samples; |
}; |
fz_bitmap *fz_new_bitmap(int w, int h, int n); |
fz_bitmap *fz_keep_bitmap(fz_bitmap *bit); |
void fz_clear_bitmap(fz_bitmap *bit); |
void fz_drop_bitmap(fz_bitmap *bit); |
fz_error fz_write_pbm(fz_bitmap *bitmap, char *filename); |
/* |
* A halftone is a set of threshold tiles, one per component. Each threshold |
* tile is a pixmap, possibly of varying sizes and phases. |
*/ |
typedef struct fz_halftone_s fz_halftone; |
struct fz_halftone_s |
{ |
int refs; |
int n; |
fz_pixmap *comp[1]; |
}; |
fz_halftone *fz_new_halftone(int num_comps); |
fz_halftone *fz_get_default_halftone(int num_comps); |
fz_halftone *fz_keep_halftone(fz_halftone *half); |
void fz_drop_halftone(fz_halftone *half); |
fz_bitmap *fz_halftone_pixmap(fz_pixmap *pix, fz_halftone *ht); |
/* |
* Colorspace resources. |
*/ |
extern fz_colorspace *fz_device_gray; |
extern fz_colorspace *fz_device_rgb; |
extern fz_colorspace *fz_device_bgr; |
extern fz_colorspace *fz_device_cmyk; |
struct fz_colorspace_s |
{ |
int refs; |
char name[16]; |
int n; |
void (*to_rgb)(fz_colorspace *, float *src, float *rgb); |
void (*from_rgb)(fz_colorspace *, float *rgb, float *dst); |
void (*free_data)(fz_colorspace *); |
void *data; |
}; |
fz_colorspace *fz_new_colorspace(char *name, int n); |
fz_colorspace *fz_keep_colorspace(fz_colorspace *colorspace); |
void fz_drop_colorspace(fz_colorspace *colorspace); |
void fz_convert_color(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv); |
void fz_convert_pixmap(fz_pixmap *src, fz_pixmap *dst); |
fz_colorspace *fz_find_device_colorspace(char *name); |
/* |
* Fonts come in two variants: |
* Regular fonts are handled by FreeType. |
* Type 3 fonts have callbacks to the interpreter. |
*/ |
struct fz_device_s; |
typedef struct fz_font_s fz_font; |
char *ft_error_string(int err); |
struct fz_font_s |
{ |
int refs; |
char name[32]; |
void *ft_face; /* has an FT_Face if used */ |
int ft_substitute; /* ... substitute metrics */ |
int ft_bold; /* ... synthesize bold */ |
int ft_italic; /* ... synthesize italic */ |
int ft_hint; /* ... force hinting for DynaLab fonts */ |
/* origin of font data */ |
char *ft_file; |
unsigned char *ft_data; |
int ft_size; |
fz_matrix t3matrix; |
fz_obj *t3resources; |
fz_buffer **t3procs; /* has 256 entries if used */ |
float *t3widths; /* has 256 entries if used */ |
void *t3xref; /* a pdf_xref for the callback */ |
fz_error (*t3run)(void *xref, fz_obj *resources, fz_buffer *contents, |
struct fz_device_s *dev, fz_matrix ctm); |
fz_rect bbox; |
/* substitute metrics */ |
int width_count; |
int *width_table; |
}; |
fz_font *fz_new_type3_font(char *name, fz_matrix matrix); |
fz_error fz_new_font_from_memory(fz_font **fontp, unsigned char *data, int len, int index); |
fz_error fz_new_font_from_file(fz_font **fontp, char *path, int index); |
fz_font *fz_keep_font(fz_font *font); |
void fz_drop_font(fz_font *font); |
void fz_debug_font(fz_font *font); |
void fz_set_font_bbox(fz_font *font, float xmin, float ymin, float xmax, float ymax); |
/* |
* Vector path buffer. |
* It can be stroked and dashed, or be filled. |
* It has a fill rule (nonzero or even_odd). |
* |
* When rendering, they are flattened, stroked and dashed straight |
* into the Global Edge List. |
*/ |
typedef struct fz_path_s fz_path; |
typedef struct fz_stroke_state_s fz_stroke_state; |
typedef union fz_path_item_s fz_path_item; |
typedef enum fz_path_item_kind_e |
{ |
FZ_MOVETO, |
FZ_LINETO, |
FZ_CURVETO, |
FZ_CLOSE_PATH |
} fz_path_item_kind; |
union fz_path_item_s |
{ |
fz_path_item_kind k; |
float v; |
}; |
struct fz_path_s |
{ |
int len, cap; |
fz_path_item *items; |
}; |
struct fz_stroke_state_s |
{ |
int start_cap, dash_cap, end_cap; |
int linejoin; |
float linewidth; |
float miterlimit; |
float dash_phase; |
int dash_len; |
float dash_list[32]; |
}; |
fz_path *fz_new_path(void); |
void fz_moveto(fz_path*, float x, float y); |
void fz_lineto(fz_path*, float x, float y); |
void fz_curveto(fz_path*, float, float, float, float, float, float); |
void fz_curvetov(fz_path*, float, float, float, float); |
void fz_curvetoy(fz_path*, float, float, float, float); |
void fz_closepath(fz_path*); |
void fz_free_path(fz_path *path); |
void fz_transform_path(fz_path *path, fz_matrix transform); |
fz_path *fz_clone_path(fz_path *old); |
fz_rect fz_bound_path(fz_path *path, fz_stroke_state *stroke, fz_matrix ctm); |
void fz_debug_path(fz_path *, int indent); |
/* |
* Text buffer. |
* |
* The trm field contains the a, b, c and d coefficients. |
* The e and f coefficients come from the individual elements, |
* together they form the transform matrix for the glyph. |
* |
* Glyphs are referenced by glyph ID. |
* The Unicode text equivalent is kept in a separate array |
* with indexes into the glyph array. |
*/ |
typedef struct fz_text_s fz_text; |
typedef struct fz_text_item_s fz_text_item; |
struct fz_text_item_s |
{ |
float x, y; |
int gid; /* -1 for one gid to many ucs mappings */ |
int ucs; /* -1 for one ucs to many gid mappings */ |
}; |
struct fz_text_s |
{ |
fz_font *font; |
fz_matrix trm; |
int wmode; |
int len, cap; |
fz_text_item *items; |
}; |
fz_text *fz_new_text(fz_font *face, fz_matrix trm, int wmode); |
void fz_add_text(fz_text *text, int gid, int ucs, float x, float y); |
void fz_free_text(fz_text *text); |
void fz_debug_text(fz_text*, int indent); |
fz_rect fz_bound_text(fz_text *text, fz_matrix ctm); |
fz_text *fz_clone_text(fz_text *old); |
/* |
* The shading code uses gouraud shaded triangle meshes. |
*/ |
enum |
{ |
FZ_LINEAR, |
FZ_RADIAL, |
FZ_MESH, |
}; |
typedef struct fz_shade_s fz_shade; |
struct fz_shade_s |
{ |
int refs; |
fz_rect bbox; /* can be fz_infinite_rect */ |
fz_colorspace *colorspace; |
fz_matrix matrix; /* matrix from pattern dict */ |
int use_background; /* background color for fills but not 'sh' */ |
float background[FZ_MAX_COLORS]; |
int use_function; |
float function[256][FZ_MAX_COLORS + 1]; |
int type; /* linear, radial, mesh */ |
int extend[2]; |
int mesh_len; |
int mesh_cap; |
float *mesh; /* [x y 0], [x y r], [x y t] or [x y c1 ... cn] */ |
}; |
fz_shade *fz_keep_shade(fz_shade *shade); |
void fz_drop_shade(fz_shade *shade); |
void fz_debug_shade(fz_shade *shade); |
fz_rect fz_bound_shade(fz_shade *shade, fz_matrix ctm); |
void fz_paint_shade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox); |
/* |
* Glyph cache |
*/ |
typedef struct fz_glyph_cache_s fz_glyph_cache; |
fz_glyph_cache *fz_new_glyph_cache(void); |
fz_pixmap *fz_render_ft_glyph(fz_font *font, int cid, fz_matrix trm); |
fz_pixmap *fz_render_t3_glyph(fz_font *font, int cid, fz_matrix trm, fz_colorspace *model); |
fz_pixmap *fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *state); |
fz_pixmap *fz_render_glyph(fz_glyph_cache*, fz_font*, int, fz_matrix, fz_colorspace *model); |
fz_pixmap *fz_render_stroked_glyph(fz_glyph_cache*, fz_font*, int, fz_matrix, fz_matrix, fz_stroke_state *stroke); |
void fz_free_glyph_cache(fz_glyph_cache *); |
/* |
* Scan converter |
*/ |
int fz_get_aa_level(void); |
void fz_set_aa_level(int bits); |
typedef struct fz_gel_s fz_gel; |
fz_gel *fz_new_gel(void); |
void fz_insert_gel(fz_gel *gel, float x0, float y0, float x1, float y1); |
void fz_reset_gel(fz_gel *gel, fz_bbox clip); |
void fz_sort_gel(fz_gel *gel); |
fz_bbox fz_bound_gel(fz_gel *gel); |
void fz_free_gel(fz_gel *gel); |
int fz_is_rect_gel(fz_gel *gel); |
void fz_scan_convert(fz_gel *gel, int eofill, fz_bbox clip, fz_pixmap *pix, unsigned char *colorbv); |
void fz_flatten_fill_path(fz_gel *gel, fz_path *path, fz_matrix ctm, float flatness); |
void fz_flatten_stroke_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth); |
void fz_flatten_dash_path(fz_gel *gel, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, float flatness, float linewidth); |
/* |
* The device interface. |
*/ |
enum |
{ |
/* Hints */ |
FZ_IGNORE_IMAGE = 1, |
FZ_IGNORE_SHADE = 2, |
/* Flags */ |
FZ_CHARPROC_MASK = 1, |
FZ_CHARPROC_COLOR = 2, |
}; |
typedef struct fz_device_s fz_device; |
struct fz_device_s |
{ |
int hints; |
int flags; |
void *user; |
void (*free_user)(void *); |
void (*fill_path)(void *, fz_path *, int even_odd, fz_matrix, fz_colorspace *, float *color, float alpha); |
void (*stroke_path)(void *, fz_path *, fz_stroke_state *, fz_matrix, fz_colorspace *, float *color, float alpha); |
void (*clip_path)(void *, fz_path *, fz_rect *rect, int even_odd, fz_matrix); |
void (*clip_stroke_path)(void *, fz_path *, fz_rect *rect, fz_stroke_state *, fz_matrix); |
void (*fill_text)(void *, fz_text *, fz_matrix, fz_colorspace *, float *color, float alpha); |
void (*stroke_text)(void *, fz_text *, fz_stroke_state *, fz_matrix, fz_colorspace *, float *color, float alpha); |
void (*clip_text)(void *, fz_text *, fz_matrix, int accumulate); |
void (*clip_stroke_text)(void *, fz_text *, fz_stroke_state *, fz_matrix); |
void (*ignore_text)(void *, fz_text *, fz_matrix); |
void (*fill_shade)(void *, fz_shade *shd, fz_matrix ctm, float alpha); |
void (*fill_image)(void *, fz_pixmap *img, fz_matrix ctm, float alpha); |
void (*fill_image_mask)(void *, fz_pixmap *img, fz_matrix ctm, fz_colorspace *, float *color, float alpha); |
void (*clip_image_mask)(void *, fz_pixmap *img, fz_rect *rect, fz_matrix ctm); |
void (*pop_clip)(void *); |
void (*begin_mask)(void *, fz_rect, int luminosity, fz_colorspace *, float *bc); |
void (*end_mask)(void *); |
void (*begin_group)(void *, fz_rect, int isolated, int knockout, int blendmode, float alpha); |
void (*end_group)(void *); |
void (*begin_tile)(void *, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm); |
void (*end_tile)(void *); |
}; |
void fz_fill_path(fz_device *dev, fz_path *path, int even_odd, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); |
void fz_stroke_path(fz_device *dev, fz_path *path, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); |
void fz_clip_path(fz_device *dev, fz_path *path, fz_rect *rect, int even_odd, fz_matrix ctm); |
void fz_clip_stroke_path(fz_device *dev, fz_path *path, fz_rect *rect, fz_stroke_state *stroke, fz_matrix ctm); |
void fz_fill_text(fz_device *dev, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); |
void fz_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); |
void fz_clip_text(fz_device *dev, fz_text *text, fz_matrix ctm, int accumulate); |
void fz_clip_stroke_text(fz_device *dev, fz_text *text, fz_stroke_state *stroke, fz_matrix ctm); |
void fz_ignore_text(fz_device *dev, fz_text *text, fz_matrix ctm); |
void fz_pop_clip(fz_device *dev); |
void fz_fill_shade(fz_device *dev, fz_shade *shade, fz_matrix ctm, float alpha); |
void fz_fill_image(fz_device *dev, fz_pixmap *image, fz_matrix ctm, float alpha); |
void fz_fill_image_mask(fz_device *dev, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha); |
void fz_clip_image_mask(fz_device *dev, fz_pixmap *image, fz_rect *rect, fz_matrix ctm); |
void fz_begin_mask(fz_device *dev, fz_rect area, int luminosity, fz_colorspace *colorspace, float *bc); |
void fz_end_mask(fz_device *dev); |
void fz_begin_group(fz_device *dev, fz_rect area, int isolated, int knockout, int blendmode, float alpha); |
void fz_end_group(fz_device *dev); |
void fz_begin_tile(fz_device *dev, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm); |
void fz_end_tile(fz_device *dev); |
fz_device *fz_new_device(void *user); |
void fz_free_device(fz_device *dev); |
fz_device *fz_new_trace_device(void); |
fz_device *fz_new_bbox_device(fz_bbox *bboxp); |
fz_device *fz_new_draw_device(fz_glyph_cache *cache, fz_pixmap *dest); |
fz_device *fz_new_draw_device_type3(fz_glyph_cache *cache, fz_pixmap *dest); |
/* |
* Text extraction device |
*/ |
typedef struct fz_text_span_s fz_text_span; |
typedef struct fz_text_char_s fz_text_char; |
struct fz_text_char_s |
{ |
int c; |
fz_bbox bbox; |
}; |
struct fz_text_span_s |
{ |
fz_font *font; |
float size; |
int wmode; |
int len, cap; |
fz_text_char *text; |
fz_text_span *next; |
int eol; |
}; |
fz_text_span *fz_new_text_span(void); |
void fz_free_text_span(fz_text_span *line); |
void fz_debug_text_span(fz_text_span *line); |
void fz_debug_text_span_xml(fz_text_span *span); |
fz_device *fz_new_text_device(fz_text_span *text); |
/* |
* Display list device -- record and play back device commands. |
*/ |
typedef struct fz_display_list_s fz_display_list; |
fz_display_list *fz_new_display_list(void); |
void fz_free_display_list(fz_display_list *list); |
fz_device *fz_new_list_device(fz_display_list *list); |
void fz_execute_display_list(fz_display_list *list, fz_device *dev, fz_matrix ctm, fz_bbox area); |
/* |
* Plotting functions. |
*/ |
void fz_accelerate(void); |
void fz_accelerate_arch(void); |
void fz_decode_tile(fz_pixmap *pix, float *decode); |
void fz_decode_indexed_tile(fz_pixmap *pix, float *decode, int maxval); |
void fz_unpack_tile(fz_pixmap *dst, unsigned char * restrict src, int n, int depth, int stride, int scale); |
void fz_paint_solid_alpha(unsigned char * restrict dp, int w, int alpha); |
void fz_paint_solid_color(unsigned char * restrict dp, int n, int w, unsigned char *color); |
void fz_paint_span(unsigned char * restrict dp, unsigned char * restrict sp, int n, int w, int alpha); |
void fz_paint_span_with_color(unsigned char * restrict dp, unsigned char * restrict mp, int n, int w, unsigned char *color); |
void fz_paint_image(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, int alpha); |
void fz_paint_image_with_color(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *shape, fz_pixmap *img, fz_matrix ctm, unsigned char *colorbv); |
void fz_paint_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha); |
void fz_paint_pixmap_with_mask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk); |
void fz_paint_pixmap_with_rect(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_bbox bbox); |
void fz_blend_pixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, int blendmode, int isolated, fz_pixmap *shape); |
enum |
{ |
/* PDF 1.4 -- standard separable */ |
FZ_BLEND_NORMAL, |
FZ_BLEND_MULTIPLY, |
FZ_BLEND_SCREEN, |
FZ_BLEND_OVERLAY, |
FZ_BLEND_DARKEN, |
FZ_BLEND_LIGHTEN, |
FZ_BLEND_COLOR_DODGE, |
FZ_BLEND_COLOR_BURN, |
FZ_BLEND_HARD_LIGHT, |
FZ_BLEND_SOFT_LIGHT, |
FZ_BLEND_DIFFERENCE, |
FZ_BLEND_EXCLUSION, |
/* PDF 1.4 -- standard non-separable */ |
FZ_BLEND_HUE, |
FZ_BLEND_SATURATION, |
FZ_BLEND_COLOR, |
FZ_BLEND_LUMINOSITY, |
/* For packing purposes */ |
FZ_BLEND_MODEMASK = 15, |
FZ_BLEND_ISOLATED = 16, |
FZ_BLEND_KNOCKOUT = 32 |
}; |
#endif |
/contrib/media/updf/fitz/lrintf.c |
---|
0,0 → 1,5 |
#include <math.h> |
long long int lrintf(float x) { |
return floor(x); |
} |
/contrib/media/updf/fitz/obj_print.c |
---|
0,0 → 1,335 |
#include "fitz.h" |
struct fmt |
{ |
char *buf; |
int cap; |
int len; |
int indent; |
int tight; |
int col; |
int sep; |
int last; |
}; |
static void fmt_obj(struct fmt *fmt, fz_obj *obj); |
static inline int iswhite(int ch) |
{ |
return |
ch == '\000' || |
ch == '\011' || |
ch == '\012' || |
ch == '\014' || |
ch == '\015' || |
ch == '\040'; |
} |
static inline int isdelim(int ch) |
{ |
return ch == '(' || ch == ')' || |
ch == '<' || ch == '>' || |
ch == '[' || ch == ']' || |
ch == '{' || ch == '}' || |
ch == '/' || |
ch == '%'; |
} |
static inline void fmt_putc(struct fmt *fmt, int c) |
{ |
if (fmt->sep && !isdelim(fmt->last) && !isdelim(c)) { |
fmt->sep = 0; |
fmt_putc(fmt, ' '); |
} |
fmt->sep = 0; |
if (fmt->buf && fmt->len < fmt->cap) |
fmt->buf[fmt->len] = c; |
if (c == '\n') |
fmt->col = 0; |
else |
fmt->col ++; |
fmt->len ++; |
fmt->last = c; |
} |
static inline void fmt_indent(struct fmt *fmt) |
{ |
int i = fmt->indent; |
while (i--) { |
fmt_putc(fmt, ' '); |
fmt_putc(fmt, ' '); |
} |
} |
static inline void fmt_puts(struct fmt *fmt, char *s) |
{ |
while (*s) |
fmt_putc(fmt, *s++); |
} |
static inline void fmt_sep(struct fmt *fmt) |
{ |
fmt->sep = 1; |
} |
static void fmt_str(struct fmt *fmt, fz_obj *obj) |
{ |
char *s = fz_to_str_buf(obj); |
int n = fz_to_str_len(obj); |
int i, c; |
fmt_putc(fmt, '('); |
for (i = 0; i < n; i++) |
{ |
c = (unsigned char)s[i]; |
if (c == '\n') |
fmt_puts(fmt, "\\n"); |
else if (c == '\r') |
fmt_puts(fmt, "\\r"); |
else if (c == '\t') |
fmt_puts(fmt, "\\t"); |
else if (c == '\b') |
fmt_puts(fmt, "\\b"); |
else if (c == '\f') |
fmt_puts(fmt, "\\f"); |
else if (c == '(') |
fmt_puts(fmt, "\\("); |
else if (c == ')') |
fmt_puts(fmt, "\\)"); |
else if (c < 32 || c >= 127) { |
char buf[16]; |
fmt_putc(fmt, '\\'); |
sprintf(buf, "%03o", c); |
fmt_puts(fmt, buf); |
} |
else |
fmt_putc(fmt, c); |
} |
fmt_putc(fmt, ')'); |
} |
static void fmt_hex(struct fmt *fmt, fz_obj *obj) |
{ |
char *s = fz_to_str_buf(obj); |
int n = fz_to_str_len(obj); |
int i, b, c; |
fmt_putc(fmt, '<'); |
for (i = 0; i < n; i++) { |
b = (unsigned char) s[i]; |
c = (b >> 4) & 0x0f; |
fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); |
c = (b) & 0x0f; |
fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); |
} |
fmt_putc(fmt, '>'); |
} |
static void fmt_name(struct fmt *fmt, fz_obj *obj) |
{ |
unsigned char *s = (unsigned char *) fz_to_name(obj); |
int i, c; |
fmt_putc(fmt, '/'); |
for (i = 0; s[i]; i++) |
{ |
if (isdelim(s[i]) || iswhite(s[i]) || |
s[i] == '#' || s[i] < 32 || s[i] >= 127) |
{ |
fmt_putc(fmt, '#'); |
c = (s[i] >> 4) & 0xf; |
fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); |
c = s[i] & 0xf; |
fmt_putc(fmt, c < 0xA ? c + '0' : c + 'A' - 0xA); |
} |
else |
{ |
fmt_putc(fmt, s[i]); |
} |
} |
} |
static void fmt_array(struct fmt *fmt, fz_obj *obj) |
{ |
int i; |
if (fmt->tight) { |
fmt_putc(fmt, '['); |
for (i = 0; i < fz_array_len(obj); i++) { |
fmt_obj(fmt, fz_array_get(obj, i)); |
fmt_sep(fmt); |
} |
fmt_putc(fmt, ']'); |
} |
else { |
fmt_puts(fmt, "[ "); |
for (i = 0; i < fz_array_len(obj); i++) { |
if (fmt->col > 60) { |
fmt_putc(fmt, '\n'); |
fmt_indent(fmt); |
} |
fmt_obj(fmt, fz_array_get(obj, i)); |
fmt_putc(fmt, ' '); |
} |
fmt_putc(fmt, ']'); |
fmt_sep(fmt); |
} |
} |
static void fmt_dict(struct fmt *fmt, fz_obj *obj) |
{ |
int i; |
fz_obj *key, *val; |
if (fmt->tight) { |
fmt_puts(fmt, "<<"); |
for (i = 0; i < fz_dict_len(obj); i++) { |
fmt_obj(fmt, fz_dict_get_key(obj, i)); |
fmt_sep(fmt); |
fmt_obj(fmt, fz_dict_get_val(obj, i)); |
fmt_sep(fmt); |
} |
fmt_puts(fmt, ">>"); |
} |
else { |
fmt_puts(fmt, "<<\n"); |
fmt->indent ++; |
for (i = 0; i < fz_dict_len(obj); i++) { |
key = fz_dict_get_key(obj, i); |
val = fz_dict_get_val(obj, i); |
fmt_indent(fmt); |
fmt_obj(fmt, key); |
fmt_putc(fmt, ' '); |
if (!fz_is_indirect(val) && fz_is_array(val)) |
fmt->indent ++; |
fmt_obj(fmt, val); |
fmt_putc(fmt, '\n'); |
if (!fz_is_indirect(val) && fz_is_array(val)) |
fmt->indent --; |
} |
fmt->indent --; |
fmt_indent(fmt); |
fmt_puts(fmt, ">>"); |
} |
} |
static void fmt_obj(struct fmt *fmt, fz_obj *obj) |
{ |
char buf[256]; |
if (!obj) |
fmt_puts(fmt, "<NULL>"); |
else if (fz_is_indirect(obj)) |
{ |
sprintf(buf, "%d %d R", fz_to_num(obj), fz_to_gen(obj)); |
fmt_puts(fmt, buf); |
} |
else if (fz_is_null(obj)) |
fmt_puts(fmt, "null"); |
else if (fz_is_bool(obj)) |
fmt_puts(fmt, fz_to_bool(obj) ? "true" : "false"); |
else if (fz_is_int(obj)) |
{ |
sprintf(buf, "%d", fz_to_int(obj)); |
fmt_puts(fmt, buf); |
} |
else if (fz_is_real(obj)) |
{ |
sprintf(buf, "%g", fz_to_real(obj)); |
if (strchr(buf, 'e')) /* bad news! */ |
sprintf(buf, fabsf(fz_to_real(obj)) > 1 ? "%1.1f" : "%1.8f", fz_to_real(obj)); |
fmt_puts(fmt, buf); |
} |
else if (fz_is_string(obj)) |
{ |
char *str = fz_to_str_buf(obj); |
int len = fz_to_str_len(obj); |
int added = 0; |
int i, c; |
for (i = 0; i < len; i++) { |
c = (unsigned char)str[i]; |
if (strchr("()\\\n\r\t\b\f", c)) |
added ++; |
else if (c < 32 || c >= 127) |
added += 3; |
} |
if (added < len) |
fmt_str(fmt, obj); |
else |
fmt_hex(fmt, obj); |
} |
else if (fz_is_name(obj)) |
fmt_name(fmt, obj); |
else if (fz_is_array(obj)) |
fmt_array(fmt, obj); |
else if (fz_is_dict(obj)) |
fmt_dict(fmt, obj); |
else |
fmt_puts(fmt, "<unknown object>"); |
} |
static int |
fz_sprint_obj(char *s, int n, fz_obj *obj, int tight) |
{ |
struct fmt fmt; |
fmt.indent = 0; |
fmt.col = 0; |
fmt.sep = 0; |
fmt.last = 0; |
fmt.tight = tight; |
fmt.buf = s; |
fmt.cap = n; |
fmt.len = 0; |
fmt_obj(&fmt, obj); |
if (fmt.buf && fmt.len < fmt.cap) |
fmt.buf[fmt.len] = '\0'; |
return fmt.len; |
} |
int |
fz_fprint_obj(FILE *fp, fz_obj *obj, int tight) |
{ |
char buf[1024]; |
char *ptr; |
int n; |
n = fz_sprint_obj(NULL, 0, obj, tight); |
if ((n + 1) < sizeof buf) |
{ |
fz_sprint_obj(buf, sizeof buf, obj, tight); |
fputs(buf, fp); |
fputc('\n', fp); |
} |
else |
{ |
ptr = fz_malloc(n + 1); |
fz_sprint_obj(ptr, n + 1, obj, tight); |
fputs(ptr, fp); |
fputc('\n', fp); |
fz_free(ptr); |
} |
return n; |
} |
void |
fz_debug_obj(fz_obj *obj) |
{ |
fz_fprint_obj(stdout, obj, 0); |
} |
void |
fz_debug_ref(fz_obj *ref) |
{ |
fz_obj *obj; |
obj = fz_resolve_indirect(ref); |
fz_debug_obj(obj); |
} |
/contrib/media/updf/fitz/res_bitmap.c |
---|
0,0 → 1,76 |
#include "fitz.h" |
fz_bitmap * |
fz_new_bitmap(int w, int h, int n) |
{ |
fz_bitmap *bit; |
bit = fz_malloc(sizeof(fz_bitmap)); |
bit->refs = 1; |
bit->w = w; |
bit->h = h; |
bit->n = n; |
/* Span is 32 bit aligned. We may want to make this 64 bit if we |
* use SSE2 etc. */ |
bit->stride = ((n * w + 31) & ~31) >> 3; |
bit->samples = fz_calloc(h, bit->stride); |
return bit; |
} |
fz_bitmap * |
fz_keep_bitmap(fz_bitmap *pix) |
{ |
pix->refs++; |
return pix; |
} |
void |
fz_drop_bitmap(fz_bitmap *bit) |
{ |
if (bit && --bit->refs == 0) |
{ |
fz_free(bit->samples); |
fz_free(bit); |
} |
} |
void |
fz_clear_bitmap(fz_bitmap *bit) |
{ |
memset(bit->samples, 0, bit->stride * bit->h); |
} |
/* |
* Write bitmap to PBM file |
*/ |
fz_error |
fz_write_pbm(fz_bitmap *bitmap, char *filename) |
{ |
FILE *fp; |
unsigned char *p; |
int h, bytestride; |
fp = fopen(filename, "wb"); |
if (!fp) |
return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); |
assert(bitmap->n == 1); |
fprintf(fp, "P4\n%d %d\n", bitmap->w, bitmap->h); |
p = bitmap->samples; |
h = bitmap->h; |
bytestride = (bitmap->w + 7) >> 3; |
while (h--) |
{ |
fwrite(p, 1, bytestride, fp); |
p += bitmap->stride; |
} |
fclose(fp); |
return fz_okay; |
} |
/contrib/media/updf/fitz/res_colorspace.c |
---|
0,0 → 1,685 |
#include "fitz.h" |
#define SLOWCMYK |
fz_colorspace * |
fz_new_colorspace(char *name, int n) |
{ |
fz_colorspace *cs = fz_malloc(sizeof(fz_colorspace)); |
cs->refs = 1; |
fz_strlcpy(cs->name, name, sizeof cs->name); |
cs->n = n; |
cs->to_rgb = NULL; |
cs->from_rgb = NULL; |
cs->free_data = NULL; |
cs->data = NULL; |
return cs; |
} |
fz_colorspace * |
fz_keep_colorspace(fz_colorspace *cs) |
{ |
if (cs->refs < 0) |
return cs; |
cs->refs ++; |
return cs; |
} |
void |
fz_drop_colorspace(fz_colorspace *cs) |
{ |
if (cs && cs->refs < 0) |
return; |
if (cs && --cs->refs == 0) |
{ |
if (cs->free_data && cs->data) |
cs->free_data(cs); |
fz_free(cs); |
} |
} |
/* Device colorspace definitions */ |
static void gray_to_rgb(fz_colorspace *cs, float *gray, float *rgb) |
{ |
rgb[0] = gray[0]; |
rgb[1] = gray[0]; |
rgb[2] = gray[0]; |
} |
static void rgb_to_gray(fz_colorspace *cs, float *rgb, float *gray) |
{ |
float r = rgb[0]; |
float g = rgb[1]; |
float b = rgb[2]; |
gray[0] = r * 0.3f + g * 0.59f + b * 0.11f; |
} |
static void rgb_to_rgb(fz_colorspace *cs, float *rgb, float *xyz) |
{ |
xyz[0] = rgb[0]; |
xyz[1] = rgb[1]; |
xyz[2] = rgb[2]; |
} |
static void bgr_to_rgb(fz_colorspace *cs, float *bgr, float *rgb) |
{ |
rgb[0] = bgr[2]; |
rgb[1] = bgr[1]; |
rgb[2] = bgr[0]; |
} |
static void rgb_to_bgr(fz_colorspace *cs, float *rgb, float *bgr) |
{ |
bgr[0] = rgb[2]; |
bgr[1] = rgb[1]; |
bgr[2] = rgb[0]; |
} |
static void cmyk_to_rgb(fz_colorspace *cs, float *cmyk, float *rgb) |
{ |
#ifdef SLOWCMYK /* from poppler */ |
float c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3]; |
float c1 = 1 - c, m1 = 1 - m, y1 = 1 - y, k1 = 1 - k; |
float r, g, b, x; |
/* this is a matrix multiplication, unrolled for performance */ |
x = c1 * m1 * y1 * k1; /* 0 0 0 0 */ |
r = g = b = x; |
x = c1 * m1 * y1 * k; /* 0 0 0 1 */ |
r += 0.1373 * x; |
g += 0.1216 * x; |
b += 0.1255 * x; |
x = c1 * m1 * y * k1; /* 0 0 1 0 */ |
r += x; |
g += 0.9490 * x; |
x = c1 * m1 * y * k; /* 0 0 1 1 */ |
r += 0.1098 * x; |
g += 0.1020 * x; |
x = c1 * m * y1 * k1; /* 0 1 0 0 */ |
r += 0.9255 * x; |
b += 0.5490 * x; |
x = c1 * m * y1 * k; /* 0 1 0 1 */ |
r += 0.1412 * x; |
x = c1 * m * y * k1; /* 0 1 1 0 */ |
r += 0.9294 * x; |
g += 0.1098 * x; |
b += 0.1412 * x; |
x = c1 * m * y * k; /* 0 1 1 1 */ |
r += 0.1333 * x; |
x = c * m1 * y1 * k1; /* 1 0 0 0 */ |
g += 0.6784 * x; |
b += 0.9373 * x; |
x = c * m1 * y1 * k; /* 1 0 0 1 */ |
g += 0.0588 * x; |
b += 0.1412 * x; |
x = c * m1 * y * k1; /* 1 0 1 0 */ |
g += 0.6510 * x; |
b += 0.3137 * x; |
x = c * m1 * y * k; /* 1 0 1 1 */ |
g += 0.0745 * x; |
x = c * m * y1 * k1; /* 1 1 0 0 */ |
r += 0.1804 * x; |
g += 0.1922 * x; |
b += 0.5725 * x; |
x = c * m * y1 * k; /* 1 1 0 1 */ |
b += 0.0078 * x; |
x = c * m * y * k1; /* 1 1 1 0 */ |
r += 0.2118 * x; |
g += 0.2119 * x; |
b += 0.2235 * x; |
rgb[0] = CLAMP(r, 0, 1); |
rgb[1] = CLAMP(g, 0, 1); |
rgb[2] = CLAMP(b, 0, 1); |
#else |
rgb[0] = 1 - MIN(1, cmyk[0] + cmyk[3]); |
rgb[1] = 1 - MIN(1, cmyk[1] + cmyk[3]); |
rgb[2] = 1 - MIN(1, cmyk[2] + cmyk[3]); |
#endif |
} |
static void rgb_to_cmyk(fz_colorspace *cs, float *rgb, float *cmyk) |
{ |
float c, m, y, k; |
c = 1 - rgb[0]; |
m = 1 - rgb[1]; |
y = 1 - rgb[2]; |
k = MIN(c, MIN(m, y)); |
cmyk[0] = c - k; |
cmyk[1] = m - k; |
cmyk[2] = y - k; |
cmyk[3] = k; |
} |
static fz_colorspace k_device_gray = { -1, "DeviceGray", 1, gray_to_rgb, rgb_to_gray }; |
static fz_colorspace k_device_rgb = { -1, "DeviceRGB", 3, rgb_to_rgb, rgb_to_rgb }; |
static fz_colorspace k_device_bgr = { -1, "DeviceRGB", 3, bgr_to_rgb, rgb_to_bgr }; |
static fz_colorspace k_device_cmyk = { -1, "DeviceCMYK", 4, cmyk_to_rgb, rgb_to_cmyk }; |
fz_colorspace *fz_device_gray = &k_device_gray; |
fz_colorspace *fz_device_rgb = &k_device_rgb; |
fz_colorspace *fz_device_bgr = &k_device_bgr; |
fz_colorspace *fz_device_cmyk = &k_device_cmyk; |
fz_colorspace * |
fz_find_device_colorspace(char *name) |
{ |
if (!strcmp(name, "DeviceGray")) |
return fz_device_gray; |
if (!strcmp(name, "DeviceRGB")) |
return fz_device_rgb; |
if (!strcmp(name, "DeviceBGR")) |
return fz_device_bgr; |
if (!strcmp(name, "DeviceCMYK")) |
return fz_device_cmyk; |
fz_warn("unknown device colorspace: %s", name); |
return NULL; |
} |
/* Fast pixmap color conversions */ |
static void fast_gray_to_rgb(fz_pixmap *src, fz_pixmap *dst) |
{ |
unsigned char *s = src->samples; |
unsigned char *d = dst->samples; |
int n = src->w * src->h; |
while (n--) |
{ |
d[0] = s[0]; |
d[1] = s[0]; |
d[2] = s[0]; |
d[3] = s[1]; |
s += 2; |
d += 4; |
} |
} |
static void fast_gray_to_cmyk(fz_pixmap *src, fz_pixmap *dst) |
{ |
unsigned char *s = src->samples; |
unsigned char *d = dst->samples; |
int n = src->w * src->h; |
while (n--) |
{ |
d[0] = 0; |
d[1] = 0; |
d[2] = 0; |
d[3] = s[0]; |
d[4] = s[1]; |
s += 2; |
d += 5; |
} |
} |
static void fast_rgb_to_gray(fz_pixmap *src, fz_pixmap *dst) |
{ |
unsigned char *s = src->samples; |
unsigned char *d = dst->samples; |
int n = src->w * src->h; |
while (n--) |
{ |
d[0] = ((s[0]+1) * 77 + (s[1]+1) * 150 + (s[2]+1) * 28) >> 8; |
d[1] = s[3]; |
s += 4; |
d += 2; |
} |
} |
static void fast_bgr_to_gray(fz_pixmap *src, fz_pixmap *dst) |
{ |
unsigned char *s = src->samples; |
unsigned char *d = dst->samples; |
int n = src->w * src->h; |
while (n--) |
{ |
d[0] = ((s[0]+1) * 28 + (s[1]+1) * 150 + (s[2]+1) * 77) >> 8; |
d[1] = s[3]; |
s += 4; |
d += 2; |
} |
} |
static void fast_rgb_to_cmyk(fz_pixmap *src, fz_pixmap *dst) |
{ |
unsigned char *s = src->samples; |
unsigned char *d = dst->samples; |
int n = src->w * src->h; |
while (n--) |
{ |
unsigned char c = 255 - s[0]; |
unsigned char m = 255 - s[1]; |
unsigned char y = 255 - s[2]; |
unsigned char k = MIN(c, MIN(m, y)); |
d[0] = c - k; |
d[1] = m - k; |
d[2] = y - k; |
d[3] = k; |
d[4] = s[3]; |
s += 4; |
d += 5; |
} |
} |
static void fast_bgr_to_cmyk(fz_pixmap *src, fz_pixmap *dst) |
{ |
unsigned char *s = src->samples; |
unsigned char *d = dst->samples; |
int n = src->w * src->h; |
while (n--) |
{ |
unsigned char c = 255 - s[2]; |
unsigned char m = 255 - s[1]; |
unsigned char y = 255 - s[0]; |
unsigned char k = MIN(c, MIN(m, y)); |
d[0] = c - k; |
d[1] = m - k; |
d[2] = y - k; |
d[3] = k; |
d[4] = s[3]; |
s += 4; |
d += 5; |
} |
} |
static void fast_cmyk_to_gray(fz_pixmap *src, fz_pixmap *dst) |
{ |
unsigned char *s = src->samples; |
unsigned char *d = dst->samples; |
int n = src->w * src->h; |
while (n--) |
{ |
unsigned char c = fz_mul255(s[0], 77); |
unsigned char m = fz_mul255(s[1], 150); |
unsigned char y = fz_mul255(s[2], 28); |
d[0] = 255 - MIN(c + m + y + s[3], 255); |
d[1] = s[4]; |
s += 5; |
d += 2; |
} |
} |
static void fast_cmyk_to_rgb(fz_pixmap *src, fz_pixmap *dst) |
{ |
unsigned char *s = src->samples; |
unsigned char *d = dst->samples; |
int n = src->w * src->h; |
while (n--) |
{ |
#ifdef SLOWCMYK |
float cmyk[4], rgb[3]; |
cmyk[0] = s[0] / 255.0f; |
cmyk[1] = s[1] / 255.0f; |
cmyk[2] = s[2] / 255.0f; |
cmyk[3] = s[3] / 255.0f; |
cmyk_to_rgb(NULL, cmyk, rgb); |
d[0] = rgb[0] * 255; |
d[1] = rgb[1] * 255; |
d[2] = rgb[2] * 255; |
#else |
d[0] = 255 - MIN(s[0] + s[3], 255); |
d[1] = 255 - MIN(s[1] + s[3], 255); |
d[2] = 255 - MIN(s[2] + s[3], 255); |
#endif |
d[3] = s[4]; |
s += 5; |
d += 4; |
} |
} |
static void fast_cmyk_to_bgr(fz_pixmap *src, fz_pixmap *dst) |
{ |
unsigned char *s = src->samples; |
unsigned char *d = dst->samples; |
int n = src->w * src->h; |
while (n--) |
{ |
#ifdef SLOWCMYK |
float cmyk[4], rgb[3]; |
cmyk[0] = s[0] / 255.0f; |
cmyk[1] = s[1] / 255.0f; |
cmyk[2] = s[2] / 255.0f; |
cmyk[3] = s[3] / 255.0f; |
cmyk_to_rgb(NULL, cmyk, rgb); |
d[0] = rgb[2] * 255; |
d[1] = rgb[1] * 255; |
d[2] = rgb[0] * 255; |
#else |
d[0] = 255 - MIN(s[2] + s[3], 255); |
d[1] = 255 - MIN(s[1] + s[3], 255); |
d[2] = 255 - MIN(s[0] + s[3], 255); |
#endif |
d[3] = s[4]; |
s += 5; |
d += 4; |
} |
} |
static void fast_rgb_to_bgr(fz_pixmap *src, fz_pixmap *dst) |
{ |
unsigned char *s = src->samples; |
unsigned char *d = dst->samples; |
int n = src->w * src->h; |
while (n--) |
{ |
d[0] = s[2]; |
d[1] = s[1]; |
d[2] = s[0]; |
d[3] = s[3]; |
s += 4; |
d += 4; |
} |
} |
static void |
fz_std_conv_pixmap(fz_pixmap *src, fz_pixmap *dst) |
{ |
float srcv[FZ_MAX_COLORS]; |
float dstv[FZ_MAX_COLORS]; |
int srcn, dstn; |
int y, x, k, i; |
fz_colorspace *ss = src->colorspace; |
fz_colorspace *ds = dst->colorspace; |
unsigned char *s = src->samples; |
unsigned char *d = dst->samples; |
assert(src->w == dst->w && src->h == dst->h); |
assert(src->n == ss->n + 1); |
assert(dst->n == ds->n + 1); |
srcn = ss->n; |
dstn = ds->n; |
/* Special case for Lab colorspace (scaling of components to float) */ |
if (!strcmp(ss->name, "Lab") && srcn == 3) |
{ |
for (y = 0; y < src->h; y++) |
{ |
for (x = 0; x < src->w; x++) |
{ |
srcv[0] = *s++ / 255.0f * 100; |
srcv[1] = *s++ - 128; |
srcv[2] = *s++ - 128; |
fz_convert_color(ss, srcv, ds, dstv); |
for (k = 0; k < dstn; k++) |
*d++ = dstv[k] * 255; |
*d++ = *s++; |
} |
} |
} |
/* Brute-force for small images */ |
else if (src->w * src->h < 256) |
{ |
for (y = 0; y < src->h; y++) |
{ |
for (x = 0; x < src->w; x++) |
{ |
for (k = 0; k < srcn; k++) |
srcv[k] = *s++ / 255.0f; |
fz_convert_color(ss, srcv, ds, dstv); |
for (k = 0; k < dstn; k++) |
*d++ = dstv[k] * 255; |
*d++ = *s++; |
} |
} |
} |
/* 1-d lookup table for separation and similar colorspaces */ |
else if (srcn == 1) |
{ |
unsigned char lookup[FZ_MAX_COLORS * 256]; |
for (i = 0; i < 256; i++) |
{ |
srcv[0] = i / 255.0f; |
fz_convert_color(ss, srcv, ds, dstv); |
for (k = 0; k < dstn; k++) |
lookup[i * dstn + k] = dstv[k] * 255; |
} |
for (y = 0; y < src->h; y++) |
{ |
for (x = 0; x < src->w; x++) |
{ |
i = *s++; |
for (k = 0; k < dstn; k++) |
*d++ = lookup[i * dstn + k]; |
*d++ = *s++; |
} |
} |
} |
/* Memoize colors using a hash table for the general case */ |
else |
{ |
fz_hash_table *lookup; |
unsigned char *color; |
lookup = fz_new_hash_table(509, srcn); |
for (y = 0; y < src->h; y++) |
{ |
for (x = 0; x < src->w; x++) |
{ |
color = fz_hash_find(lookup, s); |
if (color) |
{ |
memcpy(d, color, dstn); |
s += srcn; |
d += dstn; |
*d++ = *s++; |
} |
else |
{ |
for (k = 0; k < srcn; k++) |
srcv[k] = *s++ / 255.0f; |
fz_convert_color(ss, srcv, ds, dstv); |
for (k = 0; k < dstn; k++) |
*d++ = dstv[k] * 255; |
fz_hash_insert(lookup, s - srcn, d - dstn); |
*d++ = *s++; |
} |
} |
} |
fz_free_hash(lookup); |
} |
} |
void |
fz_convert_pixmap(fz_pixmap *sp, fz_pixmap *dp) |
{ |
fz_colorspace *ss = sp->colorspace; |
fz_colorspace *ds = dp->colorspace; |
assert(ss && ds); |
if (sp->mask) |
dp->mask = fz_keep_pixmap(sp->mask); |
dp->interpolate = sp->interpolate; |
if (ss == fz_device_gray) |
{ |
if (ds == fz_device_rgb) fast_gray_to_rgb(sp, dp); |
else if (ds == fz_device_bgr) fast_gray_to_rgb(sp, dp); /* bgr == rgb here */ |
else if (ds == fz_device_cmyk) fast_gray_to_cmyk(sp, dp); |
else fz_std_conv_pixmap(sp, dp); |
} |
else if (ss == fz_device_rgb) |
{ |
if (ds == fz_device_gray) fast_rgb_to_gray(sp, dp); |
else if (ds == fz_device_bgr) fast_rgb_to_bgr(sp, dp); |
else if (ds == fz_device_cmyk) fast_rgb_to_cmyk(sp, dp); |
else fz_std_conv_pixmap(sp, dp); |
} |
else if (ss == fz_device_bgr) |
{ |
if (ds == fz_device_gray) fast_bgr_to_gray(sp, dp); |
else if (ds == fz_device_rgb) fast_rgb_to_bgr(sp, dp); /* bgr = rgb here */ |
else if (ds == fz_device_cmyk) fast_bgr_to_cmyk(sp, dp); |
else fz_std_conv_pixmap(sp, dp); |
} |
else if (ss == fz_device_cmyk) |
{ |
if (ds == fz_device_gray) fast_cmyk_to_gray(sp, dp); |
else if (ds == fz_device_bgr) fast_cmyk_to_bgr(sp, dp); |
else if (ds == fz_device_rgb) fast_cmyk_to_rgb(sp, dp); |
else fz_std_conv_pixmap(sp, dp); |
} |
else fz_std_conv_pixmap(sp, dp); |
} |
/* Convert a single color */ |
static void |
fz_std_conv_color(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv) |
{ |
float rgb[3]; |
int i; |
if (srcs != dsts) |
{ |
assert(srcs->to_rgb && dsts->from_rgb); |
srcs->to_rgb(srcs, srcv, rgb); |
dsts->from_rgb(dsts, rgb, dstv); |
for (i = 0; i < dsts->n; i++) |
dstv[i] = CLAMP(dstv[i], 0, 1); |
} |
else |
{ |
for (i = 0; i < srcs->n; i++) |
dstv[i] = srcv[i]; |
} |
} |
void |
fz_convert_color(fz_colorspace *ss, float *sv, fz_colorspace *ds, float *dv) |
{ |
if (ss == fz_device_gray) |
{ |
if ((ds == fz_device_rgb) || (ds == fz_device_bgr)) |
{ |
dv[0] = sv[0]; |
dv[1] = sv[0]; |
dv[2] = sv[0]; |
} |
else if (ds == fz_device_cmyk) |
{ |
dv[0] = 0; |
dv[1] = 0; |
dv[2] = 0; |
dv[3] = sv[0]; |
} |
else |
fz_std_conv_color(ss, sv, ds, dv); |
} |
else if (ss == fz_device_rgb) |
{ |
if (ds == fz_device_gray) |
{ |
dv[0] = sv[0] * 0.3f + sv[1] * 0.59f + sv[2] * 0.11f; |
} |
else if (ds == fz_device_bgr) |
{ |
dv[0] = sv[2]; |
dv[1] = sv[1]; |
dv[2] = sv[0]; |
} |
else if (ds == fz_device_cmyk) |
{ |
float c = 1 - sv[0]; |
float m = 1 - sv[1]; |
float y = 1 - sv[2]; |
float k = MIN(c, MIN(m, y)); |
dv[0] = c - k; |
dv[1] = m - k; |
dv[2] = y - k; |
dv[3] = k; |
} |
else |
fz_std_conv_color(ss, sv, ds, dv); |
} |
else if (ss == fz_device_bgr) |
{ |
if (ds == fz_device_gray) |
{ |
dv[0] = sv[0] * 0.11f + sv[1] * 0.59f + sv[2] * 0.3f; |
} |
else if (ds == fz_device_bgr) |
{ |
dv[0] = sv[2]; |
dv[1] = sv[1]; |
dv[2] = sv[0]; |
} |
else if (ds == fz_device_cmyk) |
{ |
float c = 1 - sv[2]; |
float m = 1 - sv[1]; |
float y = 1 - sv[0]; |
float k = MIN(c, MIN(m, y)); |
dv[0] = c - k; |
dv[1] = m - k; |
dv[2] = y - k; |
dv[3] = k; |
} |
else |
fz_std_conv_color(ss, sv, ds, dv); |
} |
else if (ss == fz_device_cmyk) |
{ |
if (ds == fz_device_gray) |
{ |
float c = sv[0] * 0.3f; |
float m = sv[1] * 0.59f; |
float y = sv[2] * 0.11f; |
dv[0] = 1 - MIN(c + m + y + sv[3], 1); |
} |
else if (ds == fz_device_rgb) |
{ |
#ifdef SLOWCMYK |
cmyk_to_rgb(NULL, sv, dv); |
#else |
dv[0] = 1 - MIN(sv[0] + sv[3], 1); |
dv[1] = 1 - MIN(sv[1] + sv[3], 1); |
dv[2] = 1 - MIN(sv[2] + sv[3], 1); |
#endif |
} |
else if (ds == fz_device_bgr) |
{ |
#ifdef SLOWCMYK |
float rgb[3]; |
cmyk_to_rgb(NULL, sv, rgb); |
dv[0] = rgb[2]; |
dv[1] = rgb[1]; |
dv[2] = rgb[0]; |
#else |
dv[0] = 1 - MIN(sv[2] + sv[3], 1); |
dv[1] = 1 - MIN(sv[1] + sv[3], 1); |
dv[2] = 1 - MIN(sv[0] + sv[3], 1); |
#endif |
} |
else |
fz_std_conv_color(ss, sv, ds, dv); |
} |
else |
fz_std_conv_color(ss, sv, ds, dv); |
} |
/contrib/media/updf/fitz/res_font.c |
---|
0,0 → 1,609 |
#include "fitz.h" |
#include <ft2build.h> |
#include FT_FREETYPE_H |
#include FT_STROKER_H |
static void fz_finalize_freetype(void); |
static fz_font * |
fz_new_font(char *name) |
{ |
fz_font *font; |
font = fz_malloc(sizeof(fz_font)); |
font->refs = 1; |
if (name) |
fz_strlcpy(font->name, name, sizeof font->name); |
else |
fz_strlcpy(font->name, "(null)", sizeof font->name); |
font->ft_face = NULL; |
font->ft_substitute = 0; |
font->ft_bold = 0; |
font->ft_italic = 0; |
font->ft_hint = 0; |
font->ft_file = NULL; |
font->ft_data = NULL; |
font->ft_size = 0; |
font->t3matrix = fz_identity; |
font->t3resources = NULL; |
font->t3procs = NULL; |
font->t3widths = NULL; |
font->t3xref = NULL; |
font->t3run = NULL; |
font->bbox.x0 = 0; |
font->bbox.y0 = 0; |
font->bbox.x1 = 1000; |
font->bbox.y1 = 1000; |
font->width_count = 0; |
font->width_table = NULL; |
return font; |
} |
fz_font * |
fz_keep_font(fz_font *font) |
{ |
font->refs ++; |
return font; |
} |
void |
fz_drop_font(fz_font *font) |
{ |
int fterr; |
int i; |
if (font && --font->refs == 0) |
{ |
if (font->t3procs) |
{ |
if (font->t3resources) |
fz_drop_obj(font->t3resources); |
for (i = 0; i < 256; i++) |
if (font->t3procs[i]) |
fz_drop_buffer(font->t3procs[i]); |
fz_free(font->t3procs); |
fz_free(font->t3widths); |
} |
if (font->ft_face) |
{ |
fterr = FT_Done_Face((FT_Face)font->ft_face); |
if (fterr) |
fz_warn("freetype finalizing face: %s", ft_error_string(fterr)); |
fz_finalize_freetype(); |
} |
if (font->ft_file) |
fz_free(font->ft_file); |
if (font->ft_data) |
fz_free(font->ft_data); |
if (font->width_table) |
fz_free(font->width_table); |
fz_free(font); |
} |
} |
void |
fz_set_font_bbox(fz_font *font, float xmin, float ymin, float xmax, float ymax) |
{ |
font->bbox.x0 = xmin; |
font->bbox.y0 = ymin; |
font->bbox.x1 = xmax; |
font->bbox.y1 = ymax; |
} |
/* |
* Freetype hooks |
*/ |
static FT_Library fz_ftlib = NULL; |
static int fz_ftlib_refs = 0; |
#undef __FTERRORS_H__ |
#define FT_ERRORDEF(e, v, s) { (e), (s) }, |
#define FT_ERROR_START_LIST |
#define FT_ERROR_END_LIST { 0, NULL } |
struct ft_error |
{ |
int err; |
char *str; |
}; |
static const struct ft_error ft_errors[] = |
{ |
#include FT_ERRORS_H |
}; |
char *ft_error_string(int err) |
{ |
const struct ft_error *e; |
for (e = ft_errors; e->str != NULL; e++) |
if (e->err == err) |
return e->str; |
return "Unknown error"; |
} |
static fz_error |
fz_init_freetype(void) |
{ |
int fterr; |
int maj, min, pat; |
if (fz_ftlib) |
{ |
fz_ftlib_refs++; |
return fz_okay; |
} |
fterr = FT_Init_FreeType(&fz_ftlib); |
if (fterr) |
return fz_throw("cannot init freetype: %s", ft_error_string(fterr)); |
FT_Library_Version(fz_ftlib, &maj, &min, &pat); |
if (maj == 2 && min == 1 && pat < 7) |
{ |
fterr = FT_Done_FreeType(fz_ftlib); |
if (fterr) |
fz_warn("freetype finalizing: %s", ft_error_string(fterr)); |
return fz_throw("freetype version too old: %d.%d.%d", maj, min, pat); |
} |
fz_ftlib_refs++; |
return fz_okay; |
} |
static void |
fz_finalize_freetype(void) |
{ |
int fterr; |
if (--fz_ftlib_refs == 0) |
{ |
fterr = FT_Done_FreeType(fz_ftlib); |
if (fterr) |
fz_warn("freetype finalizing: %s", ft_error_string(fterr)); |
fz_ftlib = NULL; |
} |
} |
fz_error |
fz_new_font_from_file(fz_font **fontp, char *path, int index) |
{ |
FT_Face face; |
fz_error error; |
fz_font *font; |
int fterr; |
error = fz_init_freetype(); |
if (error) |
return fz_rethrow(error, "cannot init freetype library"); |
fterr = FT_New_Face(fz_ftlib, path, index, &face); |
if (fterr) |
return fz_throw("freetype: cannot load font: %s", ft_error_string(fterr)); |
font = fz_new_font(face->family_name); |
font->ft_face = face; |
font->bbox.x0 = face->bbox.xMin * 1000 / face->units_per_EM; |
font->bbox.y0 = face->bbox.yMin * 1000 / face->units_per_EM; |
font->bbox.x1 = face->bbox.xMax * 1000 / face->units_per_EM; |
font->bbox.y1 = face->bbox.yMax * 1000 / face->units_per_EM; |
*fontp = font; |
return fz_okay; |
} |
fz_error |
fz_new_font_from_memory(fz_font **fontp, unsigned char *data, int len, int index) |
{ |
FT_Face face; |
fz_error error; |
fz_font *font; |
int fterr; |
error = fz_init_freetype(); |
if (error) |
return fz_rethrow(error, "cannot init freetype library"); |
fterr = FT_New_Memory_Face(fz_ftlib, data, len, index, &face); |
if (fterr) |
return fz_throw("freetype: cannot load font: %s", ft_error_string(fterr)); |
font = fz_new_font(face->family_name); |
font->ft_face = face; |
font->bbox.x0 = face->bbox.xMin * 1000 / face->units_per_EM; |
font->bbox.y0 = face->bbox.yMin * 1000 / face->units_per_EM; |
font->bbox.x1 = face->bbox.xMax * 1000 / face->units_per_EM; |
font->bbox.y1 = face->bbox.yMax * 1000 / face->units_per_EM; |
*fontp = font; |
return fz_okay; |
} |
static fz_matrix |
fz_adjust_ft_glyph_width(fz_font *font, int gid, fz_matrix trm) |
{ |
/* Fudge the font matrix to stretch the glyph if we've substituted the font. */ |
if (font->ft_substitute && gid < font->width_count) |
{ |
FT_Error fterr; |
int subw; |
int realw; |
float scale; |
/* TODO: use FT_Get_Advance */ |
fterr = FT_Set_Char_Size(font->ft_face, 1000, 1000, 72, 72); |
if (fterr) |
fz_warn("freetype setting character size: %s", ft_error_string(fterr)); |
fterr = FT_Load_Glyph(font->ft_face, gid, |
FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); |
if (fterr) |
fz_warn("freetype failed to load glyph: %s", ft_error_string(fterr)); |
realw = ((FT_Face)font->ft_face)->glyph->metrics.horiAdvance; |
subw = font->width_table[gid]; |
if (realw) |
scale = (float) subw / realw; |
else |
scale = 1; |
return fz_concat(fz_scale(scale, 1), trm); |
} |
return trm; |
} |
static fz_pixmap * |
fz_copy_ft_bitmap(int left, int top, FT_Bitmap *bitmap) |
{ |
fz_pixmap *pixmap; |
int y; |
pixmap = fz_new_pixmap(NULL, bitmap->width, bitmap->rows); |
pixmap->x = left; |
pixmap->y = top - bitmap->rows; |
if (bitmap->pixel_mode == FT_PIXEL_MODE_MONO) |
{ |
for (y = 0; y < pixmap->h; y++) |
{ |
unsigned char *out = pixmap->samples + y * pixmap->w; |
unsigned char *in = bitmap->buffer + (pixmap->h - y - 1) * bitmap->pitch; |
unsigned char bit = 0x80; |
int w = pixmap->w; |
while (w--) |
{ |
*out++ = (*in & bit) ? 255 : 0; |
bit >>= 1; |
if (bit == 0) |
{ |
bit = 0x80; |
in++; |
} |
} |
} |
} |
else |
{ |
for (y = 0; y < pixmap->h; y++) |
{ |
memcpy(pixmap->samples + y * pixmap->w, |
bitmap->buffer + (pixmap->h - y - 1) * bitmap->pitch, |
pixmap->w); |
} |
} |
return pixmap; |
} |
fz_pixmap * |
fz_render_ft_glyph(fz_font *font, int gid, fz_matrix trm) |
{ |
FT_Face face = font->ft_face; |
FT_Matrix m; |
FT_Vector v; |
FT_Error fterr; |
trm = fz_adjust_ft_glyph_width(font, gid, trm); |
if (font->ft_italic) |
trm = fz_concat(fz_shear(0.3f, 0), trm); |
/* |
Freetype mutilates complex glyphs if they are loaded |
with FT_Set_Char_Size 1.0. it rounds the coordinates |
before applying transformation. to get more precision in |
freetype, we shift part of the scale in the matrix |
into FT_Set_Char_Size instead |
*/ |
m.xx = trm.a * 64; /* should be 65536 */ |
m.yx = trm.b * 64; |
m.xy = trm.c * 64; |
m.yy = trm.d * 64; |
v.x = trm.e * 64; |
v.y = trm.f * 64; |
fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ |
if (fterr) |
fz_warn("freetype setting character size: %s", ft_error_string(fterr)); |
FT_Set_Transform(face, &m, &v); |
if (fz_get_aa_level() == 0) |
{ |
/* If you really want grid fitting, enable this code. */ |
float scale = fz_matrix_expansion(trm); |
m.xx = trm.a * 65536 / scale; |
m.xy = trm.b * 65536 / scale; |
m.yx = trm.c * 65536 / scale; |
m.yy = trm.d * 65536 / scale; |
v.x = 0; |
v.y = 0; |
fterr = FT_Set_Char_Size(face, 64 * scale, 64 * scale, 72, 72); |
if (fterr) |
fz_warn("freetype setting character size: %s", ft_error_string(fterr)); |
FT_Set_Transform(face, &m, &v); |
fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_TARGET_MONO); |
if (fterr) |
fz_warn("freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); |
} |
else if (font->ft_hint) |
{ |
/* |
Enable hinting, but keep the huge char size so that |
it is hinted for a character. This will in effect nullify |
the effect of grid fitting. This form of hinting should |
only be used for DynaLab and similar tricky TrueType fonts, |
so that we get the correct outline shape. |
*/ |
fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP); |
if (fterr) |
fz_warn("freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); |
} |
else |
{ |
fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); |
if (fterr) |
{ |
fz_warn("freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); |
return NULL; |
} |
} |
if (font->ft_bold) |
{ |
float strength = fz_matrix_expansion(trm) * 0.04f; |
FT_Outline_Embolden(&face->glyph->outline, strength * 64); |
FT_Outline_Translate(&face->glyph->outline, -strength * 32, -strength * 32); |
} |
fterr = FT_Render_Glyph(face->glyph, fz_get_aa_level() > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO); |
if (fterr) |
{ |
fz_warn("freetype render glyph (gid %d): %s", gid, ft_error_string(fterr)); |
return NULL; |
} |
return fz_copy_ft_bitmap(face->glyph->bitmap_left, face->glyph->bitmap_top, &face->glyph->bitmap); |
} |
fz_pixmap * |
fz_render_ft_stroked_glyph(fz_font *font, int gid, fz_matrix trm, fz_matrix ctm, fz_stroke_state *state) |
{ |
FT_Face face = font->ft_face; |
float expansion = fz_matrix_expansion(ctm); |
int linewidth = state->linewidth * expansion * 64 / 2; |
FT_Matrix m; |
FT_Vector v; |
FT_Error fterr; |
FT_Stroker stroker; |
FT_Glyph glyph; |
FT_BitmapGlyph bitmap; |
fz_pixmap *pixmap; |
trm = fz_adjust_ft_glyph_width(font, gid, trm); |
if (font->ft_italic) |
trm = fz_concat(fz_shear(0.3f, 0), trm); |
m.xx = trm.a * 64; /* should be 65536 */ |
m.yx = trm.b * 64; |
m.xy = trm.c * 64; |
m.yy = trm.d * 64; |
v.x = trm.e * 64; |
v.y = trm.f * 64; |
fterr = FT_Set_Char_Size(face, 65536, 65536, 72, 72); /* should be 64, 64 */ |
if (fterr) |
{ |
fz_warn("FT_Set_Char_Size: %s", ft_error_string(fterr)); |
return NULL; |
} |
FT_Set_Transform(face, &m, &v); |
fterr = FT_Load_Glyph(face, gid, FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING); |
if (fterr) |
{ |
fz_warn("FT_Load_Glyph(gid %d): %s", gid, ft_error_string(fterr)); |
return NULL; |
} |
fterr = FT_Stroker_New(fz_ftlib, &stroker); |
if (fterr) |
{ |
fz_warn("FT_Stroker_New: %s", ft_error_string(fterr)); |
return NULL; |
} |
FT_Stroker_Set(stroker, linewidth, state->start_cap, state->linejoin, state->miterlimit * 65536); |
fterr = FT_Get_Glyph(face->glyph, &glyph); |
if (fterr) |
{ |
fz_warn("FT_Get_Glyph: %s", ft_error_string(fterr)); |
FT_Stroker_Done(stroker); |
return NULL; |
} |
fterr = FT_Glyph_Stroke(&glyph, stroker, 1); |
if (fterr) |
{ |
fz_warn("FT_Glyph_Stroke: %s", ft_error_string(fterr)); |
FT_Done_Glyph(glyph); |
FT_Stroker_Done(stroker); |
return NULL; |
} |
FT_Stroker_Done(stroker); |
fterr = FT_Glyph_To_Bitmap(&glyph, fz_get_aa_level() > 0 ? FT_RENDER_MODE_NORMAL : FT_RENDER_MODE_MONO, 0, 1); |
if (fterr) |
{ |
fz_warn("FT_Glyph_To_Bitmap: %s", ft_error_string(fterr)); |
FT_Done_Glyph(glyph); |
return NULL; |
} |
bitmap = (FT_BitmapGlyph)glyph; |
pixmap = fz_copy_ft_bitmap(bitmap->left, bitmap->top, &bitmap->bitmap); |
FT_Done_Glyph(glyph); |
return pixmap; |
} |
/* |
* Type 3 fonts... |
*/ |
fz_font * |
fz_new_type3_font(char *name, fz_matrix matrix) |
{ |
fz_font *font; |
int i; |
font = fz_new_font(name); |
font->t3procs = fz_calloc(256, sizeof(fz_buffer*)); |
font->t3widths = fz_calloc(256, sizeof(float)); |
font->t3matrix = matrix; |
for (i = 0; i < 256; i++) |
{ |
font->t3procs[i] = NULL; |
font->t3widths[i] = 0; |
} |
return font; |
} |
fz_pixmap * |
fz_render_t3_glyph(fz_font *font, int gid, fz_matrix trm, fz_colorspace *model) |
{ |
fz_error error; |
fz_matrix ctm; |
fz_buffer *contents; |
fz_bbox bbox; |
fz_device *dev; |
fz_glyph_cache *cache; |
fz_pixmap *glyph; |
fz_pixmap *result; |
if (gid < 0 || gid > 255) |
return NULL; |
contents = font->t3procs[gid]; |
if (!contents) |
return NULL; |
ctm = fz_concat(font->t3matrix, trm); |
dev = fz_new_bbox_device(&bbox); |
error = font->t3run(font->t3xref, font->t3resources, contents, dev, ctm); |
if (error) |
fz_catch(error, "cannot draw type3 glyph"); |
if (dev->flags & FZ_CHARPROC_MASK) |
{ |
if (dev->flags & FZ_CHARPROC_COLOR) |
fz_warn("type3 glyph claims to be both masked and colored"); |
model = NULL; |
} |
else if (dev->flags & FZ_CHARPROC_COLOR) |
{ |
if (model == NULL) |
fz_warn("colored type3 glyph wanted in masked context"); |
} |
else |
{ |
fz_warn("type3 glyph doesn't specify masked or colored"); |
model = NULL; /* Treat as masked */ |
} |
fz_free_device(dev); |
bbox.x0--; |
bbox.y0--; |
bbox.x1++; |
bbox.y1++; |
glyph = fz_new_pixmap_with_rect(model ? model : fz_device_gray, bbox); |
fz_clear_pixmap(glyph); |
cache = fz_new_glyph_cache(); |
dev = fz_new_draw_device_type3(cache, glyph); |
error = font->t3run(font->t3xref, font->t3resources, contents, dev, ctm); |
if (error) |
fz_catch(error, "cannot draw type3 glyph"); |
fz_free_device(dev); |
fz_free_glyph_cache(cache); |
if (model == NULL) |
{ |
result = fz_alpha_from_gray(glyph, 0); |
fz_drop_pixmap(glyph); |
} |
else |
result = glyph; |
return result; |
} |
void |
fz_debug_font(fz_font *font) |
{ |
printf("font '%s' {\n", font->name); |
if (font->ft_face) |
{ |
printf("\tfreetype face %p\n", font->ft_face); |
if (font->ft_substitute) |
printf("\tsubstitute font\n"); |
} |
if (font->t3procs) |
{ |
printf("\ttype3 matrix [%g %g %g %g]\n", |
font->t3matrix.a, font->t3matrix.b, |
font->t3matrix.c, font->t3matrix.d); |
} |
printf("\tbbox [%g %g %g %g]\n", |
font->bbox.x0, font->bbox.y0, |
font->bbox.x1, font->bbox.y1); |
printf("}\n"); |
} |
/contrib/media/updf/fitz/res_halftone.c |
---|
0,0 → 1,190 |
#include "fitz.h" |
fz_halftone * |
fz_new_halftone(int comps) |
{ |
fz_halftone *ht; |
int i; |
ht = fz_malloc(sizeof(fz_halftone) + (comps-1)*sizeof(fz_pixmap *)); |
ht->refs = 1; |
ht->n = comps; |
for (i = 0; i < comps; i++) |
ht->comp[i] = NULL; |
return ht; |
} |
fz_halftone * |
fz_keep_halftone(fz_halftone *ht) |
{ |
ht->refs++; |
return ht; |
} |
void |
fz_drop_halftone(fz_halftone *ht) |
{ |
int i; |
if (!ht || --ht->refs != 0) |
return; |
for (i = 0; i < ht->n; i++) |
fz_drop_pixmap(ht->comp[i]); |
fz_free(ht); |
} |
/* Default mono halftone, lifted from Ghostscript. */ |
static unsigned char mono_ht[] = |
{ |
0x0E, 0x8E, 0x2E, 0xAE, 0x06, 0x86, 0x26, 0xA6, 0x0C, 0x8C, 0x2C, 0xAC, 0x04, 0x84, 0x24, 0xA4, |
0xCE, 0x4E, 0xEE, 0x6E, 0xC6, 0x46, 0xE6, 0x66, 0xCC, 0x4C, 0xEC, 0x6C, 0xC4, 0x44, 0xE4, 0x64, |
0x3E, 0xBE, 0x1E, 0x9E, 0x36, 0xB6, 0x16, 0x96, 0x3C, 0xBC, 0x1C, 0x9C, 0x34, 0xB4, 0x14, 0x94, |
0xFE, 0x7E, 0xDE, 0x5E, 0xF6, 0x76, 0xD6, 0x56, 0xFC, 0x7C, 0xDC, 0x5C, 0xF4, 0x74, 0xD4, 0x54, |
0x01, 0x81, 0x21, 0xA1, 0x09, 0x89, 0x29, 0xA9, 0x03, 0x83, 0x23, 0xA3, 0x0B, 0x8B, 0x2B, 0xAB, |
0xC1, 0x41, 0xE1, 0x61, 0xC9, 0x49, 0xE9, 0x69, 0xC3, 0x43, 0xE3, 0x63, 0xCB, 0x4B, 0xEB, 0x6B, |
0x31, 0xB1, 0x11, 0x91, 0x39, 0xB9, 0x19, 0x99, 0x33, 0xB3, 0x13, 0x93, 0x3B, 0xBB, 0x1B, 0x9B, |
0xF1, 0x71, 0xD1, 0x51, 0xF9, 0x79, 0xD9, 0x59, 0xF3, 0x73, 0xD3, 0x53, 0xFB, 0x7B, 0xDB, 0x5B, |
0x0D, 0x8D, 0x2D, 0xAD, 0x05, 0x85, 0x25, 0xA5, 0x0F, 0x8F, 0x2F, 0xAF, 0x07, 0x87, 0x27, 0xA7, |
0xCD, 0x4D, 0xED, 0x6D, 0xC5, 0x45, 0xE5, 0x65, 0xCF, 0x4F, 0xEF, 0x6F, 0xC7, 0x47, 0xE7, 0x67, |
0x3D, 0xBD, 0x1D, 0x9D, 0x35, 0xB5, 0x15, 0x95, 0x3F, 0xBF, 0x1F, 0x9F, 0x37, 0xB7, 0x17, 0x97, |
0xFD, 0x7D, 0xDD, 0x5D, 0xF5, 0x75, 0xD5, 0x55, 0xFF, 0x7F, 0xDF, 0x5F, 0xF7, 0x77, 0xD7, 0x57, |
0x02, 0x82, 0x22, 0xA2, 0x0A, 0x8A, 0x2A, 0xAA, 0x00, 0x80, 0x20, 0xA0, 0x08, 0x88, 0x28, 0xA8, |
0xC2, 0x42, 0xE2, 0x62, 0xCA, 0x4A, 0xEA, 0x6A, 0xC0, 0x40, 0xE0, 0x60, 0xC8, 0x48, 0xE8, 0x68, |
0x32, 0xB2, 0x12, 0x92, 0x3A, 0xBA, 0x1A, 0x9A, 0x30, 0xB0, 0x10, 0x90, 0x38, 0xB8, 0x18, 0x98, |
0xF2, 0x72, 0xD2, 0x52, 0xFA, 0x7A, 0xDA, 0x5A, 0xF0, 0x70, 0xD0, 0x50, 0xF8, 0x78, 0xD8, 0x58 |
}; |
fz_halftone *fz_get_default_halftone(int num_comps) |
{ |
fz_halftone *ht = fz_new_halftone(num_comps); |
assert(num_comps == 1); /* Only support 1 component for now */ |
ht->comp[0] = fz_new_pixmap_with_data(NULL, 16, 16, mono_ht); |
return ht; |
} |
/* Finally, code to actually perform halftoning. */ |
static void make_ht_line(unsigned char *buf, fz_halftone *ht, int x, int y, int w) |
{ |
/* FIXME: There is a potential optimisation here; in the case where |
* the LCM of the halftone tile widths is smaller than w, we could |
* form just one 'LCM' run, then copy it repeatedly. |
*/ |
int k, n; |
n = ht->n; |
for (k = 0; k < n; k++) |
{ |
fz_pixmap *tile = ht->comp[k]; |
unsigned char *b = buf++; |
unsigned char *t; |
unsigned char *tbase; |
int px = x + tile->x; |
int py = y + tile->y; |
int tw = tile->w; |
int th = tile->h; |
int w2 = w; |
int len; |
px = px % tw; |
if (px < 0) |
px += tw; |
py = py % th; |
if (py < 0) |
py += th; |
assert(tile->n == 1); |
/* Left hand section; from x to tile width */ |
tbase = tile->samples + py * tw; |
t = tbase + px; |
len = tw - px; |
if (len > w2) |
len = w2; |
w2 -= len; |
while (len--) |
{ |
*b = *t++; |
b += n; |
} |
/* Centre section - complete copies */ |
w2 -= tw; |
while (w2 >= 0) |
{ |
len = tw; |
t = tbase; |
while (len--) |
{ |
*b = *t++; |
b += n; |
} |
w2 -= tw; |
} |
w2 += tw; |
/* Right hand section - stragglers */ |
t = tbase; |
while (w2--) |
{ |
*b = *t++; |
b += n; |
} |
} |
} |
/* Inner mono thresholding code */ |
static void do_threshold_1(unsigned char *ht_line, unsigned char *pixmap, unsigned char *out, int w) |
{ |
int bit = 0x80; |
int h = 0; |
do |
{ |
if (*pixmap < *ht_line++) |
h |= bit; |
pixmap += 2; /* Skip the alpha */ |
bit >>= 1; |
if (bit == 0) |
{ |
*out++ = h; |
h = 0; |
bit = 0x80; |
} |
} |
while (--w); |
if (bit != 0x80) |
*out++ = h; |
} |
fz_bitmap *fz_halftone_pixmap(fz_pixmap *pix, fz_halftone *ht) |
{ |
fz_bitmap *out; |
unsigned char *ht_line, *o, *p; |
int w, h, x, y, n, pstride, ostride; |
if (pix == NULL || ht == NULL) |
return NULL; |
assert(pix->n == 2); /* Mono + Alpha */ |
n = pix->n-1; /* Remove alpha */ |
ht_line = fz_malloc(pix->w * n); |
out = fz_new_bitmap(pix->w, pix->h, n); |
o = out->samples; |
p = pix->samples; |
h = pix->h; |
x = pix->x; |
y = pix->y; |
w = pix->w; |
ostride = out->stride; |
pstride = pix->w * pix->n; |
while (h--) |
{ |
make_ht_line(ht_line, ht, x, y++, w); |
do_threshold_1(ht_line, p, o, w); |
o += ostride; |
p += pstride; |
} |
return out; |
} |
/contrib/media/updf/fitz/res_path.c |
---|
0,0 → 1,262 |
#include "fitz.h" |
fz_path * |
fz_new_path(void) |
{ |
fz_path *path; |
path = fz_malloc(sizeof(fz_path)); |
path->len = 0; |
path->cap = 0; |
path->items = NULL; |
return path; |
} |
fz_path * |
fz_clone_path(fz_path *old) |
{ |
fz_path *path; |
path = fz_malloc(sizeof(fz_path)); |
path->len = old->len; |
path->cap = old->len; |
path->items = fz_calloc(path->cap, sizeof(fz_path_item)); |
memcpy(path->items, old->items, sizeof(fz_path_item) * path->len); |
return path; |
} |
void |
fz_free_path(fz_path *path) |
{ |
fz_free(path->items); |
fz_free(path); |
} |
static void |
grow_path(fz_path *path, int n) |
{ |
if (path->len + n < path->cap) |
return; |
while (path->len + n > path->cap) |
path->cap = path->cap + 36; |
path->items = fz_realloc(path->items, path->cap, sizeof(fz_path_item)); |
} |
void |
fz_moveto(fz_path *path, float x, float y) |
{ |
grow_path(path, 3); |
path->items[path->len++].k = FZ_MOVETO; |
path->items[path->len++].v = x; |
path->items[path->len++].v = y; |
} |
void |
fz_lineto(fz_path *path, float x, float y) |
{ |
if (path->len == 0) |
{ |
fz_warn("lineto with no current point"); |
return; |
} |
grow_path(path, 3); |
path->items[path->len++].k = FZ_LINETO; |
path->items[path->len++].v = x; |
path->items[path->len++].v = y; |
} |
void |
fz_curveto(fz_path *path, |
float x1, float y1, |
float x2, float y2, |
float x3, float y3) |
{ |
if (path->len == 0) |
{ |
fz_warn("curveto with no current point"); |
return; |
} |
grow_path(path, 7); |
path->items[path->len++].k = FZ_CURVETO; |
path->items[path->len++].v = x1; |
path->items[path->len++].v = y1; |
path->items[path->len++].v = x2; |
path->items[path->len++].v = y2; |
path->items[path->len++].v = x3; |
path->items[path->len++].v = y3; |
} |
void |
fz_curvetov(fz_path *path, float x2, float y2, float x3, float y3) |
{ |
float x1, y1; |
if (path->len == 0) |
{ |
fz_warn("curvetov with no current point"); |
return; |
} |
x1 = path->items[path->len-2].v; |
y1 = path->items[path->len-1].v; |
fz_curveto(path, x1, y1, x2, y2, x3, y3); |
} |
void |
fz_curvetoy(fz_path *path, float x1, float y1, float x3, float y3) |
{ |
fz_curveto(path, x1, y1, x3, y3, x3, y3); |
} |
void |
fz_closepath(fz_path *path) |
{ |
if (path->len == 0) |
{ |
fz_warn("closepath with no current point"); |
return; |
} |
grow_path(path, 1); |
path->items[path->len++].k = FZ_CLOSE_PATH; |
} |
static inline fz_rect bound_expand(fz_rect r, fz_point p) |
{ |
if (p.x < r.x0) r.x0 = p.x; |
if (p.y < r.y0) r.y0 = p.y; |
if (p.x > r.x1) r.x1 = p.x; |
if (p.y > r.y1) r.y1 = p.y; |
return r; |
} |
fz_rect |
fz_bound_path(fz_path *path, fz_stroke_state *stroke, fz_matrix ctm) |
{ |
fz_point p; |
fz_rect r = fz_empty_rect; |
int i = 0; |
if (path->len) |
{ |
p.x = path->items[1].v; |
p.y = path->items[2].v; |
p = fz_transform_point(ctm, p); |
r.x0 = r.x1 = p.x; |
r.y0 = r.y1 = p.y; |
} |
while (i < path->len) |
{ |
switch (path->items[i++].k) |
{ |
case FZ_CURVETO: |
p.x = path->items[i++].v; |
p.y = path->items[i++].v; |
r = bound_expand(r, fz_transform_point(ctm, p)); |
p.x = path->items[i++].v; |
p.y = path->items[i++].v; |
r = bound_expand(r, fz_transform_point(ctm, p)); |
p.x = path->items[i++].v; |
p.y = path->items[i++].v; |
r = bound_expand(r, fz_transform_point(ctm, p)); |
break; |
case FZ_MOVETO: |
case FZ_LINETO: |
p.x = path->items[i++].v; |
p.y = path->items[i++].v; |
r = bound_expand(r, fz_transform_point(ctm, p)); |
break; |
case FZ_CLOSE_PATH: |
break; |
} |
} |
if (stroke) |
{ |
float miterlength = stroke->miterlimit; |
float linewidth = stroke->linewidth; |
float expand = MAX(miterlength, linewidth) * 0.5f; |
r.x0 -= expand; |
r.y0 -= expand; |
r.x1 += expand; |
r.y1 += expand; |
} |
return r; |
} |
void |
fz_transform_path(fz_path *path, fz_matrix ctm) |
{ |
fz_point p; |
int k, i = 0; |
while (i < path->len) |
{ |
switch (path->items[i++].k) |
{ |
case FZ_CURVETO: |
for (k = 0; k < 3; k++) |
{ |
p.x = path->items[i].v; |
p.y = path->items[i+1].v; |
p = fz_transform_point(ctm, p); |
path->items[i].v = p.x; |
path->items[i+1].v = p.y; |
i += 2; |
} |
break; |
case FZ_MOVETO: |
case FZ_LINETO: |
p.x = path->items[i].v; |
p.y = path->items[i+1].v; |
p = fz_transform_point(ctm, p); |
path->items[i].v = p.x; |
path->items[i+1].v = p.y; |
i += 2; |
break; |
case FZ_CLOSE_PATH: |
break; |
} |
} |
} |
void |
fz_debug_path(fz_path *path, int indent) |
{ |
float x, y; |
int i = 0; |
int n; |
while (i < path->len) |
{ |
for (n = 0; n < indent; n++) |
putchar(' '); |
switch (path->items[i++].k) |
{ |
case FZ_MOVETO: |
x = path->items[i++].v; |
y = path->items[i++].v; |
printf("%g %g m\n", x, y); |
break; |
case FZ_LINETO: |
x = path->items[i++].v; |
y = path->items[i++].v; |
printf("%g %g l\n", x, y); |
break; |
case FZ_CURVETO: |
x = path->items[i++].v; |
y = path->items[i++].v; |
printf("%g %g ", x, y); |
x = path->items[i++].v; |
y = path->items[i++].v; |
printf("%g %g ", x, y); |
x = path->items[i++].v; |
y = path->items[i++].v; |
printf("%g %g c\n", x, y); |
break; |
case FZ_CLOSE_PATH: |
printf("h\n"); |
break; |
} |
} |
} |
/contrib/media/updf/fitz/res_pixmap.c |
---|
0,0 → 1,519 |
#include "fitz.h" |
static int fz_memory_limit = 256 << 20; |
static int fz_memory_used = 0; |
fz_pixmap * |
fz_new_pixmap_with_data(fz_colorspace *colorspace, int w, int h, unsigned char *samples) |
{ |
fz_pixmap *pix; |
pix = fz_malloc(sizeof(fz_pixmap)); |
pix->refs = 1; |
pix->x = 0; |
pix->y = 0; |
pix->w = w; |
pix->h = h; |
pix->mask = NULL; |
pix->interpolate = 1; |
pix->xres = 96; |
pix->yres = 96; |
pix->colorspace = NULL; |
pix->n = 1; |
if (colorspace) |
{ |
pix->colorspace = fz_keep_colorspace(colorspace); |
pix->n = 1 + colorspace->n; |
} |
if (samples) |
{ |
pix->samples = samples; |
pix->free_samples = 0; |
} |
else |
{ |
fz_memory_used += pix->w * pix->h * pix->n; |
pix->samples = fz_calloc(pix->h, pix->w * pix->n); |
pix->free_samples = 1; |
} |
return pix; |
} |
fz_pixmap * |
fz_new_pixmap_with_limit(fz_colorspace *colorspace, int w, int h) |
{ |
int n = colorspace ? colorspace->n + 1 : 1; |
int size = w * h * n; |
if (fz_memory_used + size > fz_memory_limit) |
{ |
fz_warn("pixmap memory exceeds soft limit %dM + %dM > %dM", |
fz_memory_used/(1<<20), size/(1<<20), fz_memory_limit/(1<<20)); |
return NULL; |
} |
return fz_new_pixmap_with_data(colorspace, w, h, NULL); |
} |
fz_pixmap * |
fz_new_pixmap(fz_colorspace *colorspace, int w, int h) |
{ |
return fz_new_pixmap_with_data(colorspace, w, h, NULL); |
} |
fz_pixmap * |
fz_new_pixmap_with_rect(fz_colorspace *colorspace, fz_bbox r) |
{ |
fz_pixmap *pixmap; |
pixmap = fz_new_pixmap(colorspace, r.x1 - r.x0, r.y1 - r.y0); |
pixmap->x = r.x0; |
pixmap->y = r.y0; |
return pixmap; |
} |
fz_pixmap * |
fz_new_pixmap_with_rect_and_data(fz_colorspace *colorspace, fz_bbox r, unsigned char *samples) |
{ |
fz_pixmap *pixmap; |
pixmap = fz_new_pixmap_with_data(colorspace, r.x1 - r.x0, r.y1 - r.y0, samples); |
pixmap->x = r.x0; |
pixmap->y = r.y0; |
return pixmap; |
} |
fz_pixmap * |
fz_keep_pixmap(fz_pixmap *pix) |
{ |
pix->refs++; |
return pix; |
} |
void |
fz_drop_pixmap(fz_pixmap *pix) |
{ |
if (pix && --pix->refs == 0) |
{ |
fz_memory_used -= pix->w * pix->h * pix->n; |
if (pix->mask) |
fz_drop_pixmap(pix->mask); |
if (pix->colorspace) |
fz_drop_colorspace(pix->colorspace); |
if (pix->free_samples) |
fz_free(pix->samples); |
fz_free(pix); |
} |
} |
fz_bbox |
fz_bound_pixmap(fz_pixmap *pix) |
{ |
fz_bbox bbox; |
bbox.x0 = pix->x; |
bbox.y0 = pix->y; |
bbox.x1 = pix->x + pix->w; |
bbox.y1 = pix->y + pix->h; |
return bbox; |
} |
void |
fz_clear_pixmap(fz_pixmap *pix) |
{ |
memset(pix->samples, 0, pix->w * pix->h * pix->n); |
} |
void |
fz_clear_pixmap_with_color(fz_pixmap *pix, int value) |
{ |
if (value == 255) |
memset(pix->samples, 255, pix->w * pix->h * pix->n); |
else |
{ |
int k, x, y; |
unsigned char *s = pix->samples; |
for (y = 0; y < pix->h; y++) |
{ |
for (x = 0; x < pix->w; x++) |
{ |
for (k = 0; k < pix->n - 1; k++) |
*s++ = value; |
*s++ = 255; |
} |
} |
} |
} |
void |
fz_copy_pixmap_rect(fz_pixmap *dest, fz_pixmap *src, fz_bbox r) |
{ |
const unsigned char *srcp; |
unsigned char *destp; |
int y, w, destspan, srcspan; |
r = fz_intersect_bbox(r, fz_bound_pixmap(dest)); |
r = fz_intersect_bbox(r, fz_bound_pixmap(src)); |
w = r.x1 - r.x0; |
y = r.y1 - r.y0; |
if (w <= 0 || y <= 0) |
return; |
w *= src->n; |
srcspan = src->w * src->n; |
srcp = src->samples + srcspan * (r.y0 - src->y) + src->n * (r.x0 - src->x); |
destspan = dest->w * dest->n; |
destp = dest->samples + destspan * (r.y0 - dest->y) + dest->n * (r.x0 - dest->x); |
do |
{ |
memcpy(destp, srcp, w); |
srcp += srcspan; |
destp += destspan; |
} |
while (--y); |
} |
void |
fz_clear_pixmap_rect_with_color(fz_pixmap *dest, int value, fz_bbox r) |
{ |
unsigned char *destp; |
int x, y, w, k, destspan; |
r = fz_intersect_bbox(r, fz_bound_pixmap(dest)); |
w = r.x1 - r.x0; |
y = r.y1 - r.y0; |
if (w <= 0 || y <= 0) |
return; |
destspan = dest->w * dest->n; |
destp = dest->samples + destspan * (r.y0 - dest->y) + dest->n * (r.x0 - dest->x); |
if (value == 255) |
do |
{ |
memset(destp, 255, w * dest->n); |
destp += destspan; |
} |
while (--y); |
else |
do |
{ |
unsigned char *s = destp; |
for (x = 0; x < w; x++) |
{ |
for (k = 0; k < dest->n - 1; k++) |
*s++ = value; |
*s++ = 255; |
} |
destp += destspan; |
} |
while (--y); |
} |
void |
fz_premultiply_pixmap(fz_pixmap *pix) |
{ |
unsigned char *s = pix->samples; |
unsigned char a; |
int k, x, y; |
for (y = 0; y < pix->h; y++) |
{ |
for (x = 0; x < pix->w; x++) |
{ |
a = s[pix->n - 1]; |
for (k = 0; k < pix->n - 1; k++) |
s[k] = fz_mul255(s[k], a); |
s += pix->n; |
} |
} |
} |
fz_pixmap * |
fz_alpha_from_gray(fz_pixmap *gray, int luminosity) |
{ |
fz_pixmap *alpha; |
unsigned char *sp, *dp; |
int len; |
assert(gray->n == 2); |
alpha = fz_new_pixmap_with_rect(NULL, fz_bound_pixmap(gray)); |
dp = alpha->samples; |
sp = gray->samples; |
if (!luminosity) |
sp ++; |
len = gray->w * gray->h; |
while (len--) |
{ |
*dp++ = sp[0]; |
sp += 2; |
} |
return alpha; |
} |
void |
fz_invert_pixmap(fz_pixmap *pix) |
{ |
unsigned char *s = pix->samples; |
int k, x, y; |
for (y = 0; y < pix->h; y++) |
{ |
for (x = 0; x < pix->w; x++) |
{ |
for (k = 0; k < pix->n - 1; k++) |
s[k] = 255 - s[k]; |
s += pix->n; |
} |
} |
} |
void |
fz_gamma_pixmap(fz_pixmap *pix, float gamma) |
{ |
unsigned char gamma_map[256]; |
unsigned char *s = pix->samples; |
int k, x, y; |
for (k = 0; k < 256; k++) |
gamma_map[k] = pow(k / 255.0f, gamma) * 255; |
for (y = 0; y < pix->h; y++) |
{ |
for (x = 0; x < pix->w; x++) |
{ |
for (k = 0; k < pix->n - 1; k++) |
s[k] = gamma_map[s[k]]; |
s += pix->n; |
} |
} |
} |
/* |
* Write pixmap to PNM file (without alpha channel) |
*/ |
fz_error |
fz_write_pnm(fz_pixmap *pixmap, char *filename) |
{ |
FILE *fp; |
unsigned char *p; |
int len; |
if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4) |
return fz_throw("pixmap must be grayscale or rgb to write as pnm"); |
fp = fopen(filename, "wb"); |
if (!fp) |
return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); |
if (pixmap->n == 1 || pixmap->n == 2) |
fprintf(fp, "P5\n"); |
if (pixmap->n == 4) |
fprintf(fp, "P6\n"); |
fprintf(fp, "%d %d\n", pixmap->w, pixmap->h); |
fprintf(fp, "255\n"); |
len = pixmap->w * pixmap->h; |
p = pixmap->samples; |
switch (pixmap->n) |
{ |
case 1: |
fwrite(p, 1, len, fp); |
break; |
case 2: |
while (len--) |
{ |
putc(p[0], fp); |
p += 2; |
} |
break; |
case 4: |
while (len--) |
{ |
putc(p[0], fp); |
putc(p[1], fp); |
putc(p[2], fp); |
p += 4; |
} |
} |
fclose(fp); |
return fz_okay; |
} |
/* |
* Write pixmap to PAM file (with or without alpha channel) |
*/ |
fz_error |
fz_write_pam(fz_pixmap *pixmap, char *filename, int savealpha) |
{ |
unsigned char *sp; |
int y, w, k; |
FILE *fp; |
int sn = pixmap->n; |
int dn = pixmap->n; |
if (!savealpha && dn > 1) |
dn--; |
fp = fopen(filename, "wb"); |
if (!fp) |
return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); |
fprintf(fp, "P7\n"); |
fprintf(fp, "WIDTH %d\n", pixmap->w); |
fprintf(fp, "HEIGHT %d\n", pixmap->h); |
fprintf(fp, "DEPTH %d\n", dn); |
fprintf(fp, "MAXVAL 255\n"); |
if (pixmap->colorspace) |
fprintf(fp, "# COLORSPACE %s\n", pixmap->colorspace->name); |
switch (dn) |
{ |
case 1: fprintf(fp, "TUPLTYPE GRAYSCALE\n"); break; |
case 2: if (sn == 2) fprintf(fp, "TUPLTYPE GRAYSCALE_ALPHA\n"); break; |
case 3: if (sn == 4) fprintf(fp, "TUPLTYPE RGB\n"); break; |
case 4: if (sn == 4) fprintf(fp, "TUPLTYPE RGB_ALPHA\n"); break; |
} |
fprintf(fp, "ENDHDR\n"); |
sp = pixmap->samples; |
for (y = 0; y < pixmap->h; y++) |
{ |
w = pixmap->w; |
while (w--) |
{ |
for (k = 0; k < dn; k++) |
putc(sp[k], fp); |
sp += sn; |
} |
} |
fclose(fp); |
return fz_okay; |
} |
/* |
* Write pixmap to PNG file (with or without alpha channel) |
*/ |
#include <zlib.h> |
static inline void big32(unsigned char *buf, unsigned int v) |
{ |
buf[0] = (v >> 24) & 0xff; |
buf[1] = (v >> 16) & 0xff; |
buf[2] = (v >> 8) & 0xff; |
buf[3] = (v) & 0xff; |
} |
static inline void put32(unsigned int v, FILE *fp) |
{ |
putc(v >> 24, fp); |
putc(v >> 16, fp); |
putc(v >> 8, fp); |
putc(v, fp); |
} |
static void putchunk(char *tag, unsigned char *data, int size, FILE *fp) |
{ |
unsigned int sum; |
put32(size, fp); |
fwrite(tag, 1, 4, fp); |
fwrite(data, 1, size, fp); |
sum = crc32(0, NULL, 0); |
sum = crc32(sum, (unsigned char*)tag, 4); |
sum = crc32(sum, data, size); |
put32(sum, fp); |
} |
fz_error |
fz_write_png(fz_pixmap *pixmap, char *filename, int savealpha) |
{ |
static const unsigned char pngsig[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; |
FILE *fp; |
unsigned char head[13]; |
unsigned char *udata, *cdata, *sp, *dp; |
uLong usize, csize; |
int y, x, k, sn, dn; |
int color; |
int err; |
if (pixmap->n != 1 && pixmap->n != 2 && pixmap->n != 4) |
return fz_throw("pixmap must be grayscale or rgb to write as png"); |
sn = pixmap->n; |
dn = pixmap->n; |
if (!savealpha && dn > 1) |
dn--; |
switch (dn) |
{ |
default: |
case 1: color = 0; break; |
case 2: color = 4; break; |
case 3: color = 2; break; |
case 4: color = 6; break; |
} |
usize = (pixmap->w * dn + 1) * pixmap->h; |
csize = compressBound(usize); |
udata = fz_malloc(usize); |
cdata = fz_malloc(csize); |
sp = pixmap->samples; |
dp = udata; |
for (y = 0; y < pixmap->h; y++) |
{ |
*dp++ = 1; /* sub prediction filter */ |
for (x = 0; x < pixmap->w; x++) |
{ |
for (k = 0; k < dn; k++) |
{ |
if (x == 0) |
dp[k] = sp[k]; |
else |
dp[k] = sp[k] - sp[k-sn]; |
} |
sp += sn; |
dp += dn; |
} |
} |
err = compress(cdata, &csize, udata, usize); |
if (err != Z_OK) |
{ |
fz_free(udata); |
fz_free(cdata); |
return fz_throw("cannot compress image data"); |
} |
fp = fopen(filename, "wb"); |
if (!fp) |
{ |
fz_free(udata); |
fz_free(cdata); |
return fz_throw("cannot open file '%s': %s", filename, strerror(errno)); |
} |
big32(head+0, pixmap->w); |
big32(head+4, pixmap->h); |
head[8] = 8; /* depth */ |
head[9] = color; |
head[10] = 0; /* compression */ |
head[11] = 0; /* filter */ |
head[12] = 0; /* interlace */ |
fwrite(pngsig, 1, 8, fp); |
putchunk("IHDR", head, 13, fp); |
putchunk("IDAT", cdata, csize, fp); |
putchunk("IEND", head, 0, fp); |
fclose(fp); |
fz_free(udata); |
fz_free(cdata); |
return fz_okay; |
} |
/contrib/media/updf/fitz/res_shade.c |
---|
0,0 → 1,127 |
#include "fitz.h" |
fz_shade * |
fz_keep_shade(fz_shade *shade) |
{ |
shade->refs ++; |
return shade; |
} |
void |
fz_drop_shade(fz_shade *shade) |
{ |
if (shade && --shade->refs == 0) |
{ |
if (shade->colorspace) |
fz_drop_colorspace(shade->colorspace); |
fz_free(shade->mesh); |
fz_free(shade); |
} |
} |
fz_rect |
fz_bound_shade(fz_shade *shade, fz_matrix ctm) |
{ |
float *v; |
fz_rect r; |
fz_point p; |
int i, ncomp, nvert; |
ctm = fz_concat(shade->matrix, ctm); |
ncomp = shade->use_function ? 3 : 2 + shade->colorspace->n; |
nvert = shade->mesh_len / ncomp; |
v = shade->mesh; |
if (shade->type == FZ_LINEAR) |
return fz_infinite_rect; |
if (shade->type == FZ_RADIAL) |
return fz_infinite_rect; |
if (nvert == 0) |
return fz_empty_rect; |
p.x = v[0]; |
p.y = v[1]; |
v += ncomp; |
p = fz_transform_point(ctm, p); |
r.x0 = r.x1 = p.x; |
r.y0 = r.y1 = p.y; |
for (i = 1; i < nvert; i++) |
{ |
p.x = v[0]; |
p.y = v[1]; |
p = fz_transform_point(ctm, p); |
v += ncomp; |
if (p.x < r.x0) r.x0 = p.x; |
if (p.y < r.y0) r.y0 = p.y; |
if (p.x > r.x1) r.x1 = p.x; |
if (p.y > r.y1) r.y1 = p.y; |
} |
return r; |
} |
void |
fz_debug_shade(fz_shade *shade) |
{ |
int i, j, n; |
float *vertex; |
int triangle; |
printf("shading {\n"); |
switch (shade->type) |
{ |
case FZ_LINEAR: printf("\ttype linear\n"); break; |
case FZ_RADIAL: printf("\ttype radial\n"); break; |
case FZ_MESH: printf("\ttype mesh\n"); break; |
} |
printf("\tbbox [%g %g %g %g]\n", |
shade->bbox.x0, shade->bbox.y0, |
shade->bbox.x1, shade->bbox.y1); |
printf("\tcolorspace %s\n", shade->colorspace->name); |
printf("\tmatrix [%g %g %g %g %g %g]\n", |
shade->matrix.a, shade->matrix.b, shade->matrix.c, |
shade->matrix.d, shade->matrix.e, shade->matrix.f); |
if (shade->use_background) |
{ |
printf("\tbackground ["); |
for (i = 0; i < shade->colorspace->n; i++) |
printf("%s%g", i == 0 ? "" : " ", shade->background[i]); |
printf("]\n"); |
} |
if (shade->use_function) |
{ |
printf("\tfunction\n"); |
n = 3; |
} |
else |
n = 2 + shade->colorspace->n; |
printf("\tvertices: %d\n", shade->mesh_len); |
vertex = shade->mesh; |
triangle = 0; |
i = 0; |
while (i < shade->mesh_len) |
{ |
printf("\t%d:(%g, %g): ", triangle, vertex[0], vertex[1]); |
for (j = 2; j < n; j++) |
printf("%s%g", j == 2 ? "" : " ", vertex[j]); |
printf("\n"); |
vertex += n; |
i++; |
if (i % 3 == 0) |
triangle++; |
} |
printf("}\n"); |
} |
/contrib/media/updf/fitz/res_text.c |
---|
0,0 → 1,133 |
#include "fitz.h" |
fz_text * |
fz_new_text(fz_font *font, fz_matrix trm, int wmode) |
{ |
fz_text *text; |
text = fz_malloc(sizeof(fz_text)); |
text->font = fz_keep_font(font); |
text->trm = trm; |
text->wmode = wmode; |
text->len = 0; |
text->cap = 0; |
text->items = NULL; |
return text; |
} |
void |
fz_free_text(fz_text *text) |
{ |
fz_drop_font(text->font); |
fz_free(text->items); |
fz_free(text); |
} |
fz_text * |
fz_clone_text(fz_text *old) |
{ |
fz_text *text; |
text = fz_malloc(sizeof(fz_text)); |
text->font = fz_keep_font(old->font); |
text->trm = old->trm; |
text->wmode = old->wmode; |
text->len = old->len; |
text->cap = text->len; |
text->items = fz_calloc(text->len, sizeof(fz_text_item)); |
memcpy(text->items, old->items, text->len * sizeof(fz_text_item)); |
return text; |
} |
fz_rect |
fz_bound_text(fz_text *text, fz_matrix ctm) |
{ |
fz_matrix trm; |
fz_rect bbox; |
fz_rect fbox; |
int i; |
if (text->len == 0) |
return fz_empty_rect; |
/* find bbox of glyph origins in ctm space */ |
bbox.x0 = bbox.x1 = text->items[0].x; |
bbox.y0 = bbox.y1 = text->items[0].y; |
for (i = 1; i < text->len; i++) |
{ |
bbox.x0 = MIN(bbox.x0, text->items[i].x); |
bbox.y0 = MIN(bbox.y0, text->items[i].y); |
bbox.x1 = MAX(bbox.x1, text->items[i].x); |
bbox.y1 = MAX(bbox.y1, text->items[i].y); |
} |
bbox = fz_transform_rect(ctm, bbox); |
/* find bbox of font in trm * ctm space */ |
trm = fz_concat(text->trm, ctm); |
trm.e = 0; |
trm.f = 0; |
fbox.x0 = text->font->bbox.x0 * 0.001f; |
fbox.y0 = text->font->bbox.y0 * 0.001f; |
fbox.x1 = text->font->bbox.x1 * 0.001f; |
fbox.y1 = text->font->bbox.y1 * 0.001f; |
fbox = fz_transform_rect(trm, fbox); |
/* expand glyph origin bbox by font bbox */ |
bbox.x0 += fbox.x0; |
bbox.y0 += fbox.y0; |
bbox.x1 += fbox.x1; |
bbox.y1 += fbox.y1; |
return bbox; |
} |
static void |
fz_grow_text(fz_text *text, int n) |
{ |
if (text->len + n < text->cap) |
return; |
while (text->len + n > text->cap) |
text->cap = text->cap + 36; |
text->items = fz_realloc(text->items, text->cap, sizeof(fz_text_item)); |
} |
void |
fz_add_text(fz_text *text, int gid, int ucs, float x, float y) |
{ |
fz_grow_text(text, 1); |
text->items[text->len].ucs = ucs; |
text->items[text->len].gid = gid; |
text->items[text->len].x = x; |
text->items[text->len].y = y; |
text->len++; |
} |
static int isxmlmeta(int c) |
{ |
return c < 32 || c >= 128 || c == '&' || c == '<' || c == '>' || c == '\'' || c == '"'; |
} |
void fz_debug_text(fz_text *text, int indent) |
{ |
int i, n; |
for (i = 0; i < text->len; i++) |
{ |
for (n = 0; n < indent; n++) |
putchar(' '); |
if (!isxmlmeta(text->items[i].ucs)) |
printf("<g ucs=\"%c\" gid=\"%d\" x=\"%g\" y=\"%g\" />\n", |
text->items[i].ucs, text->items[i].gid, text->items[i].x, text->items[i].y); |
else |
printf("<g ucs=\"U+%04X\" gid=\"%d\" x=\"%g\" y=\"%g\" />\n", |
text->items[i].ucs, text->items[i].gid, text->items[i].x, text->items[i].y); |
} |
} |
/contrib/media/updf/fitz/stm_buffer.c |
---|
0,0 → 1,49 |
#include "fitz.h" |
fz_buffer * |
fz_new_buffer(int size) |
{ |
fz_buffer *b; |
size = size > 1 ? size : 16; |
b = fz_malloc(sizeof(fz_buffer)); |
b->refs = 1; |
b->data = fz_malloc(size); |
b->cap = size; |
b->len = 0; |
return b; |
} |
fz_buffer * |
fz_keep_buffer(fz_buffer *buf) |
{ |
buf->refs ++; |
return buf; |
} |
void |
fz_drop_buffer(fz_buffer *buf) |
{ |
if (--buf->refs == 0) |
{ |
fz_free(buf->data); |
fz_free(buf); |
} |
} |
void |
fz_resize_buffer(fz_buffer *buf, int size) |
{ |
buf->data = fz_realloc(buf->data, size, 1); |
buf->cap = size; |
if (buf->len > buf->cap) |
buf->len = buf->cap; |
} |
void |
fz_grow_buffer(fz_buffer *buf) |
{ |
fz_resize_buffer(buf, (buf->cap * 3) / 2); |
} |
/contrib/media/updf/fitz/stm_open.c |
---|
0,0 → 1,174 |
#include "fitz.h" |
fz_stream * |
fz_new_stream(void *state, |
int(*read)(fz_stream *stm, unsigned char *buf, int len), |
void(*close)(fz_stream *stm)) |
{ |
fz_stream *stm; |
stm = fz_malloc(sizeof(fz_stream)); |
stm->refs = 1; |
stm->error = 0; |
stm->eof = 0; |
stm->pos = 0; |
stm->bits = 0; |
stm->avail = 0; |
stm->bp = stm->buf; |
stm->rp = stm->bp; |
stm->wp = stm->bp; |
stm->ep = stm->buf + sizeof stm->buf; |
stm->state = state; |
stm->read = read; |
stm->close = close; |
stm->seek = NULL; |
return stm; |
} |
fz_stream * |
fz_keep_stream(fz_stream *stm) |
{ |
stm->refs ++; |
return stm; |
} |
void |
fz_close(fz_stream *stm) |
{ |
stm->refs --; |
if (stm->refs == 0) |
{ |
if (stm->close) |
stm->close(stm); |
fz_free(stm); |
} |
} |
/* File stream */ |
static int read_file(fz_stream *stm, unsigned char *buf, int len) |
{ |
int n = read(*(int*)stm->state, buf, len); |
if (n < 0) |
return fz_throw("read error: %s", strerror(errno)); |
return n; |
} |
static void seek_file(fz_stream *stm, int offset, int whence) |
{ |
int n = lseek(*(int*)stm->state, offset, whence); |
if (n < 0) |
fz_warn("cannot lseek: %s", strerror(errno)); |
stm->pos = n; |
stm->rp = stm->bp; |
stm->wp = stm->bp; |
} |
static void close_file(fz_stream *stm) |
{ |
int n = close(*(int*)stm->state); |
if (n < 0) |
fz_warn("close error: %s", strerror(errno)); |
fz_free(stm->state); |
} |
fz_stream * |
fz_open_fd(int fd) |
{ |
fz_stream *stm; |
int *state; |
state = fz_malloc(sizeof(int)); |
*state = fd; |
stm = fz_new_stream(state, read_file, close_file); |
stm->seek = seek_file; |
return stm; |
} |
fz_stream * |
fz_open_file(const char *name) |
{ |
int fd = open(name, O_BINARY | O_RDONLY, 0); |
if (fd == -1) |
return NULL; |
return fz_open_fd(fd); |
} |
#ifdef _WIN32 |
fz_stream * |
fz_open_file_w(const wchar_t *name) |
{ |
int fd = _wopen(name, O_BINARY | O_RDONLY, 0); |
if (fd == -1) |
return NULL; |
return fz_open_fd(fd); |
} |
#endif |
/* Memory stream */ |
static int read_buffer(fz_stream *stm, unsigned char *buf, int len) |
{ |
return 0; |
} |
static void seek_buffer(fz_stream *stm, int offset, int whence) |
{ |
if (whence == 0) |
stm->rp = stm->bp + offset; |
if (whence == 1) |
stm->rp += offset; |
if (whence == 2) |
stm->rp = stm->ep - offset; |
stm->rp = CLAMP(stm->rp, stm->bp, stm->ep); |
stm->wp = stm->ep; |
} |
static void close_buffer(fz_stream *stm) |
{ |
if (stm->state) |
fz_drop_buffer(stm->state); |
} |
fz_stream * |
fz_open_buffer(fz_buffer *buf) |
{ |
fz_stream *stm; |
stm = fz_new_stream(fz_keep_buffer(buf), read_buffer, close_buffer); |
stm->seek = seek_buffer; |
stm->bp = buf->data; |
stm->rp = buf->data; |
stm->wp = buf->data + buf->len; |
stm->ep = buf->data + buf->len; |
stm->pos = buf->len; |
return stm; |
} |
fz_stream * |
fz_open_memory(unsigned char *data, int len) |
{ |
fz_stream *stm; |
stm = fz_new_stream(NULL, read_buffer, close_buffer); |
stm->seek = seek_buffer; |
stm->bp = data; |
stm->rp = data; |
stm->wp = data + len; |
stm->ep = data + len; |
stm->pos = len; |
return stm; |
} |
/contrib/media/updf/fitz/stm_read.c |
---|
0,0 → 1,201 |
#include "fitz.h" |
int |
fz_read(fz_stream *stm, unsigned char *buf, int len) |
{ |
int count, n; |
count = MIN(len, stm->wp - stm->rp); |
if (count) |
{ |
memcpy(buf, stm->rp, count); |
stm->rp += count; |
} |
if (count == len || stm->error || stm->eof) |
return count; |
assert(stm->rp == stm->wp); |
if (len - count < stm->ep - stm->bp) |
{ |
n = stm->read(stm, stm->bp, stm->ep - stm->bp); |
if (n < 0) |
{ |
stm->error = 1; |
return fz_rethrow(n, "read error"); |
} |
else if (n == 0) |
{ |
stm->eof = 1; |
} |
else if (n > 0) |
{ |
stm->rp = stm->bp; |
stm->wp = stm->bp + n; |
stm->pos += n; |
} |
n = MIN(len - count, stm->wp - stm->rp); |
if (n) |
{ |
memcpy(buf + count, stm->rp, n); |
stm->rp += n; |
count += n; |
} |
} |
else |
{ |
n = stm->read(stm, buf + count, len - count); |
if (n < 0) |
{ |
stm->error = 1; |
return fz_rethrow(n, "read error"); |
} |
else if (n == 0) |
{ |
stm->eof = 1; |
} |
else if (n > 0) |
{ |
stm->pos += n; |
count += n; |
} |
} |
return count; |
} |
void |
fz_fill_buffer(fz_stream *stm) |
{ |
int n; |
assert(stm->rp == stm->wp); |
if (stm->error || stm->eof) |
return; |
n = stm->read(stm, stm->bp, stm->ep - stm->bp); |
if (n < 0) |
{ |
stm->error = 1; |
fz_catch(n, "read error; treating as end of file"); |
} |
else if (n == 0) |
{ |
stm->eof = 1; |
} |
else if (n > 0) |
{ |
stm->rp = stm->bp; |
stm->wp = stm->bp + n; |
stm->pos += n; |
} |
} |
fz_error |
fz_read_all(fz_buffer **bufp, fz_stream *stm, int initial) |
{ |
fz_buffer *buf; |
int n; |
if (initial < 1024) |
initial = 1024; |
buf = fz_new_buffer(initial); |
while (1) |
{ |
if (buf->len == buf->cap) |
fz_grow_buffer(buf); |
if (buf->len / 200 > initial) |
{ |
fz_drop_buffer(buf); |
return fz_throw("compression bomb detected"); |
} |
n = fz_read(stm, buf->data + buf->len, buf->cap - buf->len); |
if (n < 0) |
{ |
fz_drop_buffer(buf); |
return fz_rethrow(n, "read error"); |
} |
if (n == 0) |
break; |
buf->len += n; |
} |
*bufp = buf; |
return fz_okay; |
} |
void |
fz_read_line(fz_stream *stm, char *mem, int n) |
{ |
char *s = mem; |
int c = EOF; |
while (n > 1) |
{ |
c = fz_read_byte(stm); |
if (c == EOF) |
break; |
if (c == '\r') { |
c = fz_peek_byte(stm); |
if (c == '\n') |
fz_read_byte(stm); |
break; |
} |
if (c == '\n') |
break; |
*s++ = c; |
n--; |
} |
if (n) |
*s = '\0'; |
} |
int |
fz_tell(fz_stream *stm) |
{ |
return stm->pos - (stm->wp - stm->rp); |
} |
void |
fz_seek(fz_stream *stm, int offset, int whence) |
{ |
if (stm->seek) |
{ |
if (whence == 1) |
{ |
offset = fz_tell(stm) + offset; |
whence = 0; |
} |
if (whence == 0) |
{ |
unsigned char *p = stm->wp - (stm->pos - offset); |
if (p >= stm->bp && p <= stm->wp) |
{ |
stm->rp = p; |
stm->eof = 0; |
return; |
} |
} |
stm->seek(stm, offset, whence); |
stm->eof = 0; |
} |
else if (whence != 2) |
{ |
if (whence == 0) |
offset -= fz_tell(stm); |
if (offset < 0) |
fz_warn("cannot seek backwards"); |
/* dog slow, but rare enough */ |
while (offset-- > 0) |
fz_read_byte(stm); |
} |
else |
fz_warn("cannot seek"); |
} |
/contrib/media/updf/fitz/strtoll.c |
---|
0,0 → 1,30 |
#include <ctype.h> |
#include <stdlib.h> |
#include <limits.h> |
#include <errno.h> |
#include <inttypes.h> |
long long int strtoll(const char *nptr, char **endptr, int base) |
{ |
int neg=0; |
unsigned long long int v; |
const char*orig=nptr; |
while(isspace(*nptr)) nptr++; |
if (*nptr == '-' && isalnum(nptr[1])) { neg=-1; nptr++; } |
v=strtoull(nptr,endptr,base); |
if (endptr && *endptr==nptr) *endptr=(char *)orig; |
if (v>LLONG_MAX) { |
if (v==0x8000000000000000ull && neg) { |
errno=0; |
return v; |
} |
errno=ERANGE; |
return (neg?LLONG_MIN:LLONG_MAX); |
} |
return (neg?-v:v); |
} |
intmax_t strtoimax(const char *nptr, char **endptr, int base) |
__attribute__((alias("strtoll"))); |
/contrib/media/updf/fitz/strtoull.c |
---|
0,0 → 1,68 |
#include <ctype.h> |
#include <stdlib.h> |
#include <errno.h> |
#include <limits.h> |
#include <inttypes.h> |
#define __expect(foo,bar) (foo) |
#define __likely(foo) __expect((foo),1) |
#define __unlikely(foo) __expect((foo),0) |
unsigned long long int strtoull(const char *ptr, char **endptr, int base) |
{ |
int neg = 0, overflow = 0; |
long long int v=0; |
const char* orig; |
const char* nptr=ptr; |
while(isspace(*nptr)) ++nptr; |
if (*nptr == '-') { neg=1; nptr++; } |
else if (*nptr == '+') ++nptr; |
orig=nptr; |
if (base==16 && nptr[0]=='0') goto skip0x; |
if (base) { |
register unsigned int b=base-2; |
if (__unlikely(b>34)) { errno=EINVAL; return 0; } |
} else { |
if (*nptr=='0') { |
base=8; |
skip0x: |
if (((*(nptr+1)=='x')||(*(nptr+1)=='X')) && isxdigit(nptr[2])) { |
nptr+=2; |
base=16; |
} |
} else |
base=10; |
} |
while(__likely(*nptr)) { |
register unsigned char c=*nptr; |
c=(c>='a'?c-'a'+10:c>='A'?c-'A'+10:c<='9'?c-'0':0xff); |
if (__unlikely(c>=base)) break; /* out of base */ |
{ |
register unsigned long x=(v&0xff)*base+c; |
register unsigned long long w=(v>>8)*base+(x>>8); |
if (w>(ULLONG_MAX>>8)) overflow=1; |
v=(w<<8)+(x&0xff); |
} |
++nptr; |
} |
if (__unlikely(nptr==orig)) { /* no conversion done */ |
nptr=ptr; |
errno=EINVAL; |
v=0; |
} |
if (endptr) *endptr=(char *)nptr; |
if (overflow) { |
errno=ERANGE; |
return ULLONG_MAX; |
} |
return (neg?-v:v); |
} |
/* die, BSD, die!!! */ |
unsigned long long int strtouq(const char *nptr, char **endptr, int base) |
__attribute__((alias("strtoull"))); |
uintmax_t strtoumax(const char *nptr, char **endptr, int base) |
__attribute__((alias("strtoull"))); |