Перейти к содержанию
    

Алгоритм или программная реализация попиксельной бегущей строки

Нужен алгоритм или программная реализация попиксельной бегущей строки для вывода на дисплей разрешением 240х320. Длина строки в пикселях может быть больше 240. Используется шрифт, в котором символы имеют разную ширину. Бегущая строка должна двигаться по кругу по типу: "ая строка - Это бегу". В конце строки нужно вставлять символы разделения, например, " - ". Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Алгоритм для примера.

 

1.

Конструируем требуемую строку.

Считаем её длину в пикселах (L), выделяем в памяти буфер размером <масксимальная_высота_символов> * L.

Рисуем всю строку в буфере.

2.

Копируем 240 столбцов из буфера на экран начиная с первого столбца буфера.

Пауза.

...

Копируем 240 столбцов из буфера на экран начиная со столбца L-240+1 буфера.

Пауза.

Копируем 239 столбцов из буфера на экран начиная со столбца L-240 буфера, следом 1 столбец начиная со столбца 1 буфера.

Пауза.

...

Копируем 1 столбец из буфера на экран начиная со столбца L буфера, следом 239 столбцов начиная со столбца 1 буфера.

Пауза.

3.

Переходим к пункту 2.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Получается, если длина строки в пикселях 340, а высота шрифта 24 пикселя, то нужен буфер 8160 байт?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну, если не нужны буквы с попиксельной раскраской, можно выделить на точку 1 бит и получить 3 * 340 = 1020 байт :)

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне такой подход совсем не по душе.

Вот то, что получилось у меня:

void scrolling(char *Buffer, uint16_t *ScrlPos)
{
       char tmp[50];
    uint16_t bufferlen, len;
    uint16_t pos = *ScrlPos;
    uint8_t index = 0, offset = 0;

    bufferlen = string_width(Buffer);

    tmp[0] = 0;

    if(bufferlen > pos)
    {
        do
        {
            tmp[offset] = Buffer[offset];
            offset++;
        }while((string_width(tmp) - 1) < pos);
        offset--;
        tmp[offset] = 0;
        pos = *ScrlPos - string_width(tmp);
        memset(tmp, 0, sizeof(tmp));
        while(string_width(tmp) < (SCREEN_WIDTH + pos))
        {
            if((index + offset) >= strlen(Buffer))
                break;
            tmp[index] = Buffer[index + offset];
            index++;
        }
        tmp[index] = 0;
    }
    else
    {
        pos -= bufferlen;
        memset(tmp, 0, sizeof(tmp));
    }
         
    len = string_width(tmp);

    if(len < (SCREEN_WIDTH + pos))
    {
        tmp[index++] = (char)'-';
        tmp[index++] = (char)'-';
        tmp[index++] = (char)'-';
        tmp[index] = 0;

        len = string_width(tmp, NULL_PIXEL);

        if(len < (SCREEN_WIDTH + pos))
            offset = 0;
            while(string_width(tmp) < (SCREEN_WIDTH + pos))
            {
                tmp[index] = Buffer[offset];
                index++;
                offset++;
            }
            tmp[index] = 0;
    }

    string_print(tmp, pos);     

    *(ScrlPos)++;

    if(*ScrlPos > (bufferlen + string_width(" - ")))
        *ScrlPos = 0;            
}

 

Вызывается так:

uint16_t pos_in_string;

scrolling("Длинная бегущая строка", &pos_in_string);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я использую несколько модифицированную функцию string_width.

//----------------------------------------------------------------------------------------------
// Описание: Расчет ширины строки   
// Принимает: указатель на строку, интервал между символами    
// Возвращает: ширина строки  
//----------------------------------------------------------------------------------------------
uint16_t string_width(char *text, uint8_t ch_interval)
{
    char c;                     
    uint16_t i = 0;                

    while(c = *(text++))                       //Выполнять для всей строки
      {
           i += char_width(c);        //Расчет ширины символа
           i += ch_interval;                                //Учет межсимвольного пространства
      }
    i -= ch_interval;                       //Устранение межсимвольного пространства после последнего символа

    return(i);                                 //Возврат ширины строки
}
//----------------------------------------------------------------------------------------------

Функция char_width зависит от типа используемого шрифта.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

тогда возникает вопрос - а что у нас char_width() :)

Изменено пользователем Jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если озу экрана читается то делал бы так.

Сдвиг содержимого экрана на один пиксель влево и добавление справа одного очередного столбца символа.

Создал бы таблицу ширин всех символов и помнил бы номер выводимого символа в строке и номер последнего выведенного его столбца.

И буферов не надо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

тогда возникает вопрос - а что у нас char_width() :)

uint8_t char_width(uint8_t c)
{
    uint8_t codepage_index, char_index = 0;
    uint8_t codepage_count = font_pcodepage->cph.cprnum;
    uint16_t index = 0;
    pgsymbol_t p = font_psymbols;

    for(codepage_index = 0; codepage_index < codepage_count; codepage_index++)        //Выполнять для всех кодовых страниц 
    {
        if((c >= font_pcodepage->cpr[codepage_index].min) &&                
           (c <= font_pcodepage->cpr[codepage_index].max))        //Если символ в кодовой странице, то 
        {
            while(c > (font_pcodepage->cpr[codepage_index].min + index))    //Выполнять до нахождения символа 
                index++;                                                            //Увеличение индекса  

            break;
           }
        else                                                                        //Иначе 
            char_index += font_pcodepage->cpr[codepage_index].max - font_pcodepage->cpr[codepage_index].min + 1;    
    }

    char_index += index;                                                            //Индекс символа в шрифте 

    p += char_index * ((font_symsize + 4) / 4);                                    //Указатель на символ 

    return ((pgcsymbol_t) p)->sh.cxpix;                    //Возврат ширины символа
}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...