Комментарии 11
Статья хорошая. Блеванул от форматирования кода.
if(result&&cr)
{cairo_stroke(cr);}
else
printf("Ошибка отрисовки\n");
return FALSE;
typedef struct{
GtkApplication *restrict app;
GtkWidget *restrict win;
GtkBuilder *restrict builder;
}appdata;
Так нельзя. Это обучающая статья по работе с библиотекой, важный компонентом является не только текст статьи, картинки, но и сам код.
В main.c затесался <b>main.c</b>
.
Краткое ревью кода
Сюда должен передаваться указатель на data:
Далее в обработчике эти данные можно получить:
Получение данные рекомендую делать однотипно и всегда первой строкой. Однако можете даже сразу в функции объявить требуемый тип данный:
Среди этих двух вариантов всё зависит от того, как принято в рамках проекта, т. к. они эквивалентны с точки зрения Си.
Аналогично с обработчиком завершения.
Глобальные переменные в заголовочном файле — это бессмысленная и крайне плохая практика. Такой файл никуда больше не подключишь, т. к. будет повторное создание переменных. Крайний случай — extern, но лучше писать полностью реентерабельные решения без использования глобальных переменных.
Форматирование тоже выбрано не очень удачным. Рекомендую везде и всегда ставить фигурные скобки, это повышает единообразие кода, соответственно, и читабельность.
Работа со строками тоже не является качественной. Как минимум в таких случаях делают PATH_MAX:
char* result=(char*)calloc(1024,sizeof(char));
Но в таком случае обходятся обычно стековым массивом, тут вообще нет смысла выделять память, т. к. алгоритм не предполагает выполнения realloc() в случае нехватки выделенной памяти.
Просмотрел бегло, если интересно, могут отрецензировать более подробно.
Сюда должен передаваться указатель на data:
g_signal_connect(data.app, «activate», G_CALLBACK(application_activate),NULL&data);
Далее в обработчике эти данные можно получить:
void application_activate(GtkApplication *application, gpointer user_data)
{
appdata *data_ptr = user_data;
GtkBuilder *builder=builder_init();
data_ptr=&data;
Получение данные рекомендую делать однотипно и всегда первой строкой. Однако можете даже сразу в функции объявить требуемый тип данный:
void application_activate(GtkApplication *application, appdata *data_ptr)
Среди этих двух вариантов всё зависит от того, как принято в рамках проекта, т. к. они эквивалентны с точки зрения Си.
Аналогично с обработчиком завершения.
Глобальные переменные в заголовочном файле — это бессмысленная и крайне плохая практика. Такой файл никуда больше не подключишь, т. к. будет повторное создание переменных. Крайний случай — extern, но лучше писать полностью реентерабельные решения без использования глобальных переменных.
Форматирование тоже выбрано не очень удачным. Рекомендую везде и всегда ставить фигурные скобки, это повышает единообразие кода, соответственно, и читабельность.
Работа со строками тоже не является качественной. Как минимум в таких случаях делают PATH_MAX:
char* result=(char*)calloc(1024,sizeof(char));
Но в таком случае обходятся обычно стековым массивом, тут вообще нет смысла выделять память, т. к. алгоритм не предполагает выполнения realloc() в случае нехватки выделенной памяти.
Просмотрел бегло, если интересно, могут отрецензировать более подробно.
Спасибо за ревью. В следующей статье учту рекомендации. Да и архив с исходниками надо будет прикрепить.
Пожалуйста. Наконец, добрался до этой статьи ещё раз, для загрузки SVG нативная поддержка есть в GdkPixbufLoader.В итоге получается GdkPixbuf. Явно задать размер можно по обработчику «size-prepared», для этого в нём требуется вызвать функцию gdk_pixbuf_loader_set_size(). Любые данные туда можно опять же передать через user_data. При этом в обработчик попадают натуральные размеры, которые заданы в самом svg-файле. При создании своего виджета на основе картинки, к примеру, можно использовать эти размеры как натуральные для виджета (у виджетов есть натуральные и минимальные).
Единственное «но» — если требуется изменить размер, Pixbuf требуется пересоздавать, но оно и понятно, — по-другому никак. Для этого можно закешировать файл в GBytes, и писать его через gdk_pixbuf_loader_write_bytes(). Для чтения файла рекомендую g_mapped_file_get_bytes().
Если будут вопросы, спрашивайте, что могу, подскажу.
Единственное «но» — если требуется изменить размер, Pixbuf требуется пересоздавать, но оно и понятно, — по-другому никак. Для этого можно закешировать файл в GBytes, и писать его через gdk_pixbuf_loader_write_bytes(). Для чтения файла рекомендую g_mapped_file_get_bytes().
Если будут вопросы, спрашивайте, что могу, подскажу.
И ещё, если пишете под GLib, то лучше и используйте функции GLib. Например, вместо calloc()/free() лучше использовать g_malloc0()/g_free(). Результат такого выделения памяти не требуется проверять на NULL, т. к. в него встроен g_assert(), что называется «ленивым программированием».
У Вас же используется calloc()/free(), но не проверяется результат работы этой функции calloc(). Она имеет полное право вернуть NULL, если памяти не хватило. В общедоступных примерах такие проверки обязательно должны быть всегда и везде, иначе новички могут приучиться к плохому.
А почему не используете вместо get_real_path() стандартную функцию realpath()?
У Вас же используется calloc()/free(), но не проверяется результат работы этой функции calloc(). Она имеет полное право вернуть NULL, если памяти не хватило. В общедоступных примерах такие проверки обязательно должны быть всегда и везде, иначе новички могут приучиться к плохому.
А почему не используете вместо get_real_path() стандартную функцию realpath()?
И ещё одну вещь пропустил, всегда sizeof(char) == 1, это гарантируется компилятором. Что, как и почему — хорошо описано в Википедии. Поэтому проще и понятнее не использовать sizeof в этом случае. Сам некоторое время страдал такой паранойей, пока в стандарт не полез:
www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf
Уж извиняюсь, что много написал, посто делать ревью кода и показывать все недостатки уже в привычке по работе, а код на Си тут редко проплывает, не могу пройти мимо. :)
www.open-std.org/jtc1/sc22/wg14/www/abq/c17_updated_proposed_fdis.pdf
Уж извиняюсь, что много написал, посто делать ревью кода и показывать все недостатки уже в привычке по работе, а код на Си тут редко проплывает, не могу пройти мимо. :)
Да, использование g_malloc0()/g_free() является более правильным с точки зрения ведения логов. Действительно, поддержка svg есть
Выдало форматы: GdkPixdata, tiff, jpeg, tga, bmp, wmf, png, svg, ico, qtif, gif, ani, xpm, xbm, pnm, icns
GSList *list_header=gdk_pixbuf_get_formats();
GSList *list=list_header;
while(list->next!=NULL)
{
printf("%s\n",gdk_pixbuf_format_get_name(list->data));
list=list->next;
}
printf("%s\n",gdk_pixbuf_format_get_name(list->data));
g_slist_free(list_header);
Выдало форматы: GdkPixdata, tiff, jpeg, tga, bmp, wmf, png, svg, ico, qtif, gif, ani, xpm, xbm, pnm, icns
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Использование GtkApplication. Особенности отрисовки librsvg