Cairo surface auf SDL Surface abbilden.
-
Hi,
ich habe das Hauptprogramm nach deinen vorschlägen so angepasst:
#include <cstdlib> #include <string> #include <iostream> using namespace std; #include <SDL/SDL.h> #include <cairo/cairo.h> #include "init.hpp" #include "util.hpp" int main() { SDL_Surface* mainSurface; mainSurface = Initialize(1280, 1024); FillSurface(mainSurface, 0x00ffffff); SDL_LockSurface(mainSurface); cairo_surface_t* surface = cairo_image_surface_create_for_data( static_cast<unsigned char*>(mainSurface->pixels), CAIRO_FORMAT_RGB24, 1280, 1024, 0); cairo_t* cr = cairo_create(surface); cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); cairo_set_line_width(cr, 5); cairo_move_to(cr, 100 , 100); cairo_line_to(cr, 1280-100, 100); cairo_line_to(cr, 1280-100, 1024-100); cairo_line_to(cr, 100 , 1024-100); cairo_line_to(cr, 100 , 100); cairo_paint(cr); SDL_UnlockSurface(mainSurface); SDL_Flip(mainSurface); SDL_Delay(5000); exit(0); }Das Programm wird kompiliert und läuft, allerdings ist das erwartete rechteck nicht zu sehen. Danke schonmal für deine hilfe.
An den anderen Dateien habe ich nichts verändert.
-
kannst du ein pixel in der surface setzen ?
unsigned char* pPixels = static_cast<unsigned char*>(mainSurface->pixels); //setze pixel in die mitte unsigned int pixbytes = 4, stride = 1280 * pixbytes, x = stride / 2, y = 1024 / 2, rowPos = y * stride, pixPos = rowPos + x; pPixels[pixPos++] = 0xFF; //a pPixels[pixPos++] = 0xFF; //r pPixels[pixPos++] = 0x00; //g pPixels[pixPos++] = 0x00; //bwenn ja dann isses ein cairo problem.
wobe ich kA von cairo habe, hab für den vorigen code die cairo doku konsultiert
-
Ich hab mich gerade eben mal in Cairo eingearbeitet (ich mags
)
Es müsste erstmal cairo_fill heißen, da cairo_paint den kompletten bereich mit der in gesetzen Farbe (hier schwarz) füllt. Oder cairo_stroke, wenn du die umrandungslinien deines Rechteckes sehen willst.
Weiterhin gibts die Funktion cairo_rectangle zum Rechteck zeichnen
Und du solltest cairo_surface_flush( surface ); aufrufen, um sicherzugehen, dass die Zeichnunen auch auf Pixelebene landen.Ich habe selbst mal ein Beispiel mit cairo/sdl implementiert:
include <cairo.h> #include <stdlib.h> #include <time.h> #include <SDL/SDL.h> int main( void ) { int run = 1; double angel = 0; int i, last_frame; cairo_matrix_t matrix; srand( time( NULL ) ); /* erstelle das sdl-surface */ SDL_Init( SDL_INIT_VIDEO ); SDL_Surface *screen = SDL_SetVideoMode( 640, 480, 32, SDL_SWSURFACE | SDL_DOUBLEBUF ); SDL_Surface *argb_surface = SDL_CreateRGBSurface( SDL_SWSURFACE, 640, 480, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 ); /* a r g b, genau wie bei cairo argb32 */ /* erstelle unser cairo-surface */ cairo_surface_t *image = cairo_image_surface_create_for_data( (unsigned char*)screen->pixels, CAIRO_FORMAT_ARGB32, 640, 480, 640 * 4 ); cairo_t *dc = cairo_create( image ); cairo_surface_destroy( image ); /* erstelle einen zufälligen pfad */ cairo_new_path( dc ); for( i = 0; i < 20; i++ ) { int left = rand() % 300 + 200; int top = rand() % 300 + 100; int x1 = left + rand() % 60 - 30; int x2 = left + rand() % 60 - 30; int y1 = top + rand() % 60 - 30; int y2 = top + rand() % 60 - 30; cairo_curve_to( dc, x1, y1, x2, y2, left, top ); } cairo_close_path( dc ); cairo_path_t *path = cairo_copy_path( dc ); while( run ) { SDL_Event event; while( SDL_PollEvent( &event ) ) { if( event.type == SDL_QUIT ) run = 0; } SDL_LockSurface( argb_surface ); /* alle cairo aktionen ausführen... */ cairo_set_source_rgb( dc, 0, 0, 0 ); cairo_paint_with_alpha( dc, 0.3 ); cairo_save( dc ); cairo_matrix_init_translate( &matrix, 200, 200 ); cairo_matrix_rotate( &matrix, angel += 0.1 ); cairo_set_matrix( dc, &matrix ); cairo_new_path( dc ); cairo_rectangle( dc, -50, -50, 50, 200 ); cairo_set_source_rgb( dc, 1, 0.75, 0.25 ); cairo_fill( dc ); cairo_restore( dc ); cairo_path_data_t *data; for( i = 0; i < path->num_data; i += path->data[i].header.length ) { data = &path->data[i]; if( data->header.type == CAIRO_PATH_CURVE_TO ) { data[3].point.x += rand() % 5 - 2; data[3].point.y += rand() % 5 - 2; } } cairo_new_path( dc ); cairo_append_path( dc, path ); cairo_set_source_rgb( dc, 1, 1, 1 ); cairo_set_line_width( dc, 2 ); cairo_stroke( dc ); /* fertig mit cairo */ cairo_surface_flush( cairo_get_target( dc ) ); SDL_UnlockSurface( argb_surface ); SDL_BlitSurface( argb_surface, NULL, screen, NULL ); SDL_Flip( screen ); printf( "fps: %i\n", (int)( 1 / (float)(SDL_GetTicks() - last_frame) * 1000 ) ); last_frame = SDL_GetTicks(); } SDL_Quit(); return 0; }Es ergibt erstaunliche 60fps/s
-
ajo, ich empfehle jedem sich mal in AGG ( www.antigrain.com ) einzuarbeiten

einfach geile lib ^^
-
scheint mir im gegensatz zu cairo und sdl irgendwie kompliziert, abgesehen davon, dass ich aus den beispielen auch nicht erkennen kann, wofür man die braucht .
-
-Foo- schrieb:
scheint mir im gegensatz zu cairo und sdl irgendwie kompliziert, abgesehen davon, dass ich aus den beispielen auch nicht erkennen kann, wofür man die braucht .
najo, cairo könnte man als frontend bezeichnen, es gibt sogar eine agg backend implementation auf agg basis.
ansonsten, ja die lernkurve ist hoch, aber die lib ist äusserst gut durchdacht (auf einer ziemlich hohen abstraktionsstufe) und hat ne hammer performance.
-
Wie gesagt ich arbeite mich gerade in cairo ein ( und habe auch sonst noch nicht so viel erfahrung mit Grafik programmierung), daher habe ich noch ein paar fragen.
/* erstelle unser cairo-surface */ cairo_surface_t *image = cairo_image_surface_create_for_data( (unsigned char*)screen->pixels, CAIRO_FORMAT_ARGB32, 640, 480, 640 * 4 ); cairo_t *dc = cairo_create( image ); cairo_surface_destroy( image );Hier erstellst du die surface aber warum zerstörst du sie sofort wieder? Willst du nur einen darauf eingestellten device context haben? Oder bleibt es trotzdem erhalten weil cairo_t immer noch eine referenz darauf behält?
SDL_BlitSurface( argb_surface, NULL, screen, NULL ); SDL_Flip( screen );Geht das rüberkopieren nicht ziemlich auf die performance? Welchen sinn hat es? Kann ich nicht auch direkt auf screen zeichnen und zum schluss einmal flippen?
/* fertig mit cairo */ cairo_surface_flush( cairo_get_target( dc ) );Was macht flush nochmal?
Entschuldige bitte wenn sich manche fragen ergeben wenn man in die refrenz liest aber die ist im moment nicht erreichbar. Die Zeichenoperationen werde ich auch verstehen wenn die wieder on ist.
Danke!
-
Ich habe heute nachmittag, nachdem ich deinen Post gelesen hab, mit cairo angefangen... nur anhand der referenz...Prophet05 schrieb:
Wie gesagt ich arbeite mich gerade in cairo ein ( und habe auch sonst noch nicht so viel erfahrung mit Grafik programmierung), daher habe ich noch ein paar fragen.
/* erstelle unser cairo-surface */ cairo_surface_t *image = cairo_image_surface_create_for_data( (unsigned char*)screen->pixels, CAIRO_FORMAT_ARGB32, 640, 480, 640 * 4 ); cairo_t *dc = cairo_create( image ); cairo_surface_destroy( image );Hier erstellst du die surface aber warum zerstörst du sie sofort wieder? Willst du nur einen darauf eingestellten device context haben? Oder bleibt es trotzdem erhalten weil cairo_t immer noch eine referenz darauf behält?
jupp
SDL_BlitSurface( argb_surface, NULL, screen, NULL ); SDL_Flip( screen );Geht das rüberkopieren nicht ziemlich auf die performance? Welchen sinn hat es? Kann ich nicht auch direkt auf screen zeichnen und zum schluss einmal flippen?
denke nich. die
einzelnen farben des sdl surface müssen genau so gesetzt werden, wie die des cairo-bildes/* fertig mit cairo */ cairo_surface_flush( cairo_get_target( dc ) );Was macht flush nochmal?
es stellt sicher, dass die pixel auch wirklich auf dem bild gesetzt sind.
Entschuldige bitte wenn sich manche fragen ergeben wenn man in die refrenz liest aber die ist im moment nicht erreichbar. Die Zeichenoperationen werde ich auch verstehen wenn die wieder on ist.
Danke!ja is mir auch aufgefallen -.-
-
Entschuldige das ich so spät erst wieder antworte, viel zu tun gehabt...
Mir ist noch etwasaufgefallen was ich nicht verstehe:
cairo_surface_t *image = cairo_image_surface_create_for_data( (unsigned char*)screen->pixels, CAIRO_FORMAT_ARGB32, 1024, 768, 1024 * 4 );Hier erstellst du die cairo surface aufgrund der daten von screen.
cairo_surface_flush( cairo_get_target( dc ) ); SDL_UnlockSurface( argb_surface ); SDL_BlitSurface( argb_surface, NULL, screen, NULL ); SDL_Flip( screen );Hier kopierst du dann die daten von argb_surface nach screen um sie anzuzeigen. Aber wie sind die daten auf argb_surface gekommen? Ich sehe nirgends eine stelle an der eine verbindung zwischen argb_surface und dem cairo surface hergestellt wird.
Danke nochmal für deine bisherrige hilfe!
Gruß, Prophet05
EDIT: Ich habe gerade mal getestet was passiert wenn man den blit nicht durchführt und mir fällt auf das keine veränderung eintritt. Sehe ich das also richtig das du die ganze zeit über nur mit screen und nicht mit argb_surface arbeitest?
-
ups, das ist ein Fehler. Das CairoSurface sollte von argb_surface erstellt werden... dass der Screen auch im ARGB Format vorliegtist galube ich nicht sicher und somit ist das Zufall, dass es auch mit screen funktioniert hatte...
(hatte die Variablen vorher anders genannt gehabt: screen -> display, argb_surface -> screen, daher kommt noch der Fehler...
)
-
Ok, danke