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; }
/* * Handle the case of a large value or a value with a fraction part. * See gxmatrix.h for more details. */ fixed fixed_coeff_mult(fixed value, long coeff, const fixed_coeff *pfc, int maxb) { int shift = pfc->shift; /* * Test if the value is too large for simple long math. */ if ((value + (fixed_1 << (maxb - 1))) & (-fixed_1 << maxb)) { /* The second argument of fixed_mult_quo must be non-negative. */ return (coeff < 0 ? -fixed_mult_quo(value, -coeff, fixed_1 << shift) : fixed_mult_quo(value, coeff, fixed_1 << shift)); } else { /* * The construction above guarantees that the multiplications * won't overflow the capacity of an int. */ return (fixed) arith_rshift(fixed2int_var(value) * coeff + fixed2int(fixed_fraction(value) * coeff) + pfc->round, shift); } }
/* 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 {
static inline int set_x_gradient_nowedge(trap_gradient *xg, const trap_gradient *lg, const trap_gradient *rg, const trap_line *l, const trap_line *r, int il, int ir, int num_components) { /* Ignoring the ending coordinats fractions, so the gridient is slightly shifted to the left (in <1 'fixed' unit). */ int32_t xl = l->x - (l->xf == -l->h ? 1 : 0) - fixed_half; /* Revert the GX_FILL_TRAPEZOID shift. */ int32_t xr = r->x - (r->xf == -r->h ? 1 : 0) - fixed_half; /* Revert the GX_FILL_TRAPEZOID shift. */ /* The pixel span boundaries : */ int32_t x0 = int2fixed(il) + fixed_half; /* Shift to the pixel center. */ int32_t x1 = int2fixed(ir) - fixed_half; /* The center of the last pixel to paint. */ int i; # ifdef DEBUG if (arith_rshift_1(xr) - arith_rshift_1(xl) >= 0x3FFFFFFE) /* Can overflow ? */ return_error(gs_error_unregistered); /* Must not happen. */ # endif /* We cannot compute the color of the 'ir' pixel because it can overflow 'c1' due to the pixel ir center may be greater that r->x . Therefore we base the proportion on the pixel index ir-1 (see comment to 'x1'). Debugged with CET 12-14O.PS SpecialTestJ02Test12. */ xg->den = fixed2int(x1 - x0); if (xg->den <= 0) { /* The span contains a single pixel, will construct a degenerate gradient. */ xg->den = 1; /* Safety (against zerodivide). */ } for (i = 0; i < num_components; i++) { /* Ignoring the ending colors fractions, so the color gets a slightly smaller value (in <1 'frac31' unit), but it's not important due to the further conversion to [0, 1 << cinfo->comp_bits[j]], which drops the fraction anyway. */ int32_t cl = lg->c[i]; int32_t cr = rg->c[i]; int32_t c0 = (int32_t)(cl + ((int64_t)cr - cl) * (x0 - xl) / (xr - xl)); int32_t c1 = (int32_t)(cl + ((int64_t)cr - cl) * (x1 - xl) / (xr - xl)); xg->c[i] = c0; xg->f[i] = 0; /* Insufficient bits to compute it better. The color so the color gets a slightly smaller value (in <1 'frac31' unit), but it's not important due to the further conversion to [0, 1 << cinfo->comp_bits[j]], which drops the fraction anyway. So setting 0 appears pretty good and fast. */ xg->num[i] = c1 - c0; } return 0; }
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); }
static inline int mark_margin_interior(line_list * ll, margin_set * set, active_line * flp, active_line * alp, fixed y, fixed y0, fixed y1) { section *sect = set->sect; fixed x0 = (y == y0 ? flp->x_current : y == y1 ? flp->x_next : AL_X_AT_Y(flp, y)); fixed x1 = (y == y0 ? alp->x_current : y == y1 ? alp->x_next : AL_X_AT_Y(alp, y)); int i0 = fixed2int(x0), ii0, ii1, i, code; if (int2fixed(i0) + fixed_half < x0) i0++; ii0 = i0 - ll->bbox_left; ii1 = fixed2int_var_pixround(x1) - ll->bbox_left; if (ii0 < ii1) { if (ii0 < 0 || ii1 > ll->bbox_width) return_error(gs_error_unregistered); /* Must not happen. */ for (i = ii0; i < ii1; i++) { sect[i].y0 = sect[i].y1 = -2; vd_circle(int2fixed(i + ll->bbox_left) + fixed_half, y, 3, RGB(255, 0, 0)); } code = store_margin(ll, set, ii0, ii1); if (code < 0) return code; } return 0; }
/* 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; }
static void mark_line(fz_context *ctx, fz_edgebuffer *eb, fixed sx, fixed sy, fixed ex, fixed ey) { int base_y = eb->super.clip.y0; int height = eb->super.clip.y1 - eb->super.clip.y0; int *table = eb->table; int *index = eb->index; int delta; int iy, ih; fixed clip_sy, clip_ey; int dirn = DIRN_UP; int *row; if (fixed2int(sy + fixed_half-1) == fixed2int(ey + fixed_half-1)) return; if (sy > ey) { int t; t = sy; sy = ey; ey = t; t = sx; sx = ex; ex = t; dirn = DIRN_DOWN; } if (fixed2int(sx) < eb->super.bbox.x0) eb->super.bbox.x0 = fixed2int(sx); if (fixed2int(sx + fixed_1 - 1) > eb->super.bbox.x1) eb->super.bbox.x1 = fixed2int(sx + fixed_1 - 1); if (fixed2int(ex) < eb->super.bbox.x0) eb->super.bbox.x0 = fixed2int(ex); if (fixed2int(ex + fixed_1 - 1) > eb->super.bbox.x1) eb->super.bbox.x1 = fixed2int(ex + fixed_1 - 1); if (fixed2int(sy) < eb->super.bbox.y0) eb->super.bbox.y0 = fixed2int(sy); if (fixed2int(ey + fixed_1 - 1) > eb->super.bbox.y1) eb->super.bbox.y1 = fixed2int(ey + fixed_1 - 1); /* Lines go from sy to ey, closed at the start, open at the end. */ /* We clip them to a region to make them closed at both ends. */ /* Thus the unset scanline marked (>= sy) is: */ clip_sy = ((sy + fixed_half - 1) & ~(fixed_1-1)) | fixed_half; /* The last scanline marked (< ey) is: */ clip_ey = ((ey - fixed_half - 1) & ~(fixed_1-1)) | fixed_half; /* Now allow for banding */ if (clip_sy < int2fixed(base_y) + fixed_half) clip_sy = int2fixed(base_y) + fixed_half; if (ey <= clip_sy) return; if (clip_ey > int2fixed(base_y + height - 1) + fixed_half) clip_ey = int2fixed(base_y + height - 1) + fixed_half; if (sy > clip_ey) return; delta = clip_sy - sy; if (delta > 0) { int dx = ex - sx; int dy = ey - sy; int advance = (int)(((int64_t)dx * delta + (dy>>1)) / dy); sx += advance; sy += delta; }
static int margin_boundary(line_list * ll, margin_set * set, active_line * alp, fixed xx0, fixed xx1, fixed yy0, fixed yy1, int dir, fixed y0, fixed y1) { section *sect = set->sect; fixed x0, x1, xmin, xmax; int xp0, xp; int i0, i; # if !CHECK_SPOT_CONTIGUITY int i1; # endif if (yy0 > yy1) return 0; /* enumerate integral x's in [yy0,yy1] : */ if (alp == 0) x0 = xx0, x1 = xx1; else { x0 = (yy0 == y0 ? alp->x_current : AL_X_AT_Y(alp, yy0)); x1 = (yy1 == y1 ? alp->x_next : AL_X_AT_Y(alp, yy1)); } xmin = min(x0, x1); xmax = max(x0, x1); # if !CHECK_SPOT_CONTIGUITY xp0 = fixed_floor(xmin) + fixed_half; i0 = fixed2int(xp0) - ll->bbox_left; if (xp0 < xmin) { xp0 += fixed_1; i0++; } if (i0 < 0) return_error(gs_error_unregistered); /* Must not happen. */ for (i = i0, xp = xp0; xp < xmax && i < ll->bbox_width; xp += fixed_1, i++) { fixed y = (alp == 0 ? yy0 : Y_AT_X(alp, xp)); fixed dy = y - set->y; bool ud; short *b, h; section *s = §[i]; if (dy < 0) dy = 0; /* fix rounding errors in Y_AT_X */ if (dy >= fixed_1) dy = fixed_1; /* safety */ vd_circle(xp, y, 2, 0); ud = (alp == 0 ? (dir > 0) : ((alp->start.x - alp->end.x) * dir > 0)); b = (ud ? &s->y0 : &s->y1); h = (short)dy; if (*b == -1 || (*b != -2 && ( ud ? *b > h : *b < h))) *b = h; } # else xp0 = fixed_floor(xmin) + fixed_half; i0 = fixed2int(xp0) - ll->bbox_left; if (xp0 < xmin) { i0++; xp0 += fixed_1; } for (i = i0, xp = xp0; xp < xmax; xp += fixed_1, i++) { section *s = §[i]; fixed y = (alp==0 ? yy0 : Y_AT_X(alp, xp)); fixed dy = y - set->y; bool ud; short *b, h; if (dy < 0) dy = 0; /* fix rounding errors in Y_AT_X */ if (dy >= fixed_1) dy = fixed_1; /* safety */ vd_circle(xp, y, 2, 0); ud = (alp == 0 ? (dir > 0) : ((alp->start.x - alp->end.x) * dir > 0)); b = (ud ? &s->y0 : &s->y1); h = (short)dy; if (*b == -1 || (*b != -2 && ( ud ? *b > h : *b < h))) *b = h; } if (i0 < 0 || i > ll->bbox_width) return_error(gs_error_unregistered); /* Must not happen. */ # endif if (i > i0) return store_margin(ll, set, i0, i); return 0; }
int gslt_render_font_glyph(gs_state *pgs, gslt_font_t *xf, gs_matrix *tm, int gid, gslt_glyph_bitmap_t *slot) { gs_fixed_point subpixel = {0, 0}; /* we don't use subpixel accurate device metrics */ gs_log2_scale_point oversampling = {0, 0}; /* we don't use oversampling */ gs_text_params_t params; gs_text_enum_t *textenum; gs_matrix matrix; cached_fm_pair *ppair; cached_char *cc; int code; /* get the real font matrix (this is a little dance) */ gs_setfont(pgs, xf->font); /* set pgs->font and invalidate existing charmatrix */ gs_setcharmatrix(pgs, tm); /* set the charmatrix to ctm * tm */ gs_currentcharmatrix(pgs, &matrix, true); /* extract charmatrix (and multiply by FontMatrix) */ // dprintf4("tm = [%g %g %g %g]\n", matrix.xx, matrix.xy, matrix.yx, matrix.yy); /* find the font/matrix pair (or add it) */ code = gx_lookup_fm_pair(xf->font, &matrix, &oversampling, false, &ppair); if (code != 0) return gs_throw(-1, "cannot gx_lookup_fm_pair()"); cc = gx_lookup_cached_char(xf->font, ppair, gid, 0, 1, &subpixel); if (!cc) { /* No luck ... now we need to get it into the cache somehow. * * We do this by rendering one glyph (that's why we need a device and pgs). * The renderer always renders the bitmap into the cache, and draws * from out of the cache when blitting to the device. * * Things don't get evicted from the cache until there is a collision, * so we have a safe window to snarf it back out of the cache * after it's been drawn to the device. */ // dprintf1("cache miss for glyph %d\n", gid); params.operation = TEXT_FROM_SINGLE_GLYPH | TEXT_DO_DRAW | TEXT_RETURN_WIDTH; params.data.d_glyph = gid; params.size = 1; gs_moveto(pgs, 100.0, 100.0); // why? code = gs_text_begin(pgs, ¶ms, xf->font->memory, &textenum); if (code != 0) return gs_throw1(-1, "cannot gs_text_begin() (%d)", code); code = gs_text_process(textenum); if (code != 0) return gs_throw1(-1, "cannot gs_text_process() (%d)", code); gs_text_release(textenum, "gslt font render"); cc = gx_lookup_cached_char(xf->font, ppair, gid, 0, 1, &subpixel); if (!cc) { /* merde! it rendered but was not placed in the cache. */ return gs_throw(-2, "cannot render from cache"); } } /* copy values from the cache into the client struct */ slot->w = cc->width; slot->h = cc->height; slot->stride = cc_raster(cc); slot->lsb = fixed2int(cc->offset.x); slot->top = fixed2int(cc->offset.y); slot->cc = cc; slot->data = cc_bits(cc); gx_retain_cached_char(cc); #define XXX #ifndef XXX static int xxx = 0; /* declaration out in the wild not allowed in ansi c */ dprintf1("glyph %d\n", xxx); debug_dump_bitmap(cc_bits(cc), cc_raster(cc), cc->height, ""); { char fn[32]; sprintf(fn, "glyph%d.pbm", xxx); FILE *fo = fopen(fn, "wb"); if (!fo) return -1; fprintf(fo, "P4\n%d %d\n", cc->width, cc->height); int y; int s = (cc->width + 7) / 8; for (y = 0; y < cc->height; y++) fwrite(cc_bits(cc) + y * cc_raster(cc), 1, s, fo); fclose(fo); } xxx ++; #endif return 0; }
/* * If a Type 1 character is defined with 'seac', store the character codes * in chars[0] and chars[1] and return 1; otherwise, return 0 or <0. * This is exported only for the benefit of font copying. */ int gs_type1_piece_codes(/*const*/ gs_font_type1 *pfont, const gs_glyph_data_t *pgd, gs_char *chars) { gs_type1_data *const pdata = &pfont->data; /* * Decode the CharString looking for seac. We have to process * callsubr, callothersubr, and return operators, but if we see * any other operators other than [h]sbw, pop, hint operators, * or endchar, we can return immediately. We have to include * endchar because it is an (undocumented) equivalent for seac * in Type 2 CharStrings: see the cx_endchar case in * gs_type2_interpret in gstype2.c. * * It's really unfortunate that we have to duplicate so much parsing * code, but factoring out the parser from the interpreter would * involve more restructuring than we're prepared to do right now. */ bool encrypted = pdata->lenIV >= 0; fixed cstack[ostack_size]; fixed *csp; ip_state_t ipstack[ipstack_size + 1]; ip_state_t *ipsp = &ipstack[0]; const byte *cip; crypt_state state; int c; int code; CLEAR_CSTACK(cstack, csp); cip = pgd->bits.data; call: state = crypt_charstring_seed; if (encrypted) { int skip = pdata->lenIV; /* Skip initial random bytes */ for (; skip > 0; ++cip, --skip) decrypt_skip_next(*cip, state); } top: for (;;) { uint c0 = *cip++; charstring_next(c0, state, c, encrypted); if (c >= c_num1) { /* This is a number, decode it and push it on the stack. */ if (c < c_pos2_0) { /* 1-byte number */ decode_push_num1(csp, cstack, c); } else if (c < cx_num4) { /* 2-byte number */ decode_push_num2(csp, cstack, c, cip, state, encrypted); } else if (c == cx_num4) { /* 4-byte number */ long lw; decode_num4(lw, cip, state, encrypted); CS_CHECK_PUSH(csp, cstack); *++csp = int2fixed(lw); } else /* not possible */ return_error(gs_error_invalidfont); continue; } #define cnext CLEAR_CSTACK(cstack, csp); goto top switch ((char_command) c) { default: goto out; case c_callsubr: c = fixed2int_var(*csp) + pdata->subroutineNumberBias; code = pdata->procs.subr_data (pfont, c, false, &ipsp[1].cs_data); if (code < 0) return_error(code); --csp; ipsp->ip = cip, ipsp->dstate = state; ++ipsp; cip = ipsp->cs_data.bits.data; goto call; case c_return: gs_glyph_data_free(&ipsp->cs_data, "gs_type1_piece_codes"); --ipsp; cip = ipsp->ip, state = ipsp->dstate; goto top; case cx_hstem: case cx_vstem: case c1_hsbw: cnext; case cx_endchar: if (csp < cstack + 3) goto out; /* not seac */ do_seac: /* This is the payoff for all this code! */ chars[0] = fixed2int(csp[-1]); chars[1] = fixed2int(csp[0]); return 1; case cx_escape: charstring_next(*cip, state, c, encrypted); ++cip; switch ((char1_extended_command) c) { default: goto out; case ce1_vstem3: case ce1_hstem3: case ce1_sbw: cnext; case ce1_pop: /* * pop must do nothing, since it is used after * subr# 1 3 callothersubr. */ goto top; case ce1_seac: goto do_seac; case ce1_callothersubr: switch (fixed2int_var(*csp)) { default: goto out; case 3: csp -= 2; goto top; case 12: case 13: case 14: case 15: case 16: case 17: case 18: cnext; } } } #undef cnext } out: return 0; }
/* We take the trouble to do this efficiently in the simple cases. */ int gs_rectfill(gs_state * pgs, const gs_rect * pr, uint count) { const gs_rect *rlist = pr; gx_clip_path *pcpath; uint rcount = count; int code; gx_device * pdev = pgs->device; gx_device_color *pdc = gs_currentdevicecolor_inline(pgs); const gs_imager_state *pis = (const gs_imager_state *)pgs; bool hl_color_available = gx_hld_is_hl_color_available(pis, pdc); bool hl_color = (hl_color_available && dev_proc(pdev, dev_spec_op)(pdev, gxdso_supports_hlcolor, NULL, 0)); bool center_of_pixel = (pgs->fill_adjust.x == 0 && pgs->fill_adjust.y == 0); /* Processing a fill object operation */ dev_proc(pgs->device, set_graphics_type_tag)(pgs->device, GS_PATH_TAG); code = gx_set_dev_color(pgs); if (code != 0) return code; if ((is_fzero2(pgs->ctm.xy, pgs->ctm.yx) || is_fzero2(pgs->ctm.xx, pgs->ctm.yy)) && gx_effective_clip_path(pgs, &pcpath) >= 0 && clip_list_is_rectangle(gx_cpath_list(pcpath)) && (hl_color || pdc->type == gx_dc_type_pure || pdc->type == gx_dc_type_ht_binary || pdc->type == gx_dc_type_ht_colored) && gs_state_color_load(pgs) >= 0 && (*dev_proc(pdev, get_alpha_bits)) (pdev, go_graphics) <= 1 && (!pgs->overprint || !pgs->effective_overprint_mode) ) { uint i; gs_fixed_rect clip_rect; gx_cpath_inner_box(pcpath, &clip_rect); /* We should never plot anything for an empty clip rectangle */ if ((clip_rect.p.x >= clip_rect.q.x) && (clip_rect.p.y >= clip_rect.q.y)) return 0; for (i = 0; i < count; ++i) { gs_fixed_point p, q; gs_fixed_rect draw_rect; if (gs_point_transform2fixed(&pgs->ctm, pr[i].p.x, pr[i].p.y, &p) < 0 || gs_point_transform2fixed(&pgs->ctm, pr[i].q.x, pr[i].q.y, &q) < 0 ) { /* Switch to the slow algorithm. */ goto slow; } draw_rect.p.x = min(p.x, q.x); draw_rect.p.y = min(p.y, q.y); draw_rect.q.x = max(p.x, q.x); draw_rect.q.y = max(p.y, q.y); if (hl_color) { rect_intersect(draw_rect, clip_rect); /* We do pass on 0 extant rectangles to high level devices. It isn't clear how a client and an output device should interact if one uses a center of pixel algorithm and the other uses any part of pixel. For now we punt and just pass the high level rectangle on without adjustment. */ if (draw_rect.p.x <= draw_rect.q.x && draw_rect.p.y <= draw_rect.q.y) { code = dev_proc(pdev, fill_rectangle_hl_color)(pdev, &draw_rect, pis, pdc, pcpath); if (code < 0) return code; } } else { int x, y, w, h; rect_intersect(draw_rect, clip_rect); if (center_of_pixel) { draw_rect.p.x = fixed_rounded(draw_rect.p.x); draw_rect.p.y = fixed_rounded(draw_rect.p.y); draw_rect.q.x = fixed_rounded(draw_rect.q.x); draw_rect.q.y = fixed_rounded(draw_rect.q.y); } else { /* any part of pixel rule - touched */ draw_rect.p.x = fixed_floor(draw_rect.p.x); draw_rect.p.y = fixed_floor(draw_rect.p.y); draw_rect.q.x = fixed_ceiling(draw_rect.q.x); draw_rect.q.y = fixed_ceiling(draw_rect.q.y); } x = fixed2int(draw_rect.p.x); y = fixed2int(draw_rect.p.y); w = fixed2int(draw_rect.q.x) - x; h = fixed2int(draw_rect.q.y) - y; /* clients that use the "any part of pixel" rule also fill 0 areas. This is true of current graphics library clients but not a general rule. */ if (!center_of_pixel) { if (w == 0) w = 1; /* yes Adobe Acrobat 8, seems to back up the y coordinate when the width is 0, sigh. */ if (h == 0) { y--; h = 1; } } if (gx_fill_rectangle(x, y, w, h, pdc, pgs) < 0) goto slow; } } return 0; slow:rlist = pr + i; rcount = count - i; } { bool do_save = !gx_path_is_null(pgs->path); if (do_save) { if ((code = gs_gsave(pgs)) < 0) return code; gs_newpath(pgs); } if ((code = gs_rectappend(pgs, rlist, rcount)) < 0 || (code = gs_fill(pgs)) < 0 ) DO_NOTHING; if (do_save) gs_grestore(pgs); else if (code < 0) gs_newpath(pgs); } return code; }
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; }
int main() { int i, j, m, n; // gaussian low pass filter const float gaussFloat[SIZE][SIZE] = { {0.1019, 0.1154, 0.1019}, {0.1154, 0.1308, 0.1154}, {0.1019, 0.1154, 0.1019} }; int gauss[SIZE][SIZE]; for (m = 0; m < SIZE; m++) { for (n = 0; n < SIZE; n++) { gauss[m][n] = gaussFloat[m][n] * int2fixed(1); } } /* const float gauss[SIZE][SIZE] = { {1, 2, 1}, {2, 5, 2}, {1, 2, 1}, }; */ unsigned char blur[width-2][height-2]; int count = 0; /* * Non-striped memory version for (j = 0; j < height-2; j++) { for (i = 0; i < width-2; i++) { #ifdef FLOAT float sumFloat = 0; #endif int sum = 0; for (m = 0; m < SIZE; m++) { for (n = 0; n < SIZE; n++) { #ifdef FLOAT sumFloat += gaussFloat[m][n]*img[i+m][j+n]; #endif sum += fixedmul(gauss[m][n], int2fixed(img[i+m][j+n])); } } blur[i][j] = fixed2int(sum); count += blur[i][j]; //blur[i+1][j+1] = sum/17; #ifdef FLOAT float diff = fabs((float)blur[i][j]-sumFloat); assert (diff < 1.2); printf("fixed: %d expected: %f diff: %f\n", blur[i][j], sumFloat, diff); #endif } } */ int order = 0; int j_stride = 0; for (j = 0; j < height-2; j++) { // im00 im10 im20 // im01 im11 im21 // im02 im12 im22 unsigned char im00, im01, im02, im10, im11, im12, im20, im21, im22; unsigned char tmp00, tmp10, tmp01, tmp11, tmp20, tmp21; i = 0; int j1, j2, j3; if (order == 0) { j1 = j2 = j3 = j_stride; } else if (order == 1) { j2 = j3 = j_stride; j1 = j_stride+1; } else { j3 = j_stride; j1 = j2 = j_stride+1; } im00 = img1[i][j1]; im10 = img1[i+1][j1]; //assert(img[i][j]==im00); im01 = img2[i][j2]; im11 = img2[i+1][j2]; im02 = img3[i][j3]; im12 = img3[i+1][j3]; if (order == 0) { } else if (order == 1) { tmp00 = im00; tmp10 = im10; // first row from img2 im00 = im01; im10 = im11; // second row from img3 im01 = im02; im11 = im12; // third row from img1 im02 = tmp00; im12 = tmp10; } else { tmp00 = im00; tmp10 = im10; tmp01 = im01; tmp11 = im11; // first row from img3 im00 = im02; im10 = im12; // second row from img1 im01 = tmp00; im11 = tmp10; // third row from img2 im02 = tmp01; im12 = tmp11; } for (i = 0; i < width-2; i++) { im20 = img1[i+2][j1]; im21 = img2[i+2][j2]; im22 = img3[i+2][j3]; int pred1 = (order == 1); tmp20 = im20; // first row from img2 im20 = (pred1) ? im21 : im20; // second row from img3 im21 = (pred1) ? im22: im21; // third row from img1 im22 = (pred1) ? tmp20: im22; tmp20 = im20; tmp21 = im21; int pred2 = (order == 2); // first row from img3 im20 = (pred2) ? im22 : im20; // second row from img1 im21 = (pred2) ? tmp20 : im21; // third row from img2 im22 = (pred2) ? tmp21 : im22; int sum = 0; //assert(img[i][j]==im00); sum += fixedmul(gauss[0][0], int2fixed(im00)); sum += fixedmul(gauss[0][1], int2fixed(im01)); sum += fixedmul(gauss[0][2], int2fixed(im02)); sum += fixedmul(gauss[1][0], int2fixed(im10)); sum += fixedmul(gauss[1][1], int2fixed(im11)); sum += fixedmul(gauss[1][2], int2fixed(im12)); sum += fixedmul(gauss[2][0], int2fixed(im20)); sum += fixedmul(gauss[2][1], int2fixed(im21)); sum += fixedmul(gauss[2][2], int2fixed(im22)); blur[i][j] = fixed2int(sum); //blur[i+1][j+1] = sum/17; count += blur[i][j]; #ifdef FLOAT float sumFloat = 0; for (m = 0; m < SIZE; m++) { for (n = 0; n < SIZE; n++) { sumFloat += gaussFloat[m][n]*img[i+m][j+n]; } } float diff = fabs((float)blur[i][j]-sumFloat); assert (diff < 1.2); printf("fixed: %d expected: %f diff: %f\n", blur[i][j], sumFloat, diff); #endif // shift over to the right by 1 im00 = im10; im10 = im20; im01 = im11; im11 = im21; im02 = im12; im12 = im22; } if (order == 2) { order = 0; j_stride++; } else { order++; } } #ifdef PRINT_IMG //print_image(width, height, 255, img); print_image(width-2, height-2, 255, blur); #else printf("count: %d\n", count); if (count == 1931186) { printf(" _____ _____ _____ ______ _____ \n"); printf("| __ \\ /\\ / ____/ ____| ____| __ \\ \n"); printf("| |__) / \\ | (___| (___ | |__ | | | |\n"); printf("| ___/ /\\ \\ \\___ \\\\___ \\| __| | | | |\n"); printf("| | / ____ \\ ____) |___) | |____| |__| |\n"); printf("|_| /_/ \\_\\_____/_____/|______|_____/ \n"); } else { printf(" ______ _____ _ ______ _____ \n"); printf("| ____/\\ |_ _| | | ____| __ \\ \n"); printf("| |__ / \\ | | | | | |__ | | | |\n"); printf("| __/ /\\ \\ | | | | | __| | | | |\n"); printf("| | / ____ \\ _| |_| |____| |____| |__| |\n"); printf("|_|/_/ \\_\\_____|______|______|_____/ \n"); } #endif return count; }