Mercurial > hgrepos > Python2 > PyMuPDF
comparison mupdf-source/source/html/html-font.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 |
comparison
equal
deleted
inserted
replaced
| 1:1d09e1dec1d9 | 2:b50eed0cc0ef |
|---|---|
| 1 // Copyright (C) 2004-2025 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 #include "html-imp.h" | |
| 25 | |
| 26 #include <string.h> | |
| 27 | |
| 28 static fz_font * | |
| 29 fz_load_html_default_font(fz_context *ctx, fz_html_font_set *set, const char *family, int is_bold, int is_italic) | |
| 30 { | |
| 31 int is_mono = !strcmp(family, "monospace"); | |
| 32 int is_sans = !strcmp(family, "sans-serif"); | |
| 33 const char *real_family = is_mono ? "Courier" : is_sans ? "Helvetica" : "Charis SIL"; | |
| 34 const char *backup_family = is_mono ? "Courier" : is_sans ? "Helvetica" : "Times"; | |
| 35 int idx = (is_mono ? 8 : is_sans ? 4 : 0) + is_bold * 2 + is_italic; | |
| 36 if (!set->fonts[idx]) | |
| 37 { | |
| 38 const unsigned char *data; | |
| 39 int size; | |
| 40 | |
| 41 data = fz_lookup_builtin_font(ctx, real_family, is_bold, is_italic, &size); | |
| 42 if (!data) | |
| 43 data = fz_lookup_builtin_font(ctx, backup_family, is_bold, is_italic, &size); | |
| 44 if (!data) | |
| 45 fz_throw(ctx, FZ_ERROR_UNSUPPORTED, "cannot load html font: %s", real_family); | |
| 46 set->fonts[idx] = fz_new_font_from_memory(ctx, NULL, data, size, 0, 1); | |
| 47 fz_font_flags(set->fonts[idx])->is_serif = !is_sans; | |
| 48 } | |
| 49 return set->fonts[idx]; | |
| 50 } | |
| 51 | |
| 52 void | |
| 53 fz_add_html_font_face(fz_context *ctx, fz_html_font_set *set, | |
| 54 const char *family, int is_bold, int is_italic, int is_small_caps, | |
| 55 const char *src, fz_font *font) | |
| 56 { | |
| 57 fz_html_font_face *custom = fz_malloc_struct(ctx, fz_html_font_face); | |
| 58 fz_font_flags_t *flags; | |
| 59 | |
| 60 flags = fz_font_flags(font); | |
| 61 if (is_bold && !flags->is_bold) | |
| 62 flags->fake_bold = 1; | |
| 63 if (is_italic && !flags->is_italic) | |
| 64 flags->fake_italic = 1; | |
| 65 | |
| 66 fz_try(ctx) | |
| 67 { | |
| 68 custom->font = fz_keep_font(ctx, font); | |
| 69 custom->src = fz_strdup(ctx, src); | |
| 70 custom->family = fz_strdup(ctx, family); | |
| 71 custom->is_bold = is_bold; | |
| 72 custom->is_italic = is_italic; | |
| 73 custom->is_small_caps = is_small_caps; | |
| 74 custom->next = set->custom; | |
| 75 set->custom = custom; | |
| 76 } | |
| 77 fz_catch(ctx) | |
| 78 { | |
| 79 fz_drop_font(ctx, custom->font); | |
| 80 fz_free(ctx, custom->src); | |
| 81 fz_free(ctx, custom->family); | |
| 82 fz_rethrow(ctx); | |
| 83 } | |
| 84 } | |
| 85 | |
| 86 fz_font * | |
| 87 fz_load_html_font(fz_context *ctx, fz_html_font_set *set, | |
| 88 const char *family, int is_bold, int is_italic, int is_small_caps) | |
| 89 { | |
| 90 fz_html_font_face *custom; | |
| 91 const unsigned char *data; | |
| 92 int best_score = 0; | |
| 93 fz_font *best_font = NULL; | |
| 94 fz_font *font; | |
| 95 int size; | |
| 96 | |
| 97 for (custom = set->custom; custom; custom = custom->next) | |
| 98 { | |
| 99 if (!strcmp(family, custom->family)) | |
| 100 { | |
| 101 int score = | |
| 102 1 * (is_bold == custom->is_bold) + | |
| 103 2 * (is_italic == custom->is_italic) + | |
| 104 4 * (is_small_caps == custom->is_small_caps); | |
| 105 if (score > best_score) | |
| 106 { | |
| 107 best_score = score; | |
| 108 best_font = custom->font; | |
| 109 } | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 // We found a perfect match! | |
| 114 if (best_font && best_score == 1 + 2 + 4) | |
| 115 return best_font; | |
| 116 | |
| 117 // Try to load a perfect match. | |
| 118 data = fz_lookup_builtin_font(ctx, family, is_bold, is_italic, &size); | |
| 119 if (!data) | |
| 120 data = fz_lookup_builtin_font(ctx, family, 0, 0, &size); | |
| 121 if (data) | |
| 122 { | |
| 123 font = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0); | |
| 124 fz_try(ctx) | |
| 125 fz_add_html_font_face(ctx, set, family, is_bold, is_italic, 0, "<builtin>", font); | |
| 126 fz_always(ctx) | |
| 127 fz_drop_font(ctx, font); | |
| 128 fz_catch(ctx) | |
| 129 fz_rethrow(ctx); | |
| 130 return font; | |
| 131 } | |
| 132 else | |
| 133 { | |
| 134 font = fz_load_system_font(ctx, family, is_bold, is_italic, 0); | |
| 135 if (font) | |
| 136 { | |
| 137 fz_try(ctx) | |
| 138 fz_add_html_font_face(ctx, set, family, is_bold, is_italic, 0, "<system>", font); | |
| 139 fz_always(ctx) | |
| 140 fz_drop_font(ctx, font); | |
| 141 fz_catch(ctx) | |
| 142 fz_rethrow(ctx); | |
| 143 return font; | |
| 144 } | |
| 145 } | |
| 146 | |
| 147 // Use the imperfect match from before. | |
| 148 if (best_font) | |
| 149 return best_font; | |
| 150 | |
| 151 // Handle the "default" font aliases. | |
| 152 if (!strcmp(family, "monospace") || !strcmp(family, "sans-serif") || !strcmp(family, "serif")) | |
| 153 return fz_load_html_default_font(ctx, set, family, is_bold, is_italic); | |
| 154 | |
| 155 return NULL; | |
| 156 } | |
| 157 | |
| 158 fz_html_font_set *fz_new_html_font_set(fz_context *ctx) | |
| 159 { | |
| 160 return fz_malloc_struct(ctx, fz_html_font_set); | |
| 161 } | |
| 162 | |
| 163 void fz_drop_html_font_set(fz_context *ctx, fz_html_font_set *set) | |
| 164 { | |
| 165 fz_html_font_face *font, *next; | |
| 166 int i; | |
| 167 | |
| 168 if (!set) | |
| 169 return; | |
| 170 | |
| 171 font = set->custom; | |
| 172 while (font) | |
| 173 { | |
| 174 next = font->next; | |
| 175 fz_drop_font(ctx, font->font); | |
| 176 fz_free(ctx, font->src); | |
| 177 fz_free(ctx, font->family); | |
| 178 fz_free(ctx, font); | |
| 179 font = next; | |
| 180 } | |
| 181 | |
| 182 for (i = 0; i < (int)nelem(set->fonts); ++i) | |
| 183 fz_drop_font(ctx, set->fonts[i]); | |
| 184 | |
| 185 fz_free(ctx, set); | |
| 186 } |
