Как правильно очищать окно X при рисовании на нем через поверхность Каира? - PullRequest
0 голосов
/ 17 мая 2018

Я пытаюсь нарисовать прозрачное окно X с помощью Cairo. Согласно официальному Cairo FAQ , способ очистить прозрачную поверхность - установить для оператора Cairo значение CLEAR. Это не работает в моем случае. Я рисую растущий и уменьшающийся заполненный круг. Сначала круг увеличивается, но когда он сжимается, большие круги остаются на окне. Это заставляет меня думать, что, возможно, мне следует очищать и само окно X при каждой перерисовке.

Это код, который я придумал

XClearWindow(self->display, self->win_id);
cairo_push_group(self->context);

// Re-draw the whole canvas: Doesn't work as expected
// cairo_save(self->context);
// cairo_set_operator(self->context, CAIRO_OPERATOR_CLEAR);
// cairo_paint(self->context);
// cairo_restore(self->context);

// Invoke the draw callback <- Cairo drawing done here from Python
Canvas_on_draw(self, args_tuple, NULL);

cairo_pop_group_to_source(self->context);
cairo_paint(self->context);
cairo_surface_flush(self->surface);

XFlush(self->display);

Как видите, мое решение - позвонить XClearWindow до рисования в Каире, а затем очистить все с помощью XFlush. Тем не менее, я не уверен, что это самое чистое решение, и это похоже на взлом, а не на правильный подход. Например, без XFlush я получаю значительное мерцание, но документация Xlib, похоже, намекает на то, что большинству приложений не нужно вызывать эту функцию напрямую.


РЕДАКТИРОВАТЬ : После ответа ниже, вот как выглядит мой код:

    cairo_push_group(self->context);
    // Draw stuff
    cairo_pop_group_to_source(self->context);

    // The following cairo paradigm seems to have the same
    // effect as the following commented out lines:
    // XClearWindow(self->display, self->win_id);
    // cairo_paint(self->context);
    cairo_save(self->context);
    cairo_set_operator(self->context, CAIRO_OPERATOR_SOURCE);
    cairo_paint(self->context);
    cairo_restore(self->context);

Это делает намеченную вещь.

1 Ответ

0 голосов
/ 28 мая 2018

Добавить cairo_set_operator(self->context, CAIRO_OPERATOR_SOURCE); перед вашим окончательным cairo_paint().

Вы очищаете промежуточную группу, которую вы создали.Это означает, что он полностью прозрачен за пределами круга.Затем вы рисуете эту группу в целевом окне с оператором по умолчанию, который OVER.Рисование абсолютно прозрачным над чем-либо просто оставляет там старый контент.Рисование с помощью SOURCE фактически копирует источник на целевую поверхность.

Примечание: Ваш подход XClearWindow не гарантированно сработает, если вы не вызовете cairo_surface_flush и cairo_surface_mark_dirty, если необходимо, вокруг него.

...