Mercurial > emacs
comparison src/font.c @ 103889:82ad563e96ed
(font_vconcat_entity_vectors): New function.
(struct font_sort_data): New member font_driver_preference.
(font_compare): Check font_driver_preference.
(font_sort_entities): The format of the first argument changed.
(font_delete_unmatched): Likewise.
(font_list_entities): The return type changed.
(font_select_entity): The format of the second argument changed.
(font_find_for_lface): Adjusted for the above changes. Don't
suppress the checking of C even if the repertory supports it.
(Flist_fonts): Adjusted for the above changes.
author | Kenichi Handa <handa@m17n.org> |
---|---|
date | Tue, 14 Jul 2009 12:03:16 +0000 |
parents | 1a45bb782f72 |
children | 5ad8c9beecab |
comparison
equal
deleted
inserted
replaced
103888:0cebb3e8f85d | 103889:82ad563e96ed |
---|---|
271 /* The following code is copied from the function intern (in | 271 /* The following code is copied from the function intern (in |
272 lread.c), and modified to suite our purpose. */ | 272 lread.c), and modified to suite our purpose. */ |
273 obarray = Vobarray; | 273 obarray = Vobarray; |
274 if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0) | 274 if (!VECTORP (obarray) || XVECTOR (obarray)->size == 0) |
275 obarray = check_obarray (obarray); | 275 obarray = check_obarray (obarray); |
276 parse_str_as_multibyte (str, len, &nchars, &nbytes); | 276 parse_str_as_multibyte ((unsigned char *) str, len, &nchars, &nbytes); |
277 if (len == nchars || len != nbytes) | 277 if (len == nchars || len != nbytes) |
278 /* CONTENTS contains no multibyte sequences or contains an invalid | 278 /* CONTENTS contains no multibyte sequences or contains an invalid |
279 multibyte sequence. We'll make a unibyte string. */ | 279 multibyte sequence. We'll make a unibyte string. */ |
280 tem = oblookup (obarray, str, len, len); | 280 tem = oblookup (obarray, str, len, len); |
281 else | 281 else |
2278 | 2278 |
2279 return score; | 2279 return score; |
2280 } | 2280 } |
2281 | 2281 |
2282 | 2282 |
2283 /* Concatenate all elements of LIST into one vector. LIST is a list | |
2284 of font-entity vectors. */ | |
2285 | |
2286 static Lisp_Object | |
2287 font_vconcat_entity_vectors (Lisp_Object list) | |
2288 { | |
2289 int nargs = XINT (Flength (list)); | |
2290 Lisp_Object *args = alloca (sizeof (Lisp_Object) * nargs); | |
2291 int i; | |
2292 | |
2293 for (i = 0; i < nargs; i++, list = XCDR (list)) | |
2294 args[i] = XCAR (list); | |
2295 return Fvconcat (nargs, args); | |
2296 } | |
2297 | |
2298 | |
2299 /* The structure for elements being sorted by qsort. */ | |
2300 struct font_sort_data | |
2301 { | |
2302 unsigned score; | |
2303 int font_driver_preference; | |
2304 Lisp_Object entity; | |
2305 }; | |
2306 | |
2307 | |
2283 /* The comparison function for qsort. */ | 2308 /* The comparison function for qsort. */ |
2284 | 2309 |
2285 static int | 2310 static int |
2286 font_compare (d1, d2) | 2311 font_compare (d1, d2) |
2287 const void *d1, *d2; | 2312 const void *d1, *d2; |
2288 { | 2313 { |
2289 return (*(unsigned *) d1 - *(unsigned *) d2); | 2314 const struct font_sort_data *data1 = d1; |
2290 } | 2315 const struct font_sort_data *data2 = d2; |
2291 | 2316 |
2292 | 2317 if (data1->score < data2->score) |
2293 /* The structure for elements being sorted by qsort. */ | 2318 return -1; |
2294 struct font_sort_data | 2319 else if (data1->score > data2->score) |
2295 { | 2320 return 1; |
2296 unsigned score; | 2321 return (data1->font_driver_preference - data2->font_driver_preference); |
2297 Lisp_Object entity; | 2322 } |
2298 }; | 2323 |
2299 | 2324 |
2300 | 2325 /* Sort each font-entity vector in LIST by closeness to font-spec PREFER. |
2301 /* Sort font-entities in vector VEC by closeness to font-spec PREFER. | |
2302 If PREFER specifies a point-size, calculate the corresponding | 2326 If PREFER specifies a point-size, calculate the corresponding |
2303 pixel-size from QCdpi property of PREFER or from the Y-resolution | 2327 pixel-size from QCdpi property of PREFER or from the Y-resolution |
2304 of FRAME before sorting. | 2328 of FRAME before sorting. |
2305 | 2329 |
2306 If BEST-ONLY is nonzero, return the best matching entity (that | 2330 If BEST-ONLY is nonzero, return the best matching entity (that |
2307 supports the character BEST-ONLY if BEST-ONLY is positive, or any | 2331 supports the character BEST-ONLY if BEST-ONLY is positive, or any |
2308 if BEST-ONLY is negative). Otherwise, return the sorted VEC. | 2332 if BEST-ONLY is negative). Otherwise, return the sorted result as |
2309 | 2333 a single vector of font-entities. |
2310 This function does no optimization for the case that the length of | 2334 |
2311 VEC is 1. The caller should avoid calling this in such a case. */ | 2335 This function does no optimization for the case that the total |
2336 number of elements is 1. The caller should avoid calling this in | |
2337 such a case. */ | |
2312 | 2338 |
2313 static Lisp_Object | 2339 static Lisp_Object |
2314 font_sort_entities (vec, prefer, frame, best_only) | 2340 font_sort_entities (list, prefer, frame, best_only) |
2315 Lisp_Object vec, prefer, frame; | 2341 Lisp_Object list, prefer, frame; |
2316 int best_only; | 2342 int best_only; |
2317 { | 2343 { |
2318 Lisp_Object prefer_prop[FONT_SPEC_MAX]; | 2344 Lisp_Object prefer_prop[FONT_SPEC_MAX]; |
2319 int len, i; | 2345 int len, maxlen, i; |
2320 struct font_sort_data *data; | 2346 struct font_sort_data *data; |
2321 unsigned best_score; | 2347 unsigned best_score; |
2322 Lisp_Object best_entity, driver_type; | 2348 Lisp_Object best_entity; |
2323 int driver_order; | |
2324 struct frame *f = XFRAME (frame); | 2349 struct frame *f = XFRAME (frame); |
2325 struct font_driver_list *list; | 2350 Lisp_Object tail, vec; |
2326 USE_SAFE_ALLOCA; | 2351 USE_SAFE_ALLOCA; |
2327 | 2352 |
2328 len = ASIZE (vec); | |
2329 for (i = FONT_WEIGHT_INDEX; i <= FONT_AVGWIDTH_INDEX; i++) | 2353 for (i = FONT_WEIGHT_INDEX; i <= FONT_AVGWIDTH_INDEX; i++) |
2330 prefer_prop[i] = AREF (prefer, i); | 2354 prefer_prop[i] = AREF (prefer, i); |
2331 if (FLOATP (prefer_prop[FONT_SIZE_INDEX])) | 2355 if (FLOATP (prefer_prop[FONT_SIZE_INDEX])) |
2332 prefer_prop[FONT_SIZE_INDEX] | 2356 prefer_prop[FONT_SIZE_INDEX] |
2333 = make_number (font_pixel_size (XFRAME (frame), prefer)); | 2357 = make_number (font_pixel_size (XFRAME (frame), prefer)); |
2334 | 2358 |
2335 /* Scoring and sorting. */ | 2359 if (NILP (XCDR (list))) |
2336 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * len); | 2360 { |
2337 /* We are sure that the length of VEC > 1. */ | 2361 /* What we have to take care of is this single vector. */ |
2338 driver_type = AREF (AREF (vec, 0), FONT_TYPE_INDEX); | 2362 vec = XCAR (list); |
2339 for (driver_order = 0, list = f->font_driver_list; list; | 2363 maxlen = ASIZE (vec); |
2340 driver_order++, list = list->next) | 2364 } |
2341 if (EQ (driver_type, list->driver->type)) | 2365 else if (best_only) |
2342 break; | 2366 { |
2367 /* We don't have to perform sort, so there's no need of creating | |
2368 a single vector. But, we must find the length of the longest | |
2369 vector. */ | |
2370 maxlen = 0; | |
2371 for (tail = list; CONSP (tail); tail = XCDR (tail)) | |
2372 if (maxlen < ASIZE (XCAR (tail))) | |
2373 maxlen = ASIZE (XCAR (tail)); | |
2374 } | |
2375 else | |
2376 { | |
2377 /* We have to create a single vector to sort it. */ | |
2378 vec = font_vconcat_entity_vectors (list); | |
2379 maxlen = ASIZE (vec); | |
2380 } | |
2381 | |
2382 SAFE_ALLOCA (data, struct font_sort_data *, (sizeof *data) * maxlen); | |
2343 best_score = 0xFFFFFFFF; | 2383 best_score = 0xFFFFFFFF; |
2344 best_entity = Qnil; | 2384 best_entity = Qnil; |
2345 for (i = 0; i < len; i++) | 2385 |
2346 { | 2386 for (tail = list; CONSP (tail); tail = XCDR (tail)) |
2347 if (!EQ (driver_type, AREF (AREF (vec, i), FONT_TYPE_INDEX))) | 2387 { |
2348 for (driver_order = 0, list = f->font_driver_list; list; | 2388 int font_driver_preference = 0; |
2349 driver_order++, list = list->next) | 2389 Lisp_Object current_font_driver; |
2350 if (EQ (driver_type, list->driver->type)) | 2390 |
2351 break; | 2391 if (best_only) |
2352 data[i].entity = AREF (vec, i); | 2392 vec = XCAR (tail); |
2353 data[i].score | 2393 len = ASIZE (vec); |
2354 = (best_only <= 0 || font_has_char (f, data[i].entity, best_only) > 0 | 2394 |
2355 ? font_score (data[i].entity, prefer_prop) | driver_order | 2395 /* We are sure that the length of VEC > 0. */ |
2356 : 0xFFFFFFFF); | 2396 current_font_driver = AREF (AREF (vec, 0), FONT_TYPE_INDEX); |
2357 if (best_only && best_score > data[i].score) | 2397 /* Score the elements. */ |
2358 { | |
2359 best_score = data[i].score; | |
2360 best_entity = data[i].entity; | |
2361 if (best_score == 0) | |
2362 break; | |
2363 } | |
2364 } | |
2365 if (! best_only) | |
2366 { | |
2367 qsort (data, len, sizeof *data, font_compare); | |
2368 for (i = 0; i < len; i++) | 2398 for (i = 0; i < len; i++) |
2369 ASET (vec, i, data[i].entity); | 2399 { |
2370 } | 2400 data[i].entity = AREF (vec, i); |
2371 else | 2401 data[i].score |
2372 vec = best_entity; | 2402 = ((best_only <= 0 || font_has_char (f, data[i].entity, best_only) |
2403 > 0) | |
2404 ? font_score (data[i].entity, prefer_prop) | |
2405 : 0xFFFFFFFF); | |
2406 if (best_only && best_score > data[i].score) | |
2407 { | |
2408 best_score = data[i].score; | |
2409 best_entity = data[i].entity; | |
2410 if (best_score == 0) | |
2411 break; | |
2412 } | |
2413 if (! EQ (current_font_driver, AREF (AREF (vec, i), FONT_TYPE_INDEX))) | |
2414 { | |
2415 current_font_driver = AREF (AREF (vec, i), FONT_TYPE_INDEX); | |
2416 font_driver_preference++; | |
2417 } | |
2418 data[i].font_driver_preference = font_driver_preference; | |
2419 } | |
2420 | |
2421 /* Sort if necessary. */ | |
2422 if (! best_only) | |
2423 { | |
2424 qsort (data, len, sizeof *data, font_compare); | |
2425 for (i = 0; i < len; i++) | |
2426 ASET (vec, i, data[i].entity); | |
2427 break; | |
2428 } | |
2429 else | |
2430 vec = best_entity; | |
2431 } | |
2432 | |
2373 SAFE_FREE (); | 2433 SAFE_FREE (); |
2374 | 2434 |
2375 FONT_ADD_LOG ("sort-by", prefer, vec); | 2435 FONT_ADD_LOG ("sort-by", prefer, vec); |
2376 return vec; | 2436 return vec; |
2377 } | 2437 } |
2716 | 2776 |
2717 | 2777 |
2718 static Lisp_Object scratch_font_spec, scratch_font_prefer; | 2778 static Lisp_Object scratch_font_spec, scratch_font_prefer; |
2719 | 2779 |
2720 Lisp_Object | 2780 Lisp_Object |
2721 font_delete_unmatched (list, spec, size) | 2781 font_delete_unmatched (vec, spec, size) |
2722 Lisp_Object list, spec; | 2782 Lisp_Object vec, spec; |
2723 int size; | 2783 int size; |
2724 { | 2784 { |
2725 Lisp_Object entity, val; | 2785 Lisp_Object entity, val; |
2726 enum font_property_index prop; | 2786 enum font_property_index prop; |
2727 | 2787 int i; |
2728 for (val = Qnil; CONSP (list); list = XCDR (list)) | 2788 |
2729 { | 2789 for (val = Qnil, i = ASIZE (vec) - 1; i >= 0; i--) |
2730 entity = XCAR (list); | 2790 { |
2791 entity = AREF (vec, i); | |
2731 for (prop = FONT_WEIGHT_INDEX; prop < FONT_SIZE_INDEX; prop++) | 2792 for (prop = FONT_WEIGHT_INDEX; prop < FONT_SIZE_INDEX; prop++) |
2732 if (INTEGERP (AREF (spec, prop)) | 2793 if (INTEGERP (AREF (spec, prop)) |
2733 && ((XINT (AREF (spec, prop)) >> 8) | 2794 && ((XINT (AREF (spec, prop)) >> 8) |
2734 != (XINT (AREF (entity, prop)) >> 8))) | 2795 != (XINT (AREF (entity, prop)) >> 8))) |
2735 prop = FONT_SPEC_MAX; | 2796 prop = FONT_SPEC_MAX; |
2758 AREF (entity, FONT_AVGWIDTH_INDEX))) | 2819 AREF (entity, FONT_AVGWIDTH_INDEX))) |
2759 prop = FONT_SPEC_MAX; | 2820 prop = FONT_SPEC_MAX; |
2760 if (prop < FONT_SPEC_MAX) | 2821 if (prop < FONT_SPEC_MAX) |
2761 val = Fcons (entity, val); | 2822 val = Fcons (entity, val); |
2762 } | 2823 } |
2763 return Fnreverse (val); | 2824 return (Fvconcat (1, &val)); |
2764 } | 2825 } |
2765 | 2826 |
2766 | 2827 |
2767 /* Return a vector of font-entities matching with SPEC on FRAME. */ | 2828 /* Return a list of vectors of font-entities matching with SPEC on |
2829 FRAME. The elements of the list are in the same of order of | |
2830 font-drivers. */ | |
2768 | 2831 |
2769 Lisp_Object | 2832 Lisp_Object |
2770 font_list_entities (frame, spec) | 2833 font_list_entities (frame, spec) |
2771 Lisp_Object frame, spec; | 2834 Lisp_Object frame, spec; |
2772 { | 2835 { |
2773 FRAME_PTR f = XFRAME (frame); | 2836 FRAME_PTR f = XFRAME (frame); |
2774 struct font_driver_list *driver_list = f->font_driver_list; | 2837 struct font_driver_list *driver_list = f->font_driver_list; |
2775 Lisp_Object ftype, val; | 2838 Lisp_Object ftype, val; |
2776 Lisp_Object *vec; | 2839 Lisp_Object list = Qnil; |
2777 int size; | 2840 int size; |
2778 int need_filtering = 0; | 2841 int need_filtering = 0; |
2779 int i; | 2842 int i; |
2780 | 2843 |
2781 font_assert (FONT_SPEC_P (spec)); | 2844 font_assert (FONT_SPEC_P (spec)); |
2799 /* Skip FONT_SPACING_INDEX */ | 2862 /* Skip FONT_SPACING_INDEX */ |
2800 i++; | 2863 i++; |
2801 } | 2864 } |
2802 ASET (scratch_font_spec, FONT_SPACING_INDEX, AREF (spec, FONT_SPACING_INDEX)); | 2865 ASET (scratch_font_spec, FONT_SPACING_INDEX, AREF (spec, FONT_SPACING_INDEX)); |
2803 ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX)); | 2866 ASET (scratch_font_spec, FONT_EXTRA_INDEX, AREF (spec, FONT_EXTRA_INDEX)); |
2804 | |
2805 vec = alloca (sizeof (Lisp_Object) * num_font_drivers); | |
2806 if (! vec) | |
2807 return null_vector; | |
2808 | 2867 |
2809 for (i = 0; driver_list; driver_list = driver_list->next) | 2868 for (i = 0; driver_list; driver_list = driver_list->next) |
2810 if (driver_list->on | 2869 if (driver_list->on |
2811 && (NILP (ftype) || EQ (driver_list->driver->type, ftype))) | 2870 && (NILP (ftype) || EQ (driver_list->driver->type, ftype))) |
2812 { | 2871 { |
2819 else | 2878 else |
2820 { | 2879 { |
2821 Lisp_Object copy; | 2880 Lisp_Object copy; |
2822 | 2881 |
2823 val = driver_list->driver->list (frame, scratch_font_spec); | 2882 val = driver_list->driver->list (frame, scratch_font_spec); |
2883 if (NILP (val)) | |
2884 val = null_vector; | |
2885 else | |
2886 val = Fvconcat (1, &val); | |
2824 copy = Fcopy_font_spec (scratch_font_spec); | 2887 copy = Fcopy_font_spec (scratch_font_spec); |
2825 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type); | 2888 ASET (copy, FONT_TYPE_INDEX, driver_list->driver->type); |
2826 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache))); | 2889 XSETCDR (cache, Fcons (Fcons (copy, val), XCDR (cache))); |
2827 } | 2890 } |
2828 if (! NILP (val) && need_filtering) | 2891 if (ASIZE (val) > 0 && need_filtering) |
2829 val = font_delete_unmatched (val, spec, size); | 2892 val = font_delete_unmatched (val, spec, size); |
2830 if (! NILP (val)) | 2893 if (ASIZE (val) > 0) |
2831 vec[i++] = val; | 2894 list = Fcons (val, list); |
2832 } | 2895 } |
2833 | 2896 |
2834 val = (i > 0 ? Fvconcat (i, vec) : null_vector); | 2897 list = Fnreverse (list); |
2835 FONT_ADD_LOG ("list", spec, val); | 2898 FONT_ADD_LOG ("list", spec, list); |
2836 return (val); | 2899 return list; |
2837 } | 2900 } |
2838 | 2901 |
2839 | 2902 |
2840 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non | 2903 /* Return a font entity matching with SPEC on FRAME. ATTRS, if non |
2841 nil, is an array of face's attributes, which specifies preferred | 2904 nil, is an array of face's attributes, which specifies preferred |
3177 } | 3240 } |
3178 } | 3241 } |
3179 } | 3242 } |
3180 | 3243 |
3181 | 3244 |
3182 /* Selecte a font from ENTITIES that supports C and matches best with | 3245 /* Selecte a font from ENTITIES (list of font-entity vectors) that |
3183 ATTRS and PIXEL_SIZE. */ | 3246 supports C and matches best with ATTRS and PIXEL_SIZE. */ |
3184 | 3247 |
3185 static Lisp_Object | 3248 static Lisp_Object |
3186 font_select_entity (frame, entities, attrs, pixel_size, c) | 3249 font_select_entity (frame, entities, attrs, pixel_size, c) |
3187 Lisp_Object frame, entities, *attrs; | 3250 Lisp_Object frame, entities, *attrs; |
3188 int pixel_size, c; | 3251 int pixel_size, c; |
3189 { | 3252 { |
3190 Lisp_Object font_entity; | 3253 Lisp_Object font_entity; |
3191 Lisp_Object prefer; | 3254 Lisp_Object prefer; |
3192 Lisp_Object props[FONT_REGISTRY_INDEX + 1] ; | |
3193 int result, i; | 3255 int result, i; |
3194 FRAME_PTR f = XFRAME (frame); | 3256 FRAME_PTR f = XFRAME (frame); |
3195 | 3257 |
3196 if (ASIZE (entities) == 1) | 3258 if (NILP (XCDR (entities)) |
3197 { | 3259 && ASIZE (XCAR (entities)) == 1) |
3198 font_entity = AREF (entities, 0); | 3260 { |
3261 font_entity = AREF (XCAR (entities), 0); | |
3199 if (c < 0 | 3262 if (c < 0 |
3200 || (result = font_has_char (f, font_entity, c)) > 0) | 3263 || (result = font_has_char (f, font_entity, c)) > 0) |
3201 return font_entity; | 3264 return font_entity; |
3202 return Qnil; | 3265 return Qnil; |
3203 } | 3266 } |
3235 Lisp_Object *attrs; | 3298 Lisp_Object *attrs; |
3236 Lisp_Object spec; | 3299 Lisp_Object spec; |
3237 int c; | 3300 int c; |
3238 { | 3301 { |
3239 Lisp_Object work; | 3302 Lisp_Object work; |
3240 Lisp_Object frame, entities, val, props[FONT_REGISTRY_INDEX + 1] ; | 3303 Lisp_Object frame, entities, val; |
3241 Lisp_Object size, foundry[3], *family, registry[3], adstyle[3]; | 3304 Lisp_Object size, foundry[3], *family, registry[3], adstyle[3]; |
3242 int pixel_size; | 3305 int pixel_size; |
3243 int i, j, k, l, result; | 3306 int i, j, k, l; |
3244 | 3307 |
3245 registry[0] = AREF (spec, FONT_REGISTRY_INDEX); | 3308 registry[0] = AREF (spec, FONT_REGISTRY_INDEX); |
3246 if (NILP (registry[0])) | 3309 if (NILP (registry[0])) |
3247 { | 3310 { |
3248 registry[0] = DEFAULT_ENCODING; | 3311 registry[0] = DEFAULT_ENCODING; |
3257 struct charset *encoding, *repertory; | 3320 struct charset *encoding, *repertory; |
3258 | 3321 |
3259 if (font_registry_charsets (AREF (spec, FONT_REGISTRY_INDEX), | 3322 if (font_registry_charsets (AREF (spec, FONT_REGISTRY_INDEX), |
3260 &encoding, &repertory) < 0) | 3323 &encoding, &repertory) < 0) |
3261 return Qnil; | 3324 return Qnil; |
3262 if (repertory) | 3325 if (repertory |
3263 { | 3326 && ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory)) |
3264 if (ENCODE_CHAR (repertory, c) == CHARSET_INVALID_CODE (repertory)) | 3327 return Qnil; |
3265 return Qnil; | |
3266 /* Any font of this registry support C. So, let's | |
3267 suppress the further checking. */ | |
3268 c = -1; | |
3269 } | |
3270 else if (c > encoding->max_char) | 3328 else if (c > encoding->max_char) |
3271 return Qnil; | 3329 return Qnil; |
3272 } | 3330 } |
3273 | 3331 |
3274 work = Fcopy_font_spec (spec); | 3332 work = Fcopy_font_spec (spec); |
3370 ASET (work, FONT_REGISTRY_INDEX, registry[k]); | 3428 ASET (work, FONT_REGISTRY_INDEX, registry[k]); |
3371 for (l = 0; SYMBOLP (adstyle[l]); l++) | 3429 for (l = 0; SYMBOLP (adstyle[l]); l++) |
3372 { | 3430 { |
3373 ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]); | 3431 ASET (work, FONT_ADSTYLE_INDEX, adstyle[l]); |
3374 entities = font_list_entities (frame, work); | 3432 entities = font_list_entities (frame, work); |
3375 if (ASIZE (entities) > 0) | 3433 if (! NILP (entities)) |
3376 { | 3434 { |
3377 val = font_select_entity (frame, entities, | 3435 val = font_select_entity (frame, entities, |
3378 attrs, pixel_size, c); | 3436 attrs, pixel_size, c); |
3379 if (! NILP (val)) | 3437 if (! NILP (val)) |
3380 return val; | 3438 return val; |
4234 control the order of the returned list. Fonts are sorted by | 4292 control the order of the returned list. Fonts are sorted by |
4235 how close they are to PREFER. */) | 4293 how close they are to PREFER. */) |
4236 (font_spec, frame, num, prefer) | 4294 (font_spec, frame, num, prefer) |
4237 Lisp_Object font_spec, frame, num, prefer; | 4295 Lisp_Object font_spec, frame, num, prefer; |
4238 { | 4296 { |
4239 Lisp_Object vec, list, tail; | 4297 Lisp_Object vec, list; |
4240 int n = 0, i, len; | 4298 int n = 0; |
4241 | 4299 |
4242 if (NILP (frame)) | 4300 if (NILP (frame)) |
4243 frame = selected_frame; | 4301 frame = selected_frame; |
4244 CHECK_LIVE_FRAME (frame); | 4302 CHECK_LIVE_FRAME (frame); |
4245 CHECK_FONT_SPEC (font_spec); | 4303 CHECK_FONT_SPEC (font_spec); |
4251 return Qnil; | 4309 return Qnil; |
4252 } | 4310 } |
4253 if (! NILP (prefer)) | 4311 if (! NILP (prefer)) |
4254 CHECK_FONT_SPEC (prefer); | 4312 CHECK_FONT_SPEC (prefer); |
4255 | 4313 |
4256 vec = font_list_entities (frame, font_spec); | 4314 list = font_list_entities (frame, font_spec); |
4257 len = ASIZE (vec); | 4315 if (NILP (list)) |
4258 if (len == 0) | |
4259 return Qnil; | 4316 return Qnil; |
4260 if (len == 1) | 4317 if (NILP (XCDR (list)) |
4261 return Fcons (AREF (vec, 0), Qnil); | 4318 && ASIZE (XCAR (list)) == 1) |
4319 return Fcons (AREF (XCAR (list), 0), Qnil); | |
4262 | 4320 |
4263 if (! NILP (prefer)) | 4321 if (! NILP (prefer)) |
4264 vec = font_sort_entities (vec, prefer, frame, 0); | 4322 vec = font_sort_entities (list, prefer, frame, 0); |
4265 | 4323 else |
4266 list = tail = Fcons (AREF (vec, 0), Qnil); | 4324 vec = font_vconcat_entity_vectors (list); |
4267 if (n == 0 || n > len) | 4325 if (n == 0 || n >= ASIZE (vec)) |
4268 n = len; | 4326 { |
4269 for (i = 1; i < n; i++) | 4327 Lisp_Object args[2]; |
4270 { | 4328 |
4271 Lisp_Object val = Fcons (AREF (vec, i), Qnil); | 4329 args[0] = vec; |
4272 | 4330 args[1] = Qnil; |
4273 XSETCDR (tail, val); | 4331 list = Fappend (2, args); |
4274 tail = val; | 4332 } |
4333 else | |
4334 { | |
4335 for (list = Qnil, n--; n >= 0; n--) | |
4336 list = Fcons (AREF (vec, n), list); | |
4275 } | 4337 } |
4276 return list; | 4338 return list; |
4277 } | 4339 } |
4278 | 4340 |
4279 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0, | 4341 DEFUN ("font-family-list", Ffont_family_list, Sfont_family_list, 0, 1, 0, |
5057 concat2 (equalstr, | 5119 concat2 (equalstr, |
5058 SYMBOL_NAME (XCAR (XCDR (elt))))); | 5120 SYMBOL_NAME (XCAR (XCDR (elt))))); |
5059 } | 5121 } |
5060 arg = val; | 5122 arg = val; |
5061 } | 5123 } |
5124 | |
5125 if (CONSP (result) | |
5126 && VECTORP (XCAR (result)) | |
5127 && ASIZE (XCAR (result)) > 0 | |
5128 && FONTP (AREF (XCAR (result), 0))) | |
5129 result = font_vconcat_entity_vectors (result); | |
5062 if (FONTP (result)) | 5130 if (FONTP (result)) |
5063 { | 5131 { |
5064 val = Ffont_xlfd_name (result, Qt); | 5132 val = Ffont_xlfd_name (result, Qt); |
5065 if (! FONT_SPEC_P (result)) | 5133 if (! FONT_SPEC_P (result)) |
5066 val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)), | 5134 val = concat3 (SYMBOL_NAME (AREF (result, FONT_TYPE_INDEX)), |