SDL  2.0
testime.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
3 
4  This software is provided 'as-is', without any express or implied
5  warranty. In no event will the authors be held liable for any damages
6  arising from the use of this software.
7 
8  Permission is granted to anyone to use this software for any purpose,
9  including commercial applications, and to alter it and redistribute it
10  freely.
11 */
12 /* A simple program to test the Input Method support in the SDL library (2.0+)
13  If you build without SDL_ttf, you can use the GNU Unifont hex file instead.
14  Download at http://unifoundry.com/unifont.html */
15 
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <string.h>
19 
20 #include "SDL.h"
21 #ifdef HAVE_SDL_TTF
22 #include "SDL_ttf.h"
23 #endif
24 
25 #include "SDL_test_common.h"
26 
27 #define DEFAULT_PTSIZE 30
28 #ifdef HAVE_SDL_TTF
29 #ifdef __MACOSX__
30 #define DEFAULT_FONT "/System/Library/Fonts/华文细黑.ttf"
31 #elif __WIN32__
32 /* Some japanese font present on at least Windows 8.1. */
33 #define DEFAULT_FONT "C:\\Windows\\Fonts\\yugothic.ttf"
34 #else
35 #define DEFAULT_FONT "NoDefaultFont.ttf"
36 #endif
37 #else
38 #define DEFAULT_FONT "unifont-9.0.02.hex"
39 #endif
40 #define MAX_TEXT_LENGTH 256
41 
44 static SDL_Color lineColor = {0,0,0,255};
45 static SDL_Color backColor = {255,255,255,255};
46 static SDL_Color textColor = {0,0,0,255};
48 static int cursor = 0;
49 #ifdef HAVE_SDL_TTF
50 static TTF_Font *font;
51 #else
52 #define UNIFONT_MAX_CODEPOINT 0x1ffff
53 #define UNIFONT_NUM_GLYPHS 0x20000
54 /* Using 512x512 textures that are supported everywhere. */
55 #define UNIFONT_TEXTURE_WIDTH 512
56 #define UNIFONT_GLYPHS_IN_ROW (UNIFONT_TEXTURE_WIDTH / 16)
57 #define UNIFONT_GLYPHS_IN_TEXTURE (UNIFONT_GLYPHS_IN_ROW * UNIFONT_GLYPHS_IN_ROW)
58 #define UNIFONT_NUM_TEXTURES ((UNIFONT_NUM_GLYPHS + UNIFONT_GLYPHS_IN_TEXTURE - 1) / UNIFONT_GLYPHS_IN_TEXTURE)
59 #define UNIFONT_TEXTURE_SIZE (UNIFONT_TEXTURE_WIDTH * UNIFONT_TEXTURE_WIDTH * 4)
60 #define UNIFONT_TEXTURE_PITCH (UNIFONT_TEXTURE_WIDTH * 4)
61 #define UNIFONT_DRAW_SCALE 2
62 struct UnifontGlyph {
64  Uint8 data[32];
65 } *unifontGlyph;
68 
69 /* Unifont loading code start */
70 
71 static Uint8 dehex(char c)
72 {
73  if (c >= '0' && c <= '9')
74  return c - '0';
75  else if (c >= 'a' && c <= 'f')
76  return c - 'a' + 10;
77  else if (c >= 'A' && c <= 'F')
78  return c - 'A' + 10;
79  return 255;
80 }
81 
82 static Uint8 dehex2(char c1, char c2)
83 {
84  return (dehex(c1) << 4) | dehex(c2);
85 }
86 
87 static Uint8 validate_hex(const char *cp, size_t len, Uint32 *np)
88 {
89  Uint32 n = 0;
90  for (; len > 0; cp++, len--)
91  {
92  Uint8 c = dehex(*cp);
93  if (c == 255)
94  return 0;
95  n = (n << 4) | c;
96  }
97  if (np != NULL)
98  *np = n;
99  return 1;
100 }
101 
102 static int unifont_init(const char *fontname)
103 {
104  Uint8 hexBuffer[65];
105  Uint32 numGlyphs = 0;
106  int lineNumber = 1;
107  size_t bytesRead;
108  SDL_RWops *hexFile;
109  const size_t unifontGlyphSize = UNIFONT_NUM_GLYPHS * sizeof(struct UnifontGlyph);
110  const size_t unifontTextureSize = UNIFONT_NUM_TEXTURES * state->num_windows * sizeof(void *);
111 
112  /* Allocate memory for the glyph data so the file can be closed after initialization. */
113  unifontGlyph = (struct UnifontGlyph *)SDL_malloc(unifontGlyphSize);
114  if (unifontGlyph == NULL)
115  {
116  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d KiB for glyph data.\n", (int)(unifontGlyphSize + 1023) / 1024);
117  return -1;
118  }
119  SDL_memset(unifontGlyph, 0, unifontGlyphSize);
120 
121  /* Allocate memory for texture pointers for all renderers. */
122  unifontTexture = (SDL_Texture **)SDL_malloc(unifontTextureSize);
123  if (unifontTexture == NULL)
124  {
125  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d KiB for texture pointer data.\n", (int)(unifontTextureSize + 1023) / 1024);
126  return -1;
127  }
128  SDL_memset(unifontTexture, 0, unifontTextureSize);
129 
130  hexFile = SDL_RWFromFile(fontname, "rb");
131  if (hexFile == NULL)
132  {
133  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to open font file: %s\n", fontname);
134  return -1;
135  }
136 
137  /* Read all the glyph data into memory to make it accessible later when textures are created. */
138  do {
139  int i, codepointHexSize;
140  size_t bytesOverread;
141  Uint8 glyphWidth;
142  Uint32 codepoint;
143 
144  bytesRead = SDL_RWread(hexFile, hexBuffer, 1, 9);
145  if (numGlyphs > 0 && bytesRead == 0)
146  break; /* EOF */
147  if ((numGlyphs == 0 && bytesRead == 0) || (numGlyphs > 0 && bytesRead < 9))
148  {
149  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Unexpected end of hex file.\n");
150  return -1;
151  }
152 
153  /* Looking for the colon that separates the codepoint and glyph data at position 2, 4, 6 and 8. */
154  if (hexBuffer[2] == ':')
155  codepointHexSize = 2;
156  else if (hexBuffer[4] == ':')
157  codepointHexSize = 4;
158  else if (hexBuffer[6] == ':')
159  codepointHexSize = 6;
160  else if (hexBuffer[8] == ':')
161  codepointHexSize = 8;
162  else
163  {
164  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Could not find codepoint and glyph data separator symbol in hex file on line %d.\n", lineNumber);
165  return -1;
166  }
167 
168  if (!validate_hex((const char *)hexBuffer, codepointHexSize, &codepoint))
169  {
170  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Malformed hexadecimal number in hex file on line %d.\n", lineNumber);
171  return -1;
172  }
173  if (codepoint > UNIFONT_MAX_CODEPOINT)
174  SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "unifont: Codepoint on line %d exceeded limit of 0x%x.\n", lineNumber, UNIFONT_MAX_CODEPOINT);
175 
176  /* If there was glyph data read in the last file read, move it to the front of the buffer. */
177  bytesOverread = 8 - codepointHexSize;
178  if (codepointHexSize < 8)
179  SDL_memmove(hexBuffer, hexBuffer + codepointHexSize + 1, bytesOverread);
180  bytesRead = SDL_RWread(hexFile, hexBuffer + bytesOverread, 1, 33 - bytesOverread);
181  if (bytesRead < (33 - bytesOverread))
182  {
183  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Unexpected end of hex file.\n");
184  return -1;
185  }
186  if (hexBuffer[32] == '\n')
187  glyphWidth = 8;
188  else
189  {
190  glyphWidth = 16;
191  bytesRead = SDL_RWread(hexFile, hexBuffer + 33, 1, 32);
192  if (bytesRead < 32)
193  {
194  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Unexpected end of hex file.\n");
195  return -1;
196  }
197  }
198 
199  if (!validate_hex((const char *)hexBuffer, glyphWidth * 4, NULL))
200  {
201  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Malformed hexadecimal glyph data in hex file on line %d.\n", lineNumber);
202  return -1;
203  }
204 
205  if (codepoint <= UNIFONT_MAX_CODEPOINT)
206  {
207  if (unifontGlyph[codepoint].width > 0)
208  SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "unifont: Ignoring duplicate codepoint 0x%08x in hex file on line %d.\n", codepoint, lineNumber);
209  else
210  {
211  unifontGlyph[codepoint].width = glyphWidth;
212  /* Pack the hex data into a more compact form. */
213  for (i = 0; i < glyphWidth * 2; i++)
214  unifontGlyph[codepoint].data[i] = dehex2(hexBuffer[i * 2], hexBuffer[i * 2 + 1]);
215  numGlyphs++;
216  }
217  }
218 
219  lineNumber++;
220  } while (bytesRead > 0);
221 
222  SDL_RWclose(hexFile);
223  SDL_Log("unifont: Loaded %u glyphs.\n", numGlyphs);
224  return 0;
225 }
226 
228 {
229  int i, j;
230  Uint8 *row = dst;
231 
232  for (i = 0; i < width * 2; i++)
233  {
234  Uint8 data = src[i];
235  for (j = 0; j < 8; j++)
236  {
237  if (data & 0x80)
238  {
239  row[0] = textColor.r;
240  row[1] = textColor.g;
241  row[2] = textColor.b;
242  row[3] = textColor.a;
243  }
244  else
245  {
246  row[0] = 0;
247  row[1] = 0;
248  row[2] = 0;
249  row[3] = 0;
250  }
251  data <<= 1;
252  row += 4;
253  }
254 
255  if (width == 8 || (width == 16 && i % 2 == 1))
256  {
257  dst += UNIFONT_TEXTURE_PITCH;
258  row = dst;
259  }
260  }
261 }
262 
263 static int unifont_load_texture(Uint32 textureID)
264 {
265  int i;
266  Uint8 * textureRGBA;
267 
268  if (textureID >= UNIFONT_NUM_TEXTURES)
269  {
270  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Tried to load out of range texture %u.\n", textureID);
271  return -1;
272  }
273 
274  textureRGBA = (Uint8 *)SDL_malloc(UNIFONT_TEXTURE_SIZE);
275  if (textureRGBA == NULL)
276  {
277  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d MiB for a texture.\n", UNIFONT_TEXTURE_SIZE / 1024 / 1024);
278  return -1;
279  }
280  SDL_memset(textureRGBA, 0, UNIFONT_TEXTURE_SIZE);
281 
282  /* Copy the glyphs into memory in RGBA format. */
283  for (i = 0; i < UNIFONT_GLYPHS_IN_TEXTURE; i++)
284  {
285  Uint32 codepoint = UNIFONT_GLYPHS_IN_TEXTURE * textureID + i;
286  if (unifontGlyph[codepoint].width > 0)
287  {
288  const Uint32 cInTex = codepoint % UNIFONT_GLYPHS_IN_TEXTURE;
289  const size_t offset = (cInTex / UNIFONT_GLYPHS_IN_ROW) * UNIFONT_TEXTURE_PITCH * 16 + (cInTex % UNIFONT_GLYPHS_IN_ROW) * 16 * 4;
290  unifont_make_rgba(unifontGlyph[codepoint].data, textureRGBA + offset, unifontGlyph[codepoint].width);
291  }
292  }
293 
294  /* Create textures and upload the RGBA data from above. */
295  for (i = 0; i < state->num_windows; ++i)
296  {
297  SDL_Renderer *renderer = state->renderers[i];
298  SDL_Texture *tex = unifontTexture[UNIFONT_NUM_TEXTURES * i + textureID];
299  if (state->windows[i] == NULL || renderer == NULL || tex != NULL)
300  continue;
302  if (tex == NULL)
303  {
304  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to create texture %u for renderer %d.\n", textureID, i);
305  return -1;
306  }
307  unifontTexture[UNIFONT_NUM_TEXTURES * i + textureID] = tex;
309  if (SDL_UpdateTexture(tex, NULL, textureRGBA, UNIFONT_TEXTURE_PITCH) != 0)
310  {
311  SDL_Log("unifont error: Failed to update texture %u data for renderer %d.\n", textureID, i);
312  }
313  }
314 
315  SDL_free(textureRGBA);
316  unifontTextureLoaded[textureID] = 1;
317  return 0;
318 }
319 
320 static Sint32 unifont_draw_glyph(Uint32 codepoint, int rendererID, SDL_Rect *dstrect)
321 {
323  const Uint32 textureID = codepoint / UNIFONT_GLYPHS_IN_TEXTURE;
324  SDL_Rect srcrect;
325  srcrect.w = srcrect.h = 16;
326  if (codepoint > UNIFONT_MAX_CODEPOINT) {
327  return 0;
328  }
329  if (!unifontTextureLoaded[textureID]) {
330  if (unifont_load_texture(textureID) < 0) {
331  return 0;
332  }
333  }
334  texture = unifontTexture[UNIFONT_NUM_TEXTURES * rendererID + textureID];
335  if (texture != NULL)
336  {
337  const Uint32 cInTex = codepoint % UNIFONT_GLYPHS_IN_TEXTURE;
338  srcrect.x = cInTex % UNIFONT_GLYPHS_IN_ROW * 16;
339  srcrect.y = cInTex / UNIFONT_GLYPHS_IN_ROW * 16;
340  SDL_RenderCopy(state->renderers[rendererID], texture, &srcrect, dstrect);
341  }
342  return unifontGlyph[codepoint].width;
343 }
344 
345 static void unifont_cleanup()
346 {
347  int i, j;
348  for (i = 0; i < state->num_windows; ++i)
349  {
350  SDL_Renderer *renderer = state->renderers[i];
351  if (state->windows[i] == NULL || renderer == NULL)
352  continue;
353  for (j = 0; j < UNIFONT_NUM_TEXTURES; j++)
354  {
355  SDL_Texture *tex = unifontTexture[UNIFONT_NUM_TEXTURES * i + j];
356  if (tex != NULL)
357  SDL_DestroyTexture(tex);
358  }
359  }
360 
361  for (j = 0; j < UNIFONT_NUM_TEXTURES; j++)
362  unifontTextureLoaded[j] = 0;
363 
364  SDL_free(unifontTexture);
366 }
367 
368 /* Unifont code end */
369 #endif
370 
371 size_t utf8_length(unsigned char c)
372 {
373  c = (unsigned char)(0xff & c);
374  if (c < 0x80)
375  return 1;
376  else if ((c >> 5) ==0x6)
377  return 2;
378  else if ((c >> 4) == 0xe)
379  return 3;
380  else if ((c >> 3) == 0x1e)
381  return 4;
382  else
383  return 0;
384 }
385 
386 char *utf8_next(char *p)
387 {
388  size_t len = utf8_length(*p);
389  size_t i = 0;
390  if (!len)
391  return 0;
392 
393  for (; i < len; ++i)
394  {
395  ++p;
396  if (!*p)
397  return 0;
398  }
399  return p;
400 }
401 
402 char *utf8_advance(char *p, size_t distance)
403 {
404  size_t i = 0;
405  for (; i < distance && p; ++i)
406  {
407  p = utf8_next(p);
408  }
409  return p;
410 }
411 
412 Uint32 utf8_decode(char *p, size_t len)
413 {
414  Uint32 codepoint = 0;
415  size_t i = 0;
416  if (!len)
417  return 0;
418 
419  for (; i < len; ++i)
420  {
421  if (i == 0)
422  codepoint = (0xff >> len) & *p;
423  else
424  {
425  codepoint <<= 6;
426  codepoint |= 0x3f & *p;
427  }
428  if (!*p)
429  return 0;
430  p++;
431  }
432 
433  return codepoint;
434 }
435 
436 void usage()
437 {
438  SDL_Log("usage: testime [--font fontfile]\n");
439 }
440 
441 void InitInput()
442 {
443  /* Prepare a rect for text input */
444  textRect.x = textRect.y = 100;
445  textRect.w = DEFAULT_WINDOW_WIDTH - 2 * textRect.x;
446  textRect.h = 50;
447 
448  text[0] = 0;
449  markedRect = textRect;
450  markedText[0] = 0;
451 
453 }
454 
456 {
458 #ifdef HAVE_SDL_TTF
459  TTF_CloseFont(font);
460  TTF_Quit();
461 #else
462  unifont_cleanup();
463 #endif
464 }
465 
466 void _Redraw(int rendererID)
467 {
468  SDL_Renderer * renderer = state->renderers[rendererID];
469  SDL_Rect drawnTextRect, cursorRect, underlineRect;
470  drawnTextRect = textRect;
471  drawnTextRect.w = 0;
472 
473  SDL_SetRenderDrawColor(renderer, backColor.r, backColor.g, backColor.b, backColor.a);
474  SDL_RenderFillRect(renderer,&textRect);
475 
476  if (*text)
477  {
478 #ifdef HAVE_SDL_TTF
479  SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, text, textColor);
481 
482  /* Vertically center text */
483  drawnTextRect.y = textRect.y + (textRect.h - textSur->h) / 2;
484  drawnTextRect.w = textSur->w;
485  drawnTextRect.h = textSur->h;
486 
487  texture = SDL_CreateTextureFromSurface(renderer,textSur);
488  SDL_FreeSurface(textSur);
489 
490  SDL_RenderCopy(renderer,texture,NULL,&drawnTextRect);
491  SDL_DestroyTexture(texture);
492 #else
493  char *utext = text;
494  Uint32 codepoint;
495  size_t len;
496  SDL_Rect dstrect;
497 
498  dstrect.x = textRect.x;
499  dstrect.y = textRect.y + (textRect.h - 16 * UNIFONT_DRAW_SCALE) / 2;
500  dstrect.w = 16 * UNIFONT_DRAW_SCALE;
501  dstrect.h = 16 * UNIFONT_DRAW_SCALE;
502  drawnTextRect.y = dstrect.y;
503  drawnTextRect.h = dstrect.h;
504 
505  while ((codepoint = utf8_decode(utext, len = utf8_length(*utext))))
506  {
507  Sint32 advance = unifont_draw_glyph(codepoint, rendererID, &dstrect) * UNIFONT_DRAW_SCALE;
508  dstrect.x += advance;
509  drawnTextRect.w += advance;
510  utext += len;
511  }
512 #endif
513  }
514 
515  markedRect.x = textRect.x + drawnTextRect.w;
516  markedRect.w = textRect.w - drawnTextRect.w;
517  if (markedRect.w < 0)
518  {
519  /* Stop text input because we cannot hold any more characters */
521  return;
522  }
523  else
524  {
526  }
527 
528  cursorRect = drawnTextRect;
529  cursorRect.x += cursorRect.w;
530  cursorRect.w = 2;
531  cursorRect.h = drawnTextRect.h;
532 
533  drawnTextRect.x += drawnTextRect.w;
534  drawnTextRect.w = 0;
535 
536  SDL_SetRenderDrawColor(renderer, backColor.r, backColor.g, backColor.b, backColor.a);
537  SDL_RenderFillRect(renderer,&markedRect);
538 
539  if (markedText[0])
540  {
541 #ifdef HAVE_SDL_TTF
542  SDL_Surface *textSur;
544  if (cursor)
545  {
546  char *p = utf8_advance(markedText, cursor);
547  char c = 0;
548  if (!p)
550 
551  c = *p;
552  *p = 0;
553  TTF_SizeUTF8(font, markedText, &drawnTextRect.w, NULL);
554  cursorRect.x += drawnTextRect.w;
555  *p = c;
556  }
557  textSur = TTF_RenderUTF8_Blended(font, markedText, textColor);
558  /* Vertically center text */
559  drawnTextRect.y = textRect.y + (textRect.h - textSur->h) / 2;
560  drawnTextRect.w = textSur->w;
561  drawnTextRect.h = textSur->h;
562 
563  texture = SDL_CreateTextureFromSurface(renderer,textSur);
564  SDL_FreeSurface(textSur);
565 
566  SDL_RenderCopy(renderer,texture,NULL,&drawnTextRect);
567  SDL_DestroyTexture(texture);
568 #else
569  int i = 0;
570  char *utext = markedText;
571  Uint32 codepoint;
572  size_t len;
573  SDL_Rect dstrect;
574 
575  dstrect.x = drawnTextRect.x;
576  dstrect.y = textRect.y + (textRect.h - 16 * UNIFONT_DRAW_SCALE) / 2;
577  dstrect.w = 16 * UNIFONT_DRAW_SCALE;
578  dstrect.h = 16 * UNIFONT_DRAW_SCALE;
579  drawnTextRect.y = dstrect.y;
580  drawnTextRect.h = dstrect.h;
581 
582  while ((codepoint = utf8_decode(utext, len = utf8_length(*utext))))
583  {
584  Sint32 advance = unifont_draw_glyph(codepoint, rendererID, &dstrect) * UNIFONT_DRAW_SCALE;
585  dstrect.x += advance;
586  drawnTextRect.w += advance;
587  if (i < cursor)
588  cursorRect.x += advance;
589  i++;
590  utext += len;
591  }
592 #endif
593 
594  if (cursor > 0)
595  {
596  cursorRect.y = drawnTextRect.y;
597  cursorRect.h = drawnTextRect.h;
598  }
599 
600  underlineRect = markedRect;
601  underlineRect.y = drawnTextRect.y + drawnTextRect.h - 2;
602  underlineRect.h = 2;
603  underlineRect.w = drawnTextRect.w;
604 
605  SDL_SetRenderDrawColor(renderer, lineColor.r, lineColor.g, lineColor.b, lineColor.a);
606  SDL_RenderFillRect(renderer, &underlineRect);
607  }
608 
609  SDL_SetRenderDrawColor(renderer, lineColor.r, lineColor.g, lineColor.b, lineColor.a);
610  SDL_RenderFillRect(renderer,&cursorRect);
611 
612  SDL_SetTextInputRect(&markedRect);
613 }
614 
615 void Redraw()
616 {
617  int i;
618  for (i = 0; i < state->num_windows; ++i) {
619  SDL_Renderer *renderer = state->renderers[i];
620  if (state->windows[i] == NULL)
621  continue;
622  SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
623  SDL_RenderClear(renderer);
624 
625  /* Sending in the window id to let the font renderers know which one we're working with. */
626  _Redraw(i);
627 
628  SDL_RenderPresent(renderer);
629  }
630 }
631 
632 int main(int argc, char *argv[])
633 {
634  int i, done;
636  const char *fontname = DEFAULT_FONT;
637 
638  /* Enable standard application logging */
640 
641  /* Initialize test framework */
643  if (!state) {
644  return 1;
645  }
646  for (i = 1; i < argc;i++) {
647  SDLTest_CommonArg(state, i);
648  }
649  for (argc--, argv++; argc > 0; argc--, argv++)
650  {
651  if (strcmp(argv[0], "--help") == 0) {
652  usage();
653  return 0;
654  }
655 
656  else if (strcmp(argv[0], "--font") == 0)
657  {
658  argc--;
659  argv++;
660 
661  if (argc > 0)
662  fontname = argv[0];
663  else {
664  usage();
665  return 0;
666  }
667  }
668  }
669 
670  if (!SDLTest_CommonInit(state)) {
671  return 2;
672  }
673 
674 
675 #ifdef HAVE_SDL_TTF
676  /* Initialize fonts */
677  TTF_Init();
678 
679  font = TTF_OpenFont(fontname, DEFAULT_PTSIZE);
680  if (! font)
681  {
682  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to find font: %s\n", TTF_GetError());
683  return -1;
684  }
685 #else
686  if (unifont_init(fontname) < 0) {
687  return -1;
688  }
689 #endif
690 
691  SDL_Log("Using font: %s\n", fontname);
692 
693  InitInput();
694  /* Create the windows and initialize the renderers */
695  for (i = 0; i < state->num_windows; ++i) {
696  SDL_Renderer *renderer = state->renderers[i];
698  SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
699  SDL_RenderClear(renderer);
700  }
701  Redraw();
702  /* Main render loop */
703  done = 0;
704  while (!done) {
705  /* Check for events */
706  while (SDL_PollEvent(&event)) {
707  SDLTest_CommonEvent(state, &event, &done);
708  switch(event.type) {
709  case SDL_KEYDOWN: {
710  switch (event.key.keysym.sym)
711  {
712  case SDLK_RETURN:
713  text[0]=0x00;
714  Redraw();
715  break;
716  case SDLK_BACKSPACE:
717  /* Only delete text if not in editing mode. */
718  if (!markedText[0])
719  {
720  size_t textlen = SDL_strlen(text);
721 
722  do {
723  if (textlen==0)
724  {
725  break;
726  }
727  if ((text[textlen-1] & 0x80) == 0x00)
728  {
729  /* One byte */
730  text[textlen-1]=0x00;
731  break;
732  }
733  if ((text[textlen-1] & 0xC0) == 0x80)
734  {
735  /* Byte from the multibyte sequence */
736  text[textlen-1]=0x00;
737  textlen--;
738  }
739  if ((text[textlen-1] & 0xC0) == 0xC0)
740  {
741  /* First byte of multibyte sequence */
742  text[textlen-1]=0x00;
743  break;
744  }
745  } while(1);
746 
747  Redraw();
748  }
749  break;
750  }
751 
752  if (done)
753  {
754  break;
755  }
756 
757  SDL_Log("Keyboard: scancode 0x%08X = %s, keycode 0x%08X = %s\n",
758  event.key.keysym.scancode,
760  event.key.keysym.sym, SDL_GetKeyName(event.key.keysym.sym));
761  break;
762 
763  case SDL_TEXTINPUT:
764  if (event.text.text[0] == '\0' || event.text.text[0] == '\n' ||
765  markedRect.w < 0)
766  break;
767 
768  SDL_Log("Keyboard: text input \"%s\"\n", event.text.text);
769 
770  if (SDL_strlen(text) + SDL_strlen(event.text.text) < sizeof(text))
771  SDL_strlcat(text, event.text.text, sizeof(text));
772 
773  SDL_Log("text inputed: %s\n", text);
774 
775  /* After text inputed, we can clear up markedText because it */
776  /* is committed */
777  markedText[0] = 0;
778  Redraw();
779  break;
780 
781  case SDL_TEXTEDITING:
782  SDL_Log("text editing \"%s\", selected range (%d, %d)\n",
783  event.edit.text, event.edit.start, event.edit.length);
784 
786  cursor = event.edit.start;
787  Redraw();
788  break;
789  }
790  break;
791 
792  }
793  }
794  }
795  CleanupVideo();
796  SDLTest_CommonQuit(state);
797  return 0;
798 }
799 
800 
801 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_CreateTexture
Uint8 width
Definition: testime.c:63
#define SDL_strlcpy
static Uint8 dehex(char c)
Definition: testime.c:71
void CleanupVideo()
Definition: testime.c:455
#define SDL_PollEvent
static SDL_Color backColor
Definition: testime.c:45
#define SDL_strlcat
static Uint8 validate_hex(const char *cp, size_t len, Uint32 *np)
Definition: testime.c:87
Uint8 g
Definition: SDL_pixels.h:298
GLenum GLenum dst
#define UNIFONT_NUM_GLYPHS
Definition: testime.c:53
#define UNIFONT_DRAW_SCALE
Definition: testime.c:61
static Uint8 unifontTextureLoaded[UNIFONT_NUM_TEXTURES]
Definition: testime.c:67
SDLTest_CommonState * SDLTest_CommonCreateState(char **argv, Uint32 flags)
Parse command line parameters and create common state.
static Uint8 dehex2(char c1, char c2)
Definition: testime.c:82
#define UNIFONT_GLYPHS_IN_ROW
Definition: testime.c:56
#define SDL_RenderFillRect
GLfloat GLfloat p
char * utf8_next(char *p)
Definition: testime.c:386
int SDLTest_CommonArg(SDLTest_CommonState *state, int index)
Process one common argument.
A collection of pixels used in software blitting.
Definition: SDL_surface.h:69
#define SDL_SetTextureBlendMode
#define SDL_SetRenderDrawBlendMode
#define SDL_RWread(ctx, ptr, size, n)
Definition: SDL_rwops.h:187
SDL_Scancode scancode
Definition: SDL_keyboard.h:49
static void unifont_make_rgba(Uint8 *src, Uint8 *dst, Uint8 width)
Definition: testime.c:227
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
Uint8 b
Definition: SDL_pixels.h:299
GLintptr offset
uint32_t Uint32
Definition: SDL_stdinc.h:181
GLenum src
#define UNIFONT_TEXTURE_WIDTH
Definition: testime.c:55
SDL_bool SDLTest_CommonInit(SDLTest_CommonState *state)
Open test window.
#define UNIFONT_MAX_CODEPOINT
Definition: testime.c:52
#define MAX_TEXT_LENGTH
Definition: testime.c:40
#define SDL_UpdateTexture
GLenum GLsizei len
static SDL_Color lineColor
Definition: testime.c:44
GLint GLint GLsizei width
Definition: SDL_opengl.h:1572
Uint32 utf8_decode(char *p, size_t len)
Definition: testime.c:412
GLsizei GLsizei GLfloat distance
SDL_Window ** windows
static int cursor
Definition: testime.c:48
static SDL_Texture ** unifontTexture
Definition: testime.c:66
#define SDL_LogError
#define SDL_RenderCopy
#define SDL_Log
#define SDL_RWFromFile
char * utf8_advance(char *p, size_t distance)
Definition: testime.c:402
#define UNIFONT_GLYPHS_IN_TEXTURE
Definition: testime.c:57
GLenum GLenum GLuint texture
SDL_TextInputEvent text
Definition: SDL_events.h:532
#define SDL_StopTextInput
char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]
Definition: SDL_events.h:226
#define SDL_CreateTextureFromSurface
Uint8 r
Definition: SDL_pixels.h:297
void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done)
Common event handler for test windows.
void InitInput()
Definition: testime.c:441
#define SDL_FreeSurface
static SDL_Renderer * renderer
Uint8 a
Definition: SDL_pixels.h:300
uint8_t Uint8
Definition: SDL_stdinc.h:157
#define SDL_free
struct _cl_event * event
int done
Definition: checkkeys.c:28
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
Definition: SDL_x11sym.h:50
void _Redraw(int rendererID)
Definition: testime.c:466
struct UnifontGlyph * unifontGlyph
const GLubyte * c
char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]
Definition: SDL_events.h:211
int main(int argc, char *argv[])
Definition: testime.c:632
void Redraw()
Definition: testime.c:615
#define SDL_memmove
static SDLTest_CommonState * state
Definition: testime.c:42
int x
Definition: SDL_rect.h:66
SDL_Keysym keysym
Definition: SDL_events.h:199
int32_t Sint32
Definition: SDL_stdinc.h:175
int w
Definition: SDL_rect.h:67
#define SDL_StartTextInput
static Sint32 unifont_draw_glyph(Uint32 codepoint, int rendererID, SDL_Rect *dstrect)
Definition: testime.c:320
SDL_Renderer ** renderers
static int unifont_init(const char *fontname)
Definition: testime.c:102
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
#define SDL_LogSetPriority
#define NULL
Definition: begin_code.h:164
SDL_TextEditingEvent edit
Definition: SDL_events.h:531
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
static void unifont_cleanup()
Definition: testime.c:345
static char text[MAX_TEXT_LENGTH]
Definition: testime.c:47
#define SDL_RenderClear
#define SDL_GetScancodeName
#define SDL_SetTextInputRect
static char markedText[SDL_TEXTEDITINGEVENT_TEXT_SIZE]
Definition: testime.c:47
SDL_KeyboardEvent key
Definition: SDL_events.h:530
#define SDL_DestroyTexture
#define SDL_strlen
int h
Definition: SDL_rect.h:67
GLdouble n
static SDL_Rect textRect
Definition: testime.c:43
#define SDL_GetKeyName
SDL_Keycode sym
Definition: SDL_keyboard.h:50
#define DEFAULT_FONT
Definition: testime.c:38
static const double cp
Definition: e_pow.c:92
#define UNIFONT_TEXTURE_SIZE
Definition: testime.c:59
GLenum const void GLbitfield GLsizei numGlyphs
size_t utf8_length(unsigned char c)
Definition: testime.c:371
General event structure.
Definition: SDL_events.h:525
#define SDL_malloc
#define SDL_SetRenderDrawColor
#define SDL_LogWarn
#define UNIFONT_TEXTURE_PITCH
Definition: testime.c:60
void usage()
Definition: testime.c:436
#define DEFAULT_PTSIZE
Definition: testime.c:27
#define UNIFONT_NUM_TEXTURES
Definition: testime.c:58
GLenum GLenum void * row
#define DEFAULT_WINDOW_WIDTH
int y
Definition: SDL_rect.h:66
static SDL_Rect markedRect
Definition: testime.c:43
void SDLTest_CommonQuit(SDLTest_CommonState *state)
Close test window.
static int unifont_load_texture(Uint32 textureID)
Definition: testime.c:263
static SDL_Color textColor
Definition: testime.c:46
#define SDL_INIT_VIDEO
Definition: SDL.h:78
#define SDL_memset
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
#define SDL_RenderPresent
Uint32 type
Definition: SDL_events.h:527
#define SDL_TEXTEDITINGEVENT_TEXT_SIZE
Definition: SDL_events.h:202