diff options
-rw-r--r-- | draw/draw_device.c | 37 | ||||
-rw-r--r-- | draw/draw_scale.c | 176 | ||||
-rw-r--r-- | draw/draw_simple_scale.c | 105 | ||||
-rw-r--r-- | fitz/fitz.h | 2 |
4 files changed, 221 insertions, 99 deletions
diff --git a/draw/draw_device.c b/draw/draw_device.c index 9a238b73..1cb3e4b9 100644 --- a/draw/draw_device.c +++ b/draw/draw_device.c @@ -821,7 +821,7 @@ fz_draw_fill_shade(fz_device *devp, fz_shade *shade, fz_matrix ctm, float alpha) } static fz_pixmap * -fz_transform_pixmap(fz_context *ctx, fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int dy, int gridfit) +fz_transform_pixmap(fz_context *ctx, fz_pixmap *image, fz_matrix *ctm, int x, int y, int dx, int dy, int gridfit, fz_bbox *clip) { fz_pixmap *scaled; @@ -831,7 +831,7 @@ fz_transform_pixmap(fz_context *ctx, fz_pixmap *image, fz_matrix *ctm, int x, in fz_matrix m = *ctm; if (gridfit) fz_gridfit_matrix(&m); - scaled = fz_scale_pixmap(ctx, image, m.e, m.f, m.a, m.d); + scaled = fz_scale_pixmap(ctx, image, m.e, m.f, m.a, m.d, clip); if (!scaled) return NULL; ctm->a = scaled->w; @@ -845,9 +845,17 @@ fz_transform_pixmap(fz_context *ctx, fz_pixmap *image, fz_matrix *ctm, int x, in { /* Other orthogonal flip/rotation cases */ fz_matrix m = *ctm; + fz_bbox rclip; if (gridfit) fz_gridfit_matrix(&m); - scaled = fz_scale_pixmap(ctx, image, m.f, m.e, m.b, m.c); + if (clip) + { + rclip.x0 = clip->y0; + rclip.y0 = clip->x0; + rclip.x1 = clip->y1; + rclip.y1 = clip->x1; + } + scaled = fz_scale_pixmap(ctx, image, m.f, m.e, m.b, m.c, (clip ? &rclip : 0)); if (!scaled) return NULL; ctm->b = scaled->w; @@ -860,7 +868,7 @@ fz_transform_pixmap(fz_context *ctx, fz_pixmap *image, fz_matrix *ctm, int x, in /* Downscale, non rectilinear case */ if (dx > 0 && dy > 0) { - scaled = fz_scale_pixmap(ctx, image, 0, 0, (float)dx, (float)dy); + scaled = fz_scale_pixmap(ctx, image, 0, 0, (float)dx, (float)dy, NULL); return scaled; } @@ -878,6 +886,9 @@ fz_draw_fill_image(fz_device *devp, fz_pixmap *image, fz_matrix ctm, float alpha fz_context *ctx = dev->ctx; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; + fz_bbox clip = fz_bound_pixmap(state->dest); + + clip = fz_intersect_bbox(clip, state->scissor); fz_var(scaled); @@ -915,14 +926,14 @@ fz_draw_fill_image(fz_device *devp, fz_pixmap *image, fz_matrix ctm, float alpha if (dx < image->w && dy < image->h) { int gridfit = alpha == 1.0f && !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3); - scaled = fz_transform_pixmap(ctx, image, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit); + scaled = fz_transform_pixmap(ctx, image, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip); if (!scaled) { if (dx < 1) dx = 1; if (dy < 1) dy = 1; - scaled = fz_scale_pixmap(ctx, image, image->x, image->y, dx, dy); + scaled = fz_scale_pixmap(ctx, image, image->x, image->y, dx, dy, NULL); } if (scaled) image = scaled; @@ -973,6 +984,9 @@ fz_draw_fill_image_mask(fz_device *devp, fz_pixmap *image, fz_matrix ctm, int i; fz_draw_state *state = &dev->stack[dev->top]; fz_colorspace *model = state->dest->colorspace; + fz_bbox clip = fz_bound_pixmap(state->dest); + + clip = fz_intersect_bbox(clip, state->scissor); if (image->w == 0 || image->h == 0) return; @@ -985,14 +999,14 @@ fz_draw_fill_image_mask(fz_device *devp, fz_pixmap *image, fz_matrix ctm, if (dx < image->w && dy < image->h) { int gridfit = alpha == 1.0f && !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3); - scaled = fz_transform_pixmap(dev->ctx, image, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit); + scaled = fz_transform_pixmap(dev->ctx, image, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip); if (!scaled) { if (dx < 1) dx = 1; if (dy < 1) dy = 1; - scaled = fz_scale_pixmap(dev->ctx, image, image->x, image->y, dx, dy); + scaled = fz_scale_pixmap(dev->ctx, image, image->x, image->y, dx, dy, NULL); } if (scaled) image = scaled; @@ -1025,6 +1039,9 @@ fz_draw_clip_image_mask(fz_device *devp, fz_pixmap *image, fz_rect *rect, fz_mat int dx, dy; fz_draw_state *state = push_stack(dev); fz_colorspace *model = state->dest->colorspace; + fz_bbox clip = fz_bound_pixmap(state->dest); + + clip = fz_intersect_bbox(clip, state->scissor); fz_var(mask); fz_var(dest); @@ -1066,14 +1083,14 @@ fz_draw_clip_image_mask(fz_device *devp, fz_pixmap *image, fz_rect *rect, fz_mat if (dx < image->w && dy < image->h) { int gridfit = !(dev->flags & FZ_DRAWDEV_FLAGS_TYPE3); - scaled = fz_transform_pixmap(dev->ctx, image, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit); + scaled = fz_transform_pixmap(dev->ctx, image, &ctm, state->dest->x, state->dest->y, dx, dy, gridfit, &clip); if (!scaled) { if (dx < 1) dx = 1; if (dy < 1) dy = 1; - scaled = fz_scale_pixmap(dev->ctx, image, image->x, image->y, dx, dy); + scaled = fz_scale_pixmap(dev->ctx, image, image->x, image->y, dx, dy, NULL); } if (scaled) image = scaled; diff --git a/draw/draw_scale.c b/draw/draw_scale.c index e478633c..87d0b334 100644 --- a/draw/draw_scale.c +++ b/draw/draw_scale.c @@ -262,16 +262,17 @@ typedef struct fz_weights_s fz_weights; struct fz_weights_s { - int flip; - int count; - int max_len; - int n; - int new_line; + int flip; /* true if outputting reversed */ + int count; /* number of output pixels we have records for in this table */ + int max_len; /* Maximum number of weights for any one output pixel */ + int n; /* number of components (src->n) */ + int new_line; /* True if no weights for the current output pixel */ + int patch_l; /* How many output pixels we skip over */ int index[1]; }; static fz_weights * -new_weights(fz_context *ctx, fz_scale_filter *filter, int src_w, float dst_w, int dst_w_i, int n, int flip) +new_weights(fz_context *ctx, fz_scale_filter *filter, int src_w, float dst_w, int patch_w, int n, int flip, int patch_l) { int max_len; fz_weights *weights; @@ -293,26 +294,29 @@ new_weights(fz_context *ctx, fz_scale_filter *filter, int src_w, float dst_w, in max_len = 2 * filter->width; } /* We need the size of the struct, - * plus dst_w*sizeof(int) for the index + * plus patch_w*sizeof(int) for the index * plus (2+max_len)*sizeof(int) for the weights * plus room for an extra set of weights for reordering. */ - weights = fz_malloc(ctx, sizeof(*weights)+(max_len+3)*(dst_w_i+1)*sizeof(int)); + weights = fz_malloc(ctx, sizeof(*weights)+(max_len+3)*(patch_w+1)*sizeof(int)); if (!weights) return NULL; weights->count = -1; weights->max_len = max_len; - weights->index[0] = dst_w_i; + weights->index[0] = patch_w; weights->n = n; + weights->patch_l = patch_l; weights->flip = flip; return weights; } +/* j is destination pixel in the patch_l..patch_l+patch_w range */ static void init_weights(fz_weights *weights, int j) { int index; + j -= weights->patch_l; assert(weights->count == j-1); weights->count++; weights->new_line = 1; @@ -344,24 +348,7 @@ add_weight(fz_weights *weights, int j, int i, fz_scale_filter *filter, if (weight == 0) return; - /* wrap i back into range */ -#ifdef MIRROR_WRAP - do - { - if (i < 0) - i = -1-i; - else if (i >= src_w) - i = 2*src_w-1-i; - else - break; - } - while (1); -#elif defined(WRAP) - if (i < 0) - i = 0; - else if (i >= src_w) - i = src_w-1; -#else + /* Ensure i is in range */ if (i < 0) { i = 0; @@ -374,10 +361,11 @@ add_weight(fz_weights *weights, int j, int i, fz_scale_filter *filter, } if (weight == 0) return; -#endif DBUG(("add_weight[%d][%d] = %d(%g) dist=%g\n",j,i,weight,f,dist)); + /* Move j from patch_l...patch_l+patch_w range to 0..patch_w range */ + j -= weights->patch_l; if (weights->new_line) { /* New line */ @@ -428,7 +416,7 @@ add_weight(fz_weights *weights, int j, int i, fz_scale_filter *filter, static void reorder_weights(fz_weights *weights, int j, int src_w) { - int idx = weights->index[j]; + int idx = weights->index[j - weights->patch_l]; int min = weights->index[idx++]; int len = weights->index[idx++]; int max = weights->max_len; @@ -475,7 +463,7 @@ check_weights(fz_weights *weights, int j, int w, float x, float wf) int maxidx = 0; int i; - idx = weights->index[j]; + idx = weights->index[j - weights->patch_l]; idx++; /* min */ len = weights->index[idx++]; @@ -505,7 +493,7 @@ check_weights(fz_weights *weights, int j, int w, float x, float wf) } static fz_weights * -make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int n, int flip) +make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int patch_l, int patch_r, int n, int flip) { fz_weights *weights; float F, G; @@ -525,11 +513,11 @@ make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter * G = src_w / dst_w; } window = filter->width / F; - DBUG(("make_weights src_w=%d x=%g dst_w=%g dst_w_int=%d F=%g window=%g\n", src_w, x, dst_w, dst_w_int, F, window)); - weights = new_weights(ctx, filter, src_w, dst_w, dst_w_int, n, flip); + DBUG(("make_weights src_w=%d x=%g dst_w=%g patch_l=%d patch_r=%d F=%g window=%g\n", src_w, x, dst_w, patch_l, patch_r, F, window)); + weights = new_weights(ctx, filter, src_w, dst_w, patch_r-patch_l, n, flip, patch_l); if (!weights) return NULL; - for (j = 0; j < dst_w_int; j++) + for (j = patch_l; j < patch_r; j++) { /* find the position of the centre of dst[j] in src space */ float centre = (j - x + 0.5f)*src_w/dst_w - 0.5f; @@ -1206,9 +1194,8 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in } #endif /* SINGLE_PIXEL_SPECIALS */ - fz_pixmap * -fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h) +fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_bbox *clip) { fz_scale_filter *filter = &fz_scale_filter_simple; fz_weights *contrib_rows = NULL; @@ -1218,6 +1205,10 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa int max_row, temp_span, temp_rows, row; int dst_w_int, dst_h_int, dst_x_int, dst_y_int; int flip_x, flip_y; + fz_bbox patch; + + fz_var(contrib_cols); + fz_var(contrib_rows); DBUG(("Scale: (%d,%d) to (%g,%g) at (%g,%g)\n",src->w,src->h,w,h,x,y)); @@ -1281,35 +1272,82 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa DBUG(("Result image: (%d,%d) at (%d,%d) (subpix=%g,%g)\n", dst_w_int, dst_h_int, dst_x_int, dst_y_int, x, y)); - /* Step 1: Calculate the weights for columns and rows */ -#ifdef SINGLE_PIXEL_SPECIALS - if (src->w == 1) + /* Step 0: Calculate the patch */ + patch.x0 = 0; + patch.y0 = 0; + patch.x1 = dst_w_int; + patch.y1 = dst_h_int; + if (clip) { - contrib_cols = NULL; + if (flip_x) + { + if (dst_x_int + dst_w_int > clip->x1) + patch.x0 = dst_x_int + dst_w_int - clip->x1; + if (clip->x0 > dst_x_int) + { + patch.x1 = dst_w_int - (clip->x0 - dst_x_int); + dst_x_int = clip->x0; + } + } + else + { + if (dst_x_int + dst_w_int > clip->x1) + patch.x1 = clip->x1 - dst_x_int; + if (clip->x0 > dst_x_int) + { + patch.x0 = clip->x0 - dst_x_int; + dst_x_int += patch.x0; + } + } + + if (flip_y) + { + if (dst_y_int + dst_h_int > clip->y1) + patch.y1 = clip->y1 - dst_y_int; + if (clip->y0 > dst_y_int) + { + patch.y0 = clip->y0 - dst_y_int; + dst_y_int = clip->y0; + } + } + else + { + if (dst_y_int + dst_h_int > clip->y1) + patch.y1 = clip->y1 - dst_y_int; + if (clip->y0 > dst_y_int) + { + patch.y0 = clip->y0 - dst_y_int; + dst_y_int += patch.y0; + } + } } - else -#endif /* SINGLE_PIXEL_SPECIALS */ + if (patch.x0 >= patch.x1 || patch.y0 >= patch.y1) + return NULL; + + fz_try(ctx) { - contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, src->n, flip_x); - if (!contrib_cols) - goto cleanup; - } + /* Step 1: Calculate the weights for columns and rows */ #ifdef SINGLE_PIXEL_SPECIALS - if (src->h == 1) - { - contrib_rows = NULL; - } - else + if (src->w == 1) + contrib_cols = NULL; + else #endif /* SINGLE_PIXEL_SPECIALS */ + contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, patch.x0, patch.x1, src->n, flip_x); +#ifdef SINGLE_PIXEL_SPECIALS + if (src->h == 1) + contrib_rows = NULL; + else +#endif /* SINGLE_PIXEL_SPECIALS */ + contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, patch.y0, patch.y1, src->n, flip_y); + + output = fz_new_pixmap(ctx, src->colorspace, patch.x1 - patch.x0, patch.y1 - patch.y0); + } + fz_catch(ctx) { - contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, src->n, flip_y); - if (!contrib_rows) - goto cleanup; + fz_free(ctx, contrib_cols); + fz_free(ctx, contrib_rows); + fz_rethrow(ctx); } - - assert(!contrib_cols || contrib_cols->count == dst_w_int); - assert(!contrib_rows || contrib_rows->count == dst_h_int); - output = fz_new_pixmap(ctx, src->colorspace, dst_w_int, dst_h_int); output->x = dst_x_int; output->y = dst_y_int; @@ -1321,18 +1359,18 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa if (!contrib_cols) { /* Only 1 pixel in the entire image! */ - duplicate_single_pixel(output->samples, src->samples, src->n, dst_w_int, dst_h_int); + duplicate_single_pixel(output->samples, src->samples, src->n, patch.x1-patch.x0, patch.y1-patch.y0); } else { /* Scale the row once, then copy it. */ - scale_single_row(output->samples, src->samples, contrib_cols, src->w, dst_h_int); + scale_single_row(output->samples, src->samples, contrib_cols, src->w, patch.y1-patch.y0); } } else if (!contrib_cols) { /* Only 1 source pixel wide. Scale the col and duplicate. */ - scale_single_col(output->samples, src->samples, contrib_rows, src->h, src->n, dst_w_int, flip_y); + scale_single_col(output->samples, src->samples, contrib_rows, src->h, src->n, patch.x1-patch.x0, flip_y); } else #endif /* SINGLE_PIXEL_SPECIALS */ @@ -1343,9 +1381,17 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa temp_rows = contrib_rows->max_len; if (temp_span <= 0 || temp_rows > INT_MAX / temp_span) goto cleanup; - temp = fz_malloc_array(ctx, temp_span*temp_rows, sizeof(int)); - if (!temp) - goto cleanup; + fz_try(ctx) + { + temp = fz_calloc(ctx, temp_span*temp_rows, sizeof(int)); + } + fz_catch(ctx) + { + fz_drop_pixmap(ctx, output); + fz_free(ctx, contrib_cols); + fz_free(ctx, contrib_rows); + fz_rethrow(ctx); + } switch (src->n) { default: @@ -1361,7 +1407,7 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa row_scale = scale_row_to_temp4; break; } - max_row = 0; + max_row = contrib_rows->index[contrib_rows->index[0]]; for (row = 0; row < contrib_rows->count; row++) { /* diff --git a/draw/draw_simple_scale.c b/draw/draw_simple_scale.c index 178b182f..38b58e96 100644 --- a/draw/draw_simple_scale.c +++ b/draw/draw_simple_scale.c @@ -218,16 +218,17 @@ typedef struct fz_weights_s fz_weights; struct fz_weights_s { - int flip; - int count; - int max_len; - int n; - int new_line; + int flip; /* true if outputting reversed */ + int count; /* number of output pixels we have records for in this table */ + int max_len; /* Maximum number of weights for any one output pixel */ + int n; /* number of components (src->n) */ + int new_line; /* True if no weights for the current output pixel */ + int patch_l; /* How many output pixels we skip over */ int index[1]; }; static fz_weights * -new_weights(fz_context *ctx, fz_scale_filter *filter, int src_w, float dst_w, int dst_w_i, int n, int flip) +new_weights(fz_context *ctx, fz_scale_filter *filter, int src_w, float dst_w, int patch_w, int n, int flip, int patch_l) { int max_len; fz_weights *weights; @@ -249,26 +250,29 @@ new_weights(fz_context *ctx, fz_scale_filter *filter, int src_w, float dst_w, in max_len = 2 * filter->width; } /* We need the size of the struct, - * plus dst_w*sizeof(int) for the index + * plus patch_w*sizeof(int) for the index * plus (2+max_len)*sizeof(int) for the weights * plus room for an extra set of weights for reordering. */ - weights = fz_malloc(ctx, sizeof(*weights)+(max_len+3)*(dst_w_i+1)*sizeof(int)); + weights = fz_malloc(ctx, sizeof(*weights)+(max_len+3)*(patch_w+1)*sizeof(int)); if (!weights) return NULL; weights->count = -1; weights->max_len = max_len; - weights->index[0] = dst_w_i; + weights->index[0] = patch_w; weights->n = n; + weights->patch_l = patch_l; weights->flip = flip; return weights; } +/* j is destination pixel in the patch_l..patch_l+patch_w range */ static void init_weights(fz_weights *weights, int j) { int index; + j -= weights->patch_l; assert(weights->count == j-1); weights->count++; weights->new_line = 1; @@ -316,6 +320,8 @@ add_weight(fz_weights *weights, int j, int i, fz_scale_filter *filter, DBUG(("add_weight[%d][%d] = %d(%g) dist=%g\n",j,i,weight,f,dist)); + /* Move j from patch_l...patch_l+patch_w range to 0..patch_w range */ + j -= weights->patch_l; if (weights->new_line) { /* New line */ @@ -366,7 +372,7 @@ add_weight(fz_weights *weights, int j, int i, fz_scale_filter *filter, static void reorder_weights(fz_weights *weights, int j, int src_w) { - int idx = weights->index[j]; + int idx = weights->index[j - weights->patch_l]; int min = weights->index[idx++]; int len = weights->index[idx++]; int max = weights->max_len; @@ -413,7 +419,7 @@ check_weights(fz_weights *weights, int j, int w, float x, float wf) int maxidx = 0; int i; - idx = weights->index[j]; + idx = weights->index[j - weights->patch_l]; idx++; /* min */ len = weights->index[idx++]; @@ -443,7 +449,7 @@ check_weights(fz_weights *weights, int j, int w, float x, float wf) } static fz_weights * -make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int n, int flip) +make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter *filter, int vertical, int dst_w_int, int patch_l, int patch_r, int n, int flip) { fz_weights *weights; float F, G; @@ -463,11 +469,11 @@ make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter * G = src_w / dst_w; } window = filter->width / F; - DBUG(("make_weights src_w=%d x=%g dst_w=%g dst_w_int=%d F=%g window=%g\n", src_w, x, dst_w, dst_w_int, F, window)); - weights = new_weights(ctx, filter, src_w, dst_w, dst_w_int, n, flip); + DBUG(("make_weights src_w=%d x=%g dst_w=%g patch_l=%d patch_r=%d F=%g window=%g\n", src_w, x, dst_w, patch_l, patch_r, F, window)); + weights = new_weights(ctx, filter, src_w, dst_w, patch_r-patch_l, n, flip, patch_l); if (!weights) return NULL; - for (j = 0; j < dst_w_int; j++) + for (j = patch_l; j < patch_r; j++) { /* find the position of the centre of dst[j] in src space */ float centre = (j - x + 0.5f)*src_w/dst_w - 0.5f; @@ -1167,7 +1173,7 @@ scale_single_col(unsigned char *dst, unsigned char *src, fz_weights *weights, in #endif /* SINGLE_PIXEL_SPECIALS */ fz_pixmap * -fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h) +fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_bbox *clip) { fz_scale_filter *filter = &fz_scale_filter_simple; fz_weights *contrib_rows = NULL; @@ -1177,6 +1183,7 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa int max_row, temp_span, temp_rows, row; int dst_w_int, dst_h_int, dst_x_int, dst_y_int; int flip_x, flip_y; + fz_bbox patch; fz_var(contrib_cols); fz_var(contrib_rows); @@ -1243,6 +1250,58 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa DBUG(("Result image: (%d,%d) at (%d,%d) (subpix=%g,%g)\n", dst_w_int, dst_h_int, dst_x_int, dst_y_int, x, y)); + /* Step 0: Calculate the patch */ + patch.x0 = 0; + patch.y0 = 0; + patch.x1 = dst_w_int; + patch.y1 = dst_h_int; + if (clip) + { + if (flip_x) + { + if (dst_x_int + dst_w_int > clip->x1) + patch.x0 = dst_x_int + dst_w_int - clip->x1; + if (clip->x0 > dst_x_int) + { + patch.x1 = dst_w_int - (clip->x0 - dst_x_int); + dst_x_int = clip->x0; + } + } + else + { + if (dst_x_int + dst_w_int > clip->x1) + patch.x1 = clip->x1 - dst_x_int; + if (clip->x0 > dst_x_int) + { + patch.x0 = clip->x0 - dst_x_int; + dst_x_int += patch.x0; + } + } + + if (flip_y) + { + if (dst_y_int + dst_h_int > clip->y1) + patch.y1 = clip->y1 - dst_y_int; + if (clip->y0 > dst_y_int) + { + patch.y0 = clip->y0 - dst_y_int; + dst_y_int = clip->y0; + } + } + else + { + if (dst_y_int + dst_h_int > clip->y1) + patch.y1 = clip->y1 - dst_y_int; + if (clip->y0 > dst_y_int) + { + patch.y0 = clip->y0 - dst_y_int; + dst_y_int += patch.y0; + } + } + } + if (patch.x0 >= patch.x1 || patch.y0 >= patch.y1) + return NULL; + fz_try(ctx) { /* Step 1: Calculate the weights for columns and rows */ @@ -1251,15 +1310,15 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa contrib_cols = NULL; else #endif /* SINGLE_PIXEL_SPECIALS */ - contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, src->n, flip_x); + contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, dst_w_int, patch.x0, patch.x1, src->n, flip_x); #ifdef SINGLE_PIXEL_SPECIALS if (src->h == 1) contrib_rows = NULL; else #endif /* SINGLE_PIXEL_SPECIALS */ - contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, src->n, flip_y); + contrib_rows = make_weights(ctx, src->h, y, h, filter, 1, dst_h_int, patch.y0, patch.y1, src->n, flip_y); - output = fz_new_pixmap(ctx, src->colorspace, dst_w_int, dst_h_int); + output = fz_new_pixmap(ctx, src->colorspace, patch.x1 - patch.x0, patch.y1 - patch.y0); } fz_catch(ctx) { @@ -1278,18 +1337,18 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa if (!contrib_cols) { /* Only 1 pixel in the entire image! */ - duplicate_single_pixel(output->samples, src->samples, src->n, dst_w_int, dst_h_int); + duplicate_single_pixel(output->samples, src->samples, src->n, patch.x1-patch.x0, patch.y1-patch.y0); } else { /* Scale the row once, then copy it. */ - scale_single_row(output->samples, src->samples, contrib_cols, src->w, dst_h_int); + scale_single_row(output->samples, src->samples, contrib_cols, src->w, patch.y1-patch.y0); } } else if (!contrib_cols) { /* Only 1 source pixel wide. Scale the col and duplicate. */ - scale_single_col(output->samples, src->samples, contrib_rows, src->h, src->n, dst_w_int, flip_y); + scale_single_col(output->samples, src->samples, contrib_rows, src->h, src->n, patch.x1-patch.x0, flip_y); } else #endif /* SINGLE_PIXEL_SPECIALS */ @@ -1326,7 +1385,7 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa row_scale = scale_row_to_temp4; break; } - max_row = 0; + max_row = contrib_rows->index[contrib_rows->index[0]]; for (row = 0; row < contrib_rows->count; row++) { /* diff --git a/fitz/fitz.h b/fitz/fitz.h index 3971f24c..49db7dc2 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -953,7 +953,7 @@ void fz_invert_pixmap(fz_pixmap *pix); void fz_gamma_pixmap(fz_pixmap *pix, float gamma); unsigned int fz_pixmap_size(fz_pixmap *pix); -fz_pixmap *fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h); +fz_pixmap *fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, float h, fz_bbox *clip); void fz_write_pnm(fz_context *ctx, fz_pixmap *pixmap, char *filename); void fz_write_pam(fz_context *ctx, fz_pixmap *pixmap, char *filename, int savealpha); |