|
1 | 1 | #include <stdlib.h>
|
2 |
| -#include <string.h> |
3 | 2 | #include <raylib.h>
|
4 | 3 |
|
5 | 4 | #define SCREEN_WIDTH 800
|
6 | 5 | #define SCREEN_HEIGHT 450
|
7 |
| -#define INITIAL_CAPACITY 65536 // 2^16 - sufficient for most Unicode BMP characters |
8 | 6 |
|
| 7 | +typedef struct { |
| 8 | + int* data; |
| 9 | + int count; |
| 10 | + int capacity; |
| 11 | +} CodepointsArray; |
9 | 12 |
|
10 |
| -static int AddCodeRange(int* codePoints, int* count, int start, int stop) |
11 |
| -{ |
12 |
| - // Verify we have enough capacity for this range |
13 |
| - if (*count + (stop - start + 1) > INITIAL_CAPACITY) { |
14 |
| - return 0; // Not enough space |
| 13 | +static void AddRange(CodepointsArray* array, int start, int stop) { |
| 14 | + int rangeSize = stop - start + 1; |
| 15 | + |
| 16 | + if (array->count + rangeSize > array->capacity) { |
| 17 | + array->capacity = array->count + rangeSize + 1024; |
| 18 | + array->data = (int*)MemRealloc(array->data, array->capacity * sizeof(int)); |
| 19 | + if (!array->data) { |
| 20 | + TraceLog(LOG_ERROR, "FONTUTIL: Memory allocation failed"); |
| 21 | + exit(1); |
| 22 | + } |
15 | 23 | }
|
16 |
| - |
17 |
| - // Add all code points in the range |
18 |
| - while (start <= stop) { |
19 |
| - codePoints[*count] = start; |
20 |
| - (*count)++; |
21 |
| - start++; |
| 24 | + |
| 25 | + for (int i = start; i <= stop; i++) { |
| 26 | + array->data[array->count++] = i; |
22 | 27 | }
|
23 |
| - return 1; // Success |
24 | 28 | }
|
25 | 29 |
|
26 |
| -Font LoadUnicodeFont(const char* fileName, int fontSize, int textureFilter) |
27 |
| -{ |
28 |
| - // Allocate memory for code points (fixed size - no reallocation needed) |
29 |
| - int* codePoints = (int*)malloc(INITIAL_CAPACITY * sizeof(int)); |
30 |
| - if (!codePoints) return GetFontDefault(); |
31 |
| - |
32 |
| - int count = 0; // Tracks number of added code points |
| 30 | +Font LoadUnicodeFont(const char* fileName, int fontSize, int textureFilter) { |
| 31 | + CodepointsArray cp = {0}; |
| 32 | + cp.capacity = 2048; |
| 33 | + cp.data = (int*)MemAlloc(cp.capacity * sizeof(int)); |
33 | 34 |
|
34 |
| - // -------------------------------------------------- |
35 |
| - // 1. BASIC ASCII CHARACTERS |
36 |
| - // -------------------------------------------------- |
37 |
| - AddCodeRange(codePoints, &count, 32, 126); // Basic Latin (letters, digits, punctuation) |
38 |
| - |
39 |
| - // -------------------------------------------------- |
40 |
| - // 2. EUROPEAN LANGUAGES (LATIN SCRIPT) |
41 |
| - // -------------------------------------------------- |
42 |
| - AddCodeRange(codePoints, &count, 0xC0, 0x17F); // Latin-1 Supplement + Latin Extended-A |
43 |
| - AddCodeRange(codePoints, &count, 0x180, 0x24F); // Latin Extended-B |
44 |
| - AddCodeRange(codePoints, &count, 0x1E00, 0x1EFF); // Latin Extended Additional |
45 |
| - AddCodeRange(codePoints, &count, 0x2C60, 0x2C7F); // Latin Extended-C |
46 |
| - |
47 |
| - // -------------------------------------------------- |
48 |
| - // 3. GREEK AND COPTIC |
49 |
| - // -------------------------------------------------- |
50 |
| - AddCodeRange(codePoints, &count, 0x370, 0x3FF); // Greek and Coptic |
51 |
| - AddCodeRange(codePoints, &count, 0x1F00, 0x1FFF); // Greek Extended |
52 |
| - |
53 |
| - // -------------------------------------------------- |
54 |
| - // 4. CYRILLIC SCRIPTS |
55 |
| - // -------------------------------------------------- |
56 |
| - AddCodeRange(codePoints, &count, 0x400, 0x4FF); // Basic Cyrillic |
57 |
| - AddCodeRange(codePoints, &count, 0x500, 0x52F); // Cyrillic Supplement |
58 |
| - AddCodeRange(codePoints, &count, 0x2DE0, 0x2DFF); // Cyrillic Extended-A |
59 |
| - AddCodeRange(codePoints, &count, 0xA640, 0xA69F); // Cyrillic Extended-B |
60 |
| - |
61 |
| - // -------------------------------------------------- |
62 |
| - // 5. CJK LANGUAGES (CHINESE, JAPANESE, KOREAN) |
63 |
| - // -------------------------------------------------- |
64 |
| - AddCodeRange(codePoints, &count, 0x4E00, 0x9FFF); // CJK Unified Ideographs |
65 |
| - AddCodeRange(codePoints, &count, 0x3400, 0x4DBF); // CJK Extension A |
66 |
| - AddCodeRange(codePoints, &count, 0x3000, 0x303F); // CJK Symbols and Punctuation |
67 |
| - AddCodeRange(codePoints, &count, 0x3040, 0x309F); // Hiragana (Japanese) |
68 |
| - AddCodeRange(codePoints, &count, 0x30A0, 0x30FF); // Katakana (Japanese) |
69 |
| - AddCodeRange(codePoints, &count, 0x31F0, 0x31FF); // Katakana Phonetic Extensions |
70 |
| - AddCodeRange(codePoints, &count, 0xFF00, 0xFFEF); // Halfwidth and Fullwidth Forms |
71 |
| - AddCodeRange(codePoints, &count, 0xAC00, 0xD7AF); // Hangul Syllables (Korean) |
72 |
| - AddCodeRange(codePoints, &count, 0x1100, 0x11FF); // Hangul Jamo |
73 |
| - |
74 |
| - // -------------------------------------------------- |
75 |
| - // 6. SOUTHEAST ASIAN LANGUAGES |
76 |
| - // -------------------------------------------------- |
77 |
| - AddCodeRange(codePoints, &count, 0x0E00, 0x0E7F); // Thai |
78 |
| - AddCodeRange(codePoints, &count, 0x0E80, 0x0EFF); // Lao |
79 |
| - AddCodeRange(codePoints, &count, 0x1780, 0x17FF); // Khmer |
80 |
| - AddCodeRange(codePoints, &count, 0x1000, 0x109F); // Myanmar |
81 |
| - AddCodeRange(codePoints, &count, 0x1980, 0x19DF); // New Tai Lue |
82 |
| - |
83 |
| - // -------------------------------------------------- |
84 |
| - // 7. INDIAN SUBCONTINENT LANGUAGES |
85 |
| - // -------------------------------------------------- |
86 |
| - AddCodeRange(codePoints, &count, 0x900, 0x97F); // Devanagari (Hindi, Sanskrit) |
87 |
| - AddCodeRange(codePoints, &count, 0x980, 0x9FF); // Bengali |
88 |
| - AddCodeRange(codePoints, &count, 0xA00, 0xA7F); // Gurmukhi (Punjabi) |
89 |
| - AddCodeRange(codePoints, &count, 0xA80, 0xAFF); // Gujarati |
90 |
| - AddCodeRange(codePoints, &count, 0xB00, 0xB7F); // Oriya |
91 |
| - AddCodeRange(codePoints, &count, 0xB80, 0xBFF); // Tamil |
92 |
| - AddCodeRange(codePoints, &count, 0xC00, 0xC7F); // Telugu |
93 |
| - AddCodeRange(codePoints, &count, 0xC80, 0xCFF); // Kannada |
94 |
| - AddCodeRange(codePoints, &count, 0xD00, 0xD7F); // Malayalam |
95 |
| - AddCodeRange(codePoints, &count, 0xD80, 0xDFF); // Sinhala |
96 |
| - |
97 |
| - // -------------------------------------------------- |
98 |
| - // 8. MIDDLE EASTERN LANGUAGES |
99 |
| - // -------------------------------------------------- |
100 |
| - AddCodeRange(codePoints, &count, 0x600, 0x6FF); // Arabic |
101 |
| - AddCodeRange(codePoints, &count, 0x750, 0x77F); // Arabic Supplement |
102 |
| - AddCodeRange(codePoints, &count, 0x8A0, 0x8FF); // Arabic Extended-A |
103 |
| - AddCodeRange(codePoints, &count, 0xFB50, 0xFDFF); // Arabic Presentation Forms-A |
104 |
| - AddCodeRange(codePoints, &count, 0x5D0, 0x5EA); // Hebrew |
105 |
| - AddCodeRange(codePoints, &count, 0x591, 0x5C7); // Hebrew Extended |
106 |
| - AddCodeRange(codePoints, &count, 0x7C0, 0x7FF); // N'Ko |
107 |
| - AddCodeRange(codePoints, &count, 0x640, 0x6FF); // Syriac |
108 |
| - |
109 |
| - // -------------------------------------------------- |
110 |
| - // 9. AFRICAN LANGUAGES |
111 |
| - // -------------------------------------------------- |
112 |
| - AddCodeRange(codePoints, &count, 0x2C80, 0x2CFF); // Coptic |
113 |
| - AddCodeRange(codePoints, &count, 0x2D30, 0x2D7F); // Tifinagh |
114 |
| - AddCodeRange(codePoints, &count, 0xA6A0, 0xA6FF); // Bamum |
115 |
| - AddCodeRange(codePoints, &count, 0xAB00, 0xAB2F); // Ethiopic Extended |
116 |
| - |
117 |
| - // -------------------------------------------------- |
118 |
| - // 10. SPECIAL CHARACTERS AND SYMBOLS |
119 |
| - // -------------------------------------------------- |
120 |
| - AddCodeRange(codePoints, &count, 0x300, 0x36F); // Combining Diacritical Marks |
121 |
| - AddCodeRange(codePoints, &count, 0x1DC0, 0x1DFF); // Combining Diacritical Marks Supplement |
122 |
| - AddCodeRange(codePoints, &count, 0x2000, 0x206F); // General Punctuation |
123 |
| - AddCodeRange(codePoints, &count, 0x20A0, 0x20CF); // Currency Symbols |
124 |
| - AddCodeRange(codePoints, &count, 0x2100, 0x214F); // Letterlike Symbols |
125 |
| - AddCodeRange(codePoints, &count, 0x2190, 0x21FF); // Arrows |
126 |
| - AddCodeRange(codePoints, &count, 0x2200, 0x22FF); // Mathematical Operators |
127 |
| - |
128 |
| - Font result = {0}; |
| 35 | + if (!cp.data) { |
| 36 | + TraceLog(LOG_ERROR, "FONTUTIL: Initial allocation failed"); |
| 37 | + return GetFontDefault(); |
| 38 | + } |
| 39 | + |
| 40 | + // Basic ASCII |
| 41 | + AddRange(&cp, 32, 126); |
| 42 | + |
| 43 | + // European Languages |
| 44 | + AddRange(&cp, 0xC0, 0x17F); |
| 45 | + AddRange(&cp, 0x180, 0x24F); |
| 46 | + AddRange(&cp, 0x1E00, 0x1EFF); |
| 47 | + AddRange(&cp, 0x2C60, 0x2C7F); |
| 48 | + |
| 49 | + // Greek |
| 50 | + AddRange(&cp, 0x370, 0x3FF); |
| 51 | + AddRange(&cp, 0x1F00, 0x1FFF); |
| 52 | + |
| 53 | + // Cyrillic |
| 54 | + AddRange(&cp, 0x400, 0x4FF); |
| 55 | + AddRange(&cp, 0x500, 0x52F); |
| 56 | + AddRange(&cp, 0x2DE0, 0x2DFF); |
| 57 | + AddRange(&cp, 0xA640, 0xA69F); |
| 58 | + |
| 59 | + // CJK |
| 60 | + AddRange(&cp, 0x4E00, 0x9FFF); |
| 61 | + AddRange(&cp, 0x3400, 0x4DBF); |
| 62 | + AddRange(&cp, 0x3000, 0x303F); |
| 63 | + AddRange(&cp, 0x3040, 0x309F); |
| 64 | + AddRange(&cp, 0x30A0, 0x30FF); |
| 65 | + AddRange(&cp, 0x31F0, 0x31FF); |
| 66 | + AddRange(&cp, 0xFF00, 0xFFEF); |
| 67 | + AddRange(&cp, 0xAC00, 0xD7AF); |
| 68 | + AddRange(&cp, 0x1100, 0x11FF); |
| 69 | + |
| 70 | + // Other |
| 71 | + AddRange(&cp, 0x900, 0x97F); // Devanagari |
| 72 | + AddRange(&cp, 0x600, 0x6FF); // Arabic |
| 73 | + AddRange(&cp, 0x5D0, 0x5EA); // Hebrew |
| 74 | + |
| 75 | + Font font = {0}; |
129 | 76 |
|
130 |
| - // Attempt to load the font with collected code points |
131 | 77 | if (FileExists(fileName)) {
|
132 |
| - result = LoadFontEx(fileName, fontSize, codePoints, count); |
| 78 | + font = LoadFontEx(fileName, fontSize, cp.data, cp.count); |
133 | 79 | }
|
134 | 80 |
|
135 |
| - // Fallback to default font if loading fails |
136 |
| - if (result.texture.id == 0) { |
137 |
| - result = GetFontDefault(); |
| 81 | + if (font.texture.id == 0) { |
| 82 | + font = GetFontDefault(); |
| 83 | + TraceLog(LOG_WARNING, "FONTUTIL: Using default font"); |
138 | 84 | }
|
139 | 85 |
|
140 |
| - // Apply texture filtering |
141 |
| - SetTextureFilter(result.texture, textureFilter); |
| 86 | + SetTextureFilter(font.texture, textureFilter); |
| 87 | + MemFree(cp.data); |
142 | 88 |
|
143 |
| - // Clean up |
144 |
| - free(codePoints); |
145 |
| - return result; |
| 89 | + return font; |
146 | 90 | }
|
147 | 91 |
|
148 | 92 | /**
|
|
0 commit comments