Mercurial > hgrepos > Python2 > PyMuPDF
diff mupdf-source/source/fitz/glyph.c @ 2:b50eed0cc0ef upstream
ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4.
The directory name has changed: no version number in the expanded directory now.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Mon, 15 Sep 2025 11:43:07 +0200 |
| parents | |
| children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mupdf-source/source/fitz/glyph.c Mon Sep 15 11:43:07 2025 +0200 @@ -0,0 +1,468 @@ +// Copyright (C) 2004-2021 Artifex Software, Inc. +// +// This file is part of MuPDF. +// +// MuPDF is free software: you can redistribute it and/or modify it under the +// terms of the GNU Affero General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) +// any later version. +// +// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more +// details. +// +// You should have received a copy of the GNU Affero General Public License +// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> +// +// Alternative licensing terms are available from the licensor. +// For commercial licensing, see <https://www.artifex.com/> or contact +// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, +// CA 94129, USA, for further information. + +#include "mupdf/fitz.h" + +#include "glyph-imp.h" +#include "pixmap-imp.h" + +#include <string.h> + +#define RLE_THRESHOLD 256 + +fz_glyph * +fz_keep_glyph(fz_context *ctx, fz_glyph *glyph) +{ + return fz_keep_storable(ctx, &glyph->storable); +} + +void +fz_drop_glyph(fz_context *ctx, fz_glyph *glyph) +{ + fz_drop_storable(ctx, &glyph->storable); +} + +static void +fz_drop_glyph_imp(fz_context *ctx, fz_storable *glyph_) +{ + fz_glyph *glyph = (fz_glyph *)glyph_; + fz_drop_pixmap(ctx, glyph->pixmap); + fz_free(ctx, glyph); +} + +fz_irect +fz_glyph_bbox(fz_context *ctx, fz_glyph *glyph) +{ + fz_irect bbox; + bbox.x0 = glyph->x; + bbox.y0 = glyph->y; + bbox.x1 = glyph->x + glyph->w; + bbox.y1 = glyph->y + glyph->h; + return bbox; +} + +fz_irect +fz_glyph_bbox_no_ctx(fz_glyph *glyph) +{ + fz_irect bbox; + bbox.x0 = glyph->x; + bbox.y0 = glyph->y; + bbox.x1 = glyph->x + glyph->w; + bbox.y1 = glyph->y + glyph->h; + return bbox; +} + +int +fz_glyph_width(fz_context *ctx, fz_glyph *glyph) +{ + return glyph->w; +} + +int +fz_glyph_height(fz_context *ctx, fz_glyph *glyph) +{ + return glyph->h; +} + +#ifndef NDEBUG +#include <stdio.h> + +void +fz_dump_glyph(fz_glyph *glyph) +{ + int x, y; + + if (glyph->pixmap) + { + printf("pixmap glyph\n"); + return; + } + printf("glyph: %dx%d @ (%d,%d)\n", glyph->w, glyph->h, glyph->x, glyph->y); + + for (y = 0; y < glyph->h; y++) + { + int offset = ((int *)(glyph->data))[y]; + if (offset >= 0) + { + int extend = 0; + int eol = 0; + x = glyph->w; + do + { + int v = glyph->data[offset++]; + int len; + char c; + switch(v&3) + { + case 0: /* extend */ + extend = v>>2; + len = 0; + break; + case 1: /* Transparent pixels */ + len = 1 + (v>>2) + (extend<<6); + extend = 0; + c = '.'; + break; + case 2: /* Solid pixels */ + len = 1 + (v>>3) + (extend<<5); + extend = 0; + eol = v & 4; + c = (eol ? '$' :'#'); + break; + default: /* Intermediate pixels */ + len = 1 + (v>>3) + (extend<<5); + extend = 0; + offset += len; + eol = v & 4; + c = (eol ? '!' : '?'); + break; + } + x -= len; + while (len--) + fputc(c, stdout); + if (eol) + break; + } + while (x > 0); + } + printf("\n"); + } +} +#endif + +fz_glyph * +fz_new_glyph_from_pixmap(fz_context *ctx, fz_pixmap *pix) +{ + fz_glyph *glyph = NULL; + + if (pix == NULL) + return NULL; + + fz_var(glyph); + + fz_try(ctx) + { + if (pix->n != 1 || pix->w * pix->h < RLE_THRESHOLD) + { + glyph = fz_malloc_struct(ctx, fz_glyph); + FZ_INIT_STORABLE(glyph, 1, fz_drop_glyph_imp); + glyph->x = pix->x; + glyph->y = pix->y; + glyph->w = pix->w; + glyph->h = pix->h; + glyph->size = fz_pixmap_size(ctx, pix); + glyph->pixmap = fz_keep_pixmap(ctx, pix); + } + else + glyph = fz_new_glyph_from_8bpp_data(ctx, pix->x, pix->y, pix->w, pix->h, pix->samples, pix->stride); + } + fz_always(ctx) + { + fz_drop_pixmap(ctx, pix); + } + fz_catch(ctx) + { + fz_rethrow(ctx); + } + + return glyph; +} + +fz_glyph * +fz_new_glyph_from_8bpp_data(fz_context *ctx, int x, int y, int w, int h, unsigned char *sp, int span) +{ + fz_glyph *glyph = NULL; + fz_pixmap *pix = NULL; + int size, fill, yy; + unsigned char *orig_sp = sp; + + fz_var(glyph); + fz_var(pix); + + fz_try(ctx) + { + /* We start out by allocating space as large as the pixmap. + * If we need more than that give up on using RLE. We can + * never hope to beat the pixmap for really small sizes. */ + if (w <= 6 || w * h < RLE_THRESHOLD) + goto try_pixmap; + + size = h * w; + fill = h * sizeof(int); + glyph = Memento_label(fz_malloc(ctx, sizeof(fz_glyph) + size), "fz_glyph(8)"); + FZ_INIT_STORABLE(glyph, 1, fz_drop_glyph_imp); + glyph->x = x; + glyph->y = y; + glyph->w = w; + glyph->h = h; + glyph->pixmap = NULL; + if (h == 0) + { + glyph->size = 0; + break; + } + for (yy=0; yy < h; yy++) + { + int nonblankfill = fill; + int nonblankfill_end = fill; + int linefill = fill; + int ww = w; + do + { + int code; + int len = ww; + int needed; + unsigned char *ep; + switch (*sp) + { + case 0: + if (len > 0x1000) + len = 0x1000; + ep = sp+len; + while (++sp != ep && *sp == 0); + code = 1; + len -= ep-sp; + ww -= len; + needed = fill + 1 + (len > 0x40); + break; + case 255: + if (len > 0x800) + len = 0x800; + ep = sp+len; + while (++sp != ep && *sp == 255); + code = 2; + len -= ep-sp; + ww -= len; + needed = fill + 1 + (len > 0x20); + break; + default: + { + unsigned char c; + if (len > 0x800) + len = 0x800; + ep = sp+len; + while (++sp != ep && (c = *sp) != 255 && c != 0); + len -= ep-sp; + ww -= len; + needed = fill + 1 + len + (len > 0x20); + code = 3; + } + } + if (needed > size) + goto try_pixmap; + if (code == 1) + { + if (len > 0x40) + glyph->data[fill++] = ((len-1)>>6)<<2; + glyph->data[fill++] = 1 | (((len-1)&63)<<2); + } + else + { + if (len > 0x20) + glyph->data[fill++] = ((len-1)>>5)<<2; + nonblankfill = fill; + glyph->data[fill++] = code | (((len-1)&31)<<3); + if (code == 3) + { + memcpy(&glyph->data[fill], sp - len, len); + fill += len; + } + nonblankfill_end = fill; + } + } + while (ww > 0); + if (nonblankfill_end == linefill) + { + ((int *)(glyph->data))[yy] = -1; + fill = linefill; + } + else + { + glyph->data[nonblankfill] |= 4; + fill = nonblankfill_end; + ((int *)(glyph->data))[yy] = linefill; + } + sp += span - w; + } + if (fill != size) + { + glyph = fz_realloc(ctx, glyph, sizeof(fz_glyph) + fill); + size = fill; + } + glyph->size = size; + break; + + /* Nasty use of a goto here, but it saves us having to exit + * and reenter the try context, and this routine is speed + * critical. */ +try_pixmap: + glyph = Memento_label(fz_realloc(ctx, glyph, sizeof(fz_glyph)), "fz_glyph(8r)"); + FZ_INIT_STORABLE(glyph, 1, fz_drop_glyph_imp); + pix = fz_new_pixmap_from_8bpp_data(ctx, x, y, w, h, orig_sp, span); + glyph->x = pix->x; + glyph->y = pix->y; + glyph->w = pix->w; + glyph->h = pix->h; + glyph->size = fz_pixmap_size(ctx, pix); + glyph->pixmap = pix; + } + fz_catch(ctx) + { + fz_drop_pixmap(ctx, pix); + fz_free(ctx, glyph); + fz_rethrow(ctx); + } + + return glyph; +} + +fz_glyph * +fz_new_glyph_from_1bpp_data(fz_context *ctx, int x, int y, int w, int h, unsigned char *sp, int span) +{ + fz_pixmap *pix = NULL; + fz_glyph *glyph = NULL; + int size, fill, yy; + unsigned char *orig_sp = sp; + + fz_var(glyph); + fz_var(pix); + + fz_try(ctx) + { + /* We start out by allocating space as large as the pixmap. + * If we need more than that give up on using RLE. We can + * never hope to beat the pixmap for really small sizes. */ + if (w <= 6 || w * h < RLE_THRESHOLD) + goto try_pixmap; + + size = h * w; + fill = h * sizeof(int); + glyph = Memento_label(fz_malloc(ctx, sizeof(fz_glyph) + size), "fz_glyph(1)"); + FZ_INIT_STORABLE(glyph, 1, fz_drop_glyph_imp); + glyph->x = x; + glyph->y = y; + glyph->w = w; + glyph->h = h; + glyph->pixmap = NULL; + if (h == 0) + { + glyph->size = 0; + break; + } + for (yy=0; yy < h; yy++) + { + int nonblankfill = fill; + int nonblankfill_end = fill; + int linefill = fill; + int ww = w; + int bit = 0x80; + do + { + int len = 0; + int needed; + int b = *sp & bit; + bit >>= 1; + if (bit == 0) + bit = 0x80, sp++; + ww--; + if (b == 0) + { + while (ww > 0 && len < 0xfff && (*sp & bit) == 0) + { + bit >>= 1; + if (bit == 0) + bit = 0x80, sp++; + len++; + ww--; + } + needed = fill + (len >= 0x40) + 1; + if (needed > size) + goto try_pixmap; + if (len >= 0x40) + glyph->data[fill++] = (len>>6)<<2; + glyph->data[fill++] = 1 | ((len&63)<<2); + } + else + { + while (ww > 0 && len < 0x7ff && (*sp & bit) != 0) + { + bit >>= 1; + if (bit == 0) + bit = 0x80, sp++; + len++; + ww--; + } + needed = fill + (len >= 0x20) + 1; + if (needed > size) + goto try_pixmap; + if (len >= 0x20) + glyph->data[fill++] = (len>>5)<<2; + nonblankfill = fill; + glyph->data[fill++] = 2 | ((len&31)<<3); + nonblankfill_end = fill; + } + } + while (ww > 0); + if (nonblankfill_end == linefill) + { + ((int *)(glyph->data))[yy] = -1; + fill = linefill; + } + else + { + glyph->data[nonblankfill] |= 4; + fill = nonblankfill_end; + ((int *)(glyph->data))[yy] = linefill; + } + sp += span - (w>>3); + } + if (fill != size) + { + glyph = fz_realloc(ctx, glyph, sizeof(fz_glyph) + fill); + size = fill; + } + glyph->size = size; + break; + + /* Nasty use of a goto here, but it saves us having to exit + * and reenter the try context, and this routine is speed + * critical. */ +try_pixmap: + glyph = fz_realloc(ctx, glyph, sizeof(fz_glyph)); + FZ_INIT_STORABLE(glyph, 1, fz_drop_glyph_imp); + pix = fz_new_pixmap_from_1bpp_data(ctx, x, y, w, h, orig_sp, span); + glyph->x = pix->x; + glyph->y = pix->y; + glyph->w = pix->w; + glyph->h = pix->h; + glyph->size = fz_pixmap_size(ctx, pix); + glyph->pixmap = pix; + } + fz_catch(ctx) + { + fz_drop_pixmap(ctx, pix); + fz_free(ctx, glyph); + fz_rethrow(ctx); + } + + return glyph; +}
