/* Function: al_create_event_queue */ ALLEGRO_EVENT_QUEUE *al_create_event_queue(void) { ALLEGRO_EVENT_QUEUE *queue = al_malloc(sizeof *queue); ASSERT(queue); if (queue) { _al_vector_init(&queue->sources, sizeof(ALLEGRO_EVENT_SOURCE *)); _al_vector_init(&queue->events, sizeof(ALLEGRO_EVENT)); _al_vector_alloc_back(&queue->events); queue->events_head = 0; queue->events_tail = 0; queue->paused = false; _AL_MARK_MUTEX_UNINITED(queue->mutex); _al_mutex_init(&queue->mutex); _al_cond_init(&queue->cond); _al_register_destructor(_al_dtor_list, "queue", queue, (void (*)(void *)) al_destroy_event_queue); } return queue; }
/* Function: al_create_bitmap */ ALLEGRO_BITMAP *al_create_bitmap(int w, int h) { ALLEGRO_BITMAP *bitmap = do_create_bitmap(w, h); if (bitmap) { _al_register_destructor(_al_dtor_list, bitmap, (void (*)(void *))al_destroy_bitmap); } return bitmap; }
/* Function: al_create_bitmap */ ALLEGRO_BITMAP *al_create_bitmap(int w, int h) { ALLEGRO_BITMAP *bitmap; bitmap = _al_create_bitmap_params(al_get_current_display(), w, h, al_get_new_bitmap_format(), al_get_new_bitmap_flags()); if (bitmap) { _al_register_destructor(_al_dtor_list, "bitmap", bitmap, (void (*)(void *))al_destroy_bitmap); } return bitmap; }
/* Function: al_open_native_text_log */ ALLEGRO_TEXTLOG *al_open_native_text_log(char const *title, int flags) { ALLEGRO_NATIVE_DIALOG *textlog = NULL; /* Avoid warnings when log windows are unimplemented. */ (void)title; (void)flags; textlog = al_calloc(1, sizeof *textlog); textlog->title = al_ustr_new(title); textlog->flags = flags; if (TEXT_LOG_EXTRA_THREAD) { textlog->tl_thread = al_create_thread(text_log_thread_proc, textlog); } textlog->tl_text_cond = al_create_cond(); textlog->tl_text_mutex = al_create_mutex(); textlog->tl_pending_text = al_ustr_new(""); al_init_user_event_source(&textlog->tl_events); textlog->tl_init_error = false; textlog->tl_done = false; if (TEXT_LOG_EXTRA_THREAD) { /* Unlike the other dialogs, this one never blocks as the intended * use case is a log window running in the background for debugging * purposes when no console can be used. Therefore we have it run * in a separate thread. */ al_start_thread(textlog->tl_thread); al_lock_mutex(textlog->tl_text_mutex); while (!textlog->tl_done && !textlog->tl_init_error) { al_wait_cond(textlog->tl_text_cond, textlog->tl_text_mutex); } al_unlock_mutex(textlog->tl_text_mutex); } else { textlog->tl_init_error = !_al_open_native_text_log(textlog); } if (textlog->tl_init_error) { al_close_native_text_log((ALLEGRO_TEXTLOG *)textlog); return NULL; } _al_register_destructor(_al_dtor_list, textlog, (void (*)(void *))al_close_native_text_log); return (ALLEGRO_TEXTLOG *)textlog; }
/* Function: al_create_sub_bitmap */ ALLEGRO_BITMAP *al_create_sub_bitmap(ALLEGRO_BITMAP *parent, int x, int y, int w, int h) { ALLEGRO_BITMAP *bitmap; if (parent->parent) { x += parent->xofs; y += parent->yofs; parent = parent->parent; } bitmap = al_calloc(1, sizeof *bitmap); bitmap->vt = parent->vt; /* Sub-bitmap inherits these from the parent. * Leave these unchanged so they can be detected if improperly accessed * directly. */ bitmap->_format = 0; bitmap->_flags = 0; bitmap->_display = (ALLEGRO_DISPLAY*)0x1; bitmap->w = w; bitmap->h = h; bitmap->locked = false; bitmap->cl = bitmap->ct = 0; bitmap->cr_excl = w; bitmap->cb_excl = h; al_identity_transform(&bitmap->transform); al_identity_transform(&bitmap->inverse_transform); bitmap->inverse_transform_dirty = false; al_identity_transform(&bitmap->proj_transform); al_orthographic_transform(&bitmap->proj_transform, 0, 0, -1.0, w, h, 1.0); bitmap->shader = NULL; bitmap->parent = parent; bitmap->xofs = x; bitmap->yofs = y; bitmap->memory = NULL; _al_register_destructor(_al_dtor_list, "sub_bitmap", bitmap, (void (*)(void *))al_destroy_bitmap); return bitmap; }
/* Function: al_create_native_file_dialog */ ALLEGRO_FILECHOOSER *al_create_native_file_dialog( char const *initial_path, char const *title, char const *patterns, int mode) { ALLEGRO_NATIVE_DIALOG *fc; fc = al_calloc(1, sizeof *fc); if (initial_path) { fc->fc_initial_path = al_create_path(initial_path); } fc->title = al_ustr_new(title); fc->fc_patterns = al_ustr_new(patterns); fc->flags = mode; _al_register_destructor(_al_dtor_list, fc, (void (*)(void *))al_destroy_native_file_dialog); return (ALLEGRO_FILECHOOSER *)fc; }
/* Function: al_grab_font_from_bitmap */ ALLEGRO_FONT *al_grab_font_from_bitmap(ALLEGRO_BITMAP *bmp, int ranges_n, const int ranges[]) { ALLEGRO_FONT *f; ALLEGRO_FONT_COLOR_DATA *cf, *prev = NULL; ALLEGRO_STATE backup; int i; ALLEGRO_COLOR mask = al_get_pixel(bmp, 0, 0); ALLEGRO_BITMAP *glyphs = NULL, *unmasked = NULL; int import_x = 0, import_y = 0; ALLEGRO_LOCKED_REGION *lock = NULL; int w, h; ASSERT(bmp); w = al_get_bitmap_width(bmp); h = al_get_bitmap_height(bmp); f = al_calloc(1, sizeof *f); f->vtable = &_al_font_vtable_color; al_store_state(&backup, ALLEGRO_STATE_NEW_BITMAP_PARAMETERS); al_set_new_bitmap_flags(ALLEGRO_MEMORY_BITMAP); al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ANY_WITH_ALPHA); unmasked = al_clone_bitmap(bmp); /* At least with OpenGL, texture pixels at the very border of * the glyph are sometimes partly sampled from the yellow mask * pixels. To work around this, we replace the mask with full * transparency. * And we best do it on a memory copy to avoid loading back a texture. */ al_convert_mask_to_alpha(unmasked, mask); al_restore_state(&backup); al_store_state(&backup, ALLEGRO_STATE_BITMAP | ALLEGRO_STATE_BLENDER); // Use the users preferred format, so don't set this below! //al_set_new_bitmap_format(ALLEGRO_PIXEL_FORMAT_ANY_WITH_ALPHA); for (i = 0; i < ranges_n; i++) { int first = ranges[i * 2]; int last = ranges[i * 2 + 1]; int n = 1 + last - first; cf = al_calloc(1, sizeof(ALLEGRO_FONT_COLOR_DATA)); if (prev) prev->next = cf; else f->data = cf; cf->bitmaps = al_malloc(sizeof(ALLEGRO_BITMAP*) * n); cf->bitmaps[0] = NULL; if (!glyphs) { glyphs = al_clone_bitmap(unmasked); if (!glyphs) goto cleanup_and_fail_on_error; lock = al_lock_bitmap(bmp, ALLEGRO_PIXEL_FORMAT_RGBA_8888, ALLEGRO_LOCK_READONLY); } cf->glyphs = glyphs; if (import_bitmap_font_color(lock->data, lock->pitch, w, h, cf->bitmaps, cf->glyphs, n, &import_x, &import_y)) { goto cleanup_and_fail_on_error; } else { cf->begin = first; cf->end = last + 1; prev = cf; } } al_restore_state(&backup); cf = f->data; if (cf && cf->bitmaps[0]) f->height = al_get_bitmap_height(cf->bitmaps[0]); if (lock) al_unlock_bitmap(bmp); if (unmasked) al_destroy_bitmap(unmasked); f->dtor_item = _al_register_destructor(_al_dtor_list, "font", f, (void (*)(void *))al_destroy_font); return f; cleanup_and_fail_on_error: if (lock) al_unlock_bitmap(bmp); al_restore_state(&backup); al_destroy_font(f); if (unmasked) al_destroy_bitmap(unmasked); return NULL; }
/* _al_kcm_register_destructor: * Register an object to be destroyed. */ _AL_LIST_ITEM *_al_kcm_register_destructor(char const *name, void *object, void (*func)(void*)) { return _al_register_destructor(kcm_dtors, name, object, func); }