Browse Source

Merge pull request #30 from tsoding/word-wrapping

Word wrapping
Alexey Kutepov 5 years ago
parent
commit
3331089b3d
3 changed files with 86 additions and 32 deletions
  1. 7 0
      src/vodus.cpp
  2. 44 0
      src/vodus_image32.cpp
  3. 35 32
      src/vodus_main.cpp

+ 7 - 0
src/vodus.cpp

@@ -67,6 +67,13 @@ void println(FILE *stream, T... args)
     fputc('\n', stream);
     fputc('\n', stream);
 }
 }
 
 
+const size_t VODUS_FPS = 30;
+const float VODUS_DELTA_TIME_SEC = 1.0f / VODUS_FPS;
+const size_t VODUS_WIDTH = 1028;
+const size_t VODUS_HEIGHT = 768;
+const float VODUS_VIDEO_DURATION = 5.0f;
+const size_t VODUS_FONT_SIZE = 64;
+
 // https://en.wikipedia.org/wiki/Single_Compilation_Unit
 // https://en.wikipedia.org/wiki/Single_Compilation_Unit
 #include "./vodus_string.cpp"
 #include "./vodus_string.cpp"
 #include "./vodus_image32.cpp"
 #include "./vodus_image32.cpp"

+ 44 - 0
src/vodus_image32.cpp

@@ -183,6 +183,18 @@ Image32 load_image32_from_png(const char *filepath)
     return result;
     return result;
 }
 }
 
 
+void advance_pen_for_text(FT_Face face, String_View text, int *pen_x, int *pen_y)
+{
+    for (size_t i = 0; i < text.count; ++i) {
+        auto error = FT_Load_Glyph(
+            face,
+            FT_Get_Char_Index(face, text.data[i]),
+            FT_LOAD_DEFAULT);
+        assert(!error);
+
+        *pen_x += face->glyph->advance.x >> 6;
+    }
+}
 
 
 void slap_text_onto_image32(Image32 surface,
 void slap_text_onto_image32(Image32 surface,
                             FT_Face face,
                             FT_Face face,
@@ -208,6 +220,38 @@ void slap_text_onto_image32(Image32 surface,
     }
     }
 }
 }
 
 
+void slap_text_onto_image32_wrapped(Image32 surface,
+                                    FT_Face face,
+                                    String_View text,
+                                    Pixel32 color,
+                                    int *pen_x, int *pen_y)
+{
+    int copy_x = *pen_x;
+    int copy_y = *pen_y;
+
+    advance_pen_for_text(face, text, &copy_x, &copy_y);
+    if (copy_x >= (int)surface.width) {
+        *pen_x = 0;
+        // @word-wrap-face
+        *pen_y += VODUS_FONT_SIZE;
+    }
+
+    slap_text_onto_image32(surface, face, text, color, pen_x, pen_y);
+}
+
+void slap_text_onto_image32_wrapped(Image32 surface,
+                                    FT_Face face,
+                                    const char *cstr,
+                                    Pixel32 color,
+                                    int *pen_x, int *pen_y)
+{
+    slap_text_onto_image32_wrapped(surface,
+                                   face,
+                                   cstr_as_string_view(cstr),
+                                   color,
+                                   pen_x, pen_y);
+}
+
 void slap_text_onto_image32(Image32 surface,
 void slap_text_onto_image32(Image32 surface,
                             FT_Face face,
                             FT_Face face,
                             const char *text,
                             const char *text,

+ 35 - 32
src/vodus_main.cpp

@@ -35,13 +35,6 @@ T *fail_if_null(T *ptr, const char *format, ...)
     return ptr;
     return ptr;
 }
 }
 
 
-const size_t VODUS_FPS = 30;
-const float VODUS_DELTA_TIME_SEC = 1.0f / VODUS_FPS;
-const size_t VODUS_WIDTH = 1028;
-const size_t VODUS_HEIGHT = 768;
-const float VODUS_VIDEO_DURATION = 5.0f;
-const size_t VODUS_FONT_SIZE = 64;
-
 void encode_avframe(AVCodecContext *context, AVFrame *frame, AVPacket *pkt, FILE *outfile)
 void encode_avframe(AVCodecContext *context, AVFrame *frame, AVPacket *pkt, FILE *outfile)
 {
 {
     if (frame) {
     if (frame) {
@@ -95,8 +88,9 @@ Message messages[] = {
     {0, "Nice_la", "hello         AYAYA /"},
     {0, "Nice_la", "hello         AYAYA /"},
     {1, "Zuglya", "\\o/"},
     {1, "Zuglya", "\\o/"},
     {1, "Tsoding", "phpHop"},
     {1, "Tsoding", "phpHop"},
+    {2, "Tsoding", "phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop phpHop"},
     {2, "recursivechat", "me me me"},
     {2, "recursivechat", "me me me"},
-    {3, "nuffleee", "because dumb compiler"},
+    {3, "nuffleee", "because dumb AYAYA compiler"},
     {4, "marko8137", "hi phpHop"},
     {4, "marko8137", "hi phpHop"},
     {5, "nulligor", "meme?"},
     {5, "nulligor", "meme?"},
     {6, "mbgoodman", "KKool"},
     {6, "mbgoodman", "KKool"},
@@ -107,22 +101,22 @@ using Encode_Frame = std::function<void(Image32, int)>;
 
 
 void render_message(Image32 surface, FT_Face face,
 void render_message(Image32 surface, FT_Face face,
                     Message message,
                     Message message,
-                    int x, int y,
+                    int *x, int *y,
                     Bttv *bttv)
                     Bttv *bttv)
 {
 {
     assert(bttv);
     assert(bttv);
 
 
-    slap_text_onto_image32(surface,
-                           face,
-                           message.nickname,
-                           {255, 0, 0, 255},
-                           &x, &y);
+    slap_text_onto_image32_wrapped(surface,
+                                   face,
+                                   message.nickname,
+                                   {255, 0, 0, 255},
+                                   x, y);
 
 
-    slap_text_onto_image32(surface,
-                           face,
-                           ": ",
-                           {255, 0, 0, 255},
-                           &x, &y);
+    slap_text_onto_image32_wrapped(surface,
+                                   face,
+                                   ": ",
+                                   {255, 0, 0, 255},
+                                   x, y);
 
 
     auto text = cstr_as_string_view(message.message).trim();
     auto text = cstr_as_string_view(message.message).trim();
     while (text.count > 0) {
     while (text.count > 0) {
@@ -139,23 +133,31 @@ void render_message(Image32 surface, FT_Face face,
             const int emote_height = VODUS_FONT_SIZE;
             const int emote_height = VODUS_FONT_SIZE;
             const int emote_width = floorf(emote_height * emote_ratio);
             const int emote_width = floorf(emote_height * emote_ratio);
 
 
+            if (*x + emote_width >= (int)surface.width) {
+                *x = 0;
+                // TODO(#31): the size of the font in word wrapping should be taken from the face itself
+                //   Right now font size is hardcoded.
+                //   Grep for `@word-wrap-face` to find all of the hardcoded places
+                *y += VODUS_FONT_SIZE;
+            }
+
             bttv_emote.slap_onto_image32(surface,
             bttv_emote.slap_onto_image32(surface,
-                                         x, y - emote_height,
+                                         *x, *y - emote_height,
                                          emote_width, emote_height);
                                          emote_width, emote_height);
-            x += emote_width;
+            *x += emote_width;
         } else {
         } else {
-            slap_text_onto_image32(surface,
-                                   face,
-                                   word,
-                                   {0, 255, 0, 255},
-                                   &x, &y);
+            slap_text_onto_image32_wrapped(surface,
+                                           face,
+                                           word,
+                                           {0, 255, 0, 255},
+                                           x, y);
         }
         }
 
 
-        slap_text_onto_image32(surface,
-                               face,
-                               " ",
-                               {0, 255, 0, 255},
-                               &x, &y);
+        slap_text_onto_image32_wrapped(surface,
+                                       face,
+                                       " ",
+                                       {0, 255, 0, 255},
+                                       x, y);
     }
     }
 }
 }
 
 
@@ -166,7 +168,8 @@ void render_log(Image32 surface, FT_Face face, size_t message_index, Bttv *bttv)
     const int CHAT_PADDING = 0;
     const int CHAT_PADDING = 0;
     int text_y = FONT_HEIGHT + CHAT_PADDING;
     int text_y = FONT_HEIGHT + CHAT_PADDING;
     for (size_t i = 0; i < message_index; ++i) {
     for (size_t i = 0; i < message_index; ++i) {
-        render_message(surface, face, messages[i], 0, text_y, bttv);
+        int text_x = 0;
+        render_message(surface, face, messages[i], &text_x, &text_y, bttv);
         text_y += FONT_HEIGHT + CHAT_PADDING;
         text_y += FONT_HEIGHT + CHAT_PADDING;
     }
     }
 }
 }