diff options
Diffstat (limited to 'draw/draw_simple_scale.c')
-rw-r--r-- | draw/draw_simple_scale.c | 68 |
1 files changed, 46 insertions, 22 deletions
diff --git a/draw/draw_simple_scale.c b/draw/draw_simple_scale.c index 178b182f..cb419126 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 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; @@ -480,7 +486,7 @@ make_weights(fz_context *ctx, int src_w, float x, float dst_w, fz_scale_filter * { add_weight(weights, j, l, filter, x, F, G, src_w, dst_w); } - check_weights(weights, j, dst_w_int, x, dst_w); + check_weights(weights, j, patch_r-patch_l, x, dst_w); if (vertical) { reorder_weights(weights, j, src_w); @@ -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); @@ -1245,21 +1252,38 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa fz_try(ctx) { + /* Step 0: Calculate the patch */ + patch.x0 = 0; + patch.y0 = 0; + patch.x1 = dst_w_int; + patch.y1 = dst_h_int; + if (clip) + { + if (patch.x0 < clip->x0 - dst_x_int) + patch.x0 = clip->x0 - dst_x_int; + if (patch.x1 > clip->x1 - dst_x_int) + patch.x1 = clip->x1 - dst_x_int; + if (patch.y0 < clip->y0 - dst_y_int) + patch.y0 = clip->y0 - dst_y_int; + if (patch.y1 > clip->y1 - dst_y_int) + patch.y1 = clip->y1 - dst_y_int; + } + /* Step 1: Calculate the weights for columns and rows */ #ifdef SINGLE_PIXEL_SPECIALS 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, src->n, flip_x); + contrib_cols = make_weights(ctx, src->w, x, w, filter, 0, 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, 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) { @@ -1267,8 +1291,8 @@ fz_scale_pixmap(fz_context *ctx, fz_pixmap *src, float x, float y, float w, floa fz_free(ctx, contrib_rows); fz_rethrow(ctx); } - output->x = dst_x_int; - output->y = dst_y_int; + output->x = dst_x_int + patch.x0; + output->y = dst_y_int + patch.y0; /* Step 2: Apply the weights */ #ifdef SINGLE_PIXEL_SPECIALS |