Pull to refresh

Comments 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>.

Я с вами полностью согласен; Не пойму почему минусуют.
Плюс ко всему ключевое слово restrict понапихано абсолютно везде где нужно и не нужно, при чем там где не нужно намного превышает там где нужно.

Краткое ревью кода

Сюда должен передаваться указатель на 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().

Если будут вопросы, спрашивайте, что могу, подскажу.
И ещё, если пишете под GLib, то лучше и используйте функции GLib. Например, вместо calloc()/free() лучше использовать g_malloc0()/g_free(). Результат такого выделения памяти не требуется проверять на NULL, т. к. в него встроен g_assert(), что называется «ленивым программированием».

У Вас же используется 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

Уж извиняюсь, что много написал, посто делать ревью кода и показывать все недостатки уже в привычке по работе, а код на Си тут редко проплывает, не могу пройти мимо. :)
Ещё раз спасибо за содержательное ревью.
Да, использование g_malloc0()/g_free() является более правильным с точки зрения ведения логов. Действительно, поддержка svg есть
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

Этот код не покажет последний элемент. Нужно так:

for (list = list_header; list != NULL; list = list->next)

Приведённый код нормальный, после while есть ещё 1 printf, поэтому покажет правильно, но в целом да, через for будет более лаконично.

Sign up to leave a comment.

Articles