Esempio n. 1
0
/* Release all memory acquired by this allocator. */
static void
gs_heap_free_all(gs_memory_t * mem, uint free_mask, client_name_t cname)
{
    gs_malloc_memory_t *const mmem = (gs_malloc_memory_t *) mem;
    gx_monitor_t *mon = mmem->monitor;

    /*
     * We don't perform locking during this process since the 'monitor'
     * is contained in this allocator, and will get freed along the way.
     * It is only called at exit, and there better not be any threads
     * accessing this allocator.
     */
    mmem->monitor = NULL; 	/* delete reference to this monitor */
    gx_monitor_free(mon);	/* free the monitor */
    if (free_mask & FREE_ALL_DATA) {
	gs_malloc_block_t *bp = mmem->allocated;
	gs_malloc_block_t *np;

	for (; bp != 0; bp = np) {
	    np = bp->next;
	    if_debug3('a', "[a]gs_heap_free_all(%s) 0x%lx(%u)\n",
		      client_name_string(bp->cname), (ulong) (bp + 1),
		      bp->size);
	    gs_alloc_fill(bp + 1, gs_alloc_fill_free, bp->size);
	    free(bp);
	}
    }
    if (free_mask & FREE_ALL_ALLOCATOR)
	free(mem);
}
Esempio n. 2
0
/* Used for when we have to mash entire transform to CIEXYZ */
int
gx_psconcretize_CIEABC(const gs_client_color * pc, const gs_color_space * pcs,
                      frac * pconc, const gs_imager_state * pis)
{
    const gs_cie_abc *pcie = pcs->params.abc;
    cie_cached_vector3 vec3;
    int code;

    if_debug3('c', "[c]concretize CIEABC [%g %g %g]\n",
              pc->paint.values[0], pc->paint.values[1],
              pc->paint.values[2]);
    code = gx_cie_check_rendering_inline(pcs, pconc, pis);
    if (code < 0)
        return code;
    if (code == 1)
        return 0;

    vec3.u = float2cie_cached(pc->paint.values[0]);
    vec3.v = float2cie_cached(pc->paint.values[1]);
    vec3.w = float2cie_cached(pc->paint.values[2]);
    if (!pis->cie_joint_caches->skipDecodeABC)
        cie_lookup_map3(&vec3 /* ABC => LMN */, &pcie->caches.DecodeABC,
                        "Decode/MatrixABC");
    GX_CIE_REMAP_FINISH(vec3, pconc, pis, pcs);
    return 0;
}
Esempio n. 3
0
gx_color_index eprn_map_rgb_color_for_RGB(gx_device *device,
  const gx_color_value cv[])
{
  gx_color_value red = cv[0], green = cv[1], blue = cv[2];
  static const gx_color_value half = gx_max_color_value/2;
  gx_color_index value = 0;
  const eprn_Device *dev = (eprn_Device *)device;

#ifdef EPRN_TRACE
  if_debug3(EPRN_TRACE_CHAR,
    "! eprn_map_rgb_color_for_RGB() called for RGB = (%hu, %hu, %hu),\n",
    red, green, blue);
#endif

  assert(dev->eprn.colour_model == eprn_DeviceRGB);

  if (red   > half) value |= RED_BIT;
  if (green > half) value |= GREEN_BIT;
  if (blue  > half) value |= BLUE_BIT;

#ifdef EPRN_TRACE
  if_debug1(EPRN_TRACE_CHAR, "  returning 0x%lX.\n", (unsigned long)value);
#endif
  return value;
}
Esempio n. 4
0
/* Evaluate a 1-Input Stitching function. */
static int
fn_1ItSg_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
{
    const gs_function_1ItSg_t *const pfn =
	(const gs_function_1ItSg_t *)pfn_common;
    float arg = in[0], b0, b1, e0, encoded;
    int k = pfn->params.k;
    int i;

    if (arg < pfn->params.Domain[0]) {
	arg = pfn->params.Domain[0];
	i = 0;
    } else if (arg > pfn->params.Domain[1]) {
	arg = pfn->params.Domain[1];
	i = k - 1;
    } else {
	for (i = 0; i < k - 1; ++i)
	    if (arg <= pfn->params.Bounds[i])
		break;
    }
    b0 = (i == 0 ? pfn->params.Domain[0] : pfn->params.Bounds[i - 1]);
    b1 = (i == k - 1 ? pfn->params.Domain[1] : pfn->params.Bounds[i]);
    e0 = pfn->params.Encode[2 * i];
    if (b1 == b0)
	encoded = e0;
    else
	encoded =
	    (arg - b0) * (pfn->params.Encode[2 * i + 1] - e0) / (b1 - b0) + e0;
    if_debug3('~', "[~]1ItSg %g in %d => %g\n", arg, i, encoded);
    return gs_function_evaluate(pfn->params.Functions[i], &encoded, out);
}
Esempio n. 5
0
gx_color_index eprn_map_rgb_color_for_RGB_flex(gx_device *device,
  const gx_color_value cv[])
{
  gx_color_value red = cv[0], green = cv[1], blue = cv[2];
  gx_color_index value = 0;
  gx_color_value step;
  unsigned int level;
  const eprn_Eprn *eprn = &((eprn_Device *)device)->eprn;

#ifdef EPRN_TRACE
  if_debug3(EPRN_TRACE_CHAR,
    "! eprn_map_rgb_color_for_RGB_flex() called for RGB = (%hu, %hu, %hu),\n",
    red, green, blue);
#endif

  /* See the discussion in eprn_map_cmyk_color_flex() below. */

  step = gx_max_color_value/eprn->non_black_levels;

  /* The order has to be BGR from left to right */
  level = blue/step;
  if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1;
  value = level << eprn->bits_per_colorant;
  level = green/step;
  if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1;
  value = (value | level) << eprn->bits_per_colorant;
  level = red/step;
  if (level >= eprn->non_black_levels) level = eprn->non_black_levels - 1;
  value = (value | level) << eprn->bits_per_colorant;

#ifdef EPRN_TRACE
  if_debug1(EPRN_TRACE_CHAR, "  returning 0x%lX.\n", (unsigned long)value);
#endif
  return value;
}
Esempio n. 6
0
gx_color_index eprn_map_rgb_color_for_CMY_or_K(gx_device *device,
  const gx_color_value cv[])
{
  gx_color_value red = cv[0], green = cv[1], blue = cv[2];
  static const gx_color_value half = gx_max_color_value/2;
  gx_color_index value = (CYAN_BIT | MAGENTA_BIT | YELLOW_BIT);
  const eprn_Device *dev = (eprn_Device *)device;

#ifdef EPRN_TRACE
  if_debug3(EPRN_TRACE_CHAR,
    "! eprn_map_rgb_color_for_CMY_or_K() called for RGB = (%hu, %hu, %hu),\n",
    red, green, blue);
#endif

  assert(dev->eprn.colour_model == eprn_DeviceGray && red == green &&
      green == blue && (blue == 0 || blue == gx_max_color_value) ||
    dev->eprn.colour_model == eprn_DeviceCMY ||
    dev->eprn.colour_model == eprn_DeviceCMY_plus_K);

  /* Map to CMY */
  if (red   > half) value &= ~CYAN_BIT;
  if (green > half) value &= ~MAGENTA_BIT;
  if (blue  > half) value &= ~YELLOW_BIT;

  /* Remap composite black to true black if available */
  if (dev->eprn.colour_model != eprn_DeviceCMY &&
      value == (CYAN_BIT | MAGENTA_BIT | YELLOW_BIT))
    value = BLACK_BIT;

#ifdef EPRN_TRACE
  if_debug1(EPRN_TRACE_CHAR, "  returning 0x%lX.\n", (unsigned long)value);
#endif
  return value;
}
Esempio n. 7
0
gx_color_index eprn_map_rgb_color_for_CMY_or_K_flex(gx_device *device,
  const gx_color_value cv[])
{
  gx_color_value red = cv[0], green = cv[1], blue = cv[2];
  const eprn_Device *dev = (eprn_Device *)device;

#ifdef EPRN_TRACE
  if_debug3(EPRN_TRACE_CHAR,
    "! eprn_map_rgb_color_for_CMY_or_K_flex() called for "
      "RGB = (%hu, %hu, %hu).\n",
    red, green, blue);
#endif

  /* Treat pure grey levels differently if we have black. This implies that for
     CMY+K only "true" grey shades will be printed with black ink, all others
     will be mixed from CMY. */
  gx_color_value tmpcv[4];
  if (dev->eprn.colour_model != eprn_DeviceCMY && red == green && green == blue) {
    tmpcv[0] = 0; tmpcv[1] = 0; tmpcv[2] = 0;
    tmpcv[3] = gx_max_color_value - red;
    return eprn_map_cmyk_color_flex(device, tmpcv);

  }
  tmpcv[0] = gx_max_color_value - red; 
  tmpcv[1] = gx_max_color_value - green; 
  tmpcv[2] = gx_max_color_value - blue; 
  tmpcv[3] = 0;
  return eprn_map_cmyk_color_flex(device, tmpcv);
}
Esempio n. 8
0
gx_color_index eprn_map_rgb_color_for_CMY_or_K_max(gx_device *device,
  const gx_color_value cv[])
{
  gx_color_value red = cv[0], green = cv[1], blue = cv[2];
  const eprn_Device *dev = (eprn_Device *)device;

#ifdef EPRN_TRACE
  if_debug3(EPRN_TRACE_CHAR,
    "! eprn_map_rgb_color_for_CMY_or_K_max() called for "
      "RGB = (%hu, %hu, %hu).\n",
    red, green, blue);
#endif

  gx_color_value tmpcv[4];
  if (dev->eprn.colour_model == eprn_DeviceGray) {
    tmpcv[0] = 0; tmpcv[1] = 0; tmpcv[2] = 0;
    tmpcv[3] = gx_max_color_value - red;
    return eprn_map_cmyk_color_max(device, tmpcv);
  }
  /* Note that the conversion from composite black to true black for CMY+K can
     only happen at the output pixel level, not here. */
  tmpcv[0] = gx_max_color_value - red; 
  tmpcv[1] = gx_max_color_value - green; 
  tmpcv[2] = gx_max_color_value - blue; 
  tmpcv[3] = 0;
  return eprn_map_cmyk_color_max(device, tmpcv);
}
Esempio n. 9
0
/* Evaluate an Exponential Interpolation function. */
static int
fn_ElIn_evaluate(const gs_function_t * pfn_common, const float *in, float *out)
{
    const gs_function_ElIn_t *const pfn =
	(const gs_function_ElIn_t *)pfn_common;
    double arg = in[0], raised;
    int i;

    if (arg < pfn->params.Domain[0])
	arg = pfn->params.Domain[0];
    else if (arg > pfn->params.Domain[1])
	arg = pfn->params.Domain[1];
    raised = pow(arg, pfn->params.N);
    for (i = 0; i < pfn->params.n; ++i) {
	float v0 = (pfn->params.C0 == 0 ? 0.0 : pfn->params.C0[i]);
	float v1 = (pfn->params.C1 == 0 ? 1.0 : pfn->params.C1[i]);
	double value = v0 + raised * (v1 - v0);

	if (pfn->params.Range) {
	    float r0 = pfn->params.Range[2 * i],
		r1 = pfn->params.Range[2 * i + 1];

	    if (value < r0)
		value = r0;
	    else if (value > r1)
		value = r1;
	}
	out[i] = value;
	if_debug3('~', "[~]ElIn %g => [%d]%g\n", arg, i, out[i]);
    }
    return 0;
}
Esempio n. 10
0
int
gx_concretize_CIEABC(const gs_client_color * pc, const gs_color_space * pcs_in,
                     frac * pconc, const gs_imager_state * pis, gx_device *dev)
{
    gs_color_space *pcs_icc;
    gs_client_color scale_pc;
    bool islab;
    gs_color_space *pcs = (gs_color_space *) pcs_in;

    if_debug3('c', "[c]concretize CIEABC [%g %g %g]\n",
              pc->paint.values[0], pc->paint.values[1],
              pc->paint.values[2]);
    /* If we are comming in here then we have not completed
       the conversion of the ABC space to an ICC type.  We
       will finish that process now. */
    if (pcs->icc_equivalent == NULL) {
        gx_cieabc_to_icc(&pcs_icc, pcs, &islab, pis->memory->stable_memory);
    } else {
        pcs_icc = pcs->icc_equivalent;
    }
    /* Rescale the input based upon the input range since profile is
       created to remap this range from 0 to 1 */
    if (check_range(&(pcs->params.abc->RangeABC.ranges[0]), 3)) {
        return((pcs_icc->type->concretize_color)(pc, pcs_icc, pconc, pis, dev));
    }
    /* Do the rescale from 0 to 1 */
    rescale_input_color(&(pcs->params.abc->RangeABC.ranges[0]), 3, pc, &scale_pc);
    /* Now the icc remap */
    return((pcs_icc->type->concretize_color)(&scale_pc, pcs_icc, pconc, pis, dev));
}
Esempio n. 11
0
/* Render a CIEBasedDEF color. */
int
gx_psconcretize_CIEDEF(const gs_client_color * pc, const gs_color_space * pcs,
                     frac * pconc, const gs_imager_state * pis)
{
    const gs_cie_def *pcie = pcs->params.def;
    int i;
    fixed hij[3];
    frac abc[3];
    cie_cached_vector3 vec3;
    int code;

    if_debug3('c', "[c]concretize DEF [%g %g %g]\n",
              pc->paint.values[0], pc->paint.values[1],
              pc->paint.values[2]);
    code = gx_cie_check_rendering_inline(pcs, pconc, pis);
    if (code < 0)
        return code;
    if (code == 1)
        return 0;

    /*
     * Apply DecodeDEF, including restriction to RangeHIJ and scaling to
     * the Table dimensions.
     */
    for (i = 0; i < 3; ++i) {
        int tdim = pcie->Table.dims[i] - 1;
        double factor = pcie->caches_def.DecodeDEF[i].floats.params.factor;
        double v0 = pc->paint.values[i];
        const gs_range *const rangeDEF = &pcie->RangeDEF.ranges[i];
        double value =
            (v0 < rangeDEF->rmin ? 0.0 : factor *
            (v0 > rangeDEF->rmax ? rangeDEF->rmax - rangeDEF->rmin :
             v0 - rangeDEF->rmin ));
        int vi = (int)value;
        double vf = value - vi;
        double v = pcie->caches_def.DecodeDEF[i].floats.values[vi];

        if (vf != 0 && vi < factor)
            v += vf *
                (pcie->caches_def.DecodeDEF[i].floats.values[vi + 1] - v);
        v = (v < 0 ? 0 : v > tdim ? tdim : v);
        hij[i] = float2fixed(v);
    }
    /* Apply Table. */
    gx_color_interpolate_linear(hij, &pcie->Table, abc);
    /* Scale the abc[] frac values to RangeABC cie_cached result */
    vec3.u = SCALE_TO_RANGE(pcie->RangeABC.ranges[0], abc[0]);
    vec3.v = SCALE_TO_RANGE(pcie->RangeABC.ranges[1], abc[1]);
    vec3.w = SCALE_TO_RANGE(pcie->RangeABC.ranges[2], abc[2]);
    /* Apply DecodeABC and MatrixABC. */
    if (!pis->cie_joint_caches->skipDecodeABC)
        cie_lookup_map3(&vec3 /* ABC => LMN */, &pcie->caches.DecodeABC,
                        "Decode/MatrixABC");
    GX_CIE_REMAP_FINISH(vec3, pconc, pis, pcs);
    return 0;
}
Esempio n. 12
0
/* (Un)mark the strings in a chunk. */
void
gc_strings_set_marks(chunk_t * cp, bool mark)
{
    if (cp->smark != 0) {
	if_debug3('6', "[6]clearing string marks 0x%lx[%u] to %d\n",
		  (ulong) cp->smark, cp->smark_size, (int)mark);
	memset(cp->smark, 0, cp->smark_size);
	if (mark)
	    gc_mark_string(cp->sbase, cp->climit - cp->sbase, true, cp);
    }
}
Esempio n. 13
0
static void
cie_lookup_map3(cie_cached_vector3 * pvec,
                const gx_cie_vector_cache3_t * pc, const char *cname)
{
    if_debug5('c', "[c]lookup %s 0x%lx [%g %g %g]\n",
              (const char *)cname, (ulong) pc,
              cie_cached2float(pvec->u), cie_cached2float(pvec->v),
              cie_cached2float(pvec->w));
    cie_lookup_mult3(pvec, pc);
    if_debug3('c', "        =[%g %g %g]\n",
              cie_cached2float(pvec->u), cie_cached2float(pvec->v),
              cie_cached2float(pvec->w));
}
Esempio n. 14
0
/* error callback for jbig2 decoder */
static int
s_jbig2decode_error(void *error_callback_data, const char *msg, Jbig2Severity severity,
               int32_t seg_idx)
{
    stream_jbig2decode_state *const state =
        (stream_jbig2decode_state *) error_callback_data;
    const char *type;
    char segment[22];
    int code = 0;

    switch (severity) {
        case JBIG2_SEVERITY_DEBUG:
            type = "DEBUG"; break;;
        case JBIG2_SEVERITY_INFO:
            type = "info"; break;;
        case JBIG2_SEVERITY_WARNING:
            type = "WARNING"; break;;
        case JBIG2_SEVERITY_FATAL:
            type = "FATAL ERROR decoding image:";
            /* pass the fatal error upstream if possible */
            code = gs_error_ioerror;
            if (state != NULL) state->error = code;
            break;;
        default: type = "unknown message:"; break;;
    }
    if (seg_idx == -1) segment[0] = '\0';
    else gs_sprintf(segment, "(segment 0x%02x)", seg_idx);

    if (state)
    {
        if (severity == JBIG2_SEVERITY_FATAL) {
            dmlprintf3(state->memory, "jbig2dec %s %s %s\n", type, msg, segment);
        } else {
            if_debug3m('w', state->memory, "[w] jbig2dec %s %s %s\n", type, msg, segment);
        }
    }
    else
    {
/*
        FIXME error_callback_data should be updated so that jbig2_ctx_new is not called
        with a NULL argument (see jbig2.h) and we never reach here with a NULL state
*/
        if (severity == JBIG2_SEVERITY_FATAL) {
            dlprintf3("jbig2dec %s %s %s\n", type, msg, segment);
        } else {
            if_debug3('w', "[w] jbig2dec %s %s %s\n", type, msg, segment);
        }
    }

    return code;
}
Esempio n. 15
0
/* Free the row buffers when cleaning up. */
static void
free_row_buffers(gs_image_enum *penum, int num_planes, client_name_t cname)
{
    int i;

    for (i = num_planes - 1; i >= 0; --i) {
	if_debug3('b', "[b]free plane %d row (0x%lx,%u)\n",
		  i, (ulong)penum->planes[i].row.data,
		  penum->planes[i].row.size);
	gs_free_string(gs_image_row_memory(penum), penum->planes[i].row.data,
		       penum->planes[i].row.size, cname);
	penum->planes[i].row.data = 0;
	penum->planes[i].row.size = 0;
    }
}
Esempio n. 16
0
gx_color_index eprn_map_rgb_color_for_RGB_max(gx_device *device,
  const gx_color_value cv[])
{
  gx_color_value red = cv[0], green = cv[1], blue = cv[2];
  gx_color_index value;

#ifdef EPRN_TRACE
  if_debug3(EPRN_TRACE_CHAR,
    "! eprn_map_rgb_color_for_RGB_max() called for RGB = (%hu, %hu, %hu),\n",
    red, green, blue);
#endif

  value  = dominant_8bits(red)   <<  8;
  value |= dominant_8bits(green) << 16;
  value |= dominant_8bits(blue)  << 24;

#ifdef EPRN_TRACE
  if_debug1(EPRN_TRACE_CHAR, "  returning 0x%08lX.\n", (unsigned long)value);
#endif
  return value;
}
Esempio n. 17
0
/* needs to be efficient. */
int
gx_remap_CIEABC(const gs_client_color * pc, const gs_color_space * pcs_in,
        gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
                gs_color_select_t select)
{
    gs_color_space *pcs_icc;
    gs_client_color scale_pc;
    bool islab;
    int i,code;
    gs_color_space *pcs = (gs_color_space *) pcs_in;


    if_debug3('c', "[c]remap CIEABC [%g %g %g]\n",
              pc->paint.values[0], pc->paint.values[1],
              pc->paint.values[2]);
    /* If we are comming in here then we have not completed
       the conversion of the ABC space to an ICC type.  We
       will finish that process now. */
    if (pcs->icc_equivalent == NULL) {
        gx_cieabc_to_icc(&pcs_icc, pcs, &islab, pis->memory->stable_memory);
    } else {
        pcs_icc = pcs->icc_equivalent;
        }
    /* Rescale the input based upon the input range since profile is
       created to remap this range from 0 to 1 */
    if (check_range(&(pcs->params.abc->RangeABC.ranges[0]), 3)) {
        return((pcs_icc->type->remap_color)(pc,pcs_icc,pdc,pis,dev,select));
    }
    /* Do the rescale from 0 to 1 */
    rescale_input_color(&(pcs->params.abc->RangeABC.ranges[0]), 3, pc, &scale_pc);
    /* Now the icc remap */
    code = (pcs_icc->type->remap_color)(&scale_pc,pcs_icc,pdc,pis,dev,select);
    /* Save unscaled data for high level device (e.g. pdfwrite) */
    for (i = 0; i < 3; i++)
        pdc->ccolor.paint.values[i] = pc->paint.values[i];
    pdc->ccolor_valid = true;
    /* Now the icc remap */
    return(code);
}
Esempio n. 18
0
/* Set up and start the render threads */
static int
clist_setup_render_threads(gx_device *dev, int y)
{
    gx_device_printer *pdev = (gx_device_printer *)dev;
    gx_device_clist *cldev = (gx_device_clist *)dev;
    gx_device_clist_common *cdev = (gx_device_clist_common *)cldev;
    gx_device_clist_reader *crdev = &cldev->reader;
    gs_memory_t *mem = cdev->bandlist_memory;
    gs_memory_t *chunk_base_mem = mem->thread_safe_memory;
    gs_memory_status_t mem_status;
    gx_device *protodev;
    gs_c_param_list paramlist;
    int i, code, band;
    int band_count = cdev->nbands;
    char fmode[4];
    gs_devn_params *pclist_devn_params;
    crdev->num_render_threads = pdev->num_render_threads_requested;

    if(gs_debug[':'] != 0)
        dprintf1("%% %d rendering threads requested.\n", pdev->num_render_threads_requested);

    if (crdev->num_render_threads > band_count)
        crdev->num_render_threads = band_count; /* don't bother starting more threads than bands */

    /* Allocate and initialize an array of thread control structures */
    crdev->render_threads = (clist_render_thread_control_t *)
              gs_alloc_byte_array(mem, crdev->num_render_threads,
              sizeof(clist_render_thread_control_t), "clist_setup_render_threads" );
    /* fallback to non-threaded if allocation fails */
    if (crdev->render_threads == NULL) {
        emprintf(mem, " VMerror prevented threads from starting.\n");
        return_error(gs_error_VMerror);
    }

    memset(crdev->render_threads, 0, crdev->num_render_threads *
            sizeof(clist_render_thread_control_t));
    crdev->main_thread_data = cdev->data;               /* save data area */
    /* Based on the line number requested, decide the order of band rendering */
    /* Almost all devices go in increasing line order (except the bmp* devices ) */
    crdev->thread_lookahead_direction = (y < (cdev->height - 1)) ? 1 : -1;
    band = y / crdev->page_info.band_params.BandHeight;

    /* Close the files so we can open them in multiple threads */
    if ((code = cdev->page_info.io_procs->fclose(cdev->page_cfile, cdev->page_cfname, false)) < 0 ||
        (code = cdev->page_info.io_procs->fclose(cdev->page_bfile, cdev->page_bfname, false)) < 0) {
        gs_free_object(mem, crdev->render_threads, "clist_setup_render_threads");
        crdev->render_threads = NULL;
        emprintf(mem, "Closing clist files prevented threads from starting.\n");
        return_error(gs_error_unknownerror); /* shouldn't happen */
    }
    cdev->page_cfile = cdev->page_bfile = NULL;
    strcpy(fmode, "r");                 /* read access for threads */
    strncat(fmode, gp_fmode_binary_suffix, 1);
    /* Find the prototype for this device (needed so we can copy from it) */
    for (i=0; (protodev = (gx_device *)gs_getdevice(i)) != NULL; i++)
        if (strcmp(protodev->dname, dev->dname) == 0)
            break;
    if (protodev == NULL) {
        emprintf(mem,
                 "Could not find prototype device. Rendering threads not started.\n");
        return gs_error_rangecheck;
    }

    gs_c_param_list_write(&paramlist, mem);
    if ((code = gs_getdeviceparams(dev, (gs_param_list *)&paramlist)) < 0) {
        emprintf1(mem,
                  "Error getting device params, code=%d. Rendering threads not started.\n",
                  code);
        return code;
    }

    /* If the 'mem' is not thread safe, we need to wrap it in a locking memory */
    gs_memory_status(chunk_base_mem, &mem_status);
    if (mem_status.is_thread_safe == false) {
            return_error(gs_error_VMerror);
    }

    /* Loop creating the devices and semaphores for each thread, then start them */
    for (i=0; (i < crdev->num_render_threads) && (band >= 0) && (band < band_count);
            i++, band += crdev->thread_lookahead_direction) {
        gx_device *ndev;
        gx_device_clist *ncldev;
        gx_device_clist_common *ncdev;
        clist_render_thread_control_t *thread = &(crdev->render_threads[i]);

        /* Every thread will have a 'chunk allocator' to reduce the interaction
         * with the 'base' allocator which has 'mutex' (locking) protection.
         * This improves performance of the threads.
         */
        if ((code = gs_memory_chunk_wrap(&(thread->memory), chunk_base_mem )) < 0) {
            emprintf1(mem, "chunk_wrap returned error code: %d\n", code);
            break;
        }

        thread->band = -1;              /* a value that won't match any valid band */
        if ((code = gs_copydevice((gx_device **) &ndev, protodev, thread->memory)) < 0) {
            code = 0;           /* even though we failed, no cleanup needed */
            break;
        }
        ncldev = (gx_device_clist *)ndev;
        ncdev = (gx_device_clist_common *)ndev;
        gx_device_fill_in_procs(ndev);
        ((gx_device_printer *)ncdev)->buffer_memory = ncdev->memory =
                ncdev->bandlist_memory = thread->memory;
        gs_c_param_list_read(&paramlist);
        ndev->PageCount = dev->PageCount;       /* copy to prevent mismatch error */
#if CMM_THREAD_SAFE
        ndev->icc_struct = dev->icc_struct;  /* Set before put params */
        rc_increment(ndev->icc_struct);
#endif
        if ((code = gs_putdeviceparams(ndev, (gs_param_list *)&paramlist)) < 0)
            break;
        /* In the case of a separation device, we need to make sure we get the
           devn params copied over */
        pclist_devn_params = dev_proc(dev, ret_devn_params)(dev);
        if (pclist_devn_params != NULL) {
            code = devn_copy_params(dev, (gx_device*) ncdev);
            if (code < 0) return_error(gs_error_VMerror);
        }
        ncdev->page_uses_transparency = cdev->page_uses_transparency;
        if_debug3('{',"[{]MT clist device = 0x%x profile = 0x%x handle = 0x%x\n", 
                  ncdev,
                  ncdev->icc_struct->device_profile[0],
                  ncdev->icc_struct->device_profile[0]->profile_handle);
        /* gdev_prn_allocate_memory sets the clist for writing, creating new files.
         * We need  to unlink those files and open the main thread's files, then
         * reset the clist state for reading/rendering
         */
        if ((code = gdev_prn_allocate_memory(ndev, NULL, ndev->width, ndev->height)) < 0)
            break;
        /* Needed for case when the target has cielab profile and pdf14 device
           has a RGB profile stored in the profile list of the clist */
        ncdev->trans_dev_icc_hash = cdev->trans_dev_icc_hash;
        thread->cdev = ndev;
        /* close and unlink the temp files just created */
        cdev->page_info.io_procs->fclose(ncdev->page_cfile, ncdev->page_cfname, true);
        cdev->page_info.io_procs->fclose(ncdev->page_bfile, ncdev->page_bfname, true);
        /* open the main thread's files for this thread */
        if ((code=cdev->page_info.io_procs->fopen(cdev->page_cfname, fmode, &ncdev->page_cfile,
                            thread->memory, thread->memory, true)) < 0 ||
             (code=cdev->page_info.io_procs->fopen(cdev->page_bfname, fmode, &ncdev->page_bfile,
                            thread->memory, thread->memory, false)) < 0)
            break;
        clist_render_init(ncldev);      /* Initialize clist device for reading */
        ncdev->page_bfile_end_pos = cdev->page_bfile_end_pos;
        /* Use the same link cache in each thread and the same profile table.
           The threads are maintained until clist_finish_page.  At which
           point, the threads are torn down and the master clist reader device
           is destroyed along with the icc_table and the icc_cache_cl */
#if CMM_THREAD_SAFE
        ncdev->icc_cache_cl = cdev->icc_cache_cl;
#else
        ncdev->icc_cache_cl = gsicc_cache_new(crdev->memory);
#endif
        ncdev->icc_table = cdev->icc_table;
        /* create the buf device for this thread, and allocate the semaphores */
        if ((code = gdev_create_buf_device(cdev->buf_procs.create_buf_device,
                                &(thread->bdev), cdev->target,
                                band*crdev->page_band_height, NULL,
                                thread->memory, clist_get_band_complexity(dev,y)) < 0))
            break;
        if ((thread->sema_this = gx_semaphore_alloc(thread->memory)) == NULL ||
            (thread->sema_group = gx_semaphore_alloc(thread->memory)) == NULL) {
            code = gs_error_VMerror;
            break;
        }
        /* Start thread 'i' to do band */
        if ((code = clist_start_render_thread(dev, i, band)) < 0)
            break;
    }
    gs_c_param_list_release(&paramlist);
    /* If the code < 0, the last thread creation failed -- clean it up */
    if (code < 0) {
        /* the following relies on 'free' ignoring NULL pointers */
        gx_semaphore_free(crdev->render_threads[i].sema_group);
        gx_semaphore_free(crdev->render_threads[i].sema_this);
        if (crdev->render_threads[i].bdev != NULL)
            cdev->buf_procs.destroy_buf_device(crdev->render_threads[i].bdev);
        if (crdev->render_threads[i].cdev != NULL) {
            gx_device_clist_common *thread_cdev = (gx_device_clist_common *)crdev->render_threads[i].cdev;

            /* Close the file handles, but don't delete (unlink) the files */
            thread_cdev->page_info.io_procs->fclose(thread_cdev->page_bfile, thread_cdev->page_bfname, false);
            thread_cdev->page_info.io_procs->fclose(thread_cdev->page_cfile, thread_cdev->page_cfname, false);
            thread_cdev->do_not_open_or_close_bandfiles = true; /* we already closed the files */

            gdev_prn_free_memory((gx_device *)thread_cdev);
            gs_free_object(crdev->render_threads[i].memory, thread_cdev,
            "clist_setup_render_threads");
        }
        if (crdev->render_threads[i].memory != NULL)
            gs_memory_chunk_release(crdev->render_threads[i].memory);
    }
    /* If we weren't able to create at least one thread, punt   */
    /* Although a single thread isn't any more efficient, the   */
    /* machinery still works, so that's OK.                     */
    if (i == 0) {
        if (crdev->render_threads[0].memory != NULL) {
            gs_memory_chunk_release(crdev->render_threads[0].memory);
            /* free up the locking wrapper if we allocated one */
            if (chunk_base_mem != mem) {
                gs_memory_locked_release((gs_memory_locked_t *)chunk_base_mem);
                gs_free_object(mem, chunk_base_mem, "clist_setup_render_threads(locked allocator)");
            }
        }
        gs_free_object(mem, crdev->render_threads, "clist_setup_render_threads");
        crdev->render_threads = NULL;
        /* restore the file pointers */
        if (cdev->page_cfile == NULL) {
            char fmode[4];

            strcpy(fmode, "a+");        /* file already exists and we want to re-use it */
            strncat(fmode, gp_fmode_binary_suffix, 1);
            cdev->page_info.io_procs->fopen(cdev->page_cfname, fmode, &cdev->page_cfile,
                                mem, cdev->bandlist_memory, true);
            cdev->page_info.io_procs->fseek(cdev->page_cfile, 0, SEEK_SET, cdev->page_cfname);
            cdev->page_info.io_procs->fopen(cdev->page_bfname, fmode, &cdev->page_bfile,
                                mem, cdev->bandlist_memory, false);
            cdev->page_info.io_procs->fseek(cdev->page_bfile, 0, SEEK_SET, cdev->page_bfname);
        }
        emprintf1(mem, "Rendering threads not started, code=%d.\n", code);
        return_error(code);
    }
    crdev->num_render_threads = i;
    crdev->curr_render_thread = 0;

    if(gs_debug[':'] != 0)
        dprintf1("%% Using %d rendering threads\n", i);

    return 0;
}
Esempio n. 19
0
/* untraced space, so relocate all refs, not just marked ones. */
void
igc_reloc_refs(ref_packed * from, ref_packed * to, gc_state_t * gcst)
{
    int min_trace = gcst->min_collect;
    ref_packed *rp = from;
    bool do_all = gcst->relocating_untraced; 

    vm_spaces spaces = gcst->spaces;
    const gs_memory_t *cmem = space_system->stable_memory;

    while (rp < to) {
	ref *pref;
#ifdef DEBUG
	const void *before = 0;
	const void *after = 0;
# define DO_RELOC(var, stat)\
    BEGIN before = (var); stat; after = (var); END
# define SET_RELOC(var, expr)\
    BEGIN before = (var); after = (var) = (expr); END
#else
# define DO_RELOC(var, stat) stat
# define SET_RELOC(var, expr) var = expr
#endif

	if (r_is_packed(rp)) {
	    rp++;
	    continue;
	}
	/* The following assignment is logically unnecessary; */
	/* we do it only for convenience in debugging. */
	pref = (ref *) rp;
	if_debug3('8', "  [8]relocating %s %d ref at 0x%lx\n",
		  (r_has_attr(pref, l_mark) ? "marked" : "unmarked"),
		  r_btype(pref), (ulong) pref);
	if ((r_has_attr(pref, l_mark) || do_all) &&
	    r_space(pref) >= min_trace
	    ) {
	    switch (r_type(pref)) {
		    /* Struct cases */
		case t_file:
		    DO_RELOC(pref->value.pfile, RELOC_VAR(pref->value.pfile));
		    break;
		case t_device:
		    DO_RELOC(pref->value.pdevice,
			     RELOC_VAR(pref->value.pdevice));
		    break;
		case t_fontID:
		case t_struct:
		case t_astruct:
		    DO_RELOC(pref->value.pstruct,
			     RELOC_VAR(pref->value.pstruct));
		    break;
		    /* Non-trivial non-struct cases */
		case t_dictionary:
		    rputc('d');
		    SET_RELOC(pref->value.pdict,
			      (dict *)igc_reloc_ref_ptr((ref_packed *)pref->value.pdict, gcst));
		    break;
		case t_array:
		    {
			uint size = r_size(pref);

			if (size != 0) {	/* value.refs might be NULL */

			    /*
			     * If the array is large, we allocated it in its
			     * own object (at least originally -- this might
			     * be a pointer to a subarray.)  In this case,
			     * we know it is the only object in its
			     * containing st_refs object, so we know that
			     * the mark containing the relocation appears
			     * just after it.
			     */
			    if (size < max_size_st_refs / sizeof(ref)) {
				rputc('a');
				SET_RELOC(pref->value.refs,
				    (ref *) igc_reloc_ref_ptr(
				     (ref_packed *) pref->value.refs, gcst));
			    } else {
				rputc('A');
				/*
				 * See the t_shortarray case below for why we
				 * decrement size.
				 */
				--size;
				SET_RELOC(pref->value.refs,
				    (ref *) igc_reloc_ref_ptr(
				   (ref_packed *) (pref->value.refs + size),
							       gcst) - size);
			    }
			}
		    }
		    break;
		case t_mixedarray:
		    if (r_size(pref) != 0) {	/* value.refs might be NULL */
			rputc('m');
			SET_RELOC(pref->value.packed,
				  igc_reloc_ref_ptr(pref->value.packed, gcst));
		    }
		    break;
		case t_shortarray:
		    {
			uint size = r_size(pref);

			/*
			 * Since we know that igc_reloc_ref_ptr works by
			 * scanning forward, and we know that all the
			 * elements of this array itself are marked, we can
			 * save some scanning time by relocating the pointer
			 * to the end of the array rather than the
			 * beginning.
			 */
			if (size != 0) {	/* value.refs might be NULL */
			    rputc('s');
			    /*
			     * igc_reloc_ref_ptr has to be able to determine
			     * whether the pointer points into a space that
			     * isn't being collected.  It does this by
			     * checking whether the referent of the pointer
			     * is marked.  For this reason, we have to pass
			     * a pointer to the last real element of the
			     * array, rather than just beyond it.
			     */
			    --size;
			    SET_RELOC(pref->value.packed,
				igc_reloc_ref_ptr(pref->value.packed + size,
						  gcst) - size);
			}
		    }
		    break;
		case t_name:
		    {
			void *psub = name_ref_sub_table(cmem, pref);
			void *rsub = RELOC_OBJ(psub); /* gcst implicit */

			SET_RELOC(pref->value.pname,
				  (name *)
				  ((char *)rsub + ((char *)pref->value.pname -
						   (char *)psub)));
		    } break;
		case t_string:
		    {
			gs_string str;

			str.data = pref->value.bytes;
			str.size = r_size(pref);

			DO_RELOC(str.data, RELOC_STRING_VAR(str));
			pref->value.bytes = str.data;
		    }
		    break;
		case t_oparray:
		    rputc('o');
		    SET_RELOC(pref->value.const_refs,
			(const ref *)igc_reloc_ref_ptr((const ref_packed *)pref->value.const_refs, gcst));
		    break;
		default:
		    goto no_reloc; /* don't print trace message */
	    }
	    if_debug2('8', "  [8]relocated 0x%lx => 0x%lx\n",
		      (ulong)before, (ulong)after);
	}
no_reloc:
	rp += packed_per_ref;
    }
}
Esempio n. 20
0
/*
 *	Width, encoded as a variable-length uint
 *	Height, encoded ditto
 *	ImageMatrix (if A = 1), per gs_matrix_store/fetch
 *	Decode (if D = 1): blocks of up to 4 components
 *	    aabbccdd, where each xx is decoded as:
 *		00 = default, 01 = swapped default,
 *		10 = (0,V), 11 = (U,V)
 *	    non-defaulted components (up to 8 floats)
 */
int
gx_pixel_image_sput(const gs_pixel_image_t *pim, stream *s,
		    const gs_color_space **ppcs, int extra)
{
    const gs_color_space *pcs = pim->ColorSpace;
    int bpc = pim->BitsPerComponent;
    int num_components = gs_color_space_num_components(pcs);
    int num_decode;
    uint control = extra << PI_BITS;
    float decode_default_1 = 1;
    int i;
    uint ignore;

    /* Construct the control word. */

    if (!gx_image_matrix_is_default((const gs_data_image_t *)pim))
	control |= PI_ImageMatrix;
    switch (pim->format) {
    case gs_image_format_chunky:
    case gs_image_format_component_planar:
	switch (bpc) {
	case 1: case 2: case 4: case 8: case 12: break;
	default: return_error(gs_error_rangecheck);
	}
	break;
    case gs_image_format_bit_planar:
	if (bpc < 1 || bpc > 8)
	    return_error(gs_error_rangecheck);
    }
    control |= (bpc - 1) << PI_BPC_SHIFT;
    control |= pim->format << PI_FORMAT_SHIFT;
    num_decode = num_components * 2;
    if (gs_color_space_get_index(pcs) == gs_color_space_index_Indexed)
	decode_default_1 = (float)pcs->params.indexed.hival;
    for (i = 0; i < num_decode; ++i)
	if (pim->Decode[i] != DECODE_DEFAULT(i, decode_default_1)) {
	    control |= PI_Decode;
	    break;
	}
    if (pim->Interpolate)
	control |= PI_Interpolate;
    if (pim->CombineWithColor)
	control |= PI_CombineWithColor;

    /* Write the encoding on the stream. */

    if_debug3('b', "[b]put control=0x%x, Width=%d, Height=%d\n",
	      control, pim->Width, pim->Height);
    sput_variable_uint(s, control);
    sput_variable_uint(s, (uint)pim->Width);
    sput_variable_uint(s, (uint)pim->Height);
    if (control & PI_ImageMatrix) {
	debug_b_print_matrix(pim);
	sput_matrix(s, &pim->ImageMatrix);
    }
    if (control & PI_Decode) {
	int i;
	uint dflags = 1;
	float decode[8];
	int di = 0;

	debug_b_print_decode(pim, num_decode);
	for (i = 0; i < num_decode; i += 2) {
	    float u = pim->Decode[i], v = pim->Decode[i + 1];
	    float dv = DECODE_DEFAULT(i + 1, decode_default_1);

	    if (dflags >= 0x100) {
		sputc(s, (byte)(dflags & 0xff));
		sputs(s, (const byte *)decode, di * sizeof(float), &ignore);
		dflags = 1;
		di = 0;
	    }
	    dflags <<= 2;
	    if (u == 0 && v == dv)
		DO_NOTHING;
	    else if (u == dv && v == 0)
		dflags += 1;
	    else {
		if (u != 0) {
		    dflags++;
		    decode[di++] = u;
		}
		dflags += 2;
		decode[di++] = v;
	    }
	}
	sputc(s, (byte)((dflags << (8 - num_decode)) & 0xff));
	sputs(s, (const byte *)decode, di * sizeof(float), &ignore);
    }
    *ppcs = pcs;
    return 0;
}
Esempio n. 21
0
static void
gs_heap_free_object(gs_memory_t * mem, void *ptr, client_name_t cname)
{
    gs_malloc_memory_t *mmem = (gs_malloc_memory_t *) mem;
    gs_malloc_block_t *bp;
    gs_memory_type_ptr_t pstype;
    struct_proc_finalize((*finalize));

    if_debug3('a', "[a-]gs_free(%s) 0x%lx(%u)\n",
	      client_name_string(cname), (ulong) ptr,
	      (ptr == 0 ? 0 : ((gs_malloc_block_t *) ptr)[-1].size));
    if (ptr == 0)
	return;
    pstype = ((gs_malloc_block_t *) ptr)[-1].type;
    finalize = pstype->finalize;
    if (finalize != 0) {
	if_debug3('u', "[u]finalizing %s 0x%lx (%s)\n",
		  struct_type_name_string(pstype),
		  (ulong) ptr, client_name_string(cname));
	(*finalize) (ptr);
    }
    if (mmem->monitor)
	gx_monitor_enter(mmem->monitor);	/* Exclusive access */
    bp = mmem->allocated; /* If 'finalize' releases a memory,
			     this function could be called recursively and
			     change mmem->allocated. */
    if (ptr == bp + 1) {
	mmem->allocated = bp->next;
	mmem->used -= bp->size + sizeof(gs_malloc_block_t);

	if (mmem->allocated)
	    mmem->allocated->prev = 0;
	if (mmem->monitor)
	    gx_monitor_leave(mmem->monitor);	/* Done with exclusive access */
	gs_alloc_fill(bp, gs_alloc_fill_free,
		      bp->size + sizeof(gs_malloc_block_t));
	free(bp);
    } else {
	gs_malloc_block_t *np;

	/*
	 * bp == 0 at this point is an error, but we'd rather have an
	 * error message than an invalid access.
	 */
	if (bp) {
	    for (; (np = bp->next) != 0; bp = np) {
		if (ptr == np + 1) {
		    bp->next = np->next;
		    if (np->next)
			np->next->prev = bp;
		    mmem->used -= np->size + sizeof(gs_malloc_block_t);
		    if (mmem->monitor)
			gx_monitor_leave(mmem->monitor);	/* Done with exclusive access */
		    gs_alloc_fill(np, gs_alloc_fill_free,
				  np->size + sizeof(gs_malloc_block_t));
		    free(np);
		    return;
		}
	    }
	}
	if (mmem->monitor)
	    gx_monitor_leave(mmem->monitor);	/* Done with exclusive access */
	lprintf2("%s: free 0x%lx not found!\n",
		 client_name_string(cname), (ulong) ptr);
	free((char *)((gs_malloc_block_t *) ptr - 1));
    }
}
Esempio n. 22
0
/* TODO: consider using source.count (and possibly also phase) */
static int
read_headless_jpeg_bitmap_data(byte ** pdata,
			       px_args_t * par, px_state_t * pxs)
{
    px_vendor_state_t *v_state = pxs->vendor_state;
    uint data_per_row = v_state->data_per_row;	/* jpeg doesn't pad */
    uint avail = par->source.available;

    uint pos_in_row = par->source.position % data_per_row;
    const byte *data = par->source.data;
    stream_DCT_state *ss = (&v_state->dct_stream_state);
    stream_cursor_read r;
    stream_cursor_write w;
    uint used;
    int code = -1;

    if_debug3('w', "jpeg begin pos=%d row=%d/%d\n",
	      pos_in_row, v_state->rowwritten, v_state->BlockHeight);

    /* consumed all of the data */
    if ((v_state->state == vu_body)
	&& v_state->rowwritten == v_state->BlockHeight) {
	if (par->source.available == 2) {
	    /* the data includes EOI; the filter may or may not consume it */
	    par->source.data += 2;
	    par->source.available -= 2;
	}
	gs_jpeg_destroy((&v_state->dct_stream_state));
	v_state->state = vu_blank;
	v_state->rowwritten = 0;
	code = pl_end_image(pxs->pgs, v_state->info, true);

	if (code < 0)
	    return code;
	return 0;
    }

    if (v_state->state == vu_tagged) {
	jpeg_decompress_data *jddp = &(v_state->jdd);

	v_state->rowwritten = 0;
	code = vu_begin_image(pxs);
	if (code < 0)
	    return code;

	/* use the graphics library support for DCT streams */
	ss->memory = pxs->memory;
	ss->templat = &s_DCTD_template;
	s_DCTD_template.set_defaults((stream_state *) ss);
	ss->report_error = vu_stream_error;
	ss->data.decompress = jddp;
	/* set now for allocation */
	jddp->memory = ss->jpeg_memory = pxs->memory;
	/* set this early for safe error exit */
	jddp->scanline_buffer = NULL;
	if (gs_jpeg_create_decompress(ss) < 0)
	    return_error(errorInsufficientMemory);
	(*s_DCTD_template.init) ((stream_state *) ss);
	jddp->templat = s_DCTD_template;
	fastforward_jpeg_stream_state(jddp, ss, pxs);
	v_state->state = vu_body;
    }

    r.ptr = data - 1;
    r.limit = r.ptr + avail;
    if (pos_in_row < data_per_row) {
	/* Read more of the current row. */
	byte *data = *pdata;

	w.ptr = data + pos_in_row - 1;
	w.limit = data + data_per_row - 1;
	code =
	    (*s_DCTD_template.process) ((stream_state *) ss, &r, &w, false);
	/* code = num scanlines processed (0=need more data, -ve=error) */
	if_debug1('w', "s_DCTD_template.process returns %d\n", code);
	used = w.ptr + 1 - data - pos_in_row;
	if ((code == EOFC) && (used > 0))
	    code = 1;
	if_debug2('w', "data generated: %d/%d\n", used, data_per_row);
	/* pos_in_row += used; */
	par->source.position += used;
    }
    used = r.ptr + 1 - data;
    par->source.data = r.ptr + 1;
    par->source.available = avail - used;
    if_debug2('w', "scanlines %d used %d\n", code, used);
    if (code == 0)
	return pxNeedData;
    if (code == EOFC)		/* used = 0 is possible, and earlier than end */
	return 0;
    if (code > 0) {
	v_state->rowwritten++;
	if_debug1('w', "row written:%d\n", v_state->rowwritten);
	jpeg_custom_color_fixup(v_state->row,
				v_state->color_space, v_state->data_per_row);
	return 1;
    }
    return code;
}
Esempio n. 23
0
/*
 * Read generic pixel image parameters.
 */
int
gx_pixel_image_sget(gs_pixel_image_t *pim, stream *s,
		    gs_color_space *pcs)
{
    uint control;
    float decode_default_1 = 1;
    int num_components, num_decode;
    int i;
    int code;
    uint ignore;

    if ((code = sget_variable_uint(s, &control)) < 0 ||
	(code = sget_variable_uint(s, (uint *)&pim->Width)) < 0 ||
	(code = sget_variable_uint(s, (uint *)&pim->Height)) < 0
	)
	return code;
    if_debug3('b', "[b]get control=0x%x, Width=%d, Height=%d\n",
	      control, pim->Width, pim->Height);
    if (control & PI_ImageMatrix) {
	if ((code = sget_matrix(s, &pim->ImageMatrix)) < 0)
	    return code;
	debug_b_print_matrix(pim);
    } else
	gx_image_matrix_set_default((gs_data_image_t *)pim);
    pim->BitsPerComponent = ((control >> PI_BPC_SHIFT) & PI_BPC_MASK) + 1;
    pim->format = (control >> PI_FORMAT_SHIFT) & PI_FORMAT_MASK;
    pim->ColorSpace = pcs;
    num_components = gs_color_space_num_components(pcs);
    num_decode = num_components * 2;
    if (gs_color_space_get_index(pcs) == gs_color_space_index_Indexed)
	decode_default_1 = (float)pcs->params.indexed.hival;
    if (control & PI_Decode) {
	uint dflags = 0x10000;
	float *dp = pim->Decode;

	for (i = 0; i < num_decode; i += 2, dp += 2, dflags <<= 2) {
	    if (dflags >= 0x10000) {
		dflags = sgetc(s) + 0x100;
		if (dflags < 0x100)
		    return_error(gs_error_ioerror);
	    }
	    switch (dflags & 0xc0) {
	    case 0x00:
		dp[0] = 0, dp[1] = DECODE_DEFAULT(i + 1, decode_default_1);
		break;
	    case 0x40:
		dp[0] = DECODE_DEFAULT(i + 1, decode_default_1), dp[1] = 0;
		break;
	    case 0x80:
		dp[0] = 0;
		if (sgets(s, (byte *)(dp + 1), sizeof(float), &ignore) < 0)
		    return_error(gs_error_ioerror);
		break;
	    case 0xc0:
		if (sgets(s, (byte *)dp, sizeof(float) * 2, &ignore) < 0)
		    return_error(gs_error_ioerror);
		break;
	    }
	}
	debug_b_print_decode(pim, num_decode);
    } else {
        for (i = 0; i < num_decode; ++i)
	    pim->Decode[i] = DECODE_DEFAULT(i, decode_default_1);
    }
    pim->Interpolate = (control & PI_Interpolate) != 0;
    pim->CombineWithColor = (control & PI_CombineWithColor) != 0;
    return control >> PI_BITS;
}
Esempio n. 24
0
irender_proc_t
gs_image_class_1_simple(gx_image_enum * penum)
{
    irender_proc_t rproc;
    fixed ox = dda_current(penum->dda.pixel0.x);
    fixed oy = dda_current(penum->dda.pixel0.y);

    if (penum->use_rop || penum->spp != 1 || penum->bps != 1)
        return 0;
    switch (penum->posture) {
        case image_portrait:
            {			/* Use fast portrait algorithm. */
                long dev_width =
                    fixed2long_pixround(ox + penum->x_extent.x) -
                    fixed2long_pixround(ox);

                if (dev_width != penum->rect.w) {
                    /*
                     * Add an extra align_bitmap_mod of padding so that
                     * we can align scaled rows with the device.
                     */
                    long line_size =
                        bitmap_raster(any_abs(dev_width)) + align_bitmap_mod;

                    if (penum->adjust != 0 || line_size > max_uint)
                        return 0;
                    /* Must buffer a scan line. */
                    penum->line_width = any_abs(dev_width);
                    penum->line_size = (uint) line_size;
                    penum->line = gs_alloc_bytes(penum->memory,
                                            penum->line_size, "image line");
                    if (penum->line == 0) {
                        gx_default_end_image(penum->dev,
                                             (gx_image_enum_common_t *)penum,
                                             false);
                        return 0;
                    }
                }
                if_debug2('b', "[b]render=simple, unpack=copy; rect.w=%d, dev_width=%ld\n",
                          penum->rect.w, dev_width);
                rproc = image_render_simple;
                break;
            }
        case image_landscape:
            {			/* Use fast landscape algorithm. */
                long dev_width =
                    fixed2long_pixround(oy + penum->x_extent.y) -
                    fixed2long_pixround(oy);
                long line_size =
                    (dev_width = any_abs(dev_width),
                     bitmap_raster(dev_width) * 8 +
                     ROUND_UP(dev_width, 8) * align_bitmap_mod);

                if ((dev_width != penum->rect.w && penum->adjust != 0) ||
                    line_size > max_uint
                    )
                    return 0;
                /* Must buffer a group of 8N scan lines. */
                penum->line_width = dev_width;
                penum->line_size = (uint) line_size;
                penum->line = gs_alloc_bytes(penum->memory,
                                             penum->line_size, "image line");
                if (penum->line == 0) {
                    gx_default_end_image(penum->dev,
                                         (gx_image_enum_common_t *) penum,
                                         false);
                    return 0;
                }
                penum->xi_next = penum->line_xy = fixed2int_var_rounded(ox);
                if_debug3('b', "[b]render=landscape, unpack=copy; rect.w=%d, dev_width=%ld, line_size=%ld\n",
                          penum->rect.w, dev_width, line_size);
                rproc = image_render_landscape;
                /* Precompute values needed for rasterizing. */
                penum->dxy =
                    float2fixed(penum->matrix.xy +
                                fixed2float(fixed_epsilon) / 2);
                break;
            }
        default:
            return 0;
    }
    /* Precompute values needed for rasterizing. */
    penum->dxx =
        float2fixed(penum->matrix.xx + fixed2float(fixed_epsilon) / 2);
    /*
     * We don't want to spread the samples, but we have to reset unpack_bps
     * to prevent the buffer pointer from being incremented by 8 bytes per
     * input byte.
     */
    penum->unpack = sample_unpack_copy;
    penum->unpack_bps = 8;
    if (penum->use_mask_color) {
        /*
         * Set the masked color as 'no_color' to make it transparent
         *  according to the mask color range and the decoding.
         */
        penum->masked = true;
        if (penum->mask_color.values[0] == 1) {
            /* if v0 == 1, 1 is transparent since v1 must be == 1 to be a valid range */
            set_nonclient_dev_color(penum->map[0].inverted ? penum->icolor0 : penum->icolor1,
                        gx_no_color_index);
        } else if (penum->mask_color.values[1] == 0) {
            /* if v1 == 0, 0 is transparent since v0 must be == 0 to be a valid range */
            set_nonclient_dev_color(penum->map[0].inverted ? penum->icolor1 : penum->icolor0,
                        gx_no_color_index);
        } else {
            /*
             * The only other possible in-range value is v0 = 0, v1 = 1.
             * The image is completely transparent!
             */
            rproc = image_render_skip;
        }
        penum->map[0].decoding = sd_none;
    }
    return rproc;
}
Esempio n. 25
0
/* TODO: consider using source.position and source.count (and possibly also phase) */
static int
read_mode10_bitmap_data(byte ** pdata, px_args_t * par, px_state_t * pxs,
			bool mode9031)
{
    px_vendor_state_t *v_state = pxs->vendor_state;
    mode10_state_t *mode10_state = &v_state->mode10_state;
    uint avail = min(par->source.available,
		     (v_state->tag.bytes_expected -
		      v_state->tag.bytes_so_far));
    const byte *pin = par->source.data;
    byte *pout;
    bool end_of_row = false;
    uint32_t pixel;
    int i;

    update_pout(pout);

    if ((v_state->state == vu_body)
	&& v_state->rowwritten == v_state->BlockHeight) {
	int code = pl_end_image(pxs->pgs, v_state->info, true);

	if (code < 0)
	    return code;

	v_state->state = vu_blank;
	v_state->rowwritten = 0;
	return 0;
    }

    /* initialize at begin of image */
    if (v_state->state == vu_tagged) {
	int code = vu_begin_image(pxs);

	if (code < 0)
	    return code;

	mode10_state->state = next_is_cmd;
	mode10_state->cursor = 0;
	v_state->rowwritten = 0;
	v_state->state = vu_body;
    }

    /* one byte at a time until end of input or end of row */
    while ((avail || mode10_state->state == process_rle)	/* process_rle does not consume */
	   &&(!end_of_row)) {
	switch (mode10_state->state) {
	    case next_is_cmd:{
		    mode10_state->cmd = *pin++;
		    --avail;
		    if_debug4('w',
			      "command:%02X row written:%d cursor:%d cached=%08X\n",
			      mode10_state->cmd,
			      v_state->rowwritten,
			      mode10_state->cursor,
			      mode10_state->cached_pixel);
		    mode10_state->offset = (mode10_state->cmd >> 3) & 0x03;
		    mode10_state->count = mode10_state->cmd & 0x07;
		    mode10_state->cursor += mode10_state->offset;	/* may be partial */
		    if ((mode10_state->offset < 3)
			&& (mode10_state->count < 7)
			&& (!srcNEW(mode10_state->cmd))
			) {
			/* completed command */
			if (mode10_state->cmd & eRLE) {
			    mode10_state->state = process_rle;
			} else {
			    /* literal, non-new */
			    update_pout(pout);
			    pixel =
				get_pixel(pout, &mode10_state->cached_pixel,
					  mode10_state->cmd,
					  v_state->color_space);

			    copy_pixel(pout, pixel);
			    mode10_state->cursor += 1;
			    if (mode10_state->count > 0) {
				mode10_state->count--;
				mode10_state->state = next_is_pixel;
			    } else
				mode10_state->state = next_is_cmd;
			}
		    } else if (mode10_state->offset == 3)
			mode10_state->state = partial_offset;
		    else if (srcNEW(mode10_state->cmd)) {
			if ((mode10_state->cmd & eRLE)
			    && (mode10_state->cursor >= v_state->SourceWidth)) {
			    /* special case */
			    if_debug0('w', "special\n");
			    mode10_state->cursor = 0;
			    end_of_row = 1;
			    mode10_state->state = next_is_cmd;
			} else
			    mode10_state->state = next_is_pixel;
		    } else if (mode10_state->count == 7)
			mode10_state->state = partial_count;
		    else
			mode10_state->state = next_is_cmd;	/* does not happen */
		    break;
		}

	    case partial_offset:{
		    uint offset = *pin++;

		    avail--;
		    mode10_state->offset += offset;
		    mode10_state->cursor += offset;
		    if (offset == 0xff)
			mode10_state->state = partial_offset;
		    else {
			/* completed offset */
			if_debug5('w',
				  "%02X row=%d offset=%d cursor=%d/%d\n",
				  mode10_state->cmd,
				  v_state->rowwritten,
				  mode10_state->offset, mode10_state->cursor,
				  v_state->SourceWidth);
			if (srcNEW(mode10_state->cmd)) {
			    if ((mode10_state->cmd & eRLE)
				&& (mode10_state->cursor >=
				    v_state->SourceWidth)) {
				/* special case */
				if_debug0('w', "special\n");
				mode10_state->cursor = 0;
				end_of_row = 1;
				mode10_state->state = next_is_cmd;
			    } else
				mode10_state->state = next_is_pixel;
			} else if (mode10_state->count == 7) {
			    mode10_state->state = partial_count;
			} else {
			    /* not new pixels, counts under 7, so we need to process there */
			    if (mode10_state->cmd & eRLE) {
				mode10_state->state = process_rle;
			    } else {
				/* literal non-new */
				update_pout(pout);
				pixel = get_pixel(pout,
						  &mode10_state->cached_pixel,
						  mode10_state->cmd,
						  v_state->color_space);
				copy_pixel(pout, pixel);
				mode10_state->cursor += 1;
				if (mode10_state->count > 0) {
				    mode10_state->count--;
				    mode10_state->state = next_is_pixel;
				} else
				    mode10_state->state = next_is_cmd;
			    }
			}
		    }
		    break;
		}

	    case partial_count:{
		    uint count = *pin++;

		    avail--;
		    mode10_state->count += count;
		    if (count == 0xff)
			mode10_state->state = partial_count;
		    else {
			/* finished count - partial count only happens on RLE */
			if_debug1('w', "count=%d\n", mode10_state->count);
			mode10_state->state = process_rle;
		    }
		    break;
		}

	    case next_is_pixel:{
		    if (!mode9031 && (avail < 3)) {
			/* get to outer loop to get more data */
			avail = 0;
			break;
		    }
		    if_debug3('w', "pixel:%02X%02X%02X\n", pin[0], pin[1],
			      pin[2]);
		    if (v_state->color_space == eGraySub) {
			/* bug in recent hpijs */
			mode10_state->cached_pixel =
			    (pin[0] << 16 | pin[0] << 8 | pin[0]) ^
			    0x00ffffff;
		    } else if (mode9031) {
			mode10_state->cached_pixel =
			    (pin[0] << 16 | pin[0] << 8 | pin[0]);
		    } else
			mode10_state->cached_pixel =
			    (pin[0] << 16 | pin[1] << 8 | pin[2]);
		    update_pout(pout);
		    update_advance_pixel(pout, pin, mode9031);
		    if (mode9031) {
			pin += 1;
			avail -= 1;
		    } else {
			pin += 3;
			avail -= 3;
		    }
		    mode10_state->cursor++;
		    if ((mode10_state->cmd & eRLE)
			&& (mode10_state->count == 7))
			mode10_state->state = partial_count;
		    else if (mode10_state->cmd & eRLE) {
			mode10_state->state = process_rle;
		    } else if (mode10_state->count > 0) {
			/* literal */
			mode10_state->count--;
			mode10_state->state = next_is_pixel;
		    } else
			mode10_state->state = next_is_cmd;
		    break;
		}

	    case process_rle:{
		    update_pout(pout);
		    pixel =
			get_pixel(pout, &mode10_state->cached_pixel,
				  mode10_state->cmd, v_state->color_space);

		    mode10_state->cursor += mode10_state->count + 2;
		    i = mode10_state->count + 2;

		    if (srcNEW(mode10_state->cmd)) {
			i--;	/* already moved cursor in the case of new pixel */
			mode10_state->cursor--;
		    }
		    while (i > 0) {
			copy_pixel(pout, pixel);
			i--;
		    }
		    mode10_state->state = next_is_cmd;
		    break;
		}

	}			/* end switch */

	/* conditional on state may not be necessary */
	if ((mode10_state->state == next_is_cmd) &&
	    (mode10_state->cursor >= v_state->SourceWidth)) {
	    mode10_state->cursor = 0;
	    end_of_row = 1;
	}
    }				/* end of while */

    par->source.available -= pin - par->source.data;	/* subtract compressed data used */
    par->source.position += pin - par->source.data;
    par->source.data = pin;	/* new compressed data position */

    if (end_of_row) {
	v_state->rowwritten++;
	return 1;
    }
    return pxNeedData;		/* not end of row so request more data */
}
Esempio n. 26
0
/* this procedure is exported for the benefit of gsicc.c */
int
gx_cie_real_remap_finish(cie_cached_vector3 vec3, frac * pconc,
                         const gs_imager_state * pis,
                         const gs_color_space *pcs)
{
    const gs_cie_render *pcrd = pis->cie_render;
    const gx_cie_joint_caches *pjc = pis->cie_joint_caches;
    const gs_const_string *table = pcrd->RenderTable.lookup.table;
    int tabc[3];		/* indices for final EncodeABC lookup */

    /* Apply DecodeLMN, MatrixLMN(decode), and MatrixPQR. */
    if (!pjc->skipDecodeLMN)
        cie_lookup_map3(&vec3 /* LMN => PQR */, &pjc->DecodeLMN,
                        "Decode/MatrixLMN+MatrixPQR");

    /* Apply TransformPQR, MatrixPQR', and MatrixLMN(encode). */
    if (!pjc->skipPQR)
        cie_lookup_map3(&vec3 /* PQR => LMN */, &pjc->TransformPQR,
                        "Transform/Matrix'PQR+MatrixLMN");

    /* Apply EncodeLMN and MatrixABC(encode). */
    if (!pjc->skipEncodeLMN)
        cie_lookup_map3(&vec3 /* LMN => ABC */, &pcrd->caches.EncodeLMN,
                        "EncodeLMN+MatrixABC");

    /* MatrixABCEncode includes the scaling of the EncodeABC */
    /* cache index. */
#define SET_TABC(i, t)\
  BEGIN\
    tabc[i] = cie_cached2int(vec3 /*ABC*/.t - pcrd->EncodeABC_base[i],\
                             _cie_interpolate_bits);\
    if ((uint)tabc[i] > (gx_cie_cache_size - 1) << _cie_interpolate_bits)\
        tabc[i] = (tabc[i] < 0 ? 0 :\
                   (gx_cie_cache_size - 1) << _cie_interpolate_bits);\
  END
    SET_TABC(0, u);
    SET_TABC(1, v);
    SET_TABC(2, w);
#undef SET_TABC
    if (table == 0) {
        /*
         * No further transformation.
         * The final mapping step includes both restriction to
         * the range [0..1] and conversion to fracs.
         */
#define EABC(i)\
  cie_interpolate_fracs(pcrd->caches.EncodeABC[i].fixeds.fracs.values, tabc[i])
        pconc[0] = EABC(0);
        pconc[1] = EABC(1);
        pconc[2] = EABC(2);
#undef EABC
        return 3;
    } else {
        /*
         * Use the RenderTable.
         */
        int m = pcrd->RenderTable.lookup.m;

#define RT_LOOKUP(j, i) pcrd->caches.RenderTableT[j].fracs.values[i]
#ifdef CIE_RENDER_TABLE_INTERPOLATE

        /*
         * The final mapping step includes restriction to the
         * ranges [0..dims[c]] as ints with interpolation bits.
         */
        fixed rfix[3];
        const int s = _fixed_shift - _cie_interpolate_bits;

#define EABC(i)\
  cie_interpolate_fracs(pcrd->caches.EncodeABC[i].fixeds.ints.values, tabc[i])
#define FABC(i, s)\
  ((s) > 0) ? (EABC(i) << (s)) : (EABC(i) >> -(s))
        rfix[0] = FABC(0, s);
        rfix[1] = FABC(1, s);
        rfix[2] = FABC(2, s);
#undef FABC
#undef EABC
        if_debug6('c', "[c]ABC=%g,%g,%g => iabc=%g,%g,%g\n",
                  cie_cached2float(vec3.u), cie_cached2float(vec3.v),
                  cie_cached2float(vec3.w), fixed2float(rfix[0]),
                  fixed2float(rfix[1]), fixed2float(rfix[2]));
        gx_color_interpolate_linear(rfix, &pcrd->RenderTable.lookup,
                                    pconc);
        if_debug3('c', "[c]  interpolated => %g,%g,%g\n",
                  frac2float(pconc[0]), frac2float(pconc[1]),
                  frac2float(pconc[2]));
        if (!pcrd->caches.RenderTableT_is_identity) {
            /* Map the interpolated values. */
#define frac2cache_index(v) frac2bits(v, gx_cie_log2_cache_size)
            pconc[0] = RT_LOOKUP(0, frac2cache_index(pconc[0]));
            pconc[1] = RT_LOOKUP(1, frac2cache_index(pconc[1]));
            pconc[2] = RT_LOOKUP(2, frac2cache_index(pconc[2]));
            if (m > 3)
                pconc[3] = RT_LOOKUP(3, frac2cache_index(pconc[3]));
#undef frac2cache_index
        }

#else /* !CIE_RENDER_TABLE_INTERPOLATE */

        /*
         * The final mapping step includes restriction to the ranges
         * [0..dims[c]], plus scaling of the indices in the strings.
         */
#define RI(i)\
  pcrd->caches.EncodeABC[i].ints.values[tabc[i] >> _cie_interpolate_bits]
        int ia = RI(0);
        int ib = RI(1);		/* pre-multiplied by m * NC */
        int ic = RI(2);		/* pre-multiplied by m */
        const byte *prtc = table[ia].data + ib + ic;

        /* (*pcrd->RenderTable.T)(prtc, m, pcrd, pconc); */

        if_debug6('c', "[c]ABC=%g,%g,%g => iabc=%d,%d,%d\n",
                  cie_cached2float(vec3.u), cie_cached2float(vec3.v),
                  cie_cached2float(vec3.w), ia, ib, ic);
        if (pcrd->caches.RenderTableT_is_identity) {
            pconc[0] = byte2frac(prtc[0]);
            pconc[1] = byte2frac(prtc[1]);
            pconc[2] = byte2frac(prtc[2]);
            if (m > 3)
                pconc[3] = byte2frac(prtc[3]);
        } else {
#if gx_cie_log2_cache_size == 8
#  define byte2cache_index(b) (b)
#else
# if gx_cie_log2_cache_size > 8
#  define byte2cache_index(b)\
    ( ((b) << (gx_cie_log2_cache_size - 8)) +\
      ((b) >> (16 - gx_cie_log2_cache_size)) )
# else				/* < 8 */
#  define byte2cache_index(b) ((b) >> (8 - gx_cie_log2_cache_size))
# endif
#endif
            pconc[0] = RT_LOOKUP(0, byte2cache_index(prtc[0]));
            pconc[1] = RT_LOOKUP(1, byte2cache_index(prtc[1]));
            pconc[2] = RT_LOOKUP(2, byte2cache_index(prtc[2]));
            if (m > 3)
                pconc[3] = RT_LOOKUP(3, byte2cache_index(prtc[3]));
#undef byte2cache_index
        }

#endif /* !CIE_RENDER_TABLE_INTERPOLATE */
#undef RI
#undef RT_LOOKUP
        return m;
    }
}
Esempio n. 27
0
/* Set the relocation for a ref object. */
static bool
refs_set_reloc(obj_header_t * hdr, uint reloc, uint size)
{
    ref_packed *rp = (ref_packed *) (hdr + 1);
    ref_packed *end = (ref_packed *) ((byte *) rp + size);
    uint freed = 0;

    /*
     * We have to be careful to keep refs aligned properly.
     * For the moment, we do this by either keeping or discarding
     * an entire (aligned) block of align_packed_per_ref packed elements
     * as a unit.  We know that align_packed_per_ref <= packed_per_ref,
     * and we also know that packed refs are always allocated in blocks
     * of align_packed_per_ref, so this makes things relatively easy.
     */
    while (rp < end) {
	if (r_is_packed(rp)) {
#if align_packed_per_ref == 1
	    if (r_has_pmark(rp)) {
		if_debug1('8',
			  "  [8]packed ref 0x%lx is marked\n",
			  (ulong) rp);
		rp++;
	    } else {
#else
	    int i;

	    /*
	     * Note: align_packed_per_ref is typically
	     * 2 or 4 for 32-bit processors.
	     */
#define all_marked (align_packed_per_ref * lp_mark)
# if align_packed_per_ref == 2
#  if arch_sizeof_int == arch_sizeof_short * 2
#    undef all_marked
#    define all_marked ( (lp_mark << (sizeof(short) * 8)) + lp_mark )
#    define marked (*(int *)rp & all_marked)
#  else
#    define marked ((*rp & lp_mark) + (rp[1] & lp_mark))
#  endif
# else
#  if align_packed_per_ref == 4
#    define marked ((*rp & lp_mark) + (rp[1] & lp_mark) +\
		    (rp[2] & lp_mark) + (rp[3] & lp_mark))
#  else
	    /*
	     * The value of marked is logically a uint, not an int:
	     * we declare it as int only to avoid a compiler warning
	     * message about using a non-int value in a switch statement.
	     */
	    int marked = *rp & lp_mark;

	    for (i = 1; i < align_packed_per_ref; i++)
		marked += rp[i] & lp_mark;
#  endif
# endif
	    /*
	     * Now marked is lp_mark * the number of marked
	     * packed refs in the aligned block, except for
	     * a couple of special cases above.
	     */
	    switch (marked) {
		case all_marked:
		    if_debug2('8',
			      "  [8]packed refs 0x%lx..0x%lx are marked\n",
			      (ulong) rp,
			      (ulong) (rp + (align_packed_per_ref - 1)));
		    rp += align_packed_per_ref;
		    break;
		default:
		    /* At least one packed ref in the block */
		    /* is marked: Keep the whole block. */
		    for (i = align_packed_per_ref; i--; rp++) {
			r_set_pmark(rp);
			if_debug1('8',
				  "  [8]packed ref 0x%lx is marked\n",
				  (ulong) rp);
		    }
		    break;
		case 0:
#endif
		    if_debug2('8', "  [8]%d packed ref(s) at 0x%lx are unmarked\n",
			      align_packed_per_ref, (ulong) rp);
		    {
			uint rel = reloc + freed;

			/* Change this to an integer so we can */
			/* store the relocation here. */
			*rp = pt_tag(pt_integer) +
			    min(rel, packed_max_value);
		    }
		    rp += align_packed_per_ref;
		    freed += sizeof(ref_packed) * align_packed_per_ref;
	    }
	} else {		/* full-size ref */
	    uint rel = reloc + freed;

	    /* The following assignment is logically */
	    /* unnecessary; we do it only for convenience */
	    /* in debugging. */
	    ref *pref = (ref *) rp;

	    if (!r_has_attr(pref, l_mark)) {
		if_debug1('8', "  [8]ref 0x%lx is unmarked\n",
			  (ulong) pref);
		/* Change this to a mark so we can */
		/* store the relocation. */
		r_set_type(pref, t_mark);
		r_set_size(pref, rel);
		freed += sizeof(ref);
	    } else {
		if_debug1('8', "  [8]ref 0x%lx is marked\n",
			  (ulong) pref);
		/* Store the relocation here if possible. */
		if (!ref_type_uses_size_or_null(r_type(pref))) {
		    if_debug2('8', "  [8]storing reloc %u at 0x%lx\n",
			      rel, (ulong) pref);
		    r_set_size(pref, rel);
		}
	    }
	    rp += packed_per_ref;
	}
    }
    if_debug3('7', " [7]at end of refs 0x%lx, size = %u, freed = %u\n",
	      (ulong) (hdr + 1), size, freed);
    if (freed == size)
	return false;
#if arch_sizeof_int > arch_sizeof_short
    /*
     * If the final relocation can't fit in the r_size field
     * (which can't happen if the object shares a chunk with
     * any other objects, so we know reloc = 0 in this case),
     * we have to keep the entire object unless there are no
     * references to any ref in it.
     */
    if (freed <= max_ushort)
	return true;
    /*
     * We have to mark all surviving refs, but we also must
     * overwrite any non-surviving refs with something that
     * doesn't contain any pointers.
     */
    rp = (ref_packed *) (hdr + 1);
    while (rp < end) {
	if (r_is_packed(rp)) {
	    if (!r_has_pmark(rp))
		*rp = pt_tag(pt_integer) | lp_mark;
	    ++rp;
	} else {		/* The following assignment is logically */
	    /* unnecessary; we do it only for convenience */
	    /* in debugging. */
	    ref *pref = (ref *) rp;

	    if (!r_has_attr(pref, l_mark)) {
		r_set_type_attrs(pref, t_mark, l_mark);
		r_set_size(pref, reloc);
	    } else {
		if (!ref_type_uses_size_or_null(r_type(pref)))
		    r_set_size(pref, reloc);
	    }
	    rp += packed_per_ref;
	}
    }
    /* The last ref has to remain unmarked. */
    r_clear_attrs((ref *) rp - 1, l_mark);
#endif
    return true;
}
Esempio n. 28
0
/* the routine sets ph->actual_frequency and ph->actual_angle. */
static int
pick_cell_size(gs_screen_halftone * ph, const gs_matrix * pmat, ulong max_size,
               uint min_levels, bool accurate, gx_ht_cell_params_t * phcp)
{
    const bool landscape = (pmat->xy != 0.0 || pmat->yx != 0.0);

    /* Account for a possibly reflected coordinate system. */
    /* See gxstroke.c for the algorithm. */
    const bool reflected = pmat->xy * pmat->yx > pmat->xx * pmat->yy;
    const int reflection = (reflected ? -1 : 1);
    const int rotation =
    (landscape ? (pmat->yx < 0 ? 90 : -90) : pmat->xx < 0 ? 180 : 0);
    const double f0 = ph->frequency, a0 = ph->angle;
    const double T =
    fabs((landscape ? pmat->yx / pmat->xy : pmat->xx / pmat->yy));
    gs_point uv0;

#define u0 uv0.x
#define v0 uv0.y
    int rt = 1;
    double f = 0, a = 0;
    double e_best = 1000;
    bool better;

    /*
     * We need to find a vector in device space whose length is
     * 1 inch / ph->frequency and whose angle is ph->angle.
     * Because device pixels may not be square, we can't simply
     * map the length to device space and then rotate it;
     * instead, since we know that user space is uniform in X and Y,
     * we calculate the correct angle in user space before rotation.
     */

    /* Compute trial values of u and v. */

    {
        gs_matrix rmat;

        gs_make_rotation(a0 * reflection + rotation, &rmat);
        gs_distance_transform(72.0 / f0, 0.0, &rmat, &uv0);
        gs_distance_transform(u0, v0, pmat, &uv0);
        if_debug10('h', "[h]Requested: f=%g a=%g mat=[%g %g %g %g] max_size=%lu min_levels=%u =>\n     u=%g v=%g\n",
                   ph->frequency, ph->angle,
                   pmat->xx, pmat->xy, pmat->yx, pmat->yy,
                   max_size, min_levels, u0, v0);
    }

    /* Adjust u and v to reasonable values. */

    if (u0 == 0 && v0 == 0)
        return_error(gs_error_rangecheck);
    while ((fabs(u0) + fabs(v0)) * rt < 4)
        ++rt;
  try_size:
    better = false;
    {
        double fm0 = u0 * rt;
        double fn0 = v0 * rt;
        int m0 = (int)floor(u0 * rt + 0.0001);
        int n0 = (int)floor(v0 * rt + 0.0001);
        gx_ht_cell_params_t p;

        p.R = p.R1 = rt;
        for (p.M = m0 + 1; p.M >= m0; p.M--)
            for (p.N = n0 + 1; p.N >= n0; p.N--) {
                long raster, wt, wt_size;
                double fr, ar, ft, at, f_diff, a_diff, f_err, a_err;

                p.M1 = (int)floor(p.M / T + 0.5);
                p.N1 = (int)floor(p.N * T + 0.5);
                gx_compute_cell_values(&p);
                if_debug3('h', "[h]trying m=%d, n=%d, r=%d\n", p.M, p.N, rt);
                wt = p.W;
                if (wt >= max_short)
                    continue;
                /* Check the strip size, not the full tile size, */
                /* against max_size. */
                raster = bitmap_raster(wt);
                if (raster > max_size / p.D || raster > max_long / wt)
                    continue;
                wt_size = raster * wt;

                /* Compute the corresponding values of F and A. */

                if (landscape)
                    ar = atan2(p.M * pmat->xy, p.N * pmat->yx),
                        fr = 72.0 * (p.M == 0 ? pmat->xy / p.N * cos(ar) :
                                     pmat->yx / p.M * sin(ar));
                else
                    ar = atan2(p.N * pmat->xx, p.M * pmat->yy),
                        fr = 72.0 * (p.M == 0 ? pmat->yy / p.N * sin(ar) :
                                     pmat->xx / p.M * cos(ar));
                ft = fabs(fr) * rt;
                /* Normalize the angle to the requested quadrant. */
                at = (ar * radians_to_degrees - rotation) * reflection;
                at -= floor(at / 180.0) * 180.0;
                at += floor(a0 / 180.0) * 180.0;
                f_diff = fabs(ft - f0);
                a_diff = fabs(at - a0);
                f_err = f_diff / fabs(f0);
                /*
                 * We used to compute the percentage difference here:
                 *      a_err = (a0 == 0 ? a_diff : a_diff / fabs(a0));
                 * but using the angle difference makes more sense:
                 */
                a_err = a_diff;

                if_debug5('h', " ==> d=%d, wt=%ld, wt_size=%ld, f=%g, a=%g\n",
                          p.D, wt, bitmap_raster(wt) * wt, ft, at);

                {
                    /*
                     * Compute the error in position between ideal location.
                     * and the current integer location.
                     */

                    double error =
                        (fn0 - p.N) * (fn0 - p.N) + (fm0 - p.M) * (fm0 - p.M);
                    /*
                     * Adjust the error by the length of the vector.  This gives
                     * a slight bias toward larger cell sizzes.
                     */
                    error /= p.N * p.N + p.M * p.M;
                    error = sqrt(error); /* The previous calcs. gave value squared */
                    if (error > e_best)
                        continue;
                    e_best = error;
                }
                *phcp = p;
                f = ft, a = at;
                better = true;
                if_debug3('h', "*** best wt_size=%ld, f_diff=%g, a_diff=%g\n",
                          wt_size, f_diff, a_diff);
                /*
                 * We want a maximum relative frequency error of 1% and a
                 * maximum angle error of 1% (of 90 degrees).
                 */
                if (f_err <= 0.01 && a_err <= 0.9 /*degrees*/)
                    goto done;
            }
    }
    if (phcp->C < min_levels) { /* We don't have enough levels yet.  Keep going. */
        ++rt;
        goto try_size;
    }
    if (better) {               /* If we want accurate screens, continue till we fail. */
        if (accurate) {
            ++rt;
            goto try_size;
        }
    } else {                    /*
                                 * We couldn't find an acceptable M and N.  If R > 1,
                                 * take what we've got; if R = 1, give up.
                                 */
        if (rt == 1)
            return_error(gs_error_rangecheck);
    }

    /* Deliver the results. */
  done:
    if_debug5('h', "[h]Chosen: f=%g a=%g M=%d N=%d R=%d\n",
              f, a, phcp->M, phcp->N, phcp->R);
    ph->actual_frequency = f;
    ph->actual_angle = a;
    return 0;
#undef u0
#undef v0
}
Esempio n. 29
0
int eprn_set_page_layout(eprn_Device *dev)
{
  bool
    no_match = true,
     /* Are the requested flags supported for some size? */
    landscape = dev->MediaSize[0] > dev->MediaSize[1];
     /* It's not documented, but 'MediaSize' is the requested "PageSize" page
        device parameter value and hence is to be interpreted in default (not
        default default!) user space. */
  const char *epref = dev->eprn.CUPS_messages? CUPS_ERRPREF: "";
  const eprn_CustomPageDescription
    *best_cmatch = NULL;        /* best custom page size match */
  eprn_Eprn
    *eprn = &dev->eprn;
  const eprn_PageDescription
    *best_cdmatch = NULL,     /* best custom page size match in discrete list*/
    *best_dmatch = NULL,        /* best discrete match */
    *pd;                        /* loop variable */
  float
    /* Page width and height in bp with w <= h (in a moment): */
    w = dev->MediaSize[0],
    h = dev->MediaSize[1],
    /* pixmap device space margins in bp (canonical order): */
    margins[4];
  int
    quarters;
  ms_MediaCode
    desired = eprn->desired_flags;

#ifdef EPRN_TRACE
  if_debug3(EPRN_TRACE_CHAR,
    "! eprn_set_page_layout(): PageSize = [%.0f %.0f], "
      "desired_flags = 0x%04X.\n",
    dev->MediaSize[0], dev->MediaSize[1], (unsigned int)desired);
#endif

  /* Ensure w <= h */
  if (w > h) {
    float temp;
    temp = w; w = h; h = temp;
    /* This has effectively split 'MediaSize[]' into 'w', 'h' and 'landscape'.
     */
  }

  /* Initialization of primary return value */
  eprn->code = ms_none;

  /* Put the LeadingEdge value into the desired flag pattern if it's set */
  if (eprn->leading_edge_set) {
    if (eprn->default_orientation % 2 == 0)     /* true on short edge first */
      desired &= ~MS_TRANSVERSE_FLAG;
    else
      desired |= MS_TRANSVERSE_FLAG;
  }

  /* Find best match in discrete sizes */
  if (eprn->media_overrides == NULL) pd = eprn->cap->sizes;
  else pd = eprn->media_overrides;
  while (pd->code != ms_none) {
    const ms_SizeDescription *ms = ms_find_size_from_code(pd->code);
    if (ms->dimen[0] > 0.0 /* ignore variable sizes */ &&
        fabs(w - ms->dimen[0])  <= 5.0 &&
        fabs(h - ms->dimen[1]) <= 5.0) {
       /* The size does match at 5 bp tolerance. This value has been chosen
          arbitrarily to be equal to PostScript's PageSize matching tolerance
          during media selection. The tolerance should really be that at which
          the printer in question distinguishes between sizes or smaller than
          that in order to at least prevent printing on unsupported sizes.
        */
      if (best_dmatch == NULL ||
          better_flag_match(desired, eprn->optional_flags, best_dmatch->code,
            pd->code))
        best_dmatch = pd;
      if (flag_match(desired, eprn->optional_flags, pd->code))
        no_match = false;
    }
    pd++;
  }

  /* Next find the best match among the custom size descriptions */
  if (eprn->cap->custom != NULL) {
    const eprn_CustomPageDescription *cp = eprn->cap->custom;

    /* First check whether the size is in the supported range */
    while (cp->width_max > 0.0) {
      if (cp->width_min  <= w && w <= cp->width_max &&
          cp->height_min <= h && h <= cp->height_max) {
        /* The size does match. */
        if (best_cmatch == NULL ||
            better_flag_match(desired, eprn->optional_flags, best_cmatch->code,
              cp->code))
          best_cmatch = cp;
        if (eprn->media_overrides == NULL &&
            flag_match(desired, eprn->optional_flags, cp->code))
          no_match = false;
      }
      cp++;
    }

    /* If we have read a media configuration file, the flags to be matched
       must be sought in 'media_overrides'. */
    if (best_cmatch != NULL && eprn->media_overrides != NULL) {
      for (pd = eprn->media_overrides; pd->code != ms_none; pd++) {
        if (ms_without_flags(pd->code) == ms_CustomPageSize) {
          if (best_cdmatch == NULL ||
              better_flag_match(desired, eprn->optional_flags,
                best_cdmatch->code, pd->code))
            best_cdmatch = pd;
          if (flag_match(desired, eprn->optional_flags, pd->code))
            no_match = false;
        }
      }
    }
  }

  /*  Now the 'best_*match' variables indicate for each of the categories of
      page descriptions to which extent the size is supported at all (non-NULL
      value) and what the best flag match in the category is. Here we now check
      for NULL values, i.e., size matches. */
  if (best_dmatch == NULL) {
    /* No discrete match */
    if (best_cmatch == NULL) {
      /* No match at all. */
      eprintf3("%s" ERRPREF
        "This document requests a page size of %.0f x %.0f bp.\n",
           epref, dev->MediaSize[0], dev->MediaSize[1]);
      if (eprn->cap->custom == NULL) {
        /* The printer does not support custom page sizes */
        if (eprn->media_overrides != NULL)
          eprintf1(
            "%s  The media configuration file does not contain an entry for "
              " this size.\n", epref);
        else
          eprintf2("%s  This size is not supported by the %s.\n",
            epref, eprn->cap->name);
      }
      else
        eprintf3(
          "%s  This size is not supported as a discrete size and it exceeds "
            "the\n"
          "%s  custom page size limits for the %s.\n",
          epref, epref, eprn->cap->name);
      return -1;
    }
    if (eprn->media_overrides != NULL && best_cdmatch == NULL) {
      eprintf6("%s" ERRPREF
        "This document requests a page size of %.0f x %.0f bp\n"
        "%s  but there is no entry for this size in the "
          "media configuration file\n"
        "%s  %s.\n",
        epref, dev->MediaSize[0], dev->MediaSize[1], epref, epref,
        eprn->media_file);
      return -1;
    }
  }
  /* Now we have: best_dmatch != NULL || best_cmatch != NULL &&
     (eprn->media_overrides == NULL || best_cdmatch != NULL). */

  /* Find a flag match among the size matches found so far */
  {
    ms_MediaCode custom_code = ms_none;
      /* best custom page size match (either from cmatch or dcmatch) */
    if (best_cmatch != NULL &&
        (eprn->media_overrides == NULL || best_cdmatch != NULL))
      custom_code = (eprn->media_overrides == NULL?
        best_cmatch->code: best_cdmatch->code);

    if (best_dmatch == NULL ||
        best_cmatch != NULL &&
          better_flag_match(desired, eprn->optional_flags, best_dmatch->code,
            custom_code)) {
      if (flag_match(desired, eprn->optional_flags, custom_code)) {
        if (eprn->media_overrides == NULL) {
          eprn->code = best_cmatch->code;
          margins[0] = best_cmatch->left;
          margins[1] = best_cmatch->bottom;
          margins[2] = best_cmatch->right;
          margins[3] = best_cmatch->top;
        }
        else {
          eprn->code = best_cdmatch->code;
          margins[0] = best_cdmatch->left;
          margins[1] = best_cdmatch->bottom;
          margins[2] = best_cdmatch->right;
          margins[3] = best_cdmatch->top;
        }
      }
    }
    else {
      if (flag_match(desired, eprn->optional_flags, best_dmatch->code)) {
        eprn->code = best_dmatch->code;
        margins[0] = best_dmatch->left;
        margins[1] = best_dmatch->bottom;
        margins[2] = best_dmatch->right;
        margins[3] = best_dmatch->top;
      }
    }
  }
  /* If we've found a match, 'code' is no longer 'ms_none'. */
  if (eprn->code == ms_none) {
    eprn_flag_mismatch(eprn, no_match);
    return -1;
  }

  /* Adapt the orientation of default default user space if not prescribed */
  if (!eprn->leading_edge_set) {
    if (eprn->code & MS_TRANSVERSE_FLAG) eprn->default_orientation = 3;
     /* This leads to 0 if landscape orientation is requested. */
    else eprn->default_orientation = 0;
  }

  /*
    Now 'eprn->default_orientation % 2' describes the sheet's orientation in
    pixmap device space. If this does not agree with the width and height
    values in the device instance, we'll have to adapt them.
    This is only necessary if there is a significant difference between width
    and height.
   */
  if (fabs(w - h) > 1 /* arbitrary */ &&
    (eprn->default_orientation % 2 == 0) !=
        (dev->width/dev->HWResolution[0] <= dev->height/dev->HWResolution[1])) {
    bool reallocate = false;

#ifdef EPRN_TRACE
    if_debug0(EPRN_TRACE_CHAR,
      "! eprn_set_page_layout(): width-height change is necessary.\n");
#endif

    /* Free old storage if the device is open */
    if (dev->is_open) {
#ifdef EPRN_TRACE
      if_debug0(EPRN_TRACE_CHAR, "! eprn_set_page_layout(): Device is open.\n");
#endif
      reallocate = true;
       /* One could try and call the allocation/reallocation routines of the
          prn device directly, but they are not available in older ghostscript
          versions and this method is safer anyway because it relies on a
          documented API. */
      gdev_prn_close((gx_device *)dev);         /* ignore the result */
    }

    /*  Now set width and height via gx_device_set_media_size(). This function
        sets 'MediaSize[]', 'width', and 'height' based on the assumption that
        default user space has a y axis which is vertical in pixmap device
        space. This may be wrong and we have to fix it. Because fixing
        'MediaSize[]' is simpler, gx_device_set_media_size() is called such
        that it gives the correct values for 'width' and 'height'. */
    if (eprn->default_orientation % 2 == 0) {
      /* portrait orientation of the sheet in pixmap device space */
      gx_device_set_media_size((gx_device *)dev, w, h);
      if (landscape) {
        dev->MediaSize[0] = h;
        dev->MediaSize[1] = w;
      }
    }
    else {
      /* landscape orientation in pixmap device space (transverse) */
      gx_device_set_media_size((gx_device *)dev, h, w);
      if (!landscape) {
        dev->MediaSize[0] = w;
        dev->MediaSize[1] = h;
      }
    }

    /* If the device is/was open, reallocate storage */
    if (reallocate) {
      int rc;

      rc = gdev_prn_open((gx_device *)dev);
      if (rc < 0) {
        eprintf2("%s" ERRPREF
          "Failure of gdev_prn_open(), code is %d.\n",
          epref, rc);
        return rc;
      }
    }
  }

  /* Increase the bottom margin for coloured modes except if it is exactly
     zero */
  if (eprn->colour_model != eprn_DeviceGray && margins[1] != 0.0)
    margins[1] += eprn->cap->bottom_increment;

  /* Number of +90-degree rotations needed for default user space: */
  quarters = eprn->default_orientation;
  if (landscape) quarters = (quarters + 1)%4;

  /* Store the top and left margins in the device structure for use by
     eprn_get_initial_matrix() and set the margins of the printable area if
     we may.
     gx_device_set_margins() (see gsdevice.c) copies the margins[] array to
     HWMargins[] which is presumably to be interpreted in default user space
     (see gs_initclip() in gspath.c), and if its second argument is true it
     also modifies the offset variable Margins[]. The first property means
     that gx_device_set_margins() can only be used if default user space and
     pixmap device space have the same "up" direction, and the second
     appropriates a parameter which is intended for the user.
  */
  if (eprn->keep_margins) {
    eprn->down_shift  = dev->HWMargins[3 - quarters];
    eprn->right_shift = dev->HWMargins[(4 - quarters)%4];
  }
  else {
    int j;

    eprn->down_shift  = margins[3];
    eprn->right_shift = margins[0];

    if (quarters != 0) {
       /* The "canonical margin order" for ghostscript is left, bottom, right,
          top. Hence for, e.g., a +90-degree rotation ('quarters' is 1) of
          default user space with respect to pixmap device space the left
          margin (index 0) in default user space is actually the bottom margin
          (index 1) in pixmap device space, the bottom margin is the right one,
          etc.
        */
      for (j = 0; j < 4; j++) dev->HWMargins[j] = margins[(j+quarters)%4];
      /* 'HWMargins[]' is in bp (see gxdevcli.h) */
    }
    else {
      /* Convert to inches */
      for (j = 0; j < 4; j++) margins[j] /= BP_PER_IN;

      gx_device_set_margins((gx_device *)dev, margins, false);
       /* Of course, I could set HWMargins[] directly also in this case. This
          way is however less prone to break on possible future incompatible
          changes to ghostscript and it covers the most frequent case (portrait
          and short edge first). */
    }
  }

  return 0;
}
Esempio n. 30
0
/* Process a buffer */
static int
s_DCTD_process(stream_state * st, stream_cursor_read * pr,
	       stream_cursor_write * pw, bool last)
{
    stream_DCT_state *const ss = (stream_DCT_state *) st;
    jpeg_decompress_data *jddp = ss->data.decompress;
    struct jpeg_source_mgr *src = jddp->dinfo.src;
    int code;

    if_debug3('w', "[wdd]process avail=%u, skip=%u, last=%d\n",
	      (uint) (pr->limit - pr->ptr), (uint) jddp->skip, last);
    if (jddp->skip != 0) {
	long avail = pr->limit - pr->ptr;

	if (avail < jddp->skip) {
	    jddp->skip -= avail;
	    pr->ptr = pr->limit;
	    if (!last)
		return 0;	/* need more data */
	    jddp->skip = 0;	/* don't skip past input EOD */
	}
	pr->ptr += jddp->skip;
	jddp->skip = 0;
    }
    src->next_input_byte = pr->ptr + 1;
    src->bytes_in_buffer = pr->limit - pr->ptr;
    jddp->input_eod = last;
    switch (ss->phase) {
	case 0:		/* not initialized yet */
	    /*
	     * Adobe implementations seem to ignore leading garbage bytes,
	     * even though neither the standard nor Adobe's own
	     * documentation mention this.
	     */
	    while (pr->ptr < pr->limit && pr->ptr[1] != 0xff)
		pr->ptr++;
	    if (pr->ptr == pr->limit)
		return 0;
	    src->next_input_byte = pr->ptr + 1;
	    src->bytes_in_buffer = pr->limit - pr->ptr;
	    ss->phase = 1;
	    /* falls through */
	case 1:		/* reading header markers */
	    if ((code = gs_jpeg_read_header(ss, TRUE)) < 0)
		return ERRC;
	    pr->ptr =
		(jddp->faked_eoi ? pr->limit : src->next_input_byte - 1);
	    switch (code) {
		case JPEG_SUSPENDED:
		    return 0;
		    /*case JPEG_HEADER_OK: */
	    }
	    /* If we have a ColorTransform parameter, and it's not
	     * overridden by an Adobe marker in the data, set colorspace.
	     */
	    if (ss->ColorTransform >= 0 &&
		!jddp->dinfo.saw_Adobe_marker) {
		switch (jddp->dinfo.num_components) {
		    case 3:
			jddp->dinfo.jpeg_color_space =
			    (ss->ColorTransform ? JCS_YCbCr : JCS_RGB);
			/* out_color_space will default to JCS_RGB */
			break;
		    case 4:
			jddp->dinfo.jpeg_color_space =
			    (ss->ColorTransform ? JCS_YCCK : JCS_CMYK);
			/* out_color_space will default to JCS_CMYK */
			break;
		}
	    }
	    ss->phase = 2;
	    /* falls through */
	case 2:		/* start_decompress */
	    if ((code = gs_jpeg_start_decompress(ss)) < 0)
		return ERRC;
	    pr->ptr =
		(jddp->faked_eoi ? pr->limit : src->next_input_byte - 1);
	    if (code == 0)
		return 0;
	    ss->scan_line_size =
		jddp->dinfo.output_width * jddp->dinfo.output_components;
	    if_debug4('w', "[wdd]width=%u, components=%d, scan_line_size=%u, min_out_size=%u\n",
		      jddp->dinfo.output_width,
		      jddp->dinfo.output_components,
		      ss->scan_line_size, jddp->template.min_out_size);