static int init_scales(t_fdf *e) { if (!e->npw) return (0); if (e->npw == 1 && e->nph == 1) { *(int *)(e->buf + e->hig / 2 * e->lin + e->wid / 2 * e->bit) = my_col(e, e->p[0][0].z); return (0); } e->off = FT_MIN(e->wid, e->hig) / (double)FT_MIN(e->npw, e->nph); e->dx = FDF_SQRT2_2 * (-(e->nph - 1) * e->off) * -1; e->dy = FDF_SQRT_23_ * e->p[0][0].z; e->fx = e->wid / (FDF_SQRT2_2 * ((e->npw - 1) * e->off) + e->dx); e->fy = e->hig / (FDF_SQRT_23_ * -e->p[e->nph - 1][e->npw - 1].z + FDF_1_SQRT6 * ((e->npw - 1) * e->off + (e->nph - 1) * e->off) + e->dy); e->f = FT_MIN(e->fx, e->fy); if (e->fy < e->fx) e->dx += (e->wid - ((FDF_SQRT2_2 * ((e->npw - 1) * e->off) + e->dx) - e->dx * e->f)) / 2.; else e->dy += (e->hig - ((FDF_SQRT_23_ * -e->p[e->nph - 1][e->npw - 1].z + FDF_1_SQRT6 * ((e->npw - 1) * e->off + (e->nph - 1) * e->off) + e->dy) * e->f - (FDF_SQRT_23_ * -e->p[0][0].z + e->dy) * e->f)) / 2.; return (1); }
void ft_put_pixel_to_image(t_img img, int x, int y, t_color3 color) { int addr; addr = y * img.sizeline + x * (img.bpp / 8); img.data[addr + 0] = FT_MAX(FT_MIN(color.b * 255, 255), 0); img.data[addr + 1] = FT_MAX(FT_MIN(color.g * 255, 255), 0); img.data[addr + 2] = FT_MAX(FT_MIN(color.r * 255, 255), 0); }
void draw_flat_map(t_map *map, t_img *img) { float s; t_pix i; t_pix os; s = FT_MIN(img->width / (float)map->width, img->height / (float)map->height) * 0.9; os.x = img->width / 2 - map->width * s / 2; os.y = img->height / 2 - map->height * s / 2; i.x = -1; while (++i.x < map->width) { i.y = -1; while (++i.y < map->height) { draw_tex(img, tile_at_index(map, i.x, i.y), (t_pix){i.x + os.x / s, i.y + os.y / s}, s); } } set_color(0xFF0000); i = (t_pix){map->eye->pos.x * s + os.x, map->eye->pos.y * s + os.y}; draw_circle(img, i, s / 2); set_color(0xFFFF00); draw_line(img, i, (t_pix){i.x + map->eye->dir.x * s, i.y + map->eye->dir.y * s}); set_color(0x00FF00); draw_line(img, i, (t_pix){i.x + (map->eye->dir.x + map->eye->plane.x) * s, i.y + (map->eye->dir.y + map->eye->plane.y) * s}); draw_line(img, i, (t_pix){i.x + (map->eye->dir.x - map->eye->plane.x) * s, i.y + (map->eye->dir.y - map->eye->plane.y) * s}); }
int collision_test_sphere(t_ray_result *r, t_sphere *sphere) { t_real a; t_real b; t_real c; t_real det; a = collision_test_sphere_a(&r->ray.direction); b = collision_test_sphere_b(&r->ray, &sphere->position); c = collision_test_sphere_c(&r->ray, sphere); det = ft_pow(b, 2) - (4 * a * c); if (!det) r->distance = -(b / 2 * a); else if (det > 0) r->distance = FT_MIN((-b - sqrt(det)) / (2 * a), (-b + sqrt(det)) / (2 * a)); else return (0); r->hit = OT_SPHERE; r->contact.point = vec3_add(r->ray.origin, vec3_scale(r->ray.direction, r->distance)); return (1); }
void writes_str(const char *s, t_printf_arg *a) { size_t i; size_t j; size_t size; size = ft_strlen(s); size = (a->prec.right != -1) ? FT_MIN((size_t)a->prec.right, size) : size; a->size = FT_MAX((int)size, a->prec.left); if (!(a->buf = ft_strnew(a->size))) return ; if ((i = -1) && !s && !(a->flags & deci)) return ((void)(ft_memcpy(a->buf, "(null)", (a->size = 6)))); if (!(j = 0) && !(a->flags & less)) { while (++i < a->size - size) a->buf[i] = (!(a->flags & zero)) ? ' ' : '0'; while (i < a->size) a->buf[i++] = s[j++]; } else { while (++i < size) a->buf[i] = s[i]; while (i < a->size) a->buf[i++] = ' '; } }
void writes_uchar(unsigned char c, t_printf_arg *arg) { size_t i; size_t size; size = (arg->prec.right > 0) ? FT_MIN(arg->prec.right, 1) : 1; arg->size = FT_MAX((int)size, arg->prec.left); i = -1; if (!(arg->buf = ft_strnew(arg->size))) return ; if (!(arg->flags & less)) { while (++i < arg->size - size) arg->buf[i] = (!(arg->flags & zero)) ? ' ' : '0'; arg->buf[i] = c; } else { arg->buf[++i] = c; while (++i < arg->size) arg->buf[i] = ' '; } if (!arg->size) arg->size = 1; }
void writes_wintt(wchar_t c, t_printf_arg *arg) { size_t i; size_t size; size_t size2; size = (arg->prec.right > 0) ? FT_MIN(arg->prec.right, 1) : 1; size2 = FT_MAX((int)size, arg->prec.left); i = -1; if (!(arg->buf = ft_strnew(size2 * 4))) return ; if (!(arg->flags & less)) { while (++i < size2 - size) arg->buf[arg->size++] = (!(arg->flags & zero)) ? ' ' : '0'; add_char(c, arg); } else { if (c && i++) add_char(c, arg); while (++i < size2) arg->buf[arg->size++] = ' '; } if (!arg->size) arg->size = 1; }
static int check_list(t_fdf *e, t_list **list) { int i; int j; t_list *tmp; if (!(tmp = my_first_init(e, list, &i))) return (0); while ((j = -1) && tmp) { if (!(e->p[--i] = (t_3d *)malloc((e->npw + 1) * sizeof(t_3d)))) { ft_lstdel(list, &my_lstdel); return (0); } while (((char **)tmp->content)[++j]) { e->p[i][j].z = ft_atoi(((char **)tmp->content)[j]); e->mia = FT_MIN(e->mia, e->p[i][j].z); e->maa = FT_MAX(e->maa, e->p[i][j].z); } while (j < e->npw) e->p[i][j++].z = 0; tmp = tmp->next; } ft_lstdel(list, &my_lstdel); return (1); }
void *ft_memrealloc(void *s, size_t old_n, size_t new_n) { t_uchar *tmp; if (!new_n || old_n == new_n) return (s); if ((tmp = (t_uchar*)ft_memalloc(new_n * sizeof(t_uchar)))) { old_n = (size_t)FT_MIN(old_n, new_n); ft_memcpy(tmp, s, old_n); if (s) free(s); s = tmp; } return (tmp); }
t_bool intersect_sphere(t_ray ray, t_sphere* obj, float *t) { t_vector3 etoc; float radius; float vector_radius; etoc = vector_substract(obj->pos, ray.pos); if ((vector_radius = vector_dotproduct(etoc, ray.dir)) < 0.) return (FALSE); *t = vector_dotproduct(etoc, etoc) - SQUARE(vector_radius); if (*t > (radius = SQUARE(obj->radius))) return (FALSE); *t = sqrt(radius - *t); *t = FT_MIN((vector_radius - *t), (vector_radius + *t)); return (TRUE); }
static OSErr FT_FSPathMakeSpec( const UInt8* pathname, FSSpec* spec_p, Boolean isDirectory ) { const char *p, *q; short vRefNum; long dirID; Str255 nodeName; OSErr err; p = q = (const char *)pathname; dirID = 0; vRefNum = 0; while ( 1 ) { q = p + FT_MIN( 255, ft_strlen( p ) ); if ( q == p ) return 0; if ( 255 < ft_strlen( (char *)pathname ) ) { while ( p < q && *q != ':' ) q--; } if ( p < q ) *(char *)nodeName = q - p; else if ( ft_strlen( p ) < 256 ) *(char *)nodeName = ft_strlen( p ); else return errFSNameTooLong; ft_strncpy( (char *)nodeName + 1, (char *)p, *(char *)nodeName ); err = FSMakeFSSpec( vRefNum, dirID, nodeName, spec_p ); if ( err || '\0' == *q ) return err; vRefNum = spec_p->vRefNum; dirID = spec_p->parID; p = q; } }
void writes_wstr(const wchar_t *str, t_printf_arg *arg) { size_t sizes[4]; sizes[1] = 0; if (str) while (str[sizes[1]]) sizes[1]++; sizes[3] = ft_wstrlen(str, sizes[1], INT_MAX); sizes[3] = (arg->prec.right != -1) ? FT_MIN((int)ft_wstrlen(str, INT_MAX, arg->prec.right), (int)(sizes[3])) : (int)sizes[3]; sizes[2] = FT_MAX((int)(sizes[3]), arg->prec.left); if (!(arg->buf = ft_strnew(sizes[2] * 4))) return ; if (!str && !(arg->flags & deci)) return ((void)(ft_memcpy(arg->buf, "(null)", (arg->size = 6)))); wstr_less_or_not(str, arg, sizes); }
ft_lcd_padding( FT_BBox* cbox, FT_GlyphSlot slot, FT_Render_Mode mode ) { FT_Vector* sub = slot->library->lcd_geometry; if ( mode == FT_RENDER_MODE_LCD ) { cbox->xMin -= FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x ); cbox->xMax -= FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x ); cbox->yMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y ); cbox->yMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y ); } else if ( mode == FT_RENDER_MODE_LCD_V ) { cbox->xMin -= FT_MAX( FT_MAX( sub[0].y, sub[1].y ), sub[2].y ); cbox->xMax -= FT_MIN( FT_MIN( sub[0].y, sub[1].y ), sub[2].y ); cbox->yMin += FT_MIN( FT_MIN( sub[0].x, sub[1].x ), sub[2].x ); cbox->yMax += FT_MAX( FT_MAX( sub[0].x, sub[1].x ), sub[2].x ); } }
FT_Outline_EmboldenXY( FT_Outline* outline, FT_Pos xstrength, FT_Pos ystrength ) { FT_Vector* points; FT_Vector v_prev, v_first, v_next, v_cur; FT_Int c, n, first; FT_Int orientation; if ( !outline ) return FT_Err_Invalid_Argument; xstrength /= 2; ystrength /= 2; if ( xstrength == 0 && ystrength == 0 ) return FT_Err_Ok; orientation = FT_Outline_Get_Orientation( outline ); if ( orientation == FT_ORIENTATION_NONE ) { if ( outline->n_contours ) return FT_Err_Invalid_Argument; else return FT_Err_Ok; } points = outline->points; first = 0; for ( c = 0; c < outline->n_contours; c++ ) { FT_Vector in, out, shift; FT_Fixed l_in, l_out, l, q, d; int last = outline->contours[c]; v_first = points[first]; v_prev = points[last]; v_cur = v_first; /* compute the incoming vector and its length */ in.x = v_cur.x - v_prev.x; in.y = v_cur.y - v_prev.y; l_in = FT_Vector_Length( &in ); for ( n = first; n <= last; n++ ) { if ( n < last ) v_next = points[n + 1]; else v_next = v_first; /* compute the outgoing vector and its length */ out.x = v_next.x - v_cur.x; out.y = v_next.y - v_cur.y; l_out = FT_Vector_Length( &out ); d = l_in * l_out + in.x * out.x + in.y * out.y; /* shift only if turn is less then ~160 degrees */ if ( 16 * d > l_in * l_out ) { /* shift components are aligned along bisector */ /* and directed according to the outline orientation. */ shift.x = l_out * in.y + l_in * out.y; shift.y = l_out * in.x + l_in * out.x; if ( orientation == FT_ORIENTATION_TRUETYPE ) shift.x = -shift.x; else shift.y = -shift.y; /* threshold strength to better handle collapsing segments */ l = FT_MIN( l_in, l_out ); q = out.x * in.y - out.y * in.x; if ( orientation == FT_ORIENTATION_TRUETYPE ) q = -q; if ( FT_MulDiv( xstrength, q, l ) < d ) shift.x = FT_MulDiv( shift.x, xstrength, d ); else shift.x = FT_MulDiv( shift.x, l, q ); if ( FT_MulDiv( ystrength, q, l ) < d ) shift.y = FT_MulDiv( shift.y, ystrength, d ); else shift.y = FT_MulDiv( shift.y, l, q ); } else shift.x = shift.y = 0; outline->points[n].x = v_cur.x + xstrength + shift.x; outline->points[n].y = v_cur.y + ystrength + shift.y; in = out; l_in = l_out; v_cur = v_next; } first = last + 1; } return FT_Err_Ok; }
static void parse_fond( char* fond_data, short* have_sfnt, ResID* sfnt_id, Str255 lwfn_file_name, short face_index ) { AsscEntry* assoc; AsscEntry* base_assoc; FamRec* fond; *sfnt_id = 0; *have_sfnt = 0; lwfn_file_name[0] = 0; fond = (FamRec*)fond_data; assoc = (AsscEntry*)( fond_data + sizeof ( FamRec ) + 2 ); base_assoc = assoc; /* the maximum faces in a FOND is 48, size of StyleTable.indexes[] */ if ( 47 < face_index ) return; /* Let's do a little range checking before we get too excited here */ if ( face_index < count_faces_sfnt( fond_data ) ) { assoc += face_index; /* add on the face_index! */ /* if the face at this index is not scalable, fall back to the first one (old behavior) */ if ( EndianS16_BtoN( assoc->fontSize ) == 0 ) { *have_sfnt = 1; *sfnt_id = EndianS16_BtoN( assoc->fontID ); } else if ( base_assoc->fontSize == 0 ) { *have_sfnt = 1; *sfnt_id = EndianS16_BtoN( base_assoc->fontID ); } } if ( EndianS32_BtoN( fond->ffStylOff ) ) { unsigned char* p = (unsigned char*)fond_data; StyleTable* style; unsigned short string_count; char ps_name[256]; unsigned char* names[64]; int i; p += EndianS32_BtoN( fond->ffStylOff ); style = (StyleTable*)p; p += sizeof ( StyleTable ); string_count = EndianS16_BtoN( *(short*)(p) ); p += sizeof ( short ); for ( i = 0; i < string_count && i < 64; i++ ) { names[i] = p; p += names[i][0]; p++; } { size_t ps_name_len = (size_t)names[0][0]; if ( ps_name_len != 0 ) { ft_memcpy(ps_name, names[0] + 1, ps_name_len); ps_name[ps_name_len] = 0; } if ( style->indexes[face_index] > 1 && style->indexes[face_index] <= FT_MIN( string_count, 64 ) ) { unsigned char* suffixes = names[style->indexes[face_index] - 1]; for ( i = 1; i <= suffixes[0]; i++ ) { unsigned char* s; size_t j = suffixes[i] - 1; if ( j < string_count && ( s = names[j] ) != NULL ) { size_t s_len = (size_t)s[0]; if ( s_len != 0 && ps_name_len + s_len < sizeof ( ps_name ) ) { ft_memcpy( ps_name + ps_name_len, s + 1, s_len ); ps_name_len += s_len; ps_name[ps_name_len] = 0; } } } } } create_lwfn_name( ps_name, lwfn_file_name ); } }
cf2_blues_capture( const CF2_Blues blues, CF2_Hint bottomHintEdge, CF2_Hint topHintEdge ) { /* TODO: validate? */ CF2_Fixed csFuzz = blues->blueFuzz; /* new position of captured edge */ CF2_Fixed dsNew; /* amount that hint is moved when positioned */ CF2_Fixed dsMove = 0; FT_Bool captured = FALSE; CF2_UInt i; /* assert edge flags are consistent */ FT_ASSERT( !cf2_hint_isTop( bottomHintEdge ) && !cf2_hint_isBottom( topHintEdge ) ); /* TODO: search once without blue fuzz for compatibility with coretype? */ for ( i = 0; i < blues->count; i++ ) { if ( blues->zone[i].bottomZone && cf2_hint_isBottom( bottomHintEdge ) ) { if ( ( blues->zone[i].csBottomEdge - csFuzz ) <= bottomHintEdge->csCoord && bottomHintEdge->csCoord <= ( blues->zone[i].csTopEdge + csFuzz ) ) { /* bottom edge captured by bottom zone */ if ( blues->suppressOvershoot ) dsNew = blues->zone[i].dsFlatEdge; else if ( ( blues->zone[i].csTopEdge - bottomHintEdge->csCoord ) >= blues->blueShift ) { /* guarantee minimum of 1 pixel overshoot */ dsNew = FT_MIN( cf2_fixedRound( bottomHintEdge->dsCoord ), blues->zone[i].dsFlatEdge - cf2_intToFixed( 1 ) ); } else { /* simply round captured edge */ dsNew = cf2_fixedRound( bottomHintEdge->dsCoord ); } dsMove = dsNew - bottomHintEdge->dsCoord; captured = TRUE; break; } } if ( !blues->zone[i].bottomZone && cf2_hint_isTop( topHintEdge ) ) { if ( ( blues->zone[i].csBottomEdge - csFuzz ) <= topHintEdge->csCoord && topHintEdge->csCoord <= ( blues->zone[i].csTopEdge + csFuzz ) ) { /* top edge captured by top zone */ if ( blues->suppressOvershoot ) dsNew = blues->zone[i].dsFlatEdge; else if ( ( topHintEdge->csCoord - blues->zone[i].csBottomEdge ) >= blues->blueShift ) { /* guarantee minimum of 1 pixel overshoot */ dsNew = FT_MAX( cf2_fixedRound( topHintEdge->dsCoord ), blues->zone[i].dsFlatEdge + cf2_intToFixed( 1 ) ); } else { /* simply round captured edge */ dsNew = cf2_fixedRound( topHintEdge->dsCoord ); } dsMove = dsNew - topHintEdge->dsCoord; captured = TRUE; break; } } } if ( captured ) { /* move both edges and flag them `locked' */ if ( cf2_hint_isValid( bottomHintEdge ) ) { bottomHintEdge->dsCoord += dsMove; cf2_hint_lock( bottomHintEdge ); } if ( cf2_hint_isValid( topHintEdge ) ) { topHintEdge->dsCoord += dsMove; cf2_hint_lock( topHintEdge ); } } return captured; }
tt_face_colr_blend_layer( TT_Face face, FT_UInt color_index, FT_GlyphSlot dstSlot, FT_GlyphSlot srcSlot ) { FT_Error error; FT_UInt x, y; FT_Byte b, g, r, alpha; FT_ULong size; FT_Byte* src; FT_Byte* dst; if ( !dstSlot->bitmap.buffer ) { /* Initialize destination of color bitmap */ /* with the size of first component. */ dstSlot->bitmap_left = srcSlot->bitmap_left; dstSlot->bitmap_top = srcSlot->bitmap_top; dstSlot->bitmap.width = srcSlot->bitmap.width; dstSlot->bitmap.rows = srcSlot->bitmap.rows; dstSlot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA; dstSlot->bitmap.pitch = (int)dstSlot->bitmap.width * 4; dstSlot->bitmap.num_grays = 256; size = dstSlot->bitmap.rows * (unsigned int)dstSlot->bitmap.pitch; error = ft_glyphslot_alloc_bitmap( dstSlot, size ); if ( error ) return error; FT_MEM_ZERO( dstSlot->bitmap.buffer, size ); } else { /* Resize destination if needed such that new component fits. */ FT_Int x_min, x_max, y_min, y_max; x_min = FT_MIN( dstSlot->bitmap_left, srcSlot->bitmap_left ); x_max = FT_MAX( dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width, srcSlot->bitmap_left + (FT_Int)srcSlot->bitmap.width ); y_min = FT_MIN( dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows, srcSlot->bitmap_top - (FT_Int)srcSlot->bitmap.rows ); y_max = FT_MAX( dstSlot->bitmap_top, srcSlot->bitmap_top ); if ( x_min != dstSlot->bitmap_left || x_max != dstSlot->bitmap_left + (FT_Int)dstSlot->bitmap.width || y_min != dstSlot->bitmap_top - (FT_Int)dstSlot->bitmap.rows || y_max != dstSlot->bitmap_top ) { FT_Memory memory = face->root.memory; FT_UInt width = (FT_UInt)( x_max - x_min ); FT_UInt rows = (FT_UInt)( y_max - y_min ); FT_UInt pitch = width * 4; FT_Byte* buf = NULL; FT_Byte* p; FT_Byte* q; size = rows * pitch; if ( FT_ALLOC( buf, size ) ) return error; p = dstSlot->bitmap.buffer; q = buf + (int)pitch * ( y_max - dstSlot->bitmap_top ) + 4 * ( dstSlot->bitmap_left - x_min ); for ( y = 0; y < dstSlot->bitmap.rows; y++ ) { FT_MEM_COPY( q, p, dstSlot->bitmap.width * 4 ); p += dstSlot->bitmap.pitch; q += pitch; } ft_glyphslot_set_bitmap( dstSlot, buf ); dstSlot->bitmap_top = y_max; dstSlot->bitmap_left = x_min; dstSlot->bitmap.width = width; dstSlot->bitmap.rows = rows; dstSlot->bitmap.pitch = (int)pitch; dstSlot->internal->flags |= FT_GLYPH_OWN_BITMAP; dstSlot->format = FT_GLYPH_FORMAT_BITMAP; } } if ( color_index == 0xFFFF ) { if ( face->have_foreground_color ) { b = face->foreground_color.blue; g = face->foreground_color.green; r = face->foreground_color.red; alpha = face->foreground_color.alpha; } else { if ( face->palette_data.palette_flags && ( face->palette_data.palette_flags[face->palette_index] & FT_PALETTE_FOR_DARK_BACKGROUND ) ) { /* white opaque */ b = 0xFF; g = 0xFF; r = 0xFF; alpha = 0xFF; } else { /* black opaque */ b = 0x00; g = 0x00; r = 0x00; alpha = 0xFF; } } } else { b = face->palette[color_index].blue; g = face->palette[color_index].green; r = face->palette[color_index].red; alpha = face->palette[color_index].alpha; } /* XXX Convert if srcSlot.bitmap is not grey? */ src = srcSlot->bitmap.buffer; dst = dstSlot->bitmap.buffer + dstSlot->bitmap.pitch * ( dstSlot->bitmap_top - srcSlot->bitmap_top ) + 4 * ( srcSlot->bitmap_left - dstSlot->bitmap_left ); for ( y = 0; y < srcSlot->bitmap.rows; y++ ) { for ( x = 0; x < srcSlot->bitmap.width; x++ ) { int aa = src[x]; int fa = alpha * aa / 255; int fb = b * fa / 255; int fg = g * fa / 255; int fr = r * fa / 255; int ba2 = 255 - fa; int bb = dst[4 * x + 0]; int bg = dst[4 * x + 1]; int br = dst[4 * x + 2]; int ba = dst[4 * x + 3]; dst[4 * x + 0] = (FT_Byte)( bb * ba2 / 255 + fb ); dst[4 * x + 1] = (FT_Byte)( bg * ba2 / 255 + fg ); dst[4 * x + 2] = (FT_Byte)( br * ba2 / 255 + fr ); dst[4 * x + 3] = (FT_Byte)( ba * ba2 / 255 + fa ); } src += srcSlot->bitmap.pitch; dst += dstSlot->bitmap.pitch; } return FT_Err_Ok; }
FT_Outline_EmboldenXY( FT_Outline* outline, FT_Pos xstrength, FT_Pos ystrength ) { FT_Vector* points; FT_Int c, first, last; FT_Int orientation; if ( !outline ) return FT_THROW( Invalid_Outline ); xstrength /= 2; ystrength /= 2; if ( xstrength == 0 && ystrength == 0 ) return FT_Err_Ok; orientation = FT_Outline_Get_Orientation( outline ); if ( orientation == FT_ORIENTATION_NONE ) { if ( outline->n_contours ) return FT_THROW( Invalid_Argument ); else return FT_Err_Ok; } points = outline->points; first = 0; for ( c = 0; c < outline->n_contours; c++ ) { FT_Vector in, out, anchor, shift; FT_Fixed l_in, l_out, l_anchor = 0, l, q, d; FT_Int i, j, k; l_in = 0; last = outline->contours[c]; /* pacify compiler */ in.x = in.y = anchor.x = anchor.y = 0; /* Counter j cycles though the points; counter i advances only */ /* when points are moved; anchor k marks the first moved point. */ for ( i = last, j = first, k = -1; j != i && i != k; j = j < last ? j + 1 : first ) { if ( j != k ) { out.x = points[j].x - points[i].x; out.y = points[j].y - points[i].y; l_out = (FT_Fixed)FT_Vector_NormLen( &out ); if ( l_out == 0 ) continue; } else { out = anchor; l_out = l_anchor; } if ( l_in != 0 ) { if ( k < 0 ) { k = i; anchor = in; l_anchor = l_in; } d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y ); /* shift only if turn is less than ~160 degrees */ if ( d > -0xF000L ) { d = d + 0x10000L; /* shift components along lateral bisector in proper orientation */ shift.x = in.y + out.y; shift.y = in.x + out.x; if ( orientation == FT_ORIENTATION_TRUETYPE ) shift.x = -shift.x; else shift.y = -shift.y; /* restrict shift magnitude to better handle collapsing segments */ q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x ); if ( orientation == FT_ORIENTATION_TRUETYPE ) q = -q; l = FT_MIN( l_in, l_out ); /* non-strict inequalities avoid divide-by-zero when q == l == 0 */ if ( FT_MulFix( xstrength, q ) <= FT_MulFix( l, d ) ) shift.x = FT_MulDiv( shift.x, xstrength, d ); else shift.x = FT_MulDiv( shift.x, l, q ); if ( FT_MulFix( ystrength, q ) <= FT_MulFix( l, d ) ) shift.y = FT_MulDiv( shift.y, ystrength, d ); else shift.y = FT_MulDiv( shift.y, l, q ); } else shift.x = shift.y = 0; for ( ; i != j; i = i < last ? i + 1 : first ) { points[i].x += xstrength + shift.x; points[i].y += ystrength + shift.y; } } else i = j; in = out; l_in = l_out; } first = last + 1; } return FT_Err_Ok; }
cff_face_init( FT_Stream stream, FT_Face cffface, /* CFF_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { CFF_Face face = (CFF_Face)cffface; FT_Error error; SFNT_Service sfnt; FT_Service_PsCMaps psnames; PSHinter_Service pshinter; FT_Bool pure_cff = 1; FT_Bool sfnt_format = 0; #if 0 FT_FACE_FIND_GLOBAL_SERVICE( face, sfnt, SFNT ); FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_NAMES ); FT_FACE_FIND_GLOBAL_SERVICE( face, pshinter, POSTSCRIPT_HINTER ); if ( !sfnt ) goto Bad_Format; #else sfnt = (SFNT_Service)FT_Get_Module_Interface( cffface->driver->root.library, "sfnt" ); if ( !sfnt ) goto Bad_Format; FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); pshinter = (PSHinter_Service)FT_Get_Module_Interface( cffface->driver->root.library, "pshinter" ); #endif /* create input stream from resource */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; /* check whether we have a valid OpenType file */ error = sfnt->init_face( stream, face, face_index, num_params, params ); if ( !error ) { if ( face->format_tag != 0x4F54544FL ) /* `OTTO'; OpenType/CFF font */ { FT_TRACE2(( "[not a valid OpenType/CFF font]\n" )); goto Bad_Format; } /* if we are performing a simple font format check, exit immediately */ if ( face_index < 0 ) return CFF_Err_Ok; /* UNDOCUMENTED! A CFF in an SFNT can have only a single font. */ if ( face_index > 0 ) { FT_ERROR(( "cff_face_init: invalid face index\n" )); error = CFF_Err_Invalid_Argument; goto Exit; } sfnt_format = 1; /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ /* font; in the latter case it doesn't have a `head' table */ error = face->goto_table( face, TTAG_head, stream, 0 ); if ( !error ) { pure_cff = 0; /* load font directory */ error = sfnt->load_face( stream, face, face_index, num_params, params ); if ( error ) goto Exit; } else { /* load the `cmap' table explicitly */ error = sfnt->load_cmap( face, stream ); if ( error ) goto Exit; /* XXX: we don't load the GPOS table, as OpenType Layout */ /* support will be added later to a layout library on top of */ /* FreeType 2 */ } /* now load the CFF part of the file */ error = face->goto_table( face, TTAG_CFF, stream, 0 ); if ( error ) goto Exit; } else { /* rewind to start of file; we are going to load a pure-CFF font */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; error = CFF_Err_Ok; } /* now load and parse the CFF table in the file */ { CFF_Font cff; CFF_FontRecDict dict; FT_Memory memory = cffface->memory; FT_Int32 flags; FT_UInt i; if ( FT_NEW( cff ) ) goto Exit; face->extra.data = cff; error = cff_font_load( stream, face_index, cff ); if ( error ) goto Exit; cff->pshinter = pshinter; cff->psnames = (void*)psnames; /* Complement the root flags with some interesting information. */ /* Note that this is only necessary for pure CFF and CEF fonts; */ /* SFNT based fonts use the `name' table instead. */ cffface->num_glyphs = cff->num_glyphs; dict = &cff->top_font.font_dict; /* we need the `PSNames' module for CFF and CEF formats */ /* which aren't CID-keyed */ if ( dict->cid_registry == 0xFFFFU && !psnames ) { FT_ERROR(( "cff_face_init:" )); FT_ERROR(( " cannot open CFF & CEF fonts\n" )); FT_ERROR(( " " )); FT_ERROR(( " without the `PSNames' module\n" )); goto Bad_Format; } if ( pure_cff ) { char* style_name = NULL; /* set up num_faces */ cffface->num_faces = cff->num_faces; /* compute number of glyphs */ if ( dict->cid_registry != 0xFFFFU ) cffface->num_glyphs = cff->charset.max_cid; else cffface->num_glyphs = cff->charstrings_index.count; /* set global bbox, as well as EM size */ cffface->bbox.xMin = dict->font_bbox.xMin >> 16; cffface->bbox.yMin = dict->font_bbox.yMin >> 16; cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFFU ) >> 16; cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFFU ) >> 16; if ( !dict->units_per_em ) dict->units_per_em = 1000; cffface->units_per_EM = dict->units_per_em; cffface->ascender = (FT_Short)( cffface->bbox.yMax ); cffface->descender = (FT_Short)( cffface->bbox.yMin ); cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 ); if ( cffface->height < cffface->ascender - cffface->descender ) cffface->height = (FT_Short)( cffface->ascender - cffface->descender ); cffface->underline_position = (FT_Short)( dict->underline_position >> 16 ); cffface->underline_thickness = (FT_Short)( dict->underline_thickness >> 16 ); /* retrieve font family & style name */ cffface->family_name = cff_index_get_name( &cff->name_index, face_index ); if ( cffface->family_name ) { char* full = cff_index_get_sid_string( &cff->string_index, dict->full_name, psnames ); char* fullp = full; char* family = cffface->family_name; char* family_name = 0; if ( dict->family_name ) { family_name = cff_index_get_sid_string( &cff->string_index, dict->family_name, psnames); if ( family_name ) family = family_name; } /* We try to extract the style name from the full name. */ /* We need to ignore spaces and dashes during the search. */ if ( full && family ) { while ( *fullp ) { /* skip common characters at the start of both strings */ if ( *fullp == *family ) { family++; fullp++; continue; } /* ignore spaces and dashes in full name during comparison */ if ( *fullp == ' ' || *fullp == '-' ) { fullp++; continue; } /* ignore spaces and dashes in family name during comparison */ if ( *family == ' ' || *family == '-' ) { family++; continue; } if ( !*family && *fullp ) { /* The full name begins with the same characters as the */ /* family name, with spaces and dashes removed. In this */ /* case, the remaining string in `fullp' will be used as */ /* the style name. */ style_name = cff_strcpy( memory, fullp ); } break; } if ( family_name ) FT_FREE( family_name ); FT_FREE( full ); } } else { char *cid_font_name = cff_index_get_sid_string( &cff->string_index, dict->cid_font_name, psnames ); /* do we have a `/FontName' for a CID-keyed font? */ if ( cid_font_name ) cffface->family_name = cid_font_name; } if ( style_name ) cffface->style_name = style_name; else /* assume "Regular" style if we don't know better */ cffface->style_name = cff_strcpy( memory, (char *)"Regular" ); /*******************************************************************/ /* */ /* Compute face flags. */ /* */ flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ FT_FACE_FLAG_HINTER; /* has native hinter */ if ( sfnt_format ) flags |= FT_FACE_FLAG_SFNT; /* fixed width font? */ if ( dict->is_fixed_pitch ) flags |= FT_FACE_FLAG_FIXED_WIDTH; /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ #if 0 /* kerning available? */ if ( face->kern_pairs ) flags |= FT_FACE_FLAG_KERNING; #endif cffface->face_flags = flags; /*******************************************************************/ /* */ /* Compute style flags. */ /* */ flags = 0; if ( dict->italic_angle ) flags |= FT_STYLE_FLAG_ITALIC; { char *weight = cff_index_get_sid_string( &cff->string_index, dict->weight, psnames ); if ( weight ) if ( !ft_strcmp( weight, "Bold" ) || !ft_strcmp( weight, "Black" ) ) flags |= FT_STYLE_FLAG_BOLD; FT_FREE( weight ); } /* double check */ if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name ) if ( !ft_strncmp( cffface->style_name, "Bold", 4 ) || !ft_strncmp( cffface->style_name, "Black", 5 ) ) flags |= FT_STYLE_FLAG_BOLD; cffface->style_flags = flags; } else { if ( !dict->units_per_em ) dict->units_per_em = face->root.units_per_EM; } /* Normalize the font matrix so that `matrix->xx' is 1; the */ /* scaling is done with `units_per_em' then (at this point, */ /* it already contains the scaling factor, but without */ /* normalization of the matrix). */ /* */ /* Note that the offsets must be expressed in integer font */ /* units. */ { FT_Matrix* matrix = &dict->font_matrix; FT_Vector* offset = &dict->font_offset; FT_ULong* upm = &dict->units_per_em; FT_Fixed temp = FT_ABS( matrix->yy ); if ( temp != 0x10000L ) { *upm = FT_DivFix( *upm, temp ); matrix->xx = FT_DivFix( matrix->xx, temp ); matrix->yx = FT_DivFix( matrix->yx, temp ); matrix->xy = FT_DivFix( matrix->xy, temp ); matrix->yy = FT_DivFix( matrix->yy, temp ); offset->x = FT_DivFix( offset->x, temp ); offset->y = FT_DivFix( offset->y, temp ); } offset->x >>= 16; offset->y >>= 16; } for ( i = cff->num_subfonts; i > 0; i-- ) { CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict; CFF_FontRecDict top = &cff->top_font.font_dict; FT_Matrix* matrix; FT_Vector* offset; FT_ULong* upm; FT_Fixed temp; if ( sub->units_per_em ) { FT_Int scaling; if ( top->units_per_em > 1 && sub->units_per_em > 1 ) scaling = FT_MIN( top->units_per_em, sub->units_per_em ); else scaling = 1; FT_Matrix_Multiply_Scaled( &top->font_matrix, &sub->font_matrix, scaling ); FT_Vector_Transform_Scaled( &sub->font_offset, &top->font_matrix, scaling ); sub->units_per_em = FT_MulDiv( sub->units_per_em, top->units_per_em, scaling ); } else { sub->font_matrix = top->font_matrix; sub->font_offset = top->font_offset; sub->units_per_em = top->units_per_em; } matrix = &sub->font_matrix; offset = &sub->font_offset; upm = &sub->units_per_em; temp = FT_ABS( matrix->yy ); if ( temp != 0x10000L ) { *upm = FT_DivFix( *upm, temp ); /* if *upm is larger than 100*1000 we divide by 1000 -- */ /* this can happen if e.g. there is no top-font FontMatrix */ /* and the subfont FontMatrix already contains the complete */ /* scaling for the subfont (see section 5.11 of the PLRM) */ /* 100 is a heuristic value */ if ( *upm > 100L * 1000L ) *upm = ( *upm + 500 ) / 1000; matrix->xx = FT_DivFix( matrix->xx, temp ); matrix->yx = FT_DivFix( matrix->yx, temp ); matrix->xy = FT_DivFix( matrix->xy, temp ); matrix->yy = FT_DivFix( matrix->yy, temp ); offset->x = FT_DivFix( offset->x, temp ); offset->y = FT_DivFix( offset->y, temp ); } offset->x >>= 16; offset->y >>= 16; } #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */ /* has unset this flag because of the 3.0 `post' table. */ if ( dict->cid_registry == 0xFFFFU ) cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; #endif if ( dict->cid_registry != 0xFFFFU ) cffface->face_flags |= FT_FACE_FLAG_CID_KEYED; /*******************************************************************/ /* */ /* Compute char maps. */ /* */ /* Try to synthetize a Unicode charmap if there is none available */ /* already. If an OpenType font contains a Unicode "cmap", we */ /* will use it, whatever be in the CFF part of the file. */ { FT_CharMapRec cmaprec; FT_CharMap cmap; FT_UInt nn; CFF_Encoding encoding = &cff->encoding; for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ ) { cmap = cffface->charmaps[nn]; /* Windows Unicode (3,1)? */ if ( cmap->platform_id == 3 && cmap->encoding_id == 1 ) goto Skip_Unicode; /* Deprecated Unicode platform id? */ if ( cmap->platform_id == 0 ) goto Skip_Unicode; /* Standard Unicode (deprecated) */ } /* since CID-keyed fonts don't contain glyph names, we can't */ /* construct a cmap */ if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU ) goto Exit; /* we didn't find a Unicode charmap -- synthesize one */ cmaprec.face = cffface; cmaprec.platform_id = 3; cmaprec.encoding_id = 1; cmaprec.encoding = FT_ENCODING_UNICODE; nn = (FT_UInt)cffface->num_charmaps; FT_CMap_New( &cff_cmap_unicode_class_rec, NULL, &cmaprec, NULL ); /* if no Unicode charmap was previously selected, select this one */ if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps ) cffface->charmap = cffface->charmaps[nn]; Skip_Unicode: if ( encoding->count > 0 ) { FT_CMap_Class clazz; cmaprec.face = cffface; cmaprec.platform_id = 7; /* Adobe platform id */ if ( encoding->offset == 0 ) { cmaprec.encoding_id = TT_ADOBE_ID_STANDARD; cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD; clazz = &cff_cmap_encoding_class_rec; } else if ( encoding->offset == 1 ) { cmaprec.encoding_id = TT_ADOBE_ID_EXPERT; cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT; clazz = &cff_cmap_encoding_class_rec; } else { cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM; cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM; clazz = &cff_cmap_encoding_class_rec; } FT_CMap_New( clazz, NULL, &cmaprec, NULL ); } } }
tt_face_load_hmtx( TT_Face face, FT_Stream stream, FT_Bool vertical ) { FT_Error error; FT_Memory memory = stream->memory; FT_ULong table_len; FT_Long num_shorts, num_longs, num_shorts_checked; TT_LongMetrics* longs; TT_ShortMetrics** shorts; FT_Byte* p; if ( vertical ) { void* lm = &face->vertical.long_metrics; void** sm = &face->vertical.short_metrics; error = face->goto_table( face, TTAG_vmtx, stream, &table_len ); if ( error ) goto Fail; num_longs = face->vertical.number_Of_VMetrics; if ( (FT_ULong)num_longs > table_len / 4 ) num_longs = (FT_Long)( table_len / 4 ); face->vertical.number_Of_VMetrics = 0; longs = (TT_LongMetrics*)lm; shorts = (TT_ShortMetrics**)sm; } else { void* lm = &face->horizontal.long_metrics; void** sm = &face->horizontal.short_metrics; error = face->goto_table( face, TTAG_hmtx, stream, &table_len ); if ( error ) goto Fail; num_longs = face->horizontal.number_Of_HMetrics; if ( (FT_ULong)num_longs > table_len / 4 ) num_longs = (FT_Long)( table_len / 4 ); face->horizontal.number_Of_HMetrics = 0; longs = (TT_LongMetrics*)lm; shorts = (TT_ShortMetrics**)sm; } /* never trust derived values */ num_shorts = face->max_profile.numGlyphs - num_longs; num_shorts_checked = ( table_len - num_longs * 4L ) / 2; if ( num_shorts < 0 ) { FT_ERROR(( "%cmtx has more metrics than glyphs.\n" )); /* Adobe simply ignores this problem. So we shall do the same. */ #if 0 error = vertical ? SFNT_Err_Invalid_Vert_Metrics : SFNT_Err_Invalid_Horiz_Metrics; goto Exit; #else num_shorts = 0; #endif } if ( FT_QNEW_ARRAY( *longs, num_longs ) || FT_QNEW_ARRAY( *shorts, num_shorts ) ) goto Fail; if ( FT_FRAME_ENTER( table_len ) ) goto Fail; p = stream->cursor; { TT_LongMetrics cur = *longs; TT_LongMetrics limit = cur + num_longs; for ( ; cur < limit; cur++ ) { cur->advance = FT_NEXT_USHORT( p ); cur->bearing = FT_NEXT_SHORT( p ); } } /* do we have an inconsistent number of metric values? */ { TT_ShortMetrics* cur = *shorts; TT_ShortMetrics* limit = cur + FT_MIN( num_shorts, num_shorts_checked ); for ( ; cur < limit; cur++ ) *cur = FT_NEXT_SHORT( p ); /* We fill up the missing left side bearings with the */ /* last valid value. Since this will occur for buggy CJK */ /* fonts usually only, nothing serious will happen. */ if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 ) { FT_Short val = (*shorts)[num_shorts_checked - 1]; limit = *shorts + num_shorts; for ( ; cur < limit; cur++ ) *cur = val; } } FT_FRAME_EXIT(); if ( vertical ) face->vertical.number_Of_VMetrics = (FT_UShort)num_longs; else face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs; Fail: return error; }
cid_parser_new( CID_Parser* parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux ) { FT_Error error; FT_ULong base_offset, offset, ps_len; FT_Byte *cur, *limit; FT_Byte *arg1, *arg2; FT_MEM_ZERO( parser, sizeof ( *parser ) ); psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); parser->stream = stream; base_offset = FT_STREAM_POS(); /* first of all, check the font format in the header */ if ( FT_FRAME_ENTER( 31 ) ) goto Exit; if ( ft_strncmp( (char *)stream->cursor, "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) { FT_TRACE2(( " not a CID-keyed font\n" )); error = FT_THROW( Unknown_File_Format ); } FT_FRAME_EXIT(); if ( error ) goto Exit; Again: /* now, read the rest of the file until we find */ /* `StartData' or `/sfnts' */ { FT_Byte buffer[256 + 10]; FT_ULong read_len = 256 + 10; FT_Byte* p = buffer; for ( offset = FT_STREAM_POS(); ; offset += 256 ) { FT_ULong stream_len; stream_len = stream->size - FT_STREAM_POS(); if ( stream_len == 0 ) { FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } read_len = FT_MIN( read_len, stream_len ); if ( FT_STREAM_READ( p, read_len ) ) goto Exit; if ( read_len < 256 ) p[read_len] = '\0'; limit = p + read_len - 10; for ( p = buffer; p < limit; p++ ) { if ( p[0] == 'S' && ft_strncmp( (char*)p, "StartData", 9 ) == 0 ) { /* save offset of binary data after `StartData' */ offset += (FT_ULong)( p - buffer + 10 ); goto Found; } else if ( p[1] == 's' && ft_strncmp( (char*)p, "/sfnts", 6 ) == 0 ) { offset += (FT_ULong)( p - buffer + 7 ); goto Found; } } FT_MEM_MOVE( buffer, p, 10 ); read_len = 256; p = buffer + 10; } } Found: /* We have found the start of the binary data or the `/sfnts' token. */ /* Now rewind and extract the frame corresponding to this PostScript */ /* section. */ ps_len = offset - base_offset; if ( FT_STREAM_SEEK( base_offset ) || FT_FRAME_EXTRACT( ps_len, parser->postscript ) ) goto Exit; parser->data_offset = offset; parser->postscript_len = ps_len; parser->root.base = parser->postscript; parser->root.cursor = parser->postscript; parser->root.limit = parser->root.cursor + ps_len; parser->num_dict = -1; /* Finally, we check whether `StartData' or `/sfnts' was real -- */ /* it could be in a comment or string. We also get the arguments */ /* of `StartData' to find out whether the data is represented in */ /* binary or hex format. */ arg1 = parser->root.cursor; cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); arg2 = parser->root.cursor; cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); limit = parser->root.limit; cur = parser->root.cursor; while ( cur < limit ) { if ( parser->root.error ) { error = parser->root.error; goto Exit; } if ( cur[0] == 'S' && ft_strncmp( (char*)cur, "StartData", 9 ) == 0 ) { if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 ) { FT_Long tmp = ft_atol( (const char *)arg2 ); if ( tmp < 0 ) { FT_ERROR(( "cid_parser_new: invalid length of hex data\n" )); error = FT_THROW( Invalid_File_Format ); } else parser->binary_length = (FT_ULong)tmp; } goto Exit; } else if ( cur[1] == 's' && ft_strncmp( (char*)cur, "/sfnts", 6 ) == 0 ) { FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" )); error = FT_THROW( Unknown_File_Format ); goto Exit; } cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); arg1 = arg2; arg2 = cur; cur = parser->root.cursor; } /* we haven't found the correct `StartData'; go back and continue */ /* searching */ FT_FRAME_RELEASE( parser->postscript ); if ( !FT_STREAM_SEEK( offset ) ) goto Again; Exit: return error; }
void CPageMgr::InsertPageInfo(void * addr, size_t pagecount, bool frommmap) { struct SPageInfo * pageInfo = AllocPageInfo(); RB_NODE_INIT(pageInfo->address_node); RB_NODE_INIT(pageInfo->free_node); pageInfo->base_address = (size_t)addr; pageInfo->page_count = pagecount; if (frommmap) { pageInfo->UnSetFlag(SPageInfo::E_MEM_SOURCE_OFF); } else { pageInfo->SetFlag(SPageInfo::E_MEM_SOURCE_OFF); } PRINT("addr:%p, pages:%zd, mmap:%d", addr, pagecount, frommmap); PRINT("mgr info, address tree size:%zd", m_iAddressTreeSize); if (m_iAddressTreeSize == 0) { InsertPageInfo(pageInfo); m_iMaxContinuePages = pageInfo->page_count; m_iAddressTreeSize ++; } else if (m_iAddressTreeSize == 1) { rb_node * node = rb_first(&m_cAddressTree); struct SPageInfo * pInfo = (struct SPageInfo *)AddressTreeGetObject(node); if (pInfo->flag == pageInfo->flag && (pInfo->BeginAddress() == pageInfo->EndAddress() || pageInfo->BeginAddress() == pInfo->EndAddress())) { RemoveFreeTree(pInfo); RemoveCountTreeIfNeed(pInfo->page_count); RemoveIndexTreeIfNeed(pInfo->page_count); pInfo->base_address = FT_MIN(pInfo->base_address, pInfo->base_address); pInfo->page_count += pageInfo->page_count; InsertIndexTreeIfNeed(pInfo->page_count); InsertCountTreeIfNeed(pInfo->page_count); InsertFreeTree(pInfo); ReleasePageInfo(pageInfo); m_iMaxContinuePages = pInfo->page_count; } else { InsertPageInfo(pageInfo); m_iMaxContinuePages = FT_MAX(pageInfo->page_count, pInfo->page_count); m_iAddressTreeSize ++; } } else { struct SPageInfo * prevInfo = GetPageInfoByAddress(pageInfo->BeginAddress() - 1); struct SPageInfo * nextInfo = GetPageInfoByAddress(pageInfo->EndAddress()); if (prevInfo != NULL && prevInfo->flag == pageInfo->flag) { pageInfo->base_address = prevInfo->base_address; pageInfo->page_count += prevInfo->page_count; RemovePageInfo(prevInfo); m_iAddressTreeSize --; prevInfo = NULL; } if (nextInfo != NULL && nextInfo->flag == pageInfo->flag) { pageInfo->page_count += nextInfo->page_count; RemovePageInfo(nextInfo); m_iAddressTreeSize --; nextInfo = NULL; } InsertPageInfo(pageInfo); m_iMaxContinuePages = FT_MAX(pageInfo->page_count, m_iMaxContinuePages); m_iAddressTreeSize ++; } m_iFreePages += pagecount; }
cff_face_init( FT_Stream stream, FT_Face cffface, /* CFF_Face */ FT_Int face_index, FT_Int num_params, FT_Parameter* params ) { CFF_Face face = (CFF_Face)cffface; FT_Error error; SFNT_Service sfnt; FT_Service_PsCMaps psnames; PSHinter_Service pshinter; FT_Bool pure_cff = 1; FT_Bool sfnt_format = 0; FT_Library library = cffface->driver->root.library; sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); if ( !sfnt ) { FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" )); error = FT_THROW( Missing_Module ); goto Exit; } FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); pshinter = (PSHinter_Service)FT_Get_Module_Interface( library, "pshinter" ); FT_TRACE2(( "CFF driver\n" )); /* create input stream from resource */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; /* check whether we have a valid OpenType file */ error = sfnt->init_face( stream, face, face_index, num_params, params ); if ( !error ) { if ( face->format_tag != TTAG_OTTO ) /* `OTTO'; OpenType/CFF font */ { FT_TRACE2(( " not an OpenType/CFF font\n" )); error = FT_THROW( Unknown_File_Format ); goto Exit; } /* if we are performing a simple font format check, exit immediately */ if ( face_index < 0 ) return FT_Err_Ok; sfnt_format = 1; /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ /* font; in the latter case it doesn't have a `head' table */ error = face->goto_table( face, TTAG_head, stream, 0 ); if ( !error ) { pure_cff = 0; /* load font directory */ error = sfnt->load_face( stream, face, face_index, num_params, params ); if ( error ) goto Exit; } else { /* load the `cmap' table explicitly */ error = sfnt->load_cmap( face, stream ); if ( error ) goto Exit; } /* now load the CFF part of the file */ error = face->goto_table( face, TTAG_CFF, stream, 0 ); if ( error ) goto Exit; } else { /* rewind to start of file; we are going to load a pure-CFF font */ if ( FT_STREAM_SEEK( 0 ) ) goto Exit; error = FT_Err_Ok; } /* now load and parse the CFF table in the file */ { CFF_Font cff = NULL; CFF_FontRecDict dict; FT_Memory memory = cffface->memory; FT_Int32 flags; FT_UInt i; if ( FT_NEW( cff ) ) goto Exit; face->extra.data = cff; error = cff_font_load( library, stream, face_index, cff, pure_cff ); if ( error ) goto Exit; cff->pshinter = pshinter; cff->psnames = psnames; cffface->face_index = face_index; /* Complement the root flags with some interesting information. */ /* Note that this is only necessary for pure CFF and CEF fonts; */ /* SFNT based fonts use the `name' table instead. */ cffface->num_glyphs = cff->num_glyphs; dict = &cff->top_font.font_dict; /* we need the `PSNames' module for CFF and CEF formats */ /* which aren't CID-keyed */ if ( dict->cid_registry == 0xFFFFU && !psnames ) { FT_ERROR(( "cff_face_init:" " cannot open CFF & CEF fonts\n" " " " without the `PSNames' module\n" )); error = FT_THROW( Missing_Module ); goto Exit; } #ifdef FT_DEBUG_LEVEL_TRACE { FT_UInt idx; FT_String* s; FT_TRACE4(( "SIDs\n" )); /* dump string index, including default strings for convenience */ for ( idx = 0; idx < cff->num_strings + 390; idx++ ) { s = cff_index_get_sid_string( cff, idx ); if ( s ) FT_TRACE4((" %5d %s\n", idx, s )); } } #endif /* FT_DEBUG_LEVEL_TRACE */ if ( !dict->has_font_matrix ) dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM; /* Normalize the font matrix so that `matrix->xx' is 1; the */ /* scaling is done with `units_per_em' then (at this point, */ /* it already contains the scaling factor, but without */ /* normalization of the matrix). */ /* */ /* Note that the offsets must be expressed in integer font */ /* units. */ { FT_Matrix* matrix = &dict->font_matrix; FT_Vector* offset = &dict->font_offset; FT_ULong* upm = &dict->units_per_em; FT_Fixed temp = FT_ABS( matrix->yy ); if ( temp != 0x10000L ) { *upm = FT_DivFix( *upm, temp ); matrix->xx = FT_DivFix( matrix->xx, temp ); matrix->yx = FT_DivFix( matrix->yx, temp ); matrix->xy = FT_DivFix( matrix->xy, temp ); matrix->yy = FT_DivFix( matrix->yy, temp ); offset->x = FT_DivFix( offset->x, temp ); offset->y = FT_DivFix( offset->y, temp ); } offset->x >>= 16; offset->y >>= 16; } for ( i = cff->num_subfonts; i > 0; i-- ) { CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict; CFF_FontRecDict top = &cff->top_font.font_dict; FT_Matrix* matrix; FT_Vector* offset; FT_ULong* upm; FT_Fixed temp; if ( sub->has_font_matrix ) { FT_Long scaling; /* if we have a top-level matrix, */ /* concatenate the subfont matrix */ if ( top->has_font_matrix ) { if ( top->units_per_em > 1 && sub->units_per_em > 1 ) scaling = FT_MIN( top->units_per_em, sub->units_per_em ); else scaling = 1; FT_Matrix_Multiply_Scaled( &top->font_matrix, &sub->font_matrix, scaling ); FT_Vector_Transform_Scaled( &sub->font_offset, &top->font_matrix, scaling ); sub->units_per_em = FT_MulDiv( sub->units_per_em, top->units_per_em, scaling ); } } else { sub->font_matrix = top->font_matrix; sub->font_offset = top->font_offset; sub->units_per_em = top->units_per_em; } matrix = &sub->font_matrix; offset = &sub->font_offset; upm = &sub->units_per_em; temp = FT_ABS( matrix->yy ); if ( temp != 0x10000L ) { *upm = FT_DivFix( *upm, temp ); matrix->xx = FT_DivFix( matrix->xx, temp ); matrix->yx = FT_DivFix( matrix->yx, temp ); matrix->xy = FT_DivFix( matrix->xy, temp ); matrix->yy = FT_DivFix( matrix->yy, temp ); offset->x = FT_DivFix( offset->x, temp ); offset->y = FT_DivFix( offset->y, temp ); } offset->x >>= 16; offset->y >>= 16; } if ( pure_cff ) { char* style_name = NULL; /* set up num_faces */ cffface->num_faces = cff->num_faces; /* compute number of glyphs */ if ( dict->cid_registry != 0xFFFFU ) cffface->num_glyphs = cff->charset.max_cid + 1; else cffface->num_glyphs = cff->charstrings_index.count; /* set global bbox, as well as EM size */ cffface->bbox.xMin = dict->font_bbox.xMin >> 16; cffface->bbox.yMin = dict->font_bbox.yMin >> 16; /* no `U' suffix here to 0xFFFF! */ cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16; cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16; cffface->units_per_EM = (FT_UShort)( dict->units_per_em ); cffface->ascender = (FT_Short)( cffface->bbox.yMax ); cffface->descender = (FT_Short)( cffface->bbox.yMin ); cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 ); if ( cffface->height < cffface->ascender - cffface->descender ) cffface->height = (FT_Short)( cffface->ascender - cffface->descender ); cffface->underline_position = (FT_Short)( dict->underline_position >> 16 ); cffface->underline_thickness = (FT_Short)( dict->underline_thickness >> 16 ); /* retrieve font family & style name */ cffface->family_name = cff_index_get_name( cff, face_index ); if ( cffface->family_name ) { char* full = cff_index_get_sid_string( cff, dict->full_name ); char* fullp = full; char* family = cffface->family_name; char* family_name = NULL; remove_subset_prefix( cffface->family_name ); if ( dict->family_name ) { family_name = cff_index_get_sid_string( cff, dict->family_name ); if ( family_name ) family = family_name; } /* We try to extract the style name from the full name. */ /* We need to ignore spaces and dashes during the search. */ if ( full && family ) { while ( *fullp ) { /* skip common characters at the start of both strings */ if ( *fullp == *family ) { family++; fullp++; continue; } /* ignore spaces and dashes in full name during comparison */ if ( *fullp == ' ' || *fullp == '-' ) { fullp++; continue; } /* ignore spaces and dashes in family name during comparison */ if ( *family == ' ' || *family == '-' ) { family++; continue; } if ( !*family && *fullp ) { /* The full name begins with the same characters as the */ /* family name, with spaces and dashes removed. In this */ /* case, the remaining string in `fullp' will be used as */ /* the style name. */ style_name = cff_strcpy( memory, fullp ); /* remove the style part from the family name (if present) */ remove_style( cffface->family_name, style_name ); } break; } } } else { char *cid_font_name = cff_index_get_sid_string( cff, dict->cid_font_name ); /* do we have a `/FontName' for a CID-keyed font? */ if ( cid_font_name ) cffface->family_name = cff_strcpy( memory, cid_font_name ); } if ( style_name ) cffface->style_name = style_name; else /* assume "Regular" style if we don't know better */ cffface->style_name = cff_strcpy( memory, (char *)"Regular" ); /*******************************************************************/ /* */ /* Compute face flags. */ /* */ flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ FT_FACE_FLAG_HINTER; /* has native hinter */ if ( sfnt_format ) flags |= FT_FACE_FLAG_SFNT; /* fixed width font? */ if ( dict->is_fixed_pitch ) flags |= FT_FACE_FLAG_FIXED_WIDTH; /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ #if 0 /* kerning available? */ if ( face->kern_pairs ) flags |= FT_FACE_FLAG_KERNING; #endif cffface->face_flags |= flags; /*******************************************************************/ /* */ /* Compute style flags. */ /* */ flags = 0; if ( dict->italic_angle ) flags |= FT_STYLE_FLAG_ITALIC; { char *weight = cff_index_get_sid_string( cff, dict->weight ); if ( weight ) if ( !ft_strcmp( weight, "Bold" ) || !ft_strcmp( weight, "Black" ) ) flags |= FT_STYLE_FLAG_BOLD; } /* double check */ if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name ) if ( !ft_strncmp( cffface->style_name, "Bold", 4 ) || !ft_strncmp( cffface->style_name, "Black", 5 ) ) flags |= FT_STYLE_FLAG_BOLD; cffface->style_flags = flags; } #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */ /* has unset this flag because of the 3.0 `post' table. */ if ( dict->cid_registry == 0xFFFFU ) cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; #endif if ( dict->cid_registry != 0xFFFFU && pure_cff ) cffface->face_flags |= FT_FACE_FLAG_CID_KEYED; /*******************************************************************/ /* */ /* Compute char maps. */ /* */ /* Try to synthesize a Unicode charmap if there is none available */ /* already. If an OpenType font contains a Unicode "cmap", we */ /* will use it, whatever be in the CFF part of the file. */ { FT_CharMapRec cmaprec; FT_CharMap cmap; FT_UInt nn; CFF_Encoding encoding = &cff->encoding; for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ ) { cmap = cffface->charmaps[nn]; /* Windows Unicode? */ if ( cmap->platform_id == TT_PLATFORM_MICROSOFT && cmap->encoding_id == TT_MS_ID_UNICODE_CS ) goto Skip_Unicode; /* Apple Unicode platform id? */ if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE ) goto Skip_Unicode; /* Apple Unicode */ } /* since CID-keyed fonts don't contain glyph names, we can't */ /* construct a cmap */ if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU ) goto Exit; #ifdef FT_MAX_CHARMAP_CACHEABLE if ( nn + 1 > FT_MAX_CHARMAP_CACHEABLE ) { FT_ERROR(( "cff_face_init: no Unicode cmap is found, " "and too many subtables (%d) to add synthesized cmap\n", nn )); goto Exit; } #endif /* we didn't find a Unicode charmap -- synthesize one */ cmaprec.face = cffface; cmaprec.platform_id = TT_PLATFORM_MICROSOFT; cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; cmaprec.encoding = FT_ENCODING_UNICODE; nn = (FT_UInt)cffface->num_charmaps; error = FT_CMap_New( &CFF_CMAP_UNICODE_CLASS_REC_GET, NULL, &cmaprec, NULL ); if ( error && FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) goto Exit; error = FT_Err_Ok; /* if no Unicode charmap was previously selected, select this one */ if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps ) cffface->charmap = cffface->charmaps[nn]; Skip_Unicode: #ifdef FT_MAX_CHARMAP_CACHEABLE if ( nn > FT_MAX_CHARMAP_CACHEABLE ) { FT_ERROR(( "cff_face_init: Unicode cmap is found, " "but too many preceding subtables (%d) to access\n", nn - 1 )); goto Exit; } #endif if ( encoding->count > 0 ) { FT_CMap_Class clazz; cmaprec.face = cffface; cmaprec.platform_id = TT_PLATFORM_ADOBE; /* Adobe platform id */ if ( encoding->offset == 0 ) { cmaprec.encoding_id = TT_ADOBE_ID_STANDARD; cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD; clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET; } else if ( encoding->offset == 1 ) { cmaprec.encoding_id = TT_ADOBE_ID_EXPERT; cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT; clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET; } else { cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM; cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM; clazz = &CFF_CMAP_ENCODING_CLASS_REC_GET; } error = FT_CMap_New( clazz, NULL, &cmaprec, NULL ); } } } Exit: return error; }
cid_parser_new( CID_Parser* parser, FT_Stream stream, FT_Memory memory, PSAux_Service psaux ) { FT_Error error; FT_ULong base_offset, offset, ps_len; FT_Byte *cur, *limit; FT_Byte *arg1, *arg2; FT_ZERO( parser ); psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); parser->stream = stream; base_offset = FT_STREAM_POS(); /* first of all, check the font format in the header */ if ( FT_FRAME_ENTER( 31 ) ) goto Exit; if ( ft_strncmp( (char *)stream->cursor, "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) { FT_TRACE2(( " not a CID-keyed font\n" )); error = FT_THROW( Unknown_File_Format ); } FT_FRAME_EXIT(); if ( error ) goto Exit; Again: /* now, read the rest of the file until we find */ /* `StartData' or `/sfnts' */ { /* * The algorithm is as follows (omitting the case with less than 256 * bytes to fill for simplicity). * * 1. Fill the buffer with 256 + STARTDATA_LEN bytes. * * 2. Search for the STARTDATA and SFNTS strings at positions * buffer[0], buffer[1], ..., * buffer[255 + STARTDATA_LEN - SFNTS_LEN]. * * 3. Move the last STARTDATA_LEN bytes to buffer[0]. * * 4. Fill the buffer with 256 bytes, starting at STARTDATA_LEN. * * 5. Repeat with step 2. * */ FT_Byte buffer[256 + STARTDATA_LEN + 1]; /* values for the first loop */ FT_ULong read_len = 256 + STARTDATA_LEN; FT_ULong read_offset = 0; FT_Byte* p = buffer; for ( offset = FT_STREAM_POS(); ; offset += 256 ) { FT_ULong stream_len; stream_len = stream->size - FT_STREAM_POS(); read_len = FT_MIN( read_len, stream_len ); if ( FT_STREAM_READ( p, read_len ) ) goto Exit; /* ensure that we do not compare with data beyond the buffer */ p[read_len] = '\0'; limit = p + read_len - SFNTS_LEN; for ( p = buffer; p < limit; p++ ) { if ( p[0] == 'S' && ft_strncmp( (char*)p, STARTDATA, STARTDATA_LEN ) == 0 ) { /* save offset of binary data after `StartData' */ offset += (FT_ULong)( p - buffer ) + STARTDATA_LEN + 1; goto Found; } else if ( p[1] == 's' && ft_strncmp( (char*)p, SFNTS, SFNTS_LEN ) == 0 ) { offset += (FT_ULong)( p - buffer ) + SFNTS_LEN + 1; goto Found; } } if ( read_offset + read_len < STARTDATA_LEN ) { FT_TRACE2(( "cid_parser_new: no `StartData' keyword found\n" )); error = FT_THROW( Invalid_File_Format ); goto Exit; } FT_MEM_MOVE( buffer, buffer + read_offset + read_len - STARTDATA_LEN, STARTDATA_LEN ); /* values for the next loop */ read_len = 256; read_offset = STARTDATA_LEN; p = buffer + read_offset; } } Found: /* We have found the start of the binary data or the `/sfnts' token. */ /* Now rewind and extract the frame corresponding to this PostScript */ /* section. */ ps_len = offset - base_offset; if ( FT_STREAM_SEEK( base_offset ) || FT_FRAME_EXTRACT( ps_len, parser->postscript ) ) goto Exit; parser->data_offset = offset; parser->postscript_len = ps_len; parser->root.base = parser->postscript; parser->root.cursor = parser->postscript; parser->root.limit = parser->root.cursor + ps_len; parser->num_dict = -1; /* Finally, we check whether `StartData' or `/sfnts' was real -- */ /* it could be in a comment or string. We also get the arguments */ /* of `StartData' to find out whether the data is represented in */ /* binary or hex format. */ arg1 = parser->root.cursor; cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); arg2 = parser->root.cursor; cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); limit = parser->root.limit; cur = parser->root.cursor; while ( cur <= limit - SFNTS_LEN ) { if ( parser->root.error ) { error = parser->root.error; goto Exit; } if ( cur[0] == 'S' && cur <= limit - STARTDATA_LEN && ft_strncmp( (char*)cur, STARTDATA, STARTDATA_LEN ) == 0 ) { if ( ft_strncmp( (char*)arg1, "(Hex)", 5 ) == 0 ) { FT_Long tmp = ft_strtol( (const char *)arg2, NULL, 10 ); if ( tmp < 0 ) { FT_ERROR(( "cid_parser_new: invalid length of hex data\n" )); error = FT_THROW( Invalid_File_Format ); } else parser->binary_length = (FT_ULong)tmp; } goto Exit; } else if ( cur[1] == 's' && ft_strncmp( (char*)cur, SFNTS, SFNTS_LEN ) == 0 ) { FT_TRACE2(( "cid_parser_new: cannot handle Type 11 fonts\n" )); error = FT_THROW( Unknown_File_Format ); goto Exit; } cid_parser_skip_PS_token( parser ); cid_parser_skip_spaces ( parser ); arg1 = arg2; arg2 = cur; cur = parser->root.cursor; } /* we haven't found the correct `StartData'; go back and continue */ /* searching */ FT_FRAME_RELEASE( parser->postscript ); if ( !FT_STREAM_SEEK( offset ) ) goto Again; Exit: return error; }