static int alpha_buffer_init(gs_state * pgs, fixed extra_x, fixed extra_y, int alpha_bits, bool devn) { gx_device *dev = gs_currentdevice_inline(pgs); int log2_alpha_bits = ilog2(alpha_bits); gs_fixed_rect bbox; gs_int_rect ibox; uint width, raster, band_space; uint height; gs_log2_scale_point log2_scale; gs_memory_t *mem; gx_device_memory *mdev; log2_scale.x = log2_scale.y = log2_alpha_bits; gx_path_bbox(pgs->path, &bbox); ibox.p.x = fixed2int(bbox.p.x - extra_x) - 1; ibox.p.y = fixed2int(bbox.p.y - extra_y) - 1; ibox.q.x = fixed2int_ceiling(bbox.q.x + extra_x) + 1; ibox.q.y = fixed2int_ceiling(bbox.q.y + extra_y) + 1; width = (ibox.q.x - ibox.p.x) << log2_scale.x; raster = bitmap_raster(width); band_space = raster << log2_scale.y; height = (abuf_nominal / band_space) << log2_scale.y; if (height == 0) height = 1 << log2_scale.y; mem = pgs->memory; mdev = gs_alloc_struct(mem, gx_device_memory, &st_device_memory, "alpha_buffer_init"); if (mdev == 0) return 0; /* if no room, don't buffer */ /* We may have to update the marking parameters if we have a pdf14 device as our target. Need to do while dev is still active in pgs */ if (dev_proc(dev, dev_spec_op)(dev, gxdso_is_pdf14_device, NULL, 0) > 0) { gs_update_trans_marking_params(pgs); } gs_make_mem_abuf_device(mdev, mem, dev, &log2_scale, alpha_bits, ibox.p.x << log2_scale.x, devn); mdev->width = width; mdev->height = height; mdev->bitmap_memory = mem; if ((*dev_proc(mdev, open_device)) ((gx_device *) mdev) < 0) { /* No room for bits, punt. */ gs_free_object(mem, mdev, "alpha_buffer_init"); return 0; } gx_set_device_only(pgs, (gx_device *) mdev); scale_paths(pgs, log2_scale.x, log2_scale.y, true); return 1; }
/* Draw a one-pixel-wide line. */ int gz_draw_line_fixed(fixed ixf, fixed iyf, fixed itoxf, fixed itoyf, gx_device_color *pdevc, gs_state *pgs) { int ix = fixed2int(ixf); int iy = fixed2int(iyf); int itox = fixed2int(itoxf); int itoy = fixed2int(itoyf); if ( itoy == iy ) /* horizontal line */ { if ( ix <= itox ) gz_fill_rectangle(ix, iy, fixed2int_ceiling(itoxf) - ix, 1, pdevc, pgs); else gz_fill_rectangle(itox, iy, fixed2int_ceiling(ixf) - itox, 1, pdevc, pgs); } else { gx_device *dev = pgs->device->info; fixed h, w, tf; #define fswap(a, b) tf = a, a = b, b = tf if ( color_is_pure(pdevc) && (*dev->procs->draw_line)(dev, ix, iy, itox, itoy, pdevc->color1) >= 0 ) return 0; h = itoyf - iyf; w = itoxf - ixf; #define fixed_eps (fixed)1 if ( (w < 0 ? -w : w) <= (h < 0 ? -h : h) ) { if ( h < 0 ) fswap(ixf, itoxf), fswap(iyf, itoyf), h = -h; gz_fill_trapezoid_fixed(ixf, fixed_eps, iyf, itoxf, fixed_eps, h, 0, pdevc, pgs); } else { if ( w < 0 ) fswap(ixf, itoxf), fswap(iyf, itoyf), w = -w; gz_fill_trapezoid_fixed(iyf, fixed_eps, ixf, itoyf, fixed_eps, w, 1, pdevc, pgs); } #undef fixed_eps #undef fswap } return 0; }
static int alpha_buffer_init(gs_state * pgs, fixed extra_x, fixed extra_y, int alpha_bits) { gx_device *dev = gs_currentdevice_inline(pgs); int log2_alpha_bits = ilog2(alpha_bits); gs_fixed_rect bbox; gs_int_rect ibox; uint width, raster, band_space; uint height; gs_log2_scale_point log2_scale; gs_memory_t *mem; gx_device_memory *mdev; log2_scale.x = log2_scale.y = log2_alpha_bits; gx_path_bbox(pgs->path, &bbox); ibox.p.x = fixed2int(bbox.p.x - extra_x) - 1; ibox.p.y = fixed2int(bbox.p.y - extra_y) - 1; ibox.q.x = fixed2int_ceiling(bbox.q.x + extra_x) + 1; ibox.q.y = fixed2int_ceiling(bbox.q.y + extra_y) + 1; width = (ibox.q.x - ibox.p.x) << log2_scale.x; raster = bitmap_raster(width); band_space = raster << log2_scale.y; height = (abuf_nominal / band_space) << log2_scale.y; if (height == 0) height = 1 << log2_scale.y; mem = pgs->memory; mdev = gs_alloc_struct(mem, gx_device_memory, &st_device_memory, "alpha_buffer_init"); if (mdev == 0) return 0; /* if no room, don't buffer */ gs_make_mem_abuf_device(mdev, mem, dev, &log2_scale, alpha_bits, ibox.p.x << log2_scale.x); mdev->width = width; mdev->height = height; mdev->bitmap_memory = mem; if ((*dev_proc(mdev, open_device)) ((gx_device *) mdev) < 0) { /* No room for bits, punt. */ gs_free_object(mem, mdev, "alpha_buffer_init"); return 0; } gx_set_device_only(pgs, (gx_device *) mdev); scale_paths(pgs, log2_scale.x, log2_scale.y, true); return 1; }
int gx_default_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa, int i0, int j, int w, const frac31 *c0, const int32_t *c0f, const int32_t *cg_num, int32_t cg_den) { /* This default implementation decomposes the area into constant color rectangles. Devices may supply optimized implementations with the inversed nesting of the i,k cicles, i.e. with enumerating planes first, with a direct writing to the raster, and with a fixed bits per component. */ frac31 c[GX_DEVICE_COLOR_MAX_COMPONENTS]; ulong f[GX_DEVICE_COLOR_MAX_COMPONENTS]; int i, i1 = i0 + w, bi = i0, k; gx_color_index ci0 = 0, ci1; const gx_device_color_info *cinfo = &dev->color_info; int n = cinfo->num_components; int si, ei, di, code; if (j < fixed2int(fa->clip->p.y) || j > fixed2int_ceiling(fa->clip->q.y)) /* Must be compatible to the clipping logic. */ return 0; for (k = 0; k < n; k++) { int shift = cinfo->comp_shift[k]; int bits = cinfo->comp_bits[k]; c[k] = c0[k]; f[k] = c0f[k]; ci0 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift; } for (i = i0 + 1, di = 1; i < i1; i += di) { if (di == 1) { /* Advance colors by 1 pixel. */ ci1 = 0; for (k = 0; k < n; k++) { int shift = cinfo->comp_shift[k]; int bits = cinfo->comp_bits[k]; if (cg_num[k]) { int32_t m = f[k] + cg_num[k]; c[k] += m / cg_den; m -= m / cg_den * cg_den; if (m < 0) { c[k]--; m += cg_den; } f[k] = m; } ci1 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift; } } else {
int continue_margin_common(line_list * ll, margin_set * set, active_line * flp, active_line * alp, fixed y0, fixed y1) { int code; # if ADJUST_SERIF section *sect = set->sect; fixed yy0 = max(max(y0, alp->start.y), set->y); fixed yy1 = min(min(y1, alp->end.y), set->y + fixed_1); if (yy0 <= yy1) { fixed x00 = (yy0 == y0 ? flp->x_current : AL_X_AT_Y(flp, yy0)); fixed x10 = (yy0 == y0 ? alp->x_current : AL_X_AT_Y(alp, yy0)); fixed x01 = (yy1 == y1 ? flp->x_next : AL_X_AT_Y(flp, yy1)); fixed x11 = (yy1 == y1 ? alp->x_next : AL_X_AT_Y(alp, yy1)); fixed xmin = min(x00, x01), xmax = max(x10, x11); int i0 = fixed2int(xmin) - ll->bbox_left, i; int i1 = fixed2int_ceiling(xmax) - ll->bbox_left; for (i = i0; i < i1; i++) { section *s = §[i]; int x_pixel = int2fixed(i + ll->bbox_left); int xl = max(xmin - x_pixel, 0); int xu = min(xmax - x_pixel, fixed_1); s->x0 = min(s->x0, xl); s->x1 = max(s->x1, xu); x_pixel+=0; /* Just a place for breakpoint */ } code = store_margin(ll, set, i0, i1); if (code < 0) return code; /* fixme : after ADJUST_SERIF becames permanent, * don't call margin_boundary if yy0 > yy1. */ } # endif code = margin_boundary(ll, set, flp, 0, 0, yy0, yy1, 1, y0, y1); if (code < 0) return code; return margin_boundary(ll, set, alp, 0, 0, yy0, yy1, -1, y0, y1); }
/* Note that the arguments are fixeds, not ints! */ int gz_fill_trapezoid_fixed(fixed fx0, fixed fw0, fixed fy0, fixed fx1, fixed fw1, fixed fh, int swap_axes, gx_device_color *pdevc, gs_state *pgs) { /* For the moment, we just convert everything to ints. */ /* Later we will do the right thing with fractional pixels. */ int x0 = fixed2int(fx0); fixed fx0r = fx0 + fw0; int w0 = fixed2int_ceiling(fx0r) - x0; int y0 = fixed2int(fy0); int x1 = fixed2int(fx1); fixed fx1r = fx1 + fw1; int w1 = fixed2int_ceiling(fx1r) - x1; fixed fy1 = fy0 + fh; int y1 = fixed2int_ceiling(fy1); int h = y1 - y0; if ( w0 == 0 && w1 == 0 || h <= 0 ) return 0; if ( !swap_axes && color_is_pure(pdevc) ) { gx_device *dev = pgs->device->info; if ( (*dev->procs->fill_trapezoid)(dev, x0, y0, w0, x1, y1, w1, pdevc->color1) >= 0 ) return 0; } { int xl, fxl; int dxl, dxl1, dxlf = x1 - x0; int xr, fxr; int dxr, dxr1, dxrf = x1 + w1 - (x0 + w0); int y = y0; int rxl, rxr, ry; /* Compute integer and fractional deltas */ #define reduce_delta(df, d, d1, pos)\ if ( df >= 0 )\ { if ( df >= h )\ d1 = (d = df / h) + 1, df -= d * h;\ else /* save the divides */\ { pos();\ d = 0, d1 = 1;\ }\ }\ else /* df < 0 */\ { if ( df <= -h )\ d1 = (d = df / h) - 1, df = d * h - df;\ else /* save the divides */\ d = 0, d1 = -1, df = -df;\ } #define fill_trap_rect(x,y,w,h)\ if ( swap_axes ) gz_fill_rectangle(y, x, h, w, pdevc, pgs);\ else gz_fill_rectangle(x, y, w, h, pdevc, pgs) #define pos_for_xl() /* nothing */ reduce_delta(dxlf, dxl, dxl1, pos_for_xl); #define pos_for_xr()\ if ( dxl == 0 && dxlf == 0 && dxrf == 0 ) /* detect rectangle */\ { fill_trap_rect(x0, y0, w0, h);\ return 0;\ } reduce_delta(dxrf, dxr, dxr1, pos_for_xr); xl = x0, fxl = arith_rshift(dxlf, 1); xr = x0 + w0, fxr = arith_rshift(dxrf, 1); rxl = xl, rxr = xr, ry = y; /* Do the fill */ do { if ( xl != rxl || xr != rxr ) /* detect rectangles */ { fill_trap_rect(rxl, ry, rxr - rxl, y - ry); rxl = xl, rxr = xr, ry = y; } if ( (fxl += dxlf) >= h ) fxl -= h, xl += dxl1; else xl += dxl; if ( (fxr += dxrf) >= h ) fxr -= h, xr += dxr1; else xr += dxr; } while ( ++y < y1 ); if ( y != ry ) { fill_trap_rect(rxl, ry, rxr - rxl, y - ry); } #undef fill_trap_rect } return 0; }
int gx_default_fill_linear_color_scanline(gx_device *dev, const gs_fill_attributes *fa, int i0, int j, int w, const frac31 *c0, const int32_t *c0f, const int32_t *cg_num, int32_t cg_den) { /* This default implementation decomposes the area into constant color rectangles. Devices may supply optimized implementations with the inversed nesting of the i,k cicles, i.e. with enumerating planes first, with a direct writing to the raster, and with a fixed bits per component. */ frac31 c[GX_DEVICE_COLOR_MAX_COMPONENTS]; ulong f[GX_DEVICE_COLOR_MAX_COMPONENTS]; int i, i1 = i0 + w, bi = i0, k; gx_color_index ci0 = 0, ci1; const gx_device_color_info *cinfo = &dev->color_info; int n = cinfo->num_components; int si, ei, code; if (j < fixed2int(fa->clip->p.y) || j > fixed2int_ceiling(fa->clip->q.y)) /* Must be compatible to the clipping logic. */ return 0; for (k = 0; k < n; k++) { int shift = cinfo->comp_shift[k]; int bits = cinfo->comp_bits[k]; c[k] = c0[k]; f[k] = c0f[k]; ci0 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift; } for (i = i0 + 1; i < i1; i++) { ci1 = 0; for (k = 0; k < n; k++) { int shift = cinfo->comp_shift[k]; int bits = cinfo->comp_bits[k]; int32_t m = f[k] + cg_num[k]; c[k] += m / cg_den; m -= m / cg_den * cg_den; if (m < 0) { c[k]--; m += cg_den; } f[k] = m; ci1 |= (gx_color_index)(c[k] >> (sizeof(c[k]) * 8 - 1 - bits)) << shift; } if (ci1 != ci0) { si = max(bi, fixed2int(fa->clip->p.x)); /* Must be compatible to the clipping logic. */ ei = min(i, fixed2int_ceiling(fa->clip->q.x)); /* Must be compatible to the clipping logic. */ if (si < ei) { if (fa->swap_axes) { vd_rect(int2fixed(j), int2fixed(si), int2fixed(j + 1), int2fixed(ei), 1, (ulong)ci0); code = dev_proc(dev, fill_rectangle)(dev, j, si, 1, ei - si, ci0); } else { vd_rect(int2fixed(si), int2fixed(j), int2fixed(ei), int2fixed(j + 1), 1, (ulong)ci0); code = dev_proc(dev, fill_rectangle)(dev, si, j, ei - si, 1, ci0); } if (code < 0) return code; } bi = i; ci0 = ci1; } } si = max(bi, fixed2int(fa->clip->p.x)); /* Must be compatible to the clipping logic. */ ei = min(i, fixed2int_ceiling(fa->clip->q.x)); /* Must be compatible to the clipping logic. */ if (si < ei) { if (fa->swap_axes) { vd_rect(int2fixed(j), int2fixed(si), int2fixed(j + 1), int2fixed(ei), 1, (ulong)ci0); return dev_proc(dev, fill_rectangle)(dev, j, si, 1, ei - si, ci0); } else { vd_rect(int2fixed(si), int2fixed(j), int2fixed(ei), int2fixed(j + 1), 1, (ulong)ci0); return dev_proc(dev, fill_rectangle)(dev, si, j, ei - si, 1, ci0); } } return 0; }