| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735 |
- #include "u8g2.h"
- #include <stdint.h>
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- #define WORD_CLOUD_MAX_X 600
- extern uint8_t tga_is_transparent;
- extern uint8_t tga_desc_fg_r;
- extern uint8_t tga_desc_fg_g;
- extern uint8_t tga_desc_fg_b;
- extern uint8_t tga_desc_bg_r;
- extern uint8_t tga_desc_bg_g;
- extern uint8_t tga_desc_bg_b;
- extern uint8_t tga_lcd_fg_r;
- extern uint8_t tga_lcd_fg_g;
- extern uint8_t tga_lcd_fg_b;
- extern uint8_t tga_lcd_bg_r;
- extern uint8_t tga_lcd_bg_g;
- extern uint8_t tga_lcd_bg_b;
- extern void tga_save_png(const char *name);
- struct _box_t
- {
- uint32_t w, h;
- };
- typedef struct _box_t box_t;
- struct _pos_t
- {
- uint32_t x, y;
- };
- typedef struct _pos_t pos_t;
- struct _pbox_t // placed box
- {
- pos_t pos;
- int box_idx;
- };
- typedef struct _pbox_t pbox_t;
- #define BOX_LIST_MAX 50
- box_t box_list[BOX_LIST_MAX];
- char box_word[BOX_LIST_MAX][64];
- const uint8_t *box_font[BOX_LIST_MAX];
- int box_cnt = 0;
- int box_index[BOX_LIST_MAX];
- #define PLACE_OPTION_MAX 100
- int place_option_cnt = 0;
- pos_t place_option_list[PLACE_OPTION_MAX];
- #define PLACED_BOX_MAX 100
- int placed_box_cnt = 0;
- pbox_t placed_box_list[PLACED_BOX_MAX];
- uint32_t placed_box_area_max_x;
- uint32_t placed_box_area_max_y;
- uint32_t placed_box_area_value;
- /*============================================*/
- int place_option_find(pos_t *p)
- {
- int i;
- for( i = 0; i < place_option_cnt; i++ )
- {
- if ( place_option_list[i].x == p->x && place_option_list[i].y == p->y)
- return i; // place option already exists
- }
- return -1;
- }
- void place_option_add(pos_t *p)
- {
- int i;
- assert(place_option_cnt < PLACE_OPTION_MAX);
-
- if ( place_option_find(p) >= 0 )
- return; // place option already exists
-
- // the placement option also must not be part of any existing box
- for( i = 2; i < placed_box_cnt; i++ )
- {
- if ( p->x >= placed_box_list[i].pos.x && p->x < placed_box_list[i].pos.x + box_list[placed_box_list[i].box_idx].w )
- if ( p->y >= placed_box_list[i].pos.y && p->y < placed_box_list[i].pos.y + box_list[placed_box_list[i].box_idx].h )
- return; // place option would be inside an existing box
- }
-
- // place option does not exist, add new place option
-
- place_option_list[place_option_cnt] = *p;
- place_option_cnt++;
- }
- void place_option_by_xy(uint32_t x, uint32_t y)
- {
- pos_t p;
- p.x = x;
- p.y = y;
- place_option_add(&p);
- }
- void place_option_delete(int idx)
- {
- if ( idx < 0 || idx >= place_option_cnt )
- return;
- for( ; idx+1 < place_option_cnt; idx++ )
- {
- place_option_list[idx] = place_option_list[idx+1];
- }
- place_option_cnt--;
- }
- /*============================================*/
- // p is copyied, b only the address is stored
- pbox_t *placed_box_push(pos_t *p, int box_idx)
- {
- assert(placed_box_cnt < PLACED_BOX_MAX);
-
- // place the new box
- placed_box_list[placed_box_cnt].pos = *p;
- placed_box_list[placed_box_cnt].box_idx = box_idx;
- placed_box_cnt++;
- return placed_box_list+placed_box_cnt-1;
- }
- void placed_box_pop(void)
- {
- assert(placed_box_cnt > 0);
- placed_box_cnt--;
- }
- uint32_t placed_box_calculate_max_area(void)
- {
- int i;
- placed_box_area_max_y = 0;
- placed_box_area_max_x = 0;
- for( i = 2; i < placed_box_cnt; i++ )
- {
-
- if ( placed_box_area_max_y < placed_box_list[i].pos.y + box_list[placed_box_list[i].box_idx].h )
- placed_box_area_max_y = placed_box_list[i].pos.y + box_list[placed_box_list[i].box_idx].h;
- if ( placed_box_area_max_x < placed_box_list[i].pos.x + box_list[placed_box_list[i].box_idx].w )
- placed_box_area_max_x = placed_box_list[i].pos.x + box_list[placed_box_list[i].box_idx].w;
- }
-
- if ( placed_box_area_max_x > WORD_CLOUD_MAX_X )
- // weight of y is higher, so this should give a more wider picture
- placed_box_area_value = placed_box_area_max_x*5 + placed_box_area_max_y ;
- else
- // weight of y is higher, so this should give a more wider picture
- placed_box_area_value = placed_box_area_max_x + placed_box_area_max_y *5;
- return placed_box_area_value;
- }
- /*============================================*/
- int is_intersection(pos_t *p1, box_t *b1, pos_t *p2, box_t *b2)
- {
- pos_t q1 = *p1;
- pos_t q2 = *p2;
- q1.x += b1->w;
- q1.y += b1->h;
- q2.x += b2->w;
- q2.y += b2->h;
-
- if ( p1->x >= q2.x || q1.x <= p2->x )
- return 0;
- if ( p1->y >= q2.y || q1.y <= p2->y )
- return 0;
-
- return 1;
- }
- int is_intersection_with_placed_box(pos_t *p1, box_t *b1, int idx)
- {
- return is_intersection(p1, b1, &(placed_box_list[idx].pos), box_list+placed_box_list[idx].box_idx );
- }
- int is_any_intersection(pos_t *p1, box_t *b1)
- {
- int i;
- // start with the third box, because the first two are boundary boxes
- for( i = 2; i < placed_box_cnt; i++ )
- {
- if ( is_intersection_with_placed_box(p1, b1, i) != 0 )
- return 1;
- }
- return 0;
- }
- // add new place options by a give pbox
- void place_option_by_pbox(pbox_t *pbox)
- {
- int i, found_i;
- uint32_t y, x;
- uint32_t max_y, max_x;
-
- // from the lower left corner, search towards the left until another box is hit.
- y = pbox->pos.y + box_list[pbox->box_idx].h;
- max_x = 0;
- found_i = -1;
- for( i = 0; i < placed_box_cnt; i++ )
- {
- if ( placed_box_list+i != pbox ) // do not check ourself
- {
- if ( placed_box_list[i].pos.x <= pbox->pos.x )
- {
- if ( y >= placed_box_list[i].pos.y && y < placed_box_list[i].pos.y + box_list[placed_box_list[i].box_idx].h )
- {
- // left box found, but is it max?
- // must use >= here, because the initial boxes have zero area
- if ( max_x <= placed_box_list[i].pos.x + box_list[placed_box_list[i].box_idx].w )
- {
- max_x = placed_box_list[i].pos.x + box_list[placed_box_list[i].box_idx].w;
- found_i = i;
- }
- }
- }
- }
- }
- if (found_i >= 0)
- place_option_by_xy(max_x, y);
-
- // from the upper right corner, search towards the top until another box is hit.
- x = pbox->pos.x + box_list[pbox->box_idx].w;
- max_y = 0;
- found_i = -1;
- for( i = 0; i < placed_box_cnt; i++ )
- {
- if ( placed_box_list+i != pbox ) // do not check ourself
- {
- if ( placed_box_list[i].pos.y <= pbox->pos.y )
- {
- if ( x >= placed_box_list[i].pos.x && x < placed_box_list[i].pos.x + box_list[placed_box_list[i].box_idx].w )
- {
- // upper box found, but is it the next ?
- // must use >= here, because the initial boxes have zero area
- if ( max_y <= placed_box_list[i].pos.y + box_list[placed_box_list[i].box_idx].h )
- {
- max_y = placed_box_list[i].pos.y + box_list[placed_box_list[i].box_idx].h;
- found_i = i;
- }
- }
- }
- }
- }
- if (found_i >= 0)
- place_option_by_xy(x, max_y);
- }
- void add_all_place_options(void)
- {
- int i;
- //place_option_cnt = 0; // clear the place option list
- for( i = 2; i < placed_box_cnt; i++ )
- {
- place_option_by_pbox(placed_box_list+i);
- }
- }
- void show(void)
- {
- pos_t p;
- box_t b;
- int i;
- b.w = 1;
- b.h = 1;
- for( p.y = 0; p.y < 30; p.y++ )
- {
- for( p.x = 0; p.x < 60; p.x++ )
- {
- for( i = 0; i < place_option_cnt; i++ )
- {
- if ( place_option_list[i].x == p.x && place_option_list[i].y == p.y )
- {
- break;
- }
- }
- if ( i < place_option_cnt )
- {
- printf("*");
- }
- else
- {
-
- for( i = 0; i < placed_box_cnt; i++ )
- {
- if ( is_intersection_with_placed_box(&p, &b, i) != 0 )
- break;
- }
- if ( i < placed_box_cnt )
- {
- printf("%c", i+'a');
- }
- else
- {
- printf(" ");
- }
- }
- }
- printf("\n");
- }
- }
- void init(void)
- {
- pos_t p;
-
- box_list[0].w = 0x0ffffffff;
- box_list[0].h = 0;
- box_list[1].w = 0;
- box_list[1].h = 0x0ffffffff;
-
- box_cnt = 2;
-
- p.x = 0;
- p.y = 0;
- placed_box_push(&p, 0);
- p.x = 0;
- p.y = 0;
- placed_box_push(&p, 1);
- // create one place option at the upper left
- place_option_by_xy(0, 0);
-
- }
- void do_best_place(int box_idx)
- {
- int i;
- int found_i;
- pbox_t *pbox;
- uint32_t value;
- uint32_t lowest_value;
-
- found_i = -1;
- lowest_value = 0x0ffffffff;
- for( i = 0; i < place_option_cnt; i++ )
- {
- // check whether this placement would generate an intersection
- if ( is_any_intersection(place_option_list+i, box_list+box_idx) == 0 )
- {
- // place the box at the position
- pbox = placed_box_push(place_option_list+i, box_idx);
- value = placed_box_calculate_max_area();
- /*
- if ( value == 0x0ffffffff )
- {
- value = pbox->pos.y;
- }
- else
- */
- {
- value *= 8;
- value += pbox->pos.x;
- value += pbox->pos.y;
- }
-
- // greedy algorithm: We search for the lowest area increase
- if ( lowest_value > value )
- {
- lowest_value = value ;
- found_i = i;
- }
-
- placed_box_pop();
- }
- }
- if ( found_i >= 0 )
- {
-
- // now permanently place the box
- pbox = placed_box_push(place_option_list+found_i, box_idx);
- // delete the position from the place option list
- place_option_delete(found_i);
-
- // calculate new place options with the new box
- //place_option_by_pbox(pbox);
-
- // recalculate all place options
- add_all_place_options();
- }
- else
- {
- assert(found_i >= 0 );
- }
- }
- /*
- Linear Congruential Generator (LCG)
- z = (a*z + c) % m;
- m = 256 (8 Bit)
-
- for period:
- a-1: dividable by 2
- a-1: multiple of 4
- c: not dividable by 2
-
- c = 17
- a-1 = 64 --> a = 65
- */
- uint8_t cloud_z = 127; // start value
- uint8_t cloud_rnd(void) {
- cloud_z = (uint8_t)((uint16_t)65*(uint16_t)cloud_z + (uint16_t)17);
- return (uint8_t)cloud_z;
- }
- //u8g2_IsAllValidUTF8
- char *cloud_utf8[] =
- {
- "µC"
- "Numérique"
- "像素",
- "屏幕",
- "图形",
- "Ψηφιακή",
- "Οθόνη",
- "Γραφικά",
- "アイコン、",
- "ビットマップ",
- "キャラクター、",
- "전자", "엔지니어", "장치", "하드웨어",
- "Ingeniør", "Skærm",
- "Gerät",
- "Sprzęt",
- "Računar", "Ugrađen",
- "Grafică",
- "экран",
- "Графика",
- "Значок",
- "Фонт", "екран", "рачунар", "уграђен",
- "พิกเซล",
- "หน้าจอ",
- "กราฟิก",
- "Gömülü",
- "ĂăĚěŇň",
- "ÄäÖöÜü",
- "Ææ",
- "E=mc²"
- };
- char *cloud_str[] =
- {
- "Pixel",
- "Screen",
- "Graphics",
- "Icon",
- "Bitmap",
- "Character",
- "Glyph",
- "Font",
- "Display",
- "Computer",
- "Embedded",
- "Electronics",
- "Engineer",
- "Device",
- "Hardware",
- "Software",
- "Science",
- "Digital",
- "Arduino",
- "U8g2"
- };
- char *cloud_simple[] =
- {
- "U8g2",
- "Abc",
- "XYZ",
- "Aa",
- "Xy"
- };
- void cloud_add(u8g2_t *u8g2, const uint8_t *font, char *word)
- {
- u8g2_uint_t extra = 8;
- u8g2_SetFont(u8g2, font);
- box_list[box_cnt].w = u8g2_GetUTF8Width(u8g2, word) + extra;
- box_list[box_cnt].h = u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2) + extra;
- strcpy(box_word[box_cnt], word);
- //puts(word);
- box_font[box_cnt] = font;
- box_cnt++;
- }
- void cloud_auto_add(u8g2_t *u8g2, const uint8_t *font)
- {
- int i, n, cnt;
-
- u8g2_SetFont(u8g2, font);
-
-
- if ( u8g2_GetAscent(u8g2) - u8g2_GetDescent(u8g2) > 30 )
- {
- n = sizeof(cloud_simple)/sizeof(*cloud_simple);
-
- cnt = 0;
- for( i = 0; i < n; i++ )
- {
- if ( u8g2_IsAllValidUTF8(u8g2, cloud_simple[i]) != 0 )
- {
- cnt++;
- }
- }
-
- if ( cnt > 0 )
- {
- cnt = cloud_rnd() % cnt;
-
- for( i = 0; i < n; i++ )
- {
- if ( u8g2_IsAllValidUTF8(u8g2, cloud_simple[i]) != 0 )
- {
- if ( cnt == 0 )
- break;
- cnt--;
- }
- }
- }
-
- if ( i < n )
- {
- cloud_add(u8g2, font, cloud_simple[i]);
- return;
- }
-
- }
-
- n = sizeof(cloud_utf8)/sizeof(*cloud_utf8);
- //printf("n=%d\n", n);
-
- cnt = 0;
- for( i = 0; i < n; i++ )
- {
- if ( u8g2_IsAllValidUTF8(u8g2, cloud_utf8[i]) != 0 )
- {
- cnt++;
- }
- }
-
- if ( cnt > 0 )
- {
- cnt = cloud_rnd() % cnt;
-
- for( i = 0; i < n; i++ )
- {
- if ( u8g2_IsAllValidUTF8(u8g2, cloud_utf8[i]) != 0 )
- {
- if ( cnt == 0 )
- break;
- cnt--;
- }
- }
- }
- else
- {
- i = n;
- }
-
- if ( i < n )
- {
- cloud_add(u8g2, font, cloud_utf8[i]);
- return;
- }
-
- n = sizeof(cloud_str)/sizeof(*cloud_str);
- //printf("n=%d\n", n);
- i = cloud_rnd() % n;
- cloud_add(u8g2, font, cloud_str[i]);
-
- }
- void cloud_init(void)
- {
- init();
- }
- void cloud_calculate(uint8_t z)
- {
- int i;
- int a, b, t;
-
- cloud_z = z;
-
- for( i = 0; i < box_cnt; i++ )
- {
- box_index[i] = i;
- }
-
- for ( i = 0; i < box_cnt / 2; i++ )
- {
- a = cloud_rnd() % (box_cnt-2);
- a += 2;
- b = cloud_rnd() % (box_cnt-2);
- b += 2;
- t = box_index[a];
- box_index[a] = box_index[b];
- box_index[b] = t;
- }
-
- for( i = 2; i < box_cnt; i++ )
- do_best_place(box_index[i]);
- }
- void cloud_draw(u8g2_t *u8g2)
- {
- int i;
- for( i = 2; i < placed_box_cnt; i++ )
- {
- u8g2_SetFont(u8g2, box_font[placed_box_list[i].box_idx]);
- u8g2_DrawUTF8(u8g2,
- placed_box_list[i].pos.x,
- placed_box_list[i].pos.y,
- box_word[placed_box_list[i].box_idx]);
- }
- }
- u8g2_t u8g2;
- int main(void)
- {
- tga_desc_fg_r = 0;
- tga_desc_fg_g = 0;
- tga_desc_fg_b = 0;
- tga_desc_bg_r = 255;
- tga_desc_bg_g = 255;
- tga_desc_bg_b = 255;
- u8g2_SetupBuffer_TGA_DESC(&u8g2, &u8g2_cb_r0);
- u8x8_InitDisplay(u8g2_GetU8x8(&u8g2));
- u8x8_SetPowerSave(u8g2_GetU8x8(&u8g2), 0);
- u8g2_SetFont(&u8g2, u8g2_font_helvB18_tr);
- u8g2_SetFontPosTop(&u8g2);
-
- cloud_init();
- /*
- cloud_add(&u8g2, u8g2_font_helvR12_tr, "Embedded");
- cloud_add(&u8g2, u8g2_font_helvB12_tr, "Electronics");
- cloud_add(&u8g2, u8g2_font_helvR14_tr, "Arduino");
- cloud_add(&u8g2, u8g2_font_helvB14_tr, "Font");
- cloud_add(&u8g2, u8g2_font_helvR18_tr, "Controller");
- cloud_add(&u8g2, u8g2_font_helvB18_tr, "U8g2");
- cloud_add(&u8g2, u8g2_font_helvR24_tr, "ABC");
- cloud_add(&u8g2, u8g2_font_helvB24_tr, "XYZ");
- */
- cloud_auto_add(&u8g2, u8g2_font_helvR12_tr);
- cloud_auto_add(&u8g2, u8g2_font_helvB12_tr);
- cloud_auto_add(&u8g2, u8g2_font_helvR14_tr);
- cloud_auto_add(&u8g2, u8g2_font_helvB14_tr);
- cloud_auto_add(&u8g2, u8g2_font_helvR18_tr);
- cloud_auto_add(&u8g2, u8g2_font_helvB18_tr);
-
- cloud_auto_add(&u8g2, u8g2_font_gb16st_t_3);
- cloud_auto_add(&u8g2, u8g2_font_wqy12_t_gb2312);
- cloud_auto_add(&u8g2, u8g2_font_wqy14_t_gb2312);
- cloud_auto_add(&u8g2, u8g2_font_b10_t_japanese2);
- cloud_auto_add(&u8g2, u8g2_font_b16_b_t_japanese3);
- cloud_auto_add(&u8g2, u8g2_font_cu12_t_greek);
- cloud_auto_add(&u8g2, u8g2_font_cu12_t_cyrillic);
- cloud_auto_add(&u8g2, u8g2_font_unifont_t_korean2);
- cloud_auto_add(&u8g2, u8g2_font_unifont_t_polish);
- cloud_auto_add(&u8g2, u8g2_font_logisoso54_tf);
-
- cloud_auto_add(&u8g2, u8g2_font_gb16st_t_3);
- cloud_auto_add(&u8g2, u8g2_font_wqy12_t_gb2312);
- cloud_auto_add(&u8g2, u8g2_font_wqy14_t_gb2312);
- cloud_auto_add(&u8g2, u8g2_font_b10_t_japanese2);
- cloud_auto_add(&u8g2, u8g2_font_b16_b_t_japanese3);
- cloud_auto_add(&u8g2, u8g2_font_cu12_t_greek);
- cloud_auto_add(&u8g2, u8g2_font_cu12_t_cyrillic);
- cloud_auto_add(&u8g2, u8g2_font_unifont_t_korean2);
- cloud_auto_add(&u8g2, u8g2_font_unifont_t_polish);
- cloud_auto_add(&u8g2, u8g2_font_logisoso58_tf);
- cloud_calculate(4);
-
-
- u8g2_FirstPage(&u8g2);
- do
- {
- cloud_draw(&u8g2);
- /*
- u8g2_DrawFrame(&u8g2,
- placed_box_list[i].pos.x,
- placed_box_list[i].pos.y,
- box_list[placed_box_list[i].box_idx].w,
- box_list[placed_box_list[i].box_idx].h);
- */
-
- //u8g2_SetFont(&u8g2, u8g2_font_helvB18_tr);
- // u8g2_DrawStr(&u8g2, 20, 20, "abc");
-
- } while( u8g2_NextPage(&u8g2) );
- //tga_save("u8g2.tga");
- tga_save_png("u8g2.png");
- return 0;
- }
|