Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/fitz/draw-rasterize.c @ 3:2c135c81b16c
MERGE: upstream PyMuPDF 1.26.4 with MuPDF 1.26.7
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:44:09 +0200 |
| parents | b50eed0cc0ef |
| children |
comparison
equal
deleted
inserted
replaced
| 0:6015a75abc2d | 3:2c135c81b16c |
|---|---|
| 1 // Copyright (C) 2004-2021 Artifex Software, Inc. | |
| 2 // | |
| 3 // This file is part of MuPDF. | |
| 4 // | |
| 5 // MuPDF is free software: you can redistribute it and/or modify it under the | |
| 6 // terms of the GNU Affero General Public License as published by the Free | |
| 7 // Software Foundation, either version 3 of the License, or (at your option) | |
| 8 // any later version. | |
| 9 // | |
| 10 // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY | |
| 11 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| 12 // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more | |
| 13 // details. | |
| 14 // | |
| 15 // You should have received a copy of the GNU Affero General Public License | |
| 16 // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> | |
| 17 // | |
| 18 // Alternative licensing terms are available from the licensor. | |
| 19 // For commercial licensing, see <https://www.artifex.com/> or contact | |
| 20 // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, | |
| 21 // CA 94129, USA, for further information. | |
| 22 | |
| 23 #include "mupdf/fitz.h" | |
| 24 | |
| 25 #include "draw-imp.h" | |
| 26 #include "pixmap-imp.h" | |
| 27 | |
| 28 #include <string.h> | |
| 29 | |
| 30 void fz_init_aa_context(fz_context *ctx) | |
| 31 { | |
| 32 #ifndef AA_BITS | |
| 33 ctx->aa.hscale = 17; | |
| 34 ctx->aa.vscale = 15; | |
| 35 ctx->aa.scale = 256; | |
| 36 ctx->aa.bits = 8; | |
| 37 ctx->aa.text_bits = 8; | |
| 38 #endif | |
| 39 } | |
| 40 | |
| 41 int | |
| 42 fz_aa_level(fz_context *ctx) | |
| 43 { | |
| 44 return fz_aa_bits; | |
| 45 } | |
| 46 | |
| 47 int | |
| 48 fz_graphics_aa_level(fz_context *ctx) | |
| 49 { | |
| 50 return fz_aa_bits; | |
| 51 } | |
| 52 | |
| 53 int | |
| 54 fz_text_aa_level(fz_context *ctx) | |
| 55 { | |
| 56 return fz_aa_text_bits; | |
| 57 } | |
| 58 | |
| 59 int | |
| 60 fz_rasterizer_graphics_aa_level(fz_rasterizer *ras) | |
| 61 { | |
| 62 return fz_rasterizer_aa_bits(ras); | |
| 63 } | |
| 64 | |
| 65 int | |
| 66 fz_rasterizer_text_aa_level(fz_rasterizer *ras) | |
| 67 { | |
| 68 return fz_rasterizer_aa_text_bits(ras); | |
| 69 } | |
| 70 | |
| 71 void | |
| 72 fz_set_rasterizer_text_aa_level(fz_context *ctx, fz_aa_context *aa, int level) | |
| 73 { | |
| 74 #ifdef AA_BITS | |
| 75 if (level != fz_aa_bits) | |
| 76 { | |
| 77 if (fz_aa_bits == 10) | |
| 78 fz_warn(ctx, "Only the Any-part-of-a-pixel rasterizer was compiled in"); | |
| 79 else if (fz_aa_bits == 9) | |
| 80 fz_warn(ctx, "Only the Centre-of-a-pixel rasterizer was compiled in"); | |
| 81 else | |
| 82 fz_warn(ctx, "Only the %d bit anti-aliasing rasterizer was compiled in", fz_aa_bits); | |
| 83 } | |
| 84 #else | |
| 85 if (level > 8) | |
| 86 aa->text_bits = 0; | |
| 87 else if (level > 6) | |
| 88 aa->text_bits = 8; | |
| 89 else if (level > 4) | |
| 90 aa->text_bits = 6; | |
| 91 else if (level > 2) | |
| 92 aa->text_bits = 4; | |
| 93 else if (level > 0) | |
| 94 aa->text_bits = 2; | |
| 95 else | |
| 96 aa->text_bits = 0; | |
| 97 #endif | |
| 98 } | |
| 99 | |
| 100 void | |
| 101 fz_set_rasterizer_graphics_aa_level(fz_context *ctx, fz_aa_context *aa, int level) | |
| 102 { | |
| 103 #ifdef AA_BITS | |
| 104 if (level != fz_aa_bits) | |
| 105 { | |
| 106 if (fz_aa_bits == 10) | |
| 107 fz_warn(ctx, "Only the Any-part-of-a-pixel rasterizer was compiled in"); | |
| 108 else if (fz_aa_bits == 9) | |
| 109 fz_warn(ctx, "Only the Centre-of-a-pixel rasterizer was compiled in"); | |
| 110 else | |
| 111 fz_warn(ctx, "Only the %d bit anti-aliasing rasterizer was compiled in", fz_aa_bits); | |
| 112 } | |
| 113 #else | |
| 114 if (level == 9 || level == 10) | |
| 115 { | |
| 116 aa->hscale = 1; | |
| 117 aa->vscale = 1; | |
| 118 aa->bits = level; | |
| 119 } | |
| 120 else if (level > 6) | |
| 121 { | |
| 122 aa->hscale = 17; | |
| 123 aa->vscale = 15; | |
| 124 aa->bits = 8; | |
| 125 } | |
| 126 else if (level > 4) | |
| 127 { | |
| 128 aa->hscale = 8; | |
| 129 aa->vscale = 8; | |
| 130 aa->bits = 6; | |
| 131 } | |
| 132 else if (level > 2) | |
| 133 { | |
| 134 aa->hscale = 5; | |
| 135 aa->vscale = 3; | |
| 136 aa->bits = 4; | |
| 137 } | |
| 138 else if (level > 0) | |
| 139 { | |
| 140 aa->hscale = 2; | |
| 141 aa->vscale = 2; | |
| 142 aa->bits = 2; | |
| 143 } | |
| 144 else | |
| 145 { | |
| 146 aa->hscale = 1; | |
| 147 aa->vscale = 1; | |
| 148 aa->bits = 0; | |
| 149 } | |
| 150 aa->scale = 0xFF00 / (aa->hscale * aa->vscale); | |
| 151 #endif | |
| 152 } | |
| 153 | |
| 154 void | |
| 155 fz_set_aa_level(fz_context *ctx, int level) | |
| 156 { | |
| 157 fz_set_rasterizer_graphics_aa_level(ctx, &ctx->aa, level); | |
| 158 fz_set_rasterizer_text_aa_level(ctx, &ctx->aa, level); | |
| 159 } | |
| 160 | |
| 161 void | |
| 162 fz_set_text_aa_level(fz_context *ctx, int level) | |
| 163 { | |
| 164 fz_set_rasterizer_text_aa_level(ctx, &ctx->aa, level); | |
| 165 } | |
| 166 | |
| 167 void | |
| 168 fz_set_graphics_aa_level(fz_context *ctx, int level) | |
| 169 { | |
| 170 fz_set_rasterizer_graphics_aa_level(ctx, &ctx->aa, level); | |
| 171 } | |
| 172 | |
| 173 void | |
| 174 fz_set_graphics_min_line_width(fz_context *ctx, float min_line_width) | |
| 175 { | |
| 176 ctx->aa.min_line_width = min_line_width; | |
| 177 } | |
| 178 | |
| 179 float | |
| 180 fz_graphics_min_line_width(fz_context *ctx) | |
| 181 { | |
| 182 return ctx->aa.min_line_width; | |
| 183 } | |
| 184 | |
| 185 float | |
| 186 fz_rasterizer_graphics_min_line_width(fz_rasterizer *ras) | |
| 187 { | |
| 188 return ras->aa.min_line_width; | |
| 189 } | |
| 190 | |
| 191 fz_irect | |
| 192 fz_bound_rasterizer(fz_context *ctx, const fz_rasterizer *rast) | |
| 193 { | |
| 194 fz_irect bbox; | |
| 195 const int hscale = fz_rasterizer_aa_hscale(rast); | |
| 196 const int vscale = fz_rasterizer_aa_vscale(rast); | |
| 197 | |
| 198 if (rast->bbox.x1 < rast->bbox.x0 || rast->bbox.y1 < rast->bbox.y0) | |
| 199 { | |
| 200 bbox = fz_empty_irect; | |
| 201 } | |
| 202 else | |
| 203 { | |
| 204 bbox.x0 = fz_idiv(rast->bbox.x0, hscale); | |
| 205 bbox.y0 = fz_idiv(rast->bbox.y0, vscale); | |
| 206 bbox.x1 = fz_idiv_up(rast->bbox.x1, hscale); | |
| 207 bbox.y1 = fz_idiv_up(rast->bbox.y1, vscale); | |
| 208 } | |
| 209 return bbox; | |
| 210 } | |
| 211 | |
| 212 fz_rect fz_scissor_rasterizer(fz_context *ctx, const fz_rasterizer *rast) | |
| 213 { | |
| 214 fz_rect r; | |
| 215 const int hscale = fz_rasterizer_aa_hscale(rast); | |
| 216 const int vscale = fz_rasterizer_aa_vscale(rast); | |
| 217 | |
| 218 r.x0 = ((float)rast->clip.x0) / hscale; | |
| 219 r.y0 = ((float)rast->clip.y0) / vscale; | |
| 220 r.x1 = ((float)rast->clip.x1) / hscale; | |
| 221 r.y1 = ((float)rast->clip.y1) / vscale; | |
| 222 | |
| 223 return r; | |
| 224 } | |
| 225 | |
| 226 static fz_irect fz_clip_rasterizer(fz_context *ctx, const fz_rasterizer *rast) | |
| 227 { | |
| 228 fz_irect r; | |
| 229 const int hscale = fz_rasterizer_aa_hscale(rast); | |
| 230 const int vscale = fz_rasterizer_aa_vscale(rast); | |
| 231 | |
| 232 r.x0 = fz_idiv(rast->clip.x0, hscale); | |
| 233 r.y0 = fz_idiv(rast->clip.y0, vscale); | |
| 234 r.x1 = fz_idiv_up(rast->clip.x1, hscale); | |
| 235 r.y1 = fz_idiv_up(rast->clip.y1, vscale); | |
| 236 | |
| 237 return r; | |
| 238 } | |
| 239 | |
| 240 int fz_reset_rasterizer(fz_context *ctx, fz_rasterizer *rast, fz_irect clip) | |
| 241 { | |
| 242 const int hscale = fz_rasterizer_aa_hscale(rast); | |
| 243 const int vscale = fz_rasterizer_aa_vscale(rast); | |
| 244 | |
| 245 if (fz_is_infinite_irect(clip)) | |
| 246 { | |
| 247 rast->clip.x0 = rast->clip.y0 = BBOX_MIN; | |
| 248 rast->clip.x1 = rast->clip.y1 = BBOX_MAX; | |
| 249 } | |
| 250 else { | |
| 251 rast->clip.x0 = clip.x0 * hscale; | |
| 252 rast->clip.x1 = clip.x1 * hscale; | |
| 253 rast->clip.y0 = clip.y0 * vscale; | |
| 254 rast->clip.y1 = clip.y1 * vscale; | |
| 255 } | |
| 256 | |
| 257 rast->bbox.x0 = rast->bbox.y0 = BBOX_MAX; | |
| 258 rast->bbox.x1 = rast->bbox.y1 = BBOX_MIN; | |
| 259 | |
| 260 if (rast->fns.reset) | |
| 261 return rast->fns.reset(ctx, rast); | |
| 262 return 0; | |
| 263 } | |
| 264 | |
| 265 void *fz_new_rasterizer_of_size(fz_context *ctx, int size, const fz_rasterizer_fns *fns) | |
| 266 { | |
| 267 fz_rasterizer *rast = fz_calloc(ctx, 1, size); | |
| 268 | |
| 269 rast->fns = *fns; | |
| 270 rast->clip.x0 = rast->clip.y0 = BBOX_MIN; | |
| 271 rast->clip.x1 = rast->clip.y1 = BBOX_MAX; | |
| 272 | |
| 273 rast->bbox.x0 = rast->bbox.y0 = BBOX_MAX; | |
| 274 rast->bbox.x1 = rast->bbox.y1 = BBOX_MIN; | |
| 275 | |
| 276 return rast; | |
| 277 } | |
| 278 | |
| 279 fz_rasterizer *fz_new_rasterizer(fz_context *ctx, const fz_aa_context *aa) | |
| 280 { | |
| 281 fz_rasterizer *r; | |
| 282 int bits; | |
| 283 | |
| 284 #ifdef AA_BITS | |
| 285 bits = AA_BITS; | |
| 286 #else | |
| 287 if (aa == NULL) | |
| 288 aa = &ctx->aa; | |
| 289 bits = aa->bits; | |
| 290 #endif | |
| 291 if (bits == 10) | |
| 292 r = fz_new_edgebuffer(ctx, FZ_EDGEBUFFER_ANY_PART_OF_PIXEL); | |
| 293 else if (bits == 9) | |
| 294 r = fz_new_edgebuffer(ctx, FZ_EDGEBUFFER_CENTER_OF_PIXEL); | |
| 295 else | |
| 296 r = fz_new_gel(ctx); | |
| 297 #ifndef AA_BITS | |
| 298 r->aa = *aa; | |
| 299 #endif | |
| 300 | |
| 301 return r; | |
| 302 } | |
| 303 | |
| 304 void fz_convert_rasterizer(fz_context *ctx, fz_rasterizer *r, int eofill, fz_pixmap *pix, unsigned char *colorbv, fz_overprint *eop) | |
| 305 { | |
| 306 fz_irect clip = fz_bound_rasterizer(ctx, r); | |
| 307 clip = fz_intersect_irect(clip, fz_pixmap_bbox_no_ctx(pix)); | |
| 308 clip = fz_intersect_irect(clip, fz_clip_rasterizer(ctx, r)); | |
| 309 if (!fz_is_empty_irect(clip)) | |
| 310 r->fns.convert(ctx, r, eofill, &clip, pix, colorbv, eop); | |
| 311 } |
