145
145
/* Validate the parameters. */
146
146
if (pim->Height <= 0)
147
return_error(gs_error_rangecheck);
147
return_error(gs_error_rangecheck);
148
148
penum = gs_alloc_struct(mem, gx_image3x_enum_t, &st_image3x_enum,
151
return_error(gs_error_VMerror);
151
return_error(gs_error_VMerror);
152
152
/* Initialize pointers now in case we bail out. */
153
153
penum->mask[0].info = 0, penum->mask[0].mdev = 0, penum->mask[0].data = 0;
154
154
penum->mask[1].info = 0, penum->mask[1].mdev = 0, penum->mask[1].data = 0;
155
155
penum->pixel.info = 0, penum->pixel.data = 0;
159
pixel.rect.p.x = pixel.rect.p.y = 0;
160
pixel.rect.q.x = pim->Width;
161
pixel.rect.q.y = pim->Height;
159
pixel.rect.p.x = pixel.rect.p.y = 0;
160
pixel.rect.q.x = pim->Width;
161
pixel.rect.q.y = pim->Height;
163
163
if ((code = gs_matrix_invert(&pim->ImageMatrix, &pixel.matrix)) < 0 ||
164
(code = gs_point_transform(pim->Width, pim->Height, &pixel.matrix,
165
&pixel.corner)) < 0 ||
166
(code = check_image3x_mask(pim, &pim->Opacity, &pixel, &mask[0],
167
&penum->mask[0], mem)) < 0 ||
168
(code = check_image3x_mask(pim, &pim->Shape, &pixel, &mask[1],
169
&penum->mask[1], mem)) < 0
164
(code = gs_point_transform(pim->Width, pim->Height, &pixel.matrix,
165
&pixel.corner)) < 0 ||
166
(code = check_image3x_mask(pim, &pim->Opacity, &pixel, &mask[0],
167
&penum->mask[0], mem)) < 0 ||
168
(code = check_image3x_mask(pim, &pim->Shape, &pixel, &mask[1],
169
&penum->mask[1], mem)) < 0
173
173
penum->num_components =
174
gs_color_space_num_components(pim->ColorSpace);
174
gs_color_space_num_components(pim->ColorSpace);
175
175
gx_image_enum_common_init((gx_image_enum_common_t *) penum,
176
(const gs_data_image_t *)pim,
177
&image3x_enum_procs, dev,
178
1 + penum->num_components,
176
(const gs_data_image_t *)pim,
177
&image3x_enum_procs, dev,
178
1 + penum->num_components,
180
180
penum->pixel.width = pixel.rect.q.x - pixel.rect.p.x;
181
181
penum->pixel.height = pixel.rect.q.y - pixel.rect.p.y;
182
182
penum->pixel.full_height = pim->Height;
183
183
penum->pixel.y = 0;
184
184
if (penum->mask[0].data || penum->mask[1].data) {
185
/* Also allocate a row buffer for the pixel data. */
188
(penum->pixel.width * pim->BitsPerComponent *
189
penum->num_components + 7) >> 3,
190
"gx_begin_image3x(pixel.data)");
191
if (penum->pixel.data == 0) {
192
code = gs_note_error(gs_error_VMerror);
185
/* Also allocate a row buffer for the pixel data. */
188
(penum->pixel.width * pim->BitsPerComponent *
189
penum->num_components + 7) >> 3,
190
"gx_begin_image3x(pixel.data)");
191
if (penum->pixel.data == 0) {
192
code = gs_note_error(gs_error_VMerror);
196
196
penum->bpc = pim->BitsPerComponent;
197
197
penum->memory = mem;
199
pmat = &ctm_only(pis);
199
pmat = &ctm_only(pis);
200
200
for (i = 0; i < NUM_MASKS; ++i) {
204
* The mask data has to be defined in a DevicePixel color space
205
* of the correct depth so that no color mapping will occur.
207
/****** FREE COLOR SPACE ON ERROR OR AT END ******/
208
gs_color_space *pmcs;
204
* The mask data has to be defined in a DevicePixel color space
205
* of the correct depth so that no color mapping will occur.
207
/****** FREE COLOR SPACE ON ERROR OR AT END ******/
208
gs_color_space *pmcs;
210
if (penum->mask[i].depth == 0) { /* mask not supplied */
215
code = gs_cspace_new_DevicePixel(mem, &pmcs, penum->mask[i].depth);
218
mrect.p.x = mrect.p.y = 0;
219
mrect.q.x = penum->mask[i].width;
220
mrect.q.y = penum->mask[i].height;
221
if ((code = gs_matrix_multiply(&mask[i].matrix, pmat, &mat)) < 0 ||
222
(code = gs_bbox_transform(&mrect, &mat, &mrect)) < 0
225
origin[i].x = (int)floor(mrect.p.x);
226
origin[i].y = (int)floor(mrect.p.y);
227
code = make_mid(&mdev, dev,
228
(int)ceil(mrect.q.x) - origin[i].x,
229
(int)ceil(mrect.q.y) - origin[i].y,
230
penum->mask[i].depth, mem);
231
mdev->device_icc_profile = dev->device_icc_profile;
232
rc_increment(dev->device_icc_profile);
235
penum->mask[i].mdev = mdev;
210
if (penum->mask[i].depth == 0) { /* mask not supplied */
215
code = gs_cspace_new_DevicePixel(mem, &pmcs, penum->mask[i].depth);
218
mrect.p.x = mrect.p.y = 0;
219
mrect.q.x = penum->mask[i].width;
220
mrect.q.y = penum->mask[i].height;
221
if ((code = gs_matrix_multiply(&mask[i].matrix, pmat, &mat)) < 0 ||
222
(code = gs_bbox_transform(&mrect, &mat, &mrect)) < 0
225
origin[i].x = (int)floor(mrect.p.x);
226
origin[i].y = (int)floor(mrect.p.y);
227
code = make_mid(&mdev, dev,
228
(int)ceil(mrect.q.x) - origin[i].x,
229
(int)ceil(mrect.q.y) - origin[i].y,
230
penum->mask[i].depth, mem);
231
code = dev_proc(dev, get_profile)(dev, &mdev->icc_array);
232
rc_increment(mdev->icc_array);
235
penum->mask[i].mdev = mdev;
236
236
gs_image_t_init(&mask[i].image, pmcs);
237
mask[i].image.ColorSpace = pmcs;
238
mask[i].image.adjust = false;
237
mask[i].image.ColorSpace = pmcs;
238
mask[i].image.adjust = false;
239
239
mask[i].image.image_parent_type = gs_image_type3x;
241
const gx_image_type_t *type1 = mask[i].image.type;
242
const gs_image3x_mask_t *pixm =
243
(i == 0 ? &pim->Opacity : &pim->Shape);
241
const gx_image_type_t *type1 = mask[i].image.type;
242
const gs_image3x_mask_t *pixm =
243
(i == 0 ? &pim->Opacity : &pim->Shape);
245
245
/* Use memcpy because direct assignment breaks ANSI aliasing */
246
246
/* rules and causes SEGV with gcc 4.5.1 */
247
247
memcpy(&mask[i].image, &pixm->MaskDict, sizeof(pixm->MaskDict));
248
mask[i].image.type = type1;
249
mask[i].image.BitsPerComponent = pixm->MaskDict.BitsPerComponent;
248
mask[i].image.type = type1;
249
mask[i].image.BitsPerComponent = pixm->MaskDict.BitsPerComponent;
255
* Adjust the translation for rendering the mask to include a
256
* negative translation by origin.{x,y} in device space.
259
m_mat.tx -= origin[i].x;
260
m_mat.ty -= origin[i].y;
262
* Peter put in a comment that said " Note that pis = NULL here,
263
* since we don't want to have to create another imager state with
264
* default log_op, etc." and passed NULL instead of pis to this
265
* routine. However Image type 1 need the imager state (see
266
* bug 688348) thus his optimization was removed.
267
* dcolor = NULL is OK because this is an opaque image with
268
* CombineWithColor = false.
270
code = gx_device_begin_typed_image(mdev, pis, &m_mat,
271
(const gs_image_common_t *)&mask[i].image,
272
&mask[i].rect, NULL, NULL,
273
mem, &penum->mask[i].info);
278
minfo[i] = penum->mask[i].info;
255
* Adjust the translation for rendering the mask to include a
256
* negative translation by origin.{x,y} in device space.
259
m_mat.tx -= origin[i].x;
260
m_mat.ty -= origin[i].y;
262
* Peter put in a comment that said " Note that pis = NULL here,
263
* since we don't want to have to create another imager state with
264
* default log_op, etc." and passed NULL instead of pis to this
265
* routine. However Image type 1 need the imager state (see
266
* bug 688348) thus his optimization was removed.
267
* dcolor = NULL is OK because this is an opaque image with
268
* CombineWithColor = false.
270
code = gx_device_begin_typed_image(mdev, pis, &m_mat,
271
(const gs_image_common_t *)&mask[i].image,
272
&mask[i].rect, NULL, NULL,
273
mem, &penum->mask[i].info);
278
minfo[i] = penum->mask[i].info;
280
280
gs_image_t_init(&pixel.image, pim->ColorSpace);
282
const gx_image_type_t *type1 = pixel.image.type;
282
const gx_image_type_t *type1 = pixel.image.type;
284
*(gs_pixel_image_t *)&pixel.image = *(const gs_pixel_image_t *)pim;
285
pixel.image.type = type1;
284
*(gs_pixel_image_t *)&pixel.image = *(const gs_pixel_image_t *)pim;
285
pixel.image.type = type1;
286
286
pixel.image.image_parent_type = gs_image_type3x;
288
288
code = make_mcde(dev, pis, pmat, (const gs_image_common_t *)&pixel.image,
289
prect, pdcolor, pcpath, mem, &penum->pixel.info,
290
&pcdev, midev, minfo, origin, pim);
289
prect, pdcolor, pcpath, mem, &penum->pixel.info,
290
&pcdev, midev, minfo, origin, pim);
293
293
penum->pcdev = pcdev;
295
295
* Set num_planes, plane_widths, and plane_depths from the values in the
296
296
* enumerators for the mask(s) and the image data.
302
for (i = 0; i < NUM_MASKS; ++i) {
303
if (penum->mask[i].depth == 0) /* no mask */
305
switch (penum->mask[i].InterleaveType) {
306
case interleave_chunky:
307
/* Add the mask data to the depth of the image data. */
308
added_depth += pim->BitsPerComponent;
310
case interleave_separate_source:
311
/* Insert the mask as a separate plane. */
312
penum->plane_widths[pi] = penum->mask[i].width;
313
penum->plane_depths[pi] = penum->mask[i].depth;
316
default: /* can't happen */
317
code = gs_note_error(gs_error_Fatal);
321
memcpy(&penum->plane_widths[pi], &penum->pixel.info->plane_widths[0],
322
penum->pixel.info->num_planes * sizeof(penum->plane_widths[0]));
323
memcpy(&penum->plane_depths[pi], &penum->pixel.info->plane_depths[0],
324
penum->pixel.info->num_planes * sizeof(penum->plane_depths[0]));
325
penum->plane_depths[pi] += added_depth;
326
penum->num_planes = pi + penum->pixel.info->num_planes;
302
for (i = 0; i < NUM_MASKS; ++i) {
303
if (penum->mask[i].depth == 0) /* no mask */
305
switch (penum->mask[i].InterleaveType) {
306
case interleave_chunky:
307
/* Add the mask data to the depth of the image data. */
308
added_depth += pim->BitsPerComponent;
310
case interleave_separate_source:
311
/* Insert the mask as a separate plane. */
312
penum->plane_widths[pi] = penum->mask[i].width;
313
penum->plane_depths[pi] = penum->mask[i].depth;
316
default: /* can't happen */
317
code = gs_note_error(gs_error_Fatal);
321
memcpy(&penum->plane_widths[pi], &penum->pixel.info->plane_widths[0],
322
penum->pixel.info->num_planes * sizeof(penum->plane_widths[0]));
323
memcpy(&penum->plane_depths[pi], &penum->pixel.info->plane_depths[0],
324
penum->pixel.info->num_planes * sizeof(penum->plane_depths[0]));
325
penum->plane_depths[pi] += added_depth;
326
penum->num_planes = pi + penum->pixel.info->num_planes;
329
gx_device_retain(midev[0], true); /* will free explicitly */
329
gx_device_retain(midev[0], true); /* will free explicitly */
331
gx_device_retain(midev[1], true); /* ditto */
331
gx_device_retain(midev[1], true); /* ditto */
332
332
gx_device_retain(pcdev, true); /* ditto */
333
333
*pinfo = (gx_image_enum_common_t *) penum;
336
336
if (penum->mask[1].info)
337
gx_image_end(penum->mask[1].info, false);
337
gx_image_end(penum->mask[1].info, false);
338
338
if (penum->mask[0].info)
339
gx_image_end(penum->mask[0].info, false);
339
gx_image_end(penum->mask[0].info, false);
341
341
if (penum->mask[1].mdev) {
342
gs_closedevice(penum->mask[1].mdev);
343
gs_free_object(mem, penum->mask[1].mdev,
344
"gx_begin_image3x(mask[1].mdev)");
342
gs_closedevice(penum->mask[1].mdev);
343
gs_free_object(mem, penum->mask[1].mdev,
344
"gx_begin_image3x(mask[1].mdev)");
346
346
if (penum->mask[0].mdev) {
347
gs_closedevice(penum->mask[0].mdev);
348
gs_free_object(mem, penum->mask[0].mdev,
349
"gx_begin_image3x(mask[0].mdev)");
347
gs_closedevice(penum->mask[0].mdev);
348
gs_free_object(mem, penum->mask[0].mdev,
349
"gx_begin_image3x(mask[0].mdev)");
352
352
gs_free_object(mem, penum->mask[0].data, "gx_begin_image3x(mask[0].data)");
375
375
check_image3x_mask(const gs_image3x_t *pim, const gs_image3x_mask_t *pimm,
376
const image3x_channel_values_t *ppcv,
377
image3x_channel_values_t *pmcv,
378
image3x_channel_state_t *pmcs, gs_memory_t *mem)
376
const image3x_channel_values_t *ppcv,
377
image3x_channel_values_t *pmcv,
378
image3x_channel_state_t *pmcs, gs_memory_t *mem)
380
380
int mask_width = pimm->MaskDict.Width, mask_height = pimm->MaskDict.Height;
383
383
if (pimm->MaskDict.BitsPerComponent == 0) { /* mask missing */
385
385
pmcs->InterleaveType = 0; /* not a valid type */
388
388
if (mask_height <= 0)
389
return_error(gs_error_rangecheck);
389
return_error(gs_error_rangecheck);
390
390
switch (pimm->InterleaveType) {
391
/*case interleave_scan_lines:*/ /* not supported */
393
return_error(gs_error_rangecheck);
394
case interleave_chunky:
395
if (mask_width != pim->Width ||
396
mask_height != pim->Height ||
397
pimm->MaskDict.BitsPerComponent != pim->BitsPerComponent ||
398
pim->format != gs_image_format_chunky
400
return_error(gs_error_rangecheck);
402
case interleave_separate_source:
403
switch (pimm->MaskDict.BitsPerComponent) {
404
case 1: case 2: case 4: case 8: case 12: case 16:
407
return_error(gs_error_rangecheck);
391
/*case interleave_scan_lines:*/ /* not supported */
393
return_error(gs_error_rangecheck);
394
case interleave_chunky:
395
if (mask_width != pim->Width ||
396
mask_height != pim->Height ||
397
pimm->MaskDict.BitsPerComponent != pim->BitsPerComponent ||
398
pim->format != gs_image_format_chunky
400
return_error(gs_error_rangecheck);
402
case interleave_separate_source:
403
switch (pimm->MaskDict.BitsPerComponent) {
404
case 1: case 2: case 4: case 8: case 12: case 16:
407
return_error(gs_error_rangecheck);
410
410
if (!check_image3x_extent(pim->ImageMatrix.xx,
411
pimm->MaskDict.ImageMatrix.xx) ||
412
!check_image3x_extent(pim->ImageMatrix.xy,
413
pimm->MaskDict.ImageMatrix.xy) ||
414
!check_image3x_extent(pim->ImageMatrix.yx,
415
pimm->MaskDict.ImageMatrix.yx) ||
416
!check_image3x_extent(pim->ImageMatrix.yy,
417
pimm->MaskDict.ImageMatrix.yy)
419
return_error(gs_error_rangecheck);
411
pimm->MaskDict.ImageMatrix.xx) ||
412
!check_image3x_extent(pim->ImageMatrix.xy,
413
pimm->MaskDict.ImageMatrix.xy) ||
414
!check_image3x_extent(pim->ImageMatrix.yx,
415
pimm->MaskDict.ImageMatrix.yx) ||
416
!check_image3x_extent(pim->ImageMatrix.yy,
417
pimm->MaskDict.ImageMatrix.yy)
419
return_error(gs_error_rangecheck);
420
420
if ((code = gs_matrix_invert(&pimm->MaskDict.ImageMatrix, &pmcv->matrix)) < 0 ||
421
(code = gs_point_transform(mask_width, mask_height,
422
&pmcv->matrix, &pmcv->corner)) < 0
421
(code = gs_point_transform(mask_width, mask_height,
422
&pmcv->matrix, &pmcv->corner)) < 0
425
425
if (fabs(ppcv->matrix.tx - pmcv->matrix.tx) >= 0.5 ||
426
fabs(ppcv->matrix.ty - pmcv->matrix.ty) >= 0.5 ||
427
fabs(ppcv->corner.x - pmcv->corner.x) >= 0.5 ||
428
fabs(ppcv->corner.y - pmcv->corner.y) >= 0.5
430
return_error(gs_error_rangecheck);
426
fabs(ppcv->matrix.ty - pmcv->matrix.ty) >= 0.5 ||
427
fabs(ppcv->corner.x - pmcv->corner.x) >= 0.5 ||
428
fabs(ppcv->corner.y - pmcv->corner.y) >= 0.5
430
return_error(gs_error_rangecheck);
431
431
pmcv->rect.p.x = ppcv->rect.p.x * mask_width / pim->Width;
432
432
pmcv->rect.p.y = ppcv->rect.p.y * mask_height / pim->Height;
433
433
pmcv->rect.q.x = (ppcv->rect.q.x * mask_width + pim->Width - 1) /
435
435
pmcv->rect.q.y = (ppcv->rect.q.y * mask_height + pim->Height - 1) /
437
437
/* Initialize the channel state in the enumerator. */
438
438
pmcs->InterleaveType = pimm->InterleaveType;
439
439
pmcs->width = pmcv->rect.q.x - pmcv->rect.p.x;
541
541
* that can be freed at the end and that simply forwards all calls.
542
542
* The most convenient device for this purpose is the bbox device.
544
gx_device_bbox *bbdev =
545
gs_alloc_struct_immovable(mem, gx_device_bbox, &st_device_bbox,
546
"make_mcdex_default");
544
gx_device_bbox *bbdev;
546
cmm_dev_profile_t *icc_array;
548
code = dev_proc(dev, get_profile)(dev, &icc_array);
553
bbdev = gs_alloc_struct_immovable(mem, gx_device_bbox, &st_device_bbox,
554
"make_mcdex_default");
550
return_error(gs_error_VMerror);
557
return_error(gs_error_VMerror);
551
559
gx_device_bbox_init(bbdev, dev, mem);
561
bbdev->icc_array = icc_array;
562
rc_increment(bbdev->icc_array);
552
564
gx_device_bbox_fwd_open_close(bbdev, false);
553
565
code = dev_proc(bbdev, begin_typed_image)
554
((gx_device *)bbdev, pis, pmat, pic, prect, pdcolor, pcpath, mem,
566
((gx_device *)bbdev, pis, pmat, pic, prect, pdcolor, pcpath, mem,
557
gs_free_object(mem, bbdev, "make_mcdex_default");
569
gs_free_object(mem, bbdev, "make_mcdex_default");
560
572
*pmcdev = (gx_device *)bbdev;
564
576
gx_begin_image3x(gx_device * dev,
565
const gs_imager_state * pis, const gs_matrix * pmat,
566
const gs_image_common_t * pic, const gs_int_rect * prect,
567
const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
568
gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
577
const gs_imager_state * pis, const gs_matrix * pmat,
578
const gs_image_common_t * pic, const gs_int_rect * prect,
579
const gx_drawing_color * pdcolor, const gx_clip_path * pcpath,
580
gs_memory_t * mem, gx_image_enum_common_t ** pinfo)
570
582
return gx_begin_image3x_generic(dev, pis, pmat, pic, prect, pdcolor,
571
pcpath, mem, make_midx_default,
572
make_mcdex_default, pinfo);
583
pcpath, mem, make_midx_default,
584
make_mcdex_default, pinfo);
575
587
/* Process the next piece of an ImageType 3 image. */
577
589
gx_image3x_plane_data(gx_image_enum_common_t * info,
578
const gx_image_plane_t * planes, int height,
590
const gx_image_plane_t * planes, int height,
581
593
gx_image3x_enum_t *penum = (gx_image3x_enum_t *) info;
582
594
int pixel_height = penum->pixel.height;
609
621
/* FIX_ME. In the soft mask branch
610
622
the file associated with bug 689290
611
623
gets into an endless loop. This
612
is related to the size mismatch of the
613
soft mask which is 1x1 and the
624
is related to the size mismatch of the
625
soft mask which is 1x1 and the
623
635
/* Handle masks from separate sources. */
624
636
for (i = 0; i < NUM_MASKS; ++i)
625
if (penum->mask[i].InterleaveType == interleave_separate_source) {
627
* In order to be able to recover from interruptions, we must
628
* limit separate-source processing to 1 scan line at a time.
632
mask_plane[i] = planes[pi++];
637
if (penum->mask[i].InterleaveType == interleave_separate_source) {
639
* In order to be able to recover from interruptions, we must
640
* limit separate-source processing to 1 scan line at a time.
644
mask_plane[i] = planes[pi++];
634
646
pixel_planes = &planes[pi];
636
648
/* Handle chunky masks. */
637
649
if (num_chunky) {
638
int bpc = penum->bpc;
639
int num_components = penum->num_components;
640
int width = penum->pixel.width;
641
/* Pull apart the source data and the mask data. */
642
/* We do this in the simplest (not fastest) way for now. */
643
uint bit_x = bpc * (num_components + num_chunky) * planes[pi].data_x;
644
sample_load_declare_setup(sptr, sbit, planes[0].data + (bit_x >> 3),
646
sample_store_declare_setup(pptr, pbit, pbbyte,
647
penum->pixel.data, 0, bpc);
648
sample_store_declare(dptr[NUM_MASKS], dbit[NUM_MASKS],
650
int depth[NUM_MASKS];
654
/* Do the operation one row at a time. */
657
for (i = 0; i < NUM_MASKS; ++i)
658
if (penum->mask[i].data) {
659
depth[i] = penum->mask[i].depth;
660
mask_plane[i].data = dptr[i] = penum->mask[i].data;
661
mask_plane[i].data_x = 0;
662
/* raster doesn't matter */
663
sample_store_setup(dbit[i], 0, depth[i]);
664
sample_store_preload(dbbyte[i], dptr[i], 0, depth[i]);
667
pixel_plane.data = pptr;
668
pixel_plane.data_x = 0;
669
/* raster doesn't matter */
670
pixel_planes = &pixel_plane;
671
for (x = 0; x < width; ++x) {
674
for (i = 0; i < NUM_MASKS; ++i)
676
sample_load_next12(value, sptr, sbit, bpc);
677
sample_store_next12(value, dptr[i], dbit[i], depth[i],
680
for (i = 0; i < num_components; ++i) {
681
sample_load_next12(value, sptr, sbit, bpc);
682
sample_store_next12(value, pptr, pbit, bpc, pbbyte);
685
for (i = 0; i < NUM_MASKS; ++i)
686
if (penum->mask[i].data)
687
sample_store_flush(dptr[i], dbit[i], depth[i], dbbyte[i]);
688
sample_store_flush(pptr, pbit, bpc, pbbyte);
650
int bpc = penum->bpc;
651
int num_components = penum->num_components;
652
int width = penum->pixel.width;
653
/* Pull apart the source data and the mask data. */
654
/* We do this in the simplest (not fastest) way for now. */
655
uint bit_x = bpc * (num_components + num_chunky) * planes[pi].data_x;
656
sample_load_declare_setup(sptr, sbit, planes[0].data + (bit_x >> 3),
658
sample_store_declare_setup(pptr, pbit, pbbyte,
659
penum->pixel.data, 0, bpc);
660
sample_store_declare(dptr[NUM_MASKS], dbit[NUM_MASKS],
662
int depth[NUM_MASKS];
666
/* Do the operation one row at a time. */
669
for (i = 0; i < NUM_MASKS; ++i)
670
if (penum->mask[i].data) {
671
depth[i] = penum->mask[i].depth;
672
mask_plane[i].data = dptr[i] = penum->mask[i].data;
673
mask_plane[i].data_x = 0;
674
/* raster doesn't matter */
675
sample_store_setup(dbit[i], 0, depth[i]);
676
sample_store_preload(dbbyte[i], dptr[i], 0, depth[i]);
679
pixel_plane.data = pptr;
680
pixel_plane.data_x = 0;
681
/* raster doesn't matter */
682
pixel_planes = &pixel_plane;
683
for (x = 0; x < width; ++x) {
686
for (i = 0; i < NUM_MASKS; ++i)
688
sample_load_next12(value, sptr, sbit, bpc);
689
sample_store_next12(value, dptr[i], dbit[i], depth[i],
692
for (i = 0; i < num_components; ++i) {
693
sample_load_next12(value, sptr, sbit, bpc);
694
sample_store_next12(value, pptr, pbit, bpc, pbbyte);
697
for (i = 0; i < NUM_MASKS; ++i)
698
if (penum->mask[i].data)
699
sample_store_flush(dptr[i], dbit[i], depth[i], dbbyte[i]);
700
sample_store_flush(pptr, pbit, bpc, pbbyte);
691
703
* Process the mask data first, so it will set up the mask
692
704
* device for clipping the pixel data.
694
706
for (i = 0; i < NUM_MASKS; ++i)
695
if (mask_plane[i].data) {
697
* If, on the last call, we processed some mask rows
698
* successfully but processing the pixel rows was interrupted,
699
* we set rows_used to indicate the number of pixel rows
700
* processed (since there is no way to return two rows_used
701
* values). If this happened, some mask rows may get presented
702
* again. We must skip over them rather than processing them
705
int skip = penum->mask[i].skip;
708
penum->mask[i].skip = skip - (mask_used[i] = h);
710
int mask_h = h - skip;
712
mask_plane[i].data += skip * mask_plane[i].raster;
713
penum->mask[i].skip = 0;
714
code = gx_image_plane_data_rows(penum->mask[i].info,
716
mask_h, &mask_used[i]);
717
mask_used[i] += skip;
719
*rows_used = mask_used[i];
720
penum->mask[i].y += mask_used[i];
707
if (mask_plane[i].data) {
709
* If, on the last call, we processed some mask rows
710
* successfully but processing the pixel rows was interrupted,
711
* we set rows_used to indicate the number of pixel rows
712
* processed (since there is no way to return two rows_used
713
* values). If this happened, some mask rows may get presented
714
* again. We must skip over them rather than processing them
717
int skip = penum->mask[i].skip;
720
penum->mask[i].skip = skip - (mask_used[i] = h);
722
int mask_h = h - skip;
724
mask_plane[i].data += skip * mask_plane[i].raster;
725
penum->mask[i].skip = 0;
726
code = gx_image_plane_data_rows(penum->mask[i].info,
728
mask_h, &mask_used[i]);
729
mask_used[i] += skip;
731
*rows_used = mask_used[i];
732
penum->mask[i].y += mask_used[i];
724
736
if (pixel_planes[0].data) {
726
* If necessary, flush any buffered mask data to the mask clipping
729
for (i = 0; i < NUM_MASKS; ++i)
730
if (penum->mask[i].info)
731
gx_image_flush(penum->mask[i].info);
732
code = gx_image_plane_data_rows(penum->pixel.info, pixel_planes, h,
735
* There isn't any way to set rows_used if different amounts of
736
* the mask and pixel data were used. Fake it.
738
*rows_used = pixel_used;
740
* Don't return code yet: we must account for the fact that
741
* some mask data may have been processed.
743
penum->pixel.y += pixel_used;
746
* We must prevent the mask data from being processed again.
747
* We rely on the fact that h > 1 is only possible if the
748
* mask and pixel data have the same Y scaling.
750
for (i = 0; i < NUM_MASKS; ++i)
751
if (mask_used[i] > pixel_used) {
752
int skip = mask_used[i] - pixel_used;
738
* If necessary, flush any buffered mask data to the mask clipping
741
for (i = 0; i < NUM_MASKS; ++i)
742
if (penum->mask[i].info)
743
gx_image_flush(penum->mask[i].info);
744
code = gx_image_plane_data_rows(penum->pixel.info, pixel_planes, h,
747
* There isn't any way to set rows_used if different amounts of
748
* the mask and pixel data were used. Fake it.
750
*rows_used = pixel_used;
752
* Don't return code yet: we must account for the fact that
753
* some mask data may have been processed.
755
penum->pixel.y += pixel_used;
758
* We must prevent the mask data from being processed again.
759
* We rely on the fact that h > 1 is only possible if the
760
* mask and pixel data have the same Y scaling.
762
for (i = 0; i < NUM_MASKS; ++i)
763
if (mask_used[i] > pixel_used) {
764
int skip = mask_used[i] - pixel_used;
754
penum->mask[i].skip = skip;
755
penum->mask[i].y -= skip;
756
mask_used[i] = pixel_used;
766
penum->mask[i].skip = skip;
767
penum->mask[i].y -= skip;
768
mask_used[i] = pixel_used;
760
772
if_debug7('b', "[b]image3x h=%d %sopacity.y=%d %sopacity.y=%d %spixel.y=%d\n",
761
h, (mask_plane[0].data ? "+" : ""), penum->mask[0].y,
762
(mask_plane[1].data ? "+" : ""), penum->mask[1].y,
763
(pixel_planes[0].data ? "+" : ""), penum->pixel.y);
773
h, (mask_plane[0].data ? "+" : ""), penum->mask[0].y,
774
(mask_plane[1].data ? "+" : ""), penum->mask[1].y,
775
(pixel_planes[0].data ? "+" : ""), penum->pixel.y);
764
776
if (penum->mask[0].depth == 0 || penum->mask[0].y >= penum->mask[0].height) {
765
777
if (penum->mask[1].depth == 0 || penum->mask[1].y >= penum->mask[1].height) {
766
if (penum->pixel.y >= penum->pixel.height) {
778
if (penum->pixel.y >= penum->pixel.height) {
802
sso = penum->mask[0].InterleaveType == interleave_separate_source,
803
sss = penum->mask[1].InterleaveType == interleave_separate_source;
814
sso = penum->mask[0].InterleaveType == interleave_separate_source,
815
sss = penum->mask[1].InterleaveType == interleave_separate_source;
806
/* Both masks have separate sources. */
807
int mask_next = channel_next(&penum->mask[1], &penum->pixel);
818
/* Both masks have separate sources. */
819
int mask_next = channel_next(&penum->mask[1], &penum->pixel);
809
memset(wanted + 2, (mask_next <= 0 ? 0xff : 0), info->num_planes - 2);
810
wanted[1] = (mask_next >= 0 ? 0xff : 0);
812
mask_next = channel_next(&penum->mask[0], &penum->mask[1]);
813
wanted[0] = mask_next >= 0;
816
return false; /* see below */
821
memset(wanted + 2, (mask_next <= 0 ? 0xff : 0), info->num_planes - 2);
822
wanted[1] = (mask_next >= 0 ? 0xff : 0);
824
mask_next = channel_next(&penum->mask[0], &penum->mask[1]);
825
wanted[0] = mask_next >= 0;
828
return false; /* see below */
817
829
} else if (sso | sss) {
818
/* Only one separate source. */
819
const image3x_channel_state_t *pics =
820
(sso ? &penum->mask[0] : &penum->mask[1]);
821
int mask_next = channel_next(pics, &penum->pixel);
830
/* Only one separate source. */
831
const image3x_channel_state_t *pics =
832
(sso ? &penum->mask[0] : &penum->mask[1]);
833
int mask_next = channel_next(pics, &penum->pixel);
823
wanted[0] = (mask_next >= 0 ? 0xff : 0);
824
memset(wanted + 1, (mask_next <= 0 ? 0xff : 0), info->num_planes - 1);
826
* In principle, wanted will always be true for both mask and pixel
827
* data if the full_heights are equal. Unfortunately, even in this
828
* case, processing may be interrupted after a mask row has been
829
* passed to the underlying image processor but before the data row
830
* has been passed, in which case pixel data will be 'wanted', but
831
* not mask data, for the next call. Therefore, we must return
836
pics->full_height == penum->pixel.full_height)*/;
835
wanted[0] = (mask_next >= 0 ? 0xff : 0);
836
memset(wanted + 1, (mask_next <= 0 ? 0xff : 0), info->num_planes - 1);
838
* In principle, wanted will always be true for both mask and pixel
839
* data if the full_heights are equal. Unfortunately, even in this
840
* case, processing may be interrupted after a mask row has been
841
* passed to the underlying image processor but before the data row
842
* has been passed, in which case pixel data will be 'wanted', but
843
* not mask data, for the next call. Therefore, we must return
848
pics->full_height == penum->pixel.full_height)*/;
838
/* Everything is chunky, only 1 plane. */
850
/* Everything is chunky, only 1 plane. */