SDL  2.0
testime.c
Go to the documentation of this file.
1 /*
2  Copyright (C) 1997-2016 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 void 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  exit(-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  exit(-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  exit(-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, "unfiont: Unexpected end of hex file.\n");
150  exit(-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  exit(-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  exit(-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  exit(-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  exit(-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  exit(-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 }
225 
227 {
228  int i, j;
229  Uint8 *row = dst;
230 
231  for (i = 0; i < width * 2; i++)
232  {
233  Uint8 data = src[i];
234  for (j = 0; j < 8; j++)
235  {
236  if (data & 0x80)
237  {
238  row[0] = textColor.r;
239  row[1] = textColor.g;
240  row[2] = textColor.b;
241  row[3] = textColor.a;
242  }
243  else
244  {
245  row[0] = 0;
246  row[1] = 0;
247  row[2] = 0;
248  row[3] = 0;
249  }
250  data <<= 1;
251  row += 4;
252  }
253 
254  if (width == 8 || (width == 16 && i % 2 == 1))
255  {
256  dst += UNIFONT_TEXTURE_PITCH;
257  row = dst;
258  }
259  }
260 }
261 
262 static void unifont_load_texture(Uint32 textureID)
263 {
264  int i;
265  Uint8 * textureRGBA;
266 
267  if (textureID >= UNIFONT_NUM_TEXTURES)
268  {
269  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Tried to load out of range texture %u.\n", textureID);
270  exit(-1);
271  }
272 
273  textureRGBA = (Uint8 *)SDL_malloc(UNIFONT_TEXTURE_SIZE);
274  if (textureRGBA == NULL)
275  {
276  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d MiB for a texture.\n", UNIFONT_TEXTURE_SIZE / 1024 / 1024);
277  exit(-1);
278  }
279  SDL_memset(textureRGBA, 0, UNIFONT_TEXTURE_SIZE);
280 
281  /* Copy the glyphs into memory in RGBA format. */
282  for (i = 0; i < UNIFONT_GLYPHS_IN_TEXTURE; i++)
283  {
284  Uint32 codepoint = UNIFONT_GLYPHS_IN_TEXTURE * textureID + i;
285  if (unifontGlyph[codepoint].width > 0)
286  {
287  const Uint32 cInTex = codepoint % UNIFONT_GLYPHS_IN_TEXTURE;
288  const size_t offset = (cInTex / UNIFONT_GLYPHS_IN_ROW) * UNIFONT_TEXTURE_PITCH * 16 + (cInTex % UNIFONT_GLYPHS_IN_ROW) * 16 * 4;
289  unifont_make_rgba(unifontGlyph[codepoint].data, textureRGBA + offset, unifontGlyph[codepoint].width);
290  }
291  }
292 
293  /* Create textures and upload the RGBA data from above. */
294  for (i = 0; i < state->num_windows; ++i)
295  {
296  SDL_Renderer *renderer = state->renderers[i];
297  SDL_Texture *tex = unifontTexture[UNIFONT_NUM_TEXTURES * i + textureID];
298  if (state->windows[i] == NULL || renderer == NULL || tex != NULL)
299  continue;
301  if (tex == NULL)
302  {
303  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to create texture %u for renderer %d.\n", textureID, i);
304  exit(-1);
305  }
306  unifontTexture[UNIFONT_NUM_TEXTURES * i + textureID] = tex;
308  if (SDL_UpdateTexture(tex, NULL, textureRGBA, UNIFONT_TEXTURE_PITCH) != 0)
309  {
310  SDL_Log("unifont error: Failed to update texture %u data for renderer %d.\n", textureID, i);
311  }
312  }
313 
314  SDL_free(textureRGBA);
315  unifontTextureLoaded[textureID] = 1;
316 }
317 
318 static Sint32 unifont_draw_glyph(Uint32 codepoint, int rendererID, SDL_Rect *dstrect)
319 {
321  const Uint32 textureID = codepoint / UNIFONT_GLYPHS_IN_TEXTURE;
322  SDL_Rect srcrect;
323  srcrect.w = srcrect.h = 16;
324  if (codepoint > UNIFONT_MAX_CODEPOINT)
325  return 0;
326  if (!unifontTextureLoaded[textureID])
327  unifont_load_texture(textureID);
328  texture = unifontTexture[UNIFONT_NUM_TEXTURES * rendererID + textureID];
329  if (texture != NULL)
330  {
331  const Uint32 cInTex = codepoint % UNIFONT_GLYPHS_IN_TEXTURE;
332  srcrect.x = cInTex % UNIFONT_GLYPHS_IN_ROW * 16;
333  srcrect.y = cInTex / UNIFONT_GLYPHS_IN_ROW * 16;
334  SDL_RenderCopy(state->renderers[rendererID], texture, &srcrect, dstrect);
335  }
336  return unifontGlyph[codepoint].width;
337 }
338 
339 static void unifont_cleanup()
340 {
341  int i, j;
342  for (i = 0; i < state->num_windows; ++i)
343  {
344  SDL_Renderer *renderer = state->renderers[i];
345  if (state->windows[i] == NULL || renderer == NULL)
346  continue;
347  for (j = 0; j < UNIFONT_NUM_TEXTURES; j++)
348  {
349  SDL_Texture *tex = unifontTexture[UNIFONT_NUM_TEXTURES * i + j];
350  if (tex != NULL)
351  SDL_DestroyTexture(tex);
352  }
353  }
354 
355  for (j = 0; j < UNIFONT_NUM_TEXTURES; j++)
356  unifontTextureLoaded[j] = 0;
357 
358  SDL_free(unifontTexture);
360 }
361 
362 /* Unifont code end */
363 #endif
364 
365 size_t utf8_length(unsigned char c)
366 {
367  c = (unsigned char)(0xff & c);
368  if (c < 0x80)
369  return 1;
370  else if ((c >> 5) ==0x6)
371  return 2;
372  else if ((c >> 4) == 0xe)
373  return 3;
374  else if ((c >> 3) == 0x1e)
375  return 4;
376  else
377  return 0;
378 }
379 
380 char *utf8_next(char *p)
381 {
382  size_t len = utf8_length(*p);
383  size_t i = 0;
384  if (!len)
385  return 0;
386 
387  for (; i < len; ++i)
388  {
389  ++p;
390  if (!*p)
391  return 0;
392  }
393  return p;
394 }
395 
396 char *utf8_advance(char *p, size_t distance)
397 {
398  size_t i = 0;
399  for (; i < distance && p; ++i)
400  {
401  p = utf8_next(p);
402  }
403  return p;
404 }
405 
406 Uint32 utf8_decode(char *p, size_t len)
407 {
408  Uint32 codepoint = 0;
409  size_t i = 0;
410  if (!len)
411  return 0;
412 
413  for (; i < len; ++i)
414  {
415  if (i == 0)
416  codepoint = (0xff >> len) & *p;
417  else
418  {
419  codepoint <<= 6;
420  codepoint |= 0x3f & *p;
421  }
422  if (!*p)
423  return 0;
424  p++;
425  }
426 
427  return codepoint;
428 }
429 
430 void usage()
431 {
432  SDL_Log("usage: testime [--font fontfile]\n");
433  exit(0);
434 }
435 
436 void InitInput()
437 {
438 
439  /* Prepare a rect for text input */
440  textRect.x = textRect.y = 100;
441  textRect.w = DEFAULT_WINDOW_WIDTH - 2 * textRect.x;
442  textRect.h = 50;
443 
444  text[0] = 0;
445  markedRect = textRect;
446  markedText[0] = 0;
447 
449 }
450 
452 {
454 #ifdef HAVE_SDL_TTF
455  TTF_CloseFont(font);
456  TTF_Quit();
457 #else
458  unifont_cleanup();
459 #endif
460 }
461 
462 void _Redraw(int rendererID) {
463  SDL_Renderer * renderer = state->renderers[rendererID];
464  SDL_Rect drawnTextRect, cursorRect, underlineRect;
465  drawnTextRect = textRect;
466  drawnTextRect.w = 0;
467 
468  SDL_SetRenderDrawColor(renderer, backColor.r, backColor.g, backColor.b, backColor.a);
469  SDL_RenderFillRect(renderer,&textRect);
470 
471  if (*text)
472  {
473 #ifdef HAVE_SDL_TTF
474  SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, text, textColor);
476 
477  /* Vertically center text */
478  drawnTextRect.y = textRect.y + (textRect.h - textSur->h) / 2;
479  drawnTextRect.w = textSur->w;
480  drawnTextRect.h = textSur->h;
481 
482  texture = SDL_CreateTextureFromSurface(renderer,textSur);
483  SDL_FreeSurface(textSur);
484 
485  SDL_RenderCopy(renderer,texture,NULL,&drawnTextRect);
486  SDL_DestroyTexture(texture);
487 #else
488  char *utext = text;
489  Uint32 codepoint;
490  size_t len;
491  SDL_Rect dstrect;
492 
493  dstrect.x = textRect.x;
494  dstrect.y = textRect.y + (textRect.h - 16 * UNIFONT_DRAW_SCALE) / 2;
495  dstrect.w = 16 * UNIFONT_DRAW_SCALE;
496  dstrect.h = 16 * UNIFONT_DRAW_SCALE;
497  drawnTextRect.y = dstrect.y;
498  drawnTextRect.h = dstrect.h;
499 
500  while ((codepoint = utf8_decode(utext, len = utf8_length(*utext))))
501  {
502  Sint32 advance = unifont_draw_glyph(codepoint, rendererID, &dstrect) * UNIFONT_DRAW_SCALE;
503  dstrect.x += advance;
504  drawnTextRect.w += advance;
505  utext += len;
506  }
507 #endif
508  }
509 
510  markedRect.x = textRect.x + drawnTextRect.w;
511  markedRect.w = textRect.w - drawnTextRect.w;
512  if (markedRect.w < 0)
513  {
514  /* Stop text input because we cannot hold any more characters */
516  return;
517  }
518  else
519  {
521  }
522 
523  cursorRect = drawnTextRect;
524  cursorRect.x += cursorRect.w;
525  cursorRect.w = 2;
526  cursorRect.h = drawnTextRect.h;
527 
528  drawnTextRect.x += drawnTextRect.w;
529  drawnTextRect.w = 0;
530 
531  SDL_SetRenderDrawColor(renderer, backColor.r, backColor.g, backColor.b, backColor.a);
532  SDL_RenderFillRect(renderer,&markedRect);
533 
534  if (markedText[0])
535  {
536 #ifdef HAVE_SDL_TTF
537  SDL_Surface *textSur;
539  if (cursor)
540  {
541  char *p = utf8_advance(markedText, cursor);
542  char c = 0;
543  if (!p)
545 
546  c = *p;
547  *p = 0;
548  TTF_SizeUTF8(font, markedText, &drawnTextRect.w, NULL);
549  cursorRect.x += drawnTextRect.w;
550  *p = c;
551  }
552  textSur = TTF_RenderUTF8_Blended(font, markedText, textColor);
553  /* Vertically center text */
554  drawnTextRect.y = textRect.y + (textRect.h - textSur->h) / 2;
555  drawnTextRect.w = textSur->w;
556  drawnTextRect.h = textSur->h;
557 
558  texture = SDL_CreateTextureFromSurface(renderer,textSur);
559  SDL_FreeSurface(textSur);
560 
561  SDL_RenderCopy(renderer,texture,NULL,&drawnTextRect);
562  SDL_DestroyTexture(texture);
563 #else
564  int i = 0;
565  char *utext = markedText;
566  Uint32 codepoint;
567  size_t len;
568  SDL_Rect dstrect;
569 
570  dstrect.x = drawnTextRect.x;
571  dstrect.y = textRect.y + (textRect.h - 16 * UNIFONT_DRAW_SCALE) / 2;
572  dstrect.w = 16 * UNIFONT_DRAW_SCALE;
573  dstrect.h = 16 * UNIFONT_DRAW_SCALE;
574  drawnTextRect.y = dstrect.y;
575  drawnTextRect.h = dstrect.h;
576 
577  while ((codepoint = utf8_decode(utext, len = utf8_length(*utext))))
578  {
579  Sint32 advance = unifont_draw_glyph(codepoint, rendererID, &dstrect) * UNIFONT_DRAW_SCALE;
580  dstrect.x += advance;
581  drawnTextRect.w += advance;
582  if (i < cursor)
583  cursorRect.x += advance;
584  i++;
585  utext += len;
586  }
587 #endif
588 
589  if (cursor > 0)
590  {
591  cursorRect.y = drawnTextRect.y;
592  cursorRect.h = drawnTextRect.h;
593  }
594 
595  underlineRect = markedRect;
596  underlineRect.y = drawnTextRect.y + drawnTextRect.h - 2;
597  underlineRect.h = 2;
598  underlineRect.w = drawnTextRect.w;
599 
600  SDL_SetRenderDrawColor(renderer, lineColor.r, lineColor.g, lineColor.b, lineColor.a);
601  SDL_RenderFillRect(renderer, &underlineRect);
602  }
603 
604  SDL_SetRenderDrawColor(renderer, lineColor.r, lineColor.g, lineColor.b, lineColor.a);
605  SDL_RenderFillRect(renderer,&cursorRect);
606 
607  SDL_SetTextInputRect(&markedRect);
608 }
609 
610 void Redraw() {
611  int i;
612  for (i = 0; i < state->num_windows; ++i) {
613  SDL_Renderer *renderer = state->renderers[i];
614  if (state->windows[i] == NULL)
615  continue;
616  SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
617  SDL_RenderClear(renderer);
618 
619  /* Sending in the window id to let the font renderers know which one we're working with. */
620  _Redraw(i);
621 
622  SDL_RenderPresent(renderer);
623  }
624 }
625 
626 int main(int argc, char *argv[]) {
627  int i, done;
629  const char *fontname = DEFAULT_FONT;
630 
631  /* Enable standard application logging */
633 
634  /* Initialize test framework */
636  if (!state) {
637  return 1;
638  }
639  for (i = 1; i < argc;i++) {
640  SDLTest_CommonArg(state, i);
641  }
642  for (argc--, argv++; argc > 0; argc--, argv++)
643  {
644  if (strcmp(argv[0], "--help") == 0) {
645  usage();
646  return 0;
647  }
648 
649  else if (strcmp(argv[0], "--font") == 0)
650  {
651  argc--;
652  argv++;
653 
654  if (argc > 0)
655  fontname = argv[0];
656  else {
657  usage();
658  return 0;
659  }
660  }
661  }
662 
663  if (!SDLTest_CommonInit(state)) {
664  return 2;
665  }
666 
667 
668 #ifdef HAVE_SDL_TTF
669  /* Initialize fonts */
670  TTF_Init();
671 
672  font = TTF_OpenFont(fontname, DEFAULT_PTSIZE);
673  if (! font)
674  {
675  SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to find font: %s\n", TTF_GetError());
676  exit(-1);
677  }
678 #else
679  unifont_init(fontname);
680 #endif
681 
682  SDL_Log("Using font: %s\n", fontname);
683  atexit(SDL_Quit);
684 
685  InitInput();
686  /* Create the windows and initialize the renderers */
687  for (i = 0; i < state->num_windows; ++i) {
688  SDL_Renderer *renderer = state->renderers[i];
690  SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
691  SDL_RenderClear(renderer);
692  }
693  Redraw();
694  /* Main render loop */
695  done = 0;
696  while (!done) {
697  /* Check for events */
698  while (SDL_PollEvent(&event)) {
699  SDLTest_CommonEvent(state, &event, &done);
700  switch(event.type) {
701  case SDL_KEYDOWN: {
702  switch (event.key.keysym.sym)
703  {
704  case SDLK_RETURN:
705  text[0]=0x00;
706  Redraw();
707  break;
708  case SDLK_BACKSPACE:
709  /* Only delete text if not in editing mode. */
710  if (!markedText[0])
711  {
712  size_t textlen = SDL_strlen(text);
713 
714  do {
715  if (textlen==0)
716  {
717  break;
718  }
719  if ((text[textlen-1] & 0x80) == 0x00)
720  {
721  /* One byte */
722  text[textlen-1]=0x00;
723  break;
724  }
725  if ((text[textlen-1] & 0xC0) == 0x80)
726  {
727  /* Byte from the multibyte sequence */
728  text[textlen-1]=0x00;
729  textlen--;
730  }
731  if ((text[textlen-1] & 0xC0) == 0xC0)
732  {
733  /* First byte of multibyte sequence */
734  text[textlen-1]=0x00;
735  break;
736  }
737  } while(1);
738 
739  Redraw();
740  }
741  break;
742  }
743 
744  if (done)
745  {
746  break;
747  }
748 
749  SDL_Log("Keyboard: scancode 0x%08X = %s, keycode 0x%08X = %s\n",
750  event.key.keysym.scancode,
752  event.key.keysym.sym, SDL_GetKeyName(event.key.keysym.sym));
753  break;
754 
755  case SDL_TEXTINPUT:
756  if (event.text.text[0] == '\0' || event.text.text[0] == '\n' ||
757  markedRect.w < 0)
758  break;
759 
760  SDL_Log("Keyboard: text input \"%s\"\n", event.text.text);
761 
762  if (SDL_strlen(text) + SDL_strlen(event.text.text) < sizeof(text))
763  SDL_strlcat(text, event.text.text, sizeof(text));
764 
765  SDL_Log("text inputed: %s\n", text);
766 
767  /* After text inputed, we can clear up markedText because it */
768  /* is committed */
769  markedText[0] = 0;
770  Redraw();
771  break;
772 
773  case SDL_TEXTEDITING:
774  SDL_Log("text editing \"%s\", selected range (%d, %d)\n",
775  event.edit.text, event.edit.start, event.edit.length);
776 
778  cursor = event.edit.start;
779  Redraw();
780  break;
781  }
782  break;
783 
784  }
785  }
786  }
787  CleanupVideo();
788  SDLTest_CommonQuit(state);
789  return 0;
790 }
791 
792 
793 /* vi: set ts=4 sw=4 expandtab: */
#define SDL_CreateTexture
Uint8 width
Definition: testime.c:63
#define SDL_strlcpy
GLenum GLenum dst
static Uint8 dehex(char c)
Definition: testime.c:71
void CleanupVideo()
Definition: testime.c:451
#define SDL_PollEvent
static SDL_Color backColor
Definition: testime.c:45
#define SDL_strlcat
GLint GLint GLsizei width
Definition: SDL_opengl.h:1565
GLdouble n
static Uint8 validate_hex(const char *cp, size_t len, Uint32 *np)
Definition: testime.c:87
Uint8 g
Definition: SDL_pixels.h:296
#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
GLenum GLenum GLuint texture
GLfloat GLfloat p
char * utf8_next(char *p)
Definition: testime.c:380
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
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
#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:226
Uint8 b
Definition: SDL_pixels.h:297
uint32_t Uint32
An unsigned 32-bit integer type.
Definition: SDL_stdinc.h:159
#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
Uint32 utf8_decode(char *p, size_t len)
Definition: testime.c:406
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:396
#define UNIFONT_GLYPHS_IN_TEXTURE
Definition: testime.c:57
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:295
void SDLTest_CommonEvent(SDLTest_CommonState *state, SDL_Event *event, int *done)
Common event handler for test windows.
static void unifont_init(const char *fontname)
Definition: testime.c:102
void InitInput()
Definition: testime.c:436
cp
Definition: e_pow.c:96
#define SDL_FreeSurface
static SDL_Renderer * renderer
Uint8 a
Definition: SDL_pixels.h:298
uint8_t Uint8
An unsigned 8-bit integer type.
Definition: SDL_stdinc.h:143
struct _cl_event * event
void SDL_free(void *mem)
#define SDL_Quit
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:462
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:626
void Redraw()
Definition: testime.c:610
#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
A signed 32-bit integer type.
Definition: SDL_stdinc.h:155
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:318
SDL_Renderer ** renderers
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:143
SDL_TextEditingEvent edit
Definition: SDL_events.h:531
GLintptr offset
#define SDL_RWclose(ctx)
Definition: SDL_rwops.h:189
GLenum const void GLbitfield GLsizei numGlyphs
static void unifont_cleanup()
Definition: testime.c:339
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
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
#define UNIFONT_TEXTURE_SIZE
Definition: testime.c:59
size_t utf8_length(unsigned char c)
Definition: testime.c:365
General event structure.
Definition: SDL_events.h:525
#define SDL_malloc
#define SDL_SetRenderDrawColor
static void unifont_load_texture(Uint32 textureID)
Definition: testime.c:262
#define SDL_LogWarn
#define UNIFONT_TEXTURE_PITCH
Definition: testime.c:60
void usage()
Definition: testime.c:430
#define DEFAULT_PTSIZE
Definition: testime.c:27
#define UNIFONT_NUM_TEXTURES
Definition: testime.c:58
GLenum src
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 SDL_Color textColor
Definition: testime.c:46
#define SDL_INIT_VIDEO
Definition: SDL.h:77
#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