Codebase list libsdl2-ttf / upstream/2.0.18+git20220508.gaa0659b+dfsg
New upstream version 2.0.18+git20220508.gaa0659b+dfsg Simon McVittie 2 years ago
3 changed file(s) with 391 addition(s) and 97 deletion(s). Raw diff Collapse all Expand all
7474 $(HARFBUZZ_PATH)/src/hb-font.cc \
7575 $(HARFBUZZ_PATH)/src/hb-ft.cc \
7676 $(HARFBUZZ_PATH)/src/hb-number.cc \
77 $(HARFBUZZ_PATH)/src/hb-ms-feature-ranges.cc \
7778 $(HARFBUZZ_PATH)/src/hb-ot-cff1-table.cc \
7879 $(HARFBUZZ_PATH)/src/hb-ot-cff2-table.cc \
7980 $(HARFBUZZ_PATH)/src/hb-ot-face.cc \
139140 $(RC) $< $@
140141
141142 EXTRA_DIST = CHANGES.txt COPYING.txt README.txt \
142 Android.mk \
143 Makefile.os2 \
144 Xcode \
145 VisualC \
146 VisualC-WinRT \
147 version.rc \
148 external \
149 SDL2_ttf.spec \
150 SDL2_ttf.spec.in \
151 SDL2_ttfConfig.cmake \
143 Android.mk Makefile.os2 version.rc \
144 VisualC VisualC-WinRT Xcode external \
145 SDL2_ttf.spec SDL2_ttf.spec.in \
146 SDL2_ttfConfig.cmake \
152147 autogen.sh gcc-fat.sh
153148
154149 noinst_PROGRAMS = showfont glfont
165160
166161 distclean-local:
167162 -rm -rf `find $(srcdir) -name .deps`
168
169163 dist-hook:
170164 -rm -rf `find $(distdir) -name .deps`
171 -rm -rf `find $(distdir)/external -name .git*`
172 -rm -rf `find $(distdir)/external -name .ci*`
173 -rm -rf `find $(distdir)/external/harfbuzz/test`
165 -rm -rf `find $(distdir)/external -name '.git*'`
166 -rm -rf `find $(distdir)/external -name '.ci*'`
167 -rm -rf `find $(distdir)/external -name .dirstamp`
168 -rm -rf $(distdir)/external/harfbuzz/test
190190 #define DIVIDE_BY_255(x) DIVIDE_BY_255_SIGNED(x, 1)
191191
192192
193 #define CACHED_METRICS 0x10
193 #define CACHED_METRICS 0x20
194
194195 #define CACHED_BITMAP 0x01
195196 #define CACHED_PIXMAP 0x02
196197 #define CACHED_COLOR 0x04
197 #define CACHED_SUBPIX 0x08
198 #define CACHED_LCD 0x08
199 #define CACHED_SUBPIX 0x10
198200
199201
200202 typedef struct {
322324 typedef enum {
323325 RENDER_SOLID = 0,
324326 RENDER_SHADED,
325 RENDER_BLENDED
327 RENDER_BLENDED,
328 RENDER_LCD
326329 } render_mode_t;
327330
328331 typedef enum {
347350 SDL_Color fg, SDL_Color bg, Uint32 wrapLength, render_mode_t render_mode);
348351
349352 static SDL_INLINE int Find_GlyphByIndex(TTF_Font *font, FT_UInt idx,
350 int want_bitmap, int want_pixmap, int want_color, int want_subpixel,
353 int want_bitmap, int want_pixmap, int want_color, int want_lcd, int want_subpixel,
351354 int translation, c_glyph **out_glyph, TTF_Image **out_image);
352355
353356 static void Flush_Cache(TTF_Font *font);
419422 dst = (Uint32 *)((Uint8 *)dst + dstskip);
420423 }
421424 }
425 }
426
427 /* Blend with LCD rendering */
428 static SDL_INLINE void BG_Blended_LCD(const TTF_Image *image, Uint32 *destination, Sint32 srcskip, Uint32 dstskip, SDL_Color *fg)
429 {
430 const Uint32 *src = (Uint32 *)image->buffer;
431 Uint32 *dst = destination;
432 Uint32 width = image->width;
433 Uint32 height = image->rows;
434
435 Uint32 tmp, bg;
436 Uint32 r, g, b;
437 Uint8 fg_r, fg_g, fg_b;
438 Uint8 bg_r, bg_g, bg_b;
439 Uint32 bg_a;
440
441 int x, y = 0;
442
443 fg_r = fg->r;
444 fg_g = fg->g;
445 fg_b = fg->b;
446
447 while (height--) {
448 y++;
449 x = 0;
450 /* *INDENT-OFF* */
451 DUFFS_LOOP4(
452 x++;
453 tmp = *src++;
454
455 if (tmp) {
456 bg = *dst;
457
458 bg_a = bg & 0xff000000;
459 bg_r = (bg >> 16) & 0xff;
460 bg_g = (bg >> 8) & 0xff;
461 bg_b = (bg >> 0) & 0xff;
462
463 r = (tmp >> 16) & 0xff;
464 g = (tmp >> 8) & 0xff;
465 b = (tmp >> 0) & 0xff;
466
467 r = fg_r * r + bg_r * (255 - r) + 127;
468 r = DIVIDE_BY_255(r);
469
470 g = fg_g * g + bg_g * (255 - g) + 127;
471 g = DIVIDE_BY_255(g);
472
473 b = fg_b * b + bg_b * (255 - b) + 127;
474 b = DIVIDE_BY_255(b);
475
476 r <<= 16;
477 g <<= 8;
478 b <<= 0;
479
480 *dst = r | g | b | bg_a;
481 }
482 dst++;
483
484 , width);
485 /* *INDENT-ON* */
486 src = (const Uint32 *)((const Uint8 *)src + srcskip);
487 dst = (Uint32 *)((Uint8 *)dst + dstskip);
488 }
489
422490 }
423491
424492 #if TTF_USE_SDF
9491017 /* Wrapped mode with an unbroken line: 'line_width' is greater that 'textbuf->w' */
9501018 line_width = SDL_min(line_width, textbuf->w);
9511019
952 if (render_mode == RENDER_BLENDED) {
1020 if (render_mode == RENDER_BLENDED || render_mode == RENDER_LCD) {
9531021 while (line_thickness--) {
9541022 SDL_memset4(dst, color, line_width);
9551023 dst += textbuf->pitch;
9621030 }
9631031 }
9641032
965 static void clip_glyph(int *_x, int *_y, TTF_Image *image, const SDL_Surface *textbuf)
1033 static void clip_glyph(int *_x, int *_y, TTF_Image *image, const SDL_Surface *textbuf, int is_lcd)
9661034 {
9671035 int above_w;
9681036 int above_h;
9701038 int y = *_y;
9711039
9721040 int srcbpp = 1;
973 if (image->is_color) {
974 /* This isn't tested because colored image never ends up left clipped */
1041 if (image->is_color || is_lcd) {
9751042 srcbpp = 4;
9761043 }
9771044
10411108 #pragma GCC diagnostic push
10421109 #pragma GCC diagnostic ignored "-Wunused-value"
10431110 #endif
1044 #define BUILD_RENDER_LINE(NAME, IS_BLENDED, IS_BLENDED_OPAQUE, WB_WP_WC, WS, BLIT_GLYPH_BLENDED_OPAQUE_OPTIM, BLIT_GLYPH_BLENDED_OPTIM, BLIT_GLYPH_OPTIM) \
1111 #define BUILD_RENDER_LINE(NAME, IS_BLENDED, IS_BLENDED_OPAQUE, IS_LCD, WB_WP_WC, WS, BLIT_GLYPH_BLENDED_OPAQUE_OPTIM, BLIT_GLYPH_BLENDED_OPTIM, BLIT_GLYPH_OPTIM) \
10451112 \
10461113 static SDL_INLINE \
1047 int Render_Line_##NAME(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, Uint8 fg_alpha) \
1114 int Render_Line_##NAME(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) \
10481115 { \
10491116 const int alignment = Get_Alignement() - 1; \
1050 const int bpp = ((IS_BLENDED) ? 4 : 1); \
1117 const int bpp = ((IS_BLENDED || IS_LCD) ? 4 : 1); \
10511118 unsigned int i; \
1119 Uint8 fg_alpha = (fg ? fg->a : 0); \
10521120 for (i = 0; i < font->pos_len; i++) { \
10531121 FT_UInt idx = font->pos_buf[i].index; \
10541122 int x = font->pos_buf[i].x; \
10851153 srcskip = image->pitch - image->width; \
10861154 dstskip = textbuf->pitch - image->width * bpp; \
10871155 /* Render glyph at (x, y) with optimized copy functions */ \
1088 if (!IS_BLENDED || image->is_color == 0) { \
1156 if (IS_LCD) { \
1157 image->buffer = saved_buffer; \
1158 image->buffer += alignment; \
1159 image->width = saved_width; \
1160 dst = (Uint8 *)textbuf->pixels + y * textbuf->pitch + x * bpp; \
1161 /* Compute srcskip, dstskip */ \
1162 srcskip = image->pitch - 4 * image->width; \
1163 dstskip = textbuf->pitch - image->width * bpp; \
1164 BG_Blended_LCD(image, (Uint32 *)dst, srcskip, dstskip, fg); \
1165 } else if (!IS_BLENDED || image->is_color == 0) { \
10891166 if (IS_BLENDED_OPAQUE) { \
10901167 BLIT_GLYPH_BLENDED_OPAQUE_OPTIM(image, (Uint32 *)dst, srcskip, dstskip); \
10911168 } else if (IS_BLENDED) { \
11091186 /* Modify a copy, and clip it */ \
11101187 TTF_Image image_clipped = *image; \
11111188 /* Intersect image glyph at (x,y) with textbuf */ \
1112 clip_glyph(&x, &y, &image_clipped, textbuf); \
1189 clip_glyph(&x, &y, &image_clipped, textbuf, IS_LCD); \
11131190 /* Compute dst */ \
11141191 dst = (Uint8 *)textbuf->pixels + y * textbuf->pitch + x * bpp; \
11151192 /* Compute srcskip, dstskip */ \
11161193 srcskip = image_clipped.pitch - image_clipped.width; \
11171194 dstskip = textbuf->pitch - image_clipped.width * bpp; \
11181195 /* Render glyph at (x, y) */ \
1119 if (!IS_BLENDED || image->is_color == 0) { \
1196 if (IS_LCD) { \
1197 srcskip -= 3 * image_clipped.width; \
1198 BG_Blended_LCD(&image_clipped, (Uint32 *)dst, srcskip, dstskip, fg); \
1199 } else if (!IS_BLENDED || image->is_color == 0) { \
11201200 if (IS_BLENDED_OPAQUE) { \
11211201 BG_Blended_Opaque(&image_clipped, (Uint32 *)dst, srcskip, dstskip); \
11221202 } else if (IS_BLENDED) { \
11391219 } \
11401220 \
11411221
1142 #define BITMAP CACHED_BITMAP, 0, 0
1143 #define PIXMAP 0, CACHED_PIXMAP, 0
1144 #define COLOR 0, 0, CACHED_COLOR
1222 #define BITMAP CACHED_BITMAP, 0, 0, 0
1223 #define PIXMAP 0, CACHED_PIXMAP, 0, 0
1224 #define COLOR 0, 0, CACHED_COLOR, 0
1225 #define LCD 0, 0, 0, CACHED_LCD
11451226
11461227 #define SUBPIX CACHED_SUBPIX
11471228
1148 /* BUILD_RENDER_LINE(NAME, IS_BLENDED, IS_BLENDED_OPAQUE, WANT_BITMAP_PIXMAP_COLOR, WANT_SUBPIXEL, BLIT_GLYPH_BLENDED_OPAQUE_OPTIM, BLIT_GLYPH_BLENDED_OPTIM, BLIT_GLYPH_OPTIM) */
1229 /* BUILD_RENDER_LINE(NAME, IS_BLENDED, IS_BLENDED_OPAQUE, WANT_BITMAP_PIXMAP_COLOR_LCD, WANT_SUBPIXEL, BLIT_GLYPH_BLENDED_OPAQUE_OPTIM, BLIT_GLYPH_BLENDED_OPTIM, BLIT_GLYPH_OPTIM) */
11491230
11501231 #if defined(HAVE_SSE2_INTRINSICS)
1151 BUILD_RENDER_LINE(SSE_Shaded , 0, 0, PIXMAP, 0 , , , BG_SSE )
1152 BUILD_RENDER_LINE(SSE_Blended , 1, 0, COLOR, 0 , , BG_Blended_SSE , )
1153 BUILD_RENDER_LINE(SSE_Blended_Opaque , 1, 1, COLOR, 0 , BG_Blended_Opaque_SSE , , )
1154 BUILD_RENDER_LINE(SSE_Solid , 0, 0, BITMAP, 0 , , , BG_SSE )
1155 BUILD_RENDER_LINE(SSE_Shaded_SP , 0, 0, PIXMAP, SUBPIX, , , BG_SSE )
1156 BUILD_RENDER_LINE(SSE_Blended_SP , 1, 0, COLOR, SUBPIX, , BG_Blended_SSE , )
1157 BUILD_RENDER_LINE(SSE_Blended_Opaque_SP , 1, 1, COLOR, SUBPIX, BG_Blended_Opaque_SSE , , )
1232 BUILD_RENDER_LINE(SSE_Shaded , 0, 0, 0, PIXMAP, 0 , , , BG_SSE )
1233 BUILD_RENDER_LINE(SSE_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended_SSE , )
1234 BUILD_RENDER_LINE(SSE_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque_SSE , , )
1235 BUILD_RENDER_LINE(SSE_Solid , 0, 0, 0, BITMAP, 0 , , , BG_SSE )
1236 BUILD_RENDER_LINE(SSE_Shaded_SP , 0, 0, 0, PIXMAP, SUBPIX, , , BG_SSE )
1237 BUILD_RENDER_LINE(SSE_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended_SSE , )
1238 BUILD_RENDER_LINE(SSE_Blended_Opaque_SP , 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque_SSE , , )
1239 BUILD_RENDER_LINE(SSE_LCD , 0, 0, 1, LCD, 0, , , )
1240 BUILD_RENDER_LINE(SSE_LCD_SP , 0, 0, 1, LCD, SUBPIX, , , )
11581241 #endif
11591242
11601243 #if defined(HAVE_NEON_INTRINSICS)
1161 BUILD_RENDER_LINE(NEON_Shaded , 0, 0, PIXMAP, 0 , , , BG_NEON )
1162 BUILD_RENDER_LINE(NEON_Blended , 1, 0, COLOR, 0 , , BG_Blended_NEON, )
1163 BUILD_RENDER_LINE(NEON_Blended_Opaque , 1, 1, COLOR, 0 , BG_Blended_Opaque_NEON, , )
1164 BUILD_RENDER_LINE(NEON_Solid , 0, 0, BITMAP, 0 , , , BG_NEON )
1165 BUILD_RENDER_LINE(NEON_Shaded_SP , 0, 0, PIXMAP, SUBPIX, , , BG_NEON )
1166 BUILD_RENDER_LINE(NEON_Blended_SP , 1, 0, COLOR, SUBPIX, , BG_Blended_NEON, )
1167 BUILD_RENDER_LINE(NEON_Blended_Opaque_SP, 1, 1, COLOR, SUBPIX, BG_Blended_Opaque_NEON, , )
1244 BUILD_RENDER_LINE(NEON_Shaded , 0, 0, 0, PIXMAP, 0 , , , BG_NEON )
1245 BUILD_RENDER_LINE(NEON_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended_NEON, )
1246 BUILD_RENDER_LINE(NEON_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque_NEON, , )
1247 BUILD_RENDER_LINE(NEON_Solid , 0, 0, 0, BITMAP, 0 , , , BG_NEON )
1248 BUILD_RENDER_LINE(NEON_Shaded_SP , 0, 0, 0, PIXMAP, SUBPIX, , , BG_NEON )
1249 BUILD_RENDER_LINE(NEON_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended_NEON, )
1250 BUILD_RENDER_LINE(NEON_Blended_Opaque_SP, 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque_NEON, , )
1251 BUILD_RENDER_LINE(NEON_LCD , 0, 0, 1, LCD, 0 , , , )
1252 BUILD_RENDER_LINE(NEON_LCD_SP , 0, 0, 1, LCD, SUBPIX, , , )
11681253 #endif
11691254
11701255 #if defined(HAVE_BLIT_GLYPH_64)
1171 BUILD_RENDER_LINE(64_Shaded , 0, 0, PIXMAP, 0 , , , BG_64 )
1172 BUILD_RENDER_LINE(64_Blended , 1, 0, COLOR, 0 , , BG_Blended_32 , )
1173 BUILD_RENDER_LINE(64_Blended_Opaque , 1, 1, COLOR, 0 , BG_Blended_Opaque_32 , , )
1174 BUILD_RENDER_LINE(64_Solid , 0, 0, BITMAP, 0 , , , BG_64 )
1175 BUILD_RENDER_LINE(64_Shaded_SP , 0, 0, PIXMAP, SUBPIX, , , BG_64 )
1176 BUILD_RENDER_LINE(64_Blended_SP , 1, 0, COLOR, SUBPIX, , BG_Blended_32 , )
1177 BUILD_RENDER_LINE(64_Blended_Opaque_SP , 1, 1, COLOR, SUBPIX, BG_Blended_Opaque_32 , , )
1256 BUILD_RENDER_LINE(64_Shaded , 0, 0, 0, PIXMAP, 0 , , , BG_64 )
1257 BUILD_RENDER_LINE(64_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended_32 , )
1258 BUILD_RENDER_LINE(64_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque_32 , , )
1259 BUILD_RENDER_LINE(64_Solid , 0, 0, 0, BITMAP, 0 , , , BG_64 )
1260 BUILD_RENDER_LINE(64_Shaded_SP , 0, 0, 0, PIXMAP, SUBPIX, , , BG_64 )
1261 BUILD_RENDER_LINE(64_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended_32 , )
1262 BUILD_RENDER_LINE(64_Blended_Opaque_SP , 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque_32 , , )
1263 BUILD_RENDER_LINE(64_LCD , 0, 0, 1, LCD, 0 , , , )
1264 BUILD_RENDER_LINE(64_LCD_SP , 0, 0, 1, LCD, SUBPIX, , , )
11781265 #elif defined(HAVE_BLIT_GLYPH_32)
1179 BUILD_RENDER_LINE(32_Shaded , 0, 0, PIXMAP, 0 , , , BG_32 )
1180 BUILD_RENDER_LINE(32_Blended , 1, 0, COLOR, 0 , , BG_Blended_32 , )
1181 BUILD_RENDER_LINE(32_Blended_Opaque , 1, 1, COLOR, 0 , BG_Blended_Opaque_32 , , )
1182 BUILD_RENDER_LINE(32_Solid , 0, 0, BITMAP, 0 , , , BG_32 )
1183 BUILD_RENDER_LINE(32_Shaded_SP , 0, 0, PIXMAP, SUBPIX, , , BG_32 )
1184 BUILD_RENDER_LINE(32_Blended_SP , 1, 0, COLOR, SUBPIX, , BG_Blended_32 , )
1185 BUILD_RENDER_LINE(32_Blended_Opaque_SP , 1, 1, COLOR, SUBPIX, BG_Blended_Opaque_32 , , )
1266 BUILD_RENDER_LINE(32_Shaded , 0, 0, 0, PIXMAP, 0 , , , BG_32 )
1267 BUILD_RENDER_LINE(32_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended_32 , )
1268 BUILD_RENDER_LINE(32_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque_32 , , )
1269 BUILD_RENDER_LINE(32_Solid , 0, 0, 0, BITMAP, 0 , , , BG_32 )
1270 BUILD_RENDER_LINE(32_Shaded_SP , 0, 0, 0, PIXMAP, SUBPIX, , , BG_32 )
1271 BUILD_RENDER_LINE(32_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended_32 , )
1272 BUILD_RENDER_LINE(32_Blended_Opaque_SP , 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque_32 , , )
1273 BUILD_RENDER_LINE(32_LCD , 0, 0, 1, LCD, 0 , , , )
1274 BUILD_RENDER_LINE(32_LCD_SP , 0, 0, 1, LCD, SUBPIX, , , )
11861275 #else
1187 BUILD_RENDER_LINE(8_Shaded , 0, 0, PIXMAP, 0 , , , BG )
1188 BUILD_RENDER_LINE(8_Blended , 1, 0, COLOR, 0 , , BG_Blended , )
1189 BUILD_RENDER_LINE(8_Blended_Opaque , 1, 1, COLOR, 0 , BG_Blended_Opaque , , )
1190 BUILD_RENDER_LINE(8_Solid , 0, 0, BITMAP, 0 , , , BG )
1191 BUILD_RENDER_LINE(8_Shaded_SP , 0, 0, PIXMAP, SUBPIX, , , BG )
1192 BUILD_RENDER_LINE(8_Blended_SP , 1, 0, COLOR, SUBPIX, , BG_Blended , )
1193 BUILD_RENDER_LINE(8_Blended_Opaque_SP , 1, 1, COLOR, SUBPIX, BG_Blended_Opaque , , )
1276 BUILD_RENDER_LINE(8_Shaded , 0, 0, 0, PIXMAP, 0 , , , BG )
1277 BUILD_RENDER_LINE(8_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended , )
1278 BUILD_RENDER_LINE(8_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque , , )
1279 BUILD_RENDER_LINE(8_Solid , 0, 0, 0, BITMAP, 0 , , , BG )
1280 BUILD_RENDER_LINE(8_Shaded_SP , 0, 0, 0, PIXMAP, SUBPIX, , , BG )
1281 BUILD_RENDER_LINE(8_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended , )
1282 BUILD_RENDER_LINE(8_Blended_Opaque_SP , 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque , , )
1283 BUILD_RENDER_LINE(8_LCD , 0, 0, 1, LCD, 0 , , , )
1284 BUILD_RENDER_LINE(8_LCD_SP , 0, 0, 1, LCD, SUBPIX, , , )
11941285 #endif
11951286
11961287
11971288 #if TTF_USE_SDF
1198 static int (*Render_Line_SDF_Shaded)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, Uint8 fg_alpha) = NULL;
1199 BUILD_RENDER_LINE(SDF_Blended , 1, 0, COLOR, 0 , , BG_Blended_SDF , )
1200 BUILD_RENDER_LINE(SDF_Blended_Opaque , 1, 1, COLOR, 0 , BG_Blended_Opaque_SDF , , )
1201 static int (*Render_Line_SDF_Solid)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, Uint8 fg_alpha) = NULL;
1202 static int (*Render_Line_SDF_Shaded_SP)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, Uint8 fg_alpha) = NULL;
1203 BUILD_RENDER_LINE(SDF_Blended_SP , 1, 0, COLOR, SUBPIX, , BG_Blended_SDF , )
1204 BUILD_RENDER_LINE(SDF_Blended_Opaque_SP , 1, 1, COLOR, SUBPIX, BG_Blended_Opaque_SDF , , )
1289 static int (*Render_Line_SDF_Shaded)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) = NULL;
1290 BUILD_RENDER_LINE(SDF_Blended , 1, 0, 0, COLOR, 0 , , BG_Blended_SDF , )
1291 BUILD_RENDER_LINE(SDF_Blended_Opaque , 1, 1, 0, COLOR, 0 , BG_Blended_Opaque_SDF , , )
1292 static int (*Render_Line_SDF_Solid)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) = NULL;
1293 static int (*Render_Line_SDF_Shaded_SP)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) = NULL;
1294 BUILD_RENDER_LINE(SDF_Blended_SP , 1, 0, 0, COLOR, SUBPIX, , BG_Blended_SDF , )
1295 BUILD_RENDER_LINE(SDF_Blended_Opaque_SP , 1, 1, 0, COLOR, SUBPIX, BG_Blended_Opaque_SDF , , )
1296 static int (*Render_Line_SDF_LCD)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) = NULL;
1297 static int (*Render_Line_SDF_LCD_SP)(TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color *fg) = NULL;
12051298 #endif
12061299
12071300 #ifdef __GNUC__
12081301 #pragma GCC diagnostic pop
12091302 #endif
12101303
1211 static SDL_INLINE int Render_Line(const render_mode_t render_mode, int subpixel, TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, Uint8 fg_alpha)
1304 static SDL_INLINE int Render_Line(const render_mode_t render_mode, int subpixel, TTF_Font *font, SDL_Surface *textbuf, int xstart, int ystart, SDL_Color fg)
12121305 {
12131306 /* Render line (pos_buf) to textbuf at (xstart, ystart) */
12141307
12151308 /* Subpixel with RENDER_SOLID doesn't make sense. */
12161309 /* (and 'cached->subpixel.translation' would need to distinguish bitmap/pixmap). */
1217
1218 int is_opaque = (fg_alpha == SDL_ALPHA_OPAQUE);
1310 int is_opaque = (fg.a == SDL_ALPHA_OPAQUE);
12191311
12201312 #define Call_Specific_Render_Line(NAME) \
12211313 if (render_mode == RENDER_SHADED) { \
12221314 if (subpixel == 0) { \
1223 return Render_Line_##NAME##_Shaded(font, textbuf, xstart, ystart, 0); \
1315 return Render_Line_##NAME##_Shaded(font, textbuf, xstart, ystart, NULL); \
12241316 } else { \
1225 return Render_Line_##NAME##_Shaded_SP(font, textbuf, xstart, ystart, 0); \
1317 return Render_Line_##NAME##_Shaded_SP(font, textbuf, xstart, ystart, NULL); \
12261318 } \
12271319 } else if (render_mode == RENDER_BLENDED) { \
12281320 if (is_opaque) { \
12291321 if (subpixel == 0) { \
1230 return Render_Line_##NAME##_Blended_Opaque(font, textbuf, xstart, ystart, 0); \
1322 return Render_Line_##NAME##_Blended_Opaque(font, textbuf, xstart, ystart, NULL); \
12311323 } else { \
1232 return Render_Line_##NAME##_Blended_Opaque_SP(font, textbuf, xstart, ystart, 0); \
1324 return Render_Line_##NAME##_Blended_Opaque_SP(font, textbuf, xstart, ystart, NULL); \
12331325 } \
12341326 } else { \
12351327 if (subpixel == 0) { \
1236 return Render_Line_##NAME##_Blended(font, textbuf, xstart, ystart, fg_alpha); \
1328 return Render_Line_##NAME##_Blended(font, textbuf, xstart, ystart, &fg); \
12371329 } else { \
1238 return Render_Line_##NAME##_Blended_SP(font, textbuf, xstart, ystart, fg_alpha); \
1330 return Render_Line_##NAME##_Blended_SP(font, textbuf, xstart, ystart, &fg); \
12391331 } \
12401332 } \
1333 } else if (render_mode == RENDER_LCD) { \
1334 if (subpixel == 0) { \
1335 return Render_Line_##NAME##_LCD(font, textbuf, xstart, ystart, &fg); \
1336 } else { \
1337 return Render_Line_##NAME##_LCD_SP(font, textbuf, xstart, ystart, &fg); \
1338 } \
12411339 } else { \
1242 return Render_Line_##NAME##_Solid(font, textbuf, xstart, ystart, 0); \
1340 return Render_Line_##NAME##_Solid(font, textbuf, xstart, ystart, NULL); \
12431341 }
12441342
12451343 #if TTF_USE_SDF
14791577
14801578 return textbuf;
14811579 }
1580
1581 static SDL_Surface* Create_Surface_LCD(int width, int height, SDL_Color fg, SDL_Color bg, Uint32 *color)
1582 {
1583 const int alignment = Get_Alignement() - 1;
1584 SDL_Surface *textbuf = NULL;
1585 Uint32 bgcolor;
1586
1587 /* Background color */
1588 bgcolor = (bg.a << 24) | (bg.r << 16) | (bg.g << 8) | bg.b;
1589
1590 /* Underline/Strikethrough color style */
1591 *color = (bg.a << 24) | (fg.r << 16) | (fg.g << 8) | fg.b;
1592
1593 /* Create the target surface if required */
1594 if (width != 0) {
1595 /* Create a surface with memory:
1596 * - pitch is rounded to alignment
1597 * - adress is aligned
1598 */
1599 Sint64 size;
1600 void *pixels, *ptr;
1601 /* Worse case at the end of line pulling 'alignment' extra blank pixels */
1602 int pitch = (width + alignment) * 4;
1603 pitch += alignment;
1604 pitch &= ~alignment;
1605 size = height * pitch + sizeof (void *) + alignment;
1606 if (size < 0 || size > SDL_MAX_SINT32) {
1607 /* Overflow... */
1608 return NULL;
1609 }
1610
1611 ptr = SDL_malloc((size_t)size);
1612 if (ptr == NULL) {
1613 return NULL;
1614 }
1615
1616 /* address is aligned */
1617 pixels = (void *)(((size_t)ptr + sizeof(void *) + alignment) & ~alignment);
1618 ((void **)pixels)[-1] = ptr;
1619
1620 textbuf = SDL_CreateRGBSurfaceWithFormatFrom(pixels, width, height, 0, pitch, SDL_PIXELFORMAT_ARGB8888);
1621 if (textbuf == NULL) {
1622 SDL_free(ptr);
1623 return NULL;
1624 }
1625
1626 /* Let SDL handle the memory allocation */
1627 textbuf->flags &= ~SDL_PREALLOC;
1628 textbuf->flags |= SDL_SIMD_ALIGNED;
1629
1630 /* Initialize with fg and 0 alpha */
1631 SDL_memset4(pixels, bgcolor, (height * pitch) / 4);
1632
1633 /* Support alpha blending */
1634 if (bg.a != SDL_ALPHA_OPAQUE) {
1635 SDL_SetSurfaceBlendMode(textbuf, SDL_BLENDMODE_BLEND);
1636 }
1637 }
1638
1639 return textbuf;
1640 }
1641
14821642
14831643 /* rcg06192001 get linked library's version. */
14841644 const SDL_version* TTF_Linked_Version(void)
19792139 /* Get our glyph shortcut */
19802140 slot = font->face->glyph;
19812141
2142 if (want & CACHED_LCD) {
2143 if (slot->format == FT_GLYPH_FORMAT_BITMAP) {
2144 TTF_SetError("LCD mode not possible with bitmap font");
2145 return -1;
2146 }
2147 }
2148
19822149 /* Get the glyph metrics, always needed */
19832150 if (cached->stored == 0) {
19842151 cached->sz_left = slot->bitmap_left;
20512218 if (((want & CACHED_BITMAP) && !(cached->stored & CACHED_BITMAP)) ||
20522219 ((want & CACHED_PIXMAP) && !(cached->stored & CACHED_PIXMAP)) ||
20532220 ((want & CACHED_COLOR) && !(cached->stored & CACHED_COLOR)) ||
2221 ((want & CACHED_LCD) && !(cached->stored & CACHED_LCD)) ||
20542222 (want & CACHED_SUBPIX)
20552223 ) {
20562224 const int mono = (want & CACHED_BITMAP);
20682236 ft_render_mode = FT_RENDER_MODE_SDF;
20692237 }
20702238 #endif
2239 if ((want & CACHED_LCD)) {
2240 ft_render_mode = FT_RENDER_MODE_LCD;
2241 }
20712242 }
20722243
20732244 /* Subpixel translation, flush previous datas */
21612332 dst->pitch += 3 * dst->width;
21622333 }
21632334 #endif
2335 if (src->pixel_mode == FT_PIXEL_MODE_LCD) {
2336 dst->pitch += 3 * dst->width;
2337 }
21642338
21652339 if (dst->rows != 0) {
21662340 unsigned int i;
22072381 quotient = src->width;
22082382 remainder = 0;
22092383 #endif
2384 } else if (src->pixel_mode == FT_PIXEL_MODE_LCD) {
2385 quotient = src->width / 3;
2386 remainder = 0;
22102387 } else {
22112388 quotient = src->width;
22122389 remainder = 0;
23332510 } else if (src->pixel_mode == FT_PIXEL_MODE_BGRA) {
23342511 SDL_memcpy(dstp, srcp, 4 * src->width);
23352512 #endif
2513 } else if (src->pixel_mode == FT_PIXEL_MODE_LCD) {
2514 while (quotient--) {
2515 Uint8 alpha = 0;
2516 Uint8 r, g, b;
2517 r = *srcp++;
2518 g = *srcp++;
2519 b = *srcp++;
2520 *dstp++ = b;
2521 *dstp++ = g;
2522 *dstp++ = r;
2523 *dstp++ = alpha;
2524 }
23362525 } else {
23372526 #if TTF_USE_SDF
23382527 if (ft_render_mode != FT_RENDER_MODE_SDF) {
24072596 /* Mark that we rendered this format */
24082597 if (mono) {
24092598 cached->stored |= CACHED_BITMAP;
2599 } else if (src->pixel_mode == FT_PIXEL_MODE_LCD) {
2600 cached->stored |= CACHED_LCD;
24102601 } else {
24112602 #if TTF_USE_COLOR
24122603 if (want & CACHED_COLOR) {
24432634 }
24442635
24452636 static SDL_INLINE int Find_GlyphByIndex(TTF_Font *font, FT_UInt idx,
2446 int want_bitmap, int want_pixmap, int want_color, int want_subpixel,
2637 int want_bitmap, int want_pixmap, int want_color, int want_lcd, int want_subpixel,
24472638 int translation, c_glyph **out_glyph, TTF_Image **out_image)
24482639 {
24492640 /* cache size is 256, get key by masking */
24532644 *out_glyph = glyph;
24542645 }
24552646
2456 if (want_pixmap || want_color) {
2647 if (want_pixmap || want_color || want_lcd) {
24572648 *out_image = &glyph->pixmap;
24582649 }
24592650
24662657 /* No a real cache, but if it always advances by integer pixels (eg translation 0 or same as previous),
24672658 * this allows to render as fast as normal mode. */
24682659 int retval;
2469 int want = CACHED_METRICS | want_bitmap | want_pixmap | want_color | want_subpixel;
2660 int want = CACHED_METRICS | want_bitmap | want_pixmap | want_color | want_lcd | want_subpixel;
24702661
24712662 if (glyph->stored && glyph->index != idx) {
24722663 Flush_Glyph(glyph);
24782669
24792670 if ((glyph->stored & want) == want) {
24802671 return 0;
2672 }
2673
2674 if (want_color || want_pixmap || want_lcd) {
2675 if (glyph->stored & (CACHED_COLOR|CACHED_PIXMAP|CACHED_LCD)) {
2676 Flush_Glyph(glyph);
2677 }
24812678 }
24822679
24832680 glyph->index = idx;
24912688 else
24922689 {
24932690 int retval;
2494 const int want = CACHED_METRICS | want_bitmap | want_pixmap | want_color;
2691 const int want = CACHED_METRICS | want_bitmap | want_pixmap | want_color | want_lcd;
24952692
24962693 /* Faster check as it gets inlined */
24972694 if (want_pixmap) {
25062703 if ((glyph->stored & CACHED_COLOR) && glyph->index == idx) {
25072704 return 0;
25082705 }
2706 } else if (want_lcd) {
2707 if ((glyph->stored & CACHED_LCD) && glyph->index == idx) {
2708 return 0;
2709 }
25092710 } else {
25102711 /* Get metrics */
25112712 if (glyph->stored && glyph->index == idx) {
25132714 }
25142715 }
25152716
2516 /* Cache cannot contain both PIXMAP and COLOR (unless COLOR is actually not colored).
2717 /* Cache cannot contain both PIXMAP and COLOR (unless COLOR is actually not colored) and LCD
25172718 So, if it's already used, clear it */
2518 if (want_color || want_pixmap) {
2519 if (glyph->stored & (CACHED_COLOR|CACHED_PIXMAP)) {
2719 if (want_color || want_pixmap || want_lcd) {
2720 if (glyph->stored & (CACHED_COLOR|CACHED_PIXMAP|CACHED_LCD)) {
25202721 Flush_Glyph(glyph);
25212722 }
25222723 }
25562757 static SDL_INLINE int Find_GlyphMetrics(TTF_Font *font, Uint32 ch, c_glyph **out_glyph)
25572758 {
25582759 FT_UInt idx = get_char_index(font, ch);
2559 return Find_GlyphByIndex(font, idx, 0, 0, 0, 0, 0, out_glyph, NULL);
2760 return Find_GlyphByIndex(font, idx, 0, 0, 0, 0, 0, 0, out_glyph, NULL);
25602761 }
25612762
25622763 void TTF_CloseFont(TTF_Font *font)
30163217 continue;
30173218 }
30183219 #endif
3019 if (Find_GlyphByIndex(font, idx, 0, 0, 0, 0, 0, &glyph, NULL) < 0) {
3220 if (Find_GlyphByIndex(font, idx, 0, 0, 0, 0, 0, 0, &glyph, NULL) < 0) {
30203221 goto failure;
30213222 }
30223223
32093410 TTF_CHECK_POINTER(font, NULL);
32103411 TTF_CHECK_POINTER(text, NULL);
32113412
3413 if (render_mode == RENDER_LCD && !FT_IS_SCALABLE(font->face)) {
3414 TTF_SetError("LCD rendering is not available for non-scalable font");
3415 goto failure;
3416 }
3417
32123418 /* Convert input string to default encoding UTF-8 */
32133419 if (str_type == STR_TEXT) {
32143420 utf8_alloc = SDL_stack_alloc(Uint8, LATIN1_to_UTF8_len(text));
32443450 textbuf = Create_Surface_Solid(width, height, fg, &color);
32453451 } else if (render_mode == RENDER_SHADED) {
32463452 textbuf = Create_Surface_Shaded(width, height, fg, bg, &color);
3247 } else { /* render_mode == RENDER_BLENDED */
3453 } else if (render_mode == RENDER_BLENDED) {
32483454 textbuf = Create_Surface_Blended(width, height, fg, &color);
3455 } else { /* render_mode == RENDER_LCD */
3456 textbuf = Create_Surface_LCD(width, height, fg, bg, &color);
32493457 }
32503458
32513459 if (textbuf == NULL) {
32533461 }
32543462
32553463 /* Render one text line to textbuf at (xstart, ystart) */
3256 if (Render_Line(render_mode, font->render_subpixel, font, textbuf, xstart, ystart, fg.a) < 0) {
3464 if (Render_Line(render_mode, font->render_subpixel, font, textbuf, xstart, ystart, fg) < 0) {
32573465 goto failure;
32583466 }
32593467
33613569 return TTF_Render_Internal(font, (const char *)text, STR_UNICODE, fg, fg /* unused */, RENDER_BLENDED);
33623570 }
33633571
3572 SDL_Surface* TTF_RenderText_LCD(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg)
3573 {
3574 return TTF_Render_Internal(font, text, STR_TEXT, fg, bg, RENDER_LCD);
3575 }
3576
3577 SDL_Surface* TTF_RenderUTF8_LCD(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg)
3578 {
3579 return TTF_Render_Internal(font, text, STR_UTF8, fg, bg, RENDER_LCD);
3580 }
3581
3582 SDL_Surface* TTF_RenderUNICODE_LCD(TTF_Font *font, const Uint16 *text, SDL_Color fg, SDL_Color bg)
3583 {
3584 return TTF_Render_Internal(font, (const char *)text, STR_UNICODE, fg, bg, RENDER_LCD);
3585 }
3586
3587 SDL_Surface* TTF_RenderGlyph_LCD(TTF_Font *font, Uint16 ch, SDL_Color fg, SDL_Color bg)
3588 {
3589 return TTF_RenderGlyph32_LCD(font, ch, fg, bg);
3590 }
3591
3592 SDL_Surface* TTF_RenderGlyph32_LCD(TTF_Font *font, Uint32 ch, SDL_Color fg, SDL_Color bg)
3593 {
3594 Uint8 utf8[7];
3595
3596 TTF_CHECK_POINTER(font, NULL);
3597
3598 if (!Char_to_UTF8(ch, utf8)) {
3599 return NULL;
3600 }
3601
3602 return TTF_RenderUTF8_LCD(font, (char *)utf8, fg, bg);
3603 }
3604
33643605 static SDL_bool CharacterIsDelimiter(Uint32 c)
33653606 {
33663607 if (c == ' ' || c == '\t' || c == '\r' || c == '\n') {
33913632 TTF_CHECK_INITIALIZED(NULL);
33923633 TTF_CHECK_POINTER(font, NULL);
33933634 TTF_CHECK_POINTER(text, NULL);
3635
3636 if (render_mode == RENDER_LCD && !FT_IS_SCALABLE(font->face)) {
3637 TTF_SetError("LCD rendering is not available for non-scalable font");
3638 goto failure;
3639 }
33943640
33953641 /* Convert input string to default encoding UTF-8 */
33963642 if (str_type == STR_TEXT) {
35663812 textbuf = Create_Surface_Solid(width, height, fg, &color);
35673813 } else if (render_mode == RENDER_SHADED) {
35683814 textbuf = Create_Surface_Shaded(width, height, fg, bg, &color);
3569 } else { /* render_mode == RENDER_BLENDED */
3815 } else if (render_mode == RENDER_BLENDED) {
35703816 textbuf = Create_Surface_Blended(width, height, fg, &color);
3817 } else { /* render_mode == RENDER_LCD */
3818 textbuf = Create_Surface_LCD(width, height, fg, bg, &color);
35713819 }
35723820
35733821 if (textbuf == NULL) {
35973845 ystart += i * lineskip;
35983846
35993847 /* Render one text line to textbuf at (xstart, ystart) */
3600 if (Render_Line(render_mode, font->render_subpixel, font, textbuf, xstart, ystart, fg.a) < 0) {
3848 if (Render_Line(render_mode, font->render_subpixel, font, textbuf, xstart, ystart, fg) < 0) {
36013849 goto failure;
36023850 }
36033851
36813929 SDL_Surface* TTF_RenderUNICODE_Blended_Wrapped(TTF_Font *font, const Uint16 *text, SDL_Color fg, Uint32 wrapLength)
36823930 {
36833931 return TTF_Render_Wrapped_Internal(font, (const char *)text, STR_UNICODE, fg, fg /* unused */, wrapLength, RENDER_BLENDED);
3932 }
3933
3934 SDL_Surface* TTF_RenderText_LCD_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength)
3935 {
3936 return TTF_Render_Wrapped_Internal(font, text, STR_TEXT, fg, bg, wrapLength, RENDER_LCD);
3937 }
3938
3939 SDL_Surface* TTF_RenderUTF8_LCD_Wrapped(TTF_Font *font, const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength)
3940 {
3941 return TTF_Render_Wrapped_Internal(font, text, STR_UTF8, fg, bg, wrapLength, RENDER_LCD);
3942 }
3943
3944 SDL_Surface* TTF_RenderUNICODE_LCD_Wrapped(TTF_Font *font, const Uint16 *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength)
3945 {
3946 return TTF_Render_Wrapped_Internal(font, (const char *)text, STR_UNICODE, fg, bg, wrapLength, RENDER_LCD);
36843947 }
36853948
36863949 SDL_Surface* TTF_RenderGlyph_Blended(TTF_Font *font, Uint16 ch, SDL_Color fg)
339339 extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph32_Blended(TTF_Font *font,
340340 Uint32 ch, SDL_Color fg);
341341
342 /* Create a 32-bit surface (SDL_PIXELFORMAT_ARGB8888) and render the given text
343 using FreeType LCD rendering, with the given font and colors.
344 This function returns the new surface, or NULL if there was an error.
345 */
346 extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_LCD(TTF_Font *font,
347 const char *text, SDL_Color fg, SDL_Color bg);
348 extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_LCD(TTF_Font *font,
349 const char *text, SDL_Color fg, SDL_Color bg);
350 extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_LCD(TTF_Font *font,
351 const Uint16 *text, SDL_Color fg, SDL_Color bg);
352
353 /* Create a 32-bit surface (SDL_PIXELFORMAT_ARGB8888) and render the given text
354 using FreeType LCD rendering, with the given font and colors.
355 Text is wrapped to multiple lines on line endings and on word boundaries
356 if it extends beyond wrapLength in pixels.
357 This function returns the new surface, or NULL if there was an error.
358 */
359 extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderText_LCD_Wrapped(TTF_Font *font,
360 const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength);
361 extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUTF8_LCD_Wrapped(TTF_Font *font,
362 const char *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength);
363 extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderUNICODE_LCD_Wrapped(TTF_Font *font,
364 const Uint16 *text, SDL_Color fg, SDL_Color bg, Uint32 wrapLength);
365
366 /* Create a 32-bit surface (SDL_PIXELFORMAT_ARGB8888) and render the given text
367 using FreeType LCD rendering, with the given font and colors.
368 The glyph is rendered without any padding or centering in the X
369 direction, and aligned normally in the Y direction.
370 This function returns the new surface, or NULL if there was an error.
371 */
372 extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph_LCD(TTF_Font *font,
373 Uint16 ch, SDL_Color fg, SDL_Color bg);
374 extern DECLSPEC SDL_Surface * SDLCALL TTF_RenderGlyph32_LCD(TTF_Font *font,
375 Uint32 ch, SDL_Color fg, SDL_Color bg);
376
377
342378 /* For compatibility with previous versions, here are the old functions */
343379 #define TTF_RenderText(font, text, fg, bg) \
344380 TTF_RenderText_Shaded(font, text, fg, bg)