public static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) { var y_scale_inv = invert != 0 ? -scale_y : scale_y; stbtt__edge *e; var n = 0; var i = 0; var j = 0; var k = 0; var m = 0; var vsubsample = 1; n = 0; for (i = 0; i < windings; ++i) { n += wcount[i]; } e = (stbtt__edge *)CRuntime.malloc((ulong)(sizeof(stbtt__edge) * (n + 1))); if (e == null) { return; } n = 0; m = 0; for (i = 0; i < windings; ++i) { var p = pts + m; m += wcount[i]; j = wcount[i] - 1; for (k = 0; k < wcount[i]; j = k++) { var a = k; var b = j; if (p[j].y == p[k].y) { continue; } e[n].invert = 0; if (invert != 0 && p[j].y > p[k].y || invert == 0 && p[j].y < p[k].y) { e[n].invert = 1; a = j; b = k; } e[n].x0 = p[a].x * scale_x + shift_x; e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; e[n].x1 = p[b].x * scale_x + shift_x; e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; ++n; } } stbtt__sort_edges(e, n); stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); CRuntime.free(e); }
public static void *stbtt__hheap_alloc(stbtt__hheap *hh, ulong size, void *userdata) { if ((hh->first_free) != null) { void *p = hh->first_free; hh->first_free = *(void **)(p); return(p); } else { if ((hh->num_remaining_in_head_chunk) == (0)) { int count = (int)((size) < (32) ? 2000 : (size) < (128) ? 800 : 100); stbtt__hheap_chunk *c = (stbtt__hheap_chunk *)(CRuntime.malloc((ulong)((ulong)sizeof(stbtt__hheap_chunk) + size * (ulong)(count)))); if ((c) == (null)) { return(null); } c->next = hh->head; hh->head = c; hh->num_remaining_in_head_chunk = (int)(count); } --hh->num_remaining_in_head_chunk; return((sbyte *)(hh->head) + sizeof(stbtt__hheap_chunk) + size * (ulong)hh->num_remaining_in_head_chunk); } }
public static int stbtt_PackFontRanges(stbtt_pack_context spc, byte *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) { stbtt_fontinfo info = new stbtt_fontinfo(); int i = 0; int j = 0; int n = 0; int return_value = (int)(1); stbrp_rect * rects; for (i = (int)(0); (i) < (num_ranges); ++i) { for (j = (int)(0); (j) < (ranges[i].num_chars); ++j) { ranges[i].chardata_for_range[j].x0 = (ushort)(ranges[i].chardata_for_range[j].y0 = (ushort)(ranges[i].chardata_for_range[j].x1 = (ushort)(ranges[i].chardata_for_range[j].y1 = (ushort)(0)))); } } n = (int)(0); for (i = (int)(0); (i) < (num_ranges); ++i) { n += (int)(ranges[i].num_chars); } rects = (stbrp_rect *)(CRuntime.malloc((ulong)(sizeof(stbrp_rect) * n))); if ((rects) == (null)) { return((int)(0)); } info.userdata = spc.user_allocator_context; stbtt_InitFont(info, fontdata, (int)(stbtt_GetFontOffsetForIndex(fontdata, (int)(font_index)))); n = (int)(stbtt_PackFontRangesGatherRects(spc, info, ranges, (int)(num_ranges), rects)); stbtt_PackFontRangesPackRects(spc, rects, (int)(n)); return_value = (int)(stbtt_PackFontRangesRenderIntoRects(spc, info, ranges, (int)(num_ranges), rects)); CRuntime.free(rects); return((int)(return_value)); }
public static void *stbtt__hheap_alloc(stbtt__hheap *hh, ulong size, void *userdata) { if (hh->first_free != null) { var p = hh->first_free; hh->first_free = *(void **)p; return(p); } if (hh->num_remaining_in_head_chunk == 0) { var count = size < 32 ? 2000 : size < 128 ? 800 : 100; var c = (stbtt__hheap_chunk *)CRuntime.malloc((ulong)sizeof(stbtt__hheap_chunk) + size * (ulong)count); if (c == null) { return(null); } c->next = hh->head; hh->head = c; hh->num_remaining_in_head_chunk = count; } --hh->num_remaining_in_head_chunk; return((sbyte *)hh->head + sizeof(stbtt__hheap_chunk) + size * (ulong)hh->num_remaining_in_head_chunk); }
public static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) { float y_scale_inv = (float)((invert) != 0 ? -scale_y : scale_y); stbtt__edge *e; int n = 0; int i = 0; int j = 0; int k = 0; int m = 0; int vsubsample = (int)(1); n = (int)(0); for (i = (int)(0); (i) < (windings); ++i) { n += (int)(wcount[i]); } e = (stbtt__edge *)(CRuntime.malloc((ulong)(sizeof(stbtt__edge) * (n + 1)))); if ((e) == (null)) { return; } n = (int)(0); m = (int)(0); for (i = (int)(0); (i) < (windings); ++i) { stbtt__point *p = pts + m; m += (int)(wcount[i]); j = (int)(wcount[i] - 1); for (k = (int)(0); (k) < (wcount[i]); j = (int)(k++)) { int a = (int)(k); int b = (int)(j); if ((p[j].y) == (p[k].y)) { continue; } e[n].invert = (int)(0); if ((((invert) != 0) && ((p[j].y) > (p[k].y))) || ((invert == 0) && ((p[j].y) < (p[k].y)))) { e[n].invert = (int)(1); a = (int)(j); b = (int)(k); } e[n].x0 = (float)(p[a].x * scale_x + shift_x); e[n].y0 = (float)((p[a].y * y_scale_inv + shift_y) * vsubsample); e[n].x1 = (float)(p[b].x * scale_x + shift_x); e[n].y1 = (float)((p[b].y * y_scale_inv + shift_y) * vsubsample); ++n; } } stbtt__sort_edges(e, (int)(n)); stbtt__rasterize_sorted_edges(result, e, (int)(n), (int)(vsubsample), (int)(off_x), (int)(off_y), userdata); CRuntime.free(e); }
/// <summary> /// Creates and initializes a font from ttf/otf/ttc data /// </summary> /// <param name="data"></param> /// <param name="offset"></param> /// <returns>null if the data was invalid</returns> public static stbtt_fontinfo CreateFont(byte[] data, int offset) { var dataCopy = (byte *)CRuntime.malloc(data.Length); Marshal.Copy(data, 0, new IntPtr(dataCopy), data.Length); var info = new stbtt_fontinfo { isDataCopy = true }; if (stbtt_InitFont_internal(info, dataCopy, offset) == 0) { info.Dispose(); return(null); } return(info); }
public static int stbtt_PackBegin(stbtt_pack_context spc, byte *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) { var context = (stbrp_context *)CRuntime.malloc((ulong)sizeof(stbrp_context)); var num_nodes = pw - padding; var nodes = (stbrp_node *)CRuntime.malloc((ulong)(sizeof(stbrp_node) * num_nodes)); if (context == null || nodes == null) { if (context != null) { CRuntime.free(context); } if (nodes != null) { CRuntime.free(nodes); } return(0); } spc.user_allocator_context = alloc_context; spc.width = pw; spc.height = ph; spc.pixels = pixels; spc.pack_info = context; spc.nodes = nodes; spc.padding = padding; spc.stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; spc.h_oversample = 1; spc.v_oversample = 1; spc.skip_missing = 0; stbrp_init_target(context, pw - padding, ph - padding, nodes, num_nodes); if (pixels != null) { CRuntime.memset(pixels, 0, (ulong)(pw * ph)); } return(1); }
public static int stbtt_PackFontRanges(stbtt_pack_context spc, byte *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) { var info = new stbtt_fontinfo(); var i = 0; var j = 0; var n = 0; var return_value = 1; stbrp_rect *rects; for (i = 0; i < num_ranges; ++i) { for (j = 0; j < ranges[i].num_chars; ++j) { ranges[i].chardata_for_range[j].x0 = ranges[i].chardata_for_range[j].y0 = ranges[i].chardata_for_range[j].x1 = ranges[i].chardata_for_range[j].y1 = 0; } } n = 0; for (i = 0; i < num_ranges; ++i) { n += ranges[i].num_chars; } rects = (stbrp_rect *)CRuntime.malloc((ulong)(sizeof(stbrp_rect) * n)); if (rects == null) { return(0); } info.userdata = spc.user_allocator_context; stbtt_InitFont(info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, font_index)); n = stbtt_PackFontRangesGatherRects(spc, info, ranges, num_ranges, rects); stbtt_PackFontRangesPackRects(spc, rects, n); return_value = stbtt_PackFontRangesRenderIntoRects(spc, info, ranges, num_ranges, rects); CRuntime.free(rects); return(return_value); }
public static int stbtt_PackBegin(stbtt_pack_context spc, byte *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) { stbrp_context *context = (stbrp_context *)(CRuntime.malloc((ulong)(sizeof(stbrp_context)))); int num_nodes = (int)(pw - padding); stbrp_node * nodes = (stbrp_node *)(CRuntime.malloc((ulong)(sizeof(stbrp_node) * num_nodes))); if (((context) == (null)) || ((nodes) == (null))) { if (context != (null)) { CRuntime.free(context); } if (nodes != (null)) { CRuntime.free(nodes); } return((int)(0)); } spc.user_allocator_context = alloc_context; spc.width = (int)(pw); spc.height = (int)(ph); spc.pixels = pixels; spc.pack_info = context; spc.nodes = nodes; spc.padding = (int)(padding); spc.stride_in_bytes = (int)(stride_in_bytes != 0 ? stride_in_bytes : pw); spc.h_oversample = (uint)(1); spc.v_oversample = (uint)(1); spc.skip_missing = (int)(0); stbrp_init_target(context, (int)(pw - padding), (int)(ph - padding), nodes, (int)(num_nodes)); if ((pixels) != null) { CRuntime.memset(pixels, (int)(0), (ulong)(pw * ph)); } return((int)(1)); }
public static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) { stbtt__point *points = null; var num_points = 0; var objspace_flatness_squared = objspace_flatness * objspace_flatness; var i = 0; var n = 0; var start = 0; var pass = 0; for (i = 0; i < num_verts; ++i) { if (vertices[i].type == STBTT_vmove) { ++n; } } *num_contours = n; if (n == 0) { return(null); } *contour_lengths = (int *)CRuntime.malloc((ulong)(sizeof(int) * n)); if (*contour_lengths == null) { *num_contours = 0; return(null); } for (pass = 0; pass < 2; ++pass) { float x = 0; float y = 0; if (pass == 1) { points = (stbtt__point *)CRuntime.malloc((ulong)(num_points * sizeof(stbtt__point))); if (points == null) { goto error; } } num_points = 0; n = -1; for (i = 0; i < num_verts; ++i) { switch (vertices[i].type) { case STBTT_vmove: if (n >= 0) { (*contour_lengths)[n] = num_points - start; } ++n; start = num_points; x = vertices[i].x; y = vertices[i].y; stbtt__add_point(points, num_points++, x, y); break; case STBTT_vline: x = vertices[i].x; y = vertices[i].y; stbtt__add_point(points, num_points++, x, y); break; case STBTT_vcurve: stbtt__tesselate_curve(points, &num_points, x, y, vertices[i].cx, vertices[i].cy, vertices[i].x, vertices[i].y, objspace_flatness_squared, 0); x = vertices[i].x; y = vertices[i].y; break; case STBTT_vcubic: stbtt__tesselate_cubic(points, &num_points, x, y, vertices[i].cx, vertices[i].cy, vertices[i].cx1, vertices[i].cy1, vertices[i].x, vertices[i].y, objspace_flatness_squared, 0); x = vertices[i].x; y = vertices[i].y; break; } } (*contour_lengths)[n] = num_points - start; } return(points); error :; CRuntime.free(points); CRuntime.free(*contour_lengths); *contour_lengths = null; *num_contours = 0; return(null); }
public static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) { var hh = new stbtt__hheap(); stbtt__active_edge *active = null; var y = 0; var j = 0; var i = 0; var scanline_data = stackalloc float[129]; float *scanline; float *scanline2; if (result->w > 64) { scanline = (float *)CRuntime.malloc((ulong)((result->w * 2 + 1) * sizeof(float))); } else { scanline = scanline_data; } scanline2 = scanline + result->w; y = off_y; e[n].y0 = (float)(off_y + result->h) + 1; while (j < result->h) { var scan_y_top = y + 0.0f; var scan_y_bottom = y + 1.0f; var step = &active; CRuntime.memset(scanline, 0, (ulong)(result->w * sizeof(float))); CRuntime.memset(scanline2, 0, (ulong)((result->w + 1) * sizeof(float))); while (*step != null) { var z = *step; if (z->ey <= scan_y_top) { *step = z->next; z->direction = 0; stbtt__hheap_free(&hh, z); } else { step = &(*step)->next; } } while (e->y0 <= scan_y_bottom) { if (e->y0 != e->y1) { var z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); if (z != null) { if (j == 0 && off_y != 0) { if (z->ey < scan_y_top) { z->ey = scan_y_top; } } z->next = active; active = z; } } ++e; } if (active != null) { stbtt__fill_active_edges_new(scanline, scanline2 + 1, result->w, active, scan_y_top); } { float sum = 0; for (i = 0; i < result->w; ++i) { float k = 0; var m = 0; sum += scanline2[i]; k = scanline[i] + sum; k = CRuntime.fabs(k) * 255 + 0.5f; m = (int)k; if (m > 255) { m = 255; } result->pixels[j * result->stride + i] = (byte)m; } } step = &active; while (*step != null) { var z = *step; z->fx += z->fdx; step = &(*step)->next; } ++y; ++j; } stbtt__hheap_cleanup(&hh, userdata); if (scanline != scanline_data) { CRuntime.free(scanline); } }
public static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) { stbtt__hheap hh = new stbtt__hheap(); stbtt__active_edge *active = (null); int y = 0; int j = (int)(0); int i = 0; float *scanline_data = stackalloc float[129]; float *scanline; float *scanline2; if ((result->w) > (64)) { scanline = (float *)(CRuntime.malloc((ulong)((result->w * 2 + 1) * sizeof(float)))); } else { scanline = scanline_data; } scanline2 = scanline + result->w; y = (int)(off_y); e[n].y0 = (float)((float)(off_y + result->h) + 1); while ((j) < (result->h)) { float scan_y_top = (float)(y + 0.0f); float scan_y_bottom = (float)(y + 1.0f); stbtt__active_edge **step = &active; CRuntime.memset(scanline, (int)(0), (ulong)(result->w * sizeof(float))); CRuntime.memset(scanline2, (int)(0), (ulong)((result->w + 1) * sizeof(float))); while ((*step) != null) { stbtt__active_edge *z = *step; if (z->ey <= scan_y_top) { *step = z->next; z->direction = (float)(0); stbtt__hheap_free(&hh, z); } else { step = &((*step)->next); } } while (e->y0 <= scan_y_bottom) { if (e->y0 != e->y1) { stbtt__active_edge *z = stbtt__new_active(&hh, e, (int)(off_x), (float)(scan_y_top), userdata); if (z != (null)) { if (((j) == (0)) && (off_y != 0)) { if ((z->ey) < (scan_y_top)) { z->ey = (float)(scan_y_top); } } z->next = active; active = z; } } ++e; } if ((active) != null) { stbtt__fill_active_edges_new(scanline, scanline2 + 1, (int)(result->w), active, (float)(scan_y_top)); } { float sum = (float)(0); for (i = (int)(0); (i) < (result->w); ++i) { float k = 0; int m = 0; sum += (float)(scanline2[i]); k = (float)(scanline[i] + sum); k = (float)((float)(CRuntime.fabs((double)(k))) * 255 + 0.5f); m = ((int)(k)); if ((m) > (255)) { m = (int)(255); } result->pixels[j * result->stride + i] = ((byte)(m)); } } step = &active; while ((*step) != null) { stbtt__active_edge *z = *step; z->fx += (float)(z->fdx); step = &((*step)->next); } ++y; ++j; } stbtt__hheap_cleanup(&hh, userdata); if (scanline != scanline_data) { CRuntime.free(scanline); } }
public static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) { stbtt__point *points = null; int num_points = (int)(0); float objspace_flatness_squared = (float)(objspace_flatness * objspace_flatness); int i = 0; int n = (int)(0); int start = (int)(0); int pass = 0; for (i = (int)(0); (i) < (num_verts); ++i) { if ((vertices[i].type) == (STBTT_vmove)) { ++n; } } *num_contours = (int)(n); if ((n) == (0)) { return(null); } *contour_lengths = (int *)(CRuntime.malloc((ulong)(sizeof(int) * n))); if ((*contour_lengths) == (null)) { *num_contours = (int)(0); return(null); } for (pass = (int)(0); (pass) < (2); ++pass) { float x = (float)(0); float y = (float)(0); if ((pass) == (1)) { points = (stbtt__point *)(CRuntime.malloc((ulong)(num_points * sizeof(stbtt__point)))); if ((points) == (null)) { goto error; } } num_points = (int)(0); n = (int)(-1); for (i = (int)(0); (i) < (num_verts); ++i) { switch (vertices[i].type) { case STBTT_vmove: if ((n) >= (0)) { (*contour_lengths)[n] = (int)(num_points - start); } ++n; start = (int)(num_points); x = (float)(vertices[i].x); y = (float)(vertices[i].y); stbtt__add_point(points, (int)(num_points++), (float)(x), (float)(y)); break; case STBTT_vline: x = (float)(vertices[i].x); y = (float)(vertices[i].y); stbtt__add_point(points, (int)(num_points++), (float)(x), (float)(y)); break; case STBTT_vcurve: stbtt__tesselate_curve(points, &num_points, (float)(x), (float)(y), (float)(vertices[i].cx), (float)(vertices[i].cy), (float)(vertices[i].x), (float)(vertices[i].y), (float)(objspace_flatness_squared), (int)(0)); x = (float)(vertices[i].x); y = (float)(vertices[i].y); break; case STBTT_vcubic: stbtt__tesselate_cubic(points, &num_points, (float)(x), (float)(y), (float)(vertices[i].cx), (float)(vertices[i].cy), (float)(vertices[i].cx1), (float)(vertices[i].cy1), (float)(vertices[i].x), (float)(vertices[i].y), (float)(objspace_flatness_squared), (int)(0)); x = (float)(vertices[i].x); y = (float)(vertices[i].y); break; } } (*contour_lengths)[n] = (int)(num_points - start); } return(points); error: ; CRuntime.free(points); CRuntime.free(*contour_lengths); *contour_lengths = null; *num_contours = (int)(0); return(null); }